cgcpu.pas 60 KB

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