cgcpu.pas 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321
  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. function getaddressregister(list:TAsmList):TRegister;override;
  36. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
  37. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
  38. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
  39. procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override;
  40. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  41. procedure a_call_reg(list : TAsmList;reg: tregister);override;
  42. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
  43. procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
  44. procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
  45. procedure a_op_const_reg_reg(list : TAsmList;op : TOpCg;size : tcgsize; a : tcgint;src,dst : tregister); override;
  46. { move instructions }
  47. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
  48. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  49. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  50. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  51. { fpu move instructions }
  52. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  53. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  54. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  55. { comparison operations }
  56. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  57. l : tasmlabel);override;
  58. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  59. procedure a_jmp_name(list : TAsmList;const s : string); override;
  60. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  61. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  62. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  63. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  64. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  65. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  66. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
  67. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  68. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  69. procedure g_save_registers(list : TAsmList);override;
  70. procedure g_restore_registers(list : TAsmList);override;
  71. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  72. procedure fixref(list : TAsmList;var ref : treference);
  73. function normalize_ref(list : TAsmList;ref : treference;
  74. tmpreg : tregister) : treference;
  75. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  76. procedure a_adjust_sp(list: TAsmList; value: longint);
  77. function GetLoad(const ref : treference) : tasmop;
  78. function GetStore(const ref: treference): tasmop;
  79. protected
  80. procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  81. procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
  82. procedure maybegetcpuregister(list : tasmlist; reg : tregister);
  83. end;
  84. tcg64favr = class(tcg64f32)
  85. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  86. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  87. end;
  88. procedure create_codegen;
  89. const
  90. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,
  91. A_NONE,A_MULS,A_MUL,A_NEG,A_COM,A_OR,
  92. A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_ROL,A_ROR);
  93. implementation
  94. uses
  95. globals,verbose,systems,cutils,
  96. fmodule,
  97. symconst,symsym,symtable,
  98. tgobj,rgobj,
  99. procinfo,cpupi,
  100. paramgr;
  101. procedure tcgavr.init_register_allocators;
  102. begin
  103. inherited init_register_allocators;
  104. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  105. [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,
  106. RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  107. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17],first_int_imreg,[]);
  108. end;
  109. procedure tcgavr.done_register_allocators;
  110. begin
  111. rg[R_INTREGISTER].free;
  112. // rg[R_ADDRESSREGISTER].free;
  113. inherited done_register_allocators;
  114. end;
  115. function tcgavr.getintregister(list: TAsmList; size: Tcgsize): Tregister;
  116. var
  117. tmp1,tmp2,tmp3 : TRegister;
  118. begin
  119. case size of
  120. OS_8,OS_S8:
  121. Result:=inherited getintregister(list, size);
  122. OS_16,OS_S16:
  123. begin
  124. Result:=inherited getintregister(list, OS_8);
  125. { ensure that the high register can be retrieved by
  126. GetNextReg
  127. }
  128. if inherited getintregister(list, OS_8)<>GetNextReg(Result) then
  129. internalerror(2011021331);
  130. end;
  131. OS_32,OS_S32:
  132. begin
  133. Result:=inherited getintregister(list, OS_8);
  134. tmp1:=inherited getintregister(list, OS_8);
  135. { ensure that the high register can be retrieved by
  136. GetNextReg
  137. }
  138. if tmp1<>GetNextReg(Result) then
  139. internalerror(2011021332);
  140. tmp2:=inherited getintregister(list, OS_8);
  141. { ensure that the upper register can be retrieved by
  142. GetNextReg
  143. }
  144. if tmp2<>GetNextReg(tmp1) then
  145. internalerror(2011021333);
  146. tmp3:=inherited getintregister(list, OS_8);
  147. { ensure that the upper register can be retrieved by
  148. GetNextReg
  149. }
  150. if tmp3<>GetNextReg(tmp2) then
  151. internalerror(2011021334);
  152. end;
  153. else
  154. internalerror(2011021330);
  155. end;
  156. end;
  157. function tcgavr.getaddressregister(list: TAsmList): TRegister;
  158. begin
  159. Result:=getintregister(list,OS_ADDR);
  160. end;
  161. procedure tcgavr.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  162. procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  163. var
  164. ref : treference;
  165. begin
  166. paramanager.allocparaloc(list,paraloc);
  167. case paraloc^.loc of
  168. LOC_REGISTER,LOC_CREGISTER:
  169. a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  170. LOC_REFERENCE,LOC_CREFERENCE:
  171. begin
  172. reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,2,[]);
  173. a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
  174. end;
  175. else
  176. internalerror(2002071004);
  177. end;
  178. end;
  179. var
  180. i, i2 : longint;
  181. hp : PCGParaLocation;
  182. begin
  183. { if use_push(cgpara) then
  184. begin
  185. if tcgsize2size[cgpara.Size] > 2 then
  186. begin
  187. if tcgsize2size[cgpara.Size] <> 4 then
  188. internalerror(2013031101);
  189. if cgpara.location^.Next = nil then
  190. begin
  191. if tcgsize2size[cgpara.location^.size] <> 4 then
  192. internalerror(2013031101);
  193. end
  194. else
  195. begin
  196. if tcgsize2size[cgpara.location^.size] <> 2 then
  197. internalerror(2013031101);
  198. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  199. internalerror(2013031101);
  200. if cgpara.location^.Next^.Next <> nil then
  201. internalerror(2013031101);
  202. end;
  203. if tcgsize2size[cgpara.size]>cgpara.alignment then
  204. pushsize:=cgpara.size
  205. else
  206. pushsize:=int_cgsize(cgpara.alignment);
  207. pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
  208. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
  209. list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
  210. end
  211. else
  212. begin
  213. cgpara.check_simple_location;
  214. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  215. pushsize:=cgpara.location^.size
  216. else
  217. pushsize:=int_cgsize(cgpara.alignment);
  218. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  219. end;
  220. end
  221. else }
  222. begin
  223. if not(tcgsize2size[cgpara.Size] in [1..4]) then
  224. internalerror(2014011101);
  225. hp:=cgpara.location;
  226. i:=0;
  227. while i<tcgsize2size[cgpara.Size] do
  228. begin
  229. if not(assigned(hp)) then
  230. internalerror(2014011102);
  231. inc(i, tcgsize2size[hp^.Size]);
  232. if hp^.Loc=LOC_REGISTER then
  233. begin
  234. load_para_loc(r,hp);
  235. hp:=hp^.Next;
  236. r:=GetNextReg(r);
  237. end
  238. else
  239. begin
  240. load_para_loc(r,hp);
  241. for i2:=1 to tcgsize2size[hp^.Size] do
  242. r:=GetNextReg(r);
  243. hp:=hp^.Next;
  244. end;
  245. end;
  246. if assigned(hp) then
  247. internalerror(2014011103);
  248. end;
  249. end;
  250. procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
  251. var
  252. i : longint;
  253. hp : PCGParaLocation;
  254. ref: treference;
  255. begin
  256. if not(tcgsize2size[paraloc.Size] in [1..4]) then
  257. internalerror(2014011101);
  258. hp:=paraloc.location;
  259. i:=1;
  260. while i<=tcgsize2size[paraloc.Size] do
  261. begin
  262. if not(assigned(hp)) then
  263. internalerror(2014011105);
  264. //paramanager.allocparaloc(list,hp);
  265. case hp^.loc of
  266. LOC_REGISTER,LOC_CREGISTER:
  267. begin
  268. if (tcgsize2size[hp^.size]<>1) or
  269. (hp^.shiftval<>0) then
  270. internalerror(2015041101);
  271. a_load_const_reg(list,hp^.size,(a shr (8*(i-1))) and $ff,hp^.register);
  272. inc(i,tcgsize2size[hp^.size]);
  273. hp:=hp^.Next;
  274. end;
  275. LOC_REFERENCE,LOC_CREFERENCE:
  276. begin
  277. reference_reset(ref,paraloc.alignment,[]);
  278. ref.base:=hp^.reference.index;
  279. ref.offset:=hp^.reference.offset;
  280. a_load_const_ref(list,hp^.size,a shr (8*(i-1)),ref);
  281. inc(i,tcgsize2size[hp^.size]);
  282. hp:=hp^.Next;
  283. end;
  284. else
  285. internalerror(2002071004);
  286. end;
  287. end;
  288. end;
  289. procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
  290. var
  291. tmpref, ref: treference;
  292. location: pcgparalocation;
  293. sizeleft: tcgint;
  294. begin
  295. location := paraloc.location;
  296. tmpref := r;
  297. sizeleft := paraloc.intsize;
  298. while assigned(location) do
  299. begin
  300. paramanager.allocparaloc(list,location);
  301. case location^.loc of
  302. LOC_REGISTER,LOC_CREGISTER:
  303. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  304. LOC_REFERENCE:
  305. begin
  306. reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment,[]);
  307. { doubles in softemu mode have a strange order of registers and references }
  308. if location^.size=OS_32 then
  309. g_concatcopy(list,tmpref,ref,4)
  310. else
  311. begin
  312. g_concatcopy(list,tmpref,ref,sizeleft);
  313. if assigned(location^.next) then
  314. internalerror(2005010710);
  315. end;
  316. end;
  317. LOC_VOID:
  318. begin
  319. // nothing to do
  320. end;
  321. else
  322. internalerror(2002081103);
  323. end;
  324. inc(tmpref.offset,tcgsize2size[location^.size]);
  325. dec(sizeleft,tcgsize2size[location^.size]);
  326. location := location^.next;
  327. end;
  328. end;
  329. procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  330. var
  331. tmpreg: tregister;
  332. begin
  333. tmpreg:=getaddressregister(list);
  334. a_loadaddr_ref_reg(list,r,tmpreg);
  335. a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
  336. end;
  337. procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean);
  338. var
  339. sym: TAsmSymbol;
  340. begin
  341. if weak then
  342. sym:=current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)
  343. else
  344. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION);
  345. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  346. list.concat(taicpu.op_sym(A_CALL,sym))
  347. else
  348. list.concat(taicpu.op_sym(A_RCALL,sym));
  349. include(current_procinfo.flags,pi_do_call);
  350. end;
  351. procedure tcgavr.a_call_reg(list : TAsmList;reg: tregister);
  352. begin
  353. a_reg_alloc(list,NR_ZLO);
  354. emit_mov(list,NR_ZLO,reg);
  355. a_reg_alloc(list,NR_ZHI);
  356. emit_mov(list,NR_ZHI,GetHigh(reg));
  357. list.concat(taicpu.op_none(A_ICALL));
  358. a_reg_dealloc(list,NR_ZHI);
  359. a_reg_dealloc(list,NR_ZLO);
  360. include(current_procinfo.flags,pi_do_call);
  361. end;
  362. procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
  363. begin
  364. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  365. internalerror(2012102403);
  366. a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
  367. end;
  368. procedure tcgavr.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
  369. begin
  370. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  371. internalerror(2012102401);
  372. a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
  373. end;
  374. procedure tcgavr.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
  375. begin
  376. if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) and
  377. (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) then
  378. begin
  379. getcpuregister(list,NR_R0);
  380. getcpuregister(list,NR_R1);
  381. list.concat(taicpu.op_reg_reg(A_MUL,src1,src2));
  382. emit_mov(list,dst,NR_R0);
  383. emit_mov(list,GetNextReg(dst),NR_R1);
  384. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),src2));
  385. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  386. list.concat(taicpu.op_reg_reg(A_MUL,src1,GetNextReg(src2)));
  387. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  388. ungetcpuregister(list,NR_R0);
  389. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  390. ungetcpuregister(list,NR_R1);
  391. end
  392. else
  393. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  394. end;
  395. procedure tcgavr.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
  396. begin
  397. if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) and (a in [2,4,8]) then
  398. begin
  399. emit_mov(list,dst,src);
  400. emit_mov(list,GetNextReg(dst),GetNextReg(src));
  401. a:=a shr 1;
  402. while a>0 do
  403. begin
  404. list.concat(taicpu.op_reg(A_LSL,dst));
  405. list.concat(taicpu.op_reg(A_ROL,GetNextReg(dst)));
  406. a:=a shr 1;
  407. end;
  408. end
  409. else
  410. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  411. end;
  412. procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  413. var
  414. countreg,
  415. tmpreg: tregister;
  416. i : integer;
  417. instr : taicpu;
  418. paraloc1,paraloc2,paraloc3 : TCGPara;
  419. l1,l2 : tasmlabel;
  420. pd : tprocdef;
  421. procedure NextSrcDst;
  422. begin
  423. if i=5 then
  424. begin
  425. dst:=dsthi;
  426. src:=srchi;
  427. end
  428. else
  429. begin
  430. dst:=GetNextReg(dst);
  431. src:=GetNextReg(src);
  432. end;
  433. end;
  434. { iterates TmpReg through all registers of dst }
  435. procedure NextTmp;
  436. begin
  437. if i=5 then
  438. tmpreg:=dsthi
  439. else
  440. tmpreg:=GetNextReg(tmpreg);
  441. end;
  442. begin
  443. case op of
  444. OP_ADD:
  445. begin
  446. list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
  447. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  448. begin
  449. for i:=2 to tcgsize2size[size] do
  450. begin
  451. NextSrcDst;
  452. list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
  453. end;
  454. end;
  455. end;
  456. OP_SUB:
  457. begin
  458. list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
  459. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  460. begin
  461. for i:=2 to tcgsize2size[size] do
  462. begin
  463. NextSrcDst;
  464. list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
  465. end;
  466. end;
  467. end;
  468. OP_NEG:
  469. begin
  470. if src<>dst then
  471. begin
  472. if size in [OS_S64,OS_64] then
  473. begin
  474. a_load_reg_reg(list,OS_32,OS_32,src,dst);
  475. a_load_reg_reg(list,OS_32,OS_32,srchi,dsthi);
  476. end
  477. else
  478. a_load_reg_reg(list,size,size,src,dst);
  479. end;
  480. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  481. begin
  482. tmpreg:=GetNextReg(dst);
  483. for i:=2 to tcgsize2size[size] do
  484. begin
  485. list.concat(taicpu.op_reg(A_COM,tmpreg));
  486. NextTmp;
  487. end;
  488. list.concat(taicpu.op_reg(A_NEG,dst));
  489. tmpreg:=GetNextReg(dst);
  490. for i:=2 to tcgsize2size[size] do
  491. begin
  492. list.concat(taicpu.op_reg_const(A_SBCI,tmpreg,-1));
  493. NextTmp;
  494. end;
  495. end;
  496. end;
  497. OP_NOT:
  498. begin
  499. for i:=1 to tcgsize2size[size] do
  500. begin
  501. if src<>dst then
  502. a_load_reg_reg(list,OS_8,OS_8,src,dst);
  503. list.concat(taicpu.op_reg(A_COM,dst));
  504. NextSrcDst;
  505. end;
  506. end;
  507. OP_MUL,OP_IMUL:
  508. begin
  509. if size in [OS_8,OS_S8] then
  510. begin
  511. if CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype] then
  512. begin
  513. cg.a_reg_alloc(list,NR_R0);
  514. cg.a_reg_alloc(list,NR_R1);
  515. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  516. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  517. cg.a_reg_dealloc(list,NR_R1);
  518. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  519. cg.a_reg_dealloc(list,NR_R0);
  520. end
  521. else
  522. internalerror(2015061001);
  523. end
  524. else if size in [OS_16,OS_S16] then
  525. begin
  526. if CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype] then
  527. begin
  528. tmpreg:=getintregister(list,OS_16);
  529. emit_mov(list,tmpreg,dst);
  530. emit_mov(list,GetNextReg(tmpreg),GetNextReg(dst));
  531. list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,src));
  532. emit_mov(list,dst,NR_R0);
  533. emit_mov(list,GetNextReg(dst),NR_R1);
  534. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(tmpreg),src));
  535. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  536. list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,GetNextReg(src)));
  537. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  538. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  539. end
  540. else
  541. begin
  542. { keep code for muls with overflow checking }
  543. if size=OS_16 then
  544. pd:=search_system_proc('fpc_mul_word')
  545. else
  546. pd:=search_system_proc('fpc_mul_integer');
  547. paraloc1.init;
  548. paraloc2.init;
  549. paraloc3.init;
  550. paramanager.getintparaloc(list,pd,1,paraloc1);
  551. paramanager.getintparaloc(list,pd,2,paraloc2);
  552. paramanager.getintparaloc(list,pd,3,paraloc3);
  553. a_load_const_cgpara(list,OS_8,0,paraloc3);
  554. a_load_reg_cgpara(list,OS_16,src,paraloc2);
  555. a_load_reg_cgpara(list,OS_16,dst,paraloc1);
  556. paramanager.freecgpara(list,paraloc3);
  557. paramanager.freecgpara(list,paraloc2);
  558. paramanager.freecgpara(list,paraloc1);
  559. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  560. if size=OS_16 then
  561. a_call_name(list,'FPC_MUL_WORD',false)
  562. else
  563. a_call_name(list,'FPC_MUL_INTEGER',false);
  564. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  565. cg.a_reg_alloc(list,NR_R24);
  566. cg.a_reg_alloc(list,NR_R25);
  567. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  568. cg.a_reg_dealloc(list,NR_R24);
  569. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R25,GetNextReg(dst));
  570. cg.a_reg_dealloc(list,NR_R25);
  571. paraloc3.done;
  572. paraloc2.done;
  573. paraloc1.done;
  574. end;
  575. end
  576. else
  577. internalerror(2011022002);
  578. end;
  579. OP_DIV,OP_IDIV:
  580. { special stuff, needs separate handling inside code }
  581. { generator }
  582. internalerror(2011022001);
  583. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  584. begin
  585. current_asmdata.getjumplabel(l1);
  586. current_asmdata.getjumplabel(l2);
  587. countreg:=getintregister(list,OS_8);
  588. a_load_reg_reg(list,size,OS_8,src,countreg);
  589. list.concat(taicpu.op_reg(A_TST,countreg));
  590. a_jmp_flags(list,F_EQ,l2);
  591. cg.a_label(list,l1);
  592. case op of
  593. OP_SHR:
  594. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  595. OP_SHL:
  596. list.concat(taicpu.op_reg(A_LSL,dst));
  597. OP_SAR:
  598. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  599. OP_ROR:
  600. begin
  601. { load carry? }
  602. if not(size in [OS_8,OS_S8]) then
  603. begin
  604. list.concat(taicpu.op_none(A_CLC));
  605. list.concat(taicpu.op_reg_const(A_SBRC,src,0));
  606. list.concat(taicpu.op_none(A_SEC));
  607. end;
  608. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  609. end;
  610. OP_ROL:
  611. begin
  612. { load carry? }
  613. if not(size in [OS_8,OS_S8]) then
  614. begin
  615. list.concat(taicpu.op_none(A_CLC));
  616. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
  617. list.concat(taicpu.op_none(A_SEC));
  618. end;
  619. list.concat(taicpu.op_reg(A_ROL,dst))
  620. end;
  621. else
  622. internalerror(2011030901);
  623. end;
  624. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  625. begin
  626. for i:=2 to tcgsize2size[size] do
  627. begin
  628. case op of
  629. OP_ROR,
  630. OP_SHR:
  631. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  632. OP_ROL,
  633. OP_SHL:
  634. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
  635. OP_SAR:
  636. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  637. else
  638. internalerror(2011030902);
  639. end;
  640. end;
  641. end;
  642. list.concat(taicpu.op_reg(A_DEC,countreg));
  643. a_jmp_flags(list,F_NE,l1);
  644. // keep registers alive
  645. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  646. cg.a_label(list,l2);
  647. end;
  648. OP_AND,OP_OR,OP_XOR:
  649. begin
  650. for i:=1 to tcgsize2size[size] do
  651. begin
  652. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  653. NextSrcDst;
  654. end;
  655. end;
  656. else
  657. internalerror(2011022004);
  658. end;
  659. end;
  660. procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  661. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  662. var
  663. mask : qword;
  664. shift : byte;
  665. i,j : byte;
  666. tmpreg : tregister;
  667. tmpreg64 : tregister64;
  668. procedure NextReg;
  669. begin
  670. if i=5 then
  671. reg:=reghi
  672. else
  673. reg:=GetNextReg(reg);
  674. end;
  675. var
  676. curvalue : byte;
  677. begin
  678. optimize_op_const(size,op,a);
  679. mask:=$ff;
  680. shift:=0;
  681. case op of
  682. OP_NONE:
  683. begin
  684. { Opcode is optimized away }
  685. end;
  686. OP_MOVE:
  687. begin
  688. { Optimized, replaced with a simple load }
  689. a_load_const_reg(list,size,a,reg);
  690. end;
  691. OP_OR:
  692. begin
  693. for i:=1 to tcgsize2size[size] do
  694. begin
  695. if ((qword(a) and mask) shr shift)<>0 then
  696. list.concat(taicpu.op_reg_const(A_ORI,reg,(qword(a) and mask) shr shift));
  697. NextReg;
  698. mask:=mask shl 8;
  699. inc(shift,8);
  700. end;
  701. end;
  702. OP_AND:
  703. begin
  704. for i:=1 to tcgsize2size[size] do
  705. begin
  706. if ((qword(a) and mask) shr shift)=0 then
  707. list.concat(taicpu.op_reg_reg(A_MOV,reg,NR_R1))
  708. else
  709. list.concat(taicpu.op_reg_const(A_ANDI,reg,(qword(a) and mask) shr shift));
  710. NextReg;
  711. mask:=mask shl 8;
  712. inc(shift,8);
  713. end;
  714. end;
  715. OP_SUB:
  716. begin
  717. if ((a and mask)=1) and (tcgsize2size[size]=1) then
  718. list.concat(taicpu.op_reg(A_DEC,reg))
  719. else
  720. list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
  721. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  722. begin
  723. for i:=2 to tcgsize2size[size] do
  724. begin
  725. NextReg;
  726. mask:=mask shl 8;
  727. inc(shift,8);
  728. curvalue:=(qword(a) and mask) shr shift;
  729. { decrease pressure on upper half of registers by using SBC ...,R1 instead
  730. of SBCI ...,0 }
  731. if curvalue=0 then
  732. list.concat(taicpu.op_reg_reg(A_SBC,reg,NR_R1))
  733. else
  734. list.concat(taicpu.op_reg_const(A_SBCI,reg,curvalue));
  735. end;
  736. end;
  737. end;
  738. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  739. begin
  740. if a*tcgsize2size[size]<=8 then
  741. begin
  742. for j:=1 to a do
  743. begin
  744. case op of
  745. OP_SHR:
  746. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  747. OP_SHL:
  748. list.concat(taicpu.op_reg(A_LSL,reg));
  749. OP_SAR:
  750. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  751. OP_ROR:
  752. begin
  753. { load carry? }
  754. if not(size in [OS_8,OS_S8]) then
  755. begin
  756. list.concat(taicpu.op_none(A_CLC));
  757. list.concat(taicpu.op_reg_const(A_SBRC,reg,0));
  758. list.concat(taicpu.op_none(A_SEC));
  759. end;
  760. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  761. end;
  762. OP_ROL:
  763. begin
  764. { load carry? }
  765. if not(size in [OS_8,OS_S8]) then
  766. begin
  767. list.concat(taicpu.op_none(A_CLC));
  768. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),7));
  769. list.concat(taicpu.op_none(A_SEC));
  770. end;
  771. list.concat(taicpu.op_reg(A_ROL,reg))
  772. end;
  773. else
  774. internalerror(2011030901);
  775. end;
  776. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  777. begin
  778. for i:=2 to tcgsize2size[size] do
  779. begin
  780. case op of
  781. OP_ROR,
  782. OP_SHR:
  783. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  784. OP_ROL,
  785. OP_SHL:
  786. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(reg,reghi,i-1)));
  787. OP_SAR:
  788. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  789. else
  790. internalerror(2011030902);
  791. end;
  792. end;
  793. end;
  794. end;
  795. end
  796. else
  797. begin
  798. tmpreg:=getintregister(list,size);
  799. a_load_const_reg(list,size,a,tmpreg);
  800. a_op_reg_reg(list,op,size,tmpreg,reg);
  801. end;
  802. end;
  803. OP_ADD:
  804. begin
  805. curvalue:=a and mask;
  806. if curvalue=0 then
  807. list.concat(taicpu.op_reg_reg(A_ADD,reg,NR_R1))
  808. else if (curvalue=1) and (tcgsize2size[size]=1) then
  809. list.concat(taicpu.op_reg(A_INC,reg))
  810. else
  811. begin
  812. tmpreg:=getintregister(list,OS_8);
  813. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  814. list.concat(taicpu.op_reg_reg(A_ADD,reg,tmpreg));
  815. end;
  816. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  817. begin
  818. for i:=2 to tcgsize2size[size] do
  819. begin
  820. NextReg;
  821. mask:=mask shl 8;
  822. inc(shift,8);
  823. curvalue:=(qword(a) and mask) shr shift;
  824. { decrease pressure on upper half of registers by using ADC ...,R1 instead
  825. of ADD ...,0 }
  826. if curvalue=0 then
  827. list.concat(taicpu.op_reg_reg(A_ADC,reg,NR_R1))
  828. else
  829. begin
  830. tmpreg:=getintregister(list,OS_8);
  831. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  832. list.concat(taicpu.op_reg_reg(A_ADC,reg,tmpreg));
  833. end;
  834. end;
  835. end;
  836. end;
  837. else
  838. begin
  839. if size in [OS_64,OS_S64] then
  840. begin
  841. tmpreg64.reglo:=getintregister(list,OS_32);
  842. tmpreg64.reghi:=getintregister(list,OS_32);
  843. cg64.a_load64_const_reg(list,a,tmpreg64);
  844. cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  845. end
  846. else
  847. begin
  848. {$if 0}
  849. { code not working yet }
  850. if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  851. begin
  852. tmpreg:=reg;
  853. for i:=1 to 4 do
  854. begin
  855. list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  856. tmpreg:=GetNextReg(tmpreg);
  857. end;
  858. end
  859. else
  860. {$endif}
  861. begin
  862. tmpreg:=getintregister(list,size);
  863. a_load_const_reg(list,size,a,tmpreg);
  864. a_op_reg_reg(list,op,size,tmpreg,reg);
  865. end;
  866. end;
  867. end;
  868. end;
  869. end;
  870. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  871. var
  872. mask : qword;
  873. shift : byte;
  874. i : byte;
  875. begin
  876. mask:=$ff;
  877. shift:=0;
  878. for i:=1 to tcgsize2size[size] do
  879. begin
  880. if ((qword(a) and mask) shr shift)=0 then
  881. emit_mov(list,reg,NR_R1)
  882. else
  883. begin
  884. getcpuregister(list,NR_R26);
  885. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
  886. a_load_reg_reg(list,OS_8,OS_8,NR_R26,reg);
  887. ungetcpuregister(list,NR_R26);
  888. end;
  889. mask:=mask shl 8;
  890. inc(shift,8);
  891. reg:=GetNextReg(reg);
  892. end;
  893. end;
  894. procedure tcgavr.maybegetcpuregister(list:tasmlist;reg : tregister);
  895. begin
  896. { allocate the register only, if a cpu register is passed }
  897. if getsupreg(reg)<first_int_imreg then
  898. getcpuregister(list,reg);
  899. end;
  900. function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
  901. var
  902. tmpref : treference;
  903. l : tasmlabel;
  904. begin
  905. Result:=ref;
  906. if ref.addressmode<>AM_UNCHANGED then
  907. internalerror(2011021701);
  908. { Be sure to have a base register }
  909. if (ref.base=NR_NO) then
  910. begin
  911. { only symbol+offset? }
  912. if ref.index=NR_NO then
  913. exit;
  914. ref.base:=ref.index;
  915. ref.index:=NR_NO;
  916. end;
  917. { can we take advantage of adiw/sbiw? }
  918. if (current_settings.cputype>=cpu_avr2) and not(assigned(ref.symbol)) and (ref.offset<>0) and (ref.offset>=-63) and (ref.offset<=63) and
  919. ((tmpreg=NR_R24) or (tmpreg=NR_R26) or (tmpreg=NR_R28) or (tmpreg=NR_R30)) and (ref.base<>NR_NO) then
  920. begin
  921. maybegetcpuregister(list,tmpreg);
  922. emit_mov(list,tmpreg,ref.base);
  923. maybegetcpuregister(list,GetNextReg(tmpreg));
  924. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  925. if ref.index<>NR_NO then
  926. begin
  927. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  928. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  929. end;
  930. if ref.offset>0 then
  931. list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
  932. else
  933. list.concat(taicpu.op_reg_const(A_SBIW,tmpreg,-ref.offset));
  934. ref.offset:=0;
  935. ref.base:=tmpreg;
  936. ref.index:=NR_NO;
  937. end
  938. else if assigned(ref.symbol) or (ref.offset<>0) then
  939. begin
  940. reference_reset(tmpref,0,[]);
  941. tmpref.symbol:=ref.symbol;
  942. tmpref.offset:=ref.offset;
  943. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  944. tmpref.refaddr:=addr_lo8_gs
  945. else
  946. tmpref.refaddr:=addr_lo8;
  947. maybegetcpuregister(list,tmpreg);
  948. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  949. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  950. tmpref.refaddr:=addr_hi8_gs
  951. else
  952. tmpref.refaddr:=addr_hi8;
  953. maybegetcpuregister(list,GetNextReg(tmpreg));
  954. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  955. if (ref.base<>NR_NO) then
  956. begin
  957. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  958. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  959. end;
  960. if (ref.index<>NR_NO) then
  961. begin
  962. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  963. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  964. end;
  965. ref.symbol:=nil;
  966. ref.offset:=0;
  967. ref.base:=tmpreg;
  968. ref.index:=NR_NO;
  969. end
  970. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  971. begin
  972. maybegetcpuregister(list,tmpreg);
  973. emit_mov(list,tmpreg,ref.base);
  974. maybegetcpuregister(list,GetNextReg(tmpreg));
  975. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  976. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  977. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  978. ref.base:=tmpreg;
  979. ref.index:=NR_NO;
  980. end
  981. else if (ref.base<>NR_NO) then
  982. begin
  983. maybegetcpuregister(list,tmpreg);
  984. emit_mov(list,tmpreg,ref.base);
  985. maybegetcpuregister(list,GetNextReg(tmpreg));
  986. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  987. ref.base:=tmpreg;
  988. ref.index:=NR_NO;
  989. end
  990. else if (ref.index<>NR_NO) then
  991. begin
  992. maybegetcpuregister(list,tmpreg);
  993. emit_mov(list,tmpreg,ref.index);
  994. maybegetcpuregister(list,GetNextReg(tmpreg));
  995. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
  996. ref.base:=tmpreg;
  997. ref.index:=NR_NO;
  998. end;
  999. Result:=ref;
  1000. end;
  1001. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1002. var
  1003. href : treference;
  1004. conv_done: boolean;
  1005. tmpreg : tregister;
  1006. i : integer;
  1007. QuickRef : Boolean;
  1008. begin
  1009. QuickRef:=false;
  1010. href:=Ref;
  1011. { ensure, href.base contains a valid register if there is any register used }
  1012. if href.base=NR_NO then
  1013. begin
  1014. href.base:=href.index;
  1015. href.index:=NR_NO;
  1016. end;
  1017. { try to use std/sts }
  1018. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1019. begin
  1020. if not((href.addressmode=AM_UNCHANGED) and
  1021. (href.symbol=nil) and
  1022. (href.Index=NR_NO) and
  1023. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1024. href:=normalize_ref(list,href,NR_R30)
  1025. else
  1026. begin
  1027. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1028. begin
  1029. maybegetcpuregister(list,NR_R30);
  1030. emit_mov(list,NR_R30,href.base);
  1031. maybegetcpuregister(list,NR_R31);
  1032. emit_mov(list,NR_R31,GetNextReg(href.base));
  1033. href.base:=NR_R30;
  1034. end;
  1035. QuickRef:=true;
  1036. end;
  1037. end
  1038. else
  1039. QuickRef:=true;
  1040. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1041. internalerror(2011021307);
  1042. conv_done:=false;
  1043. if tosize<>fromsize then
  1044. begin
  1045. conv_done:=true;
  1046. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1047. fromsize:=tosize;
  1048. case fromsize of
  1049. OS_8:
  1050. begin
  1051. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1052. href.addressmode:=AM_POSTINCREMENT;
  1053. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1054. for i:=2 to tcgsize2size[tosize] do
  1055. begin
  1056. if QuickRef then
  1057. inc(href.offset);
  1058. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1059. href.addressmode:=AM_POSTINCREMENT
  1060. else
  1061. href.addressmode:=AM_UNCHANGED;
  1062. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1063. end;
  1064. end;
  1065. OS_S8:
  1066. begin
  1067. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1068. href.addressmode:=AM_POSTINCREMENT;
  1069. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1070. if tcgsize2size[tosize]>1 then
  1071. begin
  1072. tmpreg:=getintregister(list,OS_8);
  1073. emit_mov(list,tmpreg,NR_R1);
  1074. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1075. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1076. for i:=2 to tcgsize2size[tosize] do
  1077. begin
  1078. if QuickRef then
  1079. inc(href.offset);
  1080. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1081. href.addressmode:=AM_POSTINCREMENT
  1082. else
  1083. href.addressmode:=AM_UNCHANGED;
  1084. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1085. end;
  1086. end;
  1087. end;
  1088. OS_16:
  1089. begin
  1090. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1091. href.addressmode:=AM_POSTINCREMENT;
  1092. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1093. if QuickRef then
  1094. inc(href.offset)
  1095. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1096. href.addressmode:=AM_POSTINCREMENT
  1097. else
  1098. href.addressmode:=AM_UNCHANGED;
  1099. reg:=GetNextReg(reg);
  1100. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1101. for i:=3 to tcgsize2size[tosize] do
  1102. begin
  1103. if QuickRef then
  1104. inc(href.offset);
  1105. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1106. href.addressmode:=AM_POSTINCREMENT
  1107. else
  1108. href.addressmode:=AM_UNCHANGED;
  1109. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1110. end;
  1111. end;
  1112. OS_S16:
  1113. begin
  1114. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1115. href.addressmode:=AM_POSTINCREMENT;
  1116. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1117. if QuickRef then
  1118. inc(href.offset)
  1119. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1120. href.addressmode:=AM_POSTINCREMENT
  1121. else
  1122. href.addressmode:=AM_UNCHANGED;
  1123. reg:=GetNextReg(reg);
  1124. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1125. if tcgsize2size[tosize]>2 then
  1126. begin
  1127. tmpreg:=getintregister(list,OS_8);
  1128. emit_mov(list,tmpreg,NR_R1);
  1129. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1130. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1131. for i:=3 to tcgsize2size[tosize] do
  1132. begin
  1133. if QuickRef then
  1134. inc(href.offset);
  1135. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1136. href.addressmode:=AM_POSTINCREMENT
  1137. else
  1138. href.addressmode:=AM_UNCHANGED;
  1139. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1140. end;
  1141. end;
  1142. end;
  1143. else
  1144. conv_done:=false;
  1145. end;
  1146. end;
  1147. if not conv_done then
  1148. begin
  1149. for i:=1 to tcgsize2size[fromsize] do
  1150. begin
  1151. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1152. href.addressmode:=AM_POSTINCREMENT
  1153. else
  1154. href.addressmode:=AM_UNCHANGED;
  1155. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1156. if QuickRef then
  1157. inc(href.offset);
  1158. reg:=GetNextReg(reg);
  1159. end;
  1160. end;
  1161. if not(QuickRef) then
  1162. begin
  1163. ungetcpuregister(list,href.base);
  1164. ungetcpuregister(list,GetNextReg(href.base));
  1165. end;
  1166. end;
  1167. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1168. const Ref : treference;reg : tregister);
  1169. var
  1170. href : treference;
  1171. conv_done: boolean;
  1172. tmpreg : tregister;
  1173. i : integer;
  1174. QuickRef : boolean;
  1175. begin
  1176. QuickRef:=false;
  1177. href:=Ref;
  1178. { ensure, href.base contains a valid register if there is any register used }
  1179. if href.base=NR_NO then
  1180. begin
  1181. href.base:=href.index;
  1182. href.index:=NR_NO;
  1183. end;
  1184. { try to use ldd/lds }
  1185. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1186. begin
  1187. if not((href.addressmode=AM_UNCHANGED) and
  1188. (href.symbol=nil) and
  1189. (href.Index=NR_NO) and
  1190. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1191. href:=normalize_ref(list,href,NR_R30)
  1192. else
  1193. begin
  1194. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1195. begin
  1196. maybegetcpuregister(list,NR_R30);
  1197. emit_mov(list,NR_R30,href.base);
  1198. maybegetcpuregister(list,NR_R31);
  1199. emit_mov(list,NR_R31,GetNextReg(href.base));
  1200. href.base:=NR_R30;
  1201. end;
  1202. QuickRef:=true;
  1203. end;
  1204. end
  1205. else
  1206. QuickRef:=true;
  1207. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1208. internalerror(2011021307);
  1209. conv_done:=false;
  1210. if tosize<>fromsize then
  1211. begin
  1212. conv_done:=true;
  1213. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1214. fromsize:=tosize;
  1215. case fromsize of
  1216. OS_8:
  1217. begin
  1218. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1219. for i:=2 to tcgsize2size[tosize] do
  1220. begin
  1221. reg:=GetNextReg(reg);
  1222. emit_mov(list,reg,NR_R1);
  1223. end;
  1224. end;
  1225. OS_S8:
  1226. begin
  1227. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1228. tmpreg:=reg;
  1229. if tcgsize2size[tosize]>1 then
  1230. begin
  1231. reg:=GetNextReg(reg);
  1232. emit_mov(list,reg,NR_R1);
  1233. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1234. list.concat(taicpu.op_reg(A_COM,reg));
  1235. tmpreg:=reg;
  1236. for i:=3 to tcgsize2size[tosize] do
  1237. begin
  1238. reg:=GetNextReg(reg);
  1239. emit_mov(list,reg,tmpreg);
  1240. end;
  1241. end;
  1242. end;
  1243. OS_16:
  1244. begin
  1245. if not(QuickRef) then
  1246. href.addressmode:=AM_POSTINCREMENT;
  1247. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1248. if QuickRef then
  1249. inc(href.offset);
  1250. href.addressmode:=AM_UNCHANGED;
  1251. reg:=GetNextReg(reg);
  1252. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1253. for i:=3 to tcgsize2size[tosize] do
  1254. begin
  1255. reg:=GetNextReg(reg);
  1256. emit_mov(list,reg,NR_R1);
  1257. end;
  1258. end;
  1259. OS_S16:
  1260. begin
  1261. if not(QuickRef) then
  1262. href.addressmode:=AM_POSTINCREMENT;
  1263. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1264. if QuickRef then
  1265. inc(href.offset);
  1266. href.addressmode:=AM_UNCHANGED;
  1267. reg:=GetNextReg(reg);
  1268. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1269. tmpreg:=reg;
  1270. reg:=GetNextReg(reg);
  1271. emit_mov(list,reg,NR_R1);
  1272. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1273. list.concat(taicpu.op_reg(A_COM,reg));
  1274. tmpreg:=reg;
  1275. for i:=4 to tcgsize2size[tosize] do
  1276. begin
  1277. reg:=GetNextReg(reg);
  1278. emit_mov(list,reg,tmpreg);
  1279. end;
  1280. end;
  1281. else
  1282. conv_done:=false;
  1283. end;
  1284. end;
  1285. if not conv_done then
  1286. begin
  1287. for i:=1 to tcgsize2size[fromsize] do
  1288. begin
  1289. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1290. href.addressmode:=AM_POSTINCREMENT
  1291. else
  1292. href.addressmode:=AM_UNCHANGED;
  1293. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1294. if QuickRef then
  1295. inc(href.offset);
  1296. reg:=GetNextReg(reg);
  1297. end;
  1298. end;
  1299. if not(QuickRef) then
  1300. begin
  1301. ungetcpuregister(list,href.base);
  1302. ungetcpuregister(list,GetNextReg(href.base));
  1303. end;
  1304. end;
  1305. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1306. var
  1307. conv_done: boolean;
  1308. tmpreg : tregister;
  1309. i : integer;
  1310. begin
  1311. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1312. internalerror(2011021310);
  1313. conv_done:=false;
  1314. if tosize<>fromsize then
  1315. begin
  1316. conv_done:=true;
  1317. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1318. fromsize:=tosize;
  1319. case fromsize of
  1320. OS_8:
  1321. begin
  1322. emit_mov(list,reg2,reg1);
  1323. for i:=2 to tcgsize2size[tosize] do
  1324. begin
  1325. reg2:=GetNextReg(reg2);
  1326. emit_mov(list,reg2,NR_R1);
  1327. end;
  1328. end;
  1329. OS_S8:
  1330. begin
  1331. emit_mov(list,reg2,reg1);
  1332. if tcgsize2size[tosize]>1 then
  1333. begin
  1334. reg2:=GetNextReg(reg2);
  1335. emit_mov(list,reg2,NR_R1);
  1336. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1337. list.concat(taicpu.op_reg(A_COM,reg2));
  1338. tmpreg:=reg2;
  1339. for i:=3 to tcgsize2size[tosize] do
  1340. begin
  1341. reg2:=GetNextReg(reg2);
  1342. emit_mov(list,reg2,tmpreg);
  1343. end;
  1344. end;
  1345. end;
  1346. OS_16:
  1347. begin
  1348. emit_mov(list,reg2,reg1);
  1349. reg1:=GetNextReg(reg1);
  1350. reg2:=GetNextReg(reg2);
  1351. emit_mov(list,reg2,reg1);
  1352. for i:=3 to tcgsize2size[tosize] do
  1353. begin
  1354. reg2:=GetNextReg(reg2);
  1355. emit_mov(list,reg2,NR_R1);
  1356. end;
  1357. end;
  1358. OS_S16:
  1359. begin
  1360. emit_mov(list,reg2,reg1);
  1361. reg1:=GetNextReg(reg1);
  1362. reg2:=GetNextReg(reg2);
  1363. emit_mov(list,reg2,reg1);
  1364. if tcgsize2size[tosize]>2 then
  1365. begin
  1366. reg2:=GetNextReg(reg2);
  1367. emit_mov(list,reg2,NR_R1);
  1368. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1369. list.concat(taicpu.op_reg(A_COM,reg2));
  1370. tmpreg:=reg2;
  1371. for i:=4 to tcgsize2size[tosize] do
  1372. begin
  1373. reg2:=GetNextReg(reg2);
  1374. emit_mov(list,reg2,tmpreg);
  1375. end;
  1376. end;
  1377. end;
  1378. else
  1379. conv_done:=false;
  1380. end;
  1381. end;
  1382. if not conv_done and (reg1<>reg2) then
  1383. begin
  1384. for i:=1 to tcgsize2size[fromsize] do
  1385. begin
  1386. emit_mov(list,reg2,reg1);
  1387. reg1:=GetNextReg(reg1);
  1388. reg2:=GetNextReg(reg2);
  1389. end;
  1390. end;
  1391. end;
  1392. procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1393. begin
  1394. internalerror(2012010702);
  1395. end;
  1396. procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1397. begin
  1398. internalerror(2012010703);
  1399. end;
  1400. procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1401. begin
  1402. internalerror(2012010704);
  1403. end;
  1404. { comparison operations }
  1405. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1406. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1407. var
  1408. swapped : boolean;
  1409. tmpreg : tregister;
  1410. i : byte;
  1411. begin
  1412. if a=0 then
  1413. begin
  1414. swapped:=false;
  1415. { swap parameters? }
  1416. case cmp_op of
  1417. OC_GT:
  1418. begin
  1419. swapped:=true;
  1420. cmp_op:=OC_LT;
  1421. end;
  1422. OC_LTE:
  1423. begin
  1424. swapped:=true;
  1425. cmp_op:=OC_GTE;
  1426. end;
  1427. OC_BE:
  1428. begin
  1429. swapped:=true;
  1430. cmp_op:=OC_AE;
  1431. end;
  1432. OC_A:
  1433. begin
  1434. swapped:=true;
  1435. cmp_op:=OC_B;
  1436. end;
  1437. end;
  1438. if swapped then
  1439. list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
  1440. else
  1441. list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
  1442. for i:=2 to tcgsize2size[size] do
  1443. begin
  1444. reg:=GetNextReg(reg);
  1445. if swapped then
  1446. list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
  1447. else
  1448. list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
  1449. end;
  1450. a_jmp_cond(list,cmp_op,l);
  1451. end
  1452. else
  1453. inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1454. end;
  1455. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1456. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1457. var
  1458. swapped : boolean;
  1459. tmpreg : tregister;
  1460. i : byte;
  1461. begin
  1462. swapped:=false;
  1463. { swap parameters? }
  1464. case cmp_op of
  1465. OC_GT:
  1466. begin
  1467. swapped:=true;
  1468. cmp_op:=OC_LT;
  1469. end;
  1470. OC_LTE:
  1471. begin
  1472. swapped:=true;
  1473. cmp_op:=OC_GTE;
  1474. end;
  1475. OC_BE:
  1476. begin
  1477. swapped:=true;
  1478. cmp_op:=OC_AE;
  1479. end;
  1480. OC_A:
  1481. begin
  1482. swapped:=true;
  1483. cmp_op:=OC_B;
  1484. end;
  1485. end;
  1486. if swapped then
  1487. begin
  1488. tmpreg:=reg1;
  1489. reg1:=reg2;
  1490. reg2:=tmpreg;
  1491. end;
  1492. list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1493. for i:=2 to tcgsize2size[size] do
  1494. begin
  1495. reg1:=GetNextReg(reg1);
  1496. reg2:=GetNextReg(reg2);
  1497. list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1498. end;
  1499. a_jmp_cond(list,cmp_op,l);
  1500. end;
  1501. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  1502. var
  1503. ai : taicpu;
  1504. begin
  1505. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1506. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION))
  1507. else
  1508. ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1509. ai.is_jmp:=true;
  1510. list.concat(ai);
  1511. end;
  1512. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  1513. var
  1514. ai : taicpu;
  1515. begin
  1516. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1517. ai:=taicpu.op_sym(A_JMP,l)
  1518. else
  1519. ai:=taicpu.op_sym(A_RJMP,l);
  1520. ai.is_jmp:=true;
  1521. list.concat(ai);
  1522. end;
  1523. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1524. var
  1525. ai : taicpu;
  1526. begin
  1527. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  1528. ai.is_jmp:=true;
  1529. list.concat(ai);
  1530. end;
  1531. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1532. var
  1533. l : TAsmLabel;
  1534. tmpflags : TResFlags;
  1535. begin
  1536. current_asmdata.getjumplabel(l);
  1537. {
  1538. if flags_to_cond(f) then
  1539. begin
  1540. tmpflags:=f;
  1541. inverse_flags(tmpflags);
  1542. emit_mov(reg,NR_R1);
  1543. a_jmp_flags(list,tmpflags,l);
  1544. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1545. end
  1546. else
  1547. }
  1548. begin
  1549. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1550. a_jmp_flags(list,f,l);
  1551. emit_mov(list,reg,NR_R1);
  1552. end;
  1553. cg.a_label(list,l);
  1554. end;
  1555. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  1556. var
  1557. i : integer;
  1558. begin
  1559. case value of
  1560. 0:
  1561. ;
  1562. {-14..-1:
  1563. begin
  1564. if ((-value) mod 2)<>0 then
  1565. list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1566. for i:=1 to (-value) div 2 do
  1567. list.concat(taicpu.op_const(A_RCALL,0));
  1568. end;
  1569. 1..7:
  1570. begin
  1571. for i:=1 to value do
  1572. list.concat(taicpu.op_reg(A_POP,NR_R0));
  1573. end;}
  1574. else
  1575. begin
  1576. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1577. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1578. // get SREG
  1579. list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1580. // block interrupts
  1581. list.concat(taicpu.op_none(A_CLI));
  1582. // write high SP
  1583. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1584. // release interrupts
  1585. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1586. // write low SP
  1587. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1588. end;
  1589. end;
  1590. end;
  1591. function tcgavr.GetLoad(const ref: treference) : tasmop;
  1592. begin
  1593. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1594. result:=A_LDS
  1595. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1596. result:=A_LDD
  1597. else
  1598. result:=A_LD;
  1599. end;
  1600. function tcgavr.GetStore(const ref: treference) : tasmop;
  1601. begin
  1602. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1603. result:=A_STS
  1604. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1605. result:=A_STD
  1606. else
  1607. result:=A_ST;
  1608. end;
  1609. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1610. var
  1611. regs : tcpuregisterset;
  1612. reg : tsuperregister;
  1613. begin
  1614. if po_interrupt in current_procinfo.procdef.procoptions then
  1615. begin
  1616. { check if the framepointer is actually used, this is done here because
  1617. we have to know the size of the locals (must be 0), avr does not know
  1618. an sp based stack }
  1619. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1620. (localsize=0) then
  1621. current_procinfo.framepointer:=NR_NO;
  1622. { save int registers,
  1623. but only if the procedure returns }
  1624. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1625. regs:=rg[R_INTREGISTER].used_in_proc
  1626. else
  1627. regs:=[];
  1628. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1629. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1630. an outer stackframe }
  1631. if current_procinfo.framepointer<>NR_NO then
  1632. regs:=regs+[RS_R28,RS_R29];
  1633. regs:=regs+[RS_R0];
  1634. for reg:=RS_R31 downto RS_R0 do
  1635. if reg in regs then
  1636. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1637. { Save SREG }
  1638. list.concat(taicpu.op_reg_const(A_IN, NR_R0, $3F));
  1639. list.concat(taicpu.op_reg(A_PUSH, NR_R0));
  1640. if current_procinfo.framepointer<>NR_NO then
  1641. begin
  1642. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1643. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1644. a_adjust_sp(list,-localsize);
  1645. end;
  1646. end
  1647. else if not(nostackframe) then
  1648. begin
  1649. { check if the framepointer is actually used, this is done here because
  1650. we have to know the size of the locals (must be 0), avr does not know
  1651. an sp based stack }
  1652. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1653. (localsize=0) then
  1654. current_procinfo.framepointer:=NR_NO;
  1655. { save int registers,
  1656. but only if the procedure returns }
  1657. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1658. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)
  1659. else
  1660. regs:=[];
  1661. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1662. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1663. an outer stackframe }
  1664. if current_procinfo.framepointer<>NR_NO then
  1665. regs:=regs+[RS_R28,RS_R29];
  1666. for reg:=RS_R31 downto RS_R0 do
  1667. if reg in regs then
  1668. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1669. if current_procinfo.framepointer<>NR_NO then
  1670. begin
  1671. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1672. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1673. a_adjust_sp(list,-localsize);
  1674. end;
  1675. end;
  1676. end;
  1677. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1678. var
  1679. regs : tcpuregisterset;
  1680. reg : TSuperRegister;
  1681. LocalSize : longint;
  1682. begin
  1683. { every byte counts for avr, so if a subroutine is marked as non-returning, we do
  1684. not generate any exit code, so we really trust the noreturn directive
  1685. }
  1686. if po_noreturn in current_procinfo.procdef.procoptions then
  1687. exit;
  1688. if po_interrupt in current_procinfo.procdef.procoptions then
  1689. begin
  1690. regs:=rg[R_INTREGISTER].used_in_proc;
  1691. if current_procinfo.framepointer<>NR_NO then
  1692. begin
  1693. regs:=regs+[RS_R28,RS_R29];
  1694. LocalSize:=current_procinfo.calc_stackframe_size;
  1695. a_adjust_sp(list,LocalSize);
  1696. end;
  1697. { Reload SREG }
  1698. regs:=regs+[RS_R0];
  1699. list.concat(taicpu.op_reg(A_POP, NR_R0));
  1700. list.concat(taicpu.op_const_reg(A_OUT, $3F, NR_R0));
  1701. for reg:=RS_R0 to RS_R31 do
  1702. if reg in regs then
  1703. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1704. list.concat(taicpu.op_none(A_RETI));
  1705. end
  1706. else if not(nostackframe) then
  1707. begin
  1708. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  1709. if current_procinfo.framepointer<>NR_NO then
  1710. begin
  1711. regs:=regs+[RS_R28,RS_R29];
  1712. LocalSize:=current_procinfo.calc_stackframe_size;
  1713. a_adjust_sp(list,LocalSize);
  1714. end;
  1715. for reg:=RS_R0 to RS_R31 do
  1716. if reg in regs then
  1717. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1718. list.concat(taicpu.op_none(A_RET));
  1719. end
  1720. else
  1721. list.concat(taicpu.op_none(A_RET));
  1722. end;
  1723. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1724. var
  1725. tmpref : treference;
  1726. begin
  1727. if ref.addressmode<>AM_UNCHANGED then
  1728. internalerror(2011021701);
  1729. if assigned(ref.symbol) or (ref.offset<>0) then
  1730. begin
  1731. reference_reset(tmpref,0,[]);
  1732. tmpref.symbol:=ref.symbol;
  1733. tmpref.offset:=ref.offset;
  1734. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1735. tmpref.refaddr:=addr_lo8_gs
  1736. else
  1737. tmpref.refaddr:=addr_lo8;
  1738. list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  1739. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1740. tmpref.refaddr:=addr_hi8_gs
  1741. else
  1742. tmpref.refaddr:=addr_hi8;
  1743. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  1744. if (ref.base<>NR_NO) then
  1745. begin
  1746. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  1747. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  1748. end;
  1749. if (ref.index<>NR_NO) then
  1750. begin
  1751. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1752. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1753. end;
  1754. end
  1755. else if (ref.base<>NR_NO)then
  1756. begin
  1757. emit_mov(list,r,ref.base);
  1758. emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  1759. if (ref.index<>NR_NO) then
  1760. begin
  1761. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1762. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1763. end;
  1764. end
  1765. else if (ref.index<>NR_NO) then
  1766. begin
  1767. emit_mov(list,r,ref.index);
  1768. emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  1769. end;
  1770. end;
  1771. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  1772. begin
  1773. internalerror(2011021320);
  1774. end;
  1775. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  1776. var
  1777. paraloc1,paraloc2,paraloc3 : TCGPara;
  1778. pd : tprocdef;
  1779. begin
  1780. pd:=search_system_proc('MOVE');
  1781. paraloc1.init;
  1782. paraloc2.init;
  1783. paraloc3.init;
  1784. paramanager.getintparaloc(list,pd,1,paraloc1);
  1785. paramanager.getintparaloc(list,pd,2,paraloc2);
  1786. paramanager.getintparaloc(list,pd,3,paraloc3);
  1787. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  1788. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  1789. a_loadaddr_ref_cgpara(list,source,paraloc1);
  1790. paramanager.freecgpara(list,paraloc3);
  1791. paramanager.freecgpara(list,paraloc2);
  1792. paramanager.freecgpara(list,paraloc1);
  1793. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1794. a_call_name_static(list,'FPC_MOVE');
  1795. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1796. paraloc3.done;
  1797. paraloc2.done;
  1798. paraloc1.done;
  1799. end;
  1800. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1801. var
  1802. countreg,tmpreg : tregister;
  1803. srcref,dstref : treference;
  1804. copysize,countregsize : tcgsize;
  1805. l : TAsmLabel;
  1806. i : longint;
  1807. SrcQuickRef, DestQuickRef : Boolean;
  1808. begin
  1809. if len>16 then
  1810. begin
  1811. current_asmdata.getjumplabel(l);
  1812. reference_reset(srcref,source.alignment,source.volatility);
  1813. reference_reset(dstref,dest.alignment,source.volatility);
  1814. srcref.base:=NR_R30;
  1815. srcref.addressmode:=AM_POSTINCREMENT;
  1816. dstref.base:=NR_R26;
  1817. dstref.addressmode:=AM_POSTINCREMENT;
  1818. copysize:=OS_8;
  1819. if len<256 then
  1820. countregsize:=OS_8
  1821. else if len<65536 then
  1822. countregsize:=OS_16
  1823. else
  1824. internalerror(2011022007);
  1825. countreg:=getintregister(list,countregsize);
  1826. a_load_const_reg(list,countregsize,len,countreg);
  1827. a_loadaddr_ref_reg(list,source,NR_R30);
  1828. { only base or index register in dest? }
  1829. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1830. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1831. begin
  1832. if dest.base<>NR_NO then
  1833. tmpreg:=dest.base
  1834. else if dest.index<>NR_NO then
  1835. tmpreg:=dest.index
  1836. else
  1837. internalerror(2016112001);
  1838. end
  1839. else
  1840. begin
  1841. tmpreg:=getaddressregister(list);
  1842. a_loadaddr_ref_reg(list,dest,tmpreg);
  1843. end;
  1844. { X is used for spilling code so we can load it
  1845. only by a push/pop sequence, this can be
  1846. optimized later on by the peephole optimizer
  1847. }
  1848. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1849. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1850. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1851. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1852. cg.a_label(list,l);
  1853. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1854. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1855. list.concat(taicpu.op_reg(A_DEC,countreg));
  1856. a_jmp_flags(list,F_NE,l);
  1857. // keep registers alive
  1858. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  1859. end
  1860. else
  1861. begin
  1862. SrcQuickRef:=false;
  1863. DestQuickRef:=false;
  1864. if not((source.addressmode=AM_UNCHANGED) and
  1865. (source.symbol=nil) and
  1866. ((source.base=NR_R28) or
  1867. (source.base=NR_R30)) and
  1868. (source.Index=NR_NO) and
  1869. (source.Offset in [0..64-len])) and
  1870. not((source.Base=NR_NO) and (source.Index=NR_NO)) then
  1871. srcref:=normalize_ref(list,source,NR_R30)
  1872. else
  1873. begin
  1874. SrcQuickRef:=true;
  1875. srcref:=source;
  1876. end;
  1877. if not((dest.addressmode=AM_UNCHANGED) and
  1878. (dest.symbol=nil) and
  1879. ((dest.base=NR_R28) or
  1880. (dest.base=NR_R30)) and
  1881. (dest.Index=NR_No) and
  1882. (dest.Offset in [0..64-len])) and
  1883. not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
  1884. begin
  1885. if not(SrcQuickRef) then
  1886. begin
  1887. { only base or index register in dest? }
  1888. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1889. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1890. begin
  1891. if dest.base<>NR_NO then
  1892. tmpreg:=dest.base
  1893. else if dest.index<>NR_NO then
  1894. tmpreg:=dest.index
  1895. else
  1896. internalerror(2016112002);
  1897. end
  1898. else
  1899. tmpreg:=getaddressregister(list);
  1900. dstref:=normalize_ref(list,dest,tmpreg);
  1901. { X is used for spilling code so we can load it
  1902. only by a push/pop sequence, this can be
  1903. optimized later on by the peephole optimizer
  1904. }
  1905. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1906. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1907. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1908. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1909. dstref.base:=NR_R26;
  1910. end
  1911. else
  1912. dstref:=normalize_ref(list,dest,NR_R30);
  1913. end
  1914. else
  1915. begin
  1916. DestQuickRef:=true;
  1917. dstref:=dest;
  1918. end;
  1919. for i:=1 to len do
  1920. begin
  1921. if not(SrcQuickRef) and (i<len) then
  1922. srcref.addressmode:=AM_POSTINCREMENT
  1923. else
  1924. srcref.addressmode:=AM_UNCHANGED;
  1925. if not(DestQuickRef) and (i<len) then
  1926. dstref.addressmode:=AM_POSTINCREMENT
  1927. else
  1928. dstref.addressmode:=AM_UNCHANGED;
  1929. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1930. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1931. if SrcQuickRef then
  1932. inc(srcref.offset);
  1933. if DestQuickRef then
  1934. inc(dstref.offset);
  1935. end;
  1936. if not(SrcQuickRef) then
  1937. begin
  1938. ungetcpuregister(list,srcref.base);
  1939. ungetcpuregister(list,GetNextReg(srcref.base));
  1940. end;
  1941. end;
  1942. end;
  1943. procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  1944. var
  1945. hl : tasmlabel;
  1946. ai : taicpu;
  1947. cond : TAsmCond;
  1948. begin
  1949. if not(cs_check_overflow in current_settings.localswitches) then
  1950. exit;
  1951. current_asmdata.getjumplabel(hl);
  1952. if not ((def.typ=pointerdef) or
  1953. ((def.typ=orddef) and
  1954. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  1955. pasbool8,pasbool16,pasbool32,pasbool64]))) then
  1956. cond:=C_VC
  1957. else
  1958. cond:=C_CC;
  1959. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1960. ai.SetCondition(cond);
  1961. ai.is_jmp:=true;
  1962. list.concat(ai);
  1963. a_call_name(list,'FPC_OVERFLOW',false);
  1964. a_label(list,hl);
  1965. end;
  1966. procedure tcgavr.g_save_registers(list: TAsmList);
  1967. begin
  1968. { this is done by the entry code }
  1969. end;
  1970. procedure tcgavr.g_restore_registers(list: TAsmList);
  1971. begin
  1972. { this is done by the exit code }
  1973. end;
  1974. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1975. var
  1976. ai1,ai2 : taicpu;
  1977. hl : TAsmLabel;
  1978. begin
  1979. ai1:=Taicpu.Op_sym(A_BRxx,l);
  1980. ai1.is_jmp:=true;
  1981. hl:=nil;
  1982. case cond of
  1983. OC_EQ:
  1984. ai1.SetCondition(C_EQ);
  1985. OC_GT:
  1986. begin
  1987. { emulate GT }
  1988. current_asmdata.getjumplabel(hl);
  1989. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  1990. ai2.SetCondition(C_EQ);
  1991. ai2.is_jmp:=true;
  1992. list.concat(ai2);
  1993. ai1.SetCondition(C_GE);
  1994. end;
  1995. OC_LT:
  1996. ai1.SetCondition(C_LT);
  1997. OC_GTE:
  1998. ai1.SetCondition(C_GE);
  1999. OC_LTE:
  2000. begin
  2001. { emulate LTE }
  2002. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2003. ai2.SetCondition(C_EQ);
  2004. ai2.is_jmp:=true;
  2005. list.concat(ai2);
  2006. ai1.SetCondition(C_LT);
  2007. end;
  2008. OC_NE:
  2009. ai1.SetCondition(C_NE);
  2010. OC_BE:
  2011. begin
  2012. { emulate BE }
  2013. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2014. ai2.SetCondition(C_EQ);
  2015. ai2.is_jmp:=true;
  2016. list.concat(ai2);
  2017. ai1.SetCondition(C_LO);
  2018. end;
  2019. OC_B:
  2020. ai1.SetCondition(C_LO);
  2021. OC_AE:
  2022. ai1.SetCondition(C_SH);
  2023. OC_A:
  2024. begin
  2025. { emulate A (unsigned GT) }
  2026. current_asmdata.getjumplabel(hl);
  2027. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2028. ai2.SetCondition(C_EQ);
  2029. ai2.is_jmp:=true;
  2030. list.concat(ai2);
  2031. ai1.SetCondition(C_SH);
  2032. end;
  2033. else
  2034. internalerror(2011082501);
  2035. end;
  2036. list.concat(ai1);
  2037. if assigned(hl) then
  2038. a_label(list,hl);
  2039. end;
  2040. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2041. var
  2042. instr: taicpu;
  2043. begin
  2044. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  2045. list.Concat(instr);
  2046. { Notify the register allocator that we have written a move instruction so
  2047. it can try to eliminate it. }
  2048. add_move_instruction(instr);
  2049. end;
  2050. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2051. begin
  2052. if not(size in [OS_S64,OS_64]) then
  2053. internalerror(2012102402);
  2054. tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2055. end;
  2056. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2057. begin
  2058. tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2059. end;
  2060. procedure create_codegen;
  2061. begin
  2062. cg:=tcgavr.create;
  2063. cg64:=tcg64favr.create;
  2064. end;
  2065. end.