cpupara.pas 28 KB

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