cpupara.pas 27 KB

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