cpupara.pas 24 KB

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