cpupara.pas 28 KB

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