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) then
  113. result:=LOC_REFERENCE
  114. else
  115. result:=LOC_REGISTER;
  116. objectdef:
  117. if is_object(p) then
  118. result:=LOC_REFERENCE
  119. else
  120. result:=LOC_REGISTER;
  121. stringdef:
  122. if is_shortstring(p) or is_longstring(p) then
  123. result:=LOC_REFERENCE
  124. else
  125. result:=LOC_REGISTER;
  126. procvardef:
  127. if (po_methodpointer in tprocvardef(p).procoptions) then
  128. result:=LOC_REFERENCE
  129. else
  130. result:=LOC_REGISTER;
  131. filedef:
  132. result:=LOC_REGISTER;
  133. arraydef:
  134. result:=LOC_REFERENCE;
  135. setdef:
  136. if is_smallset(p) then
  137. result:=LOC_REGISTER
  138. else
  139. result:=LOC_REFERENCE;
  140. variantdef:
  141. result:=LOC_REFERENCE;
  142. { avoid problems with errornous definitions }
  143. errordef:
  144. result:=LOC_REGISTER;
  145. else
  146. internalerror(2002071001);
  147. end;
  148. end;
  149. function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  150. begin
  151. result:=false;
  152. { var,out always require address }
  153. if varspez in [vs_var,vs_out] then
  154. begin
  155. result:=true;
  156. exit;
  157. end;
  158. case def.deftype of
  159. variantdef,
  160. formaldef :
  161. result:=true;
  162. recorddef:
  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:=(tsetdef(def).settype<>smallset);
  181. stringdef :
  182. result:=tstringdef(def).string_typ in [st_shortstring,st_longstring];
  183. procvardef :
  184. result:=po_methodpointer in tprocvardef(def).procoptions;
  185. end;
  186. end;
  187. procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
  188. begin
  189. case target_info.abi of
  190. abi_powerpc_aix:
  191. cur_stack_offset:=24;
  192. abi_powerpc_sysv:
  193. cur_stack_offset:=8;
  194. else
  195. internalerror(2003051901);
  196. end;
  197. curintreg:=RS_R3;
  198. curfloatreg:=RS_F1;
  199. curmmreg:=RS_M1;
  200. end;
  201. procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
  202. var
  203. retcgsize : tcgsize;
  204. begin
  205. { Constructors return self instead of a boolean }
  206. if (p.proctypeoption=potype_constructor) then
  207. retcgsize:=OS_ADDR
  208. else
  209. retcgsize:=def_cgsize(p.rettype.def);
  210. location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
  211. p.funcretloc[side].size:=retcgsize;
  212. { void has no location }
  213. if is_void(p.rettype.def) then
  214. begin
  215. p.funcretloc[side].loc:=LOC_VOID;
  216. exit;
  217. end;
  218. { Return in FPU register? }
  219. if p.rettype.def.deftype=floatdef then
  220. begin
  221. p.funcretloc[side].loc:=LOC_FPUREGISTER;
  222. p.funcretloc[side].register:=NR_FPU_RESULT_REG;
  223. p.funcretloc[side].size:=retcgsize;
  224. end
  225. else
  226. { Return in register? }
  227. if not ret_in_param(p.rettype.def,p.proccalloption) then
  228. begin
  229. {$ifndef cpu64bit}
  230. if retcgsize in [OS_64,OS_S64] then
  231. begin
  232. { low 32bits }
  233. p.funcretloc[side].loc:=LOC_REGISTER;
  234. if side=callerside then
  235. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
  236. else
  237. p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  238. { high 32bits }
  239. if side=callerside then
  240. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
  241. else
  242. p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  243. end
  244. else
  245. {$endif cpu64bit}
  246. begin
  247. p.funcretloc[side].loc:=LOC_REGISTER;
  248. p.funcretloc[side].size:=retcgsize;
  249. if side=callerside then
  250. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize))
  251. else
  252. p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize));
  253. end;
  254. end
  255. else
  256. begin
  257. p.funcretloc[side].loc:=LOC_REFERENCE;
  258. p.funcretloc[side].size:=retcgsize;
  259. end;
  260. end;
  261. function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  262. var
  263. cur_stack_offset: aword;
  264. curintreg, curfloatreg, curmmreg: tsuperregister;
  265. begin
  266. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  267. result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
  268. create_funcretloc_info(p,side);
  269. end;
  270. function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
  271. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
  272. var
  273. stack_offset: longint;
  274. paralen: aint;
  275. nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
  276. paradef : tdef;
  277. paraloc : pcgparalocation;
  278. i : integer;
  279. hp : tparavarsym;
  280. loc : tcgloc;
  281. paracgsize: tcgsize;
  282. begin
  283. {$ifdef extdebug}
  284. if po_explicitparaloc in p.procoptions then
  285. internalerror(200411141);
  286. {$endif extdebug}
  287. result:=0;
  288. nextintreg := curintreg;
  289. nextfloatreg := curfloatreg;
  290. nextmmreg := curmmreg;
  291. stack_offset := cur_stack_offset;
  292. case target_info.abi of
  293. abi_powerpc_aix:
  294. maxfpureg := RS_F13;
  295. abi_powerpc_sysv:
  296. maxfpureg := RS_F8;
  297. else internalerror(2004070912);
  298. end;
  299. for i:=0 to paras.count-1 do
  300. begin
  301. hp:=tparavarsym(paras[i]);
  302. paradef := hp.vartype.def;
  303. { Syscall for Morphos can have already a paraloc set }
  304. if (vo_has_explicit_paraloc in hp.varoptions) then
  305. begin
  306. if not(vo_is_syscall_lib in hp.varoptions) then
  307. internalerror(200412153);
  308. continue;
  309. end;
  310. hp.paraloc[side].reset;
  311. { currently only support C-style array of const }
  312. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  313. is_array_of_const(paradef) then
  314. begin
  315. paraloc:=hp.paraloc[side].add_location;
  316. { hack: the paraloc must be valid, but is not actually used }
  317. paraloc^.loc := LOC_REGISTER;
  318. paraloc^.register := NR_R0;
  319. paraloc^.size := OS_ADDR;
  320. break;
  321. end;
  322. if (hp.varspez in [vs_var,vs_out]) or
  323. push_addr_param(hp.varspez,paradef,p.proccalloption) or
  324. is_open_array(paradef) or
  325. is_array_of_const(paradef) then
  326. begin
  327. paradef:=voidpointertype.def;
  328. loc:=LOC_REGISTER;
  329. paracgsize := OS_ADDR;
  330. paralen := tcgsize2size[OS_ADDR];
  331. end
  332. else
  333. begin
  334. if not is_special_array(paradef) then
  335. paralen := paradef.size
  336. else
  337. paralen := tcgsize2size[def_cgsize(paradef)];
  338. if (target_info.abi = abi_powerpc_aix) and
  339. (paradef.deftype = 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.vartype.def).symtable.symindex.count = 1) and
  346. (not trecorddef(hp.vartype.def).isunion) and
  347. ((tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype = floatdef) or
  348. ((target_info.system = system_powerpc_darwin) and
  349. (tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def.deftype in [orddef,enumdef]))) then
  350. begin
  351. paradef :=
  352. tabstractvarsym(trecorddef(hp.vartype.def).symtable.symindex.search(1)).vartype.def;
  353. loc := getparaloc(paradef);
  354. paracgsize:=def_cgsize(paradef);
  355. end
  356. else
  357. begin
  358. loc := LOC_REGISTER;
  359. paracgsize := int_cgsize(paralen);
  360. end;
  361. end
  362. else
  363. begin
  364. loc:=getparaloc(paradef);
  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.