cpupara.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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):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);
  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):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. hp.paraloc[side].alignment:=std_param_align;
  375. hp.paraloc[side].size:=paracgsize;
  376. hp.paraloc[side].intsize:=paralen;
  377. if (target_info.abi = abi_powerpc_aix) and
  378. (paradef.deftype = recorddef) then
  379. hp.paraloc[side].composite:=true;
  380. {$ifndef cpu64bit}
  381. if (target_info.abi=abi_powerpc_sysv) and
  382. is_64bit(paradef) and
  383. odd(nextintreg-RS_R3) then
  384. inc(nextintreg);
  385. {$endif not cpu64bit}
  386. if (paralen = 0) then
  387. if (paradef.deftype = recorddef) then
  388. begin
  389. paraloc:=hp.paraloc[side].add_location;
  390. paraloc^.loc := LOC_VOID;
  391. end
  392. else
  393. internalerror(2005011310);
  394. { can become < 0 for e.g. 3-byte records }
  395. while (paralen > 0) do
  396. begin
  397. paraloc:=hp.paraloc[side].add_location;
  398. if (loc = LOC_REGISTER) and
  399. (nextintreg <= RS_R10) then
  400. begin
  401. paraloc^.loc := loc;
  402. { make sure we don't lose whether or not the type is signed }
  403. if (paradef.deftype <> orddef) then
  404. paracgsize := int_cgsize(paralen);
  405. if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  406. paraloc^.size := OS_INT
  407. else
  408. paraloc^.size := paracgsize;
  409. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
  410. inc(nextintreg);
  411. dec(paralen,tcgsize2size[paraloc^.size]);
  412. if target_info.abi=abi_powerpc_aix then
  413. inc(stack_offset,tcgsize2size[paraloc^.size]);
  414. end
  415. else if (loc = LOC_FPUREGISTER) and
  416. (nextfloatreg <= maxfpureg) then
  417. begin
  418. paraloc^.loc:=loc;
  419. paraloc^.size := paracgsize;
  420. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  421. inc(nextfloatreg);
  422. dec(paralen,tcgsize2size[paraloc^.size]);
  423. { if nextfpureg > maxfpureg, all intregs are already used, since there }
  424. { are less of those available for parameter passing in the AIX abi }
  425. if target_info.abi=abi_powerpc_aix then
  426. {$ifndef cpu64bit}
  427. if (paracgsize = OS_F32) then
  428. begin
  429. inc(stack_offset,4);
  430. if (nextintreg < RS_R11) then
  431. inc(nextintreg);
  432. end
  433. else
  434. begin
  435. inc(stack_offset,8);
  436. if (nextintreg < RS_R10) then
  437. inc(nextintreg,2)
  438. else
  439. nextintreg := RS_R11;
  440. end;
  441. {$else not cpu64bit}
  442. begin
  443. inc(stack_offset,tcgsize2size[paracgsize]);
  444. if (nextintreg < RS_R11) then
  445. inc(nextintreg);
  446. end;
  447. {$endif not cpu64bit}
  448. end
  449. else { LOC_REFERENCE }
  450. begin
  451. paraloc^.loc:=LOC_REFERENCE;
  452. paraloc^.size:=int_cgsize(paralen);
  453. if (side = callerside) then
  454. paraloc^.reference.index:=NR_STACK_POINTER_REG
  455. else
  456. paraloc^.reference.index:=NR_R12;
  457. paraloc^.reference.offset:=stack_offset;
  458. inc(stack_offset,align(paralen,4));
  459. paralen := 0;
  460. end;
  461. end;
  462. end;
  463. curintreg:=nextintreg;
  464. curfloatreg:=nextfloatreg;
  465. curmmreg:=nextmmreg;
  466. cur_stack_offset:=stack_offset;
  467. result:=stack_offset;
  468. end;
  469. function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  470. var
  471. cur_stack_offset: aword;
  472. parasize, l: longint;
  473. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  474. i : integer;
  475. hp: tparavarsym;
  476. paraloc: pcgparalocation;
  477. begin
  478. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
  479. firstfloatreg:=curfloatreg;
  480. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  481. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  482. { just continue loading the parameters in the registers }
  483. begin
  484. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset);
  485. { varargs routines have to reserve at least 32 bytes for the AIX abi }
  486. if (target_info.abi = abi_powerpc_aix) and
  487. (result < 32) then
  488. result := 32;
  489. end
  490. else
  491. begin
  492. parasize:=cur_stack_offset;
  493. for i:=0 to varargspara.count-1 do
  494. begin
  495. hp:=tparavarsym(varargspara[i]);
  496. hp.paraloc[callerside].alignment:=4;
  497. paraloc:=hp.paraloc[callerside].add_location;
  498. paraloc^.loc:=LOC_REFERENCE;
  499. paraloc^.size:=def_cgsize(hp.vartype.def);
  500. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  501. l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
  502. paraloc^.reference.offset:=parasize;
  503. parasize:=parasize+l;
  504. end;
  505. result:=parasize;
  506. end;
  507. if curfloatreg<>firstfloatreg then
  508. include(varargspara.varargsinfo,va_uses_float_reg);
  509. end;
  510. function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  511. var
  512. paraloc : pcgparalocation;
  513. paracgsize : tcgsize;
  514. begin
  515. result:=false;
  516. case target_info.system of
  517. system_powerpc_morphos:
  518. begin
  519. paracgsize:=def_cgsize(p.vartype.def);
  520. p.paraloc[callerside].alignment:=4;
  521. p.paraloc[callerside].size:=paracgsize;
  522. p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
  523. paraloc:=p.paraloc[callerside].add_location;
  524. paraloc^.loc:=LOC_REFERENCE;
  525. paraloc^.size:=paracgsize;
  526. paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
  527. { pattern is always uppercase'd }
  528. if s='D0' then
  529. paraloc^.reference.offset:=0
  530. else if s='D1' then
  531. paraloc^.reference.offset:=4
  532. else if s='D2' then
  533. paraloc^.reference.offset:=8
  534. else if s='D3' then
  535. paraloc^.reference.offset:=12
  536. else if s='D4' then
  537. paraloc^.reference.offset:=16
  538. else if s='D5' then
  539. paraloc^.reference.offset:=20
  540. else if s='D6' then
  541. paraloc^.reference.offset:=24
  542. else if s='D7' then
  543. paraloc^.reference.offset:=28
  544. else if s='A0' then
  545. paraloc^.reference.offset:=32
  546. else if s='A1' then
  547. paraloc^.reference.offset:=36
  548. else if s='A2' then
  549. paraloc^.reference.offset:=40
  550. else if s='A3' then
  551. paraloc^.reference.offset:=44
  552. else if s='A4' then
  553. paraloc^.reference.offset:=48
  554. else if s='A5' then
  555. paraloc^.reference.offset:=52
  556. { 'A6' (offset 56) is used by mossyscall as libbase, so API
  557. never passes parameters in it,
  558. Indeed, but this allows to declare libbase either explicitly
  559. or let the compiler insert it }
  560. else if s='A6' then
  561. paraloc^.reference.offset:=56
  562. { 'A7' is the stack pointer on 68k, can't be overwritten
  563. by API calls, so it has no offset }
  564. { 'R12' is special, used internally to support r12base sysv
  565. calling convention }
  566. else if s='R12' then
  567. begin
  568. paraloc^.loc:=LOC_REGISTER;
  569. paraloc^.size:=OS_ADDR;
  570. paraloc^.register:=NR_R12;
  571. end
  572. else
  573. exit;
  574. { copy to callee side }
  575. p.paraloc[calleeside].add_location^:=paraloc^;
  576. end;
  577. else
  578. internalerror(200404182);
  579. end;
  580. result:=true;
  581. end;
  582. begin
  583. paramanager:=tppcparamanager.create;
  584. end.