cpupara.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. PowerPC64 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,aasmdata,
  23. cpubase,
  24. symconst, symtype, symdef, symsym,
  25. paramgr, parabase, cgbase, cgutils;
  26. type
  27. tcpuparamanager = class(tparamanager)
  28. function get_volatile_registers_int(calloption: tproccalloption):
  29. tcpuregisterset; override;
  30. function get_volatile_registers_fpu(calloption: tproccalloption):
  31. tcpuregisterset; override;
  32. function get_saved_registers_int(calloption: tproccalloption):
  33. tcpuregisterarray; override;
  34. function push_addr_param(varspez: tvarspez; def: tdef; calloption:
  35. tproccalloption): boolean; override;
  36. function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
  37. procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
  38. function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
  39. function create_varargs_paraloc_info(p: tabstractprocdef; varargspara:
  40. tvarargsparalist): longint; override;
  41. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
  42. private
  43. procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister;
  44. var cur_stack_offset: aword);
  45. function create_paraloc_info_intern(p: tabstractprocdef; side:
  46. tcallercallee; paras: tparalist;
  47. var curintreg, curfloatreg, curmmreg: tsuperregister; var
  48. cur_stack_offset: aword; isVararg : boolean): longint;
  49. function parseparaloc(p: tparavarsym; const s: string): boolean; override;
  50. procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
  51. end;
  52. implementation
  53. uses
  54. verbose, systems,
  55. defutil,symtable,symcpu,
  56. procinfo, cpupi;
  57. function tcpuparamanager.get_volatile_registers_int(calloption:
  58. tproccalloption): tcpuregisterset;
  59. begin
  60. result := [RS_R0,RS_R3..RS_R12];
  61. if (target_info.system = system_powerpc64_darwin) then
  62. include(result,RS_R2);
  63. end;
  64. function tcpuparamanager.get_volatile_registers_fpu(calloption:
  65. tproccalloption): tcpuregisterset;
  66. begin
  67. result := [RS_F0..RS_F13];
  68. end;
  69. function tcpuparamanager.get_saved_registers_int(calloption: tproccalloption):
  70. tcpuregisterarray;
  71. const
  72. saved_regs: array[0..17] of tsuperregister = (
  73. RS_R14, RS_R15, RS_R16, RS_R17, RS_R18, RS_R19,
  74. RS_R20, RS_R21, RS_R22, RS_R23, RS_R24, RS_R25,
  75. RS_R26, RS_R27, RS_R28, RS_R29, RS_R30, RS_R31
  76. );
  77. begin
  78. result:=saved_regs;
  79. end;
  80. procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
  81. var
  82. paraloc: pcgparalocation;
  83. psym: tparavarsym;
  84. pdef: tdef;
  85. begin
  86. psym:=tparavarsym(pd.paras[nr-1]);
  87. pdef:=psym.vardef;
  88. if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
  89. pdef:=cpointerdef.getreusable_no_free(pdef);
  90. cgpara.reset;
  91. cgpara.size := def_cgsize(pdef);
  92. cgpara.intsize := tcgsize2size[cgpara.size];
  93. cgpara.alignment := get_para_align(pd.proccalloption);
  94. cgpara.def:=pdef;
  95. paraloc := cgpara.add_location;
  96. with paraloc^ do begin
  97. size := def_cgsize(pdef);
  98. def := pdef;
  99. if (nr <= 8) then begin
  100. if (nr = 0) then
  101. internalerror(200309271);
  102. loc := LOC_REGISTER;
  103. register := newreg(R_INTREGISTER, RS_R2 + nr, R_SUBWHOLE);
  104. end else begin
  105. loc := LOC_REFERENCE;
  106. paraloc^.reference.index := NR_STACK_POINTER_REG;
  107. reference.offset := sizeof(aint) * (nr - 8);
  108. end;
  109. end;
  110. end;
  111. function getparaloc(p: tdef): tcgloc;
  112. begin
  113. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  114. if push_addr_param for the def is true
  115. }
  116. case p.typ of
  117. orddef:
  118. result := LOC_REGISTER;
  119. floatdef:
  120. result := LOC_FPUREGISTER;
  121. enumdef:
  122. result := LOC_REGISTER;
  123. pointerdef:
  124. result := LOC_REGISTER;
  125. formaldef:
  126. result := LOC_REGISTER;
  127. classrefdef:
  128. result := LOC_REGISTER;
  129. procvardef,
  130. recorddef:
  131. result := LOC_REGISTER;
  132. objectdef:
  133. if is_object(p) then
  134. result := LOC_REFERENCE
  135. else
  136. result := LOC_REGISTER;
  137. stringdef:
  138. if is_shortstring(p) or is_longstring(p) then
  139. result := LOC_REFERENCE
  140. else
  141. result := LOC_REGISTER;
  142. filedef:
  143. result := LOC_REGISTER;
  144. arraydef:
  145. if is_dynamic_array(p) then
  146. getparaloc:=LOC_REGISTER
  147. else
  148. result := LOC_REFERENCE;
  149. setdef:
  150. if is_smallset(p) then
  151. result := LOC_REGISTER
  152. else
  153. result := LOC_REFERENCE;
  154. variantdef:
  155. result := LOC_REFERENCE;
  156. { avoid problems with errornous definitions }
  157. errordef:
  158. result := LOC_REGISTER;
  159. else
  160. internalerror(2002071001);
  161. end;
  162. end;
  163. function tcpuparamanager.push_addr_param(varspez: tvarspez; def: tdef;
  164. calloption: tproccalloption): boolean;
  165. begin
  166. result := false;
  167. { var,out,constref always require address }
  168. if varspez in [vs_var, vs_out, vs_constref] then
  169. begin
  170. result := true;
  171. exit;
  172. end;
  173. case def.typ of
  174. variantdef,
  175. formaldef:
  176. result := true;
  177. procvardef,
  178. recorddef:
  179. result :=
  180. (varspez = vs_const) and
  181. (
  182. (
  183. (not (calloption in cdecl_pocalls) and
  184. (def.size > 8))
  185. ) or
  186. (calloption = pocall_mwpascal)
  187. );
  188. arraydef:
  189. result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
  190. is_open_array(def) or
  191. is_array_of_const(def) or
  192. is_array_constructor(def);
  193. objectdef:
  194. result := is_object(def);
  195. setdef:
  196. result := not is_smallset(def);
  197. stringdef:
  198. result := tstringdef(def).stringtype in [st_shortstring, st_longstring];
  199. end;
  200. end;
  201. function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
  202. var
  203. tmpdef: tdef;
  204. begin
  205. if handle_common_ret_in_param(def,pd,result) then
  206. exit;
  207. { general rule: passed in registers -> returned in registers }
  208. result:=push_addr_param(vs_value,def,pd.proccalloption);
  209. case target_info.abi of
  210. { elfv2: non-homogeneous aggregate larger than 2 doublewords or a
  211. homogeneous aggregate with more than eight registers are returned by
  212. reference }
  213. abi_powerpc_elfv2:
  214. begin
  215. if not result then
  216. begin
  217. if (def.typ=recorddef) then
  218. begin
  219. if tcpurecorddef(def).has_single_type_elfv2(tmpdef) then
  220. begin
  221. if def.size>8*tmpdef.size then
  222. result:=true
  223. end
  224. else if def.size>2*sizeof(aint) then
  225. result:=true;
  226. end
  227. else if (def.typ=arraydef) then
  228. begin
  229. if tcpuarraydef(def).has_single_type_elfv2(tmpdef) then
  230. begin
  231. if def.size>8*tmpdef.size then
  232. result:=true
  233. end
  234. else if def.size>2*sizeof(aint) then
  235. result:=true;
  236. end;
  237. end;
  238. end;
  239. { sysv/aix: any non-scalar/non-floating point is returned by reference }
  240. abi_powerpc_sysv,
  241. abi_powerpc_aix:
  242. begin
  243. case def.typ of
  244. procvardef:
  245. result:=def.size>8;
  246. recorddef:
  247. result:=true;
  248. end;
  249. end;
  250. { Darwin: if completely passed in registers -> returned by registers;
  251. i.e., if part is passed via memory because there are not enough
  252. registers, return via memory }
  253. abi_powerpc_darwin:
  254. begin
  255. case def.typ of
  256. recorddef:
  257. { todo: fix once the Darwin/ppc64 abi is fully implemented, as it
  258. requires individual fields to be passed in individual registers,
  259. so a record with 9 bytes may need to be passed via memory }
  260. if def.size>8*sizeof(aint) then
  261. result:=true;
  262. end;
  263. end;
  264. end;
  265. end;
  266. procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg:
  267. tsuperregister; var cur_stack_offset: aword);
  268. begin
  269. case target_info.abi of
  270. abi_powerpc_elfv2:
  271. cur_stack_offset := 32;
  272. else
  273. cur_stack_offset := 48;
  274. end;
  275. curintreg := RS_R3;
  276. curfloatreg := RS_F1;
  277. curmmreg := RS_M2;
  278. end;
  279. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side:
  280. tcallercallee; forcetempdef: tdef): tcgpara;
  281. var
  282. paraloc: pcgparalocation;
  283. retcgsize: tcgsize;
  284. nextfloatreg, nextintreg, nextmmreg: tsuperregister;
  285. stack_offset: aword;
  286. begin
  287. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  288. exit;
  289. { on Darwin and with ELFv2, results are returned the same way as they are
  290. passed }
  291. if target_info.abi in [abi_powerpc_elfv2,abi_powerpc_darwin] then
  292. begin
  293. init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
  294. create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
  295. end
  296. else
  297. begin
  298. { for AIX and ELFv1, the situation is simpler: always just one register }
  299. paraloc:=result.add_location;
  300. { Return in FPU register? }
  301. if result.def.typ=floatdef then
  302. begin
  303. paraloc^.loc:=LOC_FPUREGISTER;
  304. paraloc^.register:=NR_FPU_RESULT_REG;
  305. paraloc^.size:=retcgsize;
  306. paraloc^.def:=result.def;
  307. end
  308. else
  309. { Return in register }
  310. begin
  311. paraloc^.loc:=LOC_REGISTER;
  312. if side=callerside then
  313. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  314. else
  315. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  316. paraloc^.size:=retcgsize;
  317. paraloc^.def:=result.def;
  318. end;
  319. end;
  320. end;
  321. function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side:
  322. tcallercallee): longint;
  323. var
  324. cur_stack_offset: aword;
  325. curintreg, curfloatreg, curmmreg : tsuperregister;
  326. begin
  327. init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
  328. result := create_paraloc_info_intern(p, side, p.paras, curintreg, curfloatreg,
  329. curmmreg, cur_stack_offset, false);
  330. create_funcretloc_info(p, side);
  331. end;
  332. function tcpuparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
  333. tcallercallee; paras: tparalist;
  334. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
  335. aword; isVararg : boolean): longint;
  336. var
  337. nextintreg, nextfloatreg, nextmmreg : tsuperregister;
  338. i: integer;
  339. hp: tparavarsym;
  340. paraloc: pcgparalocation;
  341. delphi_nestedfp: boolean;
  342. begin
  343. {$IFDEF extdebug}
  344. if po_explicitparaloc in p.procoptions then
  345. internalerror(200411141);
  346. {$ENDIF extdebug}
  347. result := 0;
  348. nextintreg := curintreg;
  349. nextfloatreg := curfloatreg;
  350. nextmmreg := curmmreg;
  351. for i := 0 to paras.count - 1 do begin
  352. hp := tparavarsym(paras[i]);
  353. { Syscall for Morphos can have already a paraloc set; not supported on ppc64 }
  354. if (vo_has_explicit_paraloc in hp.varoptions) then begin
  355. internalerror(200412153);
  356. end;
  357. { currently only support C-style array of const }
  358. if (p.proccalloption in cstylearrayofconst) and
  359. is_array_of_const(hp.vardef) then begin
  360. paraloc := hp.paraloc[side].add_location;
  361. { hack: the paraloc must be valid, but is not actually used }
  362. paraloc^.loc := LOC_REGISTER;
  363. paraloc^.register := NR_R0;
  364. paraloc^.size := OS_ADDR;
  365. paraloc^.def := voidpointertype;
  366. break;
  367. end;
  368. delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
  369. create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
  370. nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
  371. end;
  372. curintreg := nextintreg;
  373. curfloatreg := nextfloatreg;
  374. curmmreg := nextmmreg;
  375. result := cur_stack_offset;
  376. end;
  377. procedure tcpuparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
  378. var
  379. paracgsize: tcgsize;
  380. loc: tcgloc;
  381. paraloc: pcgparalocation;
  382. { def to use for all paralocs if <> nil }
  383. alllocdef,
  384. { def to use for the current paraloc }
  385. locdef,
  386. tmpdef: tdef;
  387. paralen: aint;
  388. parashift: byte;
  389. tailpadding,
  390. firstparaloc,
  391. paraaligned: boolean;
  392. begin
  393. alllocdef:=nil;
  394. locdef:=nil;
  395. parashift := 0;
  396. para.reset;
  397. { should the tail be shifted into the most significant bits? }
  398. tailpadding:=false;
  399. { have we ensured that the next parameter location will be aligned to the
  400. next 8 byte boundary? }
  401. paraaligned:=false;
  402. if push_addr_param(varspez, paradef, p.proccalloption) then begin
  403. paradef := cpointerdef.getreusable_no_free(paradef);
  404. loc := LOC_REGISTER;
  405. paracgsize := OS_ADDR;
  406. paralen := tcgsize2size[OS_ADDR];
  407. end else begin
  408. if not is_special_array(paradef) then
  409. paralen := paradef.size
  410. else
  411. paralen := tcgsize2size[def_cgsize(paradef)];
  412. { default rules:
  413. * integer parameters sign/zero-extended to 64 bit
  414. * floating point register used -> skip equivalent GP register
  415. * floating point parameters passed as is (32/64 bit)
  416. * floating point parameters to variable arguments -> in int registers
  417. * aggregates passed in consecutive integer registers
  418. * all *aggregate* data in integer registers exactly mirrors the data
  419. in memory -> on big endian it's left aligned (passed in most
  420. significant part of the 64 bit word if it's < 64 bit), on little
  421. endian it's right aligned (least significant part of the 64 bit
  422. word)
  423. special rules:
  424. implemented
  425. |
  426. | * AIX/ELFv1/SysV ppc64 ABI (big endian only):
  427. x a) single precision floats are stored in the second word of a 64 bit
  428. location when passed on the stack
  429. x b) aggregate with 1 floating point element passed like a floating
  430. point parameter of the same size
  431. x c) aggregates smaller than 64 bit are aligned in least significant bits
  432. of a single 64bit location (incl. register) (AIX exception: it puts
  433. them in the most significant bits)
  434. * ELFv2 ppc64 ABI:
  435. x a) so-called "homogeneous" aggregates, i.e. struct, arrays, or unions
  436. that (recursively) contain only elements of the same floating-
  437. point or vector type, are passed as if those elements were passed as
  438. separate arguments. This is done for up to 8 such elements.
  439. x b) other than a), it's the same as the AIX ppc64 ABI
  440. * Darwin ppc64 ABI:
  441. - as in the general case, aggregates in registers mirror their place in
  442. memory, so if e.g. a struct starts with a 32 bit integer, it's
  443. placed in the upper 32 bits of a the corresponding register. A plain
  444. 32 bit integer para is however passed in the lower 32 bits, since it
  445. is promoted to a 64 bit int first (see below)
  446. x a) aggregates with sizes 1, 2 and 4 bytes are padded with 0s on the left
  447. (-> aligned in least significant bits of 64 bit word on big endian) to
  448. a multiple of *4 bytes* (when passed by memory, don't occupy 8 bytes)
  449. x b) other aggregates are padded with 0s on the right (-> aligned in most
  450. signifcant bits of 64 bit word of integer register) to a multiple of
  451. *4 bytes*
  452. x c) all floating pointer parameters (not in aggregates) are promoted to
  453. double (doesn't seem to be correct: 8 bytes are reserved in the
  454. stack frame, but the compiler still stores a single in it (in the
  455. lower 4 bytes -- like with SysV a) )
  456. x d) all integer parameters (not in aggregates) are promoted to 64 bit
  457. (x) e) aggregates (incl. arrays) of exactly 16 bytes passed in two integer
  458. registers
  459. f) floats in *structures without unions* are processed per rule c)
  460. (similar for vector fields)
  461. g) other fields in *structures without unions* are processed
  462. recursively according to e) / f) if they are aggragates, and h)
  463. otherwise (i.e, without promotion!)
  464. (x) h) everything else (structures with unions and size<>16, arrays with
  465. size<>16, ...) is passed "normally" in integer registers
  466. }
  467. { ELFv2 a) }
  468. if (target_info.abi=abi_powerpc_elfv2) and
  469. (((paradef.typ=recorddef) and
  470. tcpurecorddef(paradef).has_single_type_elfv2(tmpdef)) or
  471. ((paradef.typ=arraydef) and
  472. tcpuarraydef(paradef).has_single_type_elfv2(tmpdef))) and
  473. (tmpdef.typ=floatdef { or vectordef }) and
  474. (paradef.size<=(8*tmpdef.size)) then
  475. begin
  476. alllocdef:=tmpdef;
  477. loc:=getparaloc(alllocdef);
  478. paracgsize:=def_cgsize(paradef);
  479. end
  480. { AIX/ELFv1 b) }
  481. else if (target_info.abi in [abi_powerpc_aix,abi_powerpc_sysv]) and
  482. (paradef.typ=recorddef) and
  483. tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
  484. (tmpdef.typ=floatdef) then
  485. begin
  486. paradef:=tmpdef;
  487. loc:=getparaloc(paradef);
  488. paracgsize:=def_cgsize(paradef)
  489. end
  490. else if (((paradef.typ=arraydef) and not
  491. is_special_array(paradef)) or
  492. (paradef.typ=recorddef)) then
  493. begin
  494. { should handle Darwin f/g/h) now, but can't model that yet }
  495. { general rule: aggregate data is aligned in the most significant bits
  496. except for ELFv1 c) and Darwin a) }
  497. if (target_info.endian=endian_big) and
  498. ((target_info.abi in [abi_powerpc_aix,abi_powerpc_elfv2]) or
  499. ((target_info.abi=abi_powerpc_sysv) and
  500. (paralen>8)) or
  501. ((target_info.abi=abi_powerpc_darwin) and
  502. not(paralen in [1,2,4]))) then
  503. tailpadding:=true
  504. { if we don't add tailpadding on the caller side, the callee will have
  505. to shift the value in the register before it can store it to memory }
  506. else if (target_info.endian=endian_big) and
  507. (paralen in [3,5,6,7]) then
  508. parashift:=(8-paralen)*8;
  509. { general fallback rule: pass aggregate types in integer registers
  510. without special adjustments (incl. Darwin h) }
  511. loc:=LOC_REGISTER;
  512. paracgsize:=int_cgsize(paralen);
  513. end
  514. else
  515. begin
  516. loc:=getparaloc(paradef);
  517. paracgsize:=def_cgsize(paradef);
  518. { for things like formaldef }
  519. if (paracgsize=OS_NO) then
  520. begin
  521. paracgsize:=OS_ADDR;
  522. paralen:=tcgsize2size[OS_ADDR];
  523. end;
  524. end
  525. end;
  526. { patch FPU values into integer registers if we are processing varargs }
  527. if (isVararg) and (paradef.typ = floatdef) then begin
  528. loc := LOC_REGISTER;
  529. if paracgsize = OS_F64 then
  530. paracgsize := OS_64
  531. else
  532. paracgsize := OS_32;
  533. end;
  534. { AIX/SysV a), Darwin c) -> skip 4 bytes in the stack frame }
  535. if (target_info.endian=endian_big) and
  536. (paradef.typ=floatdef) and
  537. (tfloatdef(paradef).floattype=s32real) and
  538. (nextfloatreg>RS_F13) then
  539. begin
  540. inc(stack_offset,4);
  541. paraaligned:=true;
  542. end;
  543. { Darwin d) }
  544. if (target_info.abi=abi_powerpc_darwin) and
  545. (paradef.typ in [orddef,enumdef]) and
  546. (paralen<8) and
  547. { we don't have to sign/zero extend the lower 8/16/32 bit on the callee
  548. side since it's done on the caller side; however, if the value is
  549. passed via memory, we do have to modify the stack offset since this
  550. is big endian and otherwise we'll load/store the wrong bytes) }
  551. ((side=callerside) or
  552. forceintmem or
  553. (nextintreg>RS_R10)) then
  554. begin
  555. if side=callerside then
  556. begin
  557. paralen:=8;
  558. paradef:=s64inttype;
  559. paracgsize:=OS_S64;
  560. end
  561. else
  562. begin
  563. inc(stack_offset,8-paralen);
  564. paraaligned:=true;
  565. end;
  566. end;
  567. para.alignment := std_param_align;
  568. para.size := paracgsize;
  569. para.intsize := paralen;
  570. para.def := paradef;
  571. if (paralen = 0) then
  572. if (paradef.typ = recorddef) then begin
  573. paraloc := para.add_location;
  574. paraloc^.loc := LOC_VOID;
  575. end else
  576. internalerror(2005011310);
  577. if not assigned(alllocdef) then
  578. locdef:=paradef
  579. else
  580. begin
  581. locdef:=alllocdef;
  582. paracgsize:=def_cgsize(locdef);
  583. end;
  584. firstparaloc:=true;
  585. { can become < 0 for e.g. 3-byte records }
  586. while (paralen > 0) do begin
  587. paraloc := para.add_location;
  588. { ELF64v2 a: overflow homogeneous float storage into integer registers
  589. if possible (only possible in case of single precision floats, because
  590. there are more fprs than gprs for parameter passing) }
  591. if assigned(alllocdef) and
  592. (loc=LOC_FPUREGISTER) and
  593. (((nextfloatreg=RS_F13) and
  594. (tcgsize2size[paracgsize]=4) and
  595. (paralen>4)) or
  596. (nextfloatreg>RS_F13)) then
  597. begin
  598. loc:=LOC_REGISTER;
  599. paracgsize:=OS_64;
  600. locdef:=u64inttype;
  601. end;
  602. { In case of po_delphi_nested_cc, the parent frame pointer
  603. is always passed on the stack. }
  604. if (loc = LOC_REGISTER) and
  605. (nextintreg <= RS_R10) and
  606. not forceintmem then begin
  607. paraloc^.loc := loc;
  608. paraloc^.shiftval := parashift;
  609. { make sure we don't lose whether or not the type is signed }
  610. if (paracgsize <> OS_NO) and
  611. (paradef.typ <> orddef) and
  612. not assigned(alllocdef) then
  613. begin
  614. paracgsize := int_cgsize(paralen);
  615. locdef:=get_paraloc_def(paradef, paralen, firstparaloc);
  616. end;
  617. { Partial aggregate data may have to be left-aligned. If so, add tail
  618. padding }
  619. if tailpadding and
  620. (paralen < sizeof(aint)) then
  621. begin
  622. paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
  623. paraloc^.size := OS_INT;
  624. paraloc^.def := u64inttype;
  625. end
  626. else if (paracgsize in [OS_NO, OS_128, OS_S128]) then
  627. begin
  628. if (paralen>4) or
  629. (parashift<>0) then
  630. begin
  631. paraloc^.size := OS_INT;
  632. paraloc^.def := osuinttype;
  633. end
  634. else
  635. begin
  636. { for 3-byte records aligned in the lower bits of register }
  637. paraloc^.size := OS_32;
  638. paraloc^.def := u32inttype;
  639. end;
  640. end
  641. else
  642. begin
  643. paraloc^.size := paracgsize;
  644. paraloc^.def := locdef;
  645. end;
  646. paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
  647. inc(nextintreg);
  648. dec(paralen, tcgsize2size[paraloc^.size]);
  649. inc(stack_offset, sizeof(pint));
  650. end else if (loc = LOC_FPUREGISTER) and
  651. (nextfloatreg <= RS_F13) then begin
  652. paraloc^.loc := loc;
  653. paraloc^.size := paracgsize;
  654. paraloc^.def := locdef;
  655. paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
  656. { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
  657. which type it is stored in
  658. -- exception: ELFv2 abi when passing aggregate parts in FPRs, because those are
  659. a direct mirror of the memory layout of the aggregate }
  660. if not assigned(alllocdef) then
  661. begin
  662. inc(nextintreg);
  663. inc(stack_offset, tcgsize2size[OS_FLOAT]);
  664. end
  665. else
  666. begin
  667. if (tcgsize2size[paracgsize]=8) or
  668. odd(ord(nextfloatreg)-ord(RS_F1)) then
  669. inc(nextintreg);
  670. inc(stack_offset, tcgsize2size[paracgsize]);
  671. end;
  672. inc(nextfloatreg);
  673. dec(paralen, tcgsize2size[paraloc^.size]);
  674. end else if (loc = LOC_MMREGISTER) then begin
  675. { Altivec not supported }
  676. internalerror(200510192);
  677. end else begin
  678. { either LOC_REFERENCE, or one of the above which must be passed on the
  679. stack because of insufficient registers }
  680. paraloc^.loc := LOC_REFERENCE;
  681. case loc of
  682. LOC_FPUREGISTER:
  683. begin
  684. if assigned(alllocdef) then
  685. paraloc^.size:=def_cgsize(alllocdef)
  686. else
  687. paraloc^.size:=int_float_cgsize(paralen);
  688. case paraloc^.size of
  689. OS_F32: paraloc^.def:=s32floattype;
  690. OS_F64: paraloc^.def:=s64floattype;
  691. else
  692. internalerror(2013060122);
  693. end;
  694. end;
  695. LOC_REGISTER,
  696. LOC_REFERENCE:
  697. begin
  698. paraloc^.size:=int_cgsize(paralen);
  699. paraloc^.def:=get_paraloc_def(paradef, paralen, firstparaloc);
  700. end;
  701. else
  702. internalerror(2006011101);
  703. end;
  704. if (side = callerside) then
  705. paraloc^.reference.index := NR_STACK_POINTER_REG
  706. else begin
  707. { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
  708. paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
  709. { create_paraloc_info_intern might be also called when being outside of
  710. code generation so current_procinfo might be not set }
  711. if assigned(current_procinfo) then
  712. tcpuprocinfo(current_procinfo).needs_frame_pointer := true;
  713. end;
  714. paraloc^.reference.offset := stack_offset;
  715. { align temp contents to next register size }
  716. if not paraaligned then
  717. inc(stack_offset, align(paralen, 8))
  718. else
  719. inc(stack_offset, paralen);
  720. paralen := 0;
  721. end;
  722. firstparaloc:=false;
  723. end;
  724. end;
  725. function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
  726. varargspara: tvarargsparalist): longint;
  727. var
  728. cur_stack_offset: aword;
  729. parasize, l: longint;
  730. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  731. i: integer;
  732. hp: tparavarsym;
  733. paraloc: pcgparalocation;
  734. begin
  735. init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
  736. firstfloatreg := curfloatreg;
  737. result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
  738. curfloatreg, curmmreg, cur_stack_offset, false);
  739. if (p.proccalloption in cstylearrayofconst) then begin
  740. { just continue loading the parameters in the registers }
  741. result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
  742. curfloatreg, curmmreg, cur_stack_offset, true);
  743. { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
  744. if (result < 64) then
  745. result := 64;
  746. end else begin
  747. parasize := cur_stack_offset;
  748. for i := 0 to varargspara.count - 1 do begin
  749. hp := tparavarsym(varargspara[i]);
  750. hp.paraloc[callerside].alignment := 8;
  751. paraloc := hp.paraloc[callerside].add_location;
  752. paraloc^.loc := LOC_REFERENCE;
  753. paraloc^.size := def_cgsize(hp.vardef);
  754. paraloc^.def := hp.vardef;
  755. paraloc^.reference.index := NR_STACK_POINTER_REG;
  756. l := push_size(hp.varspez, hp.vardef, p.proccalloption);
  757. paraloc^.reference.offset := parasize;
  758. parasize := parasize + l;
  759. end;
  760. result := parasize;
  761. end;
  762. if curfloatreg <> firstfloatreg then
  763. include(varargspara.varargsinfo, va_uses_float_reg);
  764. end;
  765. function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
  766. begin
  767. { not supported/required for PowerPC64-linux target }
  768. internalerror(200404182);
  769. result := true;
  770. end;
  771. begin
  772. paramanager := tcpuparamanager.create;
  773. end.