cpupara.pas 26 KB

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