cpupara.pas 27 KB

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