cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  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. function tppcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  193. begin
  194. result := false;
  195. if (target_info.abi <> abi_powerpc_aix) then
  196. result := inherited copy_value_on_stack(varspez,def,calloption);
  197. end;
  198. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  199. var
  200. retcgsize : tcgsize;
  201. begin
  202. { Constructors return self instead of a boolean }
  203. if (p.proctypeoption=potype_constructor) then
  204. retcgsize:=OS_ADDR
  205. else
  206. retcgsize:=def_cgsize(p.rettype.def);
  207. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  208. p.funcretloc[side].size:=retcgsize;
  209. { void has no location }
  210. if is_void(p.rettype.def) then
  211. begin
  212. p.funcretloc[side].loc:=LOC_VOID;
  213. exit;
  214. end;
  215. { Return in FPU register? }
  216. if p.rettype.def.deftype=floatdef then
  217. begin
  218. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  219. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  220. p.funcretloc[side].size:=retcgsize;
  221. end
  222. else
  223. { Return in register? }
  224. if not ret_in_param(p.rettype.def,p.proccalloption) then
  225. begin
  226. {$ifndef cpu64bit}
  227. if retcgsize in [OS_64,OS_S64] then
  228. begin
  229. { low 32bits }
  230. p.funcretloc[side].loc:=LOC_REGISTER;
  231. if side=callerside then
  232. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  233. else
  234. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  235. { high 32bits }
  236. if side=callerside then
  237. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  238. else
  239. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  240. end
  241. else
  242. {$endif cpu64bit}
  243. begin
  244. p.funcretloc[side].loc:=LOC_REGISTER;
  245. p.funcretloc[side].size:=retcgsize;
  246. if side=callerside then
  247. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  248. else
  249. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  250. end;
  251. end
  252. else
  253. begin
  254. p.funcretloc[side].loc:=LOC_REFERENCE;
  255. p.funcretloc[side].size:=retcgsize;
  256. end;
  257. end;
  258. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  259. var
  260. cur_stack_offset: aword;
  261. curintreg, curfloatreg, curmmreg: tsuperregister;
  262. begin
  263. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  264. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  265. create_funcretloc_info(p,side);
  266. end;
  267. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  268. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
  269. var
  270. stack_offset, parasize: longint;
  271. paralen: aint;
  272. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  273. paradef : tdef;
  274. paraloc,paraloc2 : pcgparalocation;
  275. i : integer;
  276. hp : tparavarsym;
  277. loc : tcgloc;
  278. paracgsize: tcgsize;
  279. def64bit: boolean;
  280. (*
  281. procedure assignintreg;
  282. begin
  283. if nextintreg<=RS_R10 then
  284. begin
  285. paraloc^.loc:=LOC_REGISTER;
  286. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  287. inc(nextintreg);
  288. if target_info.abi=abi_powerpc_aix then
  289. inc(stack_offset,4);
  290. end
  291. else
  292. begin
  293. paraloc^.loc:=LOC_REFERENCE;
  294. if (side = callerside) then
  295. paraloc^.reference.index:=NR_STACK_POINTER_REG
  296. else
  297. paraloc^.reference.index:=NR_R12;
  298. paraloc^.reference.offset:=stack_offset;
  299. inc(stack_offset,4);
  300. end;
  301. end;
  302. *)
  303. begin
  304. {$ifdef extdebug}
  305. if po_explicitparaloc in p.procoptions then
  306. internalerror(200411141);
  307. {$endif extdebug}
  308. result:=0;
  309. nextintreg := curintreg;
  310. nextfloatreg := curfloatreg;
  311. nextmmreg := curmmreg;
  312. stack_offset := cur_stack_offset;
  313. parasize := cur_stack_offset;
  314. case target_info.abi of
  315. abi_powerpc_aix:
  316. maxfpureg := RS_F13;
  317. abi_powerpc_sysv:
  318. maxfpureg := RS_F8;
  319. else internalerror(2004070912);
  320. end;
  321. for i:=0 to paras.count-1 do
  322. begin
  323. hp:=tparavarsym(paras[i]);
  324. paradef := hp.vartype.def;
  325. { Syscall for Morphos can have already a paraloc set }
  326. if (vo_has_explicit_paraloc in hp.varoptions) then
  327. begin
  328. if not(vo_is_syscall_lib in hp.varoptions) then
  329. internalerror(200412153);
  330. continue;
  331. end;
  332. hp.paraloc[side].reset;
  333. { currently only support C-style array of const }
  334. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  335. is_array_of_const(paradef) then
  336. begin
  337. paraloc:=hp.paraloc[side].add_location;
  338. { hack: the paraloc must be valid, but is not actually used }
  339. paraloc^.loc := LOC_REGISTER;
  340. paraloc^.register := NR_R0;
  341. paraloc^.size := OS_ADDR;
  342. break;
  343. end;
  344. if (hp.varspez in [vs_var,vs_out]) or
  345. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  346. is_open_array(paradef) or
  347. is_array_of_const(paradef) then
  348. begin
  349. paradef:=voidpointertype.def;
  350. loc:=LOC_REGISTER;
  351. paracgsize := OS_ADDR;
  352. paralen := tcgsize2size[OS_ADDR];
  353. end
  354. else
  355. begin
  356. if not is_special_array(paradef) then
  357. paralen := paradef.size
  358. else
  359. paralen := tcgsize2size[def_cgsize(paradef)];
  360. if (target_info.abi = abi_powerpc_aix) and
  361. (paradef.deftype = recorddef) and
  362. (hp.varspez in [vs_value,vs_const]) then
  363. begin
  364. { if a record has only one field and that field is }
  365. { non-composite (not array or record), it must be }
  366. { passed according to the rules of that type. }
  367. if (trecorddef(hp.vartype.def).symtable.symindex.count = 1) and
  368. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  369. ((target_info.system = system_powerpc_darwin) and
  370. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  371. begin
  372. paradef :=
  373. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  374. loc := getparaloc(paradef);
  375. paracgsize:=def_cgsize(paradef);
  376. end
  377. else
  378. begin
  379. loc := LOC_REGISTER;
  380. paracgsize := int_cgsize(paralen);
  381. end;
  382. end
  383. else
  384. begin
  385. loc:=getparaloc(paradef);
  386. paracgsize:=def_cgsize(paradef);
  387. { for things like formaldef }
  388. if (paracgsize=OS_NO) then
  389. begin
  390. paracgsize:=OS_ADDR;
  391. paralen := tcgsize2size[OS_ADDR];
  392. end;
  393. end
  394. end;
  395. hp.paraloc[side].alignment:=std_param_align;
  396. hp.paraloc[side].size:=paracgsize;
  397. hp.paraloc[side].intsize:=paralen;
  398. if (target_info.abi = abi_powerpc_aix) and
  399. (paradef.deftype = recorddef) then
  400. hp.paraloc[side].composite:=true;
  401. {$ifndef cpu64bit}
  402. if (target_info.abi=abi_powerpc_sysv) and
  403. is_64bit(paradef) and
  404. odd(nextintreg-RS_R3) then
  405. inc(nextintreg);
  406. {$endif not cpu64bit}
  407. if (paralen = 0) then
  408. if (paradef.deftype = recorddef) then
  409. begin
  410. paraloc:=hp.paraloc[side].add_location;
  411. paraloc^.loc := LOC_VOID;
  412. end
  413. else
  414. internalerror(2005011310);
  415. { can become < 0 for e.g. 3-byte records }
  416. while (paralen > 0) do
  417. begin
  418. paraloc:=hp.paraloc[side].add_location;
  419. if (loc = LOC_REGISTER) and
  420. (nextintreg <= RS_R10) then
  421. begin
  422. paraloc^.loc := loc;
  423. paracgsize := int_cgsize(paralen);
  424. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  425. paraloc^.size := OS_INT
  426. else
  427. paraloc^.size := paracgsize;
  428. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  429. inc(nextintreg);
  430. dec(paralen,tcgsize2size[paraloc^.size]);
  431. inc(parasize,tcgsize2size[paraloc^.size]);
  432. if target_info.abi=abi_powerpc_aix then
  433. stack_offset := parasize;
  434. end
  435. else if (loc = LOC_FPUREGISTER) and
  436. (nextfloatreg <= maxfpureg) then
  437. begin
  438. paraloc^.loc:=loc;
  439. paraloc^.size := paracgsize;
  440. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  441. inc(nextfloatreg);
  442. dec(paralen,tcgsize2size[paraloc^.size]);
  443. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  444. { are less of those available for parameter passing in the AIX abi }
  445. {$ifndef cpu64bit}
  446. if (paracgsize = OS_F32) then
  447. begin
  448. inc(parasize,4);
  449. if (nextintreg < RS_R11) then
  450. inc(nextintreg);
  451. end
  452. else
  453. begin
  454. inc(parasize,8);
  455. if (nextintreg < RS_R10) then
  456. inc(nextintreg,2)
  457. else
  458. nextintreg := RS_R11;
  459. end;
  460. {$else not cpu64bit}
  461. begin
  462. inc(parasize,tcgsize2size[paracgsize]);
  463. if (nextintreg < RS_R11) then
  464. inc(nextintreg);
  465. end;
  466. {$endif not cpu64bit}
  467. if target_info.abi=abi_powerpc_aix then
  468. stack_offset := parasize;
  469. end
  470. else { LOC_REFERENCE }
  471. begin
  472. paraloc^.loc:=LOC_REFERENCE;
  473. paraloc^.size:=int_cgsize(paralen);
  474. if (side = callerside) then
  475. paraloc^.reference.index:=NR_STACK_POINTER_REG
  476. else
  477. paraloc^.reference.index:=NR_R12;
  478. paraloc^.reference.offset:=stack_offset;
  479. inc(stack_offset,align(paralen,4));
  480. inc(parasize,align(paralen,4));
  481. paralen := 0;
  482. end;
  483. end;
  484. end;
  485. curintreg:=nextintreg;
  486. curfloatreg:=nextfloatreg;
  487. curmmreg:=nextmmreg;
  488. cur_stack_offset:=stack_offset;
  489. result:=parasize;
  490. end;
  491. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  492. var
  493. cur_stack_offset: aword;
  494. parasize, l: longint;
  495. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  496. i : integer;
  497. hp: tparavarsym;
  498. paraloc: pcgparalocation;
  499. begin
  500. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  501. firstfloatreg:=curfloatreg;
  502. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  503. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  504. { just continue loading the parameters in the registers }
  505. begin
  506. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  507. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  508. if (target_info.abi = abi_powerpc_aix) and
  509. (result < 32) then
  510. result := 32;
  511. end
  512. else
  513. begin
  514. parasize:=cur_stack_offset;
  515. for i:=0 to varargspara.count-1 do
  516. begin
  517. hp:=tparavarsym(varargspara[i]);
  518. hp.paraloc[callerside].alignment:=4;
  519. paraloc:=hp.paraloc[callerside].add_location;
  520. paraloc^.loc:=LOC_REFERENCE;
  521. paraloc^.size:=def_cgsize(hp.vartype.def);
  522. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  523. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  524. paraloc^.reference.offset:=parasize;
  525. parasize:=parasize+l;
  526. end;
  527. result:=parasize;
  528. end;
  529. if curfloatreg<>firstfloatreg then
  530. include(varargspara.varargsinfo,va_uses_float_reg);
  531. end;
  532. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  533. var
  534. paraloc : pcgparalocation;
  535. begin
  536. result:=false;
  537. case target_info.system of
  538. system_powerpc_morphos:
  539. begin
  540. p.paraloc[callerside].alignment:=4;
  541. p.paraloc[callerside].size:=def_cgsize(p.vartype.def);
  542. paraloc:=p.paraloc[callerside].add_location;
  543. paraloc^.loc:=LOC_REFERENCE;
  544. paraloc^.size:=def_cgsize(p.vartype.def);
  545. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  546. { pattern is always uppercase'd }
  547. if s='D0' then
  548. paraloc^.reference.offset:=0
  549. else if s='D1' then
  550. paraloc^.reference.offset:=4
  551. else if s='D2' then
  552. paraloc^.reference.offset:=8
  553. else if s='D3' then
  554. paraloc^.reference.offset:=12
  555. else if s='D4' then
  556. paraloc^.reference.offset:=16
  557. else if s='D5' then
  558. paraloc^.reference.offset:=20
  559. else if s='D6' then
  560. paraloc^.reference.offset:=24
  561. else if s='D7' then
  562. paraloc^.reference.offset:=28
  563. else if s='A0' then
  564. paraloc^.reference.offset:=32
  565. else if s='A1' then
  566. paraloc^.reference.offset:=36
  567. else if s='A2' then
  568. paraloc^.reference.offset:=40
  569. else if s='A3' then
  570. paraloc^.reference.offset:=44
  571. else if s='A4' then
  572. paraloc^.reference.offset:=48
  573. else if s='A5' then
  574. paraloc^.reference.offset:=52
  575. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  576. never passes parameters in it,
  577. Indeed, but this allows to declare libbase either explicitly
  578. or let the compiler insert it }
  579. else if s='A6' then
  580. paraloc^.reference.offset:=56
  581. { 'A7' is the stack pointer on 68k, can't be overwritten
  582. by API calls, so it has no offset }
  583. { 'R12' is special, used internally to support r12base sysv
  584. calling convention }
  585. else if s='R12' then
  586. begin
  587. paraloc^.loc:=LOC_REGISTER;
  588. paraloc^.size:=OS_ADDR;
  589. paraloc^.register:=NR_R12;
  590. end
  591. else
  592. exit;
  593. { copy to callee side }
  594. p.paraloc[calleeside].add_location^:=paraloc^;
  595. end;
  596. else
  597. internalerror(200404182);
  598. end;
  599. result:=true;
  600. end;
  601. begin
  602. paramanager:=tppcparamanager.create;
  603. end.
  604. {
  605. $Log$
  606. Revision 1.82 2005-01-13 19:32:08 jonas
  607. * fixed copy_value_on_stack() for AIX abi
  608. + added support for passing empty record parameters
  609. Revision 1.81 2005/01/10 21:50:05 jonas
  610. + support for passing records in registers under darwin
  611. * tcgpara now also has an intsize field, which contains the size in
  612. bytes of the whole parameter
  613. Revision 1.80 2005/01/07 10:58:03 jonas
  614. * fixed stupid tregister/tsuperregister bug (type checking circumvented
  615. using explicit typecase), caused bug3523
  616. Revision 1.79 2005/01/06 02:13:03 karoly
  617. * more SysV call support stuff for MorphOS
  618. Revision 1.78 2005/01/05 19:01:53 karoly
  619. * sysv abi also uses F0-F13 as volatile registers
  620. Revision 1.77 2004/12/24 15:00:11 jonas
  621. * fixed call-by-value passing of records with size 1, 2 or 4 for AIX abi
  622. (using a hack, normally all records should by passed by value under the
  623. aix abi, but that's currently impossible)
  624. Revision 1.76 2004/12/15 19:30:32 peter
  625. * syscall with sysv abi for morphos
  626. Revision 1.75 2004/12/04 21:47:46 jonas
  627. * modifications to work with the generic code to copy LOC_REFERENCE
  628. parameters to local temps (fixes tests/test/cg/tmanypara)
  629. Revision 1.74 2004/11/22 22:01:19 peter
  630. * fixed varargs
  631. * replaced dynarray with tlist
  632. Revision 1.73 2004/11/21 17:54:59 peter
  633. * ttempcreatenode.create_reg merged into .create with parameter
  634. whether a register is allowed
  635. * funcret_paraloc renamed to funcretloc
  636. Revision 1.72 2004/11/21 17:17:04 florian
  637. * changed funcret location back to tlocation
  638. Revision 1.71 2004/11/15 23:35:31 peter
  639. * tparaitem removed, use tparavarsym instead
  640. * parameter order is now calculated from paranr value in tparavarsym
  641. Revision 1.70 2004/11/14 16:26:29 florian
  642. * fixed morphos syscall
  643. Revision 1.69 2004/09/25 20:28:20 florian
  644. * indention fixed
  645. Revision 1.68 2004/09/21 17:25:13 peter
  646. * paraloc branch merged
  647. Revision 1.67.4.3 2004/09/18 20:21:08 jonas
  648. * fixed ppc, but still needs fix in tgobj
  649. Revision 1.67.4.2 2004/09/10 11:10:08 florian
  650. * first part of ppc fixes
  651. Revision 1.67.4.1 2004/08/31 20:43:06 peter
  652. * paraloc patch
  653. Revision 1.67 2004/07/19 19:15:50 florian
  654. * fixed funcretloc writing in units
  655. Revision 1.66 2004/07/17 13:51:57 florian
  656. * function result location for syscalls on MOS hopefully correctly set now
  657. Revision 1.65 2004/07/09 21:45:24 jonas
  658. * fixed passing of fpu paras on the stack
  659. * fixed number of fpu parameters passed in registers
  660. * skip corresponding integer registers when using an fpu register for a
  661. parameter under the AIX abi
  662. Revision 1.64 2004/07/01 18:00:37 jonas
  663. * fix for broken TP-style constructor handling in the compiler
  664. Revision 1.63 2004/06/20 08:55:32 florian
  665. * logs truncated
  666. Revision 1.62 2004/05/01 22:05:02 florian
  667. + added lib support for Amiga/MorphOS syscalls
  668. Revision 1.61 2004/04/18 23:19:48 karoly
  669. * added correct offsets for PowerPC/MorphOS location support
  670. Revision 1.60 2004/04/18 15:22:24 florian
  671. + location support for arguments, currently PowerPC/MorphOS only
  672. Revision 1.59 2004/02/19 17:07:42 florian
  673. * fixed arg. area calculation
  674. Revision 1.58 2004/02/11 23:18:59 florian
  675. * fixed to compile the rtl again
  676. }