cgcpu.pas 62 KB

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