cpupara.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. PowerPC specific calling conventions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cpupara;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmtai,aasmdata,
  23. cpubase,
  24. symconst,symtype,symdef,symsym,
  25. paramgr,parabase,cgbase,cgutils;
  26. type
  27. tppcparamanager = class(tparamanager)
  28. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  29. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  30. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  31. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
  32. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  33. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  34. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;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; varargsparas: boolean):longint;
  40. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  41. end;
  42. implementation
  43. uses
  44. verbose,systems,
  45. defutil,symtable,
  46. procinfo,cpupi;
  47. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  48. begin
  49. if (target_info.system = system_powerpc_darwin) then
  50. result := [RS_R0,RS_R2..RS_R12]
  51. else
  52. result := [RS_R0,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_ADDR;
  70. cgpara.intsize:=sizeof(pint);
  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(pint)*(nr-8)
  89. else
  90. reference.offset:=sizeof(pint)*(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.typ 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. procvardef:
  113. if (target_info.abi = abi_powerpc_aix) or
  114. (p.size = sizeof(pint)) then
  115. result:=LOC_REGISTER
  116. else
  117. result:=LOC_REFERENCE;
  118. recorddef:
  119. if not(target_info.system in systems_aix) and
  120. ((target_info.abi<>abi_powerpc_aix) or
  121. ((p.size >= 3) and
  122. ((p.size mod 4) <> 0))) then
  123. result:=LOC_REFERENCE
  124. else
  125. result:=LOC_REGISTER;
  126. objectdef:
  127. if is_object(p) then
  128. result:=LOC_REFERENCE
  129. else
  130. result:=LOC_REGISTER;
  131. stringdef:
  132. if is_shortstring(p) or is_longstring(p) 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. result:=false;
  157. { var,out,constref always require address }
  158. if varspez in [vs_var,vs_out,vs_constref] then
  159. begin
  160. result:=true;
  161. exit;
  162. end;
  163. case def.typ of
  164. variantdef,
  165. formaldef :
  166. result:=true;
  167. { regular procvars must be passed by value, because you cannot pass
  168. the address of a local stack location when calling e.g.
  169. pthread_create with the address of a function (first of all it
  170. expects the address of the function to execute and not the address
  171. of a memory location containing that address, and secondly if you
  172. first store the address on the stack and then pass the address of
  173. this stack location, then this stack location may no longer be
  174. valid when the newly started thread accesses it.
  175. However, for "procedure of object" we must use the same calling
  176. convention as for "8 byte record" due to the need for
  177. interchangeability with the TMethod record type.
  178. }
  179. procvardef :
  180. result:=
  181. (target_info.abi <> abi_powerpc_aix) and
  182. (def.size <> sizeof(pint));
  183. recorddef :
  184. result :=
  185. (target_info.abi<>abi_powerpc_aix) or
  186. ((varspez = vs_const) and
  187. ((calloption = pocall_mwpascal) or
  188. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  189. (def.size > 8)
  190. )
  191. )
  192. );
  193. arraydef:
  194. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  195. is_open_array(def) or
  196. is_array_of_const(def) or
  197. is_array_constructor(def);
  198. objectdef :
  199. result:=is_object(def);
  200. setdef :
  201. result:=not is_smallset(def);
  202. stringdef :
  203. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  204. end;
  205. end;
  206. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  207. begin
  208. case target_info.abi of
  209. abi_powerpc_aix:
  210. cur_stack_offset:=24;
  211. abi_powerpc_sysv:
  212. cur_stack_offset:=8;
  213. else
  214. internalerror(2003051901);
  215. end;
  216. curintreg:=RS_R3;
  217. curfloatreg:=RS_F1;
  218. curmmreg:=RS_M1;
  219. end;
  220. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  221. begin
  222. p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
  223. end;
  224. function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
  225. var
  226. paraloc : pcgparalocation;
  227. retcgsize : tcgsize;
  228. begin
  229. result.init;
  230. result.alignment:=get_para_align(p.proccalloption);
  231. { void has no location }
  232. if is_void(def) then
  233. begin
  234. paraloc:=result.add_location;
  235. result.size:=OS_NO;
  236. result.intsize:=0;
  237. paraloc^.size:=OS_NO;
  238. paraloc^.loc:=LOC_VOID;
  239. exit;
  240. end;
  241. { Constructors return self instead of a boolean }
  242. if (p.proctypeoption=potype_constructor) then
  243. begin
  244. retcgsize:=OS_ADDR;
  245. result.intsize:=sizeof(pint);
  246. end
  247. else
  248. begin
  249. retcgsize:=def_cgsize(def);
  250. result.intsize:=def.size;
  251. end;
  252. result.size:=retcgsize;
  253. { Return is passed as var parameter }
  254. if ret_in_param(def,p.proccalloption) then
  255. begin
  256. paraloc:=result.add_location;
  257. paraloc^.loc:=LOC_REFERENCE;
  258. paraloc^.size:=retcgsize;
  259. exit;
  260. end;
  261. paraloc:=result.add_location;
  262. { Return in FPU register? }
  263. if def.typ=floatdef then
  264. begin
  265. paraloc^.loc:=LOC_FPUREGISTER;
  266. paraloc^.register:=NR_FPU_RESULT_REG;
  267. paraloc^.size:=retcgsize;
  268. end
  269. else
  270. { Return in register }
  271. begin
  272. if retcgsize in [OS_64,OS_S64] then
  273. begin
  274. { low 32bits }
  275. paraloc^.loc:=LOC_REGISTER;
  276. if side=callerside then
  277. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  278. else
  279. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  280. paraloc^.size:=OS_32;
  281. { high 32bits }
  282. paraloc:=result.add_location;
  283. paraloc^.loc:=LOC_REGISTER;
  284. if side=callerside then
  285. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  286. else
  287. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  288. paraloc^.size:=OS_32;
  289. end
  290. else
  291. begin
  292. paraloc^.loc:=LOC_REGISTER;
  293. if side=callerside then
  294. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  295. else
  296. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  297. paraloc^.size:=retcgsize;
  298. end;
  299. end;
  300. end;
  301. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  302. var
  303. cur_stack_offset: aword;
  304. curintreg, curfloatreg, curmmreg: tsuperregister;
  305. begin
  306. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  307. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
  308. create_funcretloc_info(p,side);
  309. end;
  310. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  311. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  312. var
  313. stack_offset: longint;
  314. paralen: aint;
  315. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  316. paradef : tdef;
  317. paraloc : pcgparalocation;
  318. i : integer;
  319. hp : tparavarsym;
  320. loc : tcgloc;
  321. paracgsize: tcgsize;
  322. sym: tfieldvarsym;
  323. begin
  324. {$ifdef extdebug}
  325. if po_explicitparaloc in p.procoptions then
  326. internalerror(200411141);
  327. {$endif extdebug}
  328. result:=0;
  329. nextintreg := curintreg;
  330. nextfloatreg := curfloatreg;
  331. nextmmreg := curmmreg;
  332. stack_offset := cur_stack_offset;
  333. case target_info.abi of
  334. abi_powerpc_aix:
  335. maxfpureg := RS_F13;
  336. abi_powerpc_sysv:
  337. maxfpureg := RS_F8;
  338. else internalerror(2004070912);
  339. end;
  340. for i:=0 to paras.count-1 do
  341. begin
  342. hp:=tparavarsym(paras[i]);
  343. paradef := hp.vardef;
  344. { Syscall for Morphos can have already a paraloc set }
  345. if (vo_has_explicit_paraloc in hp.varoptions) then
  346. begin
  347. if not(vo_is_syscall_lib in hp.varoptions) then
  348. internalerror(200412153);
  349. continue;
  350. end;
  351. hp.paraloc[side].reset;
  352. { currently only support C-style array of const }
  353. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) and
  354. is_array_of_const(paradef) then
  355. begin
  356. paraloc:=hp.paraloc[side].add_location;
  357. { hack: the paraloc must be valid, but is not actually used }
  358. paraloc^.loc := LOC_REGISTER;
  359. paraloc^.register := NR_R0;
  360. paraloc^.size := OS_ADDR;
  361. break;
  362. end;
  363. if (hp.varspez in [vs_var,vs_out]) or
  364. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  365. is_open_array(paradef) or
  366. is_array_of_const(paradef) then
  367. begin
  368. paradef:=voidpointertype;
  369. loc:=LOC_REGISTER;
  370. paracgsize := OS_ADDR;
  371. paralen := tcgsize2size[OS_ADDR];
  372. end
  373. else
  374. begin
  375. if not is_special_array(paradef) then
  376. paralen := paradef.size
  377. else
  378. paralen := tcgsize2size[def_cgsize(paradef)];
  379. if (target_info.abi = abi_powerpc_aix) and
  380. (paradef.typ = recorddef) and
  381. (hp.varspez in [vs_value,vs_const]) then
  382. begin
  383. { if a record has only one field and that field is }
  384. { non-composite (not array or record), it must be }
  385. { passed according to the rules of that type. }
  386. if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
  387. ((sym.vardef.typ=floatdef) or
  388. ((target_info.system=system_powerpc_darwin) and
  389. (sym.vardef.typ in [orddef,enumdef]))) then
  390. begin
  391. paradef:=sym.vardef;
  392. paracgsize:=def_cgsize(paradef);
  393. end
  394. else
  395. begin
  396. paracgsize := int_cgsize(paralen);
  397. end;
  398. end
  399. else
  400. begin
  401. paracgsize:=def_cgsize(paradef);
  402. { for things like formaldef }
  403. if (paracgsize=OS_NO) then
  404. begin
  405. paracgsize:=OS_ADDR;
  406. paralen := tcgsize2size[OS_ADDR];
  407. end;
  408. end
  409. end;
  410. loc := getparaloc(paradef);
  411. if varargsparas and
  412. (target_info.abi = abi_powerpc_aix) and
  413. (paradef.typ = floatdef) then
  414. begin
  415. loc := LOC_REGISTER;
  416. if paracgsize = OS_F64 then
  417. paracgsize := OS_64
  418. else
  419. paracgsize := OS_32;
  420. end;
  421. hp.paraloc[side].alignment:=std_param_align;
  422. hp.paraloc[side].size:=paracgsize;
  423. hp.paraloc[side].intsize:=paralen;
  424. if (target_info.abi = abi_powerpc_aix) and
  425. (paradef.typ in [recorddef,arraydef]) then
  426. hp.paraloc[side].composite:=true;
  427. {$ifndef cpu64bitaddr}
  428. if (target_info.abi=abi_powerpc_sysv) and
  429. is_64bit(paradef) and
  430. odd(nextintreg-RS_R3) then
  431. inc(nextintreg);
  432. {$endif not cpu64bitaddr}
  433. if (paralen = 0) then
  434. if (paradef.typ = recorddef) then
  435. begin
  436. paraloc:=hp.paraloc[side].add_location;
  437. paraloc^.loc := LOC_VOID;
  438. end
  439. else
  440. internalerror(2005011310);
  441. { can become < 0 for e.g. 3-byte records }
  442. while (paralen > 0) do
  443. begin
  444. paraloc:=hp.paraloc[side].add_location;
  445. { In case of po_delphi_nested_cc, the parent frame pointer
  446. is always passed on the stack. }
  447. if (loc = LOC_REGISTER) and
  448. (nextintreg <= RS_R10) and
  449. (not(vo_is_parentfp in hp.varoptions) or
  450. not(po_delphi_nested_cc in p.procoptions)) then
  451. begin
  452. paraloc^.loc := loc;
  453. { make sure we don't lose whether or not the type is signed }
  454. if (paradef.typ <> orddef) then
  455. paracgsize := int_cgsize(paralen);
  456. if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
  457. paraloc^.size := OS_INT
  458. else
  459. paraloc^.size := paracgsize;
  460. { aix requires that record data stored in parameter
  461. registers is left-aligned }
  462. if (target_info.system in systems_aix) and
  463. (paradef.typ = recorddef) and
  464. (tcgsize2size[paraloc^.size] <> sizeof(aint)) then
  465. begin
  466. paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
  467. paraloc^.size := OS_INT;
  468. end;
  469. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  470. inc(nextintreg);
  471. dec(paralen,tcgsize2size[paraloc^.size]);
  472. if target_info.abi=abi_powerpc_aix then
  473. inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
  474. end
  475. else if (loc = LOC_FPUREGISTER) and
  476. (nextfloatreg <= maxfpureg) then
  477. begin
  478. paraloc^.loc:=loc;
  479. paraloc^.size := paracgsize;
  480. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  481. inc(nextfloatreg);
  482. dec(paralen,tcgsize2size[paraloc^.size]);
  483. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  484. { are less of those available for parameter passing in the AIX abi }
  485. if target_info.abi=abi_powerpc_aix then
  486. {$ifndef cpu64bitaddr}
  487. if (paracgsize = OS_F32) then
  488. begin
  489. inc(stack_offset,4);
  490. if (nextintreg < RS_R11) then
  491. inc(nextintreg);
  492. end
  493. else
  494. begin
  495. inc(stack_offset,8);
  496. if (nextintreg < RS_R10) then
  497. inc(nextintreg,2)
  498. else
  499. nextintreg := RS_R11;
  500. end;
  501. {$else not cpu64bitaddr}
  502. begin
  503. inc(stack_offset,tcgsize2size[paracgsize]);
  504. if (nextintreg < RS_R11) then
  505. inc(nextintreg);
  506. end;
  507. {$endif not cpu64bitaddr}
  508. end
  509. else { LOC_REFERENCE }
  510. begin
  511. paraloc^.loc:=LOC_REFERENCE;
  512. case loc of
  513. LOC_FPUREGISTER:
  514. paraloc^.size:=int_float_cgsize(paralen);
  515. LOC_REGISTER,
  516. LOC_REFERENCE:
  517. paraloc^.size:=int_cgsize(paralen);
  518. else
  519. internalerror(2006011101);
  520. end;
  521. if (side = callerside) then
  522. paraloc^.reference.index:=NR_STACK_POINTER_REG
  523. else
  524. begin
  525. paraloc^.reference.index:=NR_R12;
  526. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  527. end;
  528. if not((target_info.system in systems_aix) and
  529. (paradef.typ=recorddef)) and
  530. (target_info.abi = abi_powerpc_aix) and
  531. (hp.paraloc[side].intsize < 3) then
  532. paraloc^.reference.offset:=stack_offset+(4-paralen)
  533. else
  534. paraloc^.reference.offset:=stack_offset;
  535. inc(stack_offset,align(paralen,4));
  536. while (paralen > 0) and
  537. (nextintreg < RS_R11) do
  538. begin
  539. inc(nextintreg);
  540. dec(paralen,sizeof(pint));
  541. end;
  542. paralen := 0;
  543. end;
  544. end;
  545. end;
  546. curintreg:=nextintreg;
  547. curfloatreg:=nextfloatreg;
  548. curmmreg:=nextmmreg;
  549. cur_stack_offset:=stack_offset;
  550. result:=stack_offset;
  551. end;
  552. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  553. var
  554. cur_stack_offset: aword;
  555. parasize, l: longint;
  556. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  557. i : integer;
  558. hp: tparavarsym;
  559. paraloc: pcgparalocation;
  560. begin
  561. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  562. firstfloatreg:=curfloatreg;
  563. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  564. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) then
  565. { just continue loading the parameters in the registers }
  566. begin
  567. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  568. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  569. if (target_info.abi = abi_powerpc_aix) and
  570. (result < 32) then
  571. result := 32;
  572. end
  573. else
  574. begin
  575. parasize:=cur_stack_offset;
  576. for i:=0 to varargspara.count-1 do
  577. begin
  578. hp:=tparavarsym(varargspara[i]);
  579. hp.paraloc[callerside].alignment:=4;
  580. paraloc:=hp.paraloc[callerside].add_location;
  581. paraloc^.loc:=LOC_REFERENCE;
  582. paraloc^.size:=def_cgsize(hp.vardef);
  583. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  584. l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  585. paraloc^.reference.offset:=parasize;
  586. parasize:=parasize+l;
  587. end;
  588. result:=parasize;
  589. end;
  590. if curfloatreg<>firstfloatreg then
  591. include(varargspara.varargsinfo,va_uses_float_reg);
  592. end;
  593. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  594. var
  595. paraloc : pcgparalocation;
  596. paracgsize : tcgsize;
  597. begin
  598. result:=false;
  599. case target_info.system of
  600. system_powerpc_morphos:
  601. begin
  602. paracgsize:=def_cgsize(p.vardef);
  603. p.paraloc[callerside].alignment:=4;
  604. p.paraloc[callerside].size:=paracgsize;
  605. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  606. paraloc:=p.paraloc[callerside].add_location;
  607. paraloc^.loc:=LOC_REFERENCE;
  608. paraloc^.size:=paracgsize;
  609. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  610. { pattern is always uppercase'd }
  611. if s='D0' then
  612. paraloc^.reference.offset:=0
  613. else if s='D1' then
  614. paraloc^.reference.offset:=4
  615. else if s='D2' then
  616. paraloc^.reference.offset:=8
  617. else if s='D3' then
  618. paraloc^.reference.offset:=12
  619. else if s='D4' then
  620. paraloc^.reference.offset:=16
  621. else if s='D5' then
  622. paraloc^.reference.offset:=20
  623. else if s='D6' then
  624. paraloc^.reference.offset:=24
  625. else if s='D7' then
  626. paraloc^.reference.offset:=28
  627. else if s='A0' then
  628. paraloc^.reference.offset:=32
  629. else if s='A1' then
  630. paraloc^.reference.offset:=36
  631. else if s='A2' then
  632. paraloc^.reference.offset:=40
  633. else if s='A3' then
  634. paraloc^.reference.offset:=44
  635. else if s='A4' then
  636. paraloc^.reference.offset:=48
  637. else if s='A5' then
  638. paraloc^.reference.offset:=52
  639. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  640. never passes parameters in it,
  641. Indeed, but this allows to declare libbase either explicitly
  642. or let the compiler insert it }
  643. else if s='A6' then
  644. paraloc^.reference.offset:=56
  645. { 'A7' is the stack pointer on 68k, can't be overwritten
  646. by API calls, so it has no offset }
  647. { 'R12' is special, used internally to support r12base sysv
  648. calling convention }
  649. else if s='R12' then
  650. begin
  651. paraloc^.loc:=LOC_REGISTER;
  652. paraloc^.size:=OS_ADDR;
  653. paraloc^.register:=NR_R12;
  654. end
  655. else
  656. exit;
  657. { copy to callee side }
  658. p.paraloc[calleeside].add_location^:=paraloc^;
  659. end;
  660. else
  661. internalerror(200404182);
  662. end;
  663. result:=true;
  664. end;
  665. begin
  666. paramanager:=tppcparamanager.create;
  667. end.