cpupara.pas 24 KB

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