cgcpu.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by the FPC team
  4. This unit implements the code generator for the 680x0
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cginfo,cgbase,cgobj,
  23. aasmbase,aasmtai,aasmcpu,
  24. cpubase,cpuinfo,cpupara,
  25. node,symconst,cg64f32;
  26. type
  27. tcg68k = class(tcg)
  28. procedure a_call_name(list : taasmoutput;const s : string);override;
  29. procedure a_call_ref(list : taasmoutput;const ref : treference);override;
  30. procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);override;
  31. procedure a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);override;
  32. procedure a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);override;
  33. procedure a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);override;
  34. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  35. procedure a_loadfpu_reg_reg(list: taasmoutput; reg1, reg2: tregister); override;
  36. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  37. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  38. procedure a_loadmm_reg_reg(list: taasmoutput; reg1, reg2: tregister); override;
  39. procedure a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister); override;
  40. procedure a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference); override;
  41. procedure a_parammm_reg(list: taasmoutput; reg: tregister); override;
  42. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; a: AWord; reg: TRegister); override;
  43. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); override;
  44. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  45. l : tasmlabel);override;
  46. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  47. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  48. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  49. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister); override;
  50. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword;delsource,loadref : boolean);override;
  51. { generates overflow checking code for a node }
  52. procedure g_overflowcheck(list: taasmoutput; const p: tnode); override;
  53. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer); override;
  54. procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
  55. procedure g_restore_frame_pointer(list : taasmoutput);override;
  56. procedure g_return_from_proc(list : taasmoutput;parasize : aword);override;
  57. procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
  58. procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
  59. procedure g_save_all_registers(list : taasmoutput);override;
  60. procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
  61. protected
  62. function fixref(list: taasmoutput; var ref: treference): boolean;
  63. private
  64. { # Sign or zero extend the register to a full 32-bit value.
  65. The new value is left in the same register.
  66. }
  67. procedure sign_extend(list: taasmoutput;_oldsize : tcgsize; reg: tregister);
  68. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  69. end;
  70. tcg64f68k = class(tcg64f32)
  71. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
  72. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override;
  73. end;
  74. { This function returns true if the reference+offset is valid.
  75. Otherwise extra code must be generated to solve the reference.
  76. On the m68k, this verifies that the reference is valid
  77. (e.g : if index register is used, then the max displacement
  78. is 256 bytes, if only base is used, then max displacement
  79. is 32K
  80. }
  81. function isvalidrefoffset(const ref: treference): boolean;
  82. const
  83. TCGSize2OpSize: Array[tcgsize] of topsize =
  84. (S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,
  85. S_FS,S_FD,S_FX,S_NO,
  86. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  87. Implementation
  88. uses
  89. globtype,globals,verbose,systems,cutils,
  90. symdef,symsym,defbase,paramgr,
  91. rgobj,tgobj,rgcpu;
  92. const
  93. { opcode table lookup }
  94. topcg2tasmop: Array[topcg] of tasmop =
  95. (
  96. A_NONE,
  97. A_ADD,
  98. A_AND,
  99. A_DIVU,
  100. A_DIVS,
  101. A_MULS,
  102. A_MULU,
  103. A_NEG,
  104. A_NOT,
  105. A_OR,
  106. A_ASR,
  107. A_LSL,
  108. A_LSR,
  109. A_SUB,
  110. A_EOR
  111. );
  112. TOpCmp2AsmCond: Array[topcmp] of TAsmCond =
  113. (
  114. C_NONE,
  115. C_EQ,
  116. C_GT,
  117. C_LT,
  118. C_GE,
  119. C_LE,
  120. C_NE,
  121. C_LS,
  122. C_CS,
  123. C_CC,
  124. C_HI
  125. );
  126. function isvalidrefoffset(const ref: treference): boolean;
  127. begin
  128. isvalidrefoffset := true;
  129. if ref.index <> R_NO then
  130. begin
  131. if ref.base <> R_NO then
  132. internalerror(20020814);
  133. if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
  134. isvalidrefoffset := false
  135. end
  136. else
  137. begin
  138. if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
  139. isvalidrefoffset := false;
  140. end;
  141. end;
  142. {****************************************************************************}
  143. { TCG68K }
  144. {****************************************************************************}
  145. function tcg68k.fixref(list: taasmoutput; var ref: treference): boolean;
  146. var
  147. tmpreg: tregister;
  148. begin
  149. result := false;
  150. if (ref.base <> R_NO) then
  151. begin
  152. if (ref.index <> R_NO) and assigned(ref.symbol) then
  153. internalerror(20020814);
  154. { base + reg }
  155. if ref.index <> R_NO then
  156. begin
  157. { base + reg + offset }
  158. if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
  159. begin
  160. list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
  161. fixref := true;
  162. ref.offset := 0;
  163. exit;
  164. end;
  165. end
  166. else
  167. { base + offset }
  168. if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
  169. begin
  170. list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
  171. fixref := true;
  172. ref.offset := 0;
  173. exit;
  174. end;
  175. end;
  176. end;
  177. procedure tcg68k.a_call_name(list : taasmoutput;const s : string);
  178. begin
  179. list.concat(taicpu.op_sym(A_JSR,S_NO,objectlibrary.newasmsymbol(s)));
  180. end;
  181. procedure tcg68k.a_call_ref(list : taasmoutput;const ref : treference);
  182. var
  183. href : treference;
  184. begin
  185. href := ref;
  186. fixref(list,href);
  187. list.concat(taicpu.op_ref(A_JSR,S_NO,href));
  188. end;
  189. procedure tcg68k.a_load_const_reg(list : taasmoutput;size : tcgsize;a : aword;register : tregister);
  190. begin
  191. if (rg.isaddressregister(register)) then
  192. begin
  193. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a,register))
  194. end
  195. else
  196. if a = 0 then
  197. list.concat(taicpu.op_reg(A_CLR,S_L,register))
  198. else
  199. begin
  200. if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
  201. list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,a,register))
  202. else
  203. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a,register))
  204. end;
  205. end;
  206. procedure tcg68k.a_load_reg_ref(list : taasmoutput;size : tcgsize;register : tregister;const ref : treference);
  207. var
  208. href : treference;
  209. begin
  210. href := ref;
  211. fixref(list,href);
  212. { move to destination reference }
  213. list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[size],register,href));
  214. end;
  215. procedure tcg68k.a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);
  216. begin
  217. { move to destination register }
  218. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2));
  219. { zero/sign extend register to 32-bit }
  220. sign_extend(list, size, reg2);
  221. end;
  222. procedure tcg68k.a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;register : tregister);
  223. var
  224. href : treference;
  225. begin
  226. href := ref;
  227. fixref(list,href);
  228. list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[size],href,register));
  229. { extend the value in the register }
  230. sign_extend(list, size, register);
  231. end;
  232. procedure tcg68k.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  233. var
  234. href : treference;
  235. begin
  236. if (not rg.isaddressregister(r)) then
  237. begin
  238. internalerror(2002072901);
  239. end;
  240. href:=ref;
  241. fixref(list, href);
  242. list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,r));
  243. end;
  244. procedure tcg68k.a_loadfpu_reg_reg(list: taasmoutput; reg1, reg2: tregister);
  245. begin
  246. { in emulation mode, only 32-bit single is supported }
  247. if cs_fp_emulation in aktmoduleswitches then
  248. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
  249. else
  250. list.concat(taicpu.op_reg_reg(A_FMOVE,S_FD,reg1,reg2));
  251. end;
  252. procedure tcg68k.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  253. var
  254. opsize : topsize;
  255. href : treference;
  256. begin
  257. opsize := tcgsize2opsize[size];
  258. { extended is not supported, since it is not available on Coldfire }
  259. if opsize = S_FX then
  260. internalerror(20020729);
  261. fixref(list,href);
  262. { in emulation mode, only 32-bit single is supported }
  263. if cs_fp_emulation in aktmoduleswitches then
  264. list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
  265. else
  266. list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
  267. end;
  268. procedure tcg68k.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  269. var
  270. opsize : topsize;
  271. begin
  272. opsize := tcgsize2opsize[size];
  273. { extended is not supported, since it is not available on Coldfire }
  274. if opsize = S_FX then
  275. internalerror(20020729);
  276. { in emulation mode, only 32-bit single is supported }
  277. if cs_fp_emulation in aktmoduleswitches then
  278. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
  279. else
  280. list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
  281. end;
  282. procedure tcg68k.a_loadmm_reg_reg(list: taasmoutput; reg1, reg2: tregister);
  283. begin
  284. internalerror(20020729);
  285. end;
  286. procedure tcg68k.a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister);
  287. begin
  288. internalerror(20020729);
  289. end;
  290. procedure tcg68k.a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference);
  291. begin
  292. internalerror(20020729);
  293. end;
  294. procedure tcg68k.a_parammm_reg(list: taasmoutput; reg: tregister);
  295. begin
  296. internalerror(20020729);
  297. end;
  298. procedure tcg68k.a_op_const_reg(list : taasmoutput; Op: TOpCG; a: AWord; reg: TRegister);
  299. var
  300. scratch_reg : tregister;
  301. scratch_reg2: tregister;
  302. opcode : tasmop;
  303. begin
  304. { need to emit opcode? }
  305. if optimize_op_const_reg(list, op, a, reg) then
  306. exit;
  307. opcode := topcg2tasmop[op];
  308. case op of
  309. OP_ADD :
  310. Begin
  311. if (a >= 1) and (a <= 8) then
  312. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,a, reg))
  313. else
  314. begin
  315. { all others, including coldfire }
  316. list.concat(taicpu.op_const_reg(A_ADD,S_L,a, reg));
  317. end;
  318. end;
  319. OP_AND,
  320. OP_OR:
  321. Begin
  322. list.concat(taicpu.op_const_reg(topcg2tasmop[op],S_L,a, reg));
  323. end;
  324. OP_DIV :
  325. Begin
  326. internalerror(20020816);
  327. end;
  328. OP_IDIV :
  329. Begin
  330. internalerror(20020816);
  331. end;
  332. OP_IMUL :
  333. Begin
  334. if aktoptprocessor = MC68000 then
  335. begin
  336. rg.getexplicitregisterint(list,R_D0);
  337. rg.getexplicitregisterint(list,R_D1);
  338. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, R_D0));
  339. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, R_D1));
  340. cg.a_call_name(list,'FPC_MUL_LONGINT');
  341. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,R_D0, reg));
  342. rg.ungetregisterint(list,R_D0);
  343. rg.ungetregisterint(list,R_D1);
  344. end
  345. else
  346. begin
  347. if (rg.isaddressregister(reg)) then
  348. begin
  349. scratch_reg := cg.get_scratch_reg_int(list);
  350. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  351. list.concat(taicpu.op_const_reg(A_MULS,S_L,a,scratch_reg));
  352. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  353. cg.free_scratch_reg(list,scratch_reg);
  354. end
  355. else
  356. list.concat(taicpu.op_const_reg(A_MULS,S_L,a,reg));
  357. end;
  358. end;
  359. OP_MUL :
  360. Begin
  361. if aktoptprocessor = MC68000 then
  362. begin
  363. rg.getexplicitregisterint(list,R_D0);
  364. rg.getexplicitregisterint(list,R_D1);
  365. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, R_D0));
  366. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, R_D1));
  367. cg.a_call_name(list,'FPC_MUL_CARDINAL');
  368. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,R_D0, reg));
  369. rg.ungetregisterint(list,R_D0);
  370. rg.ungetregisterint(list,R_D1);
  371. end
  372. else
  373. begin
  374. if (rg.isaddressregister(reg)) then
  375. begin
  376. scratch_reg := cg.get_scratch_reg_int(list);
  377. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  378. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,scratch_reg));
  379. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  380. cg.free_scratch_reg(list,scratch_reg);
  381. end
  382. else
  383. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,reg));
  384. end;
  385. end;
  386. OP_SAR,
  387. OP_SHL,
  388. OP_SHR :
  389. Begin
  390. if (a >= 1) and (a <= 8) then
  391. begin
  392. { now allowed to shift an address register }
  393. if (rg.isaddressregister(reg)) then
  394. begin
  395. scratch_reg := cg.get_scratch_reg_int(list);
  396. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  397. list.concat(taicpu.op_const_reg(opcode,S_L,a, scratch_reg));
  398. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  399. cg.free_scratch_reg(list,scratch_reg);
  400. end
  401. else
  402. list.concat(taicpu.op_const_reg(opcode,S_L,a, reg));
  403. end
  404. else
  405. begin
  406. { we must load the data into a register ... :() }
  407. scratch_reg := cg.get_scratch_reg_int(list);
  408. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, scratch_reg));
  409. { again... since shifting with address register is not allowed }
  410. if (rg.isaddressregister(reg)) then
  411. begin
  412. scratch_reg2 := cg.get_scratch_reg_int(list);
  413. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg2));
  414. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, scratch_reg2));
  415. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg2,reg));
  416. cg.free_scratch_reg(list,scratch_reg2);
  417. end
  418. else
  419. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, reg));
  420. cg.free_scratch_reg(list,scratch_reg);
  421. end;
  422. end;
  423. OP_SUB :
  424. Begin
  425. if (a >= 1) and (a <= 8) then
  426. list.concat(taicpu.op_const_reg(A_SUBQ,S_L,a,reg))
  427. else
  428. begin
  429. { all others, including coldfire }
  430. list.concat(taicpu.op_const_reg(A_SUB,S_L,a, reg));
  431. end;
  432. end;
  433. OP_XOR :
  434. Begin
  435. list.concat(taicpu.op_const_reg(A_EORI,S_L,a, reg));
  436. end;
  437. else
  438. internalerror(20020729);
  439. end;
  440. end;
  441. procedure tcg68k.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister);
  442. var
  443. hreg1,hreg2: tregister;
  444. begin
  445. case op of
  446. OP_ADD :
  447. Begin
  448. if aktoptprocessor = ColdFire then
  449. begin
  450. { operation only allowed only a longword }
  451. sign_extend(list, size, reg1);
  452. sign_extend(list, size, reg2);
  453. list.concat(taicpu.op_reg_reg(A_ADD,S_L,reg1, reg2));
  454. end
  455. else
  456. begin
  457. list.concat(taicpu.op_reg_reg(A_ADD,TCGSize2OpSize[size],reg1, reg2));
  458. end;
  459. end;
  460. OP_AND,OP_OR,
  461. OP_SAR,OP_SHL,
  462. OP_SHR,OP_SUB,OP_XOR :
  463. Begin
  464. { load to data registers }
  465. if (rg.isaddressregister(reg1)) then
  466. begin
  467. hreg1 := cg.get_scratch_reg_int(list);
  468. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  469. end
  470. else
  471. hreg1 := reg1;
  472. if (rg.isaddressregister(reg2)) then
  473. begin
  474. hreg2:= cg.get_scratch_reg_int(list);
  475. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  476. end
  477. else
  478. hreg2 := reg2;
  479. if aktoptprocessor = ColdFire then
  480. begin
  481. { operation only allowed only a longword }
  482. {!***************************************
  483. in the case of shifts, the value to
  484. shift by, should already be valid, so
  485. no need to sign extend the value
  486. !
  487. }
  488. if op in [OP_AND,OP_OR,OP_SUB,OP_XOR] then
  489. sign_extend(list, size, hreg1);
  490. sign_extend(list, size, hreg2);
  491. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],S_L,hreg1, hreg2));
  492. end
  493. else
  494. begin
  495. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg1, hreg2));
  496. end;
  497. if reg1 <> hreg1 then
  498. cg.free_scratch_reg(list,hreg1);
  499. { move back result into destination register }
  500. if reg2 <> hreg2 then
  501. begin
  502. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  503. cg.free_scratch_reg(list,hreg2);
  504. end;
  505. end;
  506. OP_DIV :
  507. Begin
  508. internalerror(20020816);
  509. end;
  510. OP_IDIV :
  511. Begin
  512. internalerror(20020816);
  513. end;
  514. OP_IMUL :
  515. Begin
  516. sign_extend(list, size,reg1);
  517. sign_extend(list, size,reg2);
  518. if aktoptprocessor = MC68000 then
  519. begin
  520. rg.getexplicitregisterint(list,R_D0);
  521. rg.getexplicitregisterint(list,R_D1);
  522. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, R_D0));
  523. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, R_D1));
  524. cg.a_call_name(list,'FPC_MUL_LONGINT');
  525. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,R_D0, reg2));
  526. rg.ungetregisterint(list,R_D0);
  527. rg.ungetregisterint(list,R_D1);
  528. end
  529. else
  530. begin
  531. if (rg.isaddressregister(reg1)) then
  532. hreg1 := cg.get_scratch_reg_int(list)
  533. else
  534. hreg1 := reg1;
  535. if (rg.isaddressregister(reg2)) then
  536. hreg2:= cg.get_scratch_reg_int(list)
  537. else
  538. hreg2 := reg2;
  539. if reg1 <> hreg1 then
  540. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  541. if reg2 <> hreg2 then
  542. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  543. list.concat(taicpu.op_reg_reg(A_MULS,S_L,reg1,reg2));
  544. if reg1 <> hreg1 then
  545. cg.free_scratch_reg(list,hreg1);
  546. { move back result into destination register }
  547. if reg2 <> hreg2 then
  548. begin
  549. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  550. cg.free_scratch_reg(list,hreg2);
  551. end;
  552. end;
  553. end;
  554. OP_MUL :
  555. Begin
  556. sign_extend(list, size,reg1);
  557. sign_extend(list, size,reg2);
  558. if aktoptprocessor = MC68000 then
  559. begin
  560. rg.getexplicitregisterint(list,R_D0);
  561. rg.getexplicitregisterint(list,R_D1);
  562. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, R_D0));
  563. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, R_D1));
  564. cg.a_call_name(list,'FPC_MUL_CARDINAL');
  565. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,R_D0, reg2));
  566. rg.ungetregisterint(list,R_D0);
  567. rg.ungetregisterint(list,R_D1);
  568. end
  569. else
  570. begin
  571. if (rg.isaddressregister(reg1)) then
  572. begin
  573. hreg1 := cg.get_scratch_reg_int(list);
  574. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  575. end
  576. else
  577. hreg1 := reg1;
  578. if (rg.isaddressregister(reg2)) then
  579. begin
  580. hreg2:= cg.get_scratch_reg_int(list);
  581. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  582. end
  583. else
  584. hreg2 := reg2;
  585. list.concat(taicpu.op_reg_reg(A_MULU,S_L,reg1,reg2));
  586. if reg1 <> hreg1 then
  587. cg.free_scratch_reg(list,hreg1);
  588. { move back result into destination register }
  589. if reg2 <> hreg2 then
  590. begin
  591. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  592. cg.free_scratch_reg(list,hreg2);
  593. end;
  594. end;
  595. end;
  596. OP_NEG,
  597. OP_NOT :
  598. Begin
  599. if reg1 <> R_NO then
  600. internalerror(200112291);
  601. if (rg.isaddressregister(reg2)) then
  602. begin
  603. hreg2 := cg.get_scratch_reg_int(list);
  604. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  605. end
  606. else
  607. hreg2 := reg2;
  608. { coldfire only supports long version }
  609. if aktoptprocessor = ColdFire then
  610. begin
  611. sign_extend(list, size,hreg2);
  612. list.concat(taicpu.op_reg(topcg2tasmop[op],S_L,hreg2));
  613. end
  614. else
  615. begin
  616. list.concat(taicpu.op_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg2));
  617. end;
  618. if reg2 <> hreg2 then
  619. begin
  620. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  621. cg.free_scratch_reg(list,hreg2);
  622. end;
  623. end;
  624. else
  625. internalerror(20020729);
  626. end;
  627. end;
  628. procedure tcg68k.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  629. l : tasmlabel);
  630. var
  631. hregister : tregister;
  632. begin
  633. if a = 0 then
  634. begin
  635. list.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[size],reg));
  636. end
  637. else
  638. begin
  639. if (aktoptprocessor = ColdFire) then
  640. begin
  641. {
  642. only longword comparison is supported,
  643. and only on data registers.
  644. }
  645. hregister := cg.get_scratch_reg_int(list);
  646. { always move to a data register }
  647. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,hregister));
  648. { sign/zero extend the register }
  649. sign_extend(list, size,hregister);
  650. list.concat(taicpu.op_const_reg(A_CMPI,S_L,a,hregister));
  651. cg.free_scratch_reg(list,hregister);
  652. end
  653. else
  654. begin
  655. list.concat(taicpu.op_const_reg(A_CMPI,TCGSize2OpSize[size],a,reg));
  656. end;
  657. end;
  658. { emit the actual jump to the label }
  659. a_jmp_cond(list,cmp_op,l);
  660. end;
  661. procedure tcg68k.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  662. begin
  663. list.concat(taicpu.op_reg_reg(A_CMP,tcgsize2opsize[size],reg1,reg2));
  664. { emit the actual jump to the label }
  665. a_jmp_cond(list,cmp_op,l);
  666. end;
  667. procedure tcg68k.a_jmp_always(list : taasmoutput;l: tasmlabel);
  668. var
  669. ai: taicpu;
  670. begin
  671. ai := Taicpu.op_sym(A_JMP,S_NO,l);
  672. ai.is_jmp := true;
  673. list.concat(ai);
  674. end;
  675. procedure tcg68k.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  676. var
  677. ai : taicpu;
  678. begin
  679. ai := Taicpu.op_sym(A_BXX,S_NO,l);
  680. ai.SetCondition(flags_to_cond(f));
  681. ai.is_jmp := true;
  682. list.concat(ai);
  683. end;
  684. procedure tcg68k.g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister);
  685. var
  686. ai : taicpu;
  687. hreg : tregister;
  688. begin
  689. { move to a Dx register? }
  690. if (rg.isaddressregister(reg)) then
  691. begin
  692. hreg := get_scratch_reg_int(list);
  693. a_load_const_reg(list,size,0,hreg);
  694. ai:=Taicpu.Op_reg(A_Sxx,S_B,hreg);
  695. ai.SetCondition(flags_to_cond(f));
  696. list.concat(ai);
  697. if (aktoptprocessor = ColdFire) then
  698. begin
  699. { neg.b does not exist on the Coldfire
  700. so we need to sign extend the value
  701. before doing a neg.l
  702. }
  703. list.concat(taicpu.op_reg(A_EXTB,S_L,hreg));
  704. list.concat(taicpu.op_reg(A_NEG,S_L,hreg));
  705. end
  706. else
  707. begin
  708. list.concat(taicpu.op_reg(A_NEG,S_B,hreg));
  709. end;
  710. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg,reg));
  711. free_scratch_reg(list,hreg);
  712. end
  713. else
  714. begin
  715. a_load_const_reg(list,size,0,reg);
  716. ai:=Taicpu.Op_reg(A_Sxx,S_B,reg);
  717. ai.SetCondition(flags_to_cond(f));
  718. list.concat(ai);
  719. if (aktoptprocessor = ColdFire) then
  720. begin
  721. { neg.b does not exist on the Coldfire
  722. so we need to sign extend the value
  723. before doing a neg.l
  724. }
  725. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  726. list.concat(taicpu.op_reg(A_NEG,S_L,reg));
  727. end
  728. else
  729. begin
  730. list.concat(taicpu.op_reg(A_NEG,S_B,reg));
  731. end;
  732. end;
  733. end;
  734. procedure tcg68k.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword;delsource,loadref : boolean);
  735. var
  736. helpsize : longint;
  737. i : byte;
  738. reg8,reg32 : tregister;
  739. swap : boolean;
  740. hregister : tregister;
  741. iregister : tregister;
  742. jregister : tregister;
  743. hp1 : treference;
  744. hp2 : treference;
  745. hl : tasmlabel;
  746. hl2: tasmlabel;
  747. popaddress : boolean;
  748. srcref,dstref : treference;
  749. begin
  750. popaddress := false;
  751. { this should never occur }
  752. if len > 65535 then
  753. internalerror(0);
  754. hregister := get_scratch_reg_int(list);
  755. if delsource then
  756. reference_release(list,source);
  757. { from 12 bytes movs is being used }
  758. if (not loadref) and ((len<=8) or (not(cs_littlesize in aktglobalswitches) and (len<=12))) then
  759. begin
  760. srcref := source;
  761. dstref := dest;
  762. helpsize:=len div 4;
  763. { move a dword x times }
  764. for i:=1 to helpsize do
  765. begin
  766. a_load_ref_reg(list,OS_INT,srcref,hregister);
  767. a_load_reg_ref(list,OS_INT,hregister,dstref);
  768. inc(srcref.offset,4);
  769. inc(dstref.offset,4);
  770. dec(len,4);
  771. end;
  772. { move a word }
  773. if len>1 then
  774. begin
  775. a_load_ref_reg(list,OS_16,srcref,hregister);
  776. a_load_reg_ref(list,OS_16,hregister,dstref);
  777. inc(srcref.offset,2);
  778. inc(dstref.offset,2);
  779. dec(len,2);
  780. end;
  781. { move a single byte }
  782. if len>0 then
  783. begin
  784. a_load_ref_reg(list,OS_8,srcref,hregister);
  785. a_load_reg_ref(list,OS_8,hregister,dstref);
  786. end
  787. end
  788. else
  789. begin
  790. iregister := get_scratch_reg_address(list);
  791. jregister := get_scratch_reg_address(list);
  792. { reference for move (An)+,(An)+ }
  793. reference_reset(hp1);
  794. hp1.base := iregister; { source register }
  795. hp1.direction := dir_inc;
  796. reference_reset(hp2);
  797. hp2.base := jregister;
  798. hp2.direction := dir_inc;
  799. { iregister = source }
  800. { jregister = destination }
  801. if loadref then
  802. a_load_ref_reg(list,OS_INT,source,iregister)
  803. else
  804. a_loadaddr_ref_reg(list,source,iregister);
  805. a_loadaddr_ref_reg(list,dest,jregister);
  806. { double word move only on 68020+ machines }
  807. { because of possible alignment problems }
  808. { use fast loop mode }
  809. if (aktoptprocessor=MC68020) then
  810. begin
  811. helpsize := len - len mod 4;
  812. len := len mod 4;
  813. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize div 4,hregister));
  814. objectlibrary.getlabel(hl2);
  815. a_jmp_always(list,hl2);
  816. objectlibrary.getlabel(hl);
  817. a_label(list,hl);
  818. list.concat(taicpu.op_ref_ref(A_MOVE,S_L,hp1,hp2));
  819. cg.a_label(list,hl2);
  820. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  821. if len > 1 then
  822. begin
  823. dec(len,2);
  824. list.concat(taicpu.op_ref_ref(A_MOVE,S_W,hp1,hp2));
  825. end;
  826. if len = 1 then
  827. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  828. end
  829. else
  830. begin
  831. { Fast 68010 loop mode with no possible alignment problems }
  832. helpsize := len;
  833. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize,hregister));
  834. objectlibrary.getlabel(hl2);
  835. a_jmp_always(list,hl2);
  836. objectlibrary.getlabel(hl);
  837. a_label(list,hl);
  838. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  839. a_label(list,hl2);
  840. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  841. end;
  842. { restore the registers that we have just used olny if they are used! }
  843. if jregister = R_A1 then
  844. hp2.base := R_NO;
  845. if iregister = R_A0 then
  846. hp1.base := R_NO;
  847. reference_release(list,hp1);
  848. reference_release(list,hp2);
  849. end;
  850. { loading SELF-reference again }
  851. g_maybe_loadself(list);
  852. if delsource then
  853. tg.ungetiftemp(list,source);
  854. free_scratch_reg(list,hregister);
  855. end;
  856. procedure tcg68k.g_overflowcheck(list: taasmoutput; const p: tnode);
  857. begin
  858. end;
  859. procedure tcg68k.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);
  860. begin
  861. end;
  862. procedure tcg68k.g_stackframe_entry(list : taasmoutput;localsize : longint);
  863. begin
  864. if localsize<>0 then
  865. begin
  866. { Not to complicate the code generator too much, and since some }
  867. { of the systems only support this format, the localsize cannot }
  868. { exceed 32K in size. }
  869. if (localsize < low(smallint)) or (localsize > high(smallint)) then
  870. CGMessage(cg_e_stacklimit_in_local_routine);
  871. list.concat(taicpu.op_reg_const(A_LINK,S_W,frame_pointer_reg,-localsize));
  872. end { endif localsize <> 0 }
  873. else
  874. begin
  875. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,frame_pointer_reg,R_SPPUSH));
  876. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,stack_pointer_reg,frame_pointer_reg));
  877. end;
  878. end;
  879. procedure tcg68k.g_restore_frame_pointer(list : taasmoutput);
  880. begin
  881. list.concat(taicpu.op_reg(A_UNLK,S_NO,frame_pointer_reg));
  882. end;
  883. procedure tcg68k.g_return_from_proc(list : taasmoutput;parasize : aword);
  884. var
  885. hregister : tregister;
  886. begin
  887. {Routines with the poclearstack flag set use only a ret.}
  888. { also routines with parasize=0 }
  889. if (po_clearstack in aktprocdef.procoptions) then
  890. begin
  891. { complex return values are removed from stack in C code PM }
  892. if paramanager.ret_in_param(aktprocdef.rettype.def) then
  893. list.concat(taicpu.op_const(A_RTD,S_NO,4))
  894. else
  895. list.concat(taicpu.op_none(A_RTS,S_NO));
  896. end
  897. else if (parasize=0) then
  898. begin
  899. list.concat(taicpu.op_none(A_RTS,S_NO));
  900. end
  901. else
  902. begin
  903. { return with immediate size possible here }
  904. { signed! }
  905. { RTD is not supported on the coldfire }
  906. if (aktoptprocessor = MC68020) and (parasize < $7FFF) then
  907. list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
  908. { manually restore the stack }
  909. else
  910. begin
  911. { We must pull the PC Counter from the stack, before }
  912. { restoring the stack pointer, otherwise the PC would }
  913. { point to nowhere! }
  914. { save the PC counter (pop it from the stack) }
  915. hregister := get_scratch_reg_address(list);
  916. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,R_SPPULL,hregister));
  917. { can we do a quick addition ... }
  918. if (parasize > 0) and (parasize < 9) then
  919. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,R_SP))
  920. else { nope ... }
  921. list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,R_SP));
  922. { restore the PC counter (push it on the stack) }
  923. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hregister,R_SPPUSH));
  924. list.concat(taicpu.op_none(A_RTS,S_NO));
  925. free_scratch_reg(list,hregister);
  926. end;
  927. end;
  928. end;
  929. procedure tcg68k.g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);
  930. var
  931. tosave : tregisterlist;
  932. begin
  933. tosave:=std_saved_registers;
  934. { only save the registers which are not used and must be saved }
  935. tosave:=tosave*usedinproc;
  936. if tosave<>[] then
  937. list.concat(taicpu.op_reglist_reg(A_MOVEM,S_L,tosave,R_SPPUSH));
  938. end;
  939. procedure tcg68k.g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);
  940. var
  941. torestore : tregisterset;
  942. begin
  943. torestore:=std_saved_registers;
  944. { should be intersected with used regs, no ? }
  945. torestore:=torestore*usedinproc;
  946. if torestore<>[] then
  947. list.concat(taicpu.op_reg_reglist(A_MOVEM,S_L,R_SPPULL,torestore));
  948. end;
  949. procedure tcg68k.g_save_all_registers(list : taasmoutput);
  950. begin
  951. end;
  952. procedure tcg68k.g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);
  953. begin
  954. end;
  955. procedure tcg68k.sign_extend(list: taasmoutput;_oldsize : tcgsize; reg: tregister);
  956. begin
  957. case _oldsize of
  958. { sign extend }
  959. OS_S8:
  960. begin
  961. if (rg.isaddressregister(reg)) then
  962. internalerror(20020729);
  963. if (aktoptprocessor = MC68000) then
  964. begin
  965. list.concat(taicpu.op_reg(A_EXT,S_W,reg));
  966. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  967. end
  968. else
  969. begin
  970. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  971. end;
  972. end;
  973. OS_S16:
  974. begin
  975. if (rg.isaddressregister(reg)) then
  976. internalerror(20020729);
  977. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  978. end;
  979. { zero extend }
  980. OS_8:
  981. begin
  982. if (rg.isaddressregister(reg)) then
  983. internalerror(20020729);
  984. list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
  985. end;
  986. OS_16:
  987. begin
  988. if (rg.isaddressregister(reg)) then
  989. internalerror(20020729);
  990. list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
  991. end;
  992. end; { otherwise the size is already correct }
  993. end;
  994. procedure tcg68k.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  995. var
  996. ai : taicpu;
  997. begin
  998. if cond=OC_None then
  999. ai := Taicpu.Op_sym(A_JMP,S_NO,l)
  1000. else
  1001. begin
  1002. ai:=Taicpu.Op_sym(A_Bxx,S_NO,l);
  1003. ai.SetCondition(TOpCmp2AsmCond[cond]);
  1004. end;
  1005. ai.is_jmp:=true;
  1006. list.concat(ai);
  1007. end;
  1008. {****************************************************************************}
  1009. { TCG64F68K }
  1010. {****************************************************************************}
  1011. procedure tcg64f68k.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  1012. var
  1013. hreg1, hreg2 : tregister;
  1014. opcode : tasmop;
  1015. begin
  1016. opcode := topcg2tasmop[op];
  1017. case op of
  1018. OP_ADD :
  1019. begin
  1020. { if one of these three registers is an address
  1021. register, we'll really get into problems!
  1022. }
  1023. if rg.isaddressregister(regdst.reglo) or
  1024. rg.isaddressregister(regdst.reghi) or
  1025. rg.isaddressregister(regsrc.reghi) then
  1026. internalerror(20020817);
  1027. list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
  1028. list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
  1029. end;
  1030. OP_AND,OP_OR :
  1031. begin
  1032. { at least one of the registers must be a data register }
  1033. if (rg.isaddressregister(regdst.reglo) and
  1034. rg.isaddressregister(regsrc.reglo)) or
  1035. (rg.isaddressregister(regsrc.reghi) and
  1036. rg.isaddressregister(regdst.reghi))
  1037. then
  1038. internalerror(20020817);
  1039. cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
  1040. cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
  1041. end;
  1042. { this is handled in 1st pass for 32-bit cpu's (helper call) }
  1043. OP_IDIV,OP_DIV,
  1044. OP_IMUL,OP_MUL: internalerror(2002081701);
  1045. { this is also handled in 1st pass for 32-bit cpu's (helper call) }
  1046. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1047. OP_SUB:
  1048. begin
  1049. { if one of these three registers is an address
  1050. register, we'll really get into problems!
  1051. }
  1052. if rg.isaddressregister(regdst.reglo) or
  1053. rg.isaddressregister(regdst.reghi) or
  1054. rg.isaddressregister(regsrc.reghi) then
  1055. internalerror(20020817);
  1056. list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
  1057. list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
  1058. end;
  1059. OP_XOR:
  1060. begin
  1061. if rg.isaddressregister(regdst.reglo) or
  1062. rg.isaddressregister(regsrc.reglo) or
  1063. rg.isaddressregister(regsrc.reghi) or
  1064. rg.isaddressregister(regdst.reghi) then
  1065. internalerror(20020817);
  1066. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
  1067. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
  1068. end;
  1069. end; { end case }
  1070. end;
  1071. procedure tcg64f68k.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
  1072. var
  1073. lowvalue : cardinal;
  1074. highvalue : cardinal;
  1075. begin
  1076. { is it optimized out ? }
  1077. if optimize64_op_const_reg(list,op,value,reg) then
  1078. exit;
  1079. lowvalue := cardinal(value);
  1080. highvalue:= value shr 32;
  1081. { the destination registers must be data registers }
  1082. if rg.isaddressregister(reg.reglo) or
  1083. rg.isaddressregister(reg.reghi) then
  1084. internalerror(20020817);
  1085. case op of
  1086. OP_ADD :
  1087. begin
  1088. list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,reg.reglo));
  1089. list.concat(taicpu.op_const_reg(A_ADDX,S_L,highvalue,reg.reglo));
  1090. end;
  1091. OP_AND :
  1092. begin
  1093. { should already be optimized out }
  1094. internalerror(2002081801);
  1095. end;
  1096. OP_OR :
  1097. begin
  1098. { should already be optimized out }
  1099. internalerror(2002081802);
  1100. end;
  1101. { this is handled in 1st pass for 32-bit cpu's (helper call) }
  1102. OP_IDIV,OP_DIV,
  1103. OP_IMUL,OP_MUL: internalerror(2002081701);
  1104. { this is also handled in 1st pass for 32-bit cpu's (helper call) }
  1105. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1106. OP_SUB:
  1107. begin
  1108. list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,reg.reglo));
  1109. list.concat(taicpu.op_const_reg(A_SUBX,S_L,highvalue,reg.reglo));
  1110. end;
  1111. OP_XOR:
  1112. begin
  1113. list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,reg.reglo));
  1114. list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,reg.reglo));
  1115. end;
  1116. end; { end case }
  1117. end;
  1118. begin
  1119. cg := tcg68k.create;
  1120. cg64 :=tcg64f68k.create;
  1121. end.
  1122. {
  1123. $Log$
  1124. Revision 1.6 2002-09-07 15:25:12 peter
  1125. * old logs removed and tabs fixed
  1126. Revision 1.5 2002/08/19 18:17:48 carl
  1127. + optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
  1128. * more fixes to m68k for 64-bit operations
  1129. Revision 1.4 2002/08/16 14:24:59 carl
  1130. * issameref() to test if two references are the same (then emit no opcodes)
  1131. + ret_in_reg to replace ret_in_acc
  1132. (fix some register allocation bugs at the same time)
  1133. + save_std_register now has an extra parameter which is the
  1134. usedinproc registers
  1135. Revision 1.3 2002/08/15 08:13:54 carl
  1136. - a_load_sym_ofs_reg removed
  1137. * loadvmt now calls loadaddr_ref_reg instead
  1138. Revision 1.2 2002/08/14 19:16:34 carl
  1139. + m68k type conversion nodes
  1140. + started some mathematical nodes
  1141. * out of bound references should now be handled correctly
  1142. Revision 1.1 2002/08/13 18:30:22 carl
  1143. * rename swatoperands to swapoperands
  1144. + m68k first compilable version (still needs a lot of testing):
  1145. assembler generator, system information , inline
  1146. assembler reader.
  1147. Revision 1.5 2002/08/12 15:08:43 carl
  1148. + stab register indexes for powerpc (moved from gdb to cpubase)
  1149. + tprocessor enumeration moved to cpuinfo
  1150. + linker in target_info is now a class
  1151. * many many updates for m68k (will soon start to compile)
  1152. - removed some ifdef or correct them for correct cpu
  1153. Revision 1.2 2002/08/05 17:27:52 carl
  1154. + updated m68k
  1155. Revision 1.1 2002/07/29 17:51:32 carl
  1156. + restart m68k support
  1157. }