cpupara.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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,
  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. procedure createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
  36. private
  37. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  38. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  39. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  40. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  41. end;
  42. implementation
  43. uses
  44. verbose,systems,
  45. defutil,
  46. cgutils,
  47. procinfo,cpupi;
  48. function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  49. begin
  50. if (target_info.system = system_powerpc_darwin) then
  51. result := [RS_R2..RS_R12]
  52. else
  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. abi_powerpc_sysv:
  60. result := [RS_F0..RS_F13];
  61. else
  62. internalerror(2003091401);
  63. end;
  64. end;
  65. procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
  66. var
  67. paraloc : pcgparalocation;
  68. begin
  69. cgpara.reset;
  70. cgpara.size:=OS_INT;
  71. cgpara.intsize:=tcgsize2size[OS_INT];
  72. cgpara.alignment:=get_para_align(calloption);
  73. paraloc:=cgpara.add_location;
  74. with paraloc^ do
  75. begin
  76. size:=OS_INT;
  77. if (nr<=8) then
  78. begin
  79. if nr=0 then
  80. internalerror(200309271);
  81. loc:=LOC_REGISTER;
  82. register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
  83. end
  84. else
  85. begin
  86. loc:=LOC_REFERENCE;
  87. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  88. if (target_info.abi <> abi_powerpc_aix) then
  89. reference.offset:=sizeof(aint)*(nr-8)
  90. else
  91. reference.offset:=sizeof(aint)*(nr);
  92. end;
  93. end;
  94. end;
  95. function getparaloc(p : tdef) : tcgloc;
  96. begin
  97. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  98. if push_addr_param for the def is true
  99. }
  100. case p.deftype of
  101. orddef:
  102. result:=LOC_REGISTER;
  103. floatdef:
  104. result:=LOC_FPUREGISTER;
  105. enumdef:
  106. result:=LOC_REGISTER;
  107. pointerdef:
  108. result:=LOC_REGISTER;
  109. formaldef:
  110. result:=LOC_REGISTER;
  111. classrefdef:
  112. result:=LOC_REGISTER;
  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. procvardef:
  131. if (po_methodpointer in tprocvardef(p).procoptions) then
  132. result:=LOC_REFERENCE
  133. else
  134. result:=LOC_REGISTER;
  135. filedef:
  136. result:=LOC_REGISTER;
  137. arraydef:
  138. result:=LOC_REFERENCE;
  139. setdef:
  140. if is_smallset(p) then
  141. result:=LOC_REGISTER
  142. else
  143. result:=LOC_REFERENCE;
  144. variantdef:
  145. result:=LOC_REFERENCE;
  146. { avoid problems with errornous definitions }
  147. errordef:
  148. result:=LOC_REGISTER;
  149. else
  150. internalerror(2002071001);
  151. end;
  152. end;
  153. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  154. begin
  155. result:=false;
  156. { var,out always require address }
  157. if varspez in [vs_var,vs_out] then
  158. begin
  159. result:=true;
  160. exit;
  161. end;
  162. case def.deftype of
  163. variantdef,
  164. formaldef :
  165. result:=true;
  166. recorddef:
  167. result :=
  168. (target_info.abi<>abi_powerpc_aix) or
  169. ((varspez = vs_const) and
  170. ((calloption = pocall_mwpascal) or
  171. (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
  172. (def.size > 8)
  173. )
  174. )
  175. );
  176. arraydef:
  177. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  178. is_open_array(def) or
  179. is_array_of_const(def) or
  180. is_array_constructor(def);
  181. objectdef :
  182. result:=is_object(def);
  183. setdef :
  184. result:=(tsetdef(def).settype<>smallset);
  185. stringdef :
  186. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  187. procvardef :
  188. result:=po_methodpointer in tprocvardef(def).procoptions;
  189. end;
  190. end;
  191. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  192. begin
  193. case target_info.abi of
  194. abi_powerpc_aix:
  195. cur_stack_offset:=24;
  196. abi_powerpc_sysv:
  197. cur_stack_offset:=8;
  198. else
  199. internalerror(2003051901);
  200. end;
  201. curintreg:=RS_R3;
  202. curfloatreg:=RS_F1;
  203. curmmreg:=RS_M1;
  204. end;
  205. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  206. var
  207. retcgsize : tcgsize;
  208. begin
  209. { Constructors return self instead of a boolean }
  210. if (p.proctypeoption=potype_constructor) then
  211. retcgsize:=OS_ADDR
  212. else
  213. retcgsize:=def_cgsize(p.rettype.def);
  214. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  215. p.funcretloc[side].size:=retcgsize;
  216. { void has no location }
  217. if is_void(p.rettype.def) then
  218. begin
  219. p.funcretloc[side].loc:=LOC_VOID;
  220. exit;
  221. end;
  222. { Return in FPU register? }
  223. if p.rettype.def.deftype=floatdef then
  224. begin
  225. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  226. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  227. p.funcretloc[side].size:=retcgsize;
  228. end
  229. else
  230. { Return in register? }
  231. if not ret_in_param(p.rettype.def,p.proccalloption) then
  232. begin
  233. {$ifndef cpu64bit}
  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 cpu64bit}
  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. else
  260. begin
  261. p.funcretloc[side].loc:=LOC_REFERENCE;
  262. p.funcretloc[side].size:=retcgsize;
  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.vartype.def;
  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]) 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.def;
  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.deftype = 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.vartype.def).symtable.symindex.count = 1) and
  351. (not trecorddef(hp.vartype.def).isunion) and
  352. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  353. ((target_info.system = system_powerpc_darwin) and
  354. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  355. begin
  356. paradef :=
  357. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  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.deftype = 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.deftype = recorddef) 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.deftype = 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.deftype <> 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,tcgsize2size[paraloc^.size]);
  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. paraloc^.size:=int_cgsize(paralen);
  465. if (side = callerside) then
  466. paraloc^.reference.index:=NR_STACK_POINTER_REG
  467. else
  468. begin
  469. paraloc^.reference.index:=NR_R12;
  470. tppcprocinfo(current_procinfo).needs_frame_pointer := true;
  471. end;
  472. paraloc^.reference.offset:=stack_offset;
  473. inc(stack_offset,align(paralen,4));
  474. paralen := 0;
  475. end;
  476. end;
  477. end;
  478. curintreg:=nextintreg;
  479. curfloatreg:=nextfloatreg;
  480. curmmreg:=nextmmreg;
  481. cur_stack_offset:=stack_offset;
  482. result:=stack_offset;
  483. end;
  484. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  485. var
  486. cur_stack_offset: aword;
  487. parasize, l: longint;
  488. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  489. i : integer;
  490. hp: tparavarsym;
  491. paraloc: pcgparalocation;
  492. begin
  493. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  494. firstfloatreg:=curfloatreg;
  495. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
  496. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  497. { just continue loading the parameters in the registers }
  498. begin
  499. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
  500. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  501. if (target_info.abi = abi_powerpc_aix) and
  502. (result < 32) then
  503. result := 32;
  504. end
  505. else
  506. begin
  507. parasize:=cur_stack_offset;
  508. for i:=0 to varargspara.count-1 do
  509. begin
  510. hp:=tparavarsym(varargspara[i]);
  511. hp.paraloc[callerside].alignment:=4;
  512. paraloc:=hp.paraloc[callerside].add_location;
  513. paraloc^.loc:=LOC_REFERENCE;
  514. paraloc^.size:=def_cgsize(hp.vartype.def);
  515. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  516. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  517. paraloc^.reference.offset:=parasize;
  518. parasize:=parasize+l;
  519. end;
  520. result:=parasize;
  521. end;
  522. if curfloatreg<>firstfloatreg then
  523. include(varargspara.varargsinfo,va_uses_float_reg);
  524. end;
  525. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  526. var
  527. paraloc : pcgparalocation;
  528. paracgsize : tcgsize;
  529. begin
  530. result:=false;
  531. case target_info.system of
  532. system_powerpc_morphos:
  533. begin
  534. paracgsize:=def_cgsize(p.vartype.def);
  535. p.paraloc[callerside].alignment:=4;
  536. p.paraloc[callerside].size:=paracgsize;
  537. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  538. paraloc:=p.paraloc[callerside].add_location;
  539. paraloc^.loc:=LOC_REFERENCE;
  540. paraloc^.size:=paracgsize;
  541. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  542. { pattern is always uppercase'd }
  543. if s='D0' then
  544. paraloc^.reference.offset:=0
  545. else if s='D1' then
  546. paraloc^.reference.offset:=4
  547. else if s='D2' then
  548. paraloc^.reference.offset:=8
  549. else if s='D3' then
  550. paraloc^.reference.offset:=12
  551. else if s='D4' then
  552. paraloc^.reference.offset:=16
  553. else if s='D5' then
  554. paraloc^.reference.offset:=20
  555. else if s='D6' then
  556. paraloc^.reference.offset:=24
  557. else if s='D7' then
  558. paraloc^.reference.offset:=28
  559. else if s='A0' then
  560. paraloc^.reference.offset:=32
  561. else if s='A1' then
  562. paraloc^.reference.offset:=36
  563. else if s='A2' then
  564. paraloc^.reference.offset:=40
  565. else if s='A3' then
  566. paraloc^.reference.offset:=44
  567. else if s='A4' then
  568. paraloc^.reference.offset:=48
  569. else if s='A5' then
  570. paraloc^.reference.offset:=52
  571. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  572. never passes parameters in it,
  573. Indeed, but this allows to declare libbase either explicitly
  574. or let the compiler insert it }
  575. else if s='A6' then
  576. paraloc^.reference.offset:=56
  577. { 'A7' is the stack pointer on 68k, can't be overwritten
  578. by API calls, so it has no offset }
  579. { 'R12' is special, used internally to support r12base sysv
  580. calling convention }
  581. else if s='R12' then
  582. begin
  583. paraloc^.loc:=LOC_REGISTER;
  584. paraloc^.size:=OS_ADDR;
  585. paraloc^.register:=NR_R12;
  586. end
  587. else
  588. exit;
  589. { copy to callee side }
  590. p.paraloc[calleeside].add_location^:=paraloc^;
  591. end;
  592. else
  593. internalerror(200404182);
  594. end;
  595. result:=true;
  596. end;
  597. procedure tppcparamanager.createtempparaloc(list: taasmoutput;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
  598. var
  599. paraloc : pcgparalocation;
  600. begin
  601. paraloc:=parasym.paraloc[callerside].location;
  602. { No need for temps when value is pushed }
  603. if assigned(paraloc) and
  604. (paraloc^.loc=LOC_REFERENCE) and
  605. (paraloc^.reference.index=NR_STACK_POINTER_REG) then
  606. duplicateparaloc(list,calloption,parasym,cgpara)
  607. else
  608. inherited createtempparaloc(list,calloption,parasym,cgpara);
  609. end;
  610. begin
  611. paramanager:=tppcparamanager.create;
  612. end.