cpupara.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for 680x0
  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. cpubase,
  23. aasmdata,
  24. symconst,symtype,symdef,symsym,
  25. parabase,paramgr,cgbase,cgutils;
  26. type
  27. { Returns the location for the nr-st 32 Bit int parameter
  28. if every parameter before is an 32 Bit int parameter as well
  29. and if the calling conventions for the helper routines of the
  30. rtl are used.
  31. }
  32. tcpuparamanager = class(tparamanager)
  33. function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
  34. function param_use_paraloc(const cgpara:tcgpara):boolean;override;
  35. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  36. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  37. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
  38. procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
  39. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  40. function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override;
  41. function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
  42. function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
  43. function get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;override;
  44. function get_para_align(calloption : tproccalloption):byte;override;
  45. private
  46. function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
  47. function create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  48. var cur_stack_offset: aword):longint;
  49. function create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  50. var cur_stack_offset: aword):longint;
  51. end;
  52. implementation
  53. uses
  54. verbose,
  55. globals,
  56. systems,
  57. cpuinfo,
  58. defutil,
  59. cutils,
  60. hlcgobj;
  61. const
  62. intparasupregs : array[0..1] of tsuperregister = (RS_D0,RS_D1);
  63. addrparasupregs : array[0..1] of tsuperregister = (RS_A0,RS_A1);
  64. floatparasupregs : array[0..1] of tsuperregister = (RS_FP0,RS_FP1);
  65. function tcpuparamanager.get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;
  66. begin
  67. { d0 and d1 are considered volatile }
  68. Result:=VOLATILE_INTREGISTERS;
  69. if target_info.system in [system_m68k_palmos] then
  70. include(result,RS_D2);
  71. end;
  72. function tcpuparamanager.get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;
  73. begin
  74. { a0 and a1 are considered volatile }
  75. Result:=VOLATILE_ADDRESSREGISTERS;
  76. if target_info.system in [system_m68k_palmos] then
  77. include(result,RS_A2);
  78. end;
  79. function tcpuparamanager.get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;
  80. begin
  81. { fp0 and fp1 are considered volatile }
  82. Result:=VOLATILE_FPUREGISTERS;
  83. end;
  84. function tcpuparamanager.get_para_align(calloption : tproccalloption):byte;
  85. begin
  86. result:=target_info.stackalign;
  87. end;
  88. function tcpuparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
  89. var
  90. paraloc : pcgparalocation;
  91. begin
  92. if not assigned(cgpara.location) then
  93. internalerror(200410102);
  94. result:=true;
  95. { All locations are LOC_REFERENCE }
  96. paraloc:=cgpara.location;
  97. while assigned(paraloc) do
  98. begin
  99. if (paraloc^.loc<>LOC_REFERENCE) then
  100. begin
  101. result:=false;
  102. exit;
  103. end;
  104. paraloc:=paraloc^.next;
  105. end;
  106. end;
  107. { TODO: copied from ppc cg, needs work}
  108. function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  109. begin
  110. result:=false;
  111. { var,out,constref always require address }
  112. if varspez in [vs_var,vs_out,vs_constref] then
  113. begin
  114. result:=true;
  115. exit;
  116. end;
  117. case def.typ of
  118. variantdef,
  119. formaldef :
  120. result:=true;
  121. recorddef:
  122. result:=(calloption in [pocall_register]) and
  123. (varspez in [vs_const]);
  124. arraydef:
  125. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  126. is_open_array(def) or
  127. is_array_of_const(def) or
  128. is_array_constructor(def);
  129. objectdef :
  130. result:=is_object(def);
  131. setdef :
  132. result:=not is_smallset(def);
  133. stringdef :
  134. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  135. procvardef :
  136. { Handling of methods must match that of records }
  137. result:=false;
  138. end;
  139. end;
  140. function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
  141. begin
  142. if handle_common_ret_in_param(def,pd,result) then
  143. exit;
  144. case def.typ of
  145. recorddef:
  146. if def.size in [1,2,4] then
  147. begin
  148. result:=false;
  149. exit;
  150. end;
  151. end;
  152. result:=inherited ret_in_param(def,pd);
  153. end;
  154. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  155. var
  156. paraloc : pcgparalocation;
  157. retcgsize : tcgsize;
  158. retregtype : tregistertype;
  159. begin
  160. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  161. exit;
  162. { always use the whole 32 bit register when returning values }
  163. if (side=calleeside) and
  164. (result.intsize>0) and
  165. (result.intsize<sizeof(aint)) then
  166. begin
  167. result.def:=sinttype;
  168. result.intsize:=sizeof(aint);
  169. retcgsize:=OS_SINT;
  170. result.size:=retcgsize;
  171. end;
  172. paraloc:=result.add_location;
  173. { Return in FPU register? }
  174. if not (cs_fp_emulation in current_settings.moduleswitches) and
  175. not (current_settings.fputype=fpu_soft) and (result.def.typ=floatdef) then
  176. begin
  177. paraloc^.loc:=LOC_FPUREGISTER;
  178. paraloc^.register:=NR_FPU_RESULT_REG;
  179. paraloc^.size:=retcgsize;
  180. paraloc^.def:=result.def;
  181. end
  182. else
  183. { Return in register }
  184. begin
  185. if retcgsize in [OS_64,OS_S64] then
  186. begin
  187. { low 32bits }
  188. paraloc^.loc:=LOC_REGISTER;
  189. paraloc^.size:=OS_32;
  190. paraloc^.def:=u32inttype;
  191. if side=callerside then
  192. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  193. else
  194. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  195. { high 32bits }
  196. paraloc:=result.add_location;
  197. paraloc^.loc:=LOC_REGISTER;
  198. paraloc^.size:=OS_32;
  199. paraloc^.def:=u32inttype;
  200. if side=calleeside then
  201. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  202. else
  203. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  204. end
  205. else
  206. begin
  207. paraloc^.loc:=LOC_REGISTER;
  208. paraloc^.size:=retcgsize;
  209. paraloc^.def:=result.def;
  210. { GCC (and SVR4 in general maybe?) requires a pointer result on the A0
  211. register, as well as D0. So we init the result to be A0, then copy
  212. it also to D0 in hlcg.gen_load_loc_function_result. This is not pretty,
  213. but we don't really have an architecture for funcretlocs in two
  214. separate locations.
  215. We also have to figure out a better switch for this, because this is
  216. now compiler and platform specific... (KB) }
  217. if (tprocdef(p).proccalloption in [pocall_syscall,pocall_cdecl,pocall_cppdecl]) and
  218. (target_info.system in [system_m68k_palmos,system_m68k_linux]) and
  219. assigned(result.def) and
  220. (result.def.typ in [stringdef,pointerdef,classrefdef,objectdef,
  221. procvardef,procdef,arraydef,formaldef]) then
  222. retregtype:=R_ADDRESSREGISTER
  223. else
  224. retregtype:=R_INTREGISTER;
  225. if retregtype = R_ADDRESSREGISTER then
  226. begin
  227. if side=callerside then
  228. paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize))
  229. else
  230. paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize));
  231. end
  232. else
  233. begin
  234. if side=callerside then
  235. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  236. else
  237. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  238. end;
  239. end;
  240. end;
  241. end;
  242. function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  243. var
  244. cur_stack_offset: aword;
  245. begin
  246. cur_stack_offset:=0;
  247. case p.proccalloption of
  248. pocall_register :
  249. result:=create_register_paraloc_info(p,side,p.paras,cur_stack_offset);
  250. else
  251. result:=create_stdcall_paraloc_info(p,side,p.paras,cur_stack_offset);
  252. end;
  253. create_funcretloc_info(p,side);
  254. end;
  255. function tcpuparamanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  256. var cur_stack_offset: aword):longint;
  257. var
  258. paraloc : pcgparalocation;
  259. hp : tparavarsym;
  260. paracgsize : tcgsize;
  261. paralen : aint;
  262. paradef : tdef;
  263. i : longint;
  264. firstparaloc : boolean;
  265. paraalign : shortint;
  266. begin
  267. result:=0;
  268. if paras.count=0 then
  269. exit;
  270. paraalign:=get_para_align(p.proccalloption);
  271. for i:=0 to paras.count-1 do
  272. begin
  273. hp:=tparavarsym(paras[i]);
  274. paradef:=hp.vardef;
  275. { syscall for AmigaOS can have already a paraloc set }
  276. if (vo_has_explicit_paraloc in hp.varoptions) then
  277. begin
  278. if not(vo_is_syscall_lib in hp.varoptions) then
  279. internalerror(200506051);
  280. continue;
  281. end;
  282. hp.paraloc[side].reset;
  283. { currently only support C-style array of const }
  284. if (p.proccalloption in cstylearrayofconst) and
  285. is_array_of_const(paradef) then
  286. begin
  287. paraloc:=hp.paraloc[side].add_location;
  288. { hack: the paraloc must be valid, but is not actually used }
  289. paraloc^.loc:=LOC_REGISTER;
  290. paraloc^.register:=NR_D0;
  291. paraloc^.size:=OS_ADDR;
  292. paraloc^.def:=voidpointertype;
  293. break;
  294. end;
  295. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  296. begin
  297. paradef:=cpointerdef.getreusable_no_free(paradef);
  298. paracgsize := OS_ADDR;
  299. paralen := tcgsize2size[OS_ADDR];
  300. end
  301. else
  302. begin
  303. if not is_special_array(paradef) then
  304. paralen:=paradef.size
  305. else
  306. paralen:=tcgsize2size[def_cgsize(paradef)];
  307. paracgsize:=def_cgsize(paradef);
  308. { for things like formaldef }
  309. if (paracgsize=OS_NO) and (paradef.typ<>recorddef) then
  310. begin
  311. paracgsize:=OS_ADDR;
  312. paralen := tcgsize2size[OS_ADDR];
  313. end;
  314. end;
  315. hp.paraloc[side].alignment:=paraalign;
  316. hp.paraloc[side].size:=paracgsize;
  317. hp.paraloc[side].intsize:=paralen;
  318. hp.paraloc[side].def:=paradef;
  319. if (paralen = 0) then
  320. if (paradef.typ = recorddef) then
  321. begin
  322. paraloc:=hp.paraloc[side].add_location;
  323. paraloc^.loc := LOC_VOID;
  324. end
  325. else
  326. internalerror(200506052);
  327. firstparaloc:=true;
  328. { can become < 0 for e.g. 3-byte records }
  329. while (paralen > 0) do
  330. begin
  331. paraloc:=hp.paraloc[side].add_location;
  332. paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
  333. if (not (cs_fp_emulation in current_settings.moduleswitches)) and
  334. (paradef.typ=floatdef) then
  335. paraloc^.size:=int_float_cgsize(paralen)
  336. else
  337. paraloc^.size:=int_cgsize(paralen);
  338. { various m68k based C ABIs used in the Unix world use a register to
  339. return a struct by address. we will probably need some kind of a
  340. switch to support these various ABIs when generating cdecl calls (KB) }
  341. if ((vo_is_funcret in hp.varoptions) and
  342. (tprocdef(p).proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  343. (target_info.system in [system_m68k_linux]) and
  344. (tprocdef(p).returndef.typ = recorddef)) then
  345. begin
  346. paraloc^.loc:=LOC_REGISTER;
  347. paraloc^.register:=NR_M68K_STRUCT_RESULT_REG;
  348. paralen:=0;
  349. continue;
  350. end;
  351. paraloc^.loc:=LOC_REFERENCE;
  352. paraloc^.reference.offset:=cur_stack_offset;
  353. if (side = callerside) then
  354. paraloc^.reference.index:=NR_STACK_POINTER_REG
  355. else
  356. begin
  357. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  358. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  359. end;
  360. { M68K is a big-endian target }
  361. if (paralen<paraalign) then
  362. inc(paraloc^.reference.offset,paraalign-paralen);
  363. inc(cur_stack_offset,align(paralen,target_info.stackalign));
  364. paralen := 0;
  365. firstparaloc:=false;
  366. end;
  367. end;
  368. result:=cur_stack_offset;
  369. end;
  370. function tcpuparamanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  371. var cur_stack_offset: aword): longint;
  372. var
  373. hp : tparavarsym;
  374. paradef : tdef;
  375. paraloc : pcgparalocation;
  376. paracgsize : tcgsize;
  377. i : integer;
  378. l,
  379. paralen,
  380. parareg: longint;
  381. addrparareg: longint;
  382. floatparareg: longint;
  383. varalign : longint;
  384. paraalign : shortint;
  385. pass : byte;
  386. firstparaloc,
  387. pushaddr : boolean;
  388. rt: tregistertype;
  389. begin
  390. result:=0;
  391. if paras.count=0 then
  392. exit;
  393. parareg:=0;
  394. addrparareg:=0;
  395. floatparareg:=0;
  396. paraalign:=get_para_align(p.proccalloption);
  397. { clean up here so we can later detect properly if a parameter has been
  398. assigned or not
  399. }
  400. for i:=0 to paras.count-1 do
  401. tparavarsym(paras[i]).paraloc[side].reset;
  402. { Register parameters are assigned from left to right,
  403. stack parameters from right to left so assign first the
  404. register parameters in a first pass, in the second
  405. pass all unhandled parameters are done }
  406. for pass:=1 to 2 do
  407. begin
  408. if pass=1 then
  409. i:=0
  410. else
  411. i:=paras.count-1;
  412. while true do
  413. begin
  414. hp:=tparavarsym(paras[i]);
  415. paradef:=hp.vardef;
  416. if not(assigned(hp.paraloc[side].location)) then
  417. begin
  418. pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
  419. if pushaddr then
  420. begin
  421. paralen:=sizeof(aint);
  422. paracgsize:=OS_ADDR;
  423. paradef:=cpointerdef.getreusable_no_free(paradef);
  424. end
  425. else
  426. begin
  427. paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  428. paracgsize:=def_cgsize(hp.vardef);
  429. end;
  430. hp.paraloc[side].size:=paracgsize;
  431. hp.paraloc[side].intsize:=paralen;
  432. hp.paraloc[side].Alignment:=paraalign;
  433. hp.paraloc[side].def:=paradef;
  434. {
  435. In case of po_delphi_nested_cc, the parent frame pointer
  436. is also always passed on the stack.
  437. }
  438. rt:=chlcgobj.def2regtyp(paradef);
  439. if (rt=R_FPUREGISTER) and
  440. (floatparareg<=high(floatparasupregs)) and
  441. (not pushaddr) then
  442. begin
  443. if pass=1 then
  444. begin
  445. paraloc:=hp.paraloc[side].add_location;
  446. paraloc^.size:=paracgsize;
  447. paraloc^.def:=paradef;
  448. paraloc^.loc:=LOC_FPUREGISTER;
  449. paraloc^.register:=newreg(R_FPUREGISTER,floatparasupregs[floatparareg],R_SUBWHOLE);
  450. inc(floatparareg);
  451. end;
  452. end
  453. else
  454. if (((rt=R_INTREGISTER) and (parareg<=high(intparasupregs))) or
  455. ((rt=R_ADDRESSREGISTER) and (addrparareg<=high(addrparasupregs)))) and
  456. (paralen<=sizeof(aint)) and
  457. (not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
  458. pushaddr or
  459. is_dynamic_array(hp.vardef)) and
  460. (not(vo_is_parentfp in hp.varoptions) or
  461. not(po_delphi_nested_cc in p.procoptions)) then
  462. begin
  463. if pass=1 then
  464. begin
  465. paraloc:=hp.paraloc[side].add_location;
  466. paraloc^.size:=paracgsize;
  467. paraloc^.def:=paradef;
  468. paraloc^.loc:=LOC_REGISTER;
  469. if (rt=R_ADDRESSREGISTER) and (addrparareg<=high(addrparasupregs)) then
  470. begin
  471. paraloc^.register:=newreg(R_ADDRESSREGISTER,addrparasupregs[addrparareg],R_SUBWHOLE);
  472. inc(addrparareg);
  473. end
  474. else
  475. if (rt=R_INTREGISTER) and (parareg<=high(intparasupregs)) then
  476. begin
  477. paraloc^.register:=newreg(R_INTREGISTER,intparasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
  478. inc(parareg);
  479. end
  480. else
  481. internalerror(2016051801);
  482. end;
  483. end
  484. else
  485. if pass=2 then
  486. begin
  487. { Copy to stack? }
  488. if (use_fixed_stack) or
  489. (paracgsize=OS_NO) then
  490. begin
  491. paraloc:=hp.paraloc[side].add_location;
  492. paraloc^.loc:=LOC_REFERENCE;
  493. paraloc^.size:=paracgsize;
  494. paraloc^.def:=paradef;
  495. if side=callerside then
  496. paraloc^.reference.index:=NR_STACK_POINTER_REG
  497. else
  498. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  499. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  500. paraloc^.reference.offset:=cur_stack_offset;
  501. if (paralen<paraalign) then
  502. inc(paraloc^.reference.offset,paraalign-paralen);
  503. if side=calleeside then
  504. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  505. cur_stack_offset:=align(cur_stack_offset+paralen,varalign);
  506. end
  507. else
  508. begin
  509. if paralen=0 then
  510. internalerror(200501163);
  511. firstparaloc:=true;
  512. while (paralen>0) do
  513. begin
  514. paraloc:=hp.paraloc[side].add_location;
  515. paraloc^.loc:=LOC_REFERENCE;
  516. { Extended and double need a single location }
  517. if (paracgsize in [OS_F64,OS_F32]) then
  518. begin
  519. paraloc^.size:=paracgsize;
  520. paraloc^.def:=paradef;
  521. l:=paralen;
  522. end
  523. else
  524. begin
  525. { We can allocate at maximum 32 bits per location }
  526. if paralen>sizeof(aint) then
  527. begin
  528. l:=sizeof(aint);
  529. paraloc^.def:=uinttype;
  530. end
  531. else
  532. begin
  533. l:=paralen;
  534. paraloc^.def:=get_paraloc_def(paradef,l,firstparaloc);
  535. end;
  536. paraloc^.size:=int_cgsize(l);
  537. end;
  538. if side=callerside then
  539. paraloc^.reference.index:=NR_STACK_POINTER_REG
  540. else
  541. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  542. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  543. paraloc^.reference.offset:=cur_stack_offset;
  544. { M68K is a big-endian target }
  545. if (paralen<paraalign) then
  546. inc(paraloc^.reference.offset,paraalign-paralen);
  547. if side=calleeside then
  548. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  549. cur_stack_offset:=align(cur_stack_offset+l,varalign);
  550. dec(paralen,l);
  551. firstparaloc:=false;
  552. end;
  553. end;
  554. end;
  555. end;
  556. case pass of
  557. 1:
  558. begin
  559. if i=paras.count-1 then
  560. break;
  561. inc(i);
  562. end;
  563. 2:
  564. begin
  565. if i=0 then
  566. break;
  567. dec(i);
  568. end;
  569. end;
  570. end;
  571. end;
  572. result:=cur_stack_offset;
  573. end;
  574. function tcpuparamanager.parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
  575. begin
  576. locreg:=std_regnum_search(lower(s));
  577. result:=(locreg <> NR_NO) and (locreg <> NR_SP);
  578. end;
  579. function tcpuparamanager.parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;
  580. begin
  581. case target_info.system of
  582. system_m68k_amiga:
  583. result:=parse_loc_string_to_register(p.exp_funcretloc, s);
  584. else
  585. internalerror(2005121801);
  586. end;
  587. end;
  588. procedure tcpuparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
  589. begin
  590. { Never a need for temps when value is pushed (calls inside parameters
  591. will simply allocate even more stack space for their parameters) }
  592. if not(use_fixed_stack) then
  593. can_use_final_stack_loc:=true;
  594. inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
  595. end;
  596. function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  597. var
  598. cur_stack_offset: aword;
  599. begin
  600. cur_stack_offset:=0;
  601. result:=create_stdcall_paraloc_info(p,callerside,p.paras,cur_stack_offset);
  602. if (p.proccalloption in cstylearrayofconst) then
  603. { just continue loading the parameters in the registers }
  604. result:=create_stdcall_paraloc_info(p,callerside,varargspara,cur_stack_offset)
  605. else
  606. internalerror(200410231);
  607. end;
  608. begin
  609. paramanager:=tcpuparamanager.create;
  610. end.