cgcpu.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. {
  2. Copyright (c) 2008 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generator for the AVR
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,symtype,symdef,
  23. cgbase,cgutils,cgobj,
  24. aasmbase,aasmcpu,aasmtai,aasmdata,
  25. parabase,
  26. cpubase,cpuinfo,node,cg64f32,rgcpu;
  27. type
  28. { tcgavr }
  29. tcgavr = class(tcg)
  30. { true, if the next arithmetic operation should modify the flags }
  31. cgsetflags : boolean;
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. function getintregister(list:TAsmList;size:Tcgsize):Tregister;override;
  35. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);override;
  36. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
  37. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
  38. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  39. procedure a_call_reg(list : TAsmList;reg: tregister);override;
  40. procedure a_call_ref(list : TAsmList;ref: treference);override;
  41. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
  42. procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  43. { move instructions }
  44. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);override;
  45. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  46. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  47. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  48. { comparison operations }
  49. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  50. l : tasmlabel);override;
  51. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  52. procedure a_jmp_name(list : TAsmList;const s : string); override;
  53. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  54. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  55. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  56. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  57. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  58. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  59. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
  60. procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);override;
  61. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
  62. procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
  63. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  64. procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
  65. // procedure g_save_registers(list : TAsmList);override;
  66. // procedure g_restore_registers(list : TAsmList);override;
  67. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  68. procedure fixref(list : TAsmList;var ref : treference);
  69. function normalize_ref(list:TAsmList;ref: treference):treference;
  70. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  71. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  72. procedure a_adjust_sp(list: TAsmList; value: longint);
  73. end;
  74. tcg64favr = class(tcg64f32)
  75. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  76. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  77. procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
  78. procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
  79. procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  80. procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  81. end;
  82. procedure create_codegen;
  83. const
  84. OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
  85. C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
  86. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,
  87. A_NONE,A_MUL,A_MULS,A_NEG,A_COM,A_OR,
  88. A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_ROL,A_ROR);
  89. implementation
  90. uses
  91. globals,verbose,systems,cutils,
  92. fmodule,
  93. symconst,symsym,
  94. tgobj,
  95. procinfo,cpupi,
  96. paramgr;
  97. procedure tcgavr.init_register_allocators;
  98. begin
  99. inherited init_register_allocators;
  100. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  101. [RS_R0,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  102. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
  103. RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25],first_int_imreg,[]);
  104. rg[R_ADDRESSREGISTER]:=trgintcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
  105. [RS_R26,RS_R30],first_int_imreg,[]);
  106. end;
  107. procedure tcgavr.done_register_allocators;
  108. begin
  109. rg[R_INTREGISTER].free;
  110. rg[R_ADDRESSREGISTER].free;
  111. inherited done_register_allocators;
  112. end;
  113. function tcgavr.getintregister(list: TAsmList; size: Tcgsize): Tregister;
  114. var
  115. tmp1,tmp2,tmp3 : TRegister;
  116. begin
  117. case size of
  118. OS_8,OS_S8:
  119. Result:=inherited getintregister(list, size);
  120. OS_16,OS_S16:
  121. begin
  122. Result:=inherited getintregister(list, OS_8);
  123. { ensure that the high register can be retrieved by
  124. GetNextReg
  125. }
  126. if inherited getintregister(list, OS_8)<>GetNextReg(Result) then
  127. internalerror(2011021331);
  128. end;
  129. OS_32,OS_S32:
  130. begin
  131. Result:=inherited getintregister(list, OS_8);
  132. tmp1:=inherited getintregister(list, OS_8);
  133. { ensure that the high register can be retrieved by
  134. GetNextReg
  135. }
  136. if tmp1<>GetNextReg(Result) then
  137. internalerror(2011021332);
  138. tmp2:=inherited getintregister(list, OS_8);
  139. { ensure that the upper register can be retrieved by
  140. GetNextReg
  141. }
  142. if tmp2<>GetNextReg(tmp1) then
  143. internalerror(2011021333);
  144. tmp3:=inherited getintregister(list, OS_8);
  145. { ensure that the upper register can be retrieved by
  146. GetNextReg
  147. }
  148. if tmp3<>GetNextReg(tmp2) then
  149. internalerror(2011021334);
  150. end;
  151. else
  152. internalerror(2011021330);
  153. end;
  154. end;
  155. procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);
  156. var
  157. ref: treference;
  158. begin
  159. paraloc.check_simple_location;
  160. paramanager.allocparaloc(list,paraloc.location);
  161. case paraloc.location^.loc of
  162. LOC_REGISTER,LOC_CREGISTER:
  163. a_load_const_reg(list,size,a,paraloc.location^.register);
  164. LOC_REFERENCE:
  165. begin
  166. reference_reset(ref,paraloc.alignment);
  167. ref.base:=paraloc.location^.reference.index;
  168. ref.offset:=paraloc.location^.reference.offset;
  169. a_load_const_ref(list,size,a,ref);
  170. end;
  171. else
  172. internalerror(2002081101);
  173. end;
  174. end;
  175. procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
  176. var
  177. tmpref, ref: treference;
  178. location: pcgparalocation;
  179. sizeleft: aint;
  180. begin
  181. location := paraloc.location;
  182. tmpref := r;
  183. sizeleft := paraloc.intsize;
  184. while assigned(location) do
  185. begin
  186. paramanager.allocparaloc(list,location);
  187. case location^.loc of
  188. LOC_REGISTER,LOC_CREGISTER:
  189. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  190. LOC_REFERENCE:
  191. begin
  192. reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
  193. { doubles in softemu mode have a strange order of registers and references }
  194. if location^.size=OS_32 then
  195. g_concatcopy(list,tmpref,ref,4)
  196. else
  197. begin
  198. g_concatcopy(list,tmpref,ref,sizeleft);
  199. if assigned(location^.next) then
  200. internalerror(2005010710);
  201. end;
  202. end;
  203. LOC_VOID:
  204. begin
  205. // nothing to do
  206. end;
  207. else
  208. internalerror(2002081103);
  209. end;
  210. inc(tmpref.offset,tcgsize2size[location^.size]);
  211. dec(sizeleft,tcgsize2size[location^.size]);
  212. location := location^.next;
  213. end;
  214. end;
  215. procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  216. var
  217. ref: treference;
  218. tmpreg: tregister;
  219. begin
  220. paraloc.check_simple_location;
  221. paramanager.allocparaloc(list,paraloc.location);
  222. case paraloc.location^.loc of
  223. LOC_REGISTER,LOC_CREGISTER:
  224. a_loadaddr_ref_reg(list,r,paraloc.location^.register);
  225. LOC_REFERENCE:
  226. begin
  227. reference_reset(ref,paraloc.alignment);
  228. ref.base := paraloc.location^.reference.index;
  229. ref.offset := paraloc.location^.reference.offset;
  230. tmpreg := getintregister(list,OS_ADDR);
  231. a_loadaddr_ref_reg(list,r,tmpreg);
  232. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  233. end;
  234. else
  235. internalerror(2002080701);
  236. end;
  237. end;
  238. procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean);
  239. begin
  240. list.concat(taicpu.op_sym(A_RCALL,current_asmdata.RefAsmSymbol(s)));
  241. {
  242. the compiler does not properly set this flag anymore in pass 1, and
  243. for now we only need it after pass 2 (I hope) (JM)
  244. if not(pi_do_call in current_procinfo.flags) then
  245. internalerror(2003060703);
  246. }
  247. include(current_procinfo.flags,pi_do_call);
  248. end;
  249. procedure tcgavr.a_call_reg(list : TAsmList;reg: tregister);
  250. begin
  251. a_reg_alloc(list,NR_ZLO);
  252. a_reg_alloc(list,NR_ZHI);
  253. list.concat(taicpu.op_reg_reg(A_MOV,NR_ZLO,reg));
  254. list.concat(taicpu.op_reg_reg(A_MOV,NR_ZHI,GetHigh(reg)));
  255. list.concat(taicpu.op_none(A_ICALL));
  256. a_reg_dealloc(list,NR_ZLO);
  257. a_reg_dealloc(list,NR_ZHI);
  258. include(current_procinfo.flags,pi_do_call);
  259. end;
  260. procedure tcgavr.a_call_ref(list : TAsmList;ref: treference);
  261. begin
  262. a_reg_alloc(list,NR_ZLO);
  263. a_reg_alloc(list,NR_ZHI);
  264. a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_ZLO);
  265. list.concat(taicpu.op_none(A_ICALL));
  266. a_reg_dealloc(list,NR_ZLO);
  267. a_reg_dealloc(list,NR_ZHI);
  268. include(current_procinfo.flags,pi_do_call);
  269. end;
  270. procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
  271. var
  272. mask : qword;
  273. shift : byte;
  274. i : byte;
  275. tmpreg : tregister;
  276. begin
  277. mask:=$ff;
  278. shift:=0;
  279. case op of
  280. OP_OR:
  281. begin
  282. for i:=1 to tcgsize2size[size] do
  283. begin
  284. list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
  285. reg:=GetNextReg(reg);
  286. mask:=mask shl 8;
  287. inc(shift,8);
  288. end;
  289. end;
  290. OP_AND:
  291. begin
  292. for i:=1 to tcgsize2size[size] do
  293. begin
  294. list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
  295. reg:=GetNextReg(reg);
  296. mask:=mask shl 8;
  297. inc(shift,8);
  298. end;
  299. end;
  300. OP_SUB:
  301. begin
  302. list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
  303. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  304. begin
  305. for i:=2 to tcgsize2size[size] do
  306. begin
  307. reg:=GetNextReg(reg);
  308. mask:=mask shl 8;
  309. inc(shift,8);
  310. list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
  311. end;
  312. end;
  313. end;
  314. else
  315. begin
  316. tmpreg:=getintregister(list,size);
  317. a_load_const_reg(list,size,a,tmpreg);
  318. a_op_reg_reg(list,op,size,tmpreg,reg);
  319. end;
  320. end;
  321. end;
  322. procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  323. var
  324. tmpreg: tregister;
  325. i : integer;
  326. instr : taicpu;
  327. begin
  328. case op of
  329. OP_ADD:
  330. begin
  331. if src<>dst then
  332. a_load_reg_reg(list,size,size,src,dst);
  333. list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
  334. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  335. begin
  336. for i:=2 to tcgsize2size[size] do
  337. begin
  338. dst:=GetNextReg(dst);
  339. src:=GetNextReg(src);
  340. list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
  341. end;
  342. end
  343. else
  344. end;
  345. OP_SUB:
  346. begin
  347. if src<>dst then
  348. a_load_reg_reg(list,size,size,src,dst);
  349. list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
  350. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  351. begin
  352. for i:=2 to tcgsize2size[size] do
  353. begin
  354. dst:=GetNextReg(dst);
  355. src:=GetNextReg(src);
  356. list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
  357. end;
  358. end;
  359. end;
  360. OP_NEG:
  361. begin
  362. if src<>dst then
  363. a_load_reg_reg(list,size,size,src,dst);
  364. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  365. begin
  366. tmpreg:=GetNextReg(dst);
  367. for i:=2 to tcgsize2size[size] do
  368. begin
  369. list.concat(taicpu.op_reg(A_COM,tmpreg));
  370. tmpreg:=GetNextReg(tmpreg);
  371. end;
  372. list.concat(taicpu.op_reg(A_NEG,dst));
  373. tmpreg:=GetNextReg(dst);
  374. for i:=2 to tcgsize2size[size] do
  375. begin
  376. list.concat(taicpu.op_const_reg(A_SBCI,-1,dst));
  377. tmpreg:=GetNextReg(tmpreg);
  378. end;
  379. end
  380. else
  381. list.concat(taicpu.op_reg(A_NEG,dst));
  382. end;
  383. OP_NOT:
  384. begin
  385. for i:=1 to tcgsize2size[size] do
  386. begin
  387. if src<>dst then
  388. a_load_reg_reg(list,OS_8,OS_8,src,dst);
  389. list.concat(taicpu.op_reg(A_COM,dst));
  390. src:=GetNextReg(src);
  391. dst:=GetNextReg(dst);
  392. end;
  393. end;
  394. OP_MUL,OP_IMUL:
  395. begin
  396. if size in [OS_8,OS_S8] then
  397. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src))
  398. else
  399. internalerror(2011022002);
  400. end;
  401. OP_DIV,OP_IDIV:
  402. { special stuff, needs separate handling inside code }
  403. { generator }
  404. internalerror(2011022001);
  405. {!!!!
  406. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  407. begin
  408. { Use ecx to load the value, that allows better coalescing }
  409. getcpuregister(list,NR_ECX);
  410. a_load_reg_reg(list,size,OS_32,src,NR_ECX);
  411. list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,dst));
  412. ungetcpuregister(list,NR_ECX);
  413. end;
  414. }
  415. OP_AND,OP_OR,OP_XOR:
  416. begin
  417. if src<>dst then
  418. a_load_reg_reg(list,size,size,src,dst);
  419. for i:=1 to tcgsize2size[size] do
  420. begin
  421. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  422. dst:=GetNextReg(dst);
  423. src:=GetNextReg(src);
  424. end;
  425. end;
  426. else
  427. internalerror(2011022004);
  428. end;
  429. end;
  430. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);
  431. var
  432. mask : qword;
  433. shift : byte;
  434. i : byte;
  435. begin
  436. mask:=$ff;
  437. shift:=0;
  438. for i:=1 to tcgsize2size[size] do
  439. begin
  440. list.concat(taicpu.op_reg_const(A_LDI,reg,(a and mask) shr shift));
  441. mask:=mask shl 8;
  442. inc(shift,8);
  443. reg:=GetNextReg(reg);
  444. end;
  445. end;
  446. function tcgavr.normalize_ref(list:TAsmList;ref: treference):treference;
  447. var
  448. tmpreg : tregister;
  449. tmpref : treference;
  450. l : tasmlabel;
  451. begin
  452. tmpreg:=NR_NO;
  453. Result:=ref;
  454. if ref.addressmode<>AM_UNCHANGED then
  455. internalerror(2011021701);
  456. { Be sure to have a base register }
  457. if (ref.base=NR_NO) then
  458. begin
  459. { only symbol+offset? }
  460. if ref.index=NR_NO then
  461. exit;
  462. ref.base:=ref.index;
  463. ref.index:=NR_NO;
  464. end;
  465. if assigned(ref.symbol) or (ref.offset<>0) then
  466. begin
  467. tmpreg:=getaddressregister(list);
  468. reference_reset(tmpref,0);
  469. tmpref.symbol:=ref.symbol;
  470. tmpref.offset:=lo(word(ref.offset));
  471. tmpref.refaddr:=addr_lo8;
  472. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  473. tmpref.offset:=hi(word(ref.offset));
  474. tmpref.refaddr:=addr_hi8;
  475. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  476. if (ref.base<>NR_NO) then
  477. begin
  478. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  479. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  480. end;
  481. if (ref.index<>NR_NO) then
  482. begin
  483. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  484. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  485. end;
  486. ref.base:=tmpreg;
  487. ref.index:=NR_NO;
  488. end
  489. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  490. begin
  491. tmpreg:=getaddressregister(list);
  492. list.concat(taicpu.op_reg_reg(A_MOVW,tmpreg,ref.index));
  493. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  494. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  495. ref.base:=tmpreg;
  496. ref.index:=NR_NO;
  497. end;
  498. Result:=ref;
  499. end;
  500. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  501. var
  502. href : treference;
  503. conv_done: boolean;
  504. tmpreg : tregister;
  505. i : integer;
  506. begin
  507. href:=normalize_ref(list,Ref);
  508. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  509. internalerror(2011021307);
  510. conv_done:=false;
  511. if tosize<>fromsize then
  512. begin
  513. conv_done:=true;
  514. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  515. fromsize:=tosize;
  516. case fromsize of
  517. OS_8:
  518. begin
  519. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  520. href.addressmode:=AM_POSTINCREMENT;
  521. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  522. for i:=2 to tcgsize2size[tosize] do
  523. begin
  524. if (href.offset<>0) or assigned(href.symbol) then
  525. inc(href.offset);
  526. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  527. href.addressmode:=AM_POSTINCREMENT
  528. else
  529. href.addressmode:=AM_UNCHANGED;
  530. list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1));
  531. end;
  532. end;
  533. OS_S8:
  534. begin
  535. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  536. href.addressmode:=AM_POSTINCREMENT;
  537. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  538. if tcgsize2size[tosize]>1 then
  539. begin
  540. tmpreg:=getintregister(list,OS_8);
  541. list.concat(taicpu.op_reg(A_CLR,tmpreg));
  542. list.concat(taicpu.op_reg_const(A_SBIC,reg,7));
  543. list.concat(taicpu.op_reg(A_COM,tmpreg));
  544. for i:=2 to tcgsize2size[tosize] do
  545. begin
  546. if (href.offset<>0) or assigned(href.symbol) then
  547. inc(href.offset);
  548. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  549. href.addressmode:=AM_POSTINCREMENT
  550. else
  551. href.addressmode:=AM_UNCHANGED;
  552. list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg));
  553. end;
  554. end;
  555. end;
  556. OS_16:
  557. begin
  558. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  559. href.addressmode:=AM_POSTINCREMENT;
  560. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  561. if (href.offset<>0) or assigned(href.symbol) then
  562. inc(href.offset)
  563. else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then
  564. href.addressmode:=AM_POSTINCREMENT
  565. else
  566. href.addressmode:=AM_UNCHANGED;
  567. reg:=GetNextReg(reg);
  568. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  569. for i:=3 to tcgsize2size[tosize] do
  570. begin
  571. if (href.offset<>0) or assigned(href.symbol) then
  572. inc(href.offset);
  573. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  574. href.addressmode:=AM_POSTINCREMENT
  575. else
  576. href.addressmode:=AM_UNCHANGED;
  577. list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1));
  578. end;
  579. end;
  580. OS_S16:
  581. begin
  582. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  583. href.addressmode:=AM_POSTINCREMENT;
  584. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  585. if (href.offset<>0) or assigned(href.symbol) then
  586. inc(href.offset)
  587. else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then
  588. href.addressmode:=AM_POSTINCREMENT
  589. else
  590. href.addressmode:=AM_UNCHANGED;
  591. reg:=GetNextReg(reg);
  592. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  593. if tcgsize2size[tosize]>2 then
  594. begin
  595. tmpreg:=getintregister(list,OS_8);
  596. list.concat(taicpu.op_reg(A_CLR,tmpreg));
  597. list.concat(taicpu.op_reg_const(A_SBIC,reg,7));
  598. list.concat(taicpu.op_reg(A_COM,tmpreg));
  599. for i:=3 to tcgsize2size[tosize] do
  600. begin
  601. if (href.offset<>0) or assigned(href.symbol) then
  602. inc(href.offset);
  603. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  604. href.addressmode:=AM_POSTINCREMENT
  605. else
  606. href.addressmode:=AM_UNCHANGED;
  607. list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg));
  608. end;
  609. end;
  610. end;
  611. else
  612. conv_done:=false;
  613. end;
  614. end;
  615. if not conv_done then
  616. begin
  617. for i:=1 to tcgsize2size[fromsize] do
  618. begin
  619. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  620. href.addressmode:=AM_POSTINCREMENT
  621. else
  622. href.addressmode:=AM_UNCHANGED;
  623. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  624. if (href.offset<>0) or assigned(href.symbol) then
  625. inc(href.offset);
  626. reg:=GetNextReg(reg);
  627. end;
  628. end;
  629. end;
  630. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  631. const Ref : treference;reg : tregister);
  632. var
  633. href : treference;
  634. conv_done: boolean;
  635. tmpreg : tregister;
  636. i : integer;
  637. begin
  638. href:=normalize_ref(list,Ref);
  639. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  640. internalerror(2011021307);
  641. conv_done:=false;
  642. if tosize<>fromsize then
  643. begin
  644. conv_done:=true;
  645. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  646. fromsize:=tosize;
  647. case fromsize of
  648. OS_8:
  649. begin
  650. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  651. for i:=2 to tcgsize2size[tosize] do
  652. begin
  653. reg:=GetNextReg(reg);
  654. list.concat(taicpu.op_reg(A_CLR,reg));
  655. end;
  656. end;
  657. OS_S8:
  658. begin
  659. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  660. tmpreg:=reg;
  661. if tcgsize2size[tosize]>1 then
  662. begin
  663. reg:=GetNextReg(reg);
  664. list.concat(taicpu.op_reg(A_CLR,reg));
  665. list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7));
  666. list.concat(taicpu.op_reg(A_COM,reg));
  667. tmpreg:=reg;
  668. for i:=3 to tcgsize2size[tosize] do
  669. begin
  670. reg:=GetNextReg(reg);
  671. emit_mov(list,reg,tmpreg);
  672. end;
  673. end;
  674. end;
  675. OS_16:
  676. begin
  677. if href.base<>NR_NO then
  678. href.addressmode:=AM_POSTINCREMENT;
  679. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  680. if (href.offset<>0) or assigned(href.symbol) then
  681. inc(href.offset);
  682. href.addressmode:=AM_UNCHANGED;
  683. reg:=GetNextReg(reg);
  684. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  685. for i:=3 to tcgsize2size[tosize] do
  686. begin
  687. reg:=GetNextReg(reg);
  688. list.concat(taicpu.op_reg(A_CLR,reg));
  689. end;
  690. end;
  691. OS_S16:
  692. begin
  693. if href.base<>NR_NO then
  694. href.addressmode:=AM_POSTINCREMENT;
  695. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  696. if (href.offset<>0) or assigned(href.symbol) then
  697. inc(href.offset);
  698. href.addressmode:=AM_UNCHANGED;
  699. reg:=GetNextReg(reg);
  700. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  701. tmpreg:=reg;
  702. reg:=GetNextReg(reg);
  703. list.concat(taicpu.op_reg(A_CLR,reg));
  704. list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7));
  705. list.concat(taicpu.op_reg(A_COM,reg));
  706. tmpreg:=reg;
  707. for i:=4 to tcgsize2size[tosize] do
  708. begin
  709. reg:=GetNextReg(reg);
  710. emit_mov(list,reg,tmpreg);
  711. end;
  712. end;
  713. else
  714. conv_done:=false;
  715. end;
  716. end;
  717. if not conv_done then
  718. begin
  719. for i:=1 to tcgsize2size[fromsize] do
  720. begin
  721. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  722. href.addressmode:=AM_POSTINCREMENT
  723. else
  724. href.addressmode:=AM_UNCHANGED;
  725. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  726. if (href.offset<>0) or assigned(href.symbol) then
  727. inc(href.offset);
  728. reg:=GetNextReg(reg);
  729. end;
  730. end;
  731. end;
  732. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  733. var
  734. conv_done: boolean;
  735. tmpreg : tregister;
  736. i : integer;
  737. begin
  738. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  739. internalerror(2011021310);
  740. conv_done:=false;
  741. if tosize<>fromsize then
  742. begin
  743. conv_done:=true;
  744. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  745. fromsize:=tosize;
  746. case fromsize of
  747. OS_8:
  748. begin
  749. emit_mov(list,reg2,reg1);
  750. for i:=2 to tcgsize2size[tosize] do
  751. begin
  752. reg2:=GetNextReg(reg2);
  753. list.concat(taicpu.op_reg(A_CLR,reg2));
  754. end;
  755. end;
  756. OS_S8:
  757. begin
  758. { dest is always at least 16 bit at this point }
  759. emit_mov(list,reg2,reg1);
  760. reg2:=GetNextReg(reg2);
  761. list.concat(taicpu.op_reg(A_CLR,reg2));
  762. list.concat(taicpu.op_reg_const(A_SBIC,reg1,7));
  763. list.concat(taicpu.op_reg(A_COM,reg2));
  764. tmpreg:=reg2;
  765. for i:=3 to tcgsize2size[tosize] do
  766. begin
  767. reg2:=GetNextReg(reg2);
  768. emit_mov(list,reg2,tmpreg);
  769. end;
  770. end;
  771. OS_16:
  772. begin
  773. emit_mov(list,reg2,reg1);
  774. reg1:=GetNextReg(reg1);
  775. reg2:=GetNextReg(reg2);
  776. emit_mov(list,reg2,reg1);
  777. for i:=3 to tcgsize2size[tosize] do
  778. begin
  779. reg2:=GetNextReg(reg2);
  780. list.concat(taicpu.op_reg(A_CLR,reg2));
  781. end;
  782. end;
  783. OS_S16:
  784. begin
  785. { dest is always at least 32 bit at this point }
  786. emit_mov(list,reg2,reg1);
  787. reg1:=GetNextReg(reg1);
  788. reg2:=GetNextReg(reg2);
  789. emit_mov(list,reg2,reg1);
  790. reg2:=GetNextReg(reg2);
  791. list.concat(taicpu.op_reg(A_CLR,reg2));
  792. list.concat(taicpu.op_reg_const(A_SBIC,reg1,7));
  793. list.concat(taicpu.op_reg(A_COM,reg2));
  794. tmpreg:=reg2;
  795. for i:=4 to tcgsize2size[tosize] do
  796. begin
  797. reg2:=GetNextReg(reg2);
  798. emit_mov(list,reg2,tmpreg);
  799. end;
  800. end;
  801. else
  802. conv_done:=false;
  803. end;
  804. end;
  805. if not conv_done and (reg1<>reg2) then
  806. begin
  807. for i:=1 to tcgsize2size[fromsize] do
  808. begin
  809. emit_mov(list,reg2,reg1);
  810. reg1:=GetNextReg(reg1);
  811. reg2:=GetNextReg(reg2);
  812. end;
  813. end;
  814. end;
  815. { comparison operations }
  816. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  817. l : tasmlabel);
  818. begin
  819. internalerror(2011021311);
  820. end;
  821. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  822. begin
  823. internalerror(2011021312);
  824. end;
  825. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  826. begin
  827. internalerror(2011021313);
  828. end;
  829. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  830. var
  831. ai : taicpu;
  832. begin
  833. ai:=taicpu.op_sym(A_JMP,l);
  834. ai.is_jmp:=true;
  835. list.concat(ai);
  836. end;
  837. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  838. var
  839. ai : taicpu;
  840. begin
  841. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  842. ai.is_jmp:=true;
  843. list.concat(ai);
  844. end;
  845. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  846. begin
  847. internalerror(2011021316);
  848. end;
  849. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  850. var
  851. i : integer;
  852. begin
  853. case value of
  854. 0:
  855. ;
  856. -14..-1:
  857. begin
  858. if ((-value) mod 2)<>0 then
  859. list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  860. for i:=1 to (-value) div 2 do
  861. list.concat(taicpu.op_const(A_RCALL,0));
  862. end;
  863. 1..7:
  864. begin
  865. for i:=1 to value do
  866. list.concat(taicpu.op_reg(A_POP,NR_R0));
  867. end;
  868. else
  869. begin
  870. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  871. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  872. // get SREG
  873. list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  874. // block interrupts
  875. list.concat(taicpu.op_none(A_CLI));
  876. // write high SP
  877. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  878. // release interrupts
  879. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  880. // write low SP
  881. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  882. end;
  883. end;
  884. end;
  885. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  886. var
  887. regs : tcpuregisterset;
  888. reg : tsuperregister;
  889. begin
  890. if not(nostackframe) then
  891. begin
  892. { save int registers }
  893. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  894. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  895. regs:=regs+[RS_R28,RS_R29];
  896. for reg:=RS_R31 downto RS_R0 do
  897. if reg in regs then
  898. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  899. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  900. begin
  901. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  902. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  903. end
  904. else
  905. { the framepointer cannot be omitted on avr because sp
  906. is not a register but part of the i/o map
  907. }
  908. internalerror(2011021901);
  909. a_adjust_sp(list,-localsize);
  910. end;
  911. end;
  912. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  913. var
  914. regs : tcpuregisterset;
  915. reg : TSuperRegister;
  916. LocalSize : longint;
  917. begin
  918. if not(nostackframe) then
  919. begin
  920. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  921. begin
  922. LocalSize:=current_procinfo.calc_stackframe_size;
  923. a_adjust_sp(list,LocalSize);
  924. for reg:=RS_R0 to RS_R31 do
  925. if reg in regs then
  926. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  927. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  928. end
  929. else
  930. { the framepointer cannot be omitted on avr because sp
  931. is not a register but part of the i/o map
  932. }
  933. internalerror(2011021902);
  934. end;
  935. list.concat(taicpu.op_none(A_RET));
  936. end;
  937. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  938. begin
  939. //!!!!
  940. end;
  941. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  942. begin
  943. internalerror(2011021320);
  944. end;
  945. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
  946. var
  947. paraloc1,paraloc2,paraloc3 : TCGPara;
  948. begin
  949. paraloc1.init;
  950. paraloc2.init;
  951. paraloc3.init;
  952. paramanager.getintparaloc(pocall_default,1,paraloc1);
  953. paramanager.getintparaloc(pocall_default,2,paraloc2);
  954. paramanager.getintparaloc(pocall_default,3,paraloc3);
  955. a_load_const_cgpara(list,OS_INT,len,paraloc3);
  956. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  957. a_loadaddr_ref_cgpara(list,source,paraloc1);
  958. paramanager.freecgpara(list,paraloc3);
  959. paramanager.freecgpara(list,paraloc2);
  960. paramanager.freecgpara(list,paraloc1);
  961. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  962. a_call_name_static(list,'FPC_MOVE');
  963. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  964. paraloc3.done;
  965. paraloc2.done;
  966. paraloc1.done;
  967. end;
  968. procedure tcgavr.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
  969. begin
  970. internalerror(2011021321);
  971. end;
  972. procedure tcgavr.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);
  973. begin
  974. g_concatcopy_internal(list,source,dest,len,false);
  975. end;
  976. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);
  977. var
  978. countreg,tmpreg : tregister;
  979. srcref,dstref : treference;
  980. copysize,countregsize : tcgsize;
  981. l : TAsmLabel;
  982. i : longint;
  983. begin
  984. current_asmdata.getjumplabel(l);
  985. if len>16 then
  986. begin
  987. copysize:=OS_8;
  988. if len<256 then
  989. countregsize:=OS_8
  990. else if len<65536 then
  991. countregsize:=OS_16
  992. else
  993. internalerror(2011022007);
  994. countreg:=getintregister(list,countregsize);
  995. a_load_const_reg(list,countregsize,len,countreg);
  996. cg.a_label(list,l);
  997. tmpreg:=getintregister(list,copysize);
  998. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  999. list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg));
  1000. a_op_const_reg(list,OP_SUB,countregsize,1,countreg);
  1001. a_jmp_flags(list,F_NE,l);
  1002. end
  1003. else
  1004. begin
  1005. for i:=1 to len do
  1006. begin
  1007. srcref:=normalize_ref(list,source);
  1008. dstref:=normalize_ref(list,source);
  1009. copysize:=OS_8;
  1010. tmpreg:=getintregister(list,copysize);
  1011. if (srcref.base<>NR_NO) and (i<len) then
  1012. srcref.addressmode:=AM_POSTINCREMENT
  1013. else
  1014. srcref.addressmode:=AM_UNCHANGED;
  1015. if (dstref.base<>NR_NO) and (i<len) then
  1016. dstref.addressmode:=AM_POSTINCREMENT
  1017. else
  1018. dstref.addressmode:=AM_UNCHANGED;
  1019. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  1020. list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg));
  1021. if (dstref.offset<>0) or assigned(dstref.symbol) then
  1022. inc(dstref.offset);
  1023. if (srcref.offset<>0) or assigned(srcref.symbol) then
  1024. inc(srcref.offset);
  1025. end;
  1026. end;
  1027. end;
  1028. procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  1029. var
  1030. ovloc : tlocation;
  1031. begin
  1032. ovloc.loc:=LOC_VOID;
  1033. g_overflowCheck_loc(list,l,def,ovloc);
  1034. end;
  1035. procedure tcgavr.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
  1036. begin
  1037. internalerror(2011021322);
  1038. end;
  1039. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1040. var
  1041. ai : taicpu;
  1042. begin
  1043. ai:=Taicpu.Op_sym(A_BRxx,l);
  1044. ai.SetCondition(OpCmp2AsmCond[cond]);
  1045. ai.is_jmp:=true;
  1046. list.concat(ai);
  1047. end;
  1048. procedure tcgavr.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1049. begin
  1050. internalerror(2011021324);
  1051. end;
  1052. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  1053. var
  1054. instr: taicpu;
  1055. begin
  1056. instr:=taicpu.op_reg_reg(A_MOV, reg2, reg1);
  1057. list.Concat(instr);
  1058. { Notify the register allocator that we have written a move instruction so
  1059. it can try to eliminate it. }
  1060. add_move_instruction(instr);
  1061. end;
  1062. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  1063. begin
  1064. internalerror(2011021325);
  1065. end;
  1066. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  1067. begin
  1068. a_op64_const_reg_reg(list,op,size,value,reg,reg);
  1069. end;
  1070. procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
  1071. var
  1072. ovloc : tlocation;
  1073. begin
  1074. a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
  1075. end;
  1076. procedure tcg64favr.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
  1077. var
  1078. ovloc : tlocation;
  1079. begin
  1080. a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
  1081. end;
  1082. procedure tcg64favr.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1083. begin
  1084. internalerror(2011021326);
  1085. end;
  1086. procedure tcg64favr.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1087. begin
  1088. internalerror(2011021327);
  1089. end;
  1090. procedure create_codegen;
  1091. begin
  1092. cg:=tcgavr.create;
  1093. cg64:=tcg64favr.create;
  1094. end;
  1095. end.