cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  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. cclasses,
  24. aasmtai,
  25. cpubase,cpuinfo,
  26. symconst,symbase,symtype,symdef,symsym,
  27. paramgr,parabase,cgbase;
  28. type
  29. tppcparamanager = class(tparamanager)
  30. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  31. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  32. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  33. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
  34. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  35. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  36. procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  37. private
  38. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  39. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  40. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  41. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  42. end;
  43. implementation
  44. uses
  45. verbose,systems,
  46. procinfo,
  47. rgobj,
  48. defutil,
  49. cgutils;
  50. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  51. begin
  52. if (target_info.system = system_powerpc_darwin) then
  53. result := [RS_R2..RS_R12]
  54. else
  55. result := [RS_R3..RS_R12];
  56. end;
  57. function tppcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  58. begin
  59. case target_info.abi of
  60. abi_powerpc_aix,
  61. abi_powerpc_sysv:
  62. result := [RS_F0..RS_F13];
  63. else
  64. internalerror(2003091401);
  65. end;
  66. end;
  67. procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
  68. var
  69. paraloc : pcgparalocation;
  70. begin
  71. cgpara.reset;
  72. cgpara.size:=OS_INT;
  73. cgpara.intsize:=tcgsize2size[OS_INT];
  74. cgpara.alignment:=get_para_align(calloption);
  75. paraloc:=cgpara.add_location;
  76. with paraloc^ do
  77. begin
  78. size:=OS_INT;
  79. if (nr<=8) then
  80. begin
  81. if nr=0 then
  82. internalerror(200309271);
  83. loc:=LOC_REGISTER;
  84. register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
  85. end
  86. else
  87. begin
  88. loc:=LOC_REFERENCE;
  89. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  90. if (target_info.abi <> abi_powerpc_aix) then
  91. reference.offset:=sizeof(aint)*(nr-8)
  92. else
  93. reference.offset:=sizeof(aint)*(nr);
  94. end;
  95. end;
  96. end;
  97. function getparaloc(p : tdef) : tcgloc;
  98. begin
  99. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  100. if push_addr_param for the def is true
  101. }
  102. case p.deftype of
  103. orddef:
  104. result:=LOC_REGISTER;
  105. floatdef:
  106. result:=LOC_FPUREGISTER;
  107. enumdef:
  108. result:=LOC_REGISTER;
  109. pointerdef:
  110. result:=LOC_REGISTER;
  111. formaldef:
  112. result:=LOC_REGISTER;
  113. classrefdef:
  114. result:=LOC_REGISTER;
  115. recorddef:
  116. if (target_info.abi<>abi_powerpc_aix) then
  117. result:=LOC_REFERENCE
  118. else
  119. result:=LOC_REGISTER;
  120. objectdef:
  121. if is_object(p) then
  122. result:=LOC_REFERENCE
  123. else
  124. result:=LOC_REGISTER;
  125. stringdef:
  126. if is_shortstring(p) or is_longstring(p) then
  127. result:=LOC_REFERENCE
  128. else
  129. result:=LOC_REGISTER;
  130. procvardef:
  131. if (po_methodpointer in tprocvardef(p).procoptions) then
  132. result:=LOC_REFERENCE
  133. else
  134. result:=LOC_REGISTER;
  135. filedef:
  136. result:=LOC_REGISTER;
  137. arraydef:
  138. result:=LOC_REFERENCE;
  139. setdef:
  140. if is_smallset(p) then
  141. result:=LOC_REGISTER
  142. else
  143. result:=LOC_REFERENCE;
  144. variantdef:
  145. result:=LOC_REFERENCE;
  146. { avoid problems with errornous definitions }
  147. errordef:
  148. result:=LOC_REGISTER;
  149. else
  150. internalerror(2002071001);
  151. end;
  152. end;
  153. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  154. begin
  155. { var,out always require address }
  156. if varspez in [vs_var,vs_out] then
  157. begin
  158. result:=true;
  159. exit;
  160. end;
  161. case def.deftype of
  162. recorddef:
  163. result :=(target_info.abi<>abi_powerpc_aix);
  164. arraydef:
  165. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  166. is_open_array(def) or
  167. is_array_of_const(def) or
  168. is_array_constructor(def);
  169. setdef :
  170. result:=(tsetdef(def).settype<>smallset);
  171. stringdef :
  172. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  173. procvardef :
  174. result:=po_methodpointer in tprocvardef(def).procoptions;
  175. else
  176. result:=inherited push_addr_param(varspez,def,calloption);
  177. end;
  178. end;
  179. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  180. begin
  181. case target_info.abi of
  182. abi_powerpc_aix:
  183. cur_stack_offset:=24;
  184. abi_powerpc_sysv:
  185. cur_stack_offset:=8;
  186. else
  187. internalerror(2003051901);
  188. end;
  189. curintreg:=RS_R3;
  190. curfloatreg:=RS_F1;
  191. curmmreg:=RS_M1;
  192. end;
  193. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  194. var
  195. retcgsize : tcgsize;
  196. begin
  197. { Constructors return self instead of a boolean }
  198. if (p.proctypeoption=potype_constructor) then
  199. retcgsize:=OS_ADDR
  200. else
  201. retcgsize:=def_cgsize(p.rettype.def);
  202. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  203. p.funcretloc[side].size:=retcgsize;
  204. { void has no location }
  205. if is_void(p.rettype.def) then
  206. begin
  207. p.funcretloc[side].loc:=LOC_VOID;
  208. exit;
  209. end;
  210. { Return in FPU register? }
  211. if p.rettype.def.deftype=floatdef then
  212. begin
  213. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  214. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  215. p.funcretloc[side].size:=retcgsize;
  216. end
  217. else
  218. { Return in register? }
  219. if not ret_in_param(p.rettype.def,p.proccalloption) then
  220. begin
  221. {$ifndef cpu64bit}
  222. if retcgsize in [OS_64,OS_S64] then
  223. begin
  224. { low 32bits }
  225. p.funcretloc[side].loc:=LOC_REGISTER;
  226. if side=callerside then
  227. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  228. else
  229. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  230. { high 32bits }
  231. if side=callerside then
  232. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  233. else
  234. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  235. end
  236. else
  237. {$endif cpu64bit}
  238. begin
  239. p.funcretloc[side].loc:=LOC_REGISTER;
  240. p.funcretloc[side].size:=retcgsize;
  241. if side=callerside then
  242. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  243. else
  244. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  245. end;
  246. end
  247. else
  248. begin
  249. p.funcretloc[side].loc:=LOC_REFERENCE;
  250. p.funcretloc[side].size:=retcgsize;
  251. end;
  252. end;
  253. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  254. var
  255. cur_stack_offset: aword;
  256. curintreg, curfloatreg, curmmreg: tsuperregister;
  257. begin
  258. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  259. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  260. create_funcretloc_info(p,side);
  261. end;
  262. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  263. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  264. var
  265. stack_offset: longint;
  266. paralen: aint;
  267. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  268. paradef : tdef;
  269. paraloc,paraloc2 : pcgparalocation;
  270. i : integer;
  271. hp : tparavarsym;
  272. loc : tcgloc;
  273. paracgsize: tcgsize;
  274. def64bit: boolean;
  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. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  363. ((target_info.system = system_powerpc_darwin) and
  364. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  365. begin
  366. paradef :=
  367. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  368. loc := getparaloc(paradef);
  369. paracgsize:=def_cgsize(paradef);
  370. end
  371. else
  372. begin
  373. loc := LOC_REGISTER;
  374. paracgsize := int_cgsize(paralen);
  375. end;
  376. end
  377. else
  378. begin
  379. loc:=getparaloc(paradef);
  380. paracgsize:=def_cgsize(paradef);
  381. { for things like formaldef }
  382. if (paracgsize=OS_NO) then
  383. begin
  384. paracgsize:=OS_ADDR;
  385. paralen := tcgsize2size[OS_ADDR];
  386. end;
  387. end
  388. end;
  389. hp.paraloc[side].alignment:=std_param_align;
  390. hp.paraloc[side].size:=paracgsize;
  391. hp.paraloc[side].intsize:=paralen;
  392. if (target_info.abi = abi_powerpc_aix) and
  393. (paradef.deftype = recorddef) then
  394. hp.paraloc[side].composite:=true;
  395. {$ifndef cpu64bit}
  396. if (target_info.abi=abi_powerpc_sysv) and
  397. is_64bit(paradef) and
  398. odd(nextintreg-RS_R3) then
  399. inc(nextintreg);
  400. {$endif not cpu64bit}
  401. if (paralen = 0) then
  402. if (paradef.deftype = recorddef) then
  403. begin
  404. paraloc:=hp.paraloc[side].add_location;
  405. paraloc^.loc := LOC_VOID;
  406. end
  407. else
  408. internalerror(2005011310);
  409. { can become < 0 for e.g. 3-byte records }
  410. while (paralen > 0) do
  411. begin
  412. paraloc:=hp.paraloc[side].add_location;
  413. if (loc = LOC_REGISTER) and
  414. (nextintreg <= RS_R10) then
  415. begin
  416. paraloc^.loc := loc;
  417. paracgsize := int_cgsize(paralen);
  418. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  419. paraloc^.size := OS_INT
  420. else
  421. paraloc^.size := paracgsize;
  422. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  423. inc(nextintreg);
  424. dec(paralen,tcgsize2size[paraloc^.size]);
  425. if target_info.abi=abi_powerpc_aix then
  426. inc(stack_offset,tcgsize2size[paraloc^.size]);
  427. end
  428. else if (loc = LOC_FPUREGISTER) and
  429. (nextfloatreg <= maxfpureg) then
  430. begin
  431. paraloc^.loc:=loc;
  432. paraloc^.size := paracgsize;
  433. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  434. inc(nextfloatreg);
  435. dec(paralen,tcgsize2size[paraloc^.size]);
  436. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  437. { are less of those available for parameter passing in the AIX abi }
  438. if target_info.abi=abi_powerpc_aix then
  439. {$ifndef cpu64bit}
  440. if (paracgsize = OS_F32) then
  441. begin
  442. inc(stack_offset,4);
  443. if (nextintreg < RS_R11) then
  444. inc(nextintreg);
  445. end
  446. else
  447. begin
  448. inc(stack_offset,8);
  449. if (nextintreg < RS_R10) then
  450. inc(nextintreg,2)
  451. else
  452. nextintreg := RS_R11;
  453. end;
  454. {$else not cpu64bit}
  455. begin
  456. inc(stack_offset,tcgsize2size[paracgsize]);
  457. if (nextintreg < RS_R11) then
  458. inc(nextintreg);
  459. end;
  460. {$endif not cpu64bit}
  461. end
  462. else { LOC_REFERENCE }
  463. begin
  464. paraloc^.loc:=LOC_REFERENCE;
  465. paraloc^.size:=int_cgsize(paralen);
  466. if (side = callerside) then
  467. paraloc^.reference.index:=NR_STACK_POINTER_REG
  468. else
  469. paraloc^.reference.index:=NR_R12;
  470. paraloc^.reference.offset:=stack_offset;
  471. inc(stack_offset,align(paralen,4));
  472. paralen := 0;
  473. end;
  474. end;
  475. end;
  476. curintreg:=nextintreg;
  477. curfloatreg:=nextfloatreg;
  478. curmmreg:=nextmmreg;
  479. cur_stack_offset:=stack_offset;
  480. result:=stack_offset;
  481. end;
  482. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  483. var
  484. cur_stack_offset: aword;
  485. parasize, l: longint;
  486. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  487. i : integer;
  488. hp: tparavarsym;
  489. paraloc: pcgparalocation;
  490. begin
  491. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  492. firstfloatreg:=curfloatreg;
  493. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  494. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  495. { just continue loading the parameters in the registers }
  496. begin
  497. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  498. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  499. if (target_info.abi = abi_powerpc_aix) and
  500. (result < 32) then
  501. result := 32;
  502. end
  503. else
  504. begin
  505. parasize:=cur_stack_offset;
  506. for i:=0 to varargspara.count-1 do
  507. begin
  508. hp:=tparavarsym(varargspara[i]);
  509. hp.paraloc[callerside].alignment:=4;
  510. paraloc:=hp.paraloc[callerside].add_location;
  511. paraloc^.loc:=LOC_REFERENCE;
  512. paraloc^.size:=def_cgsize(hp.vartype.def);
  513. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  514. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  515. paraloc^.reference.offset:=parasize;
  516. parasize:=parasize+l;
  517. end;
  518. result:=parasize;
  519. end;
  520. if curfloatreg<>firstfloatreg then
  521. include(varargspara.varargsinfo,va_uses_float_reg);
  522. end;
  523. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  524. var
  525. paraloc : pcgparalocation;
  526. begin
  527. result:=false;
  528. case target_info.system of
  529. system_powerpc_morphos:
  530. begin
  531. p.paraloc[callerside].alignment:=4;
  532. p.paraloc[callerside].size:=def_cgsize(p.vartype.def);
  533. paraloc:=p.paraloc[callerside].add_location;
  534. paraloc^.loc:=LOC_REFERENCE;
  535. paraloc^.size:=def_cgsize(p.vartype.def);
  536. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  537. { pattern is always uppercase'd }
  538. if s='D0' then
  539. paraloc^.reference.offset:=0
  540. else if s='D1' then
  541. paraloc^.reference.offset:=4
  542. else if s='D2' then
  543. paraloc^.reference.offset:=8
  544. else if s='D3' then
  545. paraloc^.reference.offset:=12
  546. else if s='D4' then
  547. paraloc^.reference.offset:=16
  548. else if s='D5' then
  549. paraloc^.reference.offset:=20
  550. else if s='D6' then
  551. paraloc^.reference.offset:=24
  552. else if s='D7' then
  553. paraloc^.reference.offset:=28
  554. else if s='A0' then
  555. paraloc^.reference.offset:=32
  556. else if s='A1' then
  557. paraloc^.reference.offset:=36
  558. else if s='A2' then
  559. paraloc^.reference.offset:=40
  560. else if s='A3' then
  561. paraloc^.reference.offset:=44
  562. else if s='A4' then
  563. paraloc^.reference.offset:=48
  564. else if s='A5' then
  565. paraloc^.reference.offset:=52
  566. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  567. never passes parameters in it,
  568. Indeed, but this allows to declare libbase either explicitly
  569. or let the compiler insert it }
  570. else if s='A6' then
  571. paraloc^.reference.offset:=56
  572. { 'A7' is the stack pointer on 68k, can't be overwritten
  573. by API calls, so it has no offset }
  574. { 'R12' is special, used internally to support r12base sysv
  575. calling convention }
  576. else if s='R12' then
  577. begin
  578. paraloc^.loc:=LOC_REGISTER;
  579. paraloc^.size:=OS_ADDR;
  580. paraloc^.register:=NR_R12;
  581. end
  582. else
  583. exit;
  584. { copy to callee side }
  585. p.paraloc[calleeside].add_location^:=paraloc^;
  586. end;
  587. else
  588. internalerror(200404182);
  589. end;
  590. result:=true;
  591. end;
  592. begin
  593. paramanager:=tppcparamanager.create;
  594. end.
  595. {
  596. $Log$
  597. Revision 1.85 2005-01-20 17:47:01 peter
  598. * remove copy_value_on_stack and a_param_copy_ref
  599. Revision 1.84 2005/01/14 20:59:17 jonas
  600. * fixed overallocation of stack space for parameters under SYSV
  601. (introduced in one of my previous commits)
  602. * unified code of get_volatile_registers_fpu for SYSV and AIX
  603. Revision 1.83 2005/01/13 22:02:40 jonas
  604. * r2 can be used by the register allocator under Darwin
  605. * merged the initialisations of the fpu register allocator for AIX and
  606. SYSV
  607. Revision 1.82 2005/01/13 19:32:08 jonas
  608. * fixed copy_value_on_stack() for AIX abi
  609. + added support for passing empty record parameters
  610. Revision 1.81 2005/01/10 21:50:05 jonas
  611. + support for passing records in registers under darwin
  612. * tcgpara now also has an intsize field, which contains the size in
  613. bytes of the whole parameter
  614. Revision 1.80 2005/01/07 10:58:03 jonas
  615. * fixed stupid tregister/tsuperregister bug (type checking circumvented
  616. using explicit typecase), caused bug3523
  617. Revision 1.79 2005/01/06 02:13:03 karoly
  618. * more SysV call support stuff for MorphOS
  619. Revision 1.78 2005/01/05 19:01:53 karoly
  620. * sysv abi also uses F0-F13 as volatile registers
  621. Revision 1.77 2004/12/24 15:00:11 jonas
  622. * fixed call-by-value passing of records with size 1, 2 or 4 for AIX abi
  623. (using a hack, normally all records should by passed by value under the
  624. aix abi, but that's currently impossible)
  625. Revision 1.76 2004/12/15 19:30:32 peter
  626. * syscall with sysv abi for morphos
  627. Revision 1.75 2004/12/04 21:47:46 jonas
  628. * modifications to work with the generic code to copy LOC_REFERENCE
  629. parameters to local temps (fixes tests/test/cg/tmanypara)
  630. Revision 1.74 2004/11/22 22:01:19 peter
  631. * fixed varargs
  632. * replaced dynarray with tlist
  633. Revision 1.73 2004/11/21 17:54:59 peter
  634. * ttempcreatenode.create_reg merged into .create with parameter
  635. whether a register is allowed
  636. * funcret_paraloc renamed to funcretloc
  637. Revision 1.72 2004/11/21 17:17:04 florian
  638. * changed funcret location back to tlocation
  639. Revision 1.71 2004/11/15 23:35:31 peter
  640. * tparaitem removed, use tparavarsym instead
  641. * parameter order is now calculated from paranr value in tparavarsym
  642. Revision 1.70 2004/11/14 16:26:29 florian
  643. * fixed morphos syscall
  644. Revision 1.69 2004/09/25 20:28:20 florian
  645. * indention fixed
  646. Revision 1.68 2004/09/21 17:25:13 peter
  647. * paraloc branch merged
  648. Revision 1.67.4.3 2004/09/18 20:21:08 jonas
  649. * fixed ppc, but still needs fix in tgobj
  650. Revision 1.67.4.2 2004/09/10 11:10:08 florian
  651. * first part of ppc fixes
  652. Revision 1.67.4.1 2004/08/31 20:43:06 peter
  653. * paraloc patch
  654. Revision 1.67 2004/07/19 19:15:50 florian
  655. * fixed funcretloc writing in units
  656. Revision 1.66 2004/07/17 13:51:57 florian
  657. * function result location for syscalls on MOS hopefully correctly set now
  658. Revision 1.65 2004/07/09 21:45:24 jonas
  659. * fixed passing of fpu paras on the stack
  660. * fixed number of fpu parameters passed in registers
  661. * skip corresponding integer registers when using an fpu register for a
  662. parameter under the AIX abi
  663. Revision 1.64 2004/07/01 18:00:37 jonas
  664. * fix for broken TP-style constructor handling in the compiler
  665. Revision 1.63 2004/06/20 08:55:32 florian
  666. * logs truncated
  667. Revision 1.62 2004/05/01 22:05:02 florian
  668. + added lib support for Amiga/MorphOS syscalls
  669. Revision 1.61 2004/04/18 23:19:48 karoly
  670. * added correct offsets for PowerPC/MorphOS location support
  671. Revision 1.60 2004/04/18 15:22:24 florian
  672. + location support for arguments, currently PowerPC/MorphOS only
  673. Revision 1.59 2004/02/19 17:07:42 florian
  674. * fixed arg. area calculation
  675. Revision 1.58 2004/02/11 23:18:59 florian
  676. * fixed to compile the rtl again
  677. }