cgcpu.pas 63 KB

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