2
0

cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. {
  2. Copyright (c) 2003-2012 by Florian Klaempfl and others
  3. AArch64 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. { AArch64 specific calling conventions are handled by this unit
  18. }
  19. unit cpupara;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. globtype,globals,
  24. aasmtai,aasmdata,
  25. cpuinfo,cpubase,cgbase,cgutils,
  26. symconst,symbase,symtype,symdef,parabase,paramgr;
  27. type
  28. taarch64paramanager = class(tparamanager)
  29. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  30. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  31. function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
  32. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  33. function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
  34. procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
  35. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  36. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  37. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
  38. private
  39. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
  40. function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  41. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
  42. end;
  43. implementation
  44. uses
  45. verbose,systems,cutils,
  46. rgobj,
  47. defutil,symsym,symtable;
  48. function taarch64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  49. begin
  50. result:=VOLATILE_INTREGISTERS
  51. end;
  52. function taarch64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  53. begin
  54. result:=[];
  55. end;
  56. function taarch64paramanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
  57. begin
  58. result:=VOLATILE_MMREGISTERS;
  59. end;
  60. procedure taarch64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
  61. var
  62. paraloc : pcgparalocation;
  63. def : tdef;
  64. begin
  65. if nr<1 then
  66. internalerror(2002070801);
  67. def:=tparavarsym(pd.paras[nr-1]).vardef;
  68. cgpara.reset;
  69. cgpara.size:=def_cgsize(def);
  70. cgpara.intsize:=tcgsize2size[cgpara.size];
  71. cgpara.alignment:=std_param_align;
  72. cgpara.def:=def;
  73. paraloc:=cgpara.add_location;
  74. with paraloc^ do
  75. begin
  76. size:=OS_INT;
  77. { the four first parameters are passed into registers }
  78. if nr<=8 then
  79. begin
  80. loc:=LOC_REGISTER;
  81. register:=newreg(R_INTREGISTER,RS_X0+nr-1,R_SUBWHOLE);
  82. end
  83. else
  84. begin
  85. { the other parameters are passed on the stack }
  86. loc:=LOC_REFERENCE;
  87. reference.index:=NR_STACK_POINTER_REG;
  88. reference.offset:=(nr-9)*8;
  89. end;
  90. end;
  91. end;
  92. function Is_HFA(p : tdef) : boolean;
  93. begin
  94. result:=false;
  95. end;
  96. function getparaloc(calloption : tproccalloption; p : tdef; isvariadic: boolean) : tcgloc;
  97. begin
  98. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  99. if push_addr_param for the def is true
  100. }
  101. case p.typ of
  102. orddef:
  103. getparaloc:=LOC_REGISTER;
  104. floatdef:
  105. getparaloc:=LOC_MMREGISTER;
  106. enumdef:
  107. getparaloc:=LOC_REGISTER;
  108. pointerdef:
  109. getparaloc:=LOC_REGISTER;
  110. formaldef:
  111. getparaloc:=LOC_REGISTER;
  112. classrefdef:
  113. getparaloc:=LOC_REGISTER;
  114. recorddef:
  115. getparaloc:=LOC_REGISTER;
  116. objectdef:
  117. getparaloc:=LOC_REGISTER;
  118. stringdef:
  119. if is_shortstring(p) or is_longstring(p) then
  120. getparaloc:=LOC_REFERENCE
  121. else
  122. getparaloc:=LOC_REGISTER;
  123. procvardef:
  124. getparaloc:=LOC_REGISTER;
  125. filedef:
  126. getparaloc:=LOC_REGISTER;
  127. arraydef:
  128. getparaloc:=LOC_REFERENCE;
  129. setdef:
  130. if is_smallset(p) then
  131. getparaloc:=LOC_REGISTER
  132. else
  133. getparaloc:=LOC_REFERENCE;
  134. variantdef:
  135. getparaloc:=LOC_REGISTER;
  136. { avoid problems with errornous definitions }
  137. errordef:
  138. getparaloc:=LOC_REGISTER;
  139. else
  140. internalerror(2002071001);
  141. end;
  142. end;
  143. function taarch64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  144. begin
  145. result:=false;
  146. if varspez in [vs_var,vs_out,vs_constref] then
  147. begin
  148. result:=true;
  149. exit;
  150. end;
  151. case def.typ of
  152. objectdef:
  153. result:=not(Is_HFA(def) and (is_object(def) and ((varspez=vs_const) or (def.size=0));
  154. recorddef:
  155. { note: should this ever be changed, make sure that const records
  156. are always passed by reference for calloption=pocall_mwpascal }
  157. result:=(varspez=vs_const) or (def.size=0);
  158. variantdef,
  159. formaldef:
  160. result:=true;
  161. arraydef:
  162. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  163. is_open_array(def) or
  164. is_array_of_const(def) or
  165. is_array_constructor(def);
  166. setdef :
  167. result:=def.size>16;
  168. stringdef :
  169. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  170. end;
  171. end;
  172. function taarch64paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
  173. var
  174. i: longint;
  175. sym: tsym;
  176. fpufield: boolean;
  177. begin
  178. if handle_common_ret_in_param(def,pd,result) then
  179. exit;
  180. case def.typ of
  181. recorddef:
  182. begin
  183. result:=def.size>4;
  184. if not result and
  185. (target_info.abi in [abi_default,abi_armeb]) then
  186. begin
  187. { in case of the old ARM abi (APCS), a struct is returned in
  188. a register only if it is simple. And what is a (non-)simple
  189. struct:
  190. "A non-simple type is any non-floating-point type of size
  191. greater than one word (including structures containing only
  192. floating-point fields), and certain single-word structured
  193. types."
  194. (-- ARM APCS documentation)
  195. So only floating point types or more than one word ->
  196. definitely non-simple (more than one word is already
  197. checked above). This includes unions/variant records with
  198. overlaid floating point and integer fields.
  199. Smaller than one word struct types are simple if they are
  200. "integer-like", and:
  201. "A structure is termed integer-like if its size is less than
  202. or equal to one word, and the offset of each of its
  203. addressable subfields is zero."
  204. (-- ARM APCS documentation)
  205. An "addressable subfield" is a field of which you can take
  206. the address, which in practive means any non-bitfield.
  207. In Pascal, there is no way to express the difference that
  208. you can have in C between "char" and "int :8". In this
  209. context, we use the fake distinction that a type defined
  210. inside the record itself (such as "a: 0..255;") indicates
  211. a bitpacked field while a field using a different type
  212. (such as "a: byte;") is not.
  213. }
  214. for i:=0 to trecorddef(def).symtable.SymList.count-1 do
  215. begin
  216. sym:=tsym(trecorddef(def).symtable.SymList[i]);
  217. if sym.typ<>fieldvarsym then
  218. continue;
  219. { bitfield -> ignore }
  220. if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
  221. (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
  222. (tfieldvarsym(sym).vardef.owner.defowner=def) then
  223. continue;
  224. { all other fields must be at offset zero }
  225. if tfieldvarsym(sym).fieldoffset<>0 then
  226. begin
  227. result:=true;
  228. exit;
  229. end;
  230. { floating point field -> also by reference }
  231. if tfieldvarsym(sym).vardef.typ=floatdef then
  232. begin
  233. result:=true;
  234. exit;
  235. end;
  236. end;
  237. end;
  238. end;
  239. procvardef:
  240. if not tprocvardef(def).is_addressonly then
  241. result:=true
  242. else
  243. result:=false
  244. else
  245. result:=inherited ret_in_param(def,pd);
  246. end;
  247. end;
  248. procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
  249. begin
  250. curintreg:=RS_R0;
  251. curfloatreg:=RS_F0;
  252. curmmreg:=RS_D0;
  253. cur_stack_offset:=0;
  254. sparesinglereg := NR_NO;
  255. end;
  256. function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  257. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
  258. var
  259. nextintreg,nextfloatreg,nextmmreg : tsuperregister;
  260. paradef : tdef;
  261. paraloc : pcgparalocation;
  262. stack_offset : aword;
  263. hp : tparavarsym;
  264. loc : tcgloc;
  265. paracgsize : tcgsize;
  266. paralen : longint;
  267. i : integer;
  268. firstparaloc: boolean;
  269. procedure assignintreg;
  270. begin
  271. { In case of po_delphi_nested_cc, the parent frame pointer
  272. is always passed on the stack. }
  273. if (nextintreg<=RS_R3) and
  274. (not(vo_is_parentfp in hp.varoptions) or
  275. not(po_delphi_nested_cc in p.procoptions)) then
  276. begin
  277. paraloc^.loc:=LOC_REGISTER;
  278. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
  279. inc(nextintreg);
  280. end
  281. else
  282. begin
  283. paraloc^.loc:=LOC_REFERENCE;
  284. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  285. paraloc^.reference.offset:=stack_offset;
  286. inc(stack_offset,4);
  287. end;
  288. end;
  289. begin
  290. result:=0;
  291. nextintreg:=curintreg;
  292. nextfloatreg:=curfloatreg;
  293. nextmmreg:=curmmreg;
  294. stack_offset:=cur_stack_offset;
  295. for i:=0 to paras.count-1 do
  296. begin
  297. hp:=tparavarsym(paras[i]);
  298. paradef:=hp.vardef;
  299. hp.paraloc[side].reset;
  300. { currently only support C-style array of const,
  301. there should be no location assigned to the vararg array itself }
  302. if (p.proccalloption in cstylearrayofconst) and
  303. is_array_of_const(paradef) then
  304. begin
  305. paraloc:=hp.paraloc[side].add_location;
  306. { hack: the paraloc must be valid, but is not actually used }
  307. paraloc^.loc:=LOC_REGISTER;
  308. paraloc^.register:=NR_R0;
  309. paraloc^.size:=OS_ADDR;
  310. break;
  311. end;
  312. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  313. begin
  314. paradef:=getpointerdef(paradef);
  315. loc:=LOC_REGISTER;
  316. paracgsize := OS_ADDR;
  317. paralen := tcgsize2size[OS_ADDR];
  318. end
  319. else
  320. begin
  321. if not is_special_array(paradef) then
  322. paralen := paradef.size
  323. else
  324. paralen := tcgsize2size[def_cgsize(paradef)];
  325. loc := getparaloc(p.proccalloption,paradef,isvariadic);
  326. if (paradef.typ in [objectdef,arraydef,recorddef]) and
  327. not is_special_array(paradef) and
  328. (hp.varspez in [vs_value,vs_const]) then
  329. paracgsize := int_cgsize(paralen)
  330. else
  331. begin
  332. paracgsize:=def_cgsize(paradef);
  333. { for things like formaldef }
  334. if (paracgsize=OS_NO) then
  335. begin
  336. paracgsize:=OS_ADDR;
  337. paralen:=tcgsize2size[OS_ADDR];
  338. paradef:=voidpointertype;
  339. end;
  340. end
  341. end;
  342. hp.paraloc[side].size:=paracgsize;
  343. hp.paraloc[side].Alignment:=std_param_align;
  344. hp.paraloc[side].intsize:=paralen;
  345. hp.paraloc[side].def:=paradef;
  346. firstparaloc:=true;
  347. {$ifdef EXTDEBUG}
  348. if paralen=0 then
  349. internalerror(200410311);
  350. {$endif EXTDEBUG}
  351. while paralen>0 do
  352. begin
  353. paraloc:=hp.paraloc[side].add_location;
  354. if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
  355. case paracgsize of
  356. OS_F32:
  357. paraloc^.size:=OS_32;
  358. OS_F64:
  359. paraloc^.size:=OS_32;
  360. else
  361. internalerror(2005082901);
  362. end
  363. else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  364. paraloc^.size := OS_32
  365. else
  366. paraloc^.size:=paracgsize;
  367. case loc of
  368. LOC_REGISTER:
  369. begin
  370. { align registers for eabi }
  371. if (target_info.abi in [abi_eabi,abi_eabihf]) and
  372. firstparaloc and
  373. (paradef.alignment=8) then
  374. begin
  375. if (nextintreg in [RS_R1,RS_R3]) then
  376. inc(nextintreg)
  377. else if nextintreg>RS_R3 then
  378. stack_offset:=align(stack_offset,8);
  379. end;
  380. { this is not abi compliant
  381. why? (FK) }
  382. if nextintreg<=RS_R3 then
  383. begin
  384. paraloc^.loc:=LOC_REGISTER;
  385. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
  386. inc(nextintreg);
  387. end
  388. else
  389. begin
  390. { LOC_REFERENCE always contains everything that's left }
  391. paraloc^.loc:=LOC_REFERENCE;
  392. paraloc^.size:=int_cgsize(paralen);
  393. if (side=callerside) then
  394. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  395. paraloc^.reference.offset:=stack_offset;
  396. inc(stack_offset,align(paralen,4));
  397. paralen:=0;
  398. end;
  399. end;
  400. LOC_FPUREGISTER:
  401. begin
  402. if nextfloatreg<=RS_F3 then
  403. begin
  404. paraloc^.loc:=LOC_FPUREGISTER;
  405. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  406. inc(nextfloatreg);
  407. end
  408. else
  409. begin
  410. paraloc^.loc:=LOC_REFERENCE;
  411. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  412. paraloc^.reference.offset:=stack_offset;
  413. case paraloc^.size of
  414. OS_F32:
  415. inc(stack_offset,4);
  416. OS_F64:
  417. inc(stack_offset,8);
  418. OS_F80:
  419. inc(stack_offset,10);
  420. OS_F128:
  421. inc(stack_offset,16);
  422. else
  423. internalerror(200403201);
  424. end;
  425. end;
  426. end;
  427. LOC_MMREGISTER:
  428. begin
  429. if (nextmmreg<=RS_D7) or
  430. ((paraloc^.size = OS_F32) and
  431. (sparesinglereg<>NR_NO)) then
  432. begin
  433. paraloc^.loc:=LOC_MMREGISTER;
  434. case paraloc^.size of
  435. OS_F32:
  436. if sparesinglereg = NR_NO then
  437. begin
  438. paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
  439. sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
  440. inc(nextmmreg);
  441. end
  442. else
  443. begin
  444. paraloc^.register:=sparesinglereg;
  445. sparesinglereg := NR_NO;
  446. end;
  447. OS_F64:
  448. begin
  449. paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
  450. inc(nextmmreg);
  451. end;
  452. else
  453. internalerror(2012031601);
  454. end;
  455. end
  456. else
  457. begin
  458. { once a floating point parameters has been placed
  459. on the stack we must not pass any more in vfp regs
  460. even if there is a single precision register still
  461. free}
  462. sparesinglereg := NR_NO;
  463. { LOC_REFERENCE always contains everything that's left }
  464. paraloc^.loc:=LOC_REFERENCE;
  465. paraloc^.size:=int_cgsize(paralen);
  466. if (side=callerside) then
  467. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  468. paraloc^.reference.offset:=stack_offset;
  469. inc(stack_offset,align(paralen,4));
  470. paralen:=0;
  471. end;
  472. end;
  473. LOC_REFERENCE:
  474. begin
  475. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  476. begin
  477. paraloc^.size:=OS_ADDR;
  478. assignintreg
  479. end
  480. else
  481. begin
  482. { align stack for eabi }
  483. if (target_info.abi in [abi_eabi,abi_eabihf]) and
  484. firstparaloc and
  485. (paradef.alignment=8) then
  486. stack_offset:=align(stack_offset,8);
  487. paraloc^.size:=paracgsize;
  488. paraloc^.loc:=LOC_REFERENCE;
  489. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  490. paraloc^.reference.offset:=stack_offset;
  491. inc(stack_offset,align(paralen,4));
  492. paralen:=0
  493. end;
  494. end;
  495. else
  496. internalerror(2002071002);
  497. end;
  498. if side=calleeside then
  499. begin
  500. if paraloc^.loc=LOC_REFERENCE then
  501. begin
  502. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  503. { on non-Darwin, the framepointer contains the value
  504. of the stack pointer on entry. On Darwin, the
  505. framepointer points to the previously saved
  506. framepointer (which is followed only by the saved
  507. return address -> framepointer + 4 = stack pointer
  508. on entry }
  509. if not(target_info.system in systems_darwin) then
  510. inc(paraloc^.reference.offset,4)
  511. else
  512. inc(paraloc^.reference.offset,8);
  513. end;
  514. end;
  515. dec(paralen,tcgsize2size[paraloc^.size]);
  516. firstparaloc:=false
  517. end;
  518. end;
  519. curintreg:=nextintreg;
  520. curfloatreg:=nextfloatreg;
  521. curmmreg:=nextmmreg;
  522. cur_stack_offset:=stack_offset;
  523. result:=cur_stack_offset;
  524. end;
  525. function taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  526. var
  527. paraloc : pcgparalocation;
  528. retcgsize : tcgsize;
  529. begin
  530. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  531. exit;
  532. paraloc:=result.add_location;
  533. { Return in FPU register? }
  534. if result.def.typ=floatdef then
  535. begin
  536. if target_info.abi = abi_eabihf then
  537. begin
  538. paraloc^.loc:=LOC_MMREGISTER;
  539. case retcgsize of
  540. OS_64,
  541. OS_F64:
  542. begin
  543. paraloc^.register:=NR_MM_RESULT_REG;
  544. end;
  545. OS_32,
  546. OS_F32:
  547. begin
  548. paraloc^.register:=NR_S0;
  549. end;
  550. else
  551. internalerror(2012032501);
  552. end;
  553. paraloc^.size:=retcgsize;
  554. end
  555. else if (p.proccalloption in [pocall_softfloat]) or
  556. (cs_fp_emulation in current_settings.moduleswitches) or
  557. (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
  558. begin
  559. case retcgsize of
  560. OS_64,
  561. OS_F64:
  562. begin
  563. paraloc^.loc:=LOC_REGISTER;
  564. if target_info.endian = endian_big then
  565. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  566. else
  567. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
  568. paraloc^.size:=OS_32;
  569. paraloc:=result.add_location;
  570. paraloc^.loc:=LOC_REGISTER;
  571. if target_info.endian = endian_big then
  572. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  573. else
  574. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
  575. paraloc^.size:=OS_32;
  576. end;
  577. OS_32,
  578. OS_F32:
  579. begin
  580. paraloc^.loc:=LOC_REGISTER;
  581. paraloc^.register:=NR_FUNCTION_RETURN_REG;
  582. paraloc^.size:=OS_32;
  583. end;
  584. else
  585. internalerror(2005082603);
  586. end;
  587. end
  588. else
  589. begin
  590. paraloc^.loc:=LOC_FPUREGISTER;
  591. paraloc^.register:=NR_FPU_RESULT_REG;
  592. paraloc^.size:=retcgsize;
  593. end;
  594. end
  595. { Return in register }
  596. else
  597. begin
  598. if retcgsize in [OS_64,OS_S64] then
  599. begin
  600. paraloc^.loc:=LOC_REGISTER;
  601. if target_info.endian = endian_big then
  602. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  603. else
  604. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
  605. paraloc^.size:=OS_32;
  606. paraloc:=result.add_location;
  607. paraloc^.loc:=LOC_REGISTER;
  608. if target_info.endian = endian_big then
  609. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  610. else
  611. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
  612. paraloc^.size:=OS_32;
  613. end
  614. else
  615. begin
  616. paraloc^.loc:=LOC_REGISTER;
  617. paraloc^.register:=NR_FUNCTION_RETURN_REG;
  618. if (result.intsize<>3) then
  619. paraloc^.size:=retcgsize
  620. else
  621. paraloc^.size:=OS_32;
  622. end;
  623. end;
  624. end;
  625. function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  626. var
  627. cur_stack_offset: aword;
  628. curintreg, curfloatreg, curmmreg: tsuperregister;
  629. sparesinglereg:tregister;
  630. begin
  631. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
  632. result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
  633. create_funcretloc_info(p,side);
  634. end;
  635. function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  636. var
  637. cur_stack_offset: aword;
  638. curintreg, curfloatreg, curmmreg: tsuperregister;
  639. sparesinglereg:tregister;
  640. begin
  641. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
  642. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
  643. if (p.proccalloption in cstylearrayofconst) then
  644. { just continue loading the parameters in the registers }
  645. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
  646. else
  647. internalerror(200410231);
  648. end;
  649. begin
  650. paramanager:=taarch64paramanager.create;
  651. end.