cpupara.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. PowerPC specific calling conventions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cpupara;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. aasmtai,
  24. cpubase,
  25. symconst,symtype,symdef,symsym,
  26. paramgr,parabase,cgbase;
  27. type
  28. tppcparamanager = class(tparamanager)
  29. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  30. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  31. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  32. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
  33. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  34. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;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):longint;
  40. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  41. end;
  42. implementation
  43. uses
  44. verbose,systems,
  45. defutil,
  46. cgutils;
  47. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  48. begin
  49. if (target_info.system = system_powerpc_darwin) then
  50. result := [RS_R2..RS_R12]
  51. else
  52. result := [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_INT;
  70. cgpara.intsize:=tcgsize2size[OS_INT];
  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(aint)*(nr-8)
  89. else
  90. reference.offset:=sizeof(aint)*(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.deftype 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. recorddef:
  113. if (target_info.abi<>abi_powerpc_aix) then
  114. result:=LOC_REFERENCE
  115. else
  116. result:=LOC_REGISTER;
  117. objectdef:
  118. if is_object(p) then
  119. result:=LOC_REFERENCE
  120. else
  121. result:=LOC_REGISTER;
  122. stringdef:
  123. if is_shortstring(p) or is_longstring(p) then
  124. result:=LOC_REFERENCE
  125. else
  126. result:=LOC_REGISTER;
  127. procvardef:
  128. if (po_methodpointer in tprocvardef(p).procoptions) then
  129. result:=LOC_REFERENCE
  130. else
  131. result:=LOC_REGISTER;
  132. filedef:
  133. result:=LOC_REGISTER;
  134. arraydef:
  135. result:=LOC_REFERENCE;
  136. setdef:
  137. if is_smallset(p) then
  138. result:=LOC_REGISTER
  139. else
  140. result:=LOC_REFERENCE;
  141. variantdef:
  142. result:=LOC_REFERENCE;
  143. { avoid problems with errornous definitions }
  144. errordef:
  145. result:=LOC_REGISTER;
  146. else
  147. internalerror(2002071001);
  148. end;
  149. end;
  150. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  151. begin
  152. result:=false;
  153. { var,out always require address }
  154. if varspez in [vs_var,vs_out] then
  155. begin
  156. result:=true;
  157. exit;
  158. end;
  159. case def.deftype of
  160. variantdef,
  161. formaldef :
  162. result:=true;
  163. recorddef:
  164. result :=
  165. (target_info.abi<>abi_powerpc_aix) or
  166. ((varspez = vs_const) and
  167. ((calloption = pocall_mwpascal) or
  168. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  169. (def.size > 8)
  170. )
  171. )
  172. );
  173. arraydef:
  174. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  175. is_open_array(def) or
  176. is_array_of_const(def) or
  177. is_array_constructor(def);
  178. objectdef :
  179. result:=is_object(def);
  180. setdef :
  181. result:=(tsetdef(def).settype<>smallset);
  182. stringdef :
  183. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  184. procvardef :
  185. result:=po_methodpointer in tprocvardef(def).procoptions;
  186. end;
  187. end;
  188. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  189. begin
  190. case target_info.abi of
  191. abi_powerpc_aix:
  192. cur_stack_offset:=24;
  193. abi_powerpc_sysv:
  194. cur_stack_offset:=8;
  195. else
  196. internalerror(2003051901);
  197. end;
  198. curintreg:=RS_R3;
  199. curfloatreg:=RS_F1;
  200. curmmreg:=RS_M1;
  201. end;
  202. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  203. var
  204. retcgsize : tcgsize;
  205. begin
  206. { Constructors return self instead of a boolean }
  207. if (p.proctypeoption=potype_constructor) then
  208. retcgsize:=OS_ADDR
  209. else
  210. retcgsize:=def_cgsize(p.rettype.def);
  211. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  212. p.funcretloc[side].size:=retcgsize;
  213. { void has no location }
  214. if is_void(p.rettype.def) then
  215. begin
  216. p.funcretloc[side].loc:=LOC_VOID;
  217. exit;
  218. end;
  219. { Return in FPU register? }
  220. if p.rettype.def.deftype=floatdef then
  221. begin
  222. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  223. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  224. p.funcretloc[side].size:=retcgsize;
  225. end
  226. else
  227. { Return in register? }
  228. if not ret_in_param(p.rettype.def,p.proccalloption) then
  229. begin
  230. {$ifndef cpu64bit}
  231. if retcgsize in [OS_64,OS_S64] then
  232. begin
  233. { low 32bits }
  234. p.funcretloc[side].loc:=LOC_REGISTER;
  235. if side=callerside then
  236. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  237. else
  238. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  239. { high 32bits }
  240. if side=callerside then
  241. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  242. else
  243. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  244. end
  245. else
  246. {$endif cpu64bit}
  247. begin
  248. p.funcretloc[side].loc:=LOC_REGISTER;
  249. p.funcretloc[side].size:=retcgsize;
  250. if side=callerside then
  251. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  252. else
  253. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  254. end;
  255. end
  256. else
  257. begin
  258. p.funcretloc[side].loc:=LOC_REFERENCE;
  259. p.funcretloc[side].size:=retcgsize;
  260. end;
  261. end;
  262. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  263. var
  264. cur_stack_offset: aword;
  265. curintreg, curfloatreg, curmmreg: tsuperregister;
  266. begin
  267. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  268. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  269. create_funcretloc_info(p,side);
  270. end;
  271. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  272. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  273. var
  274. stack_offset: longint;
  275. paralen: aint;
  276. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  277. paradef : tdef;
  278. paraloc : pcgparalocation;
  279. i : integer;
  280. hp : tparavarsym;
  281. loc : tcgloc;
  282. paracgsize: tcgsize;
  283. (*
  284. procedure assignintreg;
  285. begin
  286. if nextintreg<=RS_R10 then
  287. begin
  288. paraloc^.loc:=LOC_REGISTER;
  289. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  290. inc(nextintreg);
  291. if target_info.abi=abi_powerpc_aix then
  292. inc(stack_offset,4);
  293. end
  294. else
  295. begin
  296. paraloc^.loc:=LOC_REFERENCE;
  297. if (side = callerside) then
  298. paraloc^.reference.index:=NR_STACK_POINTER_REG
  299. else
  300. paraloc^.reference.index:=NR_R12;
  301. paraloc^.reference.offset:=stack_offset;
  302. inc(stack_offset,4);
  303. end;
  304. end;
  305. *)
  306. begin
  307. {$ifdef extdebug}
  308. if po_explicitparaloc in p.procoptions then
  309. internalerror(200411141);
  310. {$endif extdebug}
  311. result:=0;
  312. nextintreg := curintreg;
  313. nextfloatreg := curfloatreg;
  314. nextmmreg := curmmreg;
  315. stack_offset := cur_stack_offset;
  316. case target_info.abi of
  317. abi_powerpc_aix:
  318. maxfpureg := RS_F13;
  319. abi_powerpc_sysv:
  320. maxfpureg := RS_F8;
  321. else internalerror(2004070912);
  322. end;
  323. for i:=0 to paras.count-1 do
  324. begin
  325. hp:=tparavarsym(paras[i]);
  326. paradef := hp.vartype.def;
  327. { Syscall for Morphos can have already a paraloc set }
  328. if (vo_has_explicit_paraloc in hp.varoptions) then
  329. begin
  330. if not(vo_is_syscall_lib in hp.varoptions) then
  331. internalerror(200412153);
  332. continue;
  333. end;
  334. hp.paraloc[side].reset;
  335. { currently only support C-style array of const }
  336. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  337. is_array_of_const(paradef) then
  338. begin
  339. paraloc:=hp.paraloc[side].add_location;
  340. { hack: the paraloc must be valid, but is not actually used }
  341. paraloc^.loc := LOC_REGISTER;
  342. paraloc^.register := NR_R0;
  343. paraloc^.size := OS_ADDR;
  344. break;
  345. end;
  346. if (hp.varspez in [vs_var,vs_out]) or
  347. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  348. is_open_array(paradef) or
  349. is_array_of_const(paradef) then
  350. begin
  351. paradef:=voidpointertype.def;
  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 = abi_powerpc_aix) and
  363. (paradef.deftype = 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 (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
  370. (not trecorddef(hp.vartype.def).isunion) and
  371. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  372. ((target_info.system = system_powerpc_darwin) and
  373. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  374. begin
  375. paradef :=
  376. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  377. loc := getparaloc(paradef);
  378. paracgsize:=def_cgsize(paradef);
  379. end
  380. else
  381. begin
  382. loc := LOC_REGISTER;
  383. paracgsize := int_cgsize(paralen);
  384. end;
  385. end
  386. else
  387. begin
  388. loc:=getparaloc(paradef);
  389. paracgsize:=def_cgsize(paradef);
  390. { for things like formaldef }
  391. if (paracgsize=OS_NO) then
  392. begin
  393. paracgsize:=OS_ADDR;
  394. paralen := tcgsize2size[OS_ADDR];
  395. end;
  396. end
  397. end;
  398. hp.paraloc[side].alignment:=std_param_align;
  399. hp.paraloc[side].size:=paracgsize;
  400. hp.paraloc[side].intsize:=paralen;
  401. if (target_info.abi = abi_powerpc_aix) and
  402. (paradef.deftype = recorddef) then
  403. hp.paraloc[side].composite:=true;
  404. {$ifndef cpu64bit}
  405. if (target_info.abi=abi_powerpc_sysv) and
  406. is_64bit(paradef) and
  407. odd(nextintreg-RS_R3) then
  408. inc(nextintreg);
  409. {$endif not cpu64bit}
  410. if (paralen = 0) then
  411. if (paradef.deftype = recorddef) then
  412. begin
  413. paraloc:=hp.paraloc[side].add_location;
  414. paraloc^.loc := LOC_VOID;
  415. end
  416. else
  417. internalerror(2005011310);
  418. { can become < 0 for e.g. 3-byte records }
  419. while (paralen > 0) do
  420. begin
  421. paraloc:=hp.paraloc[side].add_location;
  422. if (loc = LOC_REGISTER) and
  423. (nextintreg <= RS_R10) then
  424. begin
  425. paraloc^.loc := loc;
  426. { make sure we don't lose whether or not the type is signed }
  427. if (paradef.deftype <> orddef) then
  428. paracgsize := int_cgsize(paralen);
  429. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  430. paraloc^.size := OS_INT
  431. else
  432. paraloc^.size := paracgsize;
  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,tcgsize2size[paraloc^.size]);
  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 cpu64bit}
  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 cpu64bit}
  466. begin
  467. inc(stack_offset,tcgsize2size[paracgsize]);
  468. if (nextintreg < RS_R11) then
  469. inc(nextintreg);
  470. end;
  471. {$endif not cpu64bit}
  472. end
  473. else { LOC_REFERENCE }
  474. begin
  475. paraloc^.loc:=LOC_REFERENCE;
  476. paraloc^.size:=int_cgsize(paralen);
  477. if (side = callerside) then
  478. paraloc^.reference.index:=NR_STACK_POINTER_REG
  479. else
  480. paraloc^.reference.index:=NR_R12;
  481. paraloc^.reference.offset:=stack_offset;
  482. inc(stack_offset,align(paralen,4));
  483. paralen := 0;
  484. end;
  485. end;
  486. end;
  487. curintreg:=nextintreg;
  488. curfloatreg:=nextfloatreg;
  489. curmmreg:=nextmmreg;
  490. cur_stack_offset:=stack_offset;
  491. result:=stack_offset;
  492. end;
  493. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  494. var
  495. cur_stack_offset: aword;
  496. parasize, l: longint;
  497. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  498. i : integer;
  499. hp: tparavarsym;
  500. paraloc: pcgparalocation;
  501. begin
  502. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  503. firstfloatreg:=curfloatreg;
  504. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  505. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  506. { just continue loading the parameters in the registers }
  507. begin
  508. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  509. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  510. if (target_info.abi = abi_powerpc_aix) and
  511. (result < 32) then
  512. result := 32;
  513. end
  514. else
  515. begin
  516. parasize:=cur_stack_offset;
  517. for i:=0 to varargspara.count-1 do
  518. begin
  519. hp:=tparavarsym(varargspara[i]);
  520. hp.paraloc[callerside].alignment:=4;
  521. paraloc:=hp.paraloc[callerside].add_location;
  522. paraloc^.loc:=LOC_REFERENCE;
  523. paraloc^.size:=def_cgsize(hp.vartype.def);
  524. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  525. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  526. paraloc^.reference.offset:=parasize;
  527. parasize:=parasize+l;
  528. end;
  529. result:=parasize;
  530. end;
  531. if curfloatreg<>firstfloatreg then
  532. include(varargspara.varargsinfo,va_uses_float_reg);
  533. end;
  534. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  535. var
  536. paraloc : pcgparalocation;
  537. paracgsize : tcgsize;
  538. begin
  539. result:=false;
  540. case target_info.system of
  541. system_powerpc_morphos:
  542. begin
  543. paracgsize:=def_cgsize(p.vartype.def);
  544. p.paraloc[callerside].alignment:=4;
  545. p.paraloc[callerside].size:=paracgsize;
  546. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  547. paraloc:=p.paraloc[callerside].add_location;
  548. paraloc^.loc:=LOC_REFERENCE;
  549. paraloc^.size:=paracgsize;
  550. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  551. { pattern is always uppercase'd }
  552. if s='D0' then
  553. paraloc^.reference.offset:=0
  554. else if s='D1' then
  555. paraloc^.reference.offset:=4
  556. else if s='D2' then
  557. paraloc^.reference.offset:=8
  558. else if s='D3' then
  559. paraloc^.reference.offset:=12
  560. else if s='D4' then
  561. paraloc^.reference.offset:=16
  562. else if s='D5' then
  563. paraloc^.reference.offset:=20
  564. else if s='D6' then
  565. paraloc^.reference.offset:=24
  566. else if s='D7' then
  567. paraloc^.reference.offset:=28
  568. else if s='A0' then
  569. paraloc^.reference.offset:=32
  570. else if s='A1' then
  571. paraloc^.reference.offset:=36
  572. else if s='A2' then
  573. paraloc^.reference.offset:=40
  574. else if s='A3' then
  575. paraloc^.reference.offset:=44
  576. else if s='A4' then
  577. paraloc^.reference.offset:=48
  578. else if s='A5' then
  579. paraloc^.reference.offset:=52
  580. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  581. never passes parameters in it,
  582. Indeed, but this allows to declare libbase either explicitly
  583. or let the compiler insert it }
  584. else if s='A6' then
  585. paraloc^.reference.offset:=56
  586. { 'A7' is the stack pointer on 68k, can't be overwritten
  587. by API calls, so it has no offset }
  588. { 'R12' is special, used internally to support r12base sysv
  589. calling convention }
  590. else if s='R12' then
  591. begin
  592. paraloc^.loc:=LOC_REGISTER;
  593. paraloc^.size:=OS_ADDR;
  594. paraloc^.register:=NR_R12;
  595. end
  596. else
  597. exit;
  598. { copy to callee side }
  599. p.paraloc[calleeside].add_location^:=paraloc^;
  600. end;
  601. else
  602. internalerror(200404182);
  603. end;
  604. result:=true;
  605. end;
  606. begin
  607. paramanager:=tppcparamanager.create;
  608. end.
  609. {
  610. $Log$
  611. Revision 1.91 2005-03-27 14:10:53 jonas
  612. * const record parameters > 8 bytes are now passed by reference for non
  613. cdecl/cppdecl procedures on Mac OS/Mac OS X to fix compatibility with
  614. GPC (slightly more efficient than Metrowerks behaviour below, but
  615. less efficient in most cases than our previous scheme)
  616. + "mwpascal" procedure directive to support the const record parameter
  617. behaviour of Metrowerks Pascal, which passes all const records by
  618. reference
  619. Revision 1.90 2005/02/19 14:04:14 jonas
  620. * don't lose sign of ord types for register parameters
  621. Revision 1.89 2005/02/14 17:13:10 peter
  622. * truncate log
  623. Revision 1.88 2005/02/11 15:20:23 jonas
  624. * records which consist of only a union of one element have to be passed
  625. according to record parameter passing rules, not according to the rules
  626. of that item's type (change relevant to AIX abi only)
  627. Revision 1.87 2005/02/03 20:04:49 peter
  628. * push_addr_param must be defined per target
  629. Revision 1.86 2005/01/31 17:46:25 peter
  630. * fixed parseparaloc
  631. Revision 1.85 2005/01/20 17:47:01 peter
  632. * remove copy_value_on_stack and a_param_copy_ref
  633. Revision 1.84 2005/01/14 20:59:17 jonas
  634. * fixed overallocation of stack space for parameters under SYSV
  635. (introduced in one of my previous commits)
  636. * unified code of get_volatile_registers_fpu for SYSV and AIX
  637. Revision 1.83 2005/01/13 22:02:40 jonas
  638. * r2 can be used by the register allocator under Darwin
  639. * merged the initialisations of the fpu register allocator for AIX and
  640. SYSV
  641. Revision 1.82 2005/01/13 19:32:08 jonas
  642. * fixed copy_value_on_stack() for AIX abi
  643. + added support for passing empty record parameters
  644. Revision 1.81 2005/01/10 21:50:05 jonas
  645. + support for passing records in registers under darwin
  646. * tcgpara now also has an intsize field, which contains the size in
  647. bytes of the whole parameter
  648. Revision 1.80 2005/01/07 10:58:03 jonas
  649. * fixed stupid tregister/tsuperregister bug (type checking circumvented
  650. using explicit typecase), caused bug3523
  651. Revision 1.79 2005/01/06 02:13:03 karoly
  652. * more SysV call support stuff for MorphOS
  653. }