cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  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. { this must be system independent safecall and record constructor result
  179. is always return in param }
  180. if (tf_safecall_exceptions in target_info.flags) and
  181. (pd.proccalloption=pocall_safecall) or
  182. ((pd.proctypeoption=potype_constructor)and is_record(def)) then
  183. begin
  184. result:=true;
  185. exit;
  186. end;
  187. case def.typ of
  188. recorddef:
  189. begin
  190. result:=def.size>4;
  191. if not result and
  192. (target_info.abi in [abi_default,abi_armeb]) then
  193. begin
  194. { in case of the old ARM abi (APCS), a struct is returned in
  195. a register only if it is simple. And what is a (non-)simple
  196. struct:
  197. "A non-simple type is any non-floating-point type of size
  198. greater than one word (including structures containing only
  199. floating-point fields), and certain single-word structured
  200. types."
  201. (-- ARM APCS documentation)
  202. So only floating point types or more than one word ->
  203. definitely non-simple (more than one word is already
  204. checked above). This includes unions/variant records with
  205. overlaid floating point and integer fields.
  206. Smaller than one word struct types are simple if they are
  207. "integer-like", and:
  208. "A structure is termed integer-like if its size is less than
  209. or equal to one word, and the offset of each of its
  210. addressable subfields is zero."
  211. (-- ARM APCS documentation)
  212. An "addressable subfield" is a field of which you can take
  213. the address, which in practive means any non-bitfield.
  214. In Pascal, there is no way to express the difference that
  215. you can have in C between "char" and "int :8". In this
  216. context, we use the fake distinction that a type defined
  217. inside the record itself (such as "a: 0..255;") indicates
  218. a bitpacked field while a field using a different type
  219. (such as "a: byte;") is not.
  220. }
  221. for i:=0 to trecorddef(def).symtable.SymList.count-1 do
  222. begin
  223. sym:=tsym(trecorddef(def).symtable.SymList[i]);
  224. if sym.typ<>fieldvarsym then
  225. continue;
  226. { bitfield -> ignore }
  227. if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
  228. (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
  229. (tfieldvarsym(sym).vardef.owner.defowner=def) then
  230. continue;
  231. { all other fields must be at offset zero }
  232. if tfieldvarsym(sym).fieldoffset<>0 then
  233. begin
  234. result:=true;
  235. exit;
  236. end;
  237. { floating point field -> also by reference }
  238. if tfieldvarsym(sym).vardef.typ=floatdef then
  239. begin
  240. result:=true;
  241. exit;
  242. end;
  243. end;
  244. end;
  245. end;
  246. procvardef:
  247. if not tprocvardef(def).is_addressonly then
  248. result:=true
  249. else
  250. result:=false
  251. else
  252. result:=inherited ret_in_param(def,pd);
  253. end;
  254. end;
  255. procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
  256. begin
  257. curintreg:=RS_R0;
  258. curfloatreg:=RS_F0;
  259. curmmreg:=RS_D0;
  260. cur_stack_offset:=0;
  261. sparesinglereg := NR_NO;
  262. end;
  263. function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  264. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
  265. var
  266. nextintreg,nextfloatreg,nextmmreg : tsuperregister;
  267. paradef : tdef;
  268. paraloc : pcgparalocation;
  269. stack_offset : aword;
  270. hp : tparavarsym;
  271. loc : tcgloc;
  272. paracgsize : tcgsize;
  273. paralen : longint;
  274. i : integer;
  275. firstparaloc: boolean;
  276. procedure assignintreg;
  277. begin
  278. { In case of po_delphi_nested_cc, the parent frame pointer
  279. is always passed on the stack. }
  280. if (nextintreg<=RS_R3) and
  281. (not(vo_is_parentfp in hp.varoptions) or
  282. not(po_delphi_nested_cc in p.procoptions)) then
  283. begin
  284. paraloc^.loc:=LOC_REGISTER;
  285. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
  286. inc(nextintreg);
  287. end
  288. else
  289. begin
  290. paraloc^.loc:=LOC_REFERENCE;
  291. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  292. paraloc^.reference.offset:=stack_offset;
  293. inc(stack_offset,4);
  294. end;
  295. end;
  296. begin
  297. result:=0;
  298. nextintreg:=curintreg;
  299. nextfloatreg:=curfloatreg;
  300. nextmmreg:=curmmreg;
  301. stack_offset:=cur_stack_offset;
  302. for i:=0 to paras.count-1 do
  303. begin
  304. hp:=tparavarsym(paras[i]);
  305. paradef:=hp.vardef;
  306. hp.paraloc[side].reset;
  307. { currently only support C-style array of const,
  308. there should be no location assigned to the vararg array itself }
  309. if (p.proccalloption in cstylearrayofconst) and
  310. is_array_of_const(paradef) then
  311. begin
  312. paraloc:=hp.paraloc[side].add_location;
  313. { hack: the paraloc must be valid, but is not actually used }
  314. paraloc^.loc:=LOC_REGISTER;
  315. paraloc^.register:=NR_R0;
  316. paraloc^.size:=OS_ADDR;
  317. break;
  318. end;
  319. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  320. begin
  321. paradef:=getpointerdef(paradef);
  322. loc:=LOC_REGISTER;
  323. paracgsize := OS_ADDR;
  324. paralen := tcgsize2size[OS_ADDR];
  325. end
  326. else
  327. begin
  328. if not is_special_array(paradef) then
  329. paralen := paradef.size
  330. else
  331. paralen := tcgsize2size[def_cgsize(paradef)];
  332. loc := getparaloc(p.proccalloption,paradef,isvariadic);
  333. if (paradef.typ in [objectdef,arraydef,recorddef]) and
  334. not is_special_array(paradef) and
  335. (hp.varspez in [vs_value,vs_const]) then
  336. paracgsize := int_cgsize(paralen)
  337. else
  338. begin
  339. paracgsize:=def_cgsize(paradef);
  340. { for things like formaldef }
  341. if (paracgsize=OS_NO) then
  342. begin
  343. paracgsize:=OS_ADDR;
  344. paralen:=tcgsize2size[OS_ADDR];
  345. paradef:=voidpointertype;
  346. end;
  347. end
  348. end;
  349. hp.paraloc[side].size:=paracgsize;
  350. hp.paraloc[side].Alignment:=std_param_align;
  351. hp.paraloc[side].intsize:=paralen;
  352. hp.paraloc[side].def:=paradef;
  353. firstparaloc:=true;
  354. {$ifdef EXTDEBUG}
  355. if paralen=0 then
  356. internalerror(200410311);
  357. {$endif EXTDEBUG}
  358. while paralen>0 do
  359. begin
  360. paraloc:=hp.paraloc[side].add_location;
  361. if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
  362. case paracgsize of
  363. OS_F32:
  364. paraloc^.size:=OS_32;
  365. OS_F64:
  366. paraloc^.size:=OS_32;
  367. else
  368. internalerror(2005082901);
  369. end
  370. else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
  371. paraloc^.size := OS_32
  372. else
  373. paraloc^.size:=paracgsize;
  374. case loc of
  375. LOC_REGISTER:
  376. begin
  377. { align registers for eabi }
  378. if (target_info.abi in [abi_eabi,abi_eabihf]) and
  379. firstparaloc and
  380. (paradef.alignment=8) then
  381. begin
  382. if (nextintreg in [RS_R1,RS_R3]) then
  383. inc(nextintreg)
  384. else if nextintreg>RS_R3 then
  385. stack_offset:=align(stack_offset,8);
  386. end;
  387. { this is not abi compliant
  388. why? (FK) }
  389. if nextintreg<=RS_R3 then
  390. begin
  391. paraloc^.loc:=LOC_REGISTER;
  392. paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
  393. inc(nextintreg);
  394. end
  395. else
  396. begin
  397. { LOC_REFERENCE always contains everything that's left }
  398. paraloc^.loc:=LOC_REFERENCE;
  399. paraloc^.size:=int_cgsize(paralen);
  400. if (side=callerside) then
  401. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  402. paraloc^.reference.offset:=stack_offset;
  403. inc(stack_offset,align(paralen,4));
  404. paralen:=0;
  405. end;
  406. end;
  407. LOC_FPUREGISTER:
  408. begin
  409. if nextfloatreg<=RS_F3 then
  410. begin
  411. paraloc^.loc:=LOC_FPUREGISTER;
  412. paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
  413. inc(nextfloatreg);
  414. end
  415. else
  416. begin
  417. paraloc^.loc:=LOC_REFERENCE;
  418. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  419. paraloc^.reference.offset:=stack_offset;
  420. case paraloc^.size of
  421. OS_F32:
  422. inc(stack_offset,4);
  423. OS_F64:
  424. inc(stack_offset,8);
  425. OS_F80:
  426. inc(stack_offset,10);
  427. OS_F128:
  428. inc(stack_offset,16);
  429. else
  430. internalerror(200403201);
  431. end;
  432. end;
  433. end;
  434. LOC_MMREGISTER:
  435. begin
  436. if (nextmmreg<=RS_D7) or
  437. ((paraloc^.size = OS_F32) and
  438. (sparesinglereg<>NR_NO)) then
  439. begin
  440. paraloc^.loc:=LOC_MMREGISTER;
  441. case paraloc^.size of
  442. OS_F32:
  443. if sparesinglereg = NR_NO then
  444. begin
  445. paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
  446. sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
  447. inc(nextmmreg);
  448. end
  449. else
  450. begin
  451. paraloc^.register:=sparesinglereg;
  452. sparesinglereg := NR_NO;
  453. end;
  454. OS_F64:
  455. begin
  456. paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
  457. inc(nextmmreg);
  458. end;
  459. else
  460. internalerror(2012031601);
  461. end;
  462. end
  463. else
  464. begin
  465. { once a floating point parameters has been placed
  466. on the stack we must not pass any more in vfp regs
  467. even if there is a single precision register still
  468. free}
  469. sparesinglereg := NR_NO;
  470. { LOC_REFERENCE always contains everything that's left }
  471. paraloc^.loc:=LOC_REFERENCE;
  472. paraloc^.size:=int_cgsize(paralen);
  473. if (side=callerside) then
  474. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  475. paraloc^.reference.offset:=stack_offset;
  476. inc(stack_offset,align(paralen,4));
  477. paralen:=0;
  478. end;
  479. end;
  480. LOC_REFERENCE:
  481. begin
  482. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  483. begin
  484. paraloc^.size:=OS_ADDR;
  485. assignintreg
  486. end
  487. else
  488. begin
  489. { align stack for eabi }
  490. if (target_info.abi in [abi_eabi,abi_eabihf]) and
  491. firstparaloc and
  492. (paradef.alignment=8) then
  493. stack_offset:=align(stack_offset,8);
  494. paraloc^.size:=paracgsize;
  495. paraloc^.loc:=LOC_REFERENCE;
  496. paraloc^.reference.index:=NR_STACK_POINTER_REG;
  497. paraloc^.reference.offset:=stack_offset;
  498. inc(stack_offset,align(paralen,4));
  499. paralen:=0
  500. end;
  501. end;
  502. else
  503. internalerror(2002071002);
  504. end;
  505. if side=calleeside then
  506. begin
  507. if paraloc^.loc=LOC_REFERENCE then
  508. begin
  509. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  510. { on non-Darwin, the framepointer contains the value
  511. of the stack pointer on entry. On Darwin, the
  512. framepointer points to the previously saved
  513. framepointer (which is followed only by the saved
  514. return address -> framepointer + 4 = stack pointer
  515. on entry }
  516. if not(target_info.system in systems_darwin) then
  517. inc(paraloc^.reference.offset,4)
  518. else
  519. inc(paraloc^.reference.offset,8);
  520. end;
  521. end;
  522. dec(paralen,tcgsize2size[paraloc^.size]);
  523. firstparaloc:=false
  524. end;
  525. end;
  526. curintreg:=nextintreg;
  527. curfloatreg:=nextfloatreg;
  528. curmmreg:=nextmmreg;
  529. cur_stack_offset:=stack_offset;
  530. result:=cur_stack_offset;
  531. end;
  532. function taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  533. var
  534. paraloc : pcgparalocation;
  535. retcgsize : tcgsize;
  536. begin
  537. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  538. exit;
  539. paraloc:=result.add_location;
  540. { Return in FPU register? }
  541. if result.def.typ=floatdef then
  542. begin
  543. if target_info.abi = abi_eabihf then
  544. begin
  545. paraloc^.loc:=LOC_MMREGISTER;
  546. case retcgsize of
  547. OS_64,
  548. OS_F64:
  549. begin
  550. paraloc^.register:=NR_MM_RESULT_REG;
  551. end;
  552. OS_32,
  553. OS_F32:
  554. begin
  555. paraloc^.register:=NR_S0;
  556. end;
  557. else
  558. internalerror(2012032501);
  559. end;
  560. paraloc^.size:=retcgsize;
  561. end
  562. else if (p.proccalloption in [pocall_softfloat]) or
  563. (cs_fp_emulation in current_settings.moduleswitches) or
  564. (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
  565. begin
  566. case retcgsize of
  567. OS_64,
  568. OS_F64:
  569. begin
  570. paraloc^.loc:=LOC_REGISTER;
  571. if target_info.endian = endian_big then
  572. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  573. else
  574. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
  575. paraloc^.size:=OS_32;
  576. paraloc:=result.add_location;
  577. paraloc^.loc:=LOC_REGISTER;
  578. if target_info.endian = endian_big then
  579. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  580. else
  581. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
  582. paraloc^.size:=OS_32;
  583. end;
  584. OS_32,
  585. OS_F32:
  586. begin
  587. paraloc^.loc:=LOC_REGISTER;
  588. paraloc^.register:=NR_FUNCTION_RETURN_REG;
  589. paraloc^.size:=OS_32;
  590. end;
  591. else
  592. internalerror(2005082603);
  593. end;
  594. end
  595. else
  596. begin
  597. paraloc^.loc:=LOC_FPUREGISTER;
  598. paraloc^.register:=NR_FPU_RESULT_REG;
  599. paraloc^.size:=retcgsize;
  600. end;
  601. end
  602. { Return in register }
  603. else
  604. begin
  605. if retcgsize in [OS_64,OS_S64] then
  606. begin
  607. paraloc^.loc:=LOC_REGISTER;
  608. if target_info.endian = endian_big then
  609. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  610. else
  611. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
  612. paraloc^.size:=OS_32;
  613. paraloc:=result.add_location;
  614. paraloc^.loc:=LOC_REGISTER;
  615. if target_info.endian = endian_big then
  616. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  617. else
  618. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
  619. paraloc^.size:=OS_32;
  620. end
  621. else
  622. begin
  623. paraloc^.loc:=LOC_REGISTER;
  624. paraloc^.register:=NR_FUNCTION_RETURN_REG;
  625. if (result.intsize<>3) then
  626. paraloc^.size:=retcgsize
  627. else
  628. paraloc^.size:=OS_32;
  629. end;
  630. end;
  631. end;
  632. function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  633. var
  634. cur_stack_offset: aword;
  635. curintreg, curfloatreg, curmmreg: tsuperregister;
  636. sparesinglereg:tregister;
  637. begin
  638. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
  639. result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
  640. create_funcretloc_info(p,side);
  641. end;
  642. function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  643. var
  644. cur_stack_offset: aword;
  645. curintreg, curfloatreg, curmmreg: tsuperregister;
  646. sparesinglereg:tregister;
  647. begin
  648. init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
  649. result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
  650. if (p.proccalloption in cstylearrayofconst) then
  651. { just continue loading the parameters in the registers }
  652. result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
  653. else
  654. internalerror(200410231);
  655. end;
  656. begin
  657. paramanager:=taarch64paramanager.create;
  658. end.