cgcpu.pas 84 KB

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