cpupara.pas 32 KB

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