cgcpu.pas 63 KB

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