cgcpu.pas 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316
  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 : 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. paramanager.getintparaloc(list,pd,1,paraloc1);
  550. paramanager.getintparaloc(list,pd,2,paraloc2);
  551. a_load_reg_cgpara(list,OS_16,src,paraloc2);
  552. a_load_reg_cgpara(list,OS_16,dst,paraloc1);
  553. paramanager.freecgpara(list,paraloc2);
  554. paramanager.freecgpara(list,paraloc1);
  555. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  556. if size=OS_16 then
  557. a_call_name(list,'FPC_MUL_WORD',false)
  558. else
  559. a_call_name(list,'FPC_MUL_INTEGER',false);
  560. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  561. cg.a_reg_alloc(list,NR_R24);
  562. cg.a_reg_alloc(list,NR_R25);
  563. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  564. cg.a_reg_dealloc(list,NR_R24);
  565. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R25,GetNextReg(dst));
  566. cg.a_reg_dealloc(list,NR_R25);
  567. paraloc2.done;
  568. paraloc1.done;
  569. end;
  570. end
  571. else
  572. internalerror(2011022002);
  573. end;
  574. OP_DIV,OP_IDIV:
  575. { special stuff, needs separate handling inside code }
  576. { generator }
  577. internalerror(2011022001);
  578. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  579. begin
  580. current_asmdata.getjumplabel(l1);
  581. current_asmdata.getjumplabel(l2);
  582. countreg:=getintregister(list,OS_8);
  583. a_load_reg_reg(list,size,OS_8,src,countreg);
  584. list.concat(taicpu.op_reg(A_TST,countreg));
  585. a_jmp_flags(list,F_EQ,l2);
  586. cg.a_label(list,l1);
  587. case op of
  588. OP_SHR:
  589. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  590. OP_SHL:
  591. list.concat(taicpu.op_reg(A_LSL,dst));
  592. OP_SAR:
  593. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  594. OP_ROR:
  595. begin
  596. { load carry? }
  597. if not(size in [OS_8,OS_S8]) then
  598. begin
  599. list.concat(taicpu.op_none(A_CLC));
  600. list.concat(taicpu.op_reg_const(A_SBRC,src,0));
  601. list.concat(taicpu.op_none(A_SEC));
  602. end;
  603. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  604. end;
  605. OP_ROL:
  606. begin
  607. { load carry? }
  608. if not(size in [OS_8,OS_S8]) then
  609. begin
  610. list.concat(taicpu.op_none(A_CLC));
  611. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
  612. list.concat(taicpu.op_none(A_SEC));
  613. end;
  614. list.concat(taicpu.op_reg(A_ROL,dst))
  615. end;
  616. else
  617. internalerror(2011030901);
  618. end;
  619. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  620. begin
  621. for i:=2 to tcgsize2size[size] do
  622. begin
  623. case op of
  624. OP_ROR,
  625. OP_SHR:
  626. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  627. OP_ROL,
  628. OP_SHL:
  629. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
  630. OP_SAR:
  631. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  632. else
  633. internalerror(2011030902);
  634. end;
  635. end;
  636. end;
  637. list.concat(taicpu.op_reg(A_DEC,countreg));
  638. a_jmp_flags(list,F_NE,l1);
  639. // keep registers alive
  640. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  641. cg.a_label(list,l2);
  642. end;
  643. OP_AND,OP_OR,OP_XOR:
  644. begin
  645. for i:=1 to tcgsize2size[size] do
  646. begin
  647. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  648. NextSrcDst;
  649. end;
  650. end;
  651. else
  652. internalerror(2011022004);
  653. end;
  654. end;
  655. procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  656. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  657. var
  658. mask : qword;
  659. shift : byte;
  660. i,j : byte;
  661. tmpreg : tregister;
  662. tmpreg64 : tregister64;
  663. procedure NextReg;
  664. begin
  665. if i=5 then
  666. reg:=reghi
  667. else
  668. reg:=GetNextReg(reg);
  669. end;
  670. var
  671. curvalue : byte;
  672. begin
  673. optimize_op_const(size,op,a);
  674. mask:=$ff;
  675. shift:=0;
  676. case op of
  677. OP_NONE:
  678. begin
  679. { Opcode is optimized away }
  680. end;
  681. OP_MOVE:
  682. begin
  683. { Optimized, replaced with a simple load }
  684. a_load_const_reg(list,size,a,reg);
  685. end;
  686. OP_OR:
  687. begin
  688. for i:=1 to tcgsize2size[size] do
  689. begin
  690. if ((qword(a) and mask) shr shift)<>0 then
  691. list.concat(taicpu.op_reg_const(A_ORI,reg,(qword(a) and mask) shr shift));
  692. NextReg;
  693. mask:=mask shl 8;
  694. inc(shift,8);
  695. end;
  696. end;
  697. OP_AND:
  698. begin
  699. for i:=1 to tcgsize2size[size] do
  700. begin
  701. if ((qword(a) and mask) shr shift)=0 then
  702. list.concat(taicpu.op_reg_reg(A_MOV,reg,NR_R1))
  703. else
  704. list.concat(taicpu.op_reg_const(A_ANDI,reg,(qword(a) and mask) shr shift));
  705. NextReg;
  706. mask:=mask shl 8;
  707. inc(shift,8);
  708. end;
  709. end;
  710. OP_SUB:
  711. begin
  712. if ((a and mask)=1) and (tcgsize2size[size]=1) then
  713. list.concat(taicpu.op_reg(A_DEC,reg))
  714. else
  715. list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
  716. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  717. begin
  718. for i:=2 to tcgsize2size[size] do
  719. begin
  720. NextReg;
  721. mask:=mask shl 8;
  722. inc(shift,8);
  723. curvalue:=(qword(a) and mask) shr shift;
  724. { decrease pressure on upper half of registers by using SBC ...,R1 instead
  725. of SBCI ...,0 }
  726. if curvalue=0 then
  727. list.concat(taicpu.op_reg_reg(A_SBC,reg,NR_R1))
  728. else
  729. list.concat(taicpu.op_reg_const(A_SBCI,reg,curvalue));
  730. end;
  731. end;
  732. end;
  733. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  734. begin
  735. if a*tcgsize2size[size]<=8 then
  736. begin
  737. for j:=1 to a do
  738. begin
  739. case op of
  740. OP_SHR:
  741. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  742. OP_SHL:
  743. list.concat(taicpu.op_reg(A_LSL,reg));
  744. OP_SAR:
  745. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  746. OP_ROR:
  747. begin
  748. { load carry? }
  749. if not(size in [OS_8,OS_S8]) then
  750. begin
  751. list.concat(taicpu.op_none(A_CLC));
  752. list.concat(taicpu.op_reg_const(A_SBRC,reg,0));
  753. list.concat(taicpu.op_none(A_SEC));
  754. end;
  755. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  756. end;
  757. OP_ROL:
  758. begin
  759. { load carry? }
  760. if not(size in [OS_8,OS_S8]) then
  761. begin
  762. list.concat(taicpu.op_none(A_CLC));
  763. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),7));
  764. list.concat(taicpu.op_none(A_SEC));
  765. end;
  766. list.concat(taicpu.op_reg(A_ROL,reg))
  767. end;
  768. else
  769. internalerror(2011030901);
  770. end;
  771. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  772. begin
  773. for i:=2 to tcgsize2size[size] do
  774. begin
  775. case op of
  776. OP_ROR,
  777. OP_SHR:
  778. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  779. OP_ROL,
  780. OP_SHL:
  781. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(reg,reghi,i-1)));
  782. OP_SAR:
  783. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  784. else
  785. internalerror(2011030902);
  786. end;
  787. end;
  788. end;
  789. end;
  790. end
  791. else
  792. begin
  793. tmpreg:=getintregister(list,size);
  794. a_load_const_reg(list,size,a,tmpreg);
  795. a_op_reg_reg(list,op,size,tmpreg,reg);
  796. end;
  797. end;
  798. OP_ADD:
  799. begin
  800. curvalue:=a and mask;
  801. if curvalue=0 then
  802. list.concat(taicpu.op_reg_reg(A_ADD,reg,NR_R1))
  803. else if (curvalue=1) and (tcgsize2size[size]=1) then
  804. list.concat(taicpu.op_reg(A_INC,reg))
  805. else
  806. begin
  807. tmpreg:=getintregister(list,OS_8);
  808. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  809. list.concat(taicpu.op_reg_reg(A_ADD,reg,tmpreg));
  810. end;
  811. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  812. begin
  813. for i:=2 to tcgsize2size[size] do
  814. begin
  815. NextReg;
  816. mask:=mask shl 8;
  817. inc(shift,8);
  818. curvalue:=(qword(a) and mask) shr shift;
  819. { decrease pressure on upper half of registers by using ADC ...,R1 instead
  820. of ADD ...,0 }
  821. if curvalue=0 then
  822. list.concat(taicpu.op_reg_reg(A_ADC,reg,NR_R1))
  823. else
  824. begin
  825. tmpreg:=getintregister(list,OS_8);
  826. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  827. list.concat(taicpu.op_reg_reg(A_ADC,reg,tmpreg));
  828. end;
  829. end;
  830. end;
  831. end;
  832. else
  833. begin
  834. if size in [OS_64,OS_S64] then
  835. begin
  836. tmpreg64.reglo:=getintregister(list,OS_32);
  837. tmpreg64.reghi:=getintregister(list,OS_32);
  838. cg64.a_load64_const_reg(list,a,tmpreg64);
  839. cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  840. end
  841. else
  842. begin
  843. {$if 0}
  844. { code not working yet }
  845. if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  846. begin
  847. tmpreg:=reg;
  848. for i:=1 to 4 do
  849. begin
  850. list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  851. tmpreg:=GetNextReg(tmpreg);
  852. end;
  853. end
  854. else
  855. {$endif}
  856. begin
  857. tmpreg:=getintregister(list,size);
  858. a_load_const_reg(list,size,a,tmpreg);
  859. a_op_reg_reg(list,op,size,tmpreg,reg);
  860. end;
  861. end;
  862. end;
  863. end;
  864. end;
  865. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  866. var
  867. mask : qword;
  868. shift : byte;
  869. i : byte;
  870. begin
  871. mask:=$ff;
  872. shift:=0;
  873. for i:=1 to tcgsize2size[size] do
  874. begin
  875. if ((qword(a) and mask) shr shift)=0 then
  876. emit_mov(list,reg,NR_R1)
  877. else
  878. begin
  879. getcpuregister(list,NR_R26);
  880. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
  881. a_load_reg_reg(list,OS_8,OS_8,NR_R26,reg);
  882. ungetcpuregister(list,NR_R26);
  883. end;
  884. mask:=mask shl 8;
  885. inc(shift,8);
  886. reg:=GetNextReg(reg);
  887. end;
  888. end;
  889. procedure tcgavr.maybegetcpuregister(list:tasmlist;reg : tregister);
  890. begin
  891. { allocate the register only, if a cpu register is passed }
  892. if getsupreg(reg)<first_int_imreg then
  893. getcpuregister(list,reg);
  894. end;
  895. function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
  896. var
  897. tmpref : treference;
  898. l : tasmlabel;
  899. begin
  900. Result:=ref;
  901. if ref.addressmode<>AM_UNCHANGED then
  902. internalerror(2011021701);
  903. { Be sure to have a base register }
  904. if (ref.base=NR_NO) then
  905. begin
  906. { only symbol+offset? }
  907. if ref.index=NR_NO then
  908. exit;
  909. ref.base:=ref.index;
  910. ref.index:=NR_NO;
  911. end;
  912. { can we take advantage of adiw/sbiw? }
  913. if (current_settings.cputype>=cpu_avr2) and not(assigned(ref.symbol)) and (ref.offset<>0) and (ref.offset>=-63) and (ref.offset<=63) and
  914. ((tmpreg=NR_R24) or (tmpreg=NR_R26) or (tmpreg=NR_R28) or (tmpreg=NR_R30)) and (ref.base<>NR_NO) then
  915. begin
  916. maybegetcpuregister(list,tmpreg);
  917. emit_mov(list,tmpreg,ref.base);
  918. maybegetcpuregister(list,GetNextReg(tmpreg));
  919. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  920. if ref.index<>NR_NO then
  921. begin
  922. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  923. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  924. end;
  925. if ref.offset>0 then
  926. list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
  927. else
  928. list.concat(taicpu.op_reg_const(A_SBIW,tmpreg,-ref.offset));
  929. ref.offset:=0;
  930. ref.base:=tmpreg;
  931. ref.index:=NR_NO;
  932. end
  933. else if assigned(ref.symbol) or (ref.offset<>0) then
  934. begin
  935. reference_reset(tmpref,0,[]);
  936. tmpref.symbol:=ref.symbol;
  937. tmpref.offset:=ref.offset;
  938. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  939. tmpref.refaddr:=addr_lo8_gs
  940. else
  941. tmpref.refaddr:=addr_lo8;
  942. maybegetcpuregister(list,tmpreg);
  943. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  944. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  945. tmpref.refaddr:=addr_hi8_gs
  946. else
  947. tmpref.refaddr:=addr_hi8;
  948. maybegetcpuregister(list,GetNextReg(tmpreg));
  949. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  950. if (ref.base<>NR_NO) then
  951. begin
  952. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  953. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  954. end;
  955. if (ref.index<>NR_NO) then
  956. begin
  957. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  958. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  959. end;
  960. ref.symbol:=nil;
  961. ref.offset:=0;
  962. ref.base:=tmpreg;
  963. ref.index:=NR_NO;
  964. end
  965. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  966. begin
  967. maybegetcpuregister(list,tmpreg);
  968. emit_mov(list,tmpreg,ref.base);
  969. maybegetcpuregister(list,GetNextReg(tmpreg));
  970. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  971. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  972. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  973. ref.base:=tmpreg;
  974. ref.index:=NR_NO;
  975. end
  976. else if (ref.base<>NR_NO) then
  977. begin
  978. maybegetcpuregister(list,tmpreg);
  979. emit_mov(list,tmpreg,ref.base);
  980. maybegetcpuregister(list,GetNextReg(tmpreg));
  981. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  982. ref.base:=tmpreg;
  983. ref.index:=NR_NO;
  984. end
  985. else if (ref.index<>NR_NO) then
  986. begin
  987. maybegetcpuregister(list,tmpreg);
  988. emit_mov(list,tmpreg,ref.index);
  989. maybegetcpuregister(list,GetNextReg(tmpreg));
  990. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
  991. ref.base:=tmpreg;
  992. ref.index:=NR_NO;
  993. end;
  994. Result:=ref;
  995. end;
  996. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  997. var
  998. href : treference;
  999. conv_done: boolean;
  1000. tmpreg : tregister;
  1001. i : integer;
  1002. QuickRef : Boolean;
  1003. begin
  1004. QuickRef:=false;
  1005. href:=Ref;
  1006. { ensure, href.base contains a valid register if there is any register used }
  1007. if href.base=NR_NO then
  1008. begin
  1009. href.base:=href.index;
  1010. href.index:=NR_NO;
  1011. end;
  1012. { try to use std/sts }
  1013. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1014. begin
  1015. if not((href.addressmode=AM_UNCHANGED) and
  1016. (href.symbol=nil) and
  1017. (href.Index=NR_NO) and
  1018. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1019. href:=normalize_ref(list,href,NR_R30)
  1020. else
  1021. begin
  1022. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1023. begin
  1024. maybegetcpuregister(list,NR_R30);
  1025. emit_mov(list,NR_R30,href.base);
  1026. maybegetcpuregister(list,NR_R31);
  1027. emit_mov(list,NR_R31,GetNextReg(href.base));
  1028. href.base:=NR_R30;
  1029. end;
  1030. QuickRef:=true;
  1031. end;
  1032. end
  1033. else
  1034. QuickRef:=true;
  1035. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1036. internalerror(2011021307);
  1037. conv_done:=false;
  1038. if tosize<>fromsize then
  1039. begin
  1040. conv_done:=true;
  1041. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1042. fromsize:=tosize;
  1043. case fromsize of
  1044. OS_8:
  1045. begin
  1046. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1047. href.addressmode:=AM_POSTINCREMENT;
  1048. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1049. for i:=2 to tcgsize2size[tosize] do
  1050. begin
  1051. if QuickRef then
  1052. inc(href.offset);
  1053. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1054. href.addressmode:=AM_POSTINCREMENT
  1055. else
  1056. href.addressmode:=AM_UNCHANGED;
  1057. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1058. end;
  1059. end;
  1060. OS_S8:
  1061. begin
  1062. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1063. href.addressmode:=AM_POSTINCREMENT;
  1064. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1065. if tcgsize2size[tosize]>1 then
  1066. begin
  1067. tmpreg:=getintregister(list,OS_8);
  1068. emit_mov(list,tmpreg,NR_R1);
  1069. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1070. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1071. for i:=2 to tcgsize2size[tosize] do
  1072. begin
  1073. if QuickRef then
  1074. inc(href.offset);
  1075. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1076. href.addressmode:=AM_POSTINCREMENT
  1077. else
  1078. href.addressmode:=AM_UNCHANGED;
  1079. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1080. end;
  1081. end;
  1082. end;
  1083. OS_16:
  1084. begin
  1085. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1086. href.addressmode:=AM_POSTINCREMENT;
  1087. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1088. if QuickRef then
  1089. inc(href.offset)
  1090. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1091. href.addressmode:=AM_POSTINCREMENT
  1092. else
  1093. href.addressmode:=AM_UNCHANGED;
  1094. reg:=GetNextReg(reg);
  1095. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1096. for i:=3 to tcgsize2size[tosize] do
  1097. begin
  1098. if QuickRef then
  1099. inc(href.offset);
  1100. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1101. href.addressmode:=AM_POSTINCREMENT
  1102. else
  1103. href.addressmode:=AM_UNCHANGED;
  1104. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1105. end;
  1106. end;
  1107. OS_S16:
  1108. begin
  1109. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1110. href.addressmode:=AM_POSTINCREMENT;
  1111. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1112. if QuickRef then
  1113. inc(href.offset)
  1114. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1115. href.addressmode:=AM_POSTINCREMENT
  1116. else
  1117. href.addressmode:=AM_UNCHANGED;
  1118. reg:=GetNextReg(reg);
  1119. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1120. if tcgsize2size[tosize]>2 then
  1121. begin
  1122. tmpreg:=getintregister(list,OS_8);
  1123. emit_mov(list,tmpreg,NR_R1);
  1124. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1125. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1126. for i:=3 to tcgsize2size[tosize] do
  1127. begin
  1128. if QuickRef then
  1129. inc(href.offset);
  1130. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1131. href.addressmode:=AM_POSTINCREMENT
  1132. else
  1133. href.addressmode:=AM_UNCHANGED;
  1134. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1135. end;
  1136. end;
  1137. end;
  1138. else
  1139. conv_done:=false;
  1140. end;
  1141. end;
  1142. if not conv_done then
  1143. begin
  1144. for i:=1 to tcgsize2size[fromsize] do
  1145. begin
  1146. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1147. href.addressmode:=AM_POSTINCREMENT
  1148. else
  1149. href.addressmode:=AM_UNCHANGED;
  1150. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1151. if QuickRef then
  1152. inc(href.offset);
  1153. reg:=GetNextReg(reg);
  1154. end;
  1155. end;
  1156. if not(QuickRef) then
  1157. begin
  1158. ungetcpuregister(list,href.base);
  1159. ungetcpuregister(list,GetNextReg(href.base));
  1160. end;
  1161. end;
  1162. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1163. const Ref : treference;reg : tregister);
  1164. var
  1165. href : treference;
  1166. conv_done: boolean;
  1167. tmpreg : tregister;
  1168. i : integer;
  1169. QuickRef : boolean;
  1170. begin
  1171. QuickRef:=false;
  1172. href:=Ref;
  1173. { ensure, href.base contains a valid register if there is any register used }
  1174. if href.base=NR_NO then
  1175. begin
  1176. href.base:=href.index;
  1177. href.index:=NR_NO;
  1178. end;
  1179. { try to use ldd/lds }
  1180. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1181. begin
  1182. if not((href.addressmode=AM_UNCHANGED) and
  1183. (href.symbol=nil) and
  1184. (href.Index=NR_NO) and
  1185. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1186. href:=normalize_ref(list,href,NR_R30)
  1187. else
  1188. begin
  1189. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1190. begin
  1191. maybegetcpuregister(list,NR_R30);
  1192. emit_mov(list,NR_R30,href.base);
  1193. maybegetcpuregister(list,NR_R31);
  1194. emit_mov(list,NR_R31,GetNextReg(href.base));
  1195. href.base:=NR_R30;
  1196. end;
  1197. QuickRef:=true;
  1198. end;
  1199. end
  1200. else
  1201. QuickRef:=true;
  1202. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1203. internalerror(2011021307);
  1204. conv_done:=false;
  1205. if tosize<>fromsize then
  1206. begin
  1207. conv_done:=true;
  1208. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1209. fromsize:=tosize;
  1210. case fromsize of
  1211. OS_8:
  1212. begin
  1213. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1214. for i:=2 to tcgsize2size[tosize] do
  1215. begin
  1216. reg:=GetNextReg(reg);
  1217. emit_mov(list,reg,NR_R1);
  1218. end;
  1219. end;
  1220. OS_S8:
  1221. begin
  1222. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1223. tmpreg:=reg;
  1224. if tcgsize2size[tosize]>1 then
  1225. begin
  1226. reg:=GetNextReg(reg);
  1227. emit_mov(list,reg,NR_R1);
  1228. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1229. list.concat(taicpu.op_reg(A_COM,reg));
  1230. tmpreg:=reg;
  1231. for i:=3 to tcgsize2size[tosize] do
  1232. begin
  1233. reg:=GetNextReg(reg);
  1234. emit_mov(list,reg,tmpreg);
  1235. end;
  1236. end;
  1237. end;
  1238. OS_16:
  1239. begin
  1240. if not(QuickRef) then
  1241. href.addressmode:=AM_POSTINCREMENT;
  1242. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1243. if QuickRef then
  1244. inc(href.offset);
  1245. href.addressmode:=AM_UNCHANGED;
  1246. reg:=GetNextReg(reg);
  1247. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1248. for i:=3 to tcgsize2size[tosize] do
  1249. begin
  1250. reg:=GetNextReg(reg);
  1251. emit_mov(list,reg,NR_R1);
  1252. end;
  1253. end;
  1254. OS_S16:
  1255. begin
  1256. if not(QuickRef) then
  1257. href.addressmode:=AM_POSTINCREMENT;
  1258. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1259. if QuickRef then
  1260. inc(href.offset);
  1261. href.addressmode:=AM_UNCHANGED;
  1262. reg:=GetNextReg(reg);
  1263. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1264. tmpreg:=reg;
  1265. reg:=GetNextReg(reg);
  1266. emit_mov(list,reg,NR_R1);
  1267. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1268. list.concat(taicpu.op_reg(A_COM,reg));
  1269. tmpreg:=reg;
  1270. for i:=4 to tcgsize2size[tosize] do
  1271. begin
  1272. reg:=GetNextReg(reg);
  1273. emit_mov(list,reg,tmpreg);
  1274. end;
  1275. end;
  1276. else
  1277. conv_done:=false;
  1278. end;
  1279. end;
  1280. if not conv_done then
  1281. begin
  1282. for i:=1 to tcgsize2size[fromsize] do
  1283. begin
  1284. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1285. href.addressmode:=AM_POSTINCREMENT
  1286. else
  1287. href.addressmode:=AM_UNCHANGED;
  1288. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1289. if QuickRef then
  1290. inc(href.offset);
  1291. reg:=GetNextReg(reg);
  1292. end;
  1293. end;
  1294. if not(QuickRef) then
  1295. begin
  1296. ungetcpuregister(list,href.base);
  1297. ungetcpuregister(list,GetNextReg(href.base));
  1298. end;
  1299. end;
  1300. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1301. var
  1302. conv_done: boolean;
  1303. tmpreg : tregister;
  1304. i : integer;
  1305. begin
  1306. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1307. internalerror(2011021310);
  1308. conv_done:=false;
  1309. if tosize<>fromsize then
  1310. begin
  1311. conv_done:=true;
  1312. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1313. fromsize:=tosize;
  1314. case fromsize of
  1315. OS_8:
  1316. begin
  1317. emit_mov(list,reg2,reg1);
  1318. for i:=2 to tcgsize2size[tosize] do
  1319. begin
  1320. reg2:=GetNextReg(reg2);
  1321. emit_mov(list,reg2,NR_R1);
  1322. end;
  1323. end;
  1324. OS_S8:
  1325. begin
  1326. emit_mov(list,reg2,reg1);
  1327. if tcgsize2size[tosize]>1 then
  1328. begin
  1329. reg2:=GetNextReg(reg2);
  1330. emit_mov(list,reg2,NR_R1);
  1331. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1332. list.concat(taicpu.op_reg(A_COM,reg2));
  1333. tmpreg:=reg2;
  1334. for i:=3 to tcgsize2size[tosize] do
  1335. begin
  1336. reg2:=GetNextReg(reg2);
  1337. emit_mov(list,reg2,tmpreg);
  1338. end;
  1339. end;
  1340. end;
  1341. OS_16:
  1342. begin
  1343. emit_mov(list,reg2,reg1);
  1344. reg1:=GetNextReg(reg1);
  1345. reg2:=GetNextReg(reg2);
  1346. emit_mov(list,reg2,reg1);
  1347. for i:=3 to tcgsize2size[tosize] do
  1348. begin
  1349. reg2:=GetNextReg(reg2);
  1350. emit_mov(list,reg2,NR_R1);
  1351. end;
  1352. end;
  1353. OS_S16:
  1354. begin
  1355. emit_mov(list,reg2,reg1);
  1356. reg1:=GetNextReg(reg1);
  1357. reg2:=GetNextReg(reg2);
  1358. emit_mov(list,reg2,reg1);
  1359. if tcgsize2size[tosize]>2 then
  1360. begin
  1361. reg2:=GetNextReg(reg2);
  1362. emit_mov(list,reg2,NR_R1);
  1363. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1364. list.concat(taicpu.op_reg(A_COM,reg2));
  1365. tmpreg:=reg2;
  1366. for i:=4 to tcgsize2size[tosize] do
  1367. begin
  1368. reg2:=GetNextReg(reg2);
  1369. emit_mov(list,reg2,tmpreg);
  1370. end;
  1371. end;
  1372. end;
  1373. else
  1374. conv_done:=false;
  1375. end;
  1376. end;
  1377. if not conv_done and (reg1<>reg2) then
  1378. begin
  1379. for i:=1 to tcgsize2size[fromsize] do
  1380. begin
  1381. emit_mov(list,reg2,reg1);
  1382. reg1:=GetNextReg(reg1);
  1383. reg2:=GetNextReg(reg2);
  1384. end;
  1385. end;
  1386. end;
  1387. procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1388. begin
  1389. internalerror(2012010702);
  1390. end;
  1391. procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1392. begin
  1393. internalerror(2012010703);
  1394. end;
  1395. procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1396. begin
  1397. internalerror(2012010704);
  1398. end;
  1399. { comparison operations }
  1400. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1401. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1402. var
  1403. swapped : boolean;
  1404. tmpreg : tregister;
  1405. i : byte;
  1406. begin
  1407. if a=0 then
  1408. begin
  1409. swapped:=false;
  1410. { swap parameters? }
  1411. case cmp_op of
  1412. OC_GT:
  1413. begin
  1414. swapped:=true;
  1415. cmp_op:=OC_LT;
  1416. end;
  1417. OC_LTE:
  1418. begin
  1419. swapped:=true;
  1420. cmp_op:=OC_GTE;
  1421. end;
  1422. OC_BE:
  1423. begin
  1424. swapped:=true;
  1425. cmp_op:=OC_AE;
  1426. end;
  1427. OC_A:
  1428. begin
  1429. swapped:=true;
  1430. cmp_op:=OC_B;
  1431. end;
  1432. end;
  1433. if swapped then
  1434. list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
  1435. else
  1436. list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
  1437. for i:=2 to tcgsize2size[size] do
  1438. begin
  1439. reg:=GetNextReg(reg);
  1440. if swapped then
  1441. list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
  1442. else
  1443. list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
  1444. end;
  1445. a_jmp_cond(list,cmp_op,l);
  1446. end
  1447. else
  1448. inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1449. end;
  1450. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1451. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1452. var
  1453. swapped : boolean;
  1454. tmpreg : tregister;
  1455. i : byte;
  1456. begin
  1457. swapped:=false;
  1458. { swap parameters? }
  1459. case cmp_op of
  1460. OC_GT:
  1461. begin
  1462. swapped:=true;
  1463. cmp_op:=OC_LT;
  1464. end;
  1465. OC_LTE:
  1466. begin
  1467. swapped:=true;
  1468. cmp_op:=OC_GTE;
  1469. end;
  1470. OC_BE:
  1471. begin
  1472. swapped:=true;
  1473. cmp_op:=OC_AE;
  1474. end;
  1475. OC_A:
  1476. begin
  1477. swapped:=true;
  1478. cmp_op:=OC_B;
  1479. end;
  1480. end;
  1481. if swapped then
  1482. begin
  1483. tmpreg:=reg1;
  1484. reg1:=reg2;
  1485. reg2:=tmpreg;
  1486. end;
  1487. list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1488. for i:=2 to tcgsize2size[size] do
  1489. begin
  1490. reg1:=GetNextReg(reg1);
  1491. reg2:=GetNextReg(reg2);
  1492. list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1493. end;
  1494. a_jmp_cond(list,cmp_op,l);
  1495. end;
  1496. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  1497. var
  1498. ai : taicpu;
  1499. begin
  1500. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1501. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION))
  1502. else
  1503. ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1504. ai.is_jmp:=true;
  1505. list.concat(ai);
  1506. end;
  1507. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  1508. var
  1509. ai : taicpu;
  1510. begin
  1511. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1512. ai:=taicpu.op_sym(A_JMP,l)
  1513. else
  1514. ai:=taicpu.op_sym(A_RJMP,l);
  1515. ai.is_jmp:=true;
  1516. list.concat(ai);
  1517. end;
  1518. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1519. var
  1520. ai : taicpu;
  1521. begin
  1522. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  1523. ai.is_jmp:=true;
  1524. list.concat(ai);
  1525. end;
  1526. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1527. var
  1528. l : TAsmLabel;
  1529. tmpflags : TResFlags;
  1530. begin
  1531. current_asmdata.getjumplabel(l);
  1532. {
  1533. if flags_to_cond(f) then
  1534. begin
  1535. tmpflags:=f;
  1536. inverse_flags(tmpflags);
  1537. emit_mov(reg,NR_R1);
  1538. a_jmp_flags(list,tmpflags,l);
  1539. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1540. end
  1541. else
  1542. }
  1543. begin
  1544. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1545. a_jmp_flags(list,f,l);
  1546. emit_mov(list,reg,NR_R1);
  1547. end;
  1548. cg.a_label(list,l);
  1549. end;
  1550. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  1551. var
  1552. i : integer;
  1553. begin
  1554. case value of
  1555. 0:
  1556. ;
  1557. {-14..-1:
  1558. begin
  1559. if ((-value) mod 2)<>0 then
  1560. list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1561. for i:=1 to (-value) div 2 do
  1562. list.concat(taicpu.op_const(A_RCALL,0));
  1563. end;
  1564. 1..7:
  1565. begin
  1566. for i:=1 to value do
  1567. list.concat(taicpu.op_reg(A_POP,NR_R0));
  1568. end;}
  1569. else
  1570. begin
  1571. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1572. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1573. // get SREG
  1574. list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1575. // block interrupts
  1576. list.concat(taicpu.op_none(A_CLI));
  1577. // write high SP
  1578. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1579. // release interrupts
  1580. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1581. // write low SP
  1582. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1583. end;
  1584. end;
  1585. end;
  1586. function tcgavr.GetLoad(const ref: treference) : tasmop;
  1587. begin
  1588. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1589. result:=A_LDS
  1590. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1591. result:=A_LDD
  1592. else
  1593. result:=A_LD;
  1594. end;
  1595. function tcgavr.GetStore(const ref: treference) : tasmop;
  1596. begin
  1597. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1598. result:=A_STS
  1599. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1600. result:=A_STD
  1601. else
  1602. result:=A_ST;
  1603. end;
  1604. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1605. var
  1606. regs : tcpuregisterset;
  1607. reg : tsuperregister;
  1608. begin
  1609. if po_interrupt in current_procinfo.procdef.procoptions then
  1610. begin
  1611. { check if the framepointer is actually used, this is done here because
  1612. we have to know the size of the locals (must be 0), avr does not know
  1613. an sp based stack }
  1614. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1615. (localsize=0) then
  1616. current_procinfo.framepointer:=NR_NO;
  1617. { save int registers,
  1618. but only if the procedure returns }
  1619. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1620. regs:=rg[R_INTREGISTER].used_in_proc
  1621. else
  1622. regs:=[];
  1623. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1624. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1625. an outer stackframe }
  1626. if current_procinfo.framepointer<>NR_NO then
  1627. regs:=regs+[RS_R28,RS_R29];
  1628. regs:=regs+[RS_R0];
  1629. for reg:=RS_R31 downto RS_R0 do
  1630. if reg in regs then
  1631. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1632. { Save SREG }
  1633. list.concat(taicpu.op_reg_const(A_IN, NR_R0, $3F));
  1634. list.concat(taicpu.op_reg(A_PUSH, NR_R0));
  1635. if current_procinfo.framepointer<>NR_NO then
  1636. begin
  1637. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1638. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1639. a_adjust_sp(list,-localsize);
  1640. end;
  1641. end
  1642. else if not(nostackframe) then
  1643. begin
  1644. { check if the framepointer is actually used, this is done here because
  1645. we have to know the size of the locals (must be 0), avr does not know
  1646. an sp based stack }
  1647. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1648. (localsize=0) then
  1649. current_procinfo.framepointer:=NR_NO;
  1650. { save int registers,
  1651. but only if the procedure returns }
  1652. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1653. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)
  1654. else
  1655. regs:=[];
  1656. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1657. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1658. an outer stackframe }
  1659. if current_procinfo.framepointer<>NR_NO then
  1660. regs:=regs+[RS_R28,RS_R29];
  1661. for reg:=RS_R31 downto RS_R0 do
  1662. if reg in regs then
  1663. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1664. if current_procinfo.framepointer<>NR_NO then
  1665. begin
  1666. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1667. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1668. a_adjust_sp(list,-localsize);
  1669. end;
  1670. end;
  1671. end;
  1672. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1673. var
  1674. regs : tcpuregisterset;
  1675. reg : TSuperRegister;
  1676. LocalSize : longint;
  1677. begin
  1678. { every byte counts for avr, so if a subroutine is marked as non-returning, we do
  1679. not generate any exit code, so we really trust the noreturn directive
  1680. }
  1681. if po_noreturn in current_procinfo.procdef.procoptions then
  1682. exit;
  1683. if po_interrupt in current_procinfo.procdef.procoptions then
  1684. begin
  1685. regs:=rg[R_INTREGISTER].used_in_proc;
  1686. if current_procinfo.framepointer<>NR_NO then
  1687. begin
  1688. regs:=regs+[RS_R28,RS_R29];
  1689. LocalSize:=current_procinfo.calc_stackframe_size;
  1690. a_adjust_sp(list,LocalSize);
  1691. end;
  1692. { Reload SREG }
  1693. regs:=regs+[RS_R0];
  1694. list.concat(taicpu.op_reg(A_POP, NR_R0));
  1695. list.concat(taicpu.op_const_reg(A_OUT, $3F, NR_R0));
  1696. for reg:=RS_R0 to RS_R31 do
  1697. if reg in regs then
  1698. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1699. list.concat(taicpu.op_none(A_RETI));
  1700. end
  1701. else if not(nostackframe) then
  1702. begin
  1703. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  1704. if current_procinfo.framepointer<>NR_NO then
  1705. begin
  1706. regs:=regs+[RS_R28,RS_R29];
  1707. LocalSize:=current_procinfo.calc_stackframe_size;
  1708. a_adjust_sp(list,LocalSize);
  1709. end;
  1710. for reg:=RS_R0 to RS_R31 do
  1711. if reg in regs then
  1712. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1713. list.concat(taicpu.op_none(A_RET));
  1714. end
  1715. else
  1716. list.concat(taicpu.op_none(A_RET));
  1717. end;
  1718. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1719. var
  1720. tmpref : treference;
  1721. begin
  1722. if ref.addressmode<>AM_UNCHANGED then
  1723. internalerror(2011021701);
  1724. if assigned(ref.symbol) or (ref.offset<>0) then
  1725. begin
  1726. reference_reset(tmpref,0,[]);
  1727. tmpref.symbol:=ref.symbol;
  1728. tmpref.offset:=ref.offset;
  1729. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1730. tmpref.refaddr:=addr_lo8_gs
  1731. else
  1732. tmpref.refaddr:=addr_lo8;
  1733. list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  1734. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1735. tmpref.refaddr:=addr_hi8_gs
  1736. else
  1737. tmpref.refaddr:=addr_hi8;
  1738. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  1739. if (ref.base<>NR_NO) then
  1740. begin
  1741. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  1742. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  1743. end;
  1744. if (ref.index<>NR_NO) then
  1745. begin
  1746. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1747. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1748. end;
  1749. end
  1750. else if (ref.base<>NR_NO)then
  1751. begin
  1752. emit_mov(list,r,ref.base);
  1753. emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  1754. if (ref.index<>NR_NO) then
  1755. begin
  1756. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1757. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1758. end;
  1759. end
  1760. else if (ref.index<>NR_NO) then
  1761. begin
  1762. emit_mov(list,r,ref.index);
  1763. emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  1764. end;
  1765. end;
  1766. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  1767. begin
  1768. internalerror(2011021320);
  1769. end;
  1770. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  1771. var
  1772. paraloc1,paraloc2,paraloc3 : TCGPara;
  1773. pd : tprocdef;
  1774. begin
  1775. pd:=search_system_proc('MOVE');
  1776. paraloc1.init;
  1777. paraloc2.init;
  1778. paraloc3.init;
  1779. paramanager.getintparaloc(list,pd,1,paraloc1);
  1780. paramanager.getintparaloc(list,pd,2,paraloc2);
  1781. paramanager.getintparaloc(list,pd,3,paraloc3);
  1782. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  1783. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  1784. a_loadaddr_ref_cgpara(list,source,paraloc1);
  1785. paramanager.freecgpara(list,paraloc3);
  1786. paramanager.freecgpara(list,paraloc2);
  1787. paramanager.freecgpara(list,paraloc1);
  1788. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1789. a_call_name_static(list,'FPC_MOVE');
  1790. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1791. paraloc3.done;
  1792. paraloc2.done;
  1793. paraloc1.done;
  1794. end;
  1795. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1796. var
  1797. countreg,tmpreg : tregister;
  1798. srcref,dstref : treference;
  1799. copysize,countregsize : tcgsize;
  1800. l : TAsmLabel;
  1801. i : longint;
  1802. SrcQuickRef, DestQuickRef : Boolean;
  1803. begin
  1804. if len>16 then
  1805. begin
  1806. current_asmdata.getjumplabel(l);
  1807. reference_reset(srcref,source.alignment,source.volatility);
  1808. reference_reset(dstref,dest.alignment,source.volatility);
  1809. srcref.base:=NR_R30;
  1810. srcref.addressmode:=AM_POSTINCREMENT;
  1811. dstref.base:=NR_R26;
  1812. dstref.addressmode:=AM_POSTINCREMENT;
  1813. copysize:=OS_8;
  1814. if len<256 then
  1815. countregsize:=OS_8
  1816. else if len<65536 then
  1817. countregsize:=OS_16
  1818. else
  1819. internalerror(2011022007);
  1820. countreg:=getintregister(list,countregsize);
  1821. a_load_const_reg(list,countregsize,len,countreg);
  1822. a_loadaddr_ref_reg(list,source,NR_R30);
  1823. { only base or index register in dest? }
  1824. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1825. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1826. begin
  1827. if dest.base<>NR_NO then
  1828. tmpreg:=dest.base
  1829. else if dest.index<>NR_NO then
  1830. tmpreg:=dest.index
  1831. else
  1832. internalerror(2016112001);
  1833. end
  1834. else
  1835. begin
  1836. tmpreg:=getaddressregister(list);
  1837. a_loadaddr_ref_reg(list,dest,tmpreg);
  1838. end;
  1839. { X is used for spilling code so we can load it
  1840. only by a push/pop sequence, this can be
  1841. optimized later on by the peephole optimizer
  1842. }
  1843. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1844. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1845. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1846. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1847. cg.a_label(list,l);
  1848. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1849. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1850. list.concat(taicpu.op_reg(A_DEC,countreg));
  1851. a_jmp_flags(list,F_NE,l);
  1852. // keep registers alive
  1853. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  1854. end
  1855. else
  1856. begin
  1857. SrcQuickRef:=false;
  1858. DestQuickRef:=false;
  1859. if not((source.addressmode=AM_UNCHANGED) and
  1860. (source.symbol=nil) and
  1861. ((source.base=NR_R28) or
  1862. (source.base=NR_R30)) and
  1863. (source.Index=NR_NO) and
  1864. (source.Offset in [0..64-len])) and
  1865. not((source.Base=NR_NO) and (source.Index=NR_NO)) then
  1866. srcref:=normalize_ref(list,source,NR_R30)
  1867. else
  1868. begin
  1869. SrcQuickRef:=true;
  1870. srcref:=source;
  1871. end;
  1872. if not((dest.addressmode=AM_UNCHANGED) and
  1873. (dest.symbol=nil) and
  1874. ((dest.base=NR_R28) or
  1875. (dest.base=NR_R30)) and
  1876. (dest.Index=NR_No) and
  1877. (dest.Offset in [0..64-len])) and
  1878. not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
  1879. begin
  1880. if not(SrcQuickRef) then
  1881. begin
  1882. { only base or index register in dest? }
  1883. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1884. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1885. begin
  1886. if dest.base<>NR_NO then
  1887. tmpreg:=dest.base
  1888. else if dest.index<>NR_NO then
  1889. tmpreg:=dest.index
  1890. else
  1891. internalerror(2016112002);
  1892. end
  1893. else
  1894. tmpreg:=getaddressregister(list);
  1895. dstref:=normalize_ref(list,dest,tmpreg);
  1896. { X is used for spilling code so we can load it
  1897. only by a push/pop sequence, this can be
  1898. optimized later on by the peephole optimizer
  1899. }
  1900. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1901. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1902. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1903. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1904. dstref.base:=NR_R26;
  1905. end
  1906. else
  1907. dstref:=normalize_ref(list,dest,NR_R30);
  1908. end
  1909. else
  1910. begin
  1911. DestQuickRef:=true;
  1912. dstref:=dest;
  1913. end;
  1914. for i:=1 to len do
  1915. begin
  1916. if not(SrcQuickRef) and (i<len) then
  1917. srcref.addressmode:=AM_POSTINCREMENT
  1918. else
  1919. srcref.addressmode:=AM_UNCHANGED;
  1920. if not(DestQuickRef) and (i<len) then
  1921. dstref.addressmode:=AM_POSTINCREMENT
  1922. else
  1923. dstref.addressmode:=AM_UNCHANGED;
  1924. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1925. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1926. if SrcQuickRef then
  1927. inc(srcref.offset);
  1928. if DestQuickRef then
  1929. inc(dstref.offset);
  1930. end;
  1931. if not(SrcQuickRef) then
  1932. begin
  1933. ungetcpuregister(list,srcref.base);
  1934. ungetcpuregister(list,GetNextReg(srcref.base));
  1935. end;
  1936. end;
  1937. end;
  1938. procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  1939. var
  1940. hl : tasmlabel;
  1941. ai : taicpu;
  1942. cond : TAsmCond;
  1943. begin
  1944. if not(cs_check_overflow in current_settings.localswitches) then
  1945. exit;
  1946. current_asmdata.getjumplabel(hl);
  1947. if not ((def.typ=pointerdef) or
  1948. ((def.typ=orddef) and
  1949. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  1950. pasbool8,pasbool16,pasbool32,pasbool64]))) then
  1951. cond:=C_VC
  1952. else
  1953. cond:=C_CC;
  1954. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1955. ai.SetCondition(cond);
  1956. ai.is_jmp:=true;
  1957. list.concat(ai);
  1958. a_call_name(list,'FPC_OVERFLOW',false);
  1959. a_label(list,hl);
  1960. end;
  1961. procedure tcgavr.g_save_registers(list: TAsmList);
  1962. begin
  1963. { this is done by the entry code }
  1964. end;
  1965. procedure tcgavr.g_restore_registers(list: TAsmList);
  1966. begin
  1967. { this is done by the exit code }
  1968. end;
  1969. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1970. var
  1971. ai1,ai2 : taicpu;
  1972. hl : TAsmLabel;
  1973. begin
  1974. ai1:=Taicpu.Op_sym(A_BRxx,l);
  1975. ai1.is_jmp:=true;
  1976. hl:=nil;
  1977. case cond of
  1978. OC_EQ:
  1979. ai1.SetCondition(C_EQ);
  1980. OC_GT:
  1981. begin
  1982. { emulate GT }
  1983. current_asmdata.getjumplabel(hl);
  1984. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  1985. ai2.SetCondition(C_EQ);
  1986. ai2.is_jmp:=true;
  1987. list.concat(ai2);
  1988. ai1.SetCondition(C_GE);
  1989. end;
  1990. OC_LT:
  1991. ai1.SetCondition(C_LT);
  1992. OC_GTE:
  1993. ai1.SetCondition(C_GE);
  1994. OC_LTE:
  1995. begin
  1996. { emulate LTE }
  1997. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  1998. ai2.SetCondition(C_EQ);
  1999. ai2.is_jmp:=true;
  2000. list.concat(ai2);
  2001. ai1.SetCondition(C_LT);
  2002. end;
  2003. OC_NE:
  2004. ai1.SetCondition(C_NE);
  2005. OC_BE:
  2006. begin
  2007. { emulate BE }
  2008. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2009. ai2.SetCondition(C_EQ);
  2010. ai2.is_jmp:=true;
  2011. list.concat(ai2);
  2012. ai1.SetCondition(C_LO);
  2013. end;
  2014. OC_B:
  2015. ai1.SetCondition(C_LO);
  2016. OC_AE:
  2017. ai1.SetCondition(C_SH);
  2018. OC_A:
  2019. begin
  2020. { emulate A (unsigned GT) }
  2021. current_asmdata.getjumplabel(hl);
  2022. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2023. ai2.SetCondition(C_EQ);
  2024. ai2.is_jmp:=true;
  2025. list.concat(ai2);
  2026. ai1.SetCondition(C_SH);
  2027. end;
  2028. else
  2029. internalerror(2011082501);
  2030. end;
  2031. list.concat(ai1);
  2032. if assigned(hl) then
  2033. a_label(list,hl);
  2034. end;
  2035. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2036. var
  2037. instr: taicpu;
  2038. begin
  2039. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  2040. list.Concat(instr);
  2041. { Notify the register allocator that we have written a move instruction so
  2042. it can try to eliminate it. }
  2043. add_move_instruction(instr);
  2044. end;
  2045. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2046. begin
  2047. if not(size in [OS_S64,OS_64]) then
  2048. internalerror(2012102402);
  2049. tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2050. end;
  2051. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2052. begin
  2053. tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2054. end;
  2055. procedure create_codegen;
  2056. begin
  2057. cg:=tcgavr.create;
  2058. cg64:=tcg64favr.create;
  2059. end;
  2060. end.