cpupara.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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. { register parameter save area begins at 48(r2) }
  270. cur_stack_offset := 48;
  271. curintreg := RS_R3;
  272. curfloatreg := RS_F1;
  273. curmmreg := RS_M2;
  274. end;
  275. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side:
  276. tcallercallee; forcetempdef: tdef): tcgpara;
  277. var
  278. paraloc: pcgparalocation;
  279. retcgsize: tcgsize;
  280. nextfloatreg, nextintreg, nextmmreg: tsuperregister;
  281. stack_offset: aword;
  282. begin
  283. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  284. exit;
  285. { on Darwin and with ELFv2, results are returned the same way as they are
  286. passed }
  287. if target_info.abi in [abi_powerpc_elfv2,abi_powerpc_darwin] then
  288. begin
  289. init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
  290. create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
  291. end
  292. else
  293. begin
  294. { for AIX and ELFv1, the situation is simpler: always just one register }
  295. paraloc:=result.add_location;
  296. { Return in FPU register? }
  297. if result.def.typ=floatdef then
  298. begin
  299. paraloc^.loc:=LOC_FPUREGISTER;
  300. paraloc^.register:=NR_FPU_RESULT_REG;
  301. paraloc^.size:=retcgsize;
  302. paraloc^.def:=result.def;
  303. end
  304. else
  305. { Return in register }
  306. begin
  307. paraloc^.loc:=LOC_REGISTER;
  308. if side=callerside then
  309. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  310. else
  311. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  312. paraloc^.size:=retcgsize;
  313. paraloc^.def:=result.def;
  314. end;
  315. end;
  316. end;
  317. function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side:
  318. tcallercallee): longint;
  319. var
  320. cur_stack_offset: aword;
  321. curintreg, curfloatreg, curmmreg : tsuperregister;
  322. begin
  323. init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
  324. result := create_paraloc_info_intern(p, side, p.paras, curintreg, curfloatreg,
  325. curmmreg, cur_stack_offset, false);
  326. create_funcretloc_info(p, side);
  327. end;
  328. function tcpuparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
  329. tcallercallee; paras: tparalist;
  330. var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
  331. aword; isVararg : boolean): longint;
  332. var
  333. nextintreg, nextfloatreg, nextmmreg : tsuperregister;
  334. i: integer;
  335. hp: tparavarsym;
  336. paraloc: pcgparalocation;
  337. delphi_nestedfp: boolean;
  338. begin
  339. {$IFDEF extdebug}
  340. if po_explicitparaloc in p.procoptions then
  341. internalerror(200411141);
  342. {$ENDIF extdebug}
  343. result := 0;
  344. nextintreg := curintreg;
  345. nextfloatreg := curfloatreg;
  346. nextmmreg := curmmreg;
  347. for i := 0 to paras.count - 1 do begin
  348. hp := tparavarsym(paras[i]);
  349. { Syscall for Morphos can have already a paraloc set; not supported on ppc64 }
  350. if (vo_has_explicit_paraloc in hp.varoptions) then begin
  351. internalerror(200412153);
  352. end;
  353. { currently only support C-style array of const }
  354. if (p.proccalloption in cstylearrayofconst) and
  355. is_array_of_const(hp.vardef) then begin
  356. paraloc := hp.paraloc[side].add_location;
  357. { hack: the paraloc must be valid, but is not actually used }
  358. paraloc^.loc := LOC_REGISTER;
  359. paraloc^.register := NR_R0;
  360. paraloc^.size := OS_ADDR;
  361. paraloc^.def := voidpointertype;
  362. break;
  363. end;
  364. delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
  365. create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
  366. nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
  367. end;
  368. curintreg := nextintreg;
  369. curfloatreg := nextfloatreg;
  370. curmmreg := nextmmreg;
  371. result := cur_stack_offset;
  372. end;
  373. 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);
  374. var
  375. paracgsize: tcgsize;
  376. loc: tcgloc;
  377. paraloc: pcgparalocation;
  378. { def to use for all paralocs if <> nil }
  379. alllocdef,
  380. { def to use for the current paraloc }
  381. locdef,
  382. tmpdef: tdef;
  383. paralen: aint;
  384. parashift: byte;
  385. tailpadding,
  386. firstparaloc,
  387. paraaligned: boolean;
  388. begin
  389. alllocdef:=nil;
  390. locdef:=nil;
  391. parashift := 0;
  392. para.reset;
  393. { should the tail be shifted into the most significant bits? }
  394. tailpadding:=false;
  395. { have we ensured that the next parameter location will be aligned to the
  396. next 8 byte boundary? }
  397. paraaligned:=false;
  398. if push_addr_param(varspez, paradef, p.proccalloption) then begin
  399. paradef := cpointerdef.getreusable_no_free(paradef);
  400. loc := LOC_REGISTER;
  401. paracgsize := OS_ADDR;
  402. paralen := tcgsize2size[OS_ADDR];
  403. end else begin
  404. if not is_special_array(paradef) then
  405. paralen := paradef.size
  406. else
  407. paralen := tcgsize2size[def_cgsize(paradef)];
  408. { default rules:
  409. * integer parameters sign/zero-extended to 64 bit
  410. * floating point register used -> skip equivalent GP register
  411. * floating point parameters passed as is (32/64 bit)
  412. * floating point parameters to variable arguments -> in int registers
  413. * aggregates passed in consecutive integer registers
  414. * all *aggregate* data in integer registers exactly mirrors the data
  415. in memory -> on big endian it's left aligned (passed in most
  416. significant part of the 64 bit word if it's < 64 bit), on little
  417. endian it's right aligned (least significant part of the 64 bit
  418. word)
  419. special rules:
  420. implemented
  421. |
  422. | * AIX/ELFv1/SysV ppc64 ABI (big endian only):
  423. x a) single precision floats are stored in the second word of a 64 bit
  424. location when passed on the stack
  425. x b) aggregate with 1 floating point element passed like a floating
  426. point parameter of the same size
  427. x c) aggregates smaller than 64 bit are aligned in least significant bits
  428. of a single 64bit location (incl. register) (AIX exception: it puts
  429. them in the most significant bits)
  430. * ELFv2 ppc64 ABI:
  431. x a) so-called "homogeneous" aggregates, i.e. struct, arrays, or unions
  432. that (recursively) contain only elements of the same floating-
  433. point or vector type, are passed as if those elements were passed as
  434. separate arguments. This is done for up to 8 such elements.
  435. x b) other than a), it's the same as the AIX ppc64 ABI
  436. * Darwin ppc64 ABI:
  437. - as in the general case, aggregates in registers mirror their place in
  438. memory, so if e.g. a struct starts with a 32 bit integer, it's
  439. placed in the upper 32 bits of a the corresponding register. A plain
  440. 32 bit integer para is however passed in the lower 32 bits, since it
  441. is promoted to a 64 bit int first (see below)
  442. x a) aggregates with sizes 1, 2 and 4 bytes are padded with 0s on the left
  443. (-> aligned in least significant bits of 64 bit word on big endian) to
  444. a multiple of *4 bytes* (when passed by memory, don't occupy 8 bytes)
  445. x b) other aggregates are padded with 0s on the right (-> aligned in most
  446. signifcant bits of 64 bit word of integer register) to a multiple of
  447. *4 bytes*
  448. x c) all floating pointer parameters (not in aggregates) are promoted to
  449. double (doesn't seem to be correct: 8 bytes are reserved in the
  450. stack frame, but the compiler still stores a single in it (in the
  451. lower 4 bytes -- like with SysV a) )
  452. x d) all integer parameters (not in aggregates) are promoted to 64 bit
  453. (x) e) aggregates (incl. arrays) of exactly 16 bytes passed in two integer
  454. registers
  455. f) floats in *structures without unions* are processed per rule c)
  456. (similar for vector fields)
  457. g) other fields in *structures without unions* are processed
  458. recursively according to e) / f) if they are aggragates, and h)
  459. otherwise (i.e, without promotion!)
  460. (x) h) everything else (structures with unions and size<>16, arrays with
  461. size<>16, ...) is passed "normally" in integer registers
  462. }
  463. { ELFv2 a) }
  464. if (target_info.abi=abi_powerpc_elfv2) and
  465. (((paradef.typ=recorddef) and
  466. tcpurecorddef(paradef).has_single_type_elfv2(tmpdef)) or
  467. ((paradef.typ=arraydef) and
  468. tcpuarraydef(paradef).has_single_type_elfv2(tmpdef))) and
  469. (tmpdef.typ=floatdef { or vectordef }) and
  470. (paradef.size<=(8*tmpdef.size)) then
  471. begin
  472. alllocdef:=tmpdef;
  473. loc:=getparaloc(alllocdef);
  474. paracgsize:=def_cgsize(paradef);
  475. end
  476. { AIX/ELFv1 b) }
  477. else if (target_info.abi in [abi_powerpc_aix,abi_powerpc_sysv]) and
  478. (paradef.typ=recorddef) and
  479. tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
  480. (tmpdef.typ=floatdef) then
  481. begin
  482. paradef:=tmpdef;
  483. loc:=getparaloc(paradef);
  484. paracgsize:=def_cgsize(paradef)
  485. end
  486. else if (((paradef.typ=arraydef) and not
  487. is_special_array(paradef)) or
  488. (paradef.typ=recorddef)) then
  489. begin
  490. { should handle Darwin f/g/h) now, but can't model that yet }
  491. { general rule: aggregate data is aligned in the most significant bits
  492. except for ELFv1 c) and Darwin a) }
  493. if (target_info.endian=endian_big) and
  494. ((target_info.abi in [abi_powerpc_aix,abi_powerpc_elfv2]) or
  495. ((target_info.abi=abi_powerpc_sysv) and
  496. (paralen>8)) or
  497. ((target_info.abi=abi_powerpc_darwin) and
  498. not(paralen in [1,2,4]))) then
  499. tailpadding:=true
  500. { if we don't add tailpadding on the caller side, the callee will have
  501. to shift the value in the register before it can store it to memory }
  502. else if (target_info.endian=endian_big) and
  503. (paralen in [3,5,6,7]) then
  504. parashift:=(8-paralen)*8;
  505. { general fallback rule: pass aggregate types in integer registers
  506. without special adjustments (incl. Darwin h) }
  507. loc:=LOC_REGISTER;
  508. paracgsize:=int_cgsize(paralen);
  509. end
  510. else
  511. begin
  512. loc:=getparaloc(paradef);
  513. paracgsize:=def_cgsize(paradef);
  514. { for things like formaldef }
  515. if (paracgsize=OS_NO) then
  516. begin
  517. paracgsize:=OS_ADDR;
  518. paralen:=tcgsize2size[OS_ADDR];
  519. end;
  520. end
  521. end;
  522. { patch FPU values into integer registers if we are processing varargs }
  523. if (isVararg) and (paradef.typ = floatdef) then begin
  524. loc := LOC_REGISTER;
  525. if paracgsize = OS_F64 then
  526. paracgsize := OS_64
  527. else
  528. paracgsize := OS_32;
  529. end;
  530. { AIX/SysV a), Darwin c) -> skip 4 bytes in the stack frame }
  531. if (target_info.endian=endian_big) and
  532. (paradef.typ=floatdef) and
  533. (tfloatdef(paradef).floattype=s32real) and
  534. (nextfloatreg>RS_F13) then
  535. begin
  536. inc(stack_offset,4);
  537. paraaligned:=true;
  538. end;
  539. { Darwin d) }
  540. if (target_info.abi=abi_powerpc_darwin) and
  541. (paradef.typ in [orddef,enumdef]) and
  542. (paralen<8) and
  543. { we don't have to sign/zero extend the lower 8/16/32 bit on the callee
  544. side since it's done on the caller side; however, if the value is
  545. passed via memory, we do have to modify the stack offset since this
  546. is big endian and otherwise we'll load/store the wrong bytes) }
  547. ((side=callerside) or
  548. forceintmem or
  549. (nextintreg>RS_R10)) then
  550. begin
  551. if side=callerside then
  552. begin
  553. paralen:=8;
  554. paradef:=s64inttype;
  555. paracgsize:=OS_S64;
  556. end
  557. else
  558. begin
  559. inc(stack_offset,8-paralen);
  560. paraaligned:=true;
  561. end;
  562. end;
  563. para.alignment := std_param_align;
  564. para.size := paracgsize;
  565. para.intsize := paralen;
  566. para.def := paradef;
  567. if (paralen = 0) then
  568. if (paradef.typ = recorddef) then begin
  569. paraloc := para.add_location;
  570. paraloc^.loc := LOC_VOID;
  571. end else
  572. internalerror(2005011310);
  573. if not assigned(alllocdef) then
  574. locdef:=paradef
  575. else
  576. begin
  577. locdef:=alllocdef;
  578. paracgsize:=def_cgsize(locdef);
  579. end;
  580. firstparaloc:=true;
  581. { can become < 0 for e.g. 3-byte records }
  582. while (paralen > 0) do begin
  583. paraloc := para.add_location;
  584. { In case of po_delphi_nested_cc, the parent frame pointer
  585. is always passed on the stack. }
  586. if (loc = LOC_REGISTER) and
  587. (nextintreg <= RS_R10) and
  588. not forceintmem then begin
  589. paraloc^.loc := loc;
  590. paraloc^.shiftval := parashift;
  591. { make sure we don't lose whether or not the type is signed }
  592. if (paracgsize <> OS_NO) and
  593. (paradef.typ <> orddef) and
  594. not assigned(alllocdef) then
  595. begin
  596. paracgsize := int_cgsize(paralen);
  597. locdef:=get_paraloc_def(paradef, paralen, firstparaloc);
  598. end;
  599. { Partial aggregate data may have to be left-aligned. If so, add tail
  600. padding }
  601. if tailpadding and
  602. (paralen < sizeof(aint)) then
  603. begin
  604. paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
  605. paraloc^.size := OS_INT;
  606. paraloc^.def := u64inttype;
  607. end
  608. else if (paracgsize in [OS_NO, OS_128, OS_S128]) then
  609. begin
  610. if (paralen>4) or
  611. (parashift<>0) then
  612. begin
  613. paraloc^.size := OS_INT;
  614. paraloc^.def := osuinttype;
  615. end
  616. else
  617. begin
  618. { for 3-byte records aligned in the lower bits of register }
  619. paraloc^.size := OS_32;
  620. paraloc^.def := u32inttype;
  621. end;
  622. end
  623. else
  624. begin
  625. paraloc^.size := paracgsize;
  626. paraloc^.def := locdef;
  627. end;
  628. paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
  629. inc(nextintreg);
  630. dec(paralen, tcgsize2size[paraloc^.size]);
  631. inc(stack_offset, sizeof(pint));
  632. end else if (loc = LOC_FPUREGISTER) and
  633. (nextfloatreg <= RS_F13) then begin
  634. paraloc^.loc := loc;
  635. paraloc^.size := paracgsize;
  636. paraloc^.def := locdef;
  637. paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
  638. { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
  639. which type it is stored in }
  640. inc(nextintreg);
  641. inc(nextfloatreg);
  642. dec(paralen, tcgsize2size[paraloc^.size]);
  643. inc(stack_offset, tcgsize2size[OS_FLOAT]);
  644. end else if (loc = LOC_MMREGISTER) then begin
  645. { Altivec not supported }
  646. internalerror(200510192);
  647. end else begin
  648. { either LOC_REFERENCE, or one of the above which must be passed on the
  649. stack because of insufficient registers }
  650. paraloc^.loc := LOC_REFERENCE;
  651. case loc of
  652. LOC_FPUREGISTER:
  653. begin
  654. paraloc^.size:=int_float_cgsize(paralen);
  655. case paraloc^.size of
  656. OS_F32: paraloc^.def:=s32floattype;
  657. OS_F64: paraloc^.def:=s64floattype;
  658. else
  659. internalerror(2013060122);
  660. end;
  661. end;
  662. LOC_REGISTER,
  663. LOC_REFERENCE:
  664. begin
  665. paraloc^.size:=int_cgsize(paralen);
  666. paraloc^.def:=get_paraloc_def(paradef, paralen, firstparaloc);
  667. end;
  668. else
  669. internalerror(2006011101);
  670. end;
  671. if (side = callerside) then
  672. paraloc^.reference.index := NR_STACK_POINTER_REG
  673. else begin
  674. { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
  675. paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
  676. { create_paraloc_info_intern might be also called when being outside of
  677. code generation so current_procinfo might be not set }
  678. if assigned(current_procinfo) then
  679. tcpuprocinfo(current_procinfo).needs_frame_pointer := true;
  680. end;
  681. paraloc^.reference.offset := stack_offset;
  682. { align temp contents to next register size }
  683. if not paraaligned then
  684. inc(stack_offset, align(paralen, 8))
  685. else
  686. inc(stack_offset, paralen);
  687. paralen := 0;
  688. end;
  689. firstparaloc:=false;
  690. end;
  691. end;
  692. function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
  693. varargspara: tvarargsparalist): longint;
  694. var
  695. cur_stack_offset: aword;
  696. parasize, l: longint;
  697. curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
  698. i: integer;
  699. hp: tparavarsym;
  700. paraloc: pcgparalocation;
  701. begin
  702. init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
  703. firstfloatreg := curfloatreg;
  704. result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
  705. curfloatreg, curmmreg, cur_stack_offset, false);
  706. if (p.proccalloption in cstylearrayofconst) then begin
  707. { just continue loading the parameters in the registers }
  708. result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
  709. curfloatreg, curmmreg, cur_stack_offset, true);
  710. { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
  711. if (result < 64) then
  712. result := 64;
  713. end else begin
  714. parasize := cur_stack_offset;
  715. for i := 0 to varargspara.count - 1 do begin
  716. hp := tparavarsym(varargspara[i]);
  717. hp.paraloc[callerside].alignment := 8;
  718. paraloc := hp.paraloc[callerside].add_location;
  719. paraloc^.loc := LOC_REFERENCE;
  720. paraloc^.size := def_cgsize(hp.vardef);
  721. paraloc^.def := hp.vardef;
  722. paraloc^.reference.index := NR_STACK_POINTER_REG;
  723. l := push_size(hp.varspez, hp.vardef, p.proccalloption);
  724. paraloc^.reference.offset := parasize;
  725. parasize := parasize + l;
  726. end;
  727. result := parasize;
  728. end;
  729. if curfloatreg <> firstfloatreg then
  730. include(varargspara.varargsinfo, va_uses_float_reg);
  731. end;
  732. function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
  733. begin
  734. { not supported/required for PowerPC64-linux target }
  735. internalerror(200404182);
  736. result := true;
  737. end;
  738. begin
  739. paramanager := tcpuparamanager.create;
  740. end.