cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. PowerPC specific calling conventions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cpupara;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. aasmtai,
  24. cpubase,
  25. symconst,symtype,symdef,symsym,
  26. paramgr,parabase,cgbase;
  27. type
  28. tppcparamanager = class(tparamanager)
  29. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  30. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  31. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  32. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
  33. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  34. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  35. procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  36. private
  37. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  38. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  39. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  40. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  41. end;
  42. implementation
  43. uses
  44. verbose,systems,
  45. defutil,
  46. cgutils;
  47. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  48. begin
  49. if (target_info.system = system_powerpc_darwin) then
  50. result := [RS_R2..RS_R12]
  51. else
  52. result := [RS_R3..RS_R12];
  53. end;
  54. function tppcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  55. begin
  56. case target_info.abi of
  57. abi_powerpc_aix,
  58. abi_powerpc_sysv:
  59. result := [RS_F0..RS_F13];
  60. else
  61. internalerror(2003091401);
  62. end;
  63. end;
  64. procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
  65. var
  66. paraloc : pcgparalocation;
  67. begin
  68. cgpara.reset;
  69. cgpara.size:=OS_INT;
  70. cgpara.intsize:=tcgsize2size[OS_INT];
  71. cgpara.alignment:=get_para_align(calloption);
  72. paraloc:=cgpara.add_location;
  73. with paraloc^ do
  74. begin
  75. size:=OS_INT;
  76. if (nr<=8) then
  77. begin
  78. if nr=0 then
  79. internalerror(200309271);
  80. loc:=LOC_REGISTER;
  81. register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
  82. end
  83. else
  84. begin
  85. loc:=LOC_REFERENCE;
  86. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  87. if (target_info.abi <> abi_powerpc_aix) then
  88. reference.offset:=sizeof(aint)*(nr-8)
  89. else
  90. reference.offset:=sizeof(aint)*(nr);
  91. end;
  92. end;
  93. end;
  94. function getparaloc(p : tdef) : tcgloc;
  95. begin
  96. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  97. if push_addr_param for the def is true
  98. }
  99. case p.deftype of
  100. orddef:
  101. result:=LOC_REGISTER;
  102. floatdef:
  103. result:=LOC_FPUREGISTER;
  104. enumdef:
  105. result:=LOC_REGISTER;
  106. pointerdef:
  107. result:=LOC_REGISTER;
  108. formaldef:
  109. result:=LOC_REGISTER;
  110. classrefdef:
  111. result:=LOC_REGISTER;
  112. recorddef:
  113. if (target_info.abi<>abi_powerpc_aix) then
  114. result:=LOC_REFERENCE
  115. else
  116. result:=LOC_REGISTER;
  117. objectdef:
  118. if is_object(p) then
  119. result:=LOC_REFERENCE
  120. else
  121. result:=LOC_REGISTER;
  122. stringdef:
  123. if is_shortstring(p) or is_longstring(p) then
  124. result:=LOC_REFERENCE
  125. else
  126. result:=LOC_REGISTER;
  127. procvardef:
  128. if (po_methodpointer in tprocvardef(p).procoptions) then
  129. result:=LOC_REFERENCE
  130. else
  131. result:=LOC_REGISTER;
  132. filedef:
  133. result:=LOC_REGISTER;
  134. arraydef:
  135. result:=LOC_REFERENCE;
  136. setdef:
  137. if is_smallset(p) then
  138. result:=LOC_REGISTER
  139. else
  140. result:=LOC_REFERENCE;
  141. variantdef:
  142. result:=LOC_REFERENCE;
  143. { avoid problems with errornous definitions }
  144. errordef:
  145. result:=LOC_REGISTER;
  146. else
  147. internalerror(2002071001);
  148. end;
  149. end;
  150. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  151. begin
  152. { var,out always require address }
  153. if varspez in [vs_var,vs_out] then
  154. begin
  155. result:=true;
  156. exit;
  157. end;
  158. case def.deftype of
  159. recorddef:
  160. result :=(target_info.abi<>abi_powerpc_aix);
  161. arraydef:
  162. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  163. is_open_array(def) or
  164. is_array_of_const(def) or
  165. is_array_constructor(def);
  166. setdef :
  167. result:=(tsetdef(def).settype<>smallset);
  168. stringdef :
  169. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  170. procvardef :
  171. result:=po_methodpointer in tprocvardef(def).procoptions;
  172. else
  173. result:=inherited push_addr_param(varspez,def,calloption);
  174. end;
  175. end;
  176. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  177. begin
  178. case target_info.abi of
  179. abi_powerpc_aix:
  180. cur_stack_offset:=24;
  181. abi_powerpc_sysv:
  182. cur_stack_offset:=8;
  183. else
  184. internalerror(2003051901);
  185. end;
  186. curintreg:=RS_R3;
  187. curfloatreg:=RS_F1;
  188. curmmreg:=RS_M1;
  189. end;
  190. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  191. var
  192. retcgsize : tcgsize;
  193. begin
  194. { Constructors return self instead of a boolean }
  195. if (p.proctypeoption=potype_constructor) then
  196. retcgsize:=OS_ADDR
  197. else
  198. retcgsize:=def_cgsize(p.rettype.def);
  199. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  200. p.funcretloc[side].size:=retcgsize;
  201. { void has no location }
  202. if is_void(p.rettype.def) then
  203. begin
  204. p.funcretloc[side].loc:=LOC_VOID;
  205. exit;
  206. end;
  207. { Return in FPU register? }
  208. if p.rettype.def.deftype=floatdef then
  209. begin
  210. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  211. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  212. p.funcretloc[side].size:=retcgsize;
  213. end
  214. else
  215. { Return in register? }
  216. if not ret_in_param(p.rettype.def,p.proccalloption) then
  217. begin
  218. {$ifndef cpu64bit}
  219. if retcgsize in [OS_64,OS_S64] then
  220. begin
  221. { low 32bits }
  222. p.funcretloc[side].loc:=LOC_REGISTER;
  223. if side=callerside then
  224. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  225. else
  226. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  227. { high 32bits }
  228. if side=callerside then
  229. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  230. else
  231. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  232. end
  233. else
  234. {$endif cpu64bit}
  235. begin
  236. p.funcretloc[side].loc:=LOC_REGISTER;
  237. p.funcretloc[side].size:=retcgsize;
  238. if side=callerside then
  239. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  240. else
  241. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  242. end;
  243. end
  244. else
  245. begin
  246. p.funcretloc[side].loc:=LOC_REFERENCE;
  247. p.funcretloc[side].size:=retcgsize;
  248. end;
  249. end;
  250. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  251. var
  252. cur_stack_offset: aword;
  253. curintreg, curfloatreg, curmmreg: tsuperregister;
  254. begin
  255. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  256. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  257. create_funcretloc_info(p,side);
  258. end;
  259. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  260. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  261. var
  262. stack_offset: longint;
  263. paralen: aint;
  264. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  265. paradef : tdef;
  266. paraloc : pcgparalocation;
  267. i : integer;
  268. hp : tparavarsym;
  269. loc : tcgloc;
  270. paracgsize: tcgsize;
  271. (*
  272. procedure assignintreg;
  273. begin
  274. if nextintreg<=RS_R10 then
  275. begin
  276. paraloc^.loc:=LOC_REGISTER;
  277. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  278. inc(nextintreg);
  279. if target_info.abi=abi_powerpc_aix then
  280. inc(stack_offset,4);
  281. end
  282. else
  283. begin
  284. paraloc^.loc:=LOC_REFERENCE;
  285. if (side = callerside) then
  286. paraloc^.reference.index:=NR_STACK_POINTER_REG
  287. else
  288. paraloc^.reference.index:=NR_R12;
  289. paraloc^.reference.offset:=stack_offset;
  290. inc(stack_offset,4);
  291. end;
  292. end;
  293. *)
  294. begin
  295. {$ifdef extdebug}
  296. if po_explicitparaloc in p.procoptions then
  297. internalerror(200411141);
  298. {$endif extdebug}
  299. result:=0;
  300. nextintreg := curintreg;
  301. nextfloatreg := curfloatreg;
  302. nextmmreg := curmmreg;
  303. stack_offset := cur_stack_offset;
  304. case target_info.abi of
  305. abi_powerpc_aix:
  306. maxfpureg := RS_F13;
  307. abi_powerpc_sysv:
  308. maxfpureg := RS_F8;
  309. else internalerror(2004070912);
  310. end;
  311. for i:=0 to paras.count-1 do
  312. begin
  313. hp:=tparavarsym(paras[i]);
  314. paradef := hp.vartype.def;
  315. { Syscall for Morphos can have already a paraloc set }
  316. if (vo_has_explicit_paraloc in hp.varoptions) then
  317. begin
  318. if not(vo_is_syscall_lib in hp.varoptions) then
  319. internalerror(200412153);
  320. continue;
  321. end;
  322. hp.paraloc[side].reset;
  323. { currently only support C-style array of const }
  324. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  325. is_array_of_const(paradef) then
  326. begin
  327. paraloc:=hp.paraloc[side].add_location;
  328. { hack: the paraloc must be valid, but is not actually used }
  329. paraloc^.loc := LOC_REGISTER;
  330. paraloc^.register := NR_R0;
  331. paraloc^.size := OS_ADDR;
  332. break;
  333. end;
  334. if (hp.varspez in [vs_var,vs_out]) or
  335. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  336. is_open_array(paradef) or
  337. is_array_of_const(paradef) then
  338. begin
  339. paradef:=voidpointertype.def;
  340. loc:=LOC_REGISTER;
  341. paracgsize := OS_ADDR;
  342. paralen := tcgsize2size[OS_ADDR];
  343. end
  344. else
  345. begin
  346. if not is_special_array(paradef) then
  347. paralen := paradef.size
  348. else
  349. paralen := tcgsize2size[def_cgsize(paradef)];
  350. if (target_info.abi = abi_powerpc_aix) and
  351. (paradef.deftype = recorddef) and
  352. (hp.varspez in [vs_value,vs_const]) then
  353. begin
  354. { if a record has only one field and that field is }
  355. { non-composite (not array or record), it must be }
  356. { passed according to the rules of that type. }
  357. if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
  358. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  359. ((target_info.system = system_powerpc_darwin) and
  360. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  361. begin
  362. paradef :=
  363. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  364. loc := getparaloc(paradef);
  365. paracgsize:=def_cgsize(paradef);
  366. end
  367. else
  368. begin
  369. loc := LOC_REGISTER;
  370. paracgsize := int_cgsize(paralen);
  371. end;
  372. end
  373. else
  374. begin
  375. loc:=getparaloc(paradef);
  376. paracgsize:=def_cgsize(paradef);
  377. { for things like formaldef }
  378. if (paracgsize=OS_NO) then
  379. begin
  380. paracgsize:=OS_ADDR;
  381. paralen := tcgsize2size[OS_ADDR];
  382. end;
  383. end
  384. end;
  385. hp.paraloc[side].alignment:=std_param_align;
  386. hp.paraloc[side].size:=paracgsize;
  387. hp.paraloc[side].intsize:=paralen;
  388. if (target_info.abi = abi_powerpc_aix) and
  389. (paradef.deftype = recorddef) then
  390. hp.paraloc[side].composite:=true;
  391. {$ifndef cpu64bit}
  392. if (target_info.abi=abi_powerpc_sysv) and
  393. is_64bit(paradef) and
  394. odd(nextintreg-RS_R3) then
  395. inc(nextintreg);
  396. {$endif not cpu64bit}
  397. if (paralen = 0) then
  398. if (paradef.deftype = recorddef) then
  399. begin
  400. paraloc:=hp.paraloc[side].add_location;
  401. paraloc^.loc := LOC_VOID;
  402. end
  403. else
  404. internalerror(2005011310);
  405. { can become < 0 for e.g. 3-byte records }
  406. while (paralen > 0) do
  407. begin
  408. paraloc:=hp.paraloc[side].add_location;
  409. if (loc = LOC_REGISTER) and
  410. (nextintreg <= RS_R10) then
  411. begin
  412. paraloc^.loc := loc;
  413. paracgsize := int_cgsize(paralen);
  414. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  415. paraloc^.size := OS_INT
  416. else
  417. paraloc^.size := paracgsize;
  418. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  419. inc(nextintreg);
  420. dec(paralen,tcgsize2size[paraloc^.size]);
  421. if target_info.abi=abi_powerpc_aix then
  422. inc(stack_offset,tcgsize2size[paraloc^.size]);
  423. end
  424. else if (loc = LOC_FPUREGISTER) and
  425. (nextfloatreg <= maxfpureg) then
  426. begin
  427. paraloc^.loc:=loc;
  428. paraloc^.size := paracgsize;
  429. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  430. inc(nextfloatreg);
  431. dec(paralen,tcgsize2size[paraloc^.size]);
  432. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  433. { are less of those available for parameter passing in the AIX abi }
  434. if target_info.abi=abi_powerpc_aix then
  435. {$ifndef cpu64bit}
  436. if (paracgsize = OS_F32) then
  437. begin
  438. inc(stack_offset,4);
  439. if (nextintreg < RS_R11) then
  440. inc(nextintreg);
  441. end
  442. else
  443. begin
  444. inc(stack_offset,8);
  445. if (nextintreg < RS_R10) then
  446. inc(nextintreg,2)
  447. else
  448. nextintreg := RS_R11;
  449. end;
  450. {$else not cpu64bit}
  451. begin
  452. inc(stack_offset,tcgsize2size[paracgsize]);
  453. if (nextintreg < RS_R11) then
  454. inc(nextintreg);
  455. end;
  456. {$endif not cpu64bit}
  457. end
  458. else { LOC_REFERENCE }
  459. begin
  460. paraloc^.loc:=LOC_REFERENCE;
  461. paraloc^.size:=int_cgsize(paralen);
  462. if (side = callerside) then
  463. paraloc^.reference.index:=NR_STACK_POINTER_REG
  464. else
  465. paraloc^.reference.index:=NR_R12;
  466. paraloc^.reference.offset:=stack_offset;
  467. inc(stack_offset,align(paralen,4));
  468. paralen := 0;
  469. end;
  470. end;
  471. end;
  472. curintreg:=nextintreg;
  473. curfloatreg:=nextfloatreg;
  474. curmmreg:=nextmmreg;
  475. cur_stack_offset:=stack_offset;
  476. result:=stack_offset;
  477. end;
  478. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  479. var
  480. cur_stack_offset: aword;
  481. parasize, l: longint;
  482. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  483. i : integer;
  484. hp: tparavarsym;
  485. paraloc: pcgparalocation;
  486. begin
  487. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  488. firstfloatreg:=curfloatreg;
  489. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  490. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  491. { just continue loading the parameters in the registers }
  492. begin
  493. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  494. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  495. if (target_info.abi = abi_powerpc_aix) and
  496. (result < 32) then
  497. result := 32;
  498. end
  499. else
  500. begin
  501. parasize:=cur_stack_offset;
  502. for i:=0 to varargspara.count-1 do
  503. begin
  504. hp:=tparavarsym(varargspara[i]);
  505. hp.paraloc[callerside].alignment:=4;
  506. paraloc:=hp.paraloc[callerside].add_location;
  507. paraloc^.loc:=LOC_REFERENCE;
  508. paraloc^.size:=def_cgsize(hp.vartype.def);
  509. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  510. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  511. paraloc^.reference.offset:=parasize;
  512. parasize:=parasize+l;
  513. end;
  514. result:=parasize;
  515. end;
  516. if curfloatreg<>firstfloatreg then
  517. include(varargspara.varargsinfo,va_uses_float_reg);
  518. end;
  519. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  520. var
  521. paraloc : pcgparalocation;
  522. paracgsize : tcgsize;
  523. begin
  524. result:=false;
  525. case target_info.system of
  526. system_powerpc_morphos:
  527. begin
  528. paracgsize:=def_cgsize(p.vartype.def);
  529. p.paraloc[callerside].alignment:=4;
  530. p.paraloc[callerside].size:=paracgsize;
  531. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  532. paraloc:=p.paraloc[callerside].add_location;
  533. paraloc^.loc:=LOC_REFERENCE;
  534. paraloc^.size:=paracgsize;
  535. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  536. { pattern is always uppercase'd }
  537. if s='D0' then
  538. paraloc^.reference.offset:=0
  539. else if s='D1' then
  540. paraloc^.reference.offset:=4
  541. else if s='D2' then
  542. paraloc^.reference.offset:=8
  543. else if s='D3' then
  544. paraloc^.reference.offset:=12
  545. else if s='D4' then
  546. paraloc^.reference.offset:=16
  547. else if s='D5' then
  548. paraloc^.reference.offset:=20
  549. else if s='D6' then
  550. paraloc^.reference.offset:=24
  551. else if s='D7' then
  552. paraloc^.reference.offset:=28
  553. else if s='A0' then
  554. paraloc^.reference.offset:=32
  555. else if s='A1' then
  556. paraloc^.reference.offset:=36
  557. else if s='A2' then
  558. paraloc^.reference.offset:=40
  559. else if s='A3' then
  560. paraloc^.reference.offset:=44
  561. else if s='A4' then
  562. paraloc^.reference.offset:=48
  563. else if s='A5' then
  564. paraloc^.reference.offset:=52
  565. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  566. never passes parameters in it,
  567. Indeed, but this allows to declare libbase either explicitly
  568. or let the compiler insert it }
  569. else if s='A6' then
  570. paraloc^.reference.offset:=56
  571. { 'A7' is the stack pointer on 68k, can't be overwritten
  572. by API calls, so it has no offset }
  573. { 'R12' is special, used internally to support r12base sysv
  574. calling convention }
  575. else if s='R12' then
  576. begin
  577. paraloc^.loc:=LOC_REGISTER;
  578. paraloc^.size:=OS_ADDR;
  579. paraloc^.register:=NR_R12;
  580. end
  581. else
  582. exit;
  583. { copy to callee side }
  584. p.paraloc[calleeside].add_location^:=paraloc^;
  585. end;
  586. else
  587. internalerror(200404182);
  588. end;
  589. result:=true;
  590. end;
  591. begin
  592. paramanager:=tppcparamanager.create;
  593. end.
  594. {
  595. $Log$
  596. Revision 1.86 2005-01-31 17:46:25 peter
  597. * fixed parseparaloc
  598. Revision 1.85 2005/01/20 17:47:01 peter
  599. * remove copy_value_on_stack and a_param_copy_ref
  600. Revision 1.84 2005/01/14 20:59:17 jonas
  601. * fixed overallocation of stack space for parameters under SYSV
  602. (introduced in one of my previous commits)
  603. * unified code of get_volatile_registers_fpu for SYSV and AIX
  604. Revision 1.83 2005/01/13 22:02:40 jonas
  605. * r2 can be used by the register allocator under Darwin
  606. * merged the initialisations of the fpu register allocator for AIX and
  607. SYSV
  608. Revision 1.82 2005/01/13 19:32:08 jonas
  609. * fixed copy_value_on_stack() for AIX abi
  610. + added support for passing empty record parameters
  611. Revision 1.81 2005/01/10 21:50:05 jonas
  612. + support for passing records in registers under darwin
  613. * tcgpara now also has an intsize field, which contains the size in
  614. bytes of the whole parameter
  615. Revision 1.80 2005/01/07 10:58:03 jonas
  616. * fixed stupid tregister/tsuperregister bug (type checking circumvented
  617. using explicit typecase), caused bug3523
  618. Revision 1.79 2005/01/06 02:13:03 karoly
  619. * more SysV call support stuff for MorphOS
  620. Revision 1.78 2005/01/05 19:01:53 karoly
  621. * sysv abi also uses F0-F13 as volatile registers
  622. Revision 1.77 2004/12/24 15:00:11 jonas
  623. * fixed call-by-value passing of records with size 1, 2 or 4 for AIX abi
  624. (using a hack, normally all records should by passed by value under the
  625. aix abi, but that's currently impossible)
  626. Revision 1.76 2004/12/15 19:30:32 peter
  627. * syscall with sysv abi for morphos
  628. Revision 1.75 2004/12/04 21:47:46 jonas
  629. * modifications to work with the generic code to copy LOC_REFERENCE
  630. parameters to local temps (fixes tests/test/cg/tmanypara)
  631. Revision 1.74 2004/11/22 22:01:19 peter
  632. * fixed varargs
  633. * replaced dynarray with tlist
  634. Revision 1.73 2004/11/21 17:54:59 peter
  635. * ttempcreatenode.create_reg merged into .create with parameter
  636. whether a register is allowed
  637. * funcret_paraloc renamed to funcretloc
  638. Revision 1.72 2004/11/21 17:17:04 florian
  639. * changed funcret location back to tlocation
  640. Revision 1.71 2004/11/15 23:35:31 peter
  641. * tparaitem removed, use tparavarsym instead
  642. * parameter order is now calculated from paranr value in tparavarsym
  643. Revision 1.70 2004/11/14 16:26:29 florian
  644. * fixed morphos syscall
  645. Revision 1.69 2004/09/25 20:28:20 florian
  646. * indention fixed
  647. Revision 1.68 2004/09/21 17:25:13 peter
  648. * paraloc branch merged
  649. Revision 1.67.4.3 2004/09/18 20:21:08 jonas
  650. * fixed ppc, but still needs fix in tgobj
  651. Revision 1.67.4.2 2004/09/10 11:10:08 florian
  652. * first part of ppc fixes
  653. Revision 1.67.4.1 2004/08/31 20:43:06 peter
  654. * paraloc patch
  655. Revision 1.67 2004/07/19 19:15:50 florian
  656. * fixed funcretloc writing in units
  657. Revision 1.66 2004/07/17 13:51:57 florian
  658. * function result location for syscalls on MOS hopefully correctly set now
  659. Revision 1.65 2004/07/09 21:45:24 jonas
  660. * fixed passing of fpu paras on the stack
  661. * fixed number of fpu parameters passed in registers
  662. * skip corresponding integer registers when using an fpu register for a
  663. parameter under the AIX abi
  664. Revision 1.64 2004/07/01 18:00:37 jonas
  665. * fix for broken TP-style constructor handling in the compiler
  666. Revision 1.63 2004/06/20 08:55:32 florian
  667. * logs truncated
  668. Revision 1.62 2004/05/01 22:05:02 florian
  669. + added lib support for Amiga/MorphOS syscalls
  670. Revision 1.61 2004/04/18 23:19:48 karoly
  671. * added correct offsets for PowerPC/MorphOS location support
  672. Revision 1.60 2004/04/18 15:22:24 florian
  673. + location support for arguments, currently PowerPC/MorphOS only
  674. Revision 1.59 2004/02/19 17:07:42 florian
  675. * fixed arg. area calculation
  676. Revision 1.58 2004/02/11 23:18:59 florian
  677. * fixed to compile the rtl again
  678. }