cpupara.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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_R0,RS_R2..RS_R12]
  51. else
  52. result := [RS_R0,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_ADDR;
  70. cgpara.intsize:=sizeof(pint);
  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(pint)*(nr-8)
  89. else
  90. reference.offset:=sizeof(pint)*(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.typ 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. procvardef,
  113. recorddef:
  114. if (target_info.abi<>abi_powerpc_aix) or
  115. ((p.size >= 3) and
  116. ((p.size mod 4) <> 0)) then
  117. result:=LOC_REFERENCE
  118. else
  119. result:=LOC_REGISTER;
  120. objectdef:
  121. if is_object(p) then
  122. result:=LOC_REFERENCE
  123. else
  124. result:=LOC_REGISTER;
  125. stringdef:
  126. if is_shortstring(p) or is_longstring(p) then
  127. result:=LOC_REFERENCE
  128. else
  129. result:=LOC_REGISTER;
  130. filedef:
  131. result:=LOC_REGISTER;
  132. arraydef:
  133. result:=LOC_REFERENCE;
  134. setdef:
  135. if is_smallset(p) then
  136. result:=LOC_REGISTER
  137. else
  138. result:=LOC_REFERENCE;
  139. variantdef:
  140. result:=LOC_REFERENCE;
  141. { avoid problems with errornous definitions }
  142. errordef:
  143. result:=LOC_REGISTER;
  144. else
  145. internalerror(2002071001);
  146. end;
  147. end;
  148. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  149. begin
  150. result:=false;
  151. { var,out always require address }
  152. if varspez in [vs_var,vs_out] then
  153. begin
  154. result:=true;
  155. exit;
  156. end;
  157. case def.typ of
  158. variantdef,
  159. formaldef :
  160. result:=true;
  161. recorddef,
  162. procvardef :
  163. result :=
  164. (target_info.abi<>abi_powerpc_aix) or
  165. ((varspez = vs_const) and
  166. ((calloption = pocall_mwpascal) or
  167. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  168. (def.size > 8)
  169. )
  170. )
  171. );
  172. arraydef:
  173. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  174. is_open_array(def) or
  175. is_array_of_const(def) or
  176. is_array_constructor(def);
  177. objectdef :
  178. result:=is_object(def);
  179. setdef :
  180. result:=not is_smallset(def);
  181. stringdef :
  182. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  183. end;
  184. end;
  185. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  186. begin
  187. case target_info.abi of
  188. abi_powerpc_aix:
  189. cur_stack_offset:=24;
  190. abi_powerpc_sysv:
  191. cur_stack_offset:=8;
  192. else
  193. internalerror(2003051901);
  194. end;
  195. curintreg:=RS_R3;
  196. curfloatreg:=RS_F1;
  197. curmmreg:=RS_M1;
  198. end;
  199. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  200. var
  201. retcgsize : tcgsize;
  202. begin
  203. { Constructors return self instead of a boolean }
  204. if (p.proctypeoption=potype_constructor) then
  205. retcgsize:=OS_ADDR
  206. else
  207. retcgsize:=def_cgsize(p.returndef);
  208. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  209. p.funcretloc[side].size:=retcgsize;
  210. { void has no location }
  211. if is_void(p.returndef) then
  212. begin
  213. p.funcretloc[side].loc:=LOC_VOID;
  214. exit;
  215. end;
  216. { Return is passed as var parameter }
  217. if ret_in_param(p.returndef,p.proccalloption) then
  218. begin
  219. p.funcretloc[side].loc:=LOC_REFERENCE;
  220. p.funcretloc[side].size:=retcgsize;
  221. exit;
  222. end;
  223. { Return in FPU register? }
  224. if p.returndef.typ=floatdef then
  225. begin
  226. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  227. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  228. p.funcretloc[side].size:=retcgsize;
  229. end
  230. else
  231. { Return in register }
  232. begin
  233. {$ifndef cpu64bitaddr}
  234. if retcgsize in [OS_64,OS_S64] then
  235. begin
  236. { low 32bits }
  237. p.funcretloc[side].loc:=LOC_REGISTER;
  238. if side=callerside then
  239. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  240. else
  241. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  242. { high 32bits }
  243. if side=callerside then
  244. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  245. else
  246. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  247. end
  248. else
  249. {$endif cpu64bitaddr}
  250. begin
  251. p.funcretloc[side].loc:=LOC_REGISTER;
  252. p.funcretloc[side].size:=retcgsize;
  253. if side=callerside then
  254. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  255. else
  256. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  257. end;
  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,false);
  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; varargsparas: boolean):longint;
  271. var
  272. stack_offset: longint;
  273. paralen: aint;
  274. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  275. paradef : tdef;
  276. paraloc : pcgparalocation;
  277. i : integer;
  278. hp : tparavarsym;
  279. loc : tcgloc;
  280. paracgsize: tcgsize;
  281. begin
  282. {$ifdef extdebug}
  283. if po_explicitparaloc in p.procoptions then
  284. internalerror(200411141);
  285. {$endif extdebug}
  286. result:=0;
  287. nextintreg := curintreg;
  288. nextfloatreg := curfloatreg;
  289. nextmmreg := curmmreg;
  290. stack_offset := cur_stack_offset;
  291. case target_info.abi of
  292. abi_powerpc_aix:
  293. maxfpureg := RS_F13;
  294. abi_powerpc_sysv:
  295. maxfpureg := RS_F8;
  296. else internalerror(2004070912);
  297. end;
  298. for i:=0 to paras.count-1 do
  299. begin
  300. hp:=tparavarsym(paras[i]);
  301. paradef := hp.vardef;
  302. { Syscall for Morphos can have already a paraloc set }
  303. if (vo_has_explicit_paraloc in hp.varoptions) then
  304. begin
  305. if not(vo_is_syscall_lib in hp.varoptions) then
  306. internalerror(200412153);
  307. continue;
  308. end;
  309. hp.paraloc[side].reset;
  310. { currently only support C-style array of const }
  311. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) and
  312. is_array_of_const(paradef) then
  313. begin
  314. paraloc:=hp.paraloc[side].add_location;
  315. { hack: the paraloc must be valid, but is not actually used }
  316. paraloc^.loc := LOC_REGISTER;
  317. paraloc^.register := NR_R0;
  318. paraloc^.size := OS_ADDR;
  319. break;
  320. end;
  321. if (hp.varspez in [vs_var,vs_out]) or
  322. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  323. is_open_array(paradef) or
  324. is_array_of_const(paradef) then
  325. begin
  326. paradef:=voidpointertype;
  327. loc:=LOC_REGISTER;
  328. paracgsize := OS_ADDR;
  329. paralen := tcgsize2size[OS_ADDR];
  330. end
  331. else
  332. begin
  333. if not is_special_array(paradef) then
  334. paralen := paradef.size
  335. else
  336. paralen := tcgsize2size[def_cgsize(paradef)];
  337. loc := getparaloc(paradef);
  338. if (target_info.abi = abi_powerpc_aix) and
  339. (paradef.typ = recorddef) and
  340. (hp.varspez in [vs_value,vs_const]) then
  341. begin
  342. { if a record has only one field and that field is }
  343. { non-composite (not array or record), it must be }
  344. { passed according to the rules of that type. }
  345. if (trecorddef(hp.vardef).symtable.SymList.count = 1) and
  346. (not trecorddef(hp.vardef).isunion) and
  347. ((tabstractvarsym(trecorddef(hp.vardef).symtable.SymList[0]).vardef.typ = floatdef) or
  348. ((target_info.system = system_powerpc_darwin) and
  349. (tabstractvarsym(trecorddef(hp.vardef).symtable.SymList[0]).vardef.typ in [orddef,enumdef]))) then
  350. begin
  351. paradef :=
  352. tabstractvarsym(trecorddef(hp.vardef).symtable.SymList[0]).vardef;
  353. paracgsize:=def_cgsize(paradef);
  354. end
  355. else
  356. begin
  357. paracgsize := int_cgsize(paralen);
  358. end;
  359. end
  360. else
  361. begin
  362. paracgsize:=def_cgsize(paradef);
  363. { for things like formaldef }
  364. if (paracgsize=OS_NO) then
  365. begin
  366. paracgsize:=OS_ADDR;
  367. paralen := tcgsize2size[OS_ADDR];
  368. end;
  369. end
  370. end;
  371. if varargsparas and
  372. (target_info.abi = abi_powerpc_aix) and
  373. (paradef.typ = floatdef) then
  374. begin
  375. loc := LOC_REGISTER;
  376. if paracgsize = OS_F64 then
  377. paracgsize := OS_64
  378. else
  379. paracgsize := OS_32;
  380. end;
  381. hp.paraloc[side].alignment:=std_param_align;
  382. hp.paraloc[side].size:=paracgsize;
  383. hp.paraloc[side].intsize:=paralen;
  384. if (target_info.abi = abi_powerpc_aix) and
  385. (paradef.typ in [recorddef,arraydef]) then
  386. hp.paraloc[side].composite:=true;
  387. {$ifndef cpu64bitaddr}
  388. if (target_info.abi=abi_powerpc_sysv) and
  389. is_64bit(paradef) and
  390. odd(nextintreg-RS_R3) then
  391. inc(nextintreg);
  392. {$endif not cpu64bitaddr}
  393. if (paralen = 0) then
  394. if (paradef.typ = recorddef) then
  395. begin
  396. paraloc:=hp.paraloc[side].add_location;
  397. paraloc^.loc := LOC_VOID;
  398. end
  399. else
  400. internalerror(2005011310);
  401. { can become < 0 for e.g. 3-byte records }
  402. while (paralen > 0) do
  403. begin
  404. paraloc:=hp.paraloc[side].add_location;
  405. if (loc = LOC_REGISTER) and
  406. (nextintreg <= RS_R10) then
  407. begin
  408. paraloc^.loc := loc;
  409. { make sure we don't lose whether or not the type is signed }
  410. if (paradef.typ <> orddef) then
  411. paracgsize := int_cgsize(paralen);
  412. if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
  413. paraloc^.size := OS_INT
  414. else
  415. paraloc^.size := paracgsize;
  416. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  417. inc(nextintreg);
  418. dec(paralen,tcgsize2size[paraloc^.size]);
  419. if target_info.abi=abi_powerpc_aix then
  420. inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
  421. end
  422. else if (loc = LOC_FPUREGISTER) and
  423. (nextfloatreg <= maxfpureg) then
  424. begin
  425. paraloc^.loc:=loc;
  426. paraloc^.size := paracgsize;
  427. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  428. inc(nextfloatreg);
  429. dec(paralen,tcgsize2size[paraloc^.size]);
  430. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  431. { are less of those available for parameter passing in the AIX abi }
  432. if target_info.abi=abi_powerpc_aix then
  433. {$ifndef cpu64bitaddr}
  434. if (paracgsize = OS_F32) then
  435. begin
  436. inc(stack_offset,4);
  437. if (nextintreg < RS_R11) then
  438. inc(nextintreg);
  439. end
  440. else
  441. begin
  442. inc(stack_offset,8);
  443. if (nextintreg < RS_R10) then
  444. inc(nextintreg,2)
  445. else
  446. nextintreg := RS_R11;
  447. end;
  448. {$else not cpu64bitaddr}
  449. begin
  450. inc(stack_offset,tcgsize2size[paracgsize]);
  451. if (nextintreg < RS_R11) then
  452. inc(nextintreg);
  453. end;
  454. {$endif not cpu64bitaddr}
  455. end
  456. else { LOC_REFERENCE }
  457. begin
  458. paraloc^.loc:=LOC_REFERENCE;
  459. case loc of
  460. LOC_FPUREGISTER:
  461. paraloc^.size:=int_float_cgsize(paralen);
  462. LOC_REGISTER,
  463. LOC_REFERENCE:
  464. paraloc^.size:=int_cgsize(paralen);
  465. else
  466. internalerror(2006011101);
  467. end;
  468. if (side = callerside) then
  469. paraloc^.reference.index:=NR_STACK_POINTER_REG
  470. else
  471. begin
  472. paraloc^.reference.index:=NR_R12;
  473. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  474. end;
  475. if (target_info.abi = abi_powerpc_aix) and
  476. (hp.paraloc[side].intsize < 3) then
  477. paraloc^.reference.offset:=stack_offset+(4-paralen)
  478. else
  479. paraloc^.reference.offset:=stack_offset;
  480. inc(stack_offset,align(paralen,4));
  481. while (paralen > 0) and
  482. (nextintreg < RS_R11) do
  483. begin
  484. inc(nextintreg);
  485. dec(paralen,sizeof(pint));
  486. end;
  487. paralen := 0;
  488. end;
  489. end;
  490. end;
  491. curintreg:=nextintreg;
  492. curfloatreg:=nextfloatreg;
  493. curmmreg:=nextmmreg;
  494. cur_stack_offset:=stack_offset;
  495. result:=stack_offset;
  496. end;
  497. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  498. var
  499. cur_stack_offset: aword;
  500. parasize, l: longint;
  501. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  502. i : integer;
  503. hp: tparavarsym;
  504. paraloc: pcgparalocation;
  505. begin
  506. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  507. firstfloatreg:=curfloatreg;
  508. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  509. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) then
  510. { just continue loading the parameters in the registers }
  511. begin
  512. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  513. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  514. if (target_info.abi = abi_powerpc_aix) and
  515. (result < 32) then
  516. result := 32;
  517. end
  518. else
  519. begin
  520. parasize:=cur_stack_offset;
  521. for i:=0 to varargspara.count-1 do
  522. begin
  523. hp:=tparavarsym(varargspara[i]);
  524. hp.paraloc[callerside].alignment:=4;
  525. paraloc:=hp.paraloc[callerside].add_location;
  526. paraloc^.loc:=LOC_REFERENCE;
  527. paraloc^.size:=def_cgsize(hp.vardef);
  528. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  529. l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  530. paraloc^.reference.offset:=parasize;
  531. parasize:=parasize+l;
  532. end;
  533. result:=parasize;
  534. end;
  535. if curfloatreg<>firstfloatreg then
  536. include(varargspara.varargsinfo,va_uses_float_reg);
  537. end;
  538. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  539. var
  540. paraloc : pcgparalocation;
  541. paracgsize : tcgsize;
  542. begin
  543. result:=false;
  544. case target_info.system of
  545. system_powerpc_morphos:
  546. begin
  547. paracgsize:=def_cgsize(p.vardef);
  548. p.paraloc[callerside].alignment:=4;
  549. p.paraloc[callerside].size:=paracgsize;
  550. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  551. paraloc:=p.paraloc[callerside].add_location;
  552. paraloc^.loc:=LOC_REFERENCE;
  553. paraloc^.size:=paracgsize;
  554. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  555. { pattern is always uppercase'd }
  556. if s='D0' then
  557. paraloc^.reference.offset:=0
  558. else if s='D1' then
  559. paraloc^.reference.offset:=4
  560. else if s='D2' then
  561. paraloc^.reference.offset:=8
  562. else if s='D3' then
  563. paraloc^.reference.offset:=12
  564. else if s='D4' then
  565. paraloc^.reference.offset:=16
  566. else if s='D5' then
  567. paraloc^.reference.offset:=20
  568. else if s='D6' then
  569. paraloc^.reference.offset:=24
  570. else if s='D7' then
  571. paraloc^.reference.offset:=28
  572. else if s='A0' then
  573. paraloc^.reference.offset:=32
  574. else if s='A1' then
  575. paraloc^.reference.offset:=36
  576. else if s='A2' then
  577. paraloc^.reference.offset:=40
  578. else if s='A3' then
  579. paraloc^.reference.offset:=44
  580. else if s='A4' then
  581. paraloc^.reference.offset:=48
  582. else if s='A5' then
  583. paraloc^.reference.offset:=52
  584. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  585. never passes parameters in it,
  586. Indeed, but this allows to declare libbase either explicitly
  587. or let the compiler insert it }
  588. else if s='A6' then
  589. paraloc^.reference.offset:=56
  590. { 'A7' is the stack pointer on 68k, can't be overwritten
  591. by API calls, so it has no offset }
  592. { 'R12' is special, used internally to support r12base sysv
  593. calling convention }
  594. else if s='R12' then
  595. begin
  596. paraloc^.loc:=LOC_REGISTER;
  597. paraloc^.size:=OS_ADDR;
  598. paraloc^.register:=NR_R12;
  599. end
  600. else
  601. exit;
  602. { copy to callee side }
  603. p.paraloc[calleeside].add_location^:=paraloc^;
  604. end;
  605. else
  606. internalerror(200404182);
  607. end;
  608. result:=true;
  609. end;
  610. {
  611. breaks e.g. tests/test/cg/tpara1
  612. procedure tppcparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
  613. var
  614. paraloc : pcgparalocation;
  615. begin
  616. paraloc:=parasym.paraloc[callerside].location;
  617. { No need for temps when value is pushed }
  618. if assigned(paraloc) and
  619. (paraloc^.loc=LOC_REFERENCE) and
  620. (paraloc^.reference.index=NR_STACK_POINTER_REG) then
  621. duplicateparaloc(list,calloption,parasym,cgpara)
  622. else
  623. inherited createtempparaloc(list,calloption,parasym,cgpara);
  624. end;
  625. }
  626. begin
  627. paramanager:=tppcparamanager.create;
  628. end.