cgcpu.pas 62 KB

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