cpupara.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for i8086
  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,cpubase,cgbase,cgutils,
  23. symconst,symtype,symsym,symdef,
  24. parabase,paramgr;
  25. type
  26. ti8086paramanager = class(tparamanager)
  27. function param_use_paraloc(const cgpara:tcgpara):boolean;override;
  28. function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
  29. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  30. function get_para_align(calloption : tproccalloption):byte;override;
  31. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  32. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  33. function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
  34. { Returns the location for the nr-st 16 Bit int parameter
  35. if every parameter before is an 16 Bit int parameter as well
  36. and if the calling conventions for the helper routines of the
  37. rtl are used.
  38. TODO: This allocates 32-bit ints on other CPU architectures. Since
  39. we're small/tiny model only, for now we can get away with allocating
  40. always 16-bit int parameters, but in the future, when we implement
  41. other memory models, this mechanism has to be extended somehow to
  42. support 32-bit addresses on a 16-bit CPU.
  43. }
  44. procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
  45. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  46. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  47. procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
  48. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
  49. private
  50. procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
  51. procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parareg,parasize:longint);
  52. end;
  53. implementation
  54. uses
  55. cutils,
  56. systems,verbose,
  57. symtable,
  58. defutil;
  59. const
  60. parasupregs : array[0..2] of tsuperregister = (RS_AX,RS_DX,RS_CX);
  61. {****************************************************************************
  62. ti8086paramanager
  63. ****************************************************************************}
  64. function ti8086paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
  65. var
  66. paraloc : pcgparalocation;
  67. begin
  68. if not assigned(cgpara.location) then
  69. internalerror(200410102);
  70. result:=true;
  71. { All locations are LOC_REFERENCE }
  72. paraloc:=cgpara.location;
  73. while assigned(paraloc) do
  74. begin
  75. if (paraloc^.loc<>LOC_REFERENCE) then
  76. begin
  77. result:=false;
  78. exit;
  79. end;
  80. paraloc:=paraloc^.next;
  81. end;
  82. end;
  83. function ti8086paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
  84. var
  85. size: longint;
  86. begin
  87. if handle_common_ret_in_param(def,pd,result) then
  88. exit;
  89. if (def.size > 8) and (def.typ <> floatdef) then
  90. begin
  91. result:=true;
  92. exit;
  93. end;
  94. result:=inherited ret_in_param(def,pd);
  95. end;
  96. function ti8086paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  97. begin
  98. result:=false;
  99. { var,out,constref always require address }
  100. if varspez in [vs_var,vs_out,vs_constref] then
  101. begin
  102. result:=true;
  103. exit;
  104. end;
  105. { Only vs_const, vs_value here }
  106. case def.typ of
  107. variantdef :
  108. begin
  109. { variants are small enough to be passed by value except if
  110. required by the windows api
  111. variants are somethings very delphi/windows specific so do it like
  112. windows/delphi (FK)
  113. }
  114. if ((target_info.system=system_i386_win32) and
  115. (calloption in [pocall_stdcall,pocall_safecall]) and
  116. (varspez=vs_const)) or
  117. (calloption=pocall_register) then
  118. result:=true
  119. else
  120. result:=false;
  121. end;
  122. formaldef :
  123. result:=true;
  124. recorddef :
  125. begin
  126. { Delphi stdcall passes records on the stack for call by value }
  127. if (target_info.system=system_i386_win32) and
  128. (calloption=pocall_stdcall) and
  129. (varspez=vs_value) then
  130. result:=false
  131. else
  132. result:=
  133. (not(calloption in (cdecl_pocalls)) and
  134. (def.size>sizeof(aint))) or
  135. (((calloption = pocall_mwpascal) or (target_info.system=system_i386_wince)) and
  136. (varspez=vs_const));
  137. end;
  138. arraydef :
  139. begin
  140. { array of const values are pushed on the stack as
  141. well as dyn. arrays }
  142. if (calloption in cdecl_pocalls) then
  143. result:=not(is_array_of_const(def) or
  144. is_dynamic_array(def))
  145. else
  146. begin
  147. result:=(
  148. (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  149. (def.size>sizeof(aint))
  150. ) or
  151. is_open_array(def) or
  152. is_array_of_const(def) or
  153. is_array_constructor(def);
  154. end;
  155. end;
  156. objectdef :
  157. result:=is_object(def);
  158. stringdef :
  159. result:= (tstringdef(def).stringtype in [st_shortstring,st_longstring]);
  160. procvardef :
  161. result:=not(calloption in cdecl_pocalls) and not tprocvardef(def).is_addressonly;
  162. setdef :
  163. result:=not(calloption in cdecl_pocalls) and (not is_smallset(def));
  164. end;
  165. end;
  166. function ti8086paramanager.get_para_align(calloption : tproccalloption):byte;
  167. begin
  168. result:=std_param_align;
  169. end;
  170. function ti8086paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  171. begin
  172. case calloption of
  173. pocall_internproc :
  174. result:=[];
  175. pocall_register,
  176. pocall_safecall,
  177. pocall_stdcall,
  178. pocall_cdecl,
  179. pocall_cppdecl,
  180. pocall_mwpascal :
  181. result:=[RS_AX,RS_DX,RS_CX];
  182. pocall_far16,
  183. pocall_pascal,
  184. pocall_oldfpccall :
  185. result:=[RS_AX,RS_DX,RS_CX,RS_SI,RS_DI,RS_BX];
  186. else
  187. internalerror(200309071);
  188. end;
  189. end;
  190. function ti8086paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  191. begin
  192. result:=[0..first_fpu_imreg-1];
  193. end;
  194. function ti8086paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
  195. begin
  196. result:=[0..first_mm_imreg-1];
  197. end;
  198. procedure ti8086paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
  199. var
  200. paraloc : pcgparalocation;
  201. def : tdef;
  202. begin
  203. def:=tparavarsym(pd.paras[nr-1]).vardef;
  204. cgpara.reset;
  205. cgpara.size:=def_cgsize(def);
  206. cgpara.intsize:=tcgsize2size[cgpara.size];
  207. cgpara.alignment:=get_para_align(pd.proccalloption);
  208. cgpara.def:=def;
  209. paraloc:=cgpara.add_location;
  210. with paraloc^ do
  211. begin
  212. size:=OS_INT;
  213. if pd.proccalloption=pocall_register then
  214. begin
  215. if (nr<=length(parasupregs)) then
  216. begin
  217. if nr=0 then
  218. internalerror(200309271);
  219. loc:=LOC_REGISTER;
  220. register:=newreg(R_INTREGISTER,parasupregs[nr-1],R_SUBWHOLE);
  221. end
  222. else
  223. begin
  224. loc:=LOC_REFERENCE;
  225. reference.index:=NR_STACK_POINTER_REG;
  226. { the previous parameters didn't take up room in memory }
  227. reference.offset:=sizeof(aint)*(nr-length(parasupregs)-1)
  228. end;
  229. end
  230. else
  231. begin
  232. loc:=LOC_REFERENCE;
  233. reference.index:=NR_STACK_POINTER_REG;
  234. reference.offset:=sizeof(aint)*nr;
  235. end;
  236. end;
  237. end;
  238. function ti8086paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;
  239. var
  240. retcgsize : tcgsize;
  241. paraloc : pcgparalocation;
  242. sym: tfieldvarsym;
  243. usedef: tdef;
  244. handled: boolean;
  245. begin
  246. if not assigned(forcetempdef) then
  247. usedef:=p.returndef
  248. else
  249. usedef:=forcetempdef;
  250. { on darwin/i386, if a record has only one field and that field is a
  251. single or double, it has to be returned like a single/double }
  252. if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
  253. ((usedef.typ=recorddef) or
  254. is_object(usedef)) and
  255. tabstractrecordsymtable(tabstractrecorddef(usedef).symtable).has_single_field(sym) and
  256. (sym.vardef.typ=floatdef) and
  257. (tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
  258. usedef:=sym.vardef;
  259. handled:=set_common_funcretloc_info(p,usedef,retcgsize,result);
  260. { normally forcetempdef is passed straight through to
  261. set_common_funcretloc_info and that one will correctly determine whether
  262. the location is a temporary one, but that doesn't work here because we
  263. sometimes have to change the type }
  264. result.temporary:=assigned(forcetempdef);
  265. if handled then
  266. exit;
  267. { darwin/x86 requires that results < sizeof(aint) are sign/zero
  268. extended to sizeof(aint) }
  269. if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
  270. (side=calleeside) and
  271. (result.intsize>0) and
  272. (result.intsize<sizeof(aint)) then
  273. begin
  274. result.def:=sinttype;
  275. result.intsize:=sizeof(aint);
  276. retcgsize:=OS_SINT;
  277. result.size:=retcgsize;
  278. end;
  279. { Return in FPU register? }
  280. if result.def.typ=floatdef then
  281. begin
  282. paraloc:=result.add_location;
  283. paraloc^.loc:=LOC_FPUREGISTER;
  284. paraloc^.register:=NR_FPU_RESULT_REG;
  285. paraloc^.size:=retcgsize;
  286. end
  287. else
  288. { Return in register }
  289. begin
  290. paraloc:=result.add_location;
  291. paraloc^.loc:=LOC_REGISTER;
  292. if retcgsize in [OS_64,OS_S64] then
  293. begin
  294. { bits 0..15 }
  295. if side=callerside then
  296. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  297. else
  298. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  299. paraloc^.size:=OS_16;
  300. { bits 16..31 }
  301. paraloc:=result.add_location;
  302. paraloc^.loc:=LOC_REGISTER;
  303. if side=callerside then
  304. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  305. else
  306. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  307. paraloc^.size:=OS_16;
  308. { bits 32..47 }
  309. paraloc:=result.add_location;
  310. paraloc^.loc:=LOC_REGISTER;
  311. if side=callerside then
  312. paraloc^.register:=NR_FUNCTION_RESULT64_HIGHER_REG
  313. else
  314. paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
  315. paraloc^.size:=OS_16;
  316. { bits 48..63 }
  317. paraloc:=result.add_location;
  318. paraloc^.loc:=LOC_REGISTER;
  319. if side=callerside then
  320. paraloc^.register:=NR_FUNCTION_RESULT64_HIGHEST_REG
  321. else
  322. paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
  323. paraloc^.size:=OS_16;
  324. end
  325. else if retcgsize in [OS_32,OS_S32] then
  326. begin
  327. { low 16bits }
  328. if side=callerside then
  329. paraloc^.register:=NR_FUNCTION_RESULT32_LOW_REG
  330. else
  331. paraloc^.register:=NR_FUNCTION_RETURN32_LOW_REG;
  332. paraloc^.size:=OS_16;
  333. { high 16bits }
  334. paraloc:=result.add_location;
  335. paraloc^.loc:=LOC_REGISTER;
  336. if side=callerside then
  337. paraloc^.register:=NR_FUNCTION_RESULT32_HIGH_REG
  338. else
  339. paraloc^.register:=NR_FUNCTION_RETURN32_HIGH_REG;
  340. paraloc^.size:=OS_16;
  341. end
  342. else
  343. begin
  344. paraloc^.size:=retcgsize;
  345. if side=callerside then
  346. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  347. else
  348. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  349. end;
  350. end;
  351. end;
  352. procedure ti8086paramanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
  353. var
  354. i : integer;
  355. hp : tparavarsym;
  356. paradef : tdef;
  357. paraloc : pcgparalocation;
  358. l,
  359. paralen,
  360. varalign : longint;
  361. paraalign : shortint;
  362. pushaddr : boolean;
  363. paracgsize : tcgsize;
  364. begin
  365. paraalign:=get_para_align(p.proccalloption);
  366. { we push Flags and CS as long
  367. to cope with the IRETD
  368. and we save 6 register + 4 selectors }
  369. if po_interrupt in p.procoptions then
  370. inc(parasize,8+6*4+4*2);
  371. { Offset is calculated like:
  372. sub esp,12
  373. mov [esp+8],para3
  374. mov [esp+4],para2
  375. mov [esp],para1
  376. call function
  377. That means for pushes the para with the
  378. highest offset (see para3) needs to be pushed first
  379. }
  380. if p.proccalloption in pushleftright_pocalls then
  381. i:=paras.count-1
  382. else
  383. i:=0;
  384. while ((p.proccalloption in pushleftright_pocalls) and (i>=0)) or
  385. (not(p.proccalloption in pushleftright_pocalls) and (i<=paras.count-1)) do
  386. begin
  387. hp:=tparavarsym(paras[i]);
  388. paradef:=hp.vardef;
  389. pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
  390. if pushaddr then
  391. begin
  392. paralen:=sizeof(aint);
  393. paracgsize:=OS_ADDR;
  394. paradef:=getpointerdef(paradef);
  395. end
  396. else
  397. begin
  398. paralen:=push_size(hp.varspez,paradef,p.proccalloption);
  399. { darwin/x86 requires that parameters < sizeof(aint) are sign/ }
  400. { zero extended to sizeof(aint) }
  401. if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
  402. (side = callerside) and
  403. (paralen > 0) and
  404. (paralen < sizeof(aint)) then
  405. begin
  406. paralen:=sizeof(aint);
  407. paracgsize:=OS_SINT;
  408. paradef:=sinttype;
  409. end
  410. else
  411. paracgsize:=def_cgsize(paradef);
  412. end;
  413. hp.paraloc[side].reset;
  414. hp.paraloc[side].size:=paracgsize;
  415. hp.paraloc[side].intsize:=paralen;
  416. hp.paraloc[side].def:=paradef;
  417. hp.paraloc[side].Alignment:=paraalign;
  418. { Copy to stack? }
  419. if (paracgsize=OS_NO) or
  420. (use_fixed_stack) then
  421. begin
  422. paraloc:=hp.paraloc[side].add_location;
  423. paraloc^.loc:=LOC_REFERENCE;
  424. paraloc^.size:=paracgsize;
  425. if side=callerside then
  426. paraloc^.reference.index:=NR_STACK_POINTER_REG
  427. else
  428. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  429. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  430. { don't let push_size return 16, because then we can }
  431. { read past the end of the heap since the value is only }
  432. { 10 bytes long (JM) }
  433. if (paracgsize = OS_F80) and
  434. (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
  435. paralen:=16;
  436. paraloc^.reference.offset:=parasize;
  437. if side=calleeside then
  438. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  439. parasize:=align(parasize+paralen,varalign);
  440. end
  441. else
  442. begin
  443. if paralen=0 then
  444. internalerror(200501163);
  445. while (paralen>0) do
  446. begin
  447. paraloc:=hp.paraloc[side].add_location;
  448. paraloc^.loc:=LOC_REFERENCE;
  449. { single and double need a single location }
  450. if (paracgsize in [OS_F64,OS_F32]) then
  451. begin
  452. paraloc^.size:=paracgsize;
  453. l:=paralen;
  454. end
  455. else
  456. begin
  457. { We can allocate at maximum 32 bits per location }
  458. if paralen>sizeof(aint) then
  459. l:=sizeof(aint)
  460. else
  461. l:=paralen;
  462. paraloc^.size:=int_cgsize(l);
  463. end;
  464. if (side=callerside) or
  465. (po_nostackframe in p.procoptions) then
  466. paraloc^.reference.index:=NR_STACK_POINTER_REG
  467. else
  468. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  469. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  470. paraloc^.reference.offset:=parasize;
  471. if side=calleeside then
  472. if not(po_nostackframe in p.procoptions) then
  473. inc(paraloc^.reference.offset,target_info.first_parm_offset)
  474. else
  475. { return addres }
  476. inc(paraloc^.reference.offset,4);
  477. parasize:=align(parasize+l,varalign);
  478. dec(paralen,l);
  479. end;
  480. end;
  481. if p.proccalloption in pushleftright_pocalls then
  482. dec(i)
  483. else
  484. inc(i);
  485. end;
  486. end;
  487. procedure ti8086paramanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  488. var parareg,parasize:longint);
  489. var
  490. hp : tparavarsym;
  491. paradef : tdef;
  492. paraloc : pcgparalocation;
  493. paracgsize : tcgsize;
  494. i : integer;
  495. l,
  496. paralen,
  497. varalign : longint;
  498. pushaddr : boolean;
  499. paraalign : shortint;
  500. pass : byte;
  501. begin
  502. if paras.count=0 then
  503. exit;
  504. paraalign:=get_para_align(p.proccalloption);
  505. { clean up here so we can later detect properly if a parameter has been
  506. assigned or not
  507. }
  508. for i:=0 to paras.count-1 do
  509. tparavarsym(paras[i]).paraloc[side].reset;
  510. { Register parameters are assigned from left to right,
  511. stack parameters from right to left so assign first the
  512. register parameters in a first pass, in the second
  513. pass all unhandled parameters are done }
  514. for pass:=1 to 2 do
  515. begin
  516. if pass=1 then
  517. i:=0
  518. else
  519. i:=paras.count-1;
  520. while true do
  521. begin
  522. hp:=tparavarsym(paras[i]);
  523. paradef:=hp.vardef;
  524. if not(assigned(hp.paraloc[side].location)) then
  525. begin
  526. pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
  527. if pushaddr then
  528. begin
  529. paralen:=sizeof(aint);
  530. paracgsize:=OS_ADDR;
  531. paradef:=getpointerdef(paradef);
  532. end
  533. else
  534. begin
  535. paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  536. paracgsize:=def_cgsize(hp.vardef);
  537. end;
  538. hp.paraloc[side].size:=paracgsize;
  539. hp.paraloc[side].intsize:=paralen;
  540. hp.paraloc[side].Alignment:=paraalign;
  541. hp.paraloc[side].def:=paradef;
  542. {
  543. EAX
  544. EDX
  545. ECX
  546. Stack
  547. Stack
  548. 64bit values,floats,arrays and records are always
  549. on the stack.
  550. In case of po_delphi_nested_cc, the parent frame pointer
  551. is also always passed on the stack.
  552. }
  553. if (parareg<=high(parasupregs)) and
  554. (paralen<=sizeof(aint)) and
  555. (not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
  556. pushaddr) and
  557. (not(vo_is_parentfp in hp.varoptions) or
  558. not(po_delphi_nested_cc in p.procoptions)) then
  559. begin
  560. if pass=1 then
  561. begin
  562. paraloc:=hp.paraloc[side].add_location;
  563. paraloc^.size:=paracgsize;
  564. paraloc^.loc:=LOC_REGISTER;
  565. paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
  566. inc(parareg);
  567. end;
  568. end
  569. else
  570. if pass=2 then
  571. begin
  572. { Copy to stack? }
  573. if (use_fixed_stack) or
  574. (paracgsize=OS_NO) then
  575. begin
  576. paraloc:=hp.paraloc[side].add_location;
  577. paraloc^.loc:=LOC_REFERENCE;
  578. paraloc^.size:=paracgsize;
  579. if side=callerside then
  580. paraloc^.reference.index:=NR_STACK_POINTER_REG
  581. else
  582. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  583. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  584. paraloc^.reference.offset:=parasize;
  585. if side=calleeside then
  586. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  587. parasize:=align(parasize+paralen,varalign);
  588. end
  589. else
  590. begin
  591. if paralen=0 then
  592. internalerror(200501163);
  593. while (paralen>0) do
  594. begin
  595. paraloc:=hp.paraloc[side].add_location;
  596. paraloc^.loc:=LOC_REFERENCE;
  597. { Extended and double need a single location }
  598. if (paracgsize in [OS_F64,OS_F32]) then
  599. begin
  600. paraloc^.size:=paracgsize;
  601. l:=paralen;
  602. end
  603. else
  604. begin
  605. { We can allocate at maximum 32 bits per location }
  606. if paralen>sizeof(aint) then
  607. l:=sizeof(aint)
  608. else
  609. l:=paralen;
  610. paraloc^.size:=int_cgsize(l);
  611. end;
  612. if side=callerside then
  613. paraloc^.reference.index:=NR_STACK_POINTER_REG
  614. else
  615. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  616. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  617. paraloc^.reference.offset:=parasize;
  618. if side=calleeside then
  619. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  620. parasize:=align(parasize+l,varalign);
  621. dec(paralen,l);
  622. end;
  623. end;
  624. end;
  625. end;
  626. case pass of
  627. 1:
  628. begin
  629. if i=paras.count-1 then
  630. break;
  631. inc(i);
  632. end;
  633. 2:
  634. begin
  635. if i=0 then
  636. break;
  637. dec(i);
  638. end;
  639. end;
  640. end;
  641. end;
  642. end;
  643. function ti8086paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  644. var
  645. parasize,
  646. parareg : longint;
  647. begin
  648. parasize:=0;
  649. parareg:=0;
  650. case p.proccalloption of
  651. pocall_register :
  652. create_register_paraloc_info(p,side,p.paras,parareg,parasize);
  653. pocall_internproc :
  654. begin
  655. { Use default calling }
  656. {$warnings off}
  657. if (pocall_default=pocall_register) then
  658. create_register_paraloc_info(p,side,p.paras,parareg,parasize)
  659. else
  660. create_stdcall_paraloc_info(p,side,p.paras,parasize);
  661. {$warnings on}
  662. end;
  663. else
  664. create_stdcall_paraloc_info(p,side,p.paras,parasize);
  665. end;
  666. create_funcretloc_info(p,side);
  667. result:=parasize;
  668. end;
  669. function ti8086paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  670. var
  671. parasize : longint;
  672. begin
  673. parasize:=0;
  674. { calculate the registers for the normal parameters }
  675. create_stdcall_paraloc_info(p,callerside,p.paras,parasize);
  676. { append the varargs }
  677. create_stdcall_paraloc_info(p,callerside,varargspara,parasize);
  678. result:=parasize;
  679. end;
  680. procedure ti8086paramanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
  681. begin
  682. { Never a need for temps when value is pushed (calls inside parameters
  683. will simply allocate even more stack space for their parameters) }
  684. if not(use_fixed_stack) then
  685. can_use_final_stack_loc:=true;
  686. inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
  687. end;
  688. begin
  689. paramanager:=ti8086paramanager.create;
  690. end.