cpupara.pas 23 KB

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