cgcpu.pas 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
  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_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
  36. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);override;
  37. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
  38. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);override;
  39. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  40. procedure a_call_reg(list : TAsmList;reg : tregister);override;
  41. procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : tcgint;register : tregister);override;
  42. procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;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_loadmm_reg_cgpara(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: tcgint; reg: TRegister); override;
  56. // procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; 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 : tcgint;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 : tcgint);override;
  65. { generates overflow checking code for a node }
  66. procedure g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef); override;
  67. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  68. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
  69. // procedure g_restore_frame_pointer(list : TAsmList);override;
  70. // procedure g_return_from_proc(list : TAsmList;parasize : tcgint);override;
  71. procedure g_restore_registers(list:TAsmList);override;
  72. procedure g_save_registers(list:TAsmList);override;
  73. // procedure g_save_all_registers(list : TAsmList);override;
  74. // procedure g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);override;
  75. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  76. protected
  77. function fixref(list: TAsmList; var ref: treference): boolean;
  78. private
  79. { # Sign or zero extend the register to a full 32-bit value.
  80. The new value is left in the same register.
  81. }
  82. procedure sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
  83. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  84. end;
  85. tcg64f68k = class(tcg64f32)
  86. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG; size: tcgsize; regsrc,regdst : tregister64);override;
  87. procedure a_op64_const_reg(list : TAsmList;op:TOpCG; size: tcgsize; value : int64;regdst : tregister64);override;
  88. end;
  89. { This function returns true if the reference+offset is valid.
  90. Otherwise extra code must be generated to solve the reference.
  91. On the m68k, this verifies that the reference is valid
  92. (e.g : if index register is used, then the max displacement
  93. is 256 bytes, if only base is used, then max displacement
  94. is 32K
  95. }
  96. function isvalidrefoffset(const ref: treference): boolean;
  97. const
  98. TCGSize2OpSize: Array[tcgsize] of topsize =
  99. (S_NO,S_B,S_W,S_L,S_L,S_NO,S_B,S_W,S_L,S_L,S_NO,
  100. S_FS,S_FD,S_FX,S_NO,S_NO,
  101. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  102. procedure create_codegen;
  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 paramanager.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_load_reg_cgpara(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_load_reg');_cgpara
  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, cgpara.alignment);
  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_load_reg_cgpara(list,size,r,cgpara);
  215. end;
  216. procedure tcg68k.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);
  217. var
  218. pushsize : tcgsize;
  219. ref : treference;
  220. begin
  221. {$ifdef DEBUG_CHARLIE}
  222. // writeln('a_load_const');_cgpara
  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, cgpara.alignment);
  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_load_const_cgpara(list,size,a,cgpara);
  237. end;
  238. procedure tcg68k.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
  239. procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
  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(tcgint)) 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, tcgsize2size[paraloc^.size]);
  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 : tcgint;
  279. href : treference;
  280. begin
  281. {$ifdef DEBUG_CHARLIE}
  282. // writeln('a_load_ref');_cgpara
  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,cgpara.alignment);
  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_load_ref_cgpara(list,size,r,cgpara);
  307. end;
  308. procedure tcg68k.a_loadaddr_ref_cgpara(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_loadaddr_ref');_cgpara
  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_loadaddr_ref_cgpara(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; weak: boolean);
  386. var
  387. sym: tasmsymbol;
  388. begin
  389. if not(weak) then
  390. sym:=current_asmdata.RefAsmSymbol(s)
  391. else
  392. sym:=current_asmdata.WeakRefAsmSymbol(s);
  393. list.concat(taicpu.op_sym(A_JSR,S_NO,current_asmdata.RefAsmSymbol(s)));
  394. end;
  395. procedure tcg68k.a_call_reg(list : TAsmList;reg: tregister);
  396. var
  397. tmpref : treference;
  398. tmpreg : tregister;
  399. begin
  400. {$ifdef DEBUG_CHARLIE}
  401. list.concat(tai_comment.create(strpnew('a_call_reg')));
  402. {$endif}
  403. if isaddressregister(reg) then
  404. begin
  405. { if we have an address register, we can jump to the address directly }
  406. reference_reset_base(tmpref,reg,0,4);
  407. end
  408. else
  409. begin
  410. { if we have a data register, we need to move it to an address register first }
  411. tmpreg:=getaddressregister(list);
  412. reference_reset_base(tmpref,tmpreg,0,4);
  413. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,tmpreg));
  414. end;
  415. list.concat(taicpu.op_ref(A_JSR,S_NO,tmpref));
  416. end;
  417. procedure tcg68k.a_load_const_reg(list : TAsmList;size : tcgsize;a : tcgint;register : tregister);
  418. begin
  419. {$ifdef DEBUG_CHARLIE}
  420. // writeln('a_load_const_reg');
  421. {$endif DEBUG_CHARLIE}
  422. if isaddressregister(register) then
  423. begin
  424. list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
  425. end
  426. else
  427. if a = 0 then
  428. list.concat(taicpu.op_reg(A_CLR,S_L,register))
  429. else
  430. begin
  431. if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
  432. list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,longint(a),register))
  433. else
  434. list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
  435. end;
  436. end;
  437. procedure tcg68k.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);
  438. begin
  439. {$ifdef DEBUG_CHARLIE}
  440. list.concat(tai_comment.create(strpnew('a_load_const_ref')));
  441. {$endif DEBUG_CHARLIE}
  442. list.concat(taicpu.op_const_ref(A_MOVE,S_L,longint(a),ref));
  443. end;
  444. procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
  445. var
  446. href : treference;
  447. begin
  448. href := ref;
  449. fixref(list,href);
  450. {$ifdef DEBUG_CHARLIE}
  451. list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
  452. {$endif DEBUG_CHARLIE}
  453. { move to destination reference }
  454. list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
  455. end;
  456. procedure tcg68k.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
  457. var
  458. aref: treference;
  459. bref: treference;
  460. begin
  461. aref := sref;
  462. bref := dref;
  463. fixref(list,aref);
  464. fixref(list,bref);
  465. {$ifdef DEBUG_CHARLIE}
  466. // writeln('a_load_ref_ref');
  467. {$endif DEBUG_CHARLIE}
  468. list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],aref,bref));
  469. end;
  470. procedure tcg68k.a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
  471. begin
  472. { move to destination register }
  473. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2));
  474. { zero/sign extend register to 32-bit }
  475. sign_extend(list, fromsize, reg2);
  476. end;
  477. procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
  478. var
  479. href : treference;
  480. begin
  481. href := ref;
  482. fixref(list,href);
  483. list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
  484. { extend the value in the register }
  485. sign_extend(list, tosize, register);
  486. end;
  487. procedure tcg68k.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  488. var
  489. href : treference;
  490. // p: pointer;
  491. begin
  492. { TODO: FIX ME!!! take a look on this mess again...}
  493. // if getregtype(r)=R_ADDRESSREGISTER then
  494. // begin
  495. // writeln('address reg?!?');
  496. // p:=nil; dword(p^):=0; {DEBUG CODE... :D )
  497. // internalerror(2002072901);
  498. // end;
  499. href:=ref;
  500. fixref(list, href);
  501. list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,r));
  502. end;
  503. procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
  504. begin
  505. { in emulation mode, only 32-bit single is supported }
  506. if cs_fp_emulation in current_settings.moduleswitches then
  507. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
  508. else
  509. list.concat(taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2));
  510. end;
  511. procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
  512. var
  513. opsize : topsize;
  514. href : treference;
  515. tmpreg : tregister;
  516. begin
  517. opsize := tcgsize2opsize[fromsize];
  518. { extended is not supported, since it is not available on Coldfire }
  519. if opsize = S_FX then
  520. internalerror(20020729);
  521. href := ref;
  522. fixref(list,href);
  523. { in emulation mode, only 32-bit single is supported }
  524. if cs_fp_emulation in current_settings.moduleswitches then
  525. list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
  526. else
  527. begin
  528. list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
  529. if (tosize < fromsize) then
  530. a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
  531. end;
  532. end;
  533. procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
  534. var
  535. opsize : topsize;
  536. begin
  537. opsize := tcgsize2opsize[tosize];
  538. { extended is not supported, since it is not available on Coldfire }
  539. if opsize = S_FX then
  540. internalerror(20020729);
  541. { in emulation mode, only 32-bit single is supported }
  542. if cs_fp_emulation in current_settings.moduleswitches then
  543. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
  544. else
  545. list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
  546. end;
  547. procedure tcg68k.a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);
  548. begin
  549. internalerror(20020729);
  550. end;
  551. procedure tcg68k.a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle);
  552. begin
  553. internalerror(20020729);
  554. end;
  555. procedure tcg68k.a_loadmm_reg_ref(list: TAsmList;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle);
  556. begin
  557. internalerror(20020729);
  558. end;
  559. procedure tcg68k.a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle);
  560. begin
  561. internalerror(20020729);
  562. end;
  563. procedure tcg68k.a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister);
  564. var
  565. scratch_reg : tregister;
  566. scratch_reg2: tregister;
  567. opcode : tasmop;
  568. r,r2 : Tregister;
  569. begin
  570. optimize_op_const(op, a);
  571. opcode := topcg2tasmop[op];
  572. case op of
  573. OP_NONE :
  574. begin
  575. { Opcode is optimized away }
  576. end;
  577. OP_MOVE :
  578. begin
  579. { Optimized, replaced with a simple load }
  580. a_load_const_reg(list,size,a,reg);
  581. end;
  582. OP_ADD :
  583. begin
  584. if (a >= 1) and (a <= 8) then
  585. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,a, reg))
  586. else
  587. begin
  588. { all others, including coldfire }
  589. list.concat(taicpu.op_const_reg(A_ADD,S_L,a, reg));
  590. end;
  591. end;
  592. OP_AND,
  593. OP_OR:
  594. begin
  595. list.concat(taicpu.op_const_reg(topcg2tasmop[op],S_L,longint(a), reg));
  596. end;
  597. OP_DIV :
  598. begin
  599. internalerror(20020816);
  600. end;
  601. OP_IDIV :
  602. begin
  603. internalerror(20020816);
  604. end;
  605. OP_IMUL :
  606. begin
  607. if current_settings.cputype = cpu_MC68000 then
  608. begin
  609. r:=NR_D0;
  610. r2:=NR_D1;
  611. cg.getcpuregister(list,NR_D0);
  612. cg.getcpuregister(list,NR_D1);
  613. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
  614. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
  615. cg.a_call_name(list,'FPC_MUL_LONGINT',false);
  616. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
  617. cg.ungetcpuregister(list,r);
  618. cg.ungetcpuregister(list,r2);
  619. end
  620. else
  621. begin
  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(A_MULS,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(A_MULS,S_L,a,reg));
  631. end;
  632. end;
  633. OP_MUL :
  634. begin
  635. if current_settings.cputype = cpu_MC68000 then
  636. begin
  637. r:=NR_D0;
  638. r2:=NR_D1;
  639. cg.getcpuregister(list,NR_D0);
  640. cg.getcpuregister(list,NR_D1);
  641. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
  642. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
  643. cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
  644. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
  645. cg.ungetcpuregister(list,r);
  646. cg.ungetcpuregister(list,r2);
  647. end
  648. else
  649. begin
  650. if (isaddressregister(reg)) then
  651. begin
  652. scratch_reg := getintregister(list,OS_INT);
  653. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  654. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,scratch_reg));
  655. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  656. end
  657. else
  658. list.concat(taicpu.op_const_reg(A_MULU,S_L,a,reg));
  659. end;
  660. end;
  661. OP_SAR,
  662. OP_SHL,
  663. OP_SHR :
  664. begin
  665. if (a >= 1) and (a <= 8) then
  666. begin
  667. { now allowed to shift an address register }
  668. if (isaddressregister(reg)) then
  669. begin
  670. scratch_reg := getintregister(list,OS_INT);
  671. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
  672. list.concat(taicpu.op_const_reg(opcode,S_L,a, scratch_reg));
  673. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
  674. end
  675. else
  676. list.concat(taicpu.op_const_reg(opcode,S_L,a, reg));
  677. end
  678. else
  679. begin
  680. { we must load the data into a register ... :() }
  681. scratch_reg := cg.getintregister(list,OS_INT);
  682. list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, scratch_reg));
  683. { again... since shifting with address register is not allowed }
  684. if (isaddressregister(reg)) then
  685. begin
  686. scratch_reg2 := cg.getintregister(list,OS_INT);
  687. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg2));
  688. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, scratch_reg2));
  689. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg2,reg));
  690. end
  691. else
  692. list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, reg));
  693. end;
  694. end;
  695. OP_SUB :
  696. begin
  697. if (a >= 1) and (a <= 8) then
  698. list.concat(taicpu.op_const_reg(A_SUBQ,S_L,a,reg))
  699. else
  700. begin
  701. { all others, including coldfire }
  702. list.concat(taicpu.op_const_reg(A_SUB,S_L,a, reg));
  703. end;
  704. end;
  705. OP_XOR :
  706. begin
  707. list.concat(taicpu.op_const_reg(A_EORI,S_L,a, reg));
  708. end;
  709. else
  710. internalerror(20020729);
  711. end;
  712. end;
  713. {
  714. procedure tcg68k.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
  715. var
  716. opcode: tasmop;
  717. begin
  718. writeln('a_op_const_ref');
  719. optimize_op_const(op, a);
  720. opcode := topcg2tasmop[op];
  721. case op of
  722. OP_NONE :
  723. begin
  724. { opcode was optimized away }
  725. end;
  726. OP_MOVE :
  727. begin
  728. { Optimized, replaced with a simple load }
  729. a_load_const_ref(list,size,a,ref);
  730. end;
  731. else
  732. begin
  733. internalerror(2007010101);
  734. end;
  735. end;
  736. end;
  737. }
  738. procedure tcg68k.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister);
  739. var
  740. hreg1,hreg2,r,r2: tregister;
  741. begin
  742. case op of
  743. OP_ADD :
  744. begin
  745. if current_settings.cputype = cpu_ColdFire then
  746. begin
  747. { operation only allowed only a longword }
  748. sign_extend(list, size, reg1);
  749. sign_extend(list, size, reg2);
  750. list.concat(taicpu.op_reg_reg(A_ADD,S_L,reg1, reg2));
  751. end
  752. else
  753. begin
  754. list.concat(taicpu.op_reg_reg(A_ADD,TCGSize2OpSize[size],reg1, reg2));
  755. end;
  756. end;
  757. OP_AND,OP_OR,
  758. OP_SAR,OP_SHL,
  759. OP_SHR,OP_SUB,OP_XOR :
  760. begin
  761. { load to data registers }
  762. if (isaddressregister(reg1)) then
  763. begin
  764. hreg1 := getintregister(list,OS_INT);
  765. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  766. end
  767. else
  768. hreg1 := reg1;
  769. if (isaddressregister(reg2)) then
  770. begin
  771. hreg2:= getintregister(list,OS_INT);
  772. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  773. end
  774. else
  775. hreg2 := reg2;
  776. if current_settings.cputype = cpu_ColdFire then
  777. begin
  778. { operation only allowed only a longword }
  779. {!***************************************
  780. in the case of shifts, the value to
  781. shift by, should already be valid, so
  782. no need to sign extend the value
  783. !
  784. }
  785. if op in [OP_AND,OP_OR,OP_SUB,OP_XOR] then
  786. sign_extend(list, size, hreg1);
  787. sign_extend(list, size, hreg2);
  788. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],S_L,hreg1, hreg2));
  789. end
  790. else
  791. begin
  792. list.concat(taicpu.op_reg_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg1, hreg2));
  793. end;
  794. { move back result into destination register }
  795. if reg2 <> hreg2 then
  796. begin
  797. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  798. end;
  799. end;
  800. OP_DIV :
  801. begin
  802. internalerror(20020816);
  803. end;
  804. OP_IDIV :
  805. begin
  806. internalerror(20020816);
  807. end;
  808. OP_IMUL :
  809. begin
  810. sign_extend(list, size,reg1);
  811. sign_extend(list, size,reg2);
  812. if current_settings.cputype = cpu_MC68000 then
  813. begin
  814. r:=NR_D0;
  815. r2:=NR_D1;
  816. cg.getcpuregister(list,NR_D0);
  817. cg.getcpuregister(list,NR_D1);
  818. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
  819. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
  820. cg.a_call_name(list,'FPC_MUL_LONGINT',false);
  821. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
  822. cg.ungetcpuregister(list,r);
  823. cg.ungetcpuregister(list,r2);
  824. end
  825. else
  826. begin
  827. // writeln('doing 68020');
  828. if (isaddressregister(reg1)) then
  829. hreg1 := getintregister(list,OS_INT)
  830. else
  831. hreg1 := reg1;
  832. if (isaddressregister(reg2)) then
  833. hreg2:= getintregister(list,OS_INT)
  834. else
  835. hreg2 := reg2;
  836. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  837. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  838. list.concat(taicpu.op_reg_reg(A_MULS,S_L,reg1,reg2));
  839. { move back result into destination register }
  840. if reg2 <> hreg2 then
  841. begin
  842. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  843. end;
  844. end;
  845. end;
  846. OP_MUL :
  847. begin
  848. sign_extend(list, size,reg1);
  849. sign_extend(list, size,reg2);
  850. if current_settings.cputype = cpu_MC68000 then
  851. begin
  852. r:=NR_D0;
  853. r2:=NR_D1;
  854. cg.getcpuregister(list,NR_D0);
  855. cg.getcpuregister(list,NR_D1);
  856. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
  857. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
  858. cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
  859. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
  860. cg.ungetcpuregister(list,r);
  861. cg.ungetcpuregister(list,r2);
  862. end
  863. else
  864. begin
  865. if (isaddressregister(reg1)) then
  866. begin
  867. hreg1 := cg.getintregister(list,OS_INT);
  868. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
  869. end
  870. else
  871. hreg1 := reg1;
  872. if (isaddressregister(reg2)) then
  873. begin
  874. hreg2:= cg.getintregister(list,OS_INT);
  875. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  876. end
  877. else
  878. hreg2 := reg2;
  879. list.concat(taicpu.op_reg_reg(A_MULU,S_L,reg1,reg2));
  880. { move back result into destination register }
  881. if reg2<>hreg2 then
  882. begin
  883. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  884. end;
  885. end;
  886. end;
  887. OP_NEG,
  888. OP_NOT :
  889. Begin
  890. { if there are two operands, move the register,
  891. since the operation will only be done on the result
  892. register.
  893. }
  894. if reg1 <> NR_NO then
  895. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,reg1,reg2);
  896. if (isaddressregister(reg2)) then
  897. begin
  898. hreg2 := getintregister(list,OS_INT);
  899. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
  900. end
  901. else
  902. hreg2 := reg2;
  903. { coldfire only supports long version }
  904. if current_settings.cputype = cpu_ColdFire then
  905. begin
  906. sign_extend(list, size,hreg2);
  907. list.concat(taicpu.op_reg(topcg2tasmop[op],S_L,hreg2));
  908. end
  909. else
  910. begin
  911. list.concat(taicpu.op_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg2));
  912. end;
  913. if reg2 <> hreg2 then
  914. begin
  915. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
  916. end;
  917. end;
  918. else
  919. internalerror(20020729);
  920. end;
  921. end;
  922. procedure tcg68k.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  923. l : tasmlabel);
  924. var
  925. hregister : tregister;
  926. begin
  927. if a = 0 then
  928. begin
  929. list.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[size],reg));
  930. end
  931. else
  932. begin
  933. if (current_settings.cputype = cpu_ColdFire) then
  934. begin
  935. {
  936. only longword comparison is supported,
  937. and only on data registers.
  938. }
  939. hregister := getintregister(list,OS_INT);
  940. { always move to a data register }
  941. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,hregister));
  942. { sign/zero extend the register }
  943. sign_extend(list, size,hregister);
  944. list.concat(taicpu.op_const_reg(A_CMPI,S_L,a,hregister));
  945. end
  946. else
  947. begin
  948. list.concat(taicpu.op_const_reg(A_CMPI,TCGSize2OpSize[size],a,reg));
  949. end;
  950. end;
  951. { emit the actual jump to the label }
  952. a_jmp_cond(list,cmp_op,l);
  953. end;
  954. procedure tcg68k.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  955. begin
  956. list.concat(taicpu.op_reg_reg(A_CMP,tcgsize2opsize[size],reg1,reg2));
  957. { emit the actual jump to the label }
  958. a_jmp_cond(list,cmp_op,l);
  959. end;
  960. procedure tcg68k.a_jmp_always(list : TAsmList;l: tasmlabel);
  961. var
  962. ai: taicpu;
  963. begin
  964. ai := Taicpu.op_sym(A_JMP,S_NO,l);
  965. ai.is_jmp := true;
  966. list.concat(ai);
  967. end;
  968. procedure tcg68k.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  969. var
  970. ai : taicpu;
  971. begin
  972. ai := Taicpu.op_sym(A_BXX,S_NO,l);
  973. ai.SetCondition(flags_to_cond(f));
  974. ai.is_jmp := true;
  975. list.concat(ai);
  976. end;
  977. procedure tcg68k.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
  978. var
  979. ai : taicpu;
  980. hreg : tregister;
  981. begin
  982. { move to a Dx register? }
  983. if (isaddressregister(reg)) then
  984. begin
  985. hreg := getintregister(list,OS_INT);
  986. a_load_const_reg(list,size,0,hreg);
  987. ai:=Taicpu.Op_reg(A_Sxx,S_B,hreg);
  988. ai.SetCondition(flags_to_cond(f));
  989. list.concat(ai);
  990. if (current_settings.cputype = cpu_ColdFire) then
  991. begin
  992. { neg.b does not exist on the Coldfire
  993. so we need to sign extend the value
  994. before doing a neg.l
  995. }
  996. list.concat(taicpu.op_reg(A_EXTB,S_L,hreg));
  997. list.concat(taicpu.op_reg(A_NEG,S_L,hreg));
  998. end
  999. else
  1000. begin
  1001. list.concat(taicpu.op_reg(A_NEG,S_B,hreg));
  1002. end;
  1003. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg,reg));
  1004. end
  1005. else
  1006. begin
  1007. a_load_const_reg(list,size,0,reg);
  1008. ai:=Taicpu.Op_reg(A_Sxx,S_B,reg);
  1009. ai.SetCondition(flags_to_cond(f));
  1010. list.concat(ai);
  1011. if (current_settings.cputype = cpu_ColdFire) then
  1012. begin
  1013. { neg.b does not exist on the Coldfire
  1014. so we need to sign extend the value
  1015. before doing a neg.l
  1016. }
  1017. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  1018. list.concat(taicpu.op_reg(A_NEG,S_L,reg));
  1019. end
  1020. else
  1021. begin
  1022. list.concat(taicpu.op_reg(A_NEG,S_B,reg));
  1023. end;
  1024. end;
  1025. end;
  1026. procedure tcg68k.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1027. var
  1028. helpsize : longint;
  1029. i : byte;
  1030. reg8,reg32 : tregister;
  1031. swap : boolean;
  1032. hregister : tregister;
  1033. iregister : tregister;
  1034. jregister : tregister;
  1035. hp1 : treference;
  1036. hp2 : treference;
  1037. hl : tasmlabel;
  1038. hl2: tasmlabel;
  1039. popaddress : boolean;
  1040. srcref,dstref : treference;
  1041. begin
  1042. popaddress := false;
  1043. // writeln('concatcopy:',len);
  1044. { this should never occur }
  1045. if len > 65535 then
  1046. internalerror(0);
  1047. hregister := getintregister(list,OS_INT);
  1048. // if delsource then
  1049. // reference_release(list,source);
  1050. { from 12 bytes movs is being used }
  1051. if {(not loadref) and} ((len<=8) or (not(cs_opt_size in current_settings.optimizerswitches) and (len<=12))) then
  1052. begin
  1053. srcref := source;
  1054. dstref := dest;
  1055. helpsize:=len div 4;
  1056. { move a dword x times }
  1057. for i:=1 to helpsize do
  1058. begin
  1059. a_load_ref_reg(list,OS_INT,OS_INT,srcref,hregister);
  1060. a_load_reg_ref(list,OS_INT,OS_INT,hregister,dstref);
  1061. inc(srcref.offset,4);
  1062. inc(dstref.offset,4);
  1063. dec(len,4);
  1064. end;
  1065. { move a word }
  1066. if len>1 then
  1067. begin
  1068. a_load_ref_reg(list,OS_16,OS_16,srcref,hregister);
  1069. a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
  1070. inc(srcref.offset,2);
  1071. inc(dstref.offset,2);
  1072. dec(len,2);
  1073. end;
  1074. { move a single byte }
  1075. if len>0 then
  1076. begin
  1077. a_load_ref_reg(list,OS_8,OS_8,srcref,hregister);
  1078. a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
  1079. end
  1080. end
  1081. else
  1082. begin
  1083. iregister:=getaddressregister(list);
  1084. jregister:=getaddressregister(list);
  1085. { reference for move (An)+,(An)+ }
  1086. reference_reset(hp1,source.alignment);
  1087. hp1.base := iregister; { source register }
  1088. hp1.direction := dir_inc;
  1089. reference_reset(hp2,dest.alignment);
  1090. hp2.base := jregister;
  1091. hp2.direction := dir_inc;
  1092. { iregister = source }
  1093. { jregister = destination }
  1094. { if loadref then
  1095. cg.a_load_ref_reg(list,OS_INT,OS_INT,source,iregister)
  1096. else}
  1097. a_loadaddr_ref_reg(list,source,iregister);
  1098. a_loadaddr_ref_reg(list,dest,jregister);
  1099. { double word move only on 68020+ machines }
  1100. { because of possible alignment problems }
  1101. { use fast loop mode }
  1102. if (current_settings.cputype=cpu_MC68020) then
  1103. begin
  1104. helpsize := len - len mod 4;
  1105. len := len mod 4;
  1106. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize div 4,hregister));
  1107. current_asmdata.getjumplabel(hl2);
  1108. a_jmp_always(list,hl2);
  1109. current_asmdata.getjumplabel(hl);
  1110. a_label(list,hl);
  1111. list.concat(taicpu.op_ref_ref(A_MOVE,S_L,hp1,hp2));
  1112. a_label(list,hl2);
  1113. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  1114. if len > 1 then
  1115. begin
  1116. dec(len,2);
  1117. list.concat(taicpu.op_ref_ref(A_MOVE,S_W,hp1,hp2));
  1118. end;
  1119. if len = 1 then
  1120. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  1121. end
  1122. else
  1123. begin
  1124. { Fast 68010 loop mode with no possible alignment problems }
  1125. helpsize := len;
  1126. list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize,hregister));
  1127. current_asmdata.getjumplabel(hl2);
  1128. a_jmp_always(list,hl2);
  1129. current_asmdata.getjumplabel(hl);
  1130. a_label(list,hl);
  1131. list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
  1132. a_label(list,hl2);
  1133. list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
  1134. end;
  1135. { restore the registers that we have just used olny if they are used! }
  1136. if jregister = NR_A1 then
  1137. hp2.base := NR_NO;
  1138. if iregister = NR_A0 then
  1139. hp1.base := NR_NO;
  1140. // reference_release(list,hp1);
  1141. // reference_release(list,hp2);
  1142. end;
  1143. // if delsource then
  1144. // tg.ungetiftemp(list,source);
  1145. end;
  1146. procedure tcg68k.g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef);
  1147. begin
  1148. end;
  1149. procedure tcg68k.g_proc_entry(list: TAsmList; localsize: longint; nostackframe:boolean);
  1150. var
  1151. r,rsp: TRegister;
  1152. ref : TReference;
  1153. begin
  1154. {$ifdef DEBUG_CHARLIE}
  1155. // writeln('proc entry, localsize:',localsize);
  1156. {$endif DEBUG_CHARLIE}
  1157. if not nostackframe then
  1158. begin
  1159. if localsize<>0 then
  1160. begin
  1161. { size can't be negative }
  1162. if (localsize < 0) then
  1163. internalerror(2006122601);
  1164. { Not to complicate the code generator too much, and since some }
  1165. { of the systems only support this format, the localsize cannot }
  1166. { exceed 32K in size. }
  1167. if (localsize > high(smallint)) then
  1168. CGMessage(cg_e_localsize_too_big);
  1169. list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,-localsize));
  1170. end
  1171. else
  1172. begin
  1173. list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,0));
  1174. (*
  1175. { FIXME! - Carl's original code uses this method. However,
  1176. according to the 68060 users manual, a LINK is faster than
  1177. two moves. So, use a link in #0 case too, for now. I'm not
  1178. really sure tho', that LINK supports #0 disposition, but i
  1179. see no reason why it shouldn't support it. (KB) }
  1180. { when localsize = 0, use two moves, instead of link }
  1181. r:=NR_FRAME_POINTER_REG;
  1182. rsp:=NR_STACK_POINTER_REG;
  1183. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1184. ref.direction:=dir_dec;
  1185. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,r,ref));
  1186. list.concat(taicpu.op_reg_reg(A_MOVE,S_L,rsp,r));
  1187. *)
  1188. end;
  1189. end;
  1190. end;
  1191. { procedure tcg68k.g_restore_frame_pointer(list : TAsmList);
  1192. var
  1193. r:Tregister;
  1194. begin
  1195. r:=NR_FRAME_POINTER_REG;
  1196. list.concat(taicpu.op_reg(A_UNLK,S_NO,r));
  1197. end;
  1198. }
  1199. procedure tcg68k.g_proc_exit(list : TAsmList; parasize: longint; nostackframe: boolean);
  1200. var
  1201. // r,hregister : TRegister;
  1202. localsize: tcgint;
  1203. spr : TRegister;
  1204. fpr : TRegister;
  1205. ref : TReference;
  1206. begin
  1207. if not nostackframe then
  1208. begin
  1209. localsize := current_procinfo.calc_stackframe_size;
  1210. {$ifdef DEBUG_CHARLIE}
  1211. // writeln('proc exit with stackframe, size:',localsize,' parasize:',parasize);
  1212. {$endif DEBUG_CHARLIE}
  1213. list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG));
  1214. parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is
  1215. correct here, but at least it looks less
  1216. hacky, and makes some sense (KB) }
  1217. if (parasize<>0) then
  1218. begin
  1219. { only 68020+ supports RTD, so this needs another code path
  1220. for 68000 and Coldfire (KB) }
  1221. { TODO: 68020+ only code generation, without fallback}
  1222. list.concat(taicpu.op_const(A_RTD,S_NO,parasize));
  1223. end
  1224. else
  1225. list.concat(taicpu.op_none(A_RTS,S_NO));
  1226. end
  1227. else
  1228. begin
  1229. {$ifdef DEBUG_CHARLIE}
  1230. // writeln('proc exit, no stackframe');
  1231. {$endif DEBUG_CHARLIE}
  1232. list.concat(taicpu.op_none(A_RTS,S_NO));
  1233. end;
  1234. // writeln('g_proc_exit');
  1235. { Routines with the poclearstack flag set use only a ret.
  1236. also routines with parasize=0 }
  1237. (*
  1238. if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  1239. begin
  1240. { complex return values are removed from stack in C code PM }
  1241. if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
  1242. list.concat(taicpu.op_const(A_RTD,S_NO,4))
  1243. else
  1244. list.concat(taicpu.op_none(A_RTS,S_NO));
  1245. end
  1246. else if (parasize=0) then
  1247. begin
  1248. list.concat(taicpu.op_none(A_RTS,S_NO));
  1249. end
  1250. else
  1251. begin
  1252. { return with immediate size possible here
  1253. signed!
  1254. RTD is not supported on the coldfire }
  1255. if (current_settings.cputype=cpu_MC68020) and (parasize<$7FFF) then
  1256. list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
  1257. { manually restore the stack }
  1258. else
  1259. begin
  1260. { We must pull the PC Counter from the stack, before }
  1261. { restoring the stack pointer, otherwise the PC would }
  1262. { point to nowhere! }
  1263. { save the PC counter (pop it from the stack) }
  1264. hregister:=NR_A3;
  1265. cg.a_reg_alloc(list,hregister);
  1266. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1267. ref.direction:=dir_inc;
  1268. list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
  1269. { can we do a quick addition ... }
  1270. r:=NR_SP;
  1271. if (parasize > 0) and (parasize < 9) then
  1272. list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
  1273. else { nope ... }
  1274. list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
  1275. { restore the PC counter (push it on the stack) }
  1276. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1277. ref.direction:=dir_dec;
  1278. cg.a_reg_alloc(list,hregister);
  1279. list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
  1280. list.concat(taicpu.op_none(A_RTS,S_NO));
  1281. end;
  1282. end;
  1283. *)
  1284. end;
  1285. procedure Tcg68k.g_save_registers(list:TAsmList);
  1286. var
  1287. tosave : tcpuregisterset;
  1288. ref : treference;
  1289. begin
  1290. {!!!!!
  1291. tosave:=std_saved_registers;
  1292. { only save the registers which are not used and must be saved }
  1293. tosave:=tosave*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
  1294. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1295. ref.direction:=dir_dec;
  1296. if tosave<>[] then
  1297. list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,tosave,ref));
  1298. }
  1299. end;
  1300. procedure Tcg68k.g_restore_registers(list:TAsmList);
  1301. var
  1302. torestore : tcpuregisterset;
  1303. r:Tregister;
  1304. ref : treference;
  1305. begin
  1306. {!!!!!!!!
  1307. torestore:=std_saved_registers;
  1308. { should be intersected with used regs, no ? }
  1309. torestore:=torestore*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
  1310. reference_reset_base(ref,NR_STACK_POINTER_REG,0);
  1311. ref.direction:=dir_inc;
  1312. if torestore<>[] then
  1313. list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,ref,torestore));
  1314. }
  1315. end;
  1316. {
  1317. procedure tcg68k.g_save_all_registers(list : TAsmList);
  1318. begin
  1319. end;
  1320. procedure tcg68k.g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);
  1321. begin
  1322. end;
  1323. }
  1324. procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
  1325. begin
  1326. case _oldsize of
  1327. { sign extend }
  1328. OS_S8:
  1329. begin
  1330. if (isaddressregister(reg)) then
  1331. internalerror(20020729);
  1332. if (current_settings.cputype = cpu_MC68000) then
  1333. begin
  1334. list.concat(taicpu.op_reg(A_EXT,S_W,reg));
  1335. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  1336. end
  1337. else
  1338. begin
  1339. // list.concat(tai_comment.create(strpnew('sign extend byte')));
  1340. list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
  1341. end;
  1342. end;
  1343. OS_S16:
  1344. begin
  1345. if (isaddressregister(reg)) then
  1346. internalerror(20020729);
  1347. // list.concat(tai_comment.create(strpnew('sign extend word')));
  1348. list.concat(taicpu.op_reg(A_EXT,S_L,reg));
  1349. end;
  1350. { zero extend }
  1351. OS_8:
  1352. begin
  1353. // list.concat(tai_comment.create(strpnew('zero extend byte')));
  1354. list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
  1355. end;
  1356. OS_16:
  1357. begin
  1358. // list.concat(tai_comment.create(strpnew('zero extend word')));
  1359. list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
  1360. end;
  1361. end; { otherwise the size is already correct }
  1362. end;
  1363. procedure tcg68k.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1364. var
  1365. ai : taicpu;
  1366. begin
  1367. if cond=OC_None then
  1368. ai := Taicpu.Op_sym(A_JMP,S_NO,l)
  1369. else
  1370. begin
  1371. ai:=Taicpu.Op_sym(A_Bxx,S_NO,l);
  1372. ai.SetCondition(TOpCmp2AsmCond[cond]);
  1373. end;
  1374. ai.is_jmp:=true;
  1375. list.concat(ai);
  1376. end;
  1377. procedure tcg68k.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1378. {
  1379. procedure loadvmttor11;
  1380. var
  1381. href : treference;
  1382. begin
  1383. reference_reset_base(href,NR_R3,0);
  1384. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
  1385. end;
  1386. procedure op_onr11methodaddr;
  1387. var
  1388. href : treference;
  1389. begin
  1390. if (procdef.extnumber=$ffff) then
  1391. Internalerror(200006139);
  1392. { call/jmp vmtoffs(%eax) ; method offs }
  1393. reference_reset_base(href,NR_R11,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
  1394. if not((longint(href.offset) >= low(smallint)) and
  1395. (longint(href.offset) <= high(smallint))) then
  1396. begin
  1397. list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
  1398. smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
  1399. href.offset := smallint(href.offset and $ffff);
  1400. end;
  1401. list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href));
  1402. list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
  1403. list.concat(taicpu.op_none(A_BCTR));
  1404. end;
  1405. }
  1406. var
  1407. make_global : boolean;
  1408. begin
  1409. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1410. Internalerror(200006137);
  1411. if not assigned(procdef.struct) or
  1412. (procdef.procoptions*[po_classmethod, po_staticmethod,
  1413. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  1414. Internalerror(200006138);
  1415. if procdef.owner.symtabletype<>ObjectSymtable then
  1416. Internalerror(200109191);
  1417. make_global:=false;
  1418. if (not current_module.is_unit) or
  1419. create_smartlink or
  1420. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  1421. make_global:=true;
  1422. if make_global then
  1423. List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
  1424. else
  1425. List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
  1426. { set param1 interface to self }
  1427. // g_adjust_self_value(list,procdef,ioffset);
  1428. { case 4 }
  1429. if (po_virtualmethod in procdef.procoptions) and
  1430. not is_objectpascal_helper(procdef.struct) then
  1431. begin
  1432. // loadvmttor11;
  1433. // op_onr11methodaddr;
  1434. end
  1435. { case 0 }
  1436. else
  1437. // list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
  1438. List.concat(Tai_symbol_end.Createname(labelname));
  1439. end;
  1440. {****************************************************************************}
  1441. { TCG64F68K }
  1442. {****************************************************************************}
  1443. procedure tcg64f68k.a_op64_reg_reg(list : TAsmList;op:TOpCG;size: tcgsize; regsrc,regdst : tregister64);
  1444. var
  1445. hreg1, hreg2 : tregister;
  1446. opcode : tasmop;
  1447. begin
  1448. // writeln('a_op64_reg_reg');
  1449. opcode := topcg2tasmop[op];
  1450. case op of
  1451. OP_ADD :
  1452. begin
  1453. { if one of these three registers is an address
  1454. register, we'll really get into problems!
  1455. }
  1456. if isaddressregister(regdst.reglo) or
  1457. isaddressregister(regdst.reghi) or
  1458. isaddressregister(regsrc.reghi) then
  1459. internalerror(20020817);
  1460. list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
  1461. list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
  1462. end;
  1463. OP_AND,OP_OR :
  1464. begin
  1465. { at least one of the registers must be a data register }
  1466. if (isaddressregister(regdst.reglo) and
  1467. isaddressregister(regsrc.reglo)) or
  1468. (isaddressregister(regsrc.reghi) and
  1469. isaddressregister(regdst.reghi))
  1470. then
  1471. internalerror(20020817);
  1472. cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
  1473. cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
  1474. end;
  1475. { this is handled in 1st pass for 32-bit cpu's (helper call) }
  1476. OP_IDIV,OP_DIV,
  1477. OP_IMUL,OP_MUL: internalerror(2002081701);
  1478. { this is also handled in 1st pass for 32-bit cpu's (helper call) }
  1479. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1480. OP_SUB:
  1481. begin
  1482. { if one of these three registers is an address
  1483. register, we'll really get into problems!
  1484. }
  1485. if isaddressregister(regdst.reglo) or
  1486. isaddressregister(regdst.reghi) or
  1487. isaddressregister(regsrc.reghi) then
  1488. internalerror(20020817);
  1489. list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
  1490. list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
  1491. end;
  1492. OP_XOR:
  1493. begin
  1494. if isaddressregister(regdst.reglo) or
  1495. isaddressregister(regsrc.reglo) or
  1496. isaddressregister(regsrc.reghi) or
  1497. isaddressregister(regdst.reghi) then
  1498. internalerror(20020817);
  1499. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
  1500. list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
  1501. end;
  1502. end; { end case }
  1503. end;
  1504. procedure tcg64f68k.a_op64_const_reg(list : TAsmList;op:TOpCG;size: tcgsize; value : int64;regdst : tregister64);
  1505. var
  1506. lowvalue : cardinal;
  1507. highvalue : cardinal;
  1508. hreg : tregister;
  1509. begin
  1510. // writeln('a_op64_const_reg');
  1511. { is it optimized out ? }
  1512. // if cg.optimize64_op_const_reg(list,op,value,reg) then
  1513. // exit;
  1514. lowvalue := cardinal(value);
  1515. highvalue:= value shr 32;
  1516. { the destination registers must be data registers }
  1517. if isaddressregister(regdst.reglo) or
  1518. isaddressregister(regdst.reghi) then
  1519. internalerror(20020817);
  1520. case op of
  1521. OP_ADD :
  1522. begin
  1523. hreg:=cg.getintregister(list,OS_INT);
  1524. list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
  1525. list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,regdst.reglo));
  1526. list.concat(taicpu.op_reg_reg(A_ADDX,S_L,hreg,regdst.reglo));
  1527. end;
  1528. OP_AND :
  1529. begin
  1530. list.concat(taicpu.op_const_reg(A_AND,S_L,lowvalue,regdst.reglo));
  1531. list.concat(taicpu.op_const_reg(A_AND,S_L,highvalue,regdst.reglo));
  1532. end;
  1533. OP_OR :
  1534. begin
  1535. list.concat(taicpu.op_const_reg(A_OR,S_L,lowvalue,regdst.reglo));
  1536. list.concat(taicpu.op_const_reg(A_OR,S_L,highvalue,regdst.reglo));
  1537. end;
  1538. { this is handled in 1st pass for 32-bit cpus (helper call) }
  1539. OP_IDIV,OP_DIV,
  1540. OP_IMUL,OP_MUL: internalerror(2002081701);
  1541. { this is also handled in 1st pass for 32-bit cpus (helper call) }
  1542. OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
  1543. OP_SUB:
  1544. begin
  1545. hreg:=cg.getintregister(list,OS_INT);
  1546. list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
  1547. list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,regdst.reglo));
  1548. list.concat(taicpu.op_reg_reg(A_SUBX,S_L,hreg,regdst.reglo));
  1549. end;
  1550. OP_XOR:
  1551. begin
  1552. list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,regdst.reglo));
  1553. list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,regdst.reglo));
  1554. end;
  1555. end; { end case }
  1556. end;
  1557. procedure create_codegen;
  1558. begin
  1559. cg := tcg68k.create;
  1560. cg64 :=tcg64f68k.create;
  1561. end;
  1562. end.