cgcpu.pas 61 KB

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