2
0

cpupara.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  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. tcpuparamanager = 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(list: TAsmList; pd : tabstractprocdef; 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; forcetempdef: tdef): tcgpara;override;
  35. private
  36. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  37. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  38. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  39. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  40. end;
  41. implementation
  42. uses
  43. verbose,systems,
  44. defutil,symtable,
  45. procinfo,cpupi;
  46. function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  47. begin
  48. if (target_info.system = system_powerpc_darwin) then
  49. result := [RS_R0,RS_R2..RS_R12]
  50. else
  51. result := [RS_R0,RS_R3..RS_R12];
  52. end;
  53. function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  54. begin
  55. case target_info.abi of
  56. abi_powerpc_aix,
  57. abi_powerpc_darwin,
  58. abi_powerpc_sysv:
  59. result := [RS_F0..RS_F13];
  60. else
  61. internalerror(2003091401);
  62. end;
  63. end;
  64. procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
  65. var
  66. paraloc : pcgparalocation;
  67. psym : tparavarsym;
  68. pdef : tdef;
  69. begin
  70. psym:=tparavarsym(pd.paras[nr-1]);
  71. pdef:=psym.vardef;
  72. if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
  73. pdef:=cpointerdef.getreusable(pdef);
  74. cgpara.reset;
  75. cgpara.size:=def_cgsize(pdef);
  76. cgpara.intsize:=tcgsize2size[cgpara.size];
  77. cgpara.alignment:=get_para_align(pd.proccalloption);
  78. cgpara.def:=pdef;
  79. paraloc:=cgpara.add_location;
  80. with paraloc^ do
  81. begin
  82. size:=def_cgsize(pdef);
  83. def:=pdef;
  84. if (nr<=8) then
  85. begin
  86. if nr=0 then
  87. internalerror(200309271);
  88. loc:=LOC_REGISTER;
  89. register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
  90. end
  91. else
  92. begin
  93. loc:=LOC_REFERENCE;
  94. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  95. if not(target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) then
  96. reference.offset:=sizeof(pint)*(nr-8)
  97. else
  98. reference.offset:=sizeof(pint)*(nr);
  99. end;
  100. end;
  101. end;
  102. function getparaloc(p : tdef) : tcgloc;
  103. begin
  104. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  105. if push_addr_param for the def is true
  106. }
  107. case p.typ of
  108. orddef:
  109. result:=LOC_REGISTER;
  110. floatdef:
  111. result:=LOC_FPUREGISTER;
  112. enumdef:
  113. result:=LOC_REGISTER;
  114. pointerdef:
  115. result:=LOC_REGISTER;
  116. formaldef:
  117. result:=LOC_REGISTER;
  118. classrefdef:
  119. result:=LOC_REGISTER;
  120. procvardef:
  121. if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) or
  122. (p.size = sizeof(pint)) then
  123. result:=LOC_REGISTER
  124. else
  125. result:=LOC_REFERENCE;
  126. recorddef:
  127. if not(target_info.system in systems_aix) and
  128. (not(target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) or
  129. ((p.size >= 3) and
  130. ((p.size mod 4) <> 0))) then
  131. result:=LOC_REFERENCE
  132. else
  133. result:=LOC_REGISTER;
  134. objectdef:
  135. if is_object(p) then
  136. result:=LOC_REFERENCE
  137. else
  138. result:=LOC_REGISTER;
  139. stringdef:
  140. if is_shortstring(p) or is_longstring(p) then
  141. result:=LOC_REFERENCE
  142. else
  143. result:=LOC_REGISTER;
  144. filedef:
  145. result:=LOC_REGISTER;
  146. arraydef:
  147. if is_dynamic_array(p) then
  148. getparaloc:=LOC_REGISTER
  149. else
  150. result:=LOC_REFERENCE;
  151. setdef:
  152. if is_smallset(p) then
  153. result:=LOC_REGISTER
  154. else
  155. result:=LOC_REFERENCE;
  156. variantdef:
  157. result:=LOC_REFERENCE;
  158. { avoid problems with errornous definitions }
  159. errordef:
  160. result:=LOC_REGISTER;
  161. else
  162. internalerror(2002071001);
  163. end;
  164. end;
  165. function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  166. begin
  167. result:=false;
  168. { var,out,constref always require address }
  169. if varspez in [vs_var,vs_out,vs_constref] then
  170. begin
  171. result:=true;
  172. exit;
  173. end;
  174. case def.typ of
  175. variantdef,
  176. formaldef :
  177. result:=true;
  178. { regular procvars must be passed by value, because you cannot pass
  179. the address of a local stack location when calling e.g.
  180. pthread_create with the address of a function (first of all it
  181. expects the address of the function to execute and not the address
  182. of a memory location containing that address, and secondly if you
  183. first store the address on the stack and then pass the address of
  184. this stack location, then this stack location may no longer be
  185. valid when the newly started thread accesses it.
  186. However, for "procedure of object" we must use the same calling
  187. convention as for "8 byte record" due to the need for
  188. interchangeability with the TMethod record type.
  189. }
  190. procvardef :
  191. result:=
  192. not(target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  193. (def.size <> sizeof(pint));
  194. recorddef :
  195. result :=
  196. not(target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) or
  197. ((varspez = vs_const) and
  198. ((calloption = pocall_mwpascal) or
  199. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  200. (def.size > 8)
  201. )
  202. )
  203. );
  204. arraydef:
  205. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  206. is_open_array(def) or
  207. is_array_of_const(def) or
  208. is_array_constructor(def);
  209. objectdef :
  210. result:=is_object(def);
  211. setdef :
  212. result:=not is_smallset(def);
  213. stringdef :
  214. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  215. end;
  216. end;
  217. procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  218. begin
  219. case target_info.abi of
  220. abi_powerpc_aix,
  221. abi_powerpc_darwin:
  222. cur_stack_offset:=24;
  223. abi_powerpc_sysv:
  224. cur_stack_offset:=8;
  225. else
  226. internalerror(2003051901);
  227. end;
  228. curintreg:=RS_R3;
  229. curfloatreg:=RS_F1;
  230. curmmreg:=RS_M1;
  231. end;
  232. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  233. var
  234. paraloc : pcgparalocation;
  235. retcgsize : tcgsize;
  236. begin
  237. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  238. exit;
  239. paraloc:=result.add_location;
  240. { Return in FPU register? }
  241. if result.def.typ=floatdef then
  242. begin
  243. paraloc^.loc:=LOC_FPUREGISTER;
  244. paraloc^.register:=NR_FPU_RESULT_REG;
  245. paraloc^.size:=retcgsize;
  246. paraloc^.def:=result.def;
  247. end
  248. else
  249. { Return in register }
  250. begin
  251. if retcgsize in [OS_64,OS_S64] then
  252. begin
  253. { low 32bits }
  254. paraloc^.loc:=LOC_REGISTER;
  255. if side=callerside then
  256. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  257. else
  258. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  259. paraloc^.size:=OS_32;
  260. paraloc^.def:=u32inttype;
  261. { high 32bits }
  262. paraloc:=result.add_location;
  263. paraloc^.loc:=LOC_REGISTER;
  264. if side=callerside then
  265. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  266. else
  267. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  268. paraloc^.size:=OS_32;
  269. paraloc^.def:=u32inttype;
  270. end
  271. else
  272. begin
  273. paraloc^.loc:=LOC_REGISTER;
  274. if side=callerside then
  275. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  276. else
  277. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  278. paraloc^.size:=retcgsize;
  279. paraloc^.def:=result.def;
  280. end;
  281. end;
  282. end;
  283. function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  284. var
  285. cur_stack_offset: aword;
  286. curintreg, curfloatreg, curmmreg: tsuperregister;
  287. begin
  288. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  289. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
  290. create_funcretloc_info(p,side);
  291. end;
  292. function tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  293. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  294. var
  295. stack_offset: longint;
  296. paralen: aint;
  297. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  298. locdef,
  299. fdef,
  300. paradef : tdef;
  301. paraloc : pcgparalocation;
  302. i : integer;
  303. hp : tparavarsym;
  304. loc : tcgloc;
  305. paracgsize: tcgsize;
  306. firstparaloc: boolean;
  307. begin
  308. {$ifdef extdebug}
  309. if po_explicitparaloc in p.procoptions then
  310. internalerror(200411141);
  311. {$endif extdebug}
  312. result:=0;
  313. nextintreg := curintreg;
  314. nextfloatreg := curfloatreg;
  315. nextmmreg := curmmreg;
  316. stack_offset := cur_stack_offset;
  317. case target_info.abi of
  318. abi_powerpc_aix,
  319. abi_powerpc_darwin:
  320. maxfpureg := RS_F13;
  321. abi_powerpc_sysv:
  322. maxfpureg := RS_F8;
  323. else internalerror(2004070912);
  324. end;
  325. for i:=0 to paras.count-1 do
  326. begin
  327. hp:=tparavarsym(paras[i]);
  328. paradef := hp.vardef;
  329. { Syscall for Morphos can have already a paraloc set }
  330. if (vo_has_explicit_paraloc in hp.varoptions) then
  331. begin
  332. if not(vo_is_syscall_lib in hp.varoptions) then
  333. internalerror(200412153);
  334. continue;
  335. end;
  336. hp.paraloc[side].reset;
  337. { currently only support C-style array of const }
  338. if (p.proccalloption in cstylearrayofconst) and
  339. is_array_of_const(paradef) then
  340. begin
  341. paraloc:=hp.paraloc[side].add_location;
  342. { hack: the paraloc must be valid, but is not actually used }
  343. paraloc^.loc := LOC_REGISTER;
  344. paraloc^.register := NR_R0;
  345. paraloc^.size := OS_ADDR;
  346. paraloc^.def:=voidpointertype;
  347. break;
  348. end;
  349. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  350. begin
  351. paradef:=cpointerdef.getreusable(paradef);
  352. loc:=LOC_REGISTER;
  353. paracgsize := OS_ADDR;
  354. paralen := tcgsize2size[OS_ADDR];
  355. end
  356. else
  357. begin
  358. if not is_special_array(paradef) then
  359. paralen := paradef.size
  360. else
  361. paralen := tcgsize2size[def_cgsize(paradef)];
  362. if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  363. (paradef.typ = recorddef) and
  364. (hp.varspez in [vs_value,vs_const]) then
  365. begin
  366. { if a record has only one field and that field is }
  367. { non-composite (not array or record), it must be }
  368. { passed according to the rules of that type. }
  369. if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fdef) and
  370. ((fdef.typ=floatdef) or
  371. ((target_info.system=system_powerpc_darwin) and
  372. (fdef.typ in [orddef,enumdef]))) then
  373. begin
  374. paradef:=fdef;
  375. paracgsize:=def_cgsize(paradef);
  376. end
  377. else
  378. begin
  379. paracgsize := int_cgsize(paralen);
  380. end;
  381. end
  382. else
  383. begin
  384. paracgsize:=def_cgsize(paradef);
  385. { for things like formaldef }
  386. if (paracgsize=OS_NO) then
  387. begin
  388. paracgsize:=OS_ADDR;
  389. paralen := tcgsize2size[OS_ADDR];
  390. end;
  391. end
  392. end;
  393. loc := getparaloc(paradef);
  394. if varargsparas and
  395. (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  396. (paradef.typ = floatdef) then
  397. begin
  398. loc := LOC_REGISTER;
  399. if paracgsize=OS_F64 then
  400. begin
  401. paracgsize:=OS_64;
  402. paradef:=u64inttype;
  403. end
  404. else
  405. begin
  406. paracgsize:=OS_32;
  407. paradef:=u32inttype;
  408. end;
  409. end;
  410. hp.paraloc[side].alignment:=std_param_align;
  411. hp.paraloc[side].size:=paracgsize;
  412. hp.paraloc[side].intsize:=paralen;
  413. hp.paraloc[side].def:=paradef;
  414. {$ifndef cpu64bitaddr}
  415. if (target_info.abi=abi_powerpc_sysv) and
  416. is_64bit(paradef) and
  417. odd(nextintreg-RS_R3) then
  418. inc(nextintreg);
  419. {$endif not cpu64bitaddr}
  420. if (paralen = 0) then
  421. if (paradef.typ = recorddef) then
  422. begin
  423. paraloc:=hp.paraloc[side].add_location;
  424. paraloc^.loc := LOC_VOID;
  425. end
  426. else
  427. internalerror(2005011310);
  428. locdef:=paradef;
  429. firstparaloc:=true;
  430. { can become < 0 for e.g. 3-byte records }
  431. while (paralen > 0) do
  432. begin
  433. paraloc:=hp.paraloc[side].add_location;
  434. { In case of po_delphi_nested_cc, the parent frame pointer
  435. is always passed on the stack. }
  436. if (loc = LOC_REGISTER) and
  437. (nextintreg <= RS_R10) and
  438. (not(vo_is_parentfp in hp.varoptions) or
  439. not(po_delphi_nested_cc in p.procoptions)) then
  440. begin
  441. paraloc^.loc := loc;
  442. { make sure we don't lose whether or not the type is signed }
  443. if (paradef.typ<>orddef) then
  444. begin
  445. paracgsize:=int_cgsize(paralen);
  446. locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
  447. end;
  448. if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
  449. begin
  450. paraloc^.size:=OS_INT;
  451. paraloc^.def:=u32inttype;
  452. end
  453. else
  454. begin
  455. paraloc^.size:=paracgsize;
  456. paraloc^.def:=locdef;
  457. end;
  458. { aix requires that record data stored in parameter
  459. registers is left-aligned }
  460. if (target_info.system in systems_aix) and
  461. (paradef.typ = recorddef) and
  462. (tcgsize2size[paraloc^.size] <> sizeof(aint)) then
  463. begin
  464. paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
  465. paraloc^.size := OS_INT;
  466. paraloc^.def := u32inttype;
  467. end;
  468. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  469. inc(nextintreg);
  470. dec(paralen,tcgsize2size[paraloc^.size]);
  471. if target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin] then
  472. inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
  473. end
  474. else if (loc = LOC_FPUREGISTER) and
  475. (nextfloatreg <= maxfpureg) then
  476. begin
  477. paraloc^.loc:=loc;
  478. paraloc^.size := paracgsize;
  479. paraloc^.def := paradef;
  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 in [abi_powerpc_aix,abi_powerpc_darwin] 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. begin
  515. paraloc^.size:=int_float_cgsize(paralen);
  516. case paraloc^.size of
  517. OS_F32: paraloc^.def:=s32floattype;
  518. OS_F64: paraloc^.def:=s64floattype;
  519. else
  520. internalerror(2013060124);
  521. end;
  522. end;
  523. LOC_REGISTER,
  524. LOC_REFERENCE:
  525. begin
  526. paraloc^.size:=int_cgsize(paralen);
  527. if paraloc^.size<>OS_NO then
  528. paraloc^.def:=cgsize_orddef(paraloc^.size)
  529. else
  530. paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
  531. end;
  532. else
  533. internalerror(2006011101);
  534. end;
  535. if (side = callerside) then
  536. paraloc^.reference.index:=NR_STACK_POINTER_REG
  537. else
  538. begin
  539. paraloc^.reference.index:=NR_R12;
  540. { create_paraloc_info_intern might be also called when being outside of
  541. code generation so current_procinfo might be not set }
  542. if assigned(current_procinfo) then
  543. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  544. end;
  545. if not((target_info.system in systems_aix) and
  546. (paradef.typ=recorddef)) and
  547. (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  548. (hp.paraloc[side].intsize < 3) then
  549. paraloc^.reference.offset:=stack_offset+(4-paralen)
  550. else
  551. paraloc^.reference.offset:=stack_offset;
  552. inc(stack_offset,align(paralen,4));
  553. while (paralen > 0) and
  554. (nextintreg < RS_R11) do
  555. begin
  556. inc(nextintreg);
  557. dec(paralen,sizeof(pint));
  558. end;
  559. paralen := 0;
  560. end;
  561. firstparaloc:=false;
  562. end;
  563. end;
  564. curintreg:=nextintreg;
  565. curfloatreg:=nextfloatreg;
  566. curmmreg:=nextmmreg;
  567. cur_stack_offset:=stack_offset;
  568. result:=stack_offset;
  569. end;
  570. function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  571. var
  572. cur_stack_offset: aword;
  573. parasize, l: longint;
  574. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  575. i : integer;
  576. hp: tparavarsym;
  577. paraloc: pcgparalocation;
  578. begin
  579. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  580. firstfloatreg:=curfloatreg;
  581. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  582. if (p.proccalloption in cstylearrayofconst) then
  583. { just continue loading the parameters in the registers }
  584. begin
  585. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  586. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  587. if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  588. (result < 32) then
  589. result := 32;
  590. end
  591. else
  592. begin
  593. parasize:=cur_stack_offset;
  594. for i:=0 to varargspara.count-1 do
  595. begin
  596. hp:=tparavarsym(varargspara[i]);
  597. hp.paraloc[callerside].alignment:=4;
  598. paraloc:=hp.paraloc[callerside].add_location;
  599. paraloc^.loc:=LOC_REFERENCE;
  600. paraloc^.size:=def_cgsize(hp.vardef);
  601. paraloc^.def:=hp.vardef;
  602. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  603. l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  604. paraloc^.reference.offset:=parasize;
  605. parasize:=parasize+l;
  606. end;
  607. result:=parasize;
  608. end;
  609. if curfloatreg<>firstfloatreg then
  610. include(varargspara.varargsinfo,va_uses_float_reg);
  611. end;
  612. function tcpuparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  613. var
  614. paraloc : pcgparalocation;
  615. paracgsize : tcgsize;
  616. begin
  617. result:=false;
  618. case target_info.system of
  619. system_powerpc_morphos:
  620. begin
  621. paracgsize:=def_cgsize(p.vardef);
  622. p.paraloc[callerside].alignment:=4;
  623. p.paraloc[callerside].size:=paracgsize;
  624. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  625. paraloc:=p.paraloc[callerside].add_location;
  626. paraloc^.loc:=LOC_REFERENCE;
  627. { The OS side should be zero extended and the entire "virtual"
  628. 68k register should be overwritten. This is what the C ppcinline
  629. macros do as well, by casting all arguments to ULONG. A call
  630. which breaks w/o this is for example exec/RawPutChar (KB) }
  631. paraloc^.size:=OS_ADDR;
  632. paraloc^.def:=p.vardef;
  633. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  634. { pattern is always uppercase'd }
  635. if s='D0' then
  636. paraloc^.reference.offset:=0
  637. else if s='D1' then
  638. paraloc^.reference.offset:=4
  639. else if s='D2' then
  640. paraloc^.reference.offset:=8
  641. else if s='D3' then
  642. paraloc^.reference.offset:=12
  643. else if s='D4' then
  644. paraloc^.reference.offset:=16
  645. else if s='D5' then
  646. paraloc^.reference.offset:=20
  647. else if s='D6' then
  648. paraloc^.reference.offset:=24
  649. else if s='D7' then
  650. paraloc^.reference.offset:=28
  651. else if s='A0' then
  652. paraloc^.reference.offset:=32
  653. else if s='A1' then
  654. paraloc^.reference.offset:=36
  655. else if s='A2' then
  656. paraloc^.reference.offset:=40
  657. else if s='A3' then
  658. paraloc^.reference.offset:=44
  659. else if s='A4' then
  660. paraloc^.reference.offset:=48
  661. else if s='A5' then
  662. paraloc^.reference.offset:=52
  663. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  664. never passes parameters in it,
  665. Indeed, but this allows to declare libbase either explicitly
  666. or let the compiler insert it }
  667. else if s='A6' then
  668. paraloc^.reference.offset:=56
  669. { 'A7' is the stack pointer on 68k, can't be overwritten
  670. by API calls, so it has no offset }
  671. { 'R12' is special, used internally to support r12base sysv
  672. calling convention }
  673. else if s='R12' then
  674. begin
  675. paraloc^.loc:=LOC_REGISTER;
  676. paraloc^.size:=OS_ADDR;
  677. paraloc^.def:=voidpointertype;
  678. paraloc^.register:=NR_R12;
  679. end
  680. else
  681. exit;
  682. { copy to callee side }
  683. p.paraloc[calleeside].add_location^:=paraloc^;
  684. end;
  685. else
  686. internalerror(200404182);
  687. end;
  688. result:=true;
  689. end;
  690. begin
  691. paramanager:=tcpuparamanager.create;
  692. end.