cgcpu.pas 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
  1. {
  2. Copyright (c) 1998-2002 by the FPC team
  3. This unit implements the code generator for the 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. {DEFINE DEBUG_CHARLIE}
  18. {$IFNDEF DEBUG_CHARLIE}
  19. {$WARNINGS OFF}
  20. {$ENDIF}
  21. unit cgcpu;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cgbase,cgobj,globtype,
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  27. cpubase,cpuinfo,
  28. parabase,cpupara,
  29. node,symconst,symtype,symdef,
  30. cgutils,cg64f32;
  31. type
  32. tcg68k = class(tcg)
  33. procedure init_register_allocators;override;
  34. procedure done_register_allocators;override;
  35. procedure a_param_reg(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
  36. procedure a_param_const(list : TAsmList;size : tcgsize;a : aint;const cgpara : tcgpara);override;
  37. procedure a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
  38. procedure a_paramaddr_ref(list : TAsmList;const r : treference;const cgpara : tcgpara);override;
  39. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  40. procedure a_call_reg(list : TAsmList;reg : tregister);override;
  41. procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : aint;register : tregister);override;
  42. procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : aint;const ref : treference);override;
  43. procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
  44. procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);override;
  45. procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
  46. procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
  47. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  48. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  49. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  50. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  51. procedure a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle); override;
  52. procedure a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
  53. procedure a_loadmm_reg_ref(list: TAsmList;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
  54. procedure a_parammm_reg(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle); override;
  55. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: aint; reg: TRegister); override;
  56. // procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference); override;
  57. procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); override;
  58. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  59. l : tasmlabel);override;
  60. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  61. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  62. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  63. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); override;
  64. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
  65. { generates overflow checking code for a node }
  66. procedure g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef); override;
  67. procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);override;
  68. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  69. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
  70. // procedure g_restore_frame_pointer(list : TAsmList);override;
  71. // procedure g_return_from_proc(list : TAsmList;parasize : aint);override;
  72. procedure g_restore_registers(list:TAsmList);override;
  73. procedure g_save_registers(list:TAsmList);override;
  74. // procedure g_save_all_registers(list : TAsmList);override;
  75. // procedure g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);override;
  76. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  77. protected
  78. function fixref(list: TAsmList; var ref: treference): boolean;
  79. private
  80. { # Sign or zero extend the register to a full 32-bit value.
  81. The new value is left in the same register.
  82. }
  83. procedure sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
  84. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  85. end;
  86. tcg64f68k = class(tcg64f32)
  87. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG; size: tcgsize; regsrc,regdst : tregister64);override;
  88. procedure a_op64_const_reg(list : TAsmList;op:TOpCG; size: tcgsize; value : int64;regdst : tregister64);override;
  89. end;
  90. { This function returns true if the reference+offset is valid.
  91. Otherwise extra code must be generated to solve the reference.
  92. On the m68k, this verifies that the reference is valid
  93. (e.g : if index register is used, then the max displacement
  94. is 256 bytes, if only base is used, then max displacement
  95. is 32K
  96. }
  97. function isvalidrefoffset(const ref: treference): boolean;
  98. const
  99. TCGSize2OpSize: Array[tcgsize] of topsize =
  100. (S_NO,S_B,S_W,S_L,S_L,S_NO,S_B,S_W,S_L,S_L,S_NO,
  101. S_FS,S_FD,S_FX,S_NO,S_NO,
  102. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  103. procedure create_codegen;
  104. implementation
  105. uses
  106. globals,verbose,systems,cutils,
  107. symsym,defutil,paramgr,procinfo,
  108. rgobj,tgobj,rgcpu,fmodule;
  109. const
  110. { opcode table lookup }
  111. topcg2tasmop: Array[topcg] of tasmop =
  112. (
  113. A_NONE,
  114. A_MOVE,
  115. A_ADD,
  116. A_AND,
  117. A_DIVU,
  118. A_DIVS,
  119. A_MULS,
  120. A_MULU,
  121. A_NEG,
  122. A_NOT,
  123. A_OR,
  124. A_ASR,
  125. A_LSL,
  126. A_LSR,
  127. A_SUB,
  128. A_EOR,
  129. A_NONE,
  130. A_NONE
  131. );
  132. TOpCmp2AsmCond: Array[topcmp] of TAsmCond =
  133. (
  134. C_NONE,
  135. C_EQ,
  136. C_GT,
  137. C_LT,
  138. C_GE,
  139. C_LE,
  140. C_NE,
  141. C_LS,
  142. C_CS,
  143. C_CC,
  144. C_HI
  145. );
  146. function isvalidrefoffset(const ref: treference): boolean;
  147. begin
  148. isvalidrefoffset := true;
  149. if ref.index <> NR_NO then
  150. begin
  151. if ref.base <> NR_NO then
  152. internalerror(20020814);
  153. if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
  154. isvalidrefoffset := false
  155. end
  156. else
  157. begin
  158. if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
  159. isvalidrefoffset := false;
  160. end;
  161. end;
  162. {****************************************************************************}
  163. { TCG68K }
  164. {****************************************************************************}
  165. function use_push(const cgpara:tcgpara):boolean;
  166. begin
  167. result:=(not use_fixed_stack) and
  168. assigned(cgpara.location) and
  169. (cgpara.location^.loc=LOC_REFERENCE) and
  170. (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
  171. end;
  172. procedure tcg68k.init_register_allocators;
  173. begin
  174. inherited init_register_allocators;
  175. rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
  176. [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7],
  177. first_int_imreg,[]);
  178. rg[R_ADDRESSREGISTER]:=trgcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
  179. [RS_A0,RS_A1,RS_A2,RS_A3,RS_A4,RS_A5,RS_A6],
  180. first_addr_imreg,[]);
  181. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  182. [RS_FP0,RS_FP1,RS_FP2,RS_FP3,RS_FP4,RS_FP5,RS_FP6,RS_FP7],
  183. first_fpu_imreg,[]);
  184. end;
  185. procedure tcg68k.done_register_allocators;
  186. begin
  187. rg[R_INTREGISTER].free;
  188. rg[R_FPUREGISTER].free;
  189. rg[R_ADDRESSREGISTER].free;
  190. inherited done_register_allocators;
  191. end;
  192. procedure tcg68k.a_param_reg(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  193. var
  194. pushsize : tcgsize;
  195. ref : treference;
  196. begin
  197. {$ifdef DEBUG_CHARLIE}
  198. // writeln('a_param_reg');
  199. {$endif DEBUG_CHARLIE}
  200. { it's probably necessary to port this from x86 later, or provide an m68k solution (KB) }
  201. { TODO: FIX ME! check_register_size()}
  202. // check_register_size(size,r);
  203. if use_push(cgpara) then
  204. begin
  205. cgpara.check_simple_location;
  206. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  207. pushsize:=cgpara.location^.size
  208. else
  209. pushsize:=int_cgsize(cgpara.alignment);
  210. reference_reset_base(ref, NR_STACK_POINTER_REG, 0, cgpara.alignment);
  211. ref.direction := dir_dec;
  212. list.concat(taicpu.op_reg_ref(A_MOVE,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize),ref));
  213. end
  214. else
  215. inherited a_param_reg(list,size,r,cgpara);
  216. end;
  217. procedure tcg68k.a_param_const(list : TAsmList;size : tcgsize;a : aint;const cgpara : tcgpara);
  218. var
  219. pushsize : tcgsize;
  220. ref : treference;
  221. begin
  222. {$ifdef DEBUG_CHARLIE}
  223. // writeln('a_param_const');
  224. {$endif DEBUG_CHARLIE}
  225. if use_push(cgpara) then
  226. begin
  227. cgpara.check_simple_location;
  228. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  229. pushsize:=cgpara.location^.size
  230. else
  231. pushsize:=int_cgsize(cgpara.alignment);
  232. reference_reset_base(ref, NR_STACK_POINTER_REG, 0, cgpara.alignment);
  233. ref.direction := dir_dec;
  234. list.concat(taicpu.op_const_ref(A_MOVE,tcgsize2opsize[pushsize],a,ref));
  235. end
  236. else
  237. inherited a_param_const(list,size,a,cgpara);
  238. end;
  239. procedure tcg68k.a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
  240. procedure pushdata(paraloc:pcgparalocation;ofs:aint);
  241. var
  242. pushsize : tcgsize;
  243. tmpreg : tregister;
  244. href : treference;
  245. ref : treference;
  246. begin
  247. if not assigned(paraloc) then
  248. exit;
  249. { TODO: FIX ME!!! this also triggers location bug }
  250. {if (paraloc^.loc<>LOC_REFERENCE) or
  251. (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  252. (tcgsize2size[paraloc^.size]>sizeof(aint)) then
  253. internalerror(200501162);}
  254. { Pushes are needed in reverse order, add the size of the
  255. current location to the offset where to load from. This
  256. prevents wrong calculations for the last location when
  257. the size is not a power of 2 }
  258. if assigned(paraloc^.next) then
  259. pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  260. { Push the data starting at ofs }
  261. href:=r;
  262. inc(href.offset,ofs);
  263. if tcgsize2size[paraloc^.size]>cgpara.alignment then
  264. pushsize:=paraloc^.size
  265. else
  266. pushsize:=int_cgsize(cgpara.alignment);
  267. reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[paraloc^.size]);
  268. ref.direction := dir_dec;
  269. if tcgsize2size[paraloc^.size]<cgpara.alignment then
  270. begin
  271. tmpreg:=getintregister(list,pushsize);
  272. a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  273. list.concat(taicpu.op_reg_ref(A_MOVE,tcgsize2opsize[pushsize],tmpreg,ref));
  274. end
  275. else
  276. list.concat(taicpu.op_ref_ref(A_MOVE,tcgsize2opsize[pushsize],href,ref));
  277. end;
  278. var
  279. len : aint;
  280. href : treference;
  281. begin
  282. {$ifdef DEBUG_CHARLIE}
  283. // writeln('a_param_ref');
  284. {$endif DEBUG_CHARLIE}
  285. { cgpara.size=OS_NO requires a copy on the stack }
  286. if use_push(cgpara) then
  287. begin
  288. { Record copy? }
  289. if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
  290. begin
  291. cgpara.check_simple_location;
  292. len:=align(cgpara.intsize,cgpara.alignment);
  293. g_stackpointer_alloc(list,len);
  294. reference_reset_base(href,NR_STACK_POINTER_REG,0,cgpara.alignment);
  295. g_concatcopy(list,r,href,len);
  296. end
  297. else
  298. begin
  299. if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  300. internalerror(200501161);
  301. { We need to push the data in reverse order,
  302. therefor we use a recursive algorithm }
  303. pushdata(cgpara.location,0);
  304. end
  305. end
  306. else
  307. inherited a_param_ref(list,size,r,cgpara);
  308. end;
  309. procedure tcg68k.a_paramaddr_ref(list : TAsmList;const r : treference;const cgpara : tcgpara);
  310. var
  311. tmpreg : tregister;
  312. opsize : topsize;
  313. begin
  314. {$ifdef DEBUG_CHARLIE}
  315. // writeln('a_paramaddr_ref');
  316. {$endif DEBUG_CHARLIE}
  317. with r do
  318. begin
  319. { i suppose this is not required for m68k (KB) }
  320. // if (segment<>NR_NO) then
  321. // cgmessage(cg_e_cant_use_far_pointer_there);
  322. if not use_push(cgpara) then
  323. begin
  324. cgpara.check_simple_location;
  325. opsize:=tcgsize2opsize[OS_ADDR];
  326. if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
  327. begin
  328. if assigned(symbol) then
  329. // list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
  330. else;
  331. // list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
  332. end
  333. else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
  334. (offset=0) and (scalefactor=0) and (symbol=nil) then
  335. // list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
  336. else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
  337. (offset=0) and (symbol=nil) then
  338. // list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
  339. else
  340. begin
  341. tmpreg:=getaddressregister(list);
  342. a_loadaddr_ref_reg(list,r,tmpreg);
  343. // list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  344. end;
  345. end
  346. else
  347. inherited a_paramaddr_ref(list,r,cgpara);
  348. end;
  349. end;
  350. function tcg68k.fixref(list: TAsmList; var ref: treference): boolean;
  351. begin
  352. result:=false;
  353. { The Coldfire and MC68020+ have extended
  354. addressing capabilities with a 32-bit
  355. displacement.
  356. }
  357. if (current_settings.cputype<>cpu_MC68000) then
  358. exit;
  359. if (ref.base<>NR_NO) then
  360. begin
  361. if (ref.index <> NR_NO) and assigned(ref.symbol) then
  362. internalerror(20020814);
  363. { base + reg }
  364. if ref.index <> NR_NO then
  365. begin
  366. { base + reg + offset }
  367. if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
  368. begin
  369. list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
  370. fixref := true;
  371. ref.offset := 0;
  372. exit;
  373. end;
  374. end
  375. else
  376. { base + offset }
  377. if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
  378. begin
  379. list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
  380. fixref := true;
  381. ref.offset := 0;
  382. exit;
  383. end;
  384. end;
  385. end;
  386. procedure tcg68k.a_call_name(list : TAsmList;const s : string; weak: boolean);
  387. var
  388. sym: tasmsymbol;
  389. begin
  390. if not(weak) then
  391. sym:=current_asmdata.RefAsmSymbol(s)
  392. else
  393. sym:=current_asmdata.WeakRefAsmSymbol(s);
  394. list.concat(taicpu.op_sym(A_JSR,S_NO,current_asmdata.RefAsmSymbol(s)));
  395. end;
  396. procedure tcg68k.a_call_reg(list : TAsmList;reg: tregister);
  397. var
  398. tmpref : treference;
  399. tmpreg : tregister;
  400. begin
  401. {$ifdef DEBUG_CHARLIE}
  402. list.concat(tai_comment.create(strpnew('a_call_reg')));
  403. {$endif}
  404. if isaddressregister(reg) then
  405. begin
  406. { if we have an address register, we can jump to the address directly }
  407. reference_reset_base(tmpref,reg,0,4);
  408. end
  409. else
  410. begin
  411. { if we have a data register, we need to move it to an address register first }
  412. tmpreg:=getaddressregister(list);
  413. reference_reset_base(tmpref,tmpreg,0,4);
  414. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,tmpreg));
  415. end;
  416. list.concat(taicpu.op_ref(A_JSR,S_NO,tmpref));
  417. end;
  418. procedure tcg68k.a_load_const_reg(list : TAsmList;size : tcgsize;a : aint;register : tregister);
  419. begin
  420. {$ifdef DEBUG_CHARLIE}
  421. // writeln('a_load_const_reg');
  422. {$endif DEBUG_CHARLIE}
  423. if isaddressregister(register) then
  424. begin
  425. list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
  426. end
  427. else
  428. if a = 0 then
  429. list.concat(taicpu.op_reg(A_CLR,S_L,register))
  430. else
  431. begin
  432. if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
  433. list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,longint(a),register))
  434. else
  435. list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
  436. end;
  437. end;
  438. procedure tcg68k.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : aint;const ref : treference);
  439. begin
  440. {$ifdef DEBUG_CHARLIE}
  441. list.concat(tai_comment.create(strpnew('a_load_const_ref')));
  442. {$endif DEBUG_CHARLIE}
  443. list.concat(taicpu.op_const_ref(A_MOVE,S_L,longint(a),ref));
  444. end;
  445. procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
  446. var
  447. href : treference;
  448. begin
  449. href := ref;
  450. fixref(list,href);
  451. {$ifdef DEBUG_CHARLIE}
  452. list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
  453. {$endif DEBUG_CHARLIE}
  454. { move to destination reference }
  455. list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
  456. end;
  457. procedure tcg68k.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
  458. var
  459. aref: treference;
  460. bref: treference;
  461. begin
  462. aref := sref;
  463. bref := dref;
  464. fixref(list,aref);
  465. fixref(list,bref);
  466. {$ifdef DEBUG_CHARLIE}
  467. // writeln('a_load_ref_ref');
  468. {$endif DEBUG_CHARLIE}
  469. list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],aref,bref));
  470. end;
  471. procedure tcg68k.a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
  472. begin
  473. { move to destination register }
  474. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2));
  475. { zero/sign extend register to 32-bit }
  476. sign_extend(list, fromsize, reg2);
  477. end;
  478. procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
  479. var
  480. href : treference;
  481. begin
  482. href := ref;
  483. fixref(list,href);
  484. list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
  485. { extend the value in the register }
  486. sign_extend(list, tosize, register);
  487. end;
  488. procedure tcg68k.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  489. var
  490. href : treference;
  491. // p: pointer;
  492. begin
  493. { TODO: FIX ME!!! take a look on this mess again...}
  494. // if getregtype(r)=R_ADDRESSREGISTER then
  495. // begin
  496. // writeln('address reg?!?');
  497. // p:=nil; dword(p^):=0; {DEBUG CODE... :D )
  498. // internalerror(2002072901);
  499. // end;
  500. href:=ref;
  501. fixref(list, href);
  502. list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,r));
  503. end;
  504. procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  505. begin
  506. { in emulation mode, only 32-bit single is supported }
  507. if cs_fp_emulation in current_settings.moduleswitches then
  508. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
  509. else
  510. list.concat(taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2));
  511. end;
  512. procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  513. var
  514. opsize : topsize;
  515. href : treference;
  516. tmpreg : tregister;
  517. begin
  518. opsize := tcgsize2opsize[fromsize];
  519. { extended is not supported, since it is not available on Coldfire }
  520. if opsize = S_FX then
  521. internalerror(20020729);
  522. href := ref;
  523. fixref(list,href);
  524. { in emulation mode, only 32-bit single is supported }
  525. if cs_fp_emulation in current_settings.moduleswitches then
  526. list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
  527. else
  528. begin
  529. list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
  530. if (tosize < fromsize) then
  531. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  532. end;
  533. end;
  534. procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
  535. var
  536. opsize : topsize;
  537. begin
  538. opsize := tcgsize2opsize[tosize];
  539. { extended is not supported, since it is not available on Coldfire }
  540. if opsize = S_FX then
  541. internalerror(20020729);
  542. { in emulation mode, only 32-bit single is supported }
  543. if cs_fp_emulation in current_settings.moduleswitches then
  544. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
  545. else
  546. list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
  547. end;
  548. procedure tcg68k.a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);
  549. begin
  550. internalerror(20020729);
  551. end;
  552. procedure tcg68k.a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle);
  553. begin
  554. internalerror(20020729);
  555. end;
  556. procedure tcg68k.a_loadmm_reg_ref(list: TAsmList;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle);
  557. begin
  558. internalerror(20020729);
  559. end;
  560. procedure tcg68k.a_parammm_reg(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle);
  561. begin
  562. internalerror(20020729);
  563. end;
  564. procedure tcg68k.a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: aint; reg: TRegister);
  565. var
  566. scratch_reg : tregister;
  567. scratch_reg2: tregister;
  568. opcode : tasmop;
  569. r,r2 : Tregister;
  570. begin
  571. optimize_op_const(op, a);
  572. opcode := topcg2tasmop[op];
  573. case op of
  574. OP_NONE :
  575. begin
  576. { Opcode is optimized away }
  577. end;
  578. OP_MOVE :
  579. begin
  580. { Optimized, replaced with a simple load }
  581. a_load_const_reg(list,size,a,reg);
  582. end;
  583. OP_ADD :
  584. begin
  585. if (a >= 1) and (a <= 8) then
  586. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,a, reg))
  587. else
  588. begin
  589. { all others, including coldfire }
  590. list.concat(taicpu.op_const_reg(A_ADD,S_L,a, reg));
  591. end;
  592. end;
  593. OP_AND,
  594. OP_OR:
  595. begin
  596. list.concat(taicpu.op_const_reg(topcg2tasmop[op],S_L,longint(a), reg));
  597. end;
  598. OP_DIV :
  599. begin
  600. internalerror(20020816);
  601. end;
  602. OP_IDIV :
  603. begin
  604. internalerror(20020816);
  605. end;
  606. OP_IMUL :
  607. begin
  608. if current_settings.cputype = cpu_MC68000 then
  609. begin
  610. r:=NR_D0;
  611. r2:=NR_D1;
  612. cg.getcpuregister(list,NR_D0);
  613. cg.getcpuregister(list,NR_D1);
  614. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
  615. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
  616. cg.a_call_name(list,'FPC_MUL_LONGINT',false);
  617. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
  618. cg.ungetcpuregister(list,r);
  619. cg.ungetcpuregister(list,r2);
  620. end
  621. else
  622. begin
  623. if (isaddressregister(reg)) then
  624. begin
  625. scratch_reg := getintregister(list,OS_INT);
  626. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  627. list.concat(taicpu.op_const_reg(A_MULS,S_L,a,scratch_reg));
  628. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  629. end
  630. else
  631. list.concat(taicpu.op_const_reg(A_MULS,S_L,a,reg));
  632. end;
  633. end;
  634. OP_MUL :
  635. begin
  636. if current_settings.cputype = cpu_MC68000 then
  637. begin
  638. r:=NR_D0;
  639. r2:=NR_D1;
  640. cg.getcpuregister(list,NR_D0);
  641. cg.getcpuregister(list,NR_D1);
  642. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
  643. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
  644. cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
  645. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
  646. cg.ungetcpuregister(list,r);
  647. cg.ungetcpuregister(list,r2);
  648. end
  649. else
  650. begin
  651. if (isaddressregister(reg)) then
  652. begin
  653. scratch_reg := getintregister(list,OS_INT);
  654. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  655. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,scratch_reg));
  656. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  657. end
  658. else
  659. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,reg));
  660. end;
  661. end;
  662. OP_SAR,
  663. OP_SHL,
  664. OP_SHR :
  665. begin
  666. if (a >= 1) and (a <= 8) then
  667. begin
  668. { now allowed to shift an address register }
  669. if (isaddressregister(reg)) then
  670. begin
  671. scratch_reg := getintregister(list,OS_INT);
  672. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  673. list.concat(taicpu.op_const_reg(opcode,S_L,a, scratch_reg));
  674. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  675. end
  676. else
  677. list.concat(taicpu.op_const_reg(opcode,S_L,a, reg));
  678. end
  679. else
  680. begin
  681. { we must load the data into a register ... :() }
  682. scratch_reg := cg.getintregister(list,OS_INT);
  683. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, scratch_reg));
  684. { again... since shifting with address register is not allowed }
  685. if (isaddressregister(reg)) then
  686. begin
  687. scratch_reg2 := cg.getintregister(list,OS_INT);
  688. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg2));
  689. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, scratch_reg2));
  690. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg2,reg));
  691. end
  692. else
  693. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, reg));
  694. end;
  695. end;
  696. OP_SUB :
  697. begin
  698. if (a >= 1) and (a <= 8) then
  699. list.concat(taicpu.op_const_reg(A_SUBQ,S_L,a,reg))
  700. else
  701. begin
  702. { all others, including coldfire }
  703. list.concat(taicpu.op_const_reg(A_SUB,S_L,a, reg));
  704. end;
  705. end;
  706. OP_XOR :
  707. begin
  708. list.concat(taicpu.op_const_reg(A_EORI,S_L,a, reg));
  709. end;
  710. else
  711. internalerror(20020729);
  712. end;
  713. end;
  714. {
  715. procedure tcg68k.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference);
  716. var
  717. opcode: tasmop;
  718. begin
  719. writeln('a_op_const_ref');
  720. optimize_op_const(op, a);
  721. opcode := topcg2tasmop[op];
  722. case op of
  723. OP_NONE :
  724. begin
  725. { opcode was optimized away }
  726. end;
  727. OP_MOVE :
  728. begin
  729. { Optimized, replaced with a simple load }
  730. a_load_const_ref(list,size,a,ref);
  731. end;
  732. else
  733. begin
  734. internalerror(2007010101);
  735. end;
  736. end;
  737. end;
  738. }
  739. procedure tcg68k.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister);
  740. var
  741. hreg1,hreg2,r,r2: tregister;
  742. begin
  743. case op of
  744. OP_ADD :
  745. begin
  746. if current_settings.cputype = cpu_ColdFire then
  747. begin
  748. { operation only allowed only a longword }
  749. sign_extend(list, size, reg1);
  750. sign_extend(list, size, reg2);
  751. list.concat(taicpu.op_reg_reg(A_ADD,S_L,reg1, reg2));
  752. end
  753. else
  754. begin
  755. list.concat(taicpu.op_reg_reg(A_ADD,TCGSize2OpSize[size],reg1, reg2));
  756. end;
  757. end;
  758. OP_AND,OP_OR,
  759. OP_SAR,OP_SHL,
  760. OP_SHR,OP_SUB,OP_XOR :
  761. begin
  762. { load to data registers }
  763. if (isaddressregister(reg1)) then
  764. begin
  765. hreg1 := getintregister(list,OS_INT);
  766. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  767. end
  768. else
  769. hreg1 := reg1;
  770. if (isaddressregister(reg2)) then
  771. begin
  772. hreg2:= getintregister(list,OS_INT);
  773. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  774. end
  775. else
  776. hreg2 := reg2;
  777. if current_settings.cputype = cpu_ColdFire then
  778. begin
  779. { operation only allowed only a longword }
  780. {!***************************************
  781. in the case of shifts, the value to
  782. shift by, should already be valid, so
  783. no need to sign extend the value
  784. !
  785. }
  786. if op in [OP_AND,OP_OR,OP_SUB,OP_XOR] then
  787. sign_extend(list, size, hreg1);
  788. sign_extend(list, size, hreg2);
  789. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],S_L,hreg1, hreg2));
  790. end
  791. else
  792. begin
  793. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg1, hreg2));
  794. end;
  795. { move back result into destination register }
  796. if reg2 <> hreg2 then
  797. begin
  798. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  799. end;
  800. end;
  801. OP_DIV :
  802. begin
  803. internalerror(20020816);
  804. end;
  805. OP_IDIV :
  806. begin
  807. internalerror(20020816);
  808. end;
  809. OP_IMUL :
  810. begin
  811. sign_extend(list, size,reg1);
  812. sign_extend(list, size,reg2);
  813. if current_settings.cputype = cpu_MC68000 then
  814. begin
  815. r:=NR_D0;
  816. r2:=NR_D1;
  817. cg.getcpuregister(list,NR_D0);
  818. cg.getcpuregister(list,NR_D1);
  819. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
  820. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
  821. cg.a_call_name(list,'FPC_MUL_LONGINT',false);
  822. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
  823. cg.ungetcpuregister(list,r);
  824. cg.ungetcpuregister(list,r2);
  825. end
  826. else
  827. begin
  828. // writeln('doing 68020');
  829. if (isaddressregister(reg1)) then
  830. hreg1 := getintregister(list,OS_INT)
  831. else
  832. hreg1 := reg1;
  833. if (isaddressregister(reg2)) then
  834. hreg2:= getintregister(list,OS_INT)
  835. else
  836. hreg2 := reg2;
  837. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  838. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  839. list.concat(taicpu.op_reg_reg(A_MULS,S_L,reg1,reg2));
  840. { move back result into destination register }
  841. if reg2 <> hreg2 then
  842. begin
  843. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  844. end;
  845. end;
  846. end;
  847. OP_MUL :
  848. begin
  849. sign_extend(list, size,reg1);
  850. sign_extend(list, size,reg2);
  851. if current_settings.cputype = cpu_MC68000 then
  852. begin
  853. r:=NR_D0;
  854. r2:=NR_D1;
  855. cg.getcpuregister(list,NR_D0);
  856. cg.getcpuregister(list,NR_D1);
  857. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
  858. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
  859. cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
  860. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
  861. cg.ungetcpuregister(list,r);
  862. cg.ungetcpuregister(list,r2);
  863. end
  864. else
  865. begin
  866. if (isaddressregister(reg1)) then
  867. begin
  868. hreg1 := cg.getintregister(list,OS_INT);
  869. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  870. end
  871. else
  872. hreg1 := reg1;
  873. if (isaddressregister(reg2)) then
  874. begin
  875. hreg2:= cg.getintregister(list,OS_INT);
  876. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  877. end
  878. else
  879. hreg2 := reg2;
  880. list.concat(taicpu.op_reg_reg(A_MULU,S_L,reg1,reg2));
  881. { move back result into destination register }
  882. if reg2<>hreg2 then
  883. begin
  884. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  885. end;
  886. end;
  887. end;
  888. OP_NEG,
  889. OP_NOT :
  890. Begin
  891. { if there are two operands, move the register,
  892. since the operation will only be done on the result
  893. register.
  894. }
  895. if reg1 <> NR_NO then
  896. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,reg1,reg2);
  897. if (isaddressregister(reg2)) then
  898. begin
  899. hreg2 := getintregister(list,OS_INT);
  900. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  901. end
  902. else
  903. hreg2 := reg2;
  904. { coldfire only supports long version }
  905. if current_settings.cputype = cpu_ColdFire then
  906. begin
  907. sign_extend(list, size,hreg2);
  908. list.concat(taicpu.op_reg(topcg2tasmop[op],S_L,hreg2));
  909. end
  910. else
  911. begin
  912. list.concat(taicpu.op_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg2));
  913. end;
  914. if reg2 <> hreg2 then
  915. begin
  916. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  917. end;
  918. end;
  919. else
  920. internalerror(20020729);
  921. end;
  922. end;
  923. procedure tcg68k.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  924. l : tasmlabel);
  925. var
  926. hregister : tregister;
  927. begin
  928. if a = 0 then
  929. begin
  930. list.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[size],reg));
  931. end
  932. else
  933. begin
  934. if (current_settings.cputype = cpu_ColdFire) then
  935. begin
  936. {
  937. only longword comparison is supported,
  938. and only on data registers.
  939. }
  940. hregister := getintregister(list,OS_INT);
  941. { always move to a data register }
  942. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,hregister));
  943. { sign/zero extend the register }
  944. sign_extend(list, size,hregister);
  945. list.concat(taicpu.op_const_reg(A_CMPI,S_L,a,hregister));
  946. end
  947. else
  948. begin
  949. list.concat(taicpu.op_const_reg(A_CMPI,TCGSize2OpSize[size],a,reg));
  950. end;
  951. end;
  952. { emit the actual jump to the label }
  953. a_jmp_cond(list,cmp_op,l);
  954. end;
  955. procedure tcg68k.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  956. begin
  957. list.concat(taicpu.op_reg_reg(A_CMP,tcgsize2opsize[size],reg1,reg2));
  958. { emit the actual jump to the label }
  959. a_jmp_cond(list,cmp_op,l);
  960. end;
  961. procedure tcg68k.a_jmp_always(list : TAsmList;l: tasmlabel);
  962. var
  963. ai: taicpu;
  964. begin
  965. ai := Taicpu.op_sym(A_JMP,S_NO,l);
  966. ai.is_jmp := true;
  967. list.concat(ai);
  968. end;
  969. procedure tcg68k.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  970. var
  971. ai : taicpu;
  972. begin
  973. ai := Taicpu.op_sym(A_BXX,S_NO,l);
  974. ai.SetCondition(flags_to_cond(f));
  975. ai.is_jmp := true;
  976. list.concat(ai);
  977. end;
  978. procedure tcg68k.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
  979. var
  980. ai : taicpu;
  981. hreg : tregister;
  982. begin
  983. { move to a Dx register? }
  984. if (isaddressregister(reg)) then
  985. begin
  986. hreg := getintregister(list,OS_INT);
  987. a_load_const_reg(list,size,0,hreg);
  988. ai:=Taicpu.Op_reg(A_Sxx,S_B,hreg);
  989. ai.SetCondition(flags_to_cond(f));
  990. list.concat(ai);
  991. if (current_settings.cputype = cpu_ColdFire) then
  992. begin
  993. { neg.b does not exist on the Coldfire
  994. so we need to sign extend the value
  995. before doing a neg.l
  996. }
  997. list.concat(taicpu.op_reg(A_EXTB,S_L,hreg));
  998. list.concat(taicpu.op_reg(A_NEG,S_L,hreg));
  999. end
  1000. else
  1001. begin
  1002. list.concat(taicpu.op_reg(A_NEG,S_B,hreg));
  1003. end;
  1004. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg,reg));
  1005. end
  1006. else
  1007. begin
  1008. a_load_const_reg(list,size,0,reg);
  1009. ai:=Taicpu.Op_reg(A_Sxx,S_B,reg);
  1010. ai.SetCondition(flags_to_cond(f));
  1011. list.concat(ai);
  1012. if (current_settings.cputype = cpu_ColdFire) then
  1013. begin
  1014. { neg.b does not exist on the Coldfire
  1015. so we need to sign extend the value
  1016. before doing a neg.l
  1017. }
  1018. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  1019. list.concat(taicpu.op_reg(A_NEG,S_L,reg));
  1020. end
  1021. else
  1022. begin
  1023. list.concat(taicpu.op_reg(A_NEG,S_B,reg));
  1024. end;
  1025. end;
  1026. end;
  1027. procedure tcg68k.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);
  1028. var
  1029. helpsize : longint;
  1030. i : byte;
  1031. reg8,reg32 : tregister;
  1032. swap : boolean;
  1033. hregister : tregister;
  1034. iregister : tregister;
  1035. jregister : tregister;
  1036. hp1 : treference;
  1037. hp2 : treference;
  1038. hl : tasmlabel;
  1039. hl2: tasmlabel;
  1040. popaddress : boolean;
  1041. srcref,dstref : treference;
  1042. begin
  1043. popaddress := false;
  1044. // writeln('concatcopy:',len);
  1045. { this should never occur }
  1046. if len > 65535 then
  1047. internalerror(0);
  1048. hregister := getintregister(list,OS_INT);
  1049. // if delsource then
  1050. // reference_release(list,source);
  1051. { from 12 bytes movs is being used }
  1052. if {(not loadref) and} ((len<=8) or (not(cs_opt_size in current_settings.optimizerswitches) and (len<=12))) then
  1053. begin
  1054. srcref := source;
  1055. dstref := dest;
  1056. helpsize:=len div 4;
  1057. { move a dword x times }
  1058. for i:=1 to helpsize do
  1059. begin
  1060. a_load_ref_reg(list,OS_INT,OS_INT,srcref,hregister);
  1061. a_load_reg_ref(list,OS_INT,OS_INT,hregister,dstref);
  1062. inc(srcref.offset,4);
  1063. inc(dstref.offset,4);
  1064. dec(len,4);
  1065. end;
  1066. { move a word }
  1067. if len>1 then
  1068. begin
  1069. a_load_ref_reg(list,OS_16,OS_16,srcref,hregister);
  1070. a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
  1071. inc(srcref.offset,2);
  1072. inc(dstref.offset,2);
  1073. dec(len,2);
  1074. end;
  1075. { move a single byte }
  1076. if len>0 then
  1077. begin
  1078. a_load_ref_reg(list,OS_8,OS_8,srcref,hregister);
  1079. a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
  1080. end
  1081. end
  1082. else
  1083. begin
  1084. iregister:=getaddressregister(list);
  1085. jregister:=getaddressregister(list);
  1086. { reference for move (An)+,(An)+ }
  1087. reference_reset(hp1,source.alignment);
  1088. hp1.base := iregister; { source register }
  1089. hp1.direction := dir_inc;
  1090. reference_reset(hp2,dest.alignment);
  1091. hp2.base := jregister;
  1092. hp2.direction := dir_inc;
  1093. { iregister = source }
  1094. { jregister = destination }
  1095. { if loadref then
  1096. cg.a_load_ref_reg(list,OS_INT,OS_INT,source,iregister)
  1097. else}
  1098. a_loadaddr_ref_reg(list,source,iregister);
  1099. a_loadaddr_ref_reg(list,dest,jregister);
  1100. { double word move only on 68020+ machines }
  1101. { because of possible alignment problems }
  1102. { use fast loop mode }
  1103. if (current_settings.cputype=cpu_MC68020) then
  1104. begin
  1105. helpsize := len - len mod 4;
  1106. len := len mod 4;
  1107. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize div 4,hregister));
  1108. current_asmdata.getjumplabel(hl2);
  1109. a_jmp_always(list,hl2);
  1110. current_asmdata.getjumplabel(hl);
  1111. a_label(list,hl);
  1112. list.concat(taicpu.op_ref_ref(A_MOVE,S_L,hp1,hp2));
  1113. a_label(list,hl2);
  1114. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  1115. if len > 1 then
  1116. begin
  1117. dec(len,2);
  1118. list.concat(taicpu.op_ref_ref(A_MOVE,S_W,hp1,hp2));
  1119. end;
  1120. if len = 1 then
  1121. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  1122. end
  1123. else
  1124. begin
  1125. { Fast 68010 loop mode with no possible alignment problems }
  1126. helpsize := len;
  1127. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize,hregister));
  1128. current_asmdata.getjumplabel(hl2);
  1129. a_jmp_always(list,hl2);
  1130. current_asmdata.getjumplabel(hl);
  1131. a_label(list,hl);
  1132. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  1133. a_label(list,hl2);
  1134. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  1135. end;
  1136. { restore the registers that we have just used olny if they are used! }
  1137. if jregister = NR_A1 then
  1138. hp2.base := NR_NO;
  1139. if iregister = NR_A0 then
  1140. hp1.base := NR_NO;
  1141. // reference_release(list,hp1);
  1142. // reference_release(list,hp2);
  1143. end;
  1144. // if delsource then
  1145. // tg.ungetiftemp(list,source);
  1146. end;
  1147. procedure tcg68k.g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef);
  1148. begin
  1149. end;
  1150. procedure tcg68k.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
  1151. begin
  1152. end;
  1153. procedure tcg68k.g_proc_entry(list: TAsmList; localsize: longint; nostackframe:boolean);
  1154. var
  1155. r,rsp: TRegister;
  1156. ref : TReference;
  1157. begin
  1158. {$ifdef DEBUG_CHARLIE}
  1159. // writeln('proc entry, localsize:',localsize);
  1160. {$endif DEBUG_CHARLIE}
  1161. if not nostackframe then
  1162. begin
  1163. if localsize<>0 then
  1164. begin
  1165. { size can't be negative }
  1166. if (localsize < 0) then
  1167. internalerror(2006122601);
  1168. { Not to complicate the code generator too much, and since some }
  1169. { of the systems only support this format, the localsize cannot }
  1170. { exceed 32K in size. }
  1171. if (localsize > high(smallint)) then
  1172. CGMessage(cg_e_localsize_too_big);
  1173. list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,-localsize));
  1174. end
  1175. else
  1176. begin
  1177. list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,0));
  1178. (*
  1179. { FIXME! - Carl's original code uses this method. However,
  1180. according to the 68060 users manual, a LINK is faster than
  1181. two moves. So, use a link in #0 case too, for now. I'm not
  1182. really sure tho', that LINK supports #0 disposition, but i
  1183. see no reason why it shouldn't support it. (KB) }
  1184. { when localsize = 0, use two moves, instead of link }
  1185. r:=NR_FRAME_POINTER_REG;
  1186. rsp:=NR_STACK_POINTER_REG;
  1187. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1188. ref.direction:=dir_dec;
  1189. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,r,ref));
  1190. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,rsp,r));
  1191. *)
  1192. end;
  1193. end;
  1194. end;
  1195. { procedure tcg68k.g_restore_frame_pointer(list : TAsmList);
  1196. var
  1197. r:Tregister;
  1198. begin
  1199. r:=NR_FRAME_POINTER_REG;
  1200. list.concat(taicpu.op_reg(A_UNLK,S_NO,r));
  1201. end;
  1202. }
  1203. procedure tcg68k.g_proc_exit(list : TAsmList; parasize: longint; nostackframe: boolean);
  1204. var
  1205. // r,hregister : TRegister;
  1206. localsize: aint;
  1207. spr : TRegister;
  1208. fpr : TRegister;
  1209. ref : TReference;
  1210. begin
  1211. if not nostackframe then
  1212. begin
  1213. localsize := current_procinfo.calc_stackframe_size;
  1214. {$ifdef DEBUG_CHARLIE}
  1215. // writeln('proc exit with stackframe, size:',localsize,' parasize:',parasize);
  1216. {$endif DEBUG_CHARLIE}
  1217. list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG));
  1218. parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is
  1219. correct here, but at least it looks less
  1220. hacky, and makes some sense (KB) }
  1221. if (parasize<>0) then
  1222. begin
  1223. { only 68020+ supports RTD, so this needs another code path
  1224. for 68000 and Coldfire (KB) }
  1225. { TODO: 68020+ only code generation, without fallback}
  1226. list.concat(taicpu.op_const(A_RTD,S_NO,parasize));
  1227. end
  1228. else
  1229. list.concat(taicpu.op_none(A_RTS,S_NO));
  1230. end
  1231. else
  1232. begin
  1233. {$ifdef DEBUG_CHARLIE}
  1234. // writeln('proc exit, no stackframe');
  1235. {$endif DEBUG_CHARLIE}
  1236. list.concat(taicpu.op_none(A_RTS,S_NO));
  1237. end;
  1238. // writeln('g_proc_exit');
  1239. { Routines with the poclearstack flag set use only a ret.
  1240. also routines with parasize=0 }
  1241. (*
  1242. if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  1243. begin
  1244. { complex return values are removed from stack in C code PM }
  1245. if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
  1246. list.concat(taicpu.op_const(A_RTD,S_NO,4))
  1247. else
  1248. list.concat(taicpu.op_none(A_RTS,S_NO));
  1249. end
  1250. else if (parasize=0) then
  1251. begin
  1252. list.concat(taicpu.op_none(A_RTS,S_NO));
  1253. end
  1254. else
  1255. begin
  1256. { return with immediate size possible here
  1257. signed!
  1258. RTD is not supported on the coldfire }
  1259. if (current_settings.cputype=cpu_MC68020) and (parasize<$7FFF) then
  1260. list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
  1261. { manually restore the stack }
  1262. else
  1263. begin
  1264. { We must pull the PC Counter from the stack, before }
  1265. { restoring the stack pointer, otherwise the PC would }
  1266. { point to nowhere! }
  1267. { save the PC counter (pop it from the stack) }
  1268. hregister:=NR_A3;
  1269. cg.a_reg_alloc(list,hregister);
  1270. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1271. ref.direction:=dir_inc;
  1272. list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
  1273. { can we do a quick addition ... }
  1274. r:=NR_SP;
  1275. if (parasize > 0) and (parasize < 9) then
  1276. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
  1277. else { nope ... }
  1278. list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
  1279. { restore the PC counter (push it on the stack) }
  1280. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1281. ref.direction:=dir_dec;
  1282. cg.a_reg_alloc(list,hregister);
  1283. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
  1284. list.concat(taicpu.op_none(A_RTS,S_NO));
  1285. end;
  1286. end;
  1287. *)
  1288. end;
  1289. procedure Tcg68k.g_save_registers(list:TAsmList);
  1290. var
  1291. tosave : tcpuregisterset;
  1292. ref : treference;
  1293. begin
  1294. {!!!!!
  1295. tosave:=std_saved_registers;
  1296. { only save the registers which are not used and must be saved }
  1297. tosave:=tosave*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
  1298. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1299. ref.direction:=dir_dec;
  1300. if tosave<>[] then
  1301. list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,tosave,ref));
  1302. }
  1303. end;
  1304. procedure Tcg68k.g_restore_registers(list:TAsmList);
  1305. var
  1306. torestore : tcpuregisterset;
  1307. r:Tregister;
  1308. ref : treference;
  1309. begin
  1310. {!!!!!!!!
  1311. torestore:=std_saved_registers;
  1312. { should be intersected with used regs, no ? }
  1313. torestore:=torestore*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
  1314. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1315. ref.direction:=dir_inc;
  1316. if torestore<>[] then
  1317. list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,ref,torestore));
  1318. }
  1319. end;
  1320. {
  1321. procedure tcg68k.g_save_all_registers(list : TAsmList);
  1322. begin
  1323. end;
  1324. procedure tcg68k.g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);
  1325. begin
  1326. end;
  1327. }
  1328. procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
  1329. begin
  1330. case _oldsize of
  1331. { sign extend }
  1332. OS_S8:
  1333. begin
  1334. if (isaddressregister(reg)) then
  1335. internalerror(20020729);
  1336. if (current_settings.cputype = cpu_MC68000) then
  1337. begin
  1338. list.concat(taicpu.op_reg(A_EXT,S_W,reg));
  1339. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  1340. end
  1341. else
  1342. begin
  1343. // list.concat(tai_comment.create(strpnew('sign extend byte')));
  1344. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  1345. end;
  1346. end;
  1347. OS_S16:
  1348. begin
  1349. if (isaddressregister(reg)) then
  1350. internalerror(20020729);
  1351. // list.concat(tai_comment.create(strpnew('sign extend word')));
  1352. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  1353. end;
  1354. { zero extend }
  1355. OS_8:
  1356. begin
  1357. // list.concat(tai_comment.create(strpnew('zero extend byte')));
  1358. list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
  1359. end;
  1360. OS_16:
  1361. begin
  1362. // list.concat(tai_comment.create(strpnew('zero extend word')));
  1363. list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
  1364. end;
  1365. end; { otherwise the size is already correct }
  1366. end;
  1367. procedure tcg68k.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1368. var
  1369. ai : taicpu;
  1370. begin
  1371. if cond=OC_None then
  1372. ai := Taicpu.Op_sym(A_JMP,S_NO,l)
  1373. else
  1374. begin
  1375. ai:=Taicpu.Op_sym(A_Bxx,S_NO,l);
  1376. ai.SetCondition(TOpCmp2AsmCond[cond]);
  1377. end;
  1378. ai.is_jmp:=true;
  1379. list.concat(ai);
  1380. end;
  1381. procedure tcg68k.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1382. {
  1383. procedure loadvmttor11;
  1384. var
  1385. href : treference;
  1386. begin
  1387. reference_reset_base(href,NR_R3,0);
  1388. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
  1389. end;
  1390. procedure op_onr11methodaddr;
  1391. var
  1392. href : treference;
  1393. begin
  1394. if (procdef.extnumber=$ffff) then
  1395. Internalerror(200006139);
  1396. { call/jmp vmtoffs(%eax) ; method offs }
  1397. reference_reset_base(href,NR_R11,procdef._class.vmtmethodoffset(procdef.extnumber));
  1398. if not((longint(href.offset) >= low(smallint)) and
  1399. (longint(href.offset) <= high(smallint))) then
  1400. begin
  1401. list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
  1402. smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
  1403. href.offset := smallint(href.offset and $ffff);
  1404. end;
  1405. list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href));
  1406. list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
  1407. list.concat(taicpu.op_none(A_BCTR));
  1408. end;
  1409. }
  1410. var
  1411. make_global : boolean;
  1412. begin
  1413. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1414. Internalerror(200006137);
  1415. if not assigned(procdef._class) or
  1416. (procdef.procoptions*[po_classmethod, po_staticmethod,
  1417. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  1418. Internalerror(200006138);
  1419. if procdef.owner.symtabletype<>ObjectSymtable then
  1420. Internalerror(200109191);
  1421. make_global:=false;
  1422. if (not current_module.is_unit) or
  1423. create_smartlink or
  1424. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  1425. make_global:=true;
  1426. if make_global then
  1427. List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
  1428. else
  1429. List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
  1430. { set param1 interface to self }
  1431. // g_adjust_self_value(list,procdef,ioffset);
  1432. { case 4 }
  1433. if po_virtualmethod in procdef.procoptions then
  1434. begin
  1435. // loadvmttor11;
  1436. // op_onr11methodaddr;
  1437. end
  1438. { case 0 }
  1439. else
  1440. // list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
  1441. List.concat(Tai_symbol_end.Createname(labelname));
  1442. end;
  1443. {****************************************************************************}
  1444. { TCG64F68K }
  1445. {****************************************************************************}
  1446. procedure tcg64f68k.a_op64_reg_reg(list : TAsmList;op:TOpCG;size: tcgsize; regsrc,regdst : tregister64);
  1447. var
  1448. hreg1, hreg2 : tregister;
  1449. opcode : tasmop;
  1450. begin
  1451. // writeln('a_op64_reg_reg');
  1452. opcode := topcg2tasmop[op];
  1453. case op of
  1454. OP_ADD :
  1455. begin
  1456. { if one of these three registers is an address
  1457. register, we'll really get into problems!
  1458. }
  1459. if isaddressregister(regdst.reglo) or
  1460. isaddressregister(regdst.reghi) or
  1461. isaddressregister(regsrc.reghi) then
  1462. internalerror(20020817);
  1463. list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
  1464. list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
  1465. end;
  1466. OP_AND,OP_OR :
  1467. begin
  1468. { at least one of the registers must be a data register }
  1469. if (isaddressregister(regdst.reglo) and
  1470. isaddressregister(regsrc.reglo)) or
  1471. (isaddressregister(regsrc.reghi) and
  1472. isaddressregister(regdst.reghi))
  1473. then
  1474. internalerror(20020817);
  1475. cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
  1476. cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
  1477. end;
  1478. { this is handled in 1st pass for 32-bit cpu's (helper call) }
  1479. OP_IDIV,OP_DIV,
  1480. OP_IMUL,OP_MUL: internalerror(2002081701);
  1481. { this is also handled in 1st pass for 32-bit cpu's (helper call) }
  1482. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1483. OP_SUB:
  1484. begin
  1485. { if one of these three registers is an address
  1486. register, we'll really get into problems!
  1487. }
  1488. if isaddressregister(regdst.reglo) or
  1489. isaddressregister(regdst.reghi) or
  1490. isaddressregister(regsrc.reghi) then
  1491. internalerror(20020817);
  1492. list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
  1493. list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
  1494. end;
  1495. OP_XOR:
  1496. begin
  1497. if isaddressregister(regdst.reglo) or
  1498. isaddressregister(regsrc.reglo) or
  1499. isaddressregister(regsrc.reghi) or
  1500. isaddressregister(regdst.reghi) then
  1501. internalerror(20020817);
  1502. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
  1503. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
  1504. end;
  1505. end; { end case }
  1506. end;
  1507. procedure tcg64f68k.a_op64_const_reg(list : TAsmList;op:TOpCG;size: tcgsize; value : int64;regdst : tregister64);
  1508. var
  1509. lowvalue : cardinal;
  1510. highvalue : cardinal;
  1511. hreg : tregister;
  1512. begin
  1513. // writeln('a_op64_const_reg');
  1514. { is it optimized out ? }
  1515. // if cg.optimize64_op_const_reg(list,op,value,reg) then
  1516. // exit;
  1517. lowvalue := cardinal(value);
  1518. highvalue:= value shr 32;
  1519. { the destination registers must be data registers }
  1520. if isaddressregister(regdst.reglo) or
  1521. isaddressregister(regdst.reghi) then
  1522. internalerror(20020817);
  1523. case op of
  1524. OP_ADD :
  1525. begin
  1526. hreg:=cg.getintregister(list,OS_INT);
  1527. list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
  1528. list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,regdst.reglo));
  1529. list.concat(taicpu.op_reg_reg(A_ADDX,S_L,hreg,regdst.reglo));
  1530. end;
  1531. OP_AND :
  1532. begin
  1533. list.concat(taicpu.op_const_reg(A_AND,S_L,lowvalue,regdst.reglo));
  1534. list.concat(taicpu.op_const_reg(A_AND,S_L,highvalue,regdst.reglo));
  1535. end;
  1536. OP_OR :
  1537. begin
  1538. list.concat(taicpu.op_const_reg(A_OR,S_L,lowvalue,regdst.reglo));
  1539. list.concat(taicpu.op_const_reg(A_OR,S_L,highvalue,regdst.reglo));
  1540. end;
  1541. { this is handled in 1st pass for 32-bit cpus (helper call) }
  1542. OP_IDIV,OP_DIV,
  1543. OP_IMUL,OP_MUL: internalerror(2002081701);
  1544. { this is also handled in 1st pass for 32-bit cpus (helper call) }
  1545. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1546. OP_SUB:
  1547. begin
  1548. hreg:=cg.getintregister(list,OS_INT);
  1549. list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
  1550. list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,regdst.reglo));
  1551. list.concat(taicpu.op_reg_reg(A_SUBX,S_L,hreg,regdst.reglo));
  1552. end;
  1553. OP_XOR:
  1554. begin
  1555. list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,regdst.reglo));
  1556. list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,regdst.reglo));
  1557. end;
  1558. end; { end case }
  1559. end;
  1560. procedure create_codegen;
  1561. begin
  1562. cg := tcg68k.create;
  1563. cg64 :=tcg64f68k.create;
  1564. end;
  1565. end.