cpupara.pas 26 KB

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