cpupara.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  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 :=(target_info.abi<>abi_powerpc_aix);
  165. arraydef:
  166. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  167. is_open_array(def) or
  168. is_array_of_const(def) or
  169. is_array_constructor(def);
  170. objectdef :
  171. result:=is_object(def);
  172. setdef :
  173. result:=(tsetdef(def).settype<>smallset);
  174. stringdef :
  175. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  176. procvardef :
  177. result:=po_methodpointer in tprocvardef(def).procoptions;
  178. end;
  179. end;
  180. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  181. begin
  182. case target_info.abi of
  183. abi_powerpc_aix:
  184. cur_stack_offset:=24;
  185. abi_powerpc_sysv:
  186. cur_stack_offset:=8;
  187. else
  188. internalerror(2003051901);
  189. end;
  190. curintreg:=RS_R3;
  191. curfloatreg:=RS_F1;
  192. curmmreg:=RS_M1;
  193. end;
  194. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  195. var
  196. retcgsize : tcgsize;
  197. begin
  198. { Constructors return self instead of a boolean }
  199. if (p.proctypeoption=potype_constructor) then
  200. retcgsize:=OS_ADDR
  201. else
  202. retcgsize:=def_cgsize(p.rettype.def);
  203. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  204. p.funcretloc[side].size:=retcgsize;
  205. { void has no location }
  206. if is_void(p.rettype.def) then
  207. begin
  208. p.funcretloc[side].loc:=LOC_VOID;
  209. exit;
  210. end;
  211. { Return in FPU register? }
  212. if p.rettype.def.deftype=floatdef then
  213. begin
  214. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  215. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  216. p.funcretloc[side].size:=retcgsize;
  217. end
  218. else
  219. { Return in register? }
  220. if not ret_in_param(p.rettype.def,p.proccalloption) then
  221. begin
  222. {$ifndef cpu64bit}
  223. if retcgsize in [OS_64,OS_S64] then
  224. begin
  225. { low 32bits }
  226. p.funcretloc[side].loc:=LOC_REGISTER;
  227. if side=callerside then
  228. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  229. else
  230. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  231. { high 32bits }
  232. if side=callerside then
  233. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  234. else
  235. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  236. end
  237. else
  238. {$endif cpu64bit}
  239. begin
  240. p.funcretloc[side].loc:=LOC_REGISTER;
  241. p.funcretloc[side].size:=retcgsize;
  242. if side=callerside then
  243. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  244. else
  245. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  246. end;
  247. end
  248. else
  249. begin
  250. p.funcretloc[side].loc:=LOC_REFERENCE;
  251. p.funcretloc[side].size:=retcgsize;
  252. end;
  253. end;
  254. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  255. var
  256. cur_stack_offset: aword;
  257. curintreg, curfloatreg, curmmreg: tsuperregister;
  258. begin
  259. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  260. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  261. create_funcretloc_info(p,side);
  262. end;
  263. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  264. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  265. var
  266. stack_offset: longint;
  267. paralen: aint;
  268. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  269. paradef : tdef;
  270. paraloc : pcgparalocation;
  271. i : integer;
  272. hp : tparavarsym;
  273. loc : tcgloc;
  274. paracgsize: tcgsize;
  275. (*
  276. procedure assignintreg;
  277. begin
  278. if nextintreg<=RS_R10 then
  279. begin
  280. paraloc^.loc:=LOC_REGISTER;
  281. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  282. inc(nextintreg);
  283. if target_info.abi=abi_powerpc_aix then
  284. inc(stack_offset,4);
  285. end
  286. else
  287. begin
  288. paraloc^.loc:=LOC_REFERENCE;
  289. if (side = callerside) then
  290. paraloc^.reference.index:=NR_STACK_POINTER_REG
  291. else
  292. paraloc^.reference.index:=NR_R12;
  293. paraloc^.reference.offset:=stack_offset;
  294. inc(stack_offset,4);
  295. end;
  296. end;
  297. *)
  298. begin
  299. {$ifdef extdebug}
  300. if po_explicitparaloc in p.procoptions then
  301. internalerror(200411141);
  302. {$endif extdebug}
  303. result:=0;
  304. nextintreg := curintreg;
  305. nextfloatreg := curfloatreg;
  306. nextmmreg := curmmreg;
  307. stack_offset := cur_stack_offset;
  308. case target_info.abi of
  309. abi_powerpc_aix:
  310. maxfpureg := RS_F13;
  311. abi_powerpc_sysv:
  312. maxfpureg := RS_F8;
  313. else internalerror(2004070912);
  314. end;
  315. for i:=0 to paras.count-1 do
  316. begin
  317. hp:=tparavarsym(paras[i]);
  318. paradef := hp.vartype.def;
  319. { Syscall for Morphos can have already a paraloc set }
  320. if (vo_has_explicit_paraloc in hp.varoptions) then
  321. begin
  322. if not(vo_is_syscall_lib in hp.varoptions) then
  323. internalerror(200412153);
  324. continue;
  325. end;
  326. hp.paraloc[side].reset;
  327. { currently only support C-style array of const }
  328. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  329. is_array_of_const(paradef) then
  330. begin
  331. paraloc:=hp.paraloc[side].add_location;
  332. { hack: the paraloc must be valid, but is not actually used }
  333. paraloc^.loc := LOC_REGISTER;
  334. paraloc^.register := NR_R0;
  335. paraloc^.size := OS_ADDR;
  336. break;
  337. end;
  338. if (hp.varspez in [vs_var,vs_out]) or
  339. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  340. is_open_array(paradef) or
  341. is_array_of_const(paradef) then
  342. begin
  343. paradef:=voidpointertype.def;
  344. loc:=LOC_REGISTER;
  345. paracgsize := OS_ADDR;
  346. paralen := tcgsize2size[OS_ADDR];
  347. end
  348. else
  349. begin
  350. if not is_special_array(paradef) then
  351. paralen := paradef.size
  352. else
  353. paralen := tcgsize2size[def_cgsize(paradef)];
  354. if (target_info.abi = abi_powerpc_aix) and
  355. (paradef.deftype = recorddef) and
  356. (hp.varspez in [vs_value,vs_const]) then
  357. begin
  358. { if a record has only one field and that field is }
  359. { non-composite (not array or record), it must be }
  360. { passed according to the rules of that type. }
  361. if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
  362. (not trecorddef(hp.vartype.def).isunion) and
  363. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  364. ((target_info.system = system_powerpc_darwin) and
  365. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  366. begin
  367. paradef :=
  368. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  369. loc := getparaloc(paradef);
  370. paracgsize:=def_cgsize(paradef);
  371. end
  372. else
  373. begin
  374. loc := LOC_REGISTER;
  375. paracgsize := int_cgsize(paralen);
  376. end;
  377. end
  378. else
  379. begin
  380. loc:=getparaloc(paradef);
  381. paracgsize:=def_cgsize(paradef);
  382. { for things like formaldef }
  383. if (paracgsize=OS_NO) then
  384. begin
  385. paracgsize:=OS_ADDR;
  386. paralen := tcgsize2size[OS_ADDR];
  387. end;
  388. end
  389. end;
  390. hp.paraloc[side].alignment:=std_param_align;
  391. hp.paraloc[side].size:=paracgsize;
  392. hp.paraloc[side].intsize:=paralen;
  393. if (target_info.abi = abi_powerpc_aix) and
  394. (paradef.deftype = recorddef) then
  395. hp.paraloc[side].composite:=true;
  396. {$ifndef cpu64bit}
  397. if (target_info.abi=abi_powerpc_sysv) and
  398. is_64bit(paradef) and
  399. odd(nextintreg-RS_R3) then
  400. inc(nextintreg);
  401. {$endif not cpu64bit}
  402. if (paralen = 0) then
  403. if (paradef.deftype = recorddef) then
  404. begin
  405. paraloc:=hp.paraloc[side].add_location;
  406. paraloc^.loc := LOC_VOID;
  407. end
  408. else
  409. internalerror(2005011310);
  410. { can become < 0 for e.g. 3-byte records }
  411. while (paralen > 0) do
  412. begin
  413. paraloc:=hp.paraloc[side].add_location;
  414. if (loc = LOC_REGISTER) and
  415. (nextintreg <= RS_R10) then
  416. begin
  417. paraloc^.loc := loc;
  418. { make sure we don't lose whether or not the type is signed }
  419. if (paradef.deftype <> orddef) then
  420. paracgsize := int_cgsize(paralen);
  421. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  422. paraloc^.size := OS_INT
  423. else
  424. paraloc^.size := paracgsize;
  425. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  426. inc(nextintreg);
  427. dec(paralen,tcgsize2size[paraloc^.size]);
  428. if target_info.abi=abi_powerpc_aix then
  429. inc(stack_offset,tcgsize2size[paraloc^.size]);
  430. end
  431. else if (loc = LOC_FPUREGISTER) and
  432. (nextfloatreg <= maxfpureg) then
  433. begin
  434. paraloc^.loc:=loc;
  435. paraloc^.size := paracgsize;
  436. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  437. inc(nextfloatreg);
  438. dec(paralen,tcgsize2size[paraloc^.size]);
  439. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  440. { are less of those available for parameter passing in the AIX abi }
  441. if target_info.abi=abi_powerpc_aix then
  442. {$ifndef cpu64bit}
  443. if (paracgsize = OS_F32) then
  444. begin
  445. inc(stack_offset,4);
  446. if (nextintreg < RS_R11) then
  447. inc(nextintreg);
  448. end
  449. else
  450. begin
  451. inc(stack_offset,8);
  452. if (nextintreg < RS_R10) then
  453. inc(nextintreg,2)
  454. else
  455. nextintreg := RS_R11;
  456. end;
  457. {$else not cpu64bit}
  458. begin
  459. inc(stack_offset,tcgsize2size[paracgsize]);
  460. if (nextintreg < RS_R11) then
  461. inc(nextintreg);
  462. end;
  463. {$endif not cpu64bit}
  464. end
  465. else { LOC_REFERENCE }
  466. begin
  467. paraloc^.loc:=LOC_REFERENCE;
  468. paraloc^.size:=int_cgsize(paralen);
  469. if (side = callerside) then
  470. paraloc^.reference.index:=NR_STACK_POINTER_REG
  471. else
  472. paraloc^.reference.index:=NR_R12;
  473. paraloc^.reference.offset:=stack_offset;
  474. inc(stack_offset,align(paralen,4));
  475. paralen := 0;
  476. end;
  477. end;
  478. end;
  479. curintreg:=nextintreg;
  480. curfloatreg:=nextfloatreg;
  481. curmmreg:=nextmmreg;
  482. cur_stack_offset:=stack_offset;
  483. result:=stack_offset;
  484. end;
  485. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  486. var
  487. cur_stack_offset: aword;
  488. parasize, l: longint;
  489. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  490. i : integer;
  491. hp: tparavarsym;
  492. paraloc: pcgparalocation;
  493. begin
  494. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  495. firstfloatreg:=curfloatreg;
  496. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  497. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  498. { just continue loading the parameters in the registers }
  499. begin
  500. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  501. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  502. if (target_info.abi = abi_powerpc_aix) and
  503. (result < 32) then
  504. result := 32;
  505. end
  506. else
  507. begin
  508. parasize:=cur_stack_offset;
  509. for i:=0 to varargspara.count-1 do
  510. begin
  511. hp:=tparavarsym(varargspara[i]);
  512. hp.paraloc[callerside].alignment:=4;
  513. paraloc:=hp.paraloc[callerside].add_location;
  514. paraloc^.loc:=LOC_REFERENCE;
  515. paraloc^.size:=def_cgsize(hp.vartype.def);
  516. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  517. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  518. paraloc^.reference.offset:=parasize;
  519. parasize:=parasize+l;
  520. end;
  521. result:=parasize;
  522. end;
  523. if curfloatreg<>firstfloatreg then
  524. include(varargspara.varargsinfo,va_uses_float_reg);
  525. end;
  526. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  527. var
  528. paraloc : pcgparalocation;
  529. paracgsize : tcgsize;
  530. begin
  531. result:=false;
  532. case target_info.system of
  533. system_powerpc_morphos:
  534. begin
  535. paracgsize:=def_cgsize(p.vartype.def);
  536. p.paraloc[callerside].alignment:=4;
  537. p.paraloc[callerside].size:=paracgsize;
  538. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  539. paraloc:=p.paraloc[callerside].add_location;
  540. paraloc^.loc:=LOC_REFERENCE;
  541. paraloc^.size:=paracgsize;
  542. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  543. { pattern is always uppercase'd }
  544. if s='D0' then
  545. paraloc^.reference.offset:=0
  546. else if s='D1' then
  547. paraloc^.reference.offset:=4
  548. else if s='D2' then
  549. paraloc^.reference.offset:=8
  550. else if s='D3' then
  551. paraloc^.reference.offset:=12
  552. else if s='D4' then
  553. paraloc^.reference.offset:=16
  554. else if s='D5' then
  555. paraloc^.reference.offset:=20
  556. else if s='D6' then
  557. paraloc^.reference.offset:=24
  558. else if s='D7' then
  559. paraloc^.reference.offset:=28
  560. else if s='A0' then
  561. paraloc^.reference.offset:=32
  562. else if s='A1' then
  563. paraloc^.reference.offset:=36
  564. else if s='A2' then
  565. paraloc^.reference.offset:=40
  566. else if s='A3' then
  567. paraloc^.reference.offset:=44
  568. else if s='A4' then
  569. paraloc^.reference.offset:=48
  570. else if s='A5' then
  571. paraloc^.reference.offset:=52
  572. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  573. never passes parameters in it,
  574. Indeed, but this allows to declare libbase either explicitly
  575. or let the compiler insert it }
  576. else if s='A6' then
  577. paraloc^.reference.offset:=56
  578. { 'A7' is the stack pointer on 68k, can't be overwritten
  579. by API calls, so it has no offset }
  580. { 'R12' is special, used internally to support r12base sysv
  581. calling convention }
  582. else if s='R12' then
  583. begin
  584. paraloc^.loc:=LOC_REGISTER;
  585. paraloc^.size:=OS_ADDR;
  586. paraloc^.register:=NR_R12;
  587. end
  588. else
  589. exit;
  590. { copy to callee side }
  591. p.paraloc[calleeside].add_location^:=paraloc^;
  592. end;
  593. else
  594. internalerror(200404182);
  595. end;
  596. result:=true;
  597. end;
  598. begin
  599. paramanager:=tppcparamanager.create;
  600. end.
  601. {
  602. $Log$
  603. Revision 1.90 2005-02-19 14:04:14 jonas
  604. * don't lose sign of ord types for register parameters
  605. Revision 1.89 2005/02/14 17:13:10 peter
  606. * truncate log
  607. Revision 1.88 2005/02/11 15:20:23 jonas
  608. * records which consist of only a union of one element have to be passed
  609. according to record parameter passing rules, not according to the rules
  610. of that item's type (change relevant to AIX abi only)
  611. Revision 1.87 2005/02/03 20:04:49 peter
  612. * push_addr_param must be defined per target
  613. Revision 1.86 2005/01/31 17:46:25 peter
  614. * fixed parseparaloc
  615. Revision 1.85 2005/01/20 17:47:01 peter
  616. * remove copy_value_on_stack and a_param_copy_ref
  617. Revision 1.84 2005/01/14 20:59:17 jonas
  618. * fixed overallocation of stack space for parameters under SYSV
  619. (introduced in one of my previous commits)
  620. * unified code of get_volatile_registers_fpu for SYSV and AIX
  621. Revision 1.83 2005/01/13 22:02:40 jonas
  622. * r2 can be used by the register allocator under Darwin
  623. * merged the initialisations of the fpu register allocator for AIX and
  624. SYSV
  625. Revision 1.82 2005/01/13 19:32:08 jonas
  626. * fixed copy_value_on_stack() for AIX abi
  627. + added support for passing empty record parameters
  628. Revision 1.81 2005/01/10 21:50:05 jonas
  629. + support for passing records in registers under darwin
  630. * tcgpara now also has an intsize field, which contains the size in
  631. bytes of the whole parameter
  632. Revision 1.80 2005/01/07 10:58:03 jonas
  633. * fixed stupid tregister/tsuperregister bug (type checking circumvented
  634. using explicit typecase), caused bug3523
  635. Revision 1.79 2005/01/06 02:13:03 karoly
  636. * more SysV call support stuff for MorphOS
  637. }