cpupara.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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; def : tdef; 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(calloption : tproccalloption; nr : longint; def : tdef; var cgpara : tcgpara);
  64. var
  65. paraloc : pcgparalocation;
  66. begin
  67. cgpara.reset;
  68. cgpara.size:=def_cgsize(def);
  69. cgpara.intsize:=tcgsize2size[cgpara.size];
  70. cgpara.alignment:=get_para_align(calloption);
  71. cgpara.def:=def;
  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. function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  221. var
  222. paraloc : pcgparalocation;
  223. retcgsize : tcgsize;
  224. begin
  225. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  226. exit;
  227. paraloc:=result.add_location;
  228. { Return in FPU register? }
  229. if result.def.typ=floatdef then
  230. begin
  231. paraloc^.loc:=LOC_FPUREGISTER;
  232. paraloc^.register:=NR_FPU_RESULT_REG;
  233. paraloc^.size:=retcgsize;
  234. end
  235. else
  236. { Return in register }
  237. begin
  238. if retcgsize in [OS_64,OS_S64] then
  239. begin
  240. { low 32bits }
  241. paraloc^.loc:=LOC_REGISTER;
  242. if side=callerside then
  243. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  244. else
  245. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  246. paraloc^.size:=OS_32;
  247. { high 32bits }
  248. paraloc:=result.add_location;
  249. paraloc^.loc:=LOC_REGISTER;
  250. if side=callerside then
  251. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  252. else
  253. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  254. paraloc^.size:=OS_32;
  255. end
  256. else
  257. begin
  258. paraloc^.loc:=LOC_REGISTER;
  259. if side=callerside then
  260. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  261. else
  262. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  263. paraloc^.size:=retcgsize;
  264. end;
  265. end;
  266. end;
  267. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  268. var
  269. cur_stack_offset: aword;
  270. curintreg, curfloatreg, curmmreg: tsuperregister;
  271. begin
  272. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  273. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
  274. create_funcretloc_info(p,side);
  275. end;
  276. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  277. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  278. var
  279. stack_offset: longint;
  280. paralen: aint;
  281. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  282. paradef : tdef;
  283. paraloc : pcgparalocation;
  284. i : integer;
  285. hp : tparavarsym;
  286. loc : tcgloc;
  287. paracgsize: tcgsize;
  288. sym: tfieldvarsym;
  289. begin
  290. {$ifdef extdebug}
  291. if po_explicitparaloc in p.procoptions then
  292. internalerror(200411141);
  293. {$endif extdebug}
  294. result:=0;
  295. nextintreg := curintreg;
  296. nextfloatreg := curfloatreg;
  297. nextmmreg := curmmreg;
  298. stack_offset := cur_stack_offset;
  299. case target_info.abi of
  300. abi_powerpc_aix:
  301. maxfpureg := RS_F13;
  302. abi_powerpc_sysv:
  303. maxfpureg := RS_F8;
  304. else internalerror(2004070912);
  305. end;
  306. for i:=0 to paras.count-1 do
  307. begin
  308. hp:=tparavarsym(paras[i]);
  309. paradef := hp.vardef;
  310. { Syscall for Morphos can have already a paraloc set }
  311. if (vo_has_explicit_paraloc in hp.varoptions) then
  312. begin
  313. if not(vo_is_syscall_lib in hp.varoptions) then
  314. internalerror(200412153);
  315. continue;
  316. end;
  317. hp.paraloc[side].reset;
  318. { currently only support C-style array of const }
  319. if (p.proccalloption in cstylearrayofconst) and
  320. is_array_of_const(paradef) then
  321. begin
  322. paraloc:=hp.paraloc[side].add_location;
  323. { hack: the paraloc must be valid, but is not actually used }
  324. paraloc^.loc := LOC_REGISTER;
  325. paraloc^.register := NR_R0;
  326. paraloc^.size := OS_ADDR;
  327. break;
  328. end;
  329. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  330. begin
  331. paradef:=getpointerdef(paradef);
  332. loc:=LOC_REGISTER;
  333. paracgsize := OS_ADDR;
  334. paralen := tcgsize2size[OS_ADDR];
  335. end
  336. else
  337. begin
  338. if not is_special_array(paradef) then
  339. paralen := paradef.size
  340. else
  341. paralen := tcgsize2size[def_cgsize(paradef)];
  342. if (target_info.abi = abi_powerpc_aix) and
  343. (paradef.typ = recorddef) and
  344. (hp.varspez in [vs_value,vs_const]) then
  345. begin
  346. { if a record has only one field and that field is }
  347. { non-composite (not array or record), it must be }
  348. { passed according to the rules of that type. }
  349. if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
  350. ((sym.vardef.typ=floatdef) or
  351. ((target_info.system=system_powerpc_darwin) and
  352. (sym.vardef.typ in [orddef,enumdef]))) then
  353. begin
  354. paradef:=sym.vardef;
  355. paracgsize:=def_cgsize(paradef);
  356. end
  357. else
  358. begin
  359. paracgsize := int_cgsize(paralen);
  360. end;
  361. end
  362. else
  363. begin
  364. paracgsize:=def_cgsize(paradef);
  365. { for things like formaldef }
  366. if (paracgsize=OS_NO) then
  367. begin
  368. paracgsize:=OS_ADDR;
  369. paralen := tcgsize2size[OS_ADDR];
  370. end;
  371. end
  372. end;
  373. loc := getparaloc(paradef);
  374. if varargsparas and
  375. (target_info.abi = abi_powerpc_aix) and
  376. (paradef.typ = floatdef) then
  377. begin
  378. loc := LOC_REGISTER;
  379. if paracgsize = OS_F64 then
  380. paracgsize := OS_64
  381. else
  382. paracgsize := OS_32;
  383. end;
  384. hp.paraloc[side].alignment:=std_param_align;
  385. hp.paraloc[side].size:=paracgsize;
  386. hp.paraloc[side].intsize:=paralen;
  387. hp.paraloc[side].def:=paradef;
  388. if (target_info.abi = abi_powerpc_aix) and
  389. (paradef.typ in [recorddef,arraydef]) then
  390. hp.paraloc[side].composite:=true;
  391. {$ifndef cpu64bitaddr}
  392. if (target_info.abi=abi_powerpc_sysv) and
  393. is_64bit(paradef) and
  394. odd(nextintreg-RS_R3) then
  395. inc(nextintreg);
  396. {$endif not cpu64bitaddr}
  397. if (paralen = 0) then
  398. if (paradef.typ = recorddef) then
  399. begin
  400. paraloc:=hp.paraloc[side].add_location;
  401. paraloc^.loc := LOC_VOID;
  402. end
  403. else
  404. internalerror(2005011310);
  405. { can become < 0 for e.g. 3-byte records }
  406. while (paralen > 0) do
  407. begin
  408. paraloc:=hp.paraloc[side].add_location;
  409. { In case of po_delphi_nested_cc, the parent frame pointer
  410. is always passed on the stack. }
  411. if (loc = LOC_REGISTER) and
  412. (nextintreg <= RS_R10) and
  413. (not(vo_is_parentfp in hp.varoptions) or
  414. not(po_delphi_nested_cc in p.procoptions)) then
  415. begin
  416. paraloc^.loc := loc;
  417. { make sure we don't lose whether or not the type is signed }
  418. if (paradef.typ <> orddef) then
  419. paracgsize := int_cgsize(paralen);
  420. if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
  421. paraloc^.size := OS_INT
  422. else
  423. paraloc^.size := paracgsize;
  424. { aix requires that record data stored in parameter
  425. registers is left-aligned }
  426. if (target_info.system in systems_aix) and
  427. (paradef.typ = recorddef) and
  428. (tcgsize2size[paraloc^.size] <> sizeof(aint)) then
  429. begin
  430. paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
  431. paraloc^.size := OS_INT;
  432. end;
  433. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  434. inc(nextintreg);
  435. dec(paralen,tcgsize2size[paraloc^.size]);
  436. if target_info.abi=abi_powerpc_aix then
  437. inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
  438. end
  439. else if (loc = LOC_FPUREGISTER) and
  440. (nextfloatreg <= maxfpureg) then
  441. begin
  442. paraloc^.loc:=loc;
  443. paraloc^.size := paracgsize;
  444. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  445. inc(nextfloatreg);
  446. dec(paralen,tcgsize2size[paraloc^.size]);
  447. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  448. { are less of those available for parameter passing in the AIX abi }
  449. if target_info.abi=abi_powerpc_aix then
  450. {$ifndef cpu64bitaddr}
  451. if (paracgsize = OS_F32) then
  452. begin
  453. inc(stack_offset,4);
  454. if (nextintreg < RS_R11) then
  455. inc(nextintreg);
  456. end
  457. else
  458. begin
  459. inc(stack_offset,8);
  460. if (nextintreg < RS_R10) then
  461. inc(nextintreg,2)
  462. else
  463. nextintreg := RS_R11;
  464. end;
  465. {$else not cpu64bitaddr}
  466. begin
  467. inc(stack_offset,tcgsize2size[paracgsize]);
  468. if (nextintreg < RS_R11) then
  469. inc(nextintreg);
  470. end;
  471. {$endif not cpu64bitaddr}
  472. end
  473. else { LOC_REFERENCE }
  474. begin
  475. paraloc^.loc:=LOC_REFERENCE;
  476. case loc of
  477. LOC_FPUREGISTER:
  478. paraloc^.size:=int_float_cgsize(paralen);
  479. LOC_REGISTER,
  480. LOC_REFERENCE:
  481. paraloc^.size:=int_cgsize(paralen);
  482. else
  483. internalerror(2006011101);
  484. end;
  485. if (side = callerside) then
  486. paraloc^.reference.index:=NR_STACK_POINTER_REG
  487. else
  488. begin
  489. paraloc^.reference.index:=NR_R12;
  490. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  491. end;
  492. if not((target_info.system in systems_aix) and
  493. (paradef.typ=recorddef)) and
  494. (target_info.abi = abi_powerpc_aix) and
  495. (hp.paraloc[side].intsize < 3) then
  496. paraloc^.reference.offset:=stack_offset+(4-paralen)
  497. else
  498. paraloc^.reference.offset:=stack_offset;
  499. inc(stack_offset,align(paralen,4));
  500. while (paralen > 0) and
  501. (nextintreg < RS_R11) do
  502. begin
  503. inc(nextintreg);
  504. dec(paralen,sizeof(pint));
  505. end;
  506. paralen := 0;
  507. end;
  508. end;
  509. end;
  510. curintreg:=nextintreg;
  511. curfloatreg:=nextfloatreg;
  512. curmmreg:=nextmmreg;
  513. cur_stack_offset:=stack_offset;
  514. result:=stack_offset;
  515. end;
  516. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  517. var
  518. cur_stack_offset: aword;
  519. parasize, l: longint;
  520. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  521. i : integer;
  522. hp: tparavarsym;
  523. paraloc: pcgparalocation;
  524. begin
  525. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  526. firstfloatreg:=curfloatreg;
  527. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  528. if (p.proccalloption in cstylearrayofconst) then
  529. { just continue loading the parameters in the registers }
  530. begin
  531. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  532. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  533. if (target_info.abi = abi_powerpc_aix) and
  534. (result < 32) then
  535. result := 32;
  536. end
  537. else
  538. begin
  539. parasize:=cur_stack_offset;
  540. for i:=0 to varargspara.count-1 do
  541. begin
  542. hp:=tparavarsym(varargspara[i]);
  543. hp.paraloc[callerside].alignment:=4;
  544. paraloc:=hp.paraloc[callerside].add_location;
  545. paraloc^.loc:=LOC_REFERENCE;
  546. paraloc^.size:=def_cgsize(hp.vardef);
  547. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  548. l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  549. paraloc^.reference.offset:=parasize;
  550. parasize:=parasize+l;
  551. end;
  552. result:=parasize;
  553. end;
  554. if curfloatreg<>firstfloatreg then
  555. include(varargspara.varargsinfo,va_uses_float_reg);
  556. end;
  557. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  558. var
  559. paraloc : pcgparalocation;
  560. paracgsize : tcgsize;
  561. begin
  562. result:=false;
  563. case target_info.system of
  564. system_powerpc_morphos:
  565. begin
  566. paracgsize:=def_cgsize(p.vardef);
  567. p.paraloc[callerside].alignment:=4;
  568. p.paraloc[callerside].size:=paracgsize;
  569. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  570. paraloc:=p.paraloc[callerside].add_location;
  571. paraloc^.loc:=LOC_REFERENCE;
  572. paraloc^.size:=paracgsize;
  573. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  574. { pattern is always uppercase'd }
  575. if s='D0' then
  576. paraloc^.reference.offset:=0
  577. else if s='D1' then
  578. paraloc^.reference.offset:=4
  579. else if s='D2' then
  580. paraloc^.reference.offset:=8
  581. else if s='D3' then
  582. paraloc^.reference.offset:=12
  583. else if s='D4' then
  584. paraloc^.reference.offset:=16
  585. else if s='D5' then
  586. paraloc^.reference.offset:=20
  587. else if s='D6' then
  588. paraloc^.reference.offset:=24
  589. else if s='D7' then
  590. paraloc^.reference.offset:=28
  591. else if s='A0' then
  592. paraloc^.reference.offset:=32
  593. else if s='A1' then
  594. paraloc^.reference.offset:=36
  595. else if s='A2' then
  596. paraloc^.reference.offset:=40
  597. else if s='A3' then
  598. paraloc^.reference.offset:=44
  599. else if s='A4' then
  600. paraloc^.reference.offset:=48
  601. else if s='A5' then
  602. paraloc^.reference.offset:=52
  603. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  604. never passes parameters in it,
  605. Indeed, but this allows to declare libbase either explicitly
  606. or let the compiler insert it }
  607. else if s='A6' then
  608. paraloc^.reference.offset:=56
  609. { 'A7' is the stack pointer on 68k, can't be overwritten
  610. by API calls, so it has no offset }
  611. { 'R12' is special, used internally to support r12base sysv
  612. calling convention }
  613. else if s='R12' then
  614. begin
  615. paraloc^.loc:=LOC_REGISTER;
  616. paraloc^.size:=OS_ADDR;
  617. paraloc^.register:=NR_R12;
  618. end
  619. else
  620. exit;
  621. { copy to callee side }
  622. p.paraloc[calleeside].add_location^:=paraloc^;
  623. end;
  624. else
  625. internalerror(200404182);
  626. end;
  627. result:=true;
  628. end;
  629. begin
  630. paramanager:=tppcparamanager.create;
  631. end.