cpupara.pas 28 KB

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