cpupara.pas 28 KB

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