cpupara.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. PowerPC specific calling conventions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cpupara;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmtai,aasmdata,
  23. cpubase,
  24. symconst,symtype,symdef,symsym,
  25. paramgr,parabase,cgbase;
  26. type
  27. tppcparamanager = class(tparamanager)
  28. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  29. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  30. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  31. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
  32. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  33. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  34. procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  35. private
  36. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  37. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  38. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  39. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  40. end;
  41. implementation
  42. uses
  43. verbose,systems,
  44. defutil,
  45. cgutils,
  46. procinfo,cpupi;
  47. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  48. begin
  49. if (target_info.system = system_powerpc_darwin) then
  50. result := [RS_R2..RS_R12]
  51. else
  52. result := [RS_R3..RS_R12];
  53. end;
  54. function tppcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  55. begin
  56. case target_info.abi of
  57. abi_powerpc_aix,
  58. abi_powerpc_sysv:
  59. result := [RS_F0..RS_F13];
  60. else
  61. internalerror(2003091401);
  62. end;
  63. end;
  64. procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
  65. var
  66. paraloc : pcgparalocation;
  67. begin
  68. cgpara.reset;
  69. cgpara.size:=OS_INT;
  70. cgpara.intsize:=tcgsize2size[OS_INT];
  71. cgpara.alignment:=get_para_align(calloption);
  72. paraloc:=cgpara.add_location;
  73. with paraloc^ do
  74. begin
  75. size:=OS_INT;
  76. if (nr<=8) then
  77. begin
  78. if nr=0 then
  79. internalerror(200309271);
  80. loc:=LOC_REGISTER;
  81. register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
  82. end
  83. else
  84. begin
  85. loc:=LOC_REFERENCE;
  86. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  87. if (target_info.abi <> abi_powerpc_aix) then
  88. reference.offset:=sizeof(aint)*(nr-8)
  89. else
  90. reference.offset:=sizeof(aint)*(nr);
  91. end;
  92. end;
  93. end;
  94. function getparaloc(p : tdef) : tcgloc;
  95. begin
  96. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  97. if push_addr_param for the def is true
  98. }
  99. case p.deftype of
  100. orddef:
  101. result:=LOC_REGISTER;
  102. floatdef:
  103. result:=LOC_FPUREGISTER;
  104. enumdef:
  105. result:=LOC_REGISTER;
  106. pointerdef:
  107. result:=LOC_REGISTER;
  108. formaldef:
  109. result:=LOC_REGISTER;
  110. classrefdef:
  111. result:=LOC_REGISTER;
  112. recorddef:
  113. if (target_info.abi<>abi_powerpc_aix) or
  114. ((p.size >= 3) and
  115. ((p.size mod 4) <> 0)) 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. result:=false;
  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. variantdef,
  163. formaldef :
  164. result:=true;
  165. recorddef:
  166. result :=
  167. (target_info.abi<>abi_powerpc_aix) or
  168. ((varspez = vs_const) and
  169. ((calloption = pocall_mwpascal) or
  170. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  171. (def.size > 8)
  172. )
  173. )
  174. );
  175. arraydef:
  176. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  177. is_open_array(def) or
  178. is_array_of_const(def) or
  179. is_array_constructor(def);
  180. objectdef :
  181. result:=is_object(def);
  182. setdef :
  183. result:=(tsetdef(def).settype<>smallset);
  184. stringdef :
  185. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  186. procvardef :
  187. result:=po_methodpointer in tprocvardef(def).procoptions;
  188. end;
  189. end;
  190. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  191. begin
  192. case target_info.abi of
  193. abi_powerpc_aix:
  194. cur_stack_offset:=24;
  195. abi_powerpc_sysv:
  196. cur_stack_offset:=8;
  197. else
  198. internalerror(2003051901);
  199. end;
  200. curintreg:=RS_R3;
  201. curfloatreg:=RS_F1;
  202. curmmreg:=RS_M1;
  203. end;
  204. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  205. var
  206. retcgsize : tcgsize;
  207. begin
  208. { Constructors return self instead of a boolean }
  209. if (p.proctypeoption=potype_constructor) then
  210. retcgsize:=OS_ADDR
  211. else
  212. retcgsize:=def_cgsize(p.returndef);
  213. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  214. p.funcretloc[side].size:=retcgsize;
  215. { void has no location }
  216. if is_void(p.returndef) then
  217. begin
  218. p.funcretloc[side].loc:=LOC_VOID;
  219. exit;
  220. end;
  221. { Return in FPU register? }
  222. if p.returndef.deftype=floatdef then
  223. begin
  224. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  225. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  226. p.funcretloc[side].size:=retcgsize;
  227. end
  228. else
  229. { Return in register? }
  230. if not ret_in_param(p.returndef,p.proccalloption) then
  231. begin
  232. {$ifndef cpu64bit}
  233. if retcgsize in [OS_64,OS_S64] then
  234. begin
  235. { low 32bits }
  236. p.funcretloc[side].loc:=LOC_REGISTER;
  237. if side=callerside then
  238. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  239. else
  240. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  241. { high 32bits }
  242. if side=callerside then
  243. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  244. else
  245. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  246. end
  247. else
  248. {$endif cpu64bit}
  249. begin
  250. p.funcretloc[side].loc:=LOC_REGISTER;
  251. p.funcretloc[side].size:=retcgsize;
  252. if side=callerside then
  253. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  254. else
  255. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  256. end;
  257. end
  258. else
  259. begin
  260. p.funcretloc[side].loc:=LOC_REFERENCE;
  261. p.funcretloc[side].size:=retcgsize;
  262. end;
  263. end;
  264. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  265. var
  266. cur_stack_offset: aword;
  267. curintreg, curfloatreg, curmmreg: tsuperregister;
  268. begin
  269. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  270. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
  271. create_funcretloc_info(p,side);
  272. end;
  273. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  274. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  275. var
  276. stack_offset: longint;
  277. paralen: aint;
  278. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  279. paradef : tdef;
  280. paraloc : pcgparalocation;
  281. i : integer;
  282. hp : tparavarsym;
  283. loc : tcgloc;
  284. paracgsize: tcgsize;
  285. begin
  286. {$ifdef extdebug}
  287. if po_explicitparaloc in p.procoptions then
  288. internalerror(200411141);
  289. {$endif extdebug}
  290. result:=0;
  291. nextintreg := curintreg;
  292. nextfloatreg := curfloatreg;
  293. nextmmreg := curmmreg;
  294. stack_offset := cur_stack_offset;
  295. case target_info.abi of
  296. abi_powerpc_aix:
  297. maxfpureg := RS_F13;
  298. abi_powerpc_sysv:
  299. maxfpureg := RS_F8;
  300. else internalerror(2004070912);
  301. end;
  302. for i:=0 to paras.count-1 do
  303. begin
  304. hp:=tparavarsym(paras[i]);
  305. paradef := hp.vardef;
  306. { Syscall for Morphos can have already a paraloc set }
  307. if (vo_has_explicit_paraloc in hp.varoptions) then
  308. begin
  309. if not(vo_is_syscall_lib in hp.varoptions) then
  310. internalerror(200412153);
  311. continue;
  312. end;
  313. hp.paraloc[side].reset;
  314. { currently only support C-style array of const }
  315. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) and
  316. is_array_of_const(paradef) then
  317. begin
  318. paraloc:=hp.paraloc[side].add_location;
  319. { hack: the paraloc must be valid, but is not actually used }
  320. paraloc^.loc := LOC_REGISTER;
  321. paraloc^.register := NR_R0;
  322. paraloc^.size := OS_ADDR;
  323. break;
  324. end;
  325. if (hp.varspez in [vs_var,vs_out]) or
  326. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  327. is_open_array(paradef) or
  328. is_array_of_const(paradef) then
  329. begin
  330. paradef:=voidpointertype;
  331. loc:=LOC_REGISTER;
  332. paracgsize := OS_ADDR;
  333. paralen := tcgsize2size[OS_ADDR];
  334. end
  335. else
  336. begin
  337. if not is_special_array(paradef) then
  338. paralen := paradef.size
  339. else
  340. paralen := tcgsize2size[def_cgsize(paradef)];
  341. loc := getparaloc(paradef);
  342. if (target_info.abi = abi_powerpc_aix) and
  343. (paradef.deftype = recorddef) and
  344. (hp.varspez in [vs_value,vs_const]) then
  345. begin
  346. { if a record has only one field and that field is }
  347. { non-composite (not array or record), it must be }
  348. { passed according to the rules of that type. }
  349. if (trecorddef(hp.vardef).symtable.symindex.count = 1) and
  350. (not trecorddef(hp.vardef).isunion) and
  351. ((tabstractvarsym(trecorddef(hp.vardef).symtable.symindex.search(1)).vardef.deftype = floatdef) or
  352. ((target_info.system = system_powerpc_darwin) and
  353. (tabstractvarsym(trecorddef(hp.vardef).symtable.symindex.search(1)).vardef.deftype in [orddef,enumdef]))) then
  354. begin
  355. paradef :=
  356. tabstractvarsym(trecorddef(hp.vardef).symtable.symindex.search(1)).vardef;
  357. paracgsize:=def_cgsize(paradef);
  358. end
  359. else
  360. begin
  361. paracgsize := int_cgsize(paralen);
  362. end;
  363. end
  364. else
  365. begin
  366. paracgsize:=def_cgsize(paradef);
  367. { for things like formaldef }
  368. if (paracgsize=OS_NO) then
  369. begin
  370. paracgsize:=OS_ADDR;
  371. paralen := tcgsize2size[OS_ADDR];
  372. end;
  373. end
  374. end;
  375. if varargsparas and
  376. (target_info.abi = abi_powerpc_aix) and
  377. (paradef.deftype = floatdef) then
  378. begin
  379. loc := LOC_REGISTER;
  380. if paracgsize = OS_F64 then
  381. paracgsize := OS_64
  382. else
  383. paracgsize := OS_32;
  384. end;
  385. hp.paraloc[side].alignment:=std_param_align;
  386. hp.paraloc[side].size:=paracgsize;
  387. hp.paraloc[side].intsize:=paralen;
  388. if (target_info.abi = abi_powerpc_aix) and
  389. (paradef.deftype in [recorddef,arraydef]) then
  390. hp.paraloc[side].composite:=true;
  391. {$ifndef cpu64bit}
  392. if (target_info.abi=abi_powerpc_sysv) and
  393. is_64bit(paradef) and
  394. odd(nextintreg-RS_R3) then
  395. inc(nextintreg);
  396. {$endif not cpu64bit}
  397. if (paralen = 0) then
  398. if (paradef.deftype = recorddef) then
  399. begin
  400. paraloc:=hp.paraloc[side].add_location;
  401. paraloc^.loc := LOC_VOID;
  402. end
  403. else
  404. internalerror(2005011310);
  405. { can become < 0 for e.g. 3-byte records }
  406. while (paralen > 0) do
  407. begin
  408. paraloc:=hp.paraloc[side].add_location;
  409. if (loc = LOC_REGISTER) and
  410. (nextintreg <= RS_R10) then
  411. begin
  412. paraloc^.loc := loc;
  413. { make sure we don't lose whether or not the type is signed }
  414. if (paradef.deftype <> orddef) then
  415. paracgsize := int_cgsize(paralen);
  416. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  417. paraloc^.size := OS_INT
  418. else
  419. paraloc^.size := paracgsize;
  420. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  421. inc(nextintreg);
  422. dec(paralen,tcgsize2size[paraloc^.size]);
  423. if target_info.abi=abi_powerpc_aix then
  424. inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
  425. end
  426. else if (loc = LOC_FPUREGISTER) and
  427. (nextfloatreg <= maxfpureg) then
  428. begin
  429. paraloc^.loc:=loc;
  430. paraloc^.size := paracgsize;
  431. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  432. inc(nextfloatreg);
  433. dec(paralen,tcgsize2size[paraloc^.size]);
  434. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  435. { are less of those available for parameter passing in the AIX abi }
  436. if target_info.abi=abi_powerpc_aix then
  437. {$ifndef cpu64bit}
  438. if (paracgsize = OS_F32) then
  439. begin
  440. inc(stack_offset,4);
  441. if (nextintreg < RS_R11) then
  442. inc(nextintreg);
  443. end
  444. else
  445. begin
  446. inc(stack_offset,8);
  447. if (nextintreg < RS_R10) then
  448. inc(nextintreg,2)
  449. else
  450. nextintreg := RS_R11;
  451. end;
  452. {$else not cpu64bit}
  453. begin
  454. inc(stack_offset,tcgsize2size[paracgsize]);
  455. if (nextintreg < RS_R11) then
  456. inc(nextintreg);
  457. end;
  458. {$endif not cpu64bit}
  459. end
  460. else { LOC_REFERENCE }
  461. begin
  462. paraloc^.loc:=LOC_REFERENCE;
  463. paraloc^.size:=int_cgsize(paralen);
  464. if (side = callerside) then
  465. paraloc^.reference.index:=NR_STACK_POINTER_REG
  466. else
  467. begin
  468. paraloc^.reference.index:=NR_R12;
  469. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  470. end;
  471. if (target_info.abi = abi_powerpc_aix) and
  472. (hp.paraloc[side].intsize < 3) then
  473. paraloc^.reference.offset:=stack_offset+(4-paralen)
  474. else
  475. paraloc^.reference.offset:=stack_offset;
  476. inc(stack_offset,align(paralen,4));
  477. while (paralen > 0) and
  478. (nextintreg < RS_R11) do
  479. begin
  480. inc(nextintreg);
  481. dec(paralen,sizeof(aint));
  482. end;
  483. paralen := 0;
  484. end;
  485. end;
  486. end;
  487. curintreg:=nextintreg;
  488. curfloatreg:=nextfloatreg;
  489. curmmreg:=nextmmreg;
  490. cur_stack_offset:=stack_offset;
  491. result:=stack_offset;
  492. end;
  493. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  494. var
  495. cur_stack_offset: aword;
  496. parasize, l: longint;
  497. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  498. i : integer;
  499. hp: tparavarsym;
  500. paraloc: pcgparalocation;
  501. begin
  502. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  503. firstfloatreg:=curfloatreg;
  504. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  505. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) then
  506. { just continue loading the parameters in the registers }
  507. begin
  508. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  509. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  510. if (target_info.abi = abi_powerpc_aix) and
  511. (result < 32) then
  512. result := 32;
  513. end
  514. else
  515. begin
  516. parasize:=cur_stack_offset;
  517. for i:=0 to varargspara.count-1 do
  518. begin
  519. hp:=tparavarsym(varargspara[i]);
  520. hp.paraloc[callerside].alignment:=4;
  521. paraloc:=hp.paraloc[callerside].add_location;
  522. paraloc^.loc:=LOC_REFERENCE;
  523. paraloc^.size:=def_cgsize(hp.vardef);
  524. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  525. l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  526. paraloc^.reference.offset:=parasize;
  527. parasize:=parasize+l;
  528. end;
  529. result:=parasize;
  530. end;
  531. if curfloatreg<>firstfloatreg then
  532. include(varargspara.varargsinfo,va_uses_float_reg);
  533. end;
  534. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  535. var
  536. paraloc : pcgparalocation;
  537. paracgsize : tcgsize;
  538. begin
  539. result:=false;
  540. case target_info.system of
  541. system_powerpc_morphos:
  542. begin
  543. paracgsize:=def_cgsize(p.vardef);
  544. p.paraloc[callerside].alignment:=4;
  545. p.paraloc[callerside].size:=paracgsize;
  546. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  547. paraloc:=p.paraloc[callerside].add_location;
  548. paraloc^.loc:=LOC_REFERENCE;
  549. paraloc^.size:=paracgsize;
  550. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  551. { pattern is always uppercase'd }
  552. if s='D0' then
  553. paraloc^.reference.offset:=0
  554. else if s='D1' then
  555. paraloc^.reference.offset:=4
  556. else if s='D2' then
  557. paraloc^.reference.offset:=8
  558. else if s='D3' then
  559. paraloc^.reference.offset:=12
  560. else if s='D4' then
  561. paraloc^.reference.offset:=16
  562. else if s='D5' then
  563. paraloc^.reference.offset:=20
  564. else if s='D6' then
  565. paraloc^.reference.offset:=24
  566. else if s='D7' then
  567. paraloc^.reference.offset:=28
  568. else if s='A0' then
  569. paraloc^.reference.offset:=32
  570. else if s='A1' then
  571. paraloc^.reference.offset:=36
  572. else if s='A2' then
  573. paraloc^.reference.offset:=40
  574. else if s='A3' then
  575. paraloc^.reference.offset:=44
  576. else if s='A4' then
  577. paraloc^.reference.offset:=48
  578. else if s='A5' then
  579. paraloc^.reference.offset:=52
  580. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  581. never passes parameters in it,
  582. Indeed, but this allows to declare libbase either explicitly
  583. or let the compiler insert it }
  584. else if s='A6' then
  585. paraloc^.reference.offset:=56
  586. { 'A7' is the stack pointer on 68k, can't be overwritten
  587. by API calls, so it has no offset }
  588. { 'R12' is special, used internally to support r12base sysv
  589. calling convention }
  590. else if s='R12' then
  591. begin
  592. paraloc^.loc:=LOC_REGISTER;
  593. paraloc^.size:=OS_ADDR;
  594. paraloc^.register:=NR_R12;
  595. end
  596. else
  597. exit;
  598. { copy to callee side }
  599. p.paraloc[calleeside].add_location^:=paraloc^;
  600. end;
  601. else
  602. internalerror(200404182);
  603. end;
  604. result:=true;
  605. end;
  606. {
  607. breaks e.g. tests/test/cg/tpara1
  608. procedure tppcparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
  609. var
  610. paraloc : pcgparalocation;
  611. begin
  612. paraloc:=parasym.paraloc[callerside].location;
  613. { No need for temps when value is pushed }
  614. if assigned(paraloc) and
  615. (paraloc^.loc=LOC_REFERENCE) and
  616. (paraloc^.reference.index=NR_STACK_POINTER_REG) then
  617. duplicateparaloc(list,calloption,parasym,cgpara)
  618. else
  619. inherited createtempparaloc(list,calloption,parasym,cgpara);
  620. end;
  621. }
  622. begin
  623. paramanager:=tppcparamanager.create;
  624. end.