2
0

cgcpu.pas 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880
  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_const_reg_reg(list : TAsmList;op : TOpCg;size : tcgsize; a : tcgint;src,dst : tregister); override;
  47. procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
  48. procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
  49. { move instructions }
  50. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
  51. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  52. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  53. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  54. { fpu move instructions }
  55. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  56. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  57. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  58. { comparison operations }
  59. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  60. l : tasmlabel);override;
  61. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  62. procedure a_jmp_name(list : TAsmList;const s : string); override;
  63. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  64. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  65. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  66. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  67. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  68. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  69. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
  70. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  71. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  72. procedure g_overflowCheck_loc(List: TAsmList; const Loc: TLocation; def: TDef; ovloc: tlocation); override;
  73. procedure g_save_registers(list : TAsmList);override;
  74. procedure g_restore_registers(list : TAsmList);override;
  75. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  76. procedure fixref(list : TAsmList;var ref : treference);
  77. function normalize_ref(list : TAsmList;ref : treference;
  78. tmpreg : tregister) : treference;
  79. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  80. procedure a_adjust_sp(list: TAsmList; value: longint);
  81. function GetLoad(const ref : treference) : tasmop;
  82. function GetStore(const ref: treference): tasmop;
  83. procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean; var ovloc: tlocation);
  84. private
  85. procedure a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, srchi, dst, dsthi: tregister);
  86. protected
  87. procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  88. procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
  89. procedure maybegetcpuregister(list : tasmlist; reg : tregister);
  90. end;
  91. tcg64favr = class(tcg64f32)
  92. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  93. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  94. procedure a_op64_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; value: int64;src,dst: tregister64);override;
  95. end;
  96. procedure create_codegen;
  97. const
  98. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,
  99. A_NONE,A_MULS,A_MUL,A_NEG,A_COM,A_OR,
  100. A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_ROL,A_ROR);
  101. implementation
  102. uses
  103. globals,verbose,systems,cutils,
  104. fmodule,
  105. symconst,symsym,symtable,
  106. tgobj,rgobj,
  107. procinfo,cpupi,
  108. paramgr;
  109. procedure tcgavr.init_register_allocators;
  110. begin
  111. inherited init_register_allocators;
  112. if CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype] then
  113. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  114. [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25],first_int_imreg,[])
  115. else
  116. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  117. [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,
  118. RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  119. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17],first_int_imreg,[]);
  120. end;
  121. procedure tcgavr.done_register_allocators;
  122. begin
  123. rg[R_INTREGISTER].free;
  124. // rg[R_ADDRESSREGISTER].free;
  125. inherited done_register_allocators;
  126. end;
  127. function tcgavr.getaddressregister(list: TAsmList): TRegister;
  128. begin
  129. Result:=getintregister(list,OS_ADDR);
  130. end;
  131. function tcgavr.GetHigh(const r : TRegister) : TRegister;
  132. begin
  133. result:=GetNextReg(r);
  134. end;
  135. function tcgavr.GetOffsetReg(const r: TRegister;ofs : shortint): TRegister;
  136. begin
  137. result:=TRegister(longint(r)+ofs);
  138. end;
  139. function tcgavr.GetOffsetReg64(const r,rhi: TRegister;ofs : shortint): TRegister;
  140. begin
  141. if ofs>3 then
  142. result:=TRegister(longint(rhi)+ofs-4)
  143. else
  144. result:=TRegister(longint(r)+ofs);
  145. end;
  146. procedure tcgavr.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  147. procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  148. var
  149. ref : treference;
  150. begin
  151. paramanager.allocparaloc(list,paraloc);
  152. case paraloc^.loc of
  153. LOC_REGISTER,LOC_CREGISTER:
  154. a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  155. LOC_REFERENCE,LOC_CREFERENCE:
  156. begin
  157. reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
  158. if ref.base<>NR_STACK_POINTER_REG then
  159. Internalerror(2020011801);
  160. { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
  161. list.concat(taicpu.op_reg(A_PUSH,r));
  162. end;
  163. else
  164. internalerror(2002071004);
  165. end;
  166. end;
  167. var
  168. i, i2 : longint;
  169. hp : PCGParaLocation;
  170. begin
  171. if not(tcgsize2size[cgpara.Size] in [1..4]) then
  172. internalerror(2014011101);
  173. hp:=cgpara.location;
  174. i:=0;
  175. while i<tcgsize2size[cgpara.Size] do
  176. begin
  177. if not(assigned(hp)) then
  178. internalerror(2014011102);
  179. inc(i, tcgsize2size[hp^.Size]);
  180. if hp^.Loc=LOC_REGISTER then
  181. begin
  182. load_para_loc(r,hp);
  183. hp:=hp^.Next;
  184. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  185. if i<tcgsize2size[cgpara.Size] then
  186. r:=GetNextReg(r);
  187. end
  188. else
  189. begin
  190. load_para_loc(r,hp);
  191. if i<tcgsize2size[cgpara.Size] then
  192. for i2:=1 to tcgsize2size[hp^.Size] do
  193. r:=GetNextReg(r);
  194. hp:=hp^.Next;
  195. end;
  196. end;
  197. if assigned(hp) then
  198. internalerror(2014011103);
  199. end;
  200. procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
  201. var
  202. i,j : longint;
  203. hp : PCGParaLocation;
  204. ref: treference;
  205. tmpreg: TRegister;
  206. begin
  207. if not(tcgsize2size[paraloc.Size] in [1..4]) then
  208. internalerror(2014011101);
  209. hp:=paraloc.location;
  210. i:=1;
  211. while i<=tcgsize2size[paraloc.Size] do
  212. begin
  213. if not(assigned(hp)) then
  214. internalerror(2014011105);
  215. paramanager.allocparaloc(list,hp);
  216. case hp^.loc of
  217. LOC_REGISTER,LOC_CREGISTER:
  218. begin
  219. if (tcgsize2size[hp^.size]<>1) or
  220. (hp^.shiftval<>0) then
  221. internalerror(2015041101);
  222. a_load_const_reg(list,hp^.size,(a shr (8*(i-1))) and $ff,hp^.register);
  223. inc(i,tcgsize2size[hp^.size]);
  224. hp:=hp^.Next;
  225. end;
  226. LOC_REFERENCE,LOC_CREFERENCE:
  227. begin
  228. for j:=1 to tcgsize2size[hp^.size] do
  229. begin
  230. tmpreg:=getintregister(list,OS_8);
  231. a_load_const_reg(list,OS_8,(a shr (8*(i-1+j-1))) and $ff,tmpreg);
  232. { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
  233. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  234. end;
  235. inc(i,tcgsize2size[hp^.size]);
  236. hp:=hp^.Next;
  237. end;
  238. else
  239. internalerror(2002071004);
  240. end;
  241. end;
  242. end;
  243. procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
  244. var
  245. tmpref, ref: treference;
  246. location: pcgparalocation;
  247. sizeleft: tcgint;
  248. i: Integer;
  249. tmpreg: TRegister;
  250. begin
  251. location := paraloc.location;
  252. tmpref := r;
  253. sizeleft := paraloc.intsize;
  254. while assigned(location) do
  255. begin
  256. paramanager.allocparaloc(list,location);
  257. case location^.loc of
  258. LOC_REGISTER,LOC_CREGISTER:
  259. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  260. LOC_REFERENCE:
  261. begin
  262. ref:=tmpref;
  263. for i:=1 to sizeleft do
  264. begin
  265. tmpreg:=getintregister(list,OS_8);
  266. a_load_ref_reg(list,OS_8,OS_8,tmpref,tmpreg);
  267. { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
  268. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  269. inc(tmpref.offset);
  270. end;
  271. end;
  272. LOC_VOID:
  273. begin
  274. // nothing to do
  275. end;
  276. else
  277. internalerror(2002081103);
  278. end;
  279. inc(tmpref.offset,tcgsize2size[location^.size]);
  280. dec(sizeleft,tcgsize2size[location^.size]);
  281. location := location^.next;
  282. end;
  283. end;
  284. procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  285. var
  286. tmpreg: tregister;
  287. begin
  288. tmpreg:=getaddressregister(list);
  289. a_loadaddr_ref_reg(list,r,tmpreg);
  290. a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
  291. end;
  292. procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean);
  293. var
  294. sym: TAsmSymbol;
  295. begin
  296. if weak then
  297. sym:=current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)
  298. else
  299. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION);
  300. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  301. list.concat(taicpu.op_sym(A_CALL,sym))
  302. else
  303. list.concat(taicpu.op_sym(A_RCALL,sym));
  304. include(current_procinfo.flags,pi_do_call);
  305. end;
  306. procedure tcgavr.a_call_reg(list : TAsmList;reg: tregister);
  307. begin
  308. a_reg_alloc(list,NR_ZLO);
  309. emit_mov(list,NR_ZLO,reg);
  310. a_reg_alloc(list,NR_ZHI);
  311. emit_mov(list,NR_ZHI,GetHigh(reg));
  312. list.concat(taicpu.op_none(A_ICALL));
  313. a_reg_dealloc(list,NR_ZHI);
  314. a_reg_dealloc(list,NR_ZLO);
  315. include(current_procinfo.flags,pi_do_call);
  316. end;
  317. procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
  318. begin
  319. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  320. internalerror(2012102403);
  321. a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
  322. end;
  323. procedure tcgavr.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
  324. begin
  325. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  326. internalerror(2012102401);
  327. a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
  328. end;
  329. procedure tcgavr.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
  330. begin
  331. a_op_const_reg_reg_internal(list,op,size,a,src,NR_NO,dst,NR_NO);
  332. end;
  333. procedure tcgavr.a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src,srchi,dst,dsthi: tregister);
  334. var
  335. tmpSrc, tmpDst, countreg: TRegister;
  336. b, b2, i, j: byte;
  337. s1, s2, t1: integer;
  338. l1: TAsmLabel;
  339. oldexecutionweight: LongInt;
  340. begin
  341. if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) and (a in [2,4,8]) then
  342. begin
  343. emit_mov(list,dst,src);
  344. emit_mov(list,GetNextReg(dst),GetNextReg(src));
  345. a:=a shr 1;
  346. while a>0 do
  347. begin
  348. list.concat(taicpu.op_reg(A_LSL,dst));
  349. list.concat(taicpu.op_reg(A_ROL,GetNextReg(dst)));
  350. a:=a shr 1;
  351. end;
  352. end
  353. else if (op in [OP_SHL,OP_SHR]) and
  354. { a=0 get eliminated later by tcg.optimize_op_const }
  355. (a>0) then
  356. begin
  357. { number of bytes to shift }
  358. b:=a div 8;
  359. { Ensure that b is never larger than base type }
  360. if b>tcgsize2size[size] then
  361. begin
  362. b:=tcgsize2size[size];
  363. b2:=0;
  364. end
  365. else
  366. b2:=a mod 8;
  367. if b < tcgsize2size[size] then
  368. { copy from src to dst accounting for shift offset }
  369. for i:=0 to (tcgsize2size[size]-b-1) do
  370. if op=OP_SHL then
  371. a_load_reg_reg(list,OS_8,OS_8,
  372. GetOffsetReg64(src,srchi,i),
  373. GetOffsetReg64(dst,dsthi,i+b))
  374. else
  375. a_load_reg_reg(list,OS_8,OS_8,
  376. GetOffsetReg64(src,srchi,i+b),
  377. GetOffsetReg64(dst,dsthi,i));
  378. { remaining bit shifts }
  379. if b2 > 0 then
  380. begin
  381. { Cost of loop }
  382. s1:=3+tcgsize2size[size]-b;
  383. t1:=b2*(tcgsize2size[size]-b+3);
  384. { Cost of loop unrolling,t2=s2 }
  385. s2:=b2*(tcgsize2size[size]-b);
  386. if ((cs_opt_size in current_settings.optimizerswitches) and (s1<s2)) or
  387. (((s2-s1)-t1/s2)>0) then
  388. begin
  389. { Shift non-moved bytes in loop }
  390. current_asmdata.getjumplabel(l1);
  391. countreg:=getintregister(list,OS_8);
  392. a_load_const_reg(list,OS_8,b2,countreg);
  393. cg.a_label(list,l1);
  394. oldexecutionweight:=executionweight;
  395. executionweight:=executionweight*b2;
  396. if op=OP_SHL then
  397. list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,dsthi,b)))
  398. else
  399. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1-b)));
  400. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  401. begin
  402. for i:=2+b to tcgsize2size[size] do
  403. if op=OP_SHL then
  404. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)))
  405. else
  406. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  407. end;
  408. list.concat(taicpu.op_reg(A_DEC,countreg));
  409. a_jmp_flags(list,F_NE,l1);
  410. executionweight:=oldexecutionweight;
  411. { keep registers alive }
  412. a_reg_sync(list,countreg);
  413. end
  414. else
  415. begin
  416. { Unroll shift loop over non-moved bytes }
  417. for j:=1 to b2 do
  418. begin
  419. if op=OP_SHL then
  420. list.concat(taicpu.op_reg(A_LSL,
  421. GetOffsetReg64(dst,dsthi,b)))
  422. else
  423. list.concat(taicpu.op_reg(A_LSR,
  424. GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-1)));
  425. if not(size in [OS_8,OS_S8]) then
  426. for i:=2 to tcgsize2size[size]-b do
  427. if op=OP_SHL then
  428. list.concat(taicpu.op_reg(A_ROL,
  429. GetOffsetReg64(dst,dsthi,b+i-1)))
  430. else
  431. list.concat(taicpu.op_reg(A_ROR,
  432. GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-i)));
  433. end;
  434. end;
  435. end;
  436. { fill skipped destination registers with 0
  437. Do last,then optimizer can optimize register moves }
  438. for i:=1 to b do
  439. if op=OP_SHL then
  440. emit_mov(list,GetOffsetReg64(dst,dsthi,i-1),GetDefaultZeroReg)
  441. else
  442. emit_mov(list,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i),GetDefaultZeroReg);
  443. end
  444. else
  445. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  446. end;
  447. procedure tcgavr.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation);
  448. var
  449. tmpreg: TRegister;
  450. begin
  451. if (op in [OP_MUL,OP_IMUL]) and
  452. setflags then
  453. begin
  454. tmpreg:=getintregister(list,size);
  455. a_load_const_reg(list,size,a,tmpreg);
  456. a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
  457. end
  458. else
  459. begin
  460. inherited a_op_const_reg_reg_checkoverflow(list, op, size, a, src, dst, setflags, ovloc);
  461. ovloc.loc:=LOC_FLAGS;
  462. end;
  463. end;
  464. procedure tcgavr.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
  465. begin
  466. if (op in [OP_MUL,OP_IMUL]) and
  467. setflags then
  468. gen_multiply(list,op,size,src1,src2,dst,setflags,ovloc)
  469. else
  470. begin
  471. inherited a_op_reg_reg_reg_checkoverflow(list, op, size, src1, src2, dst, setflags, ovloc);
  472. ovloc.loc:=LOC_FLAGS;
  473. end;
  474. end;
  475. procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  476. var
  477. countreg,
  478. tmpreg: tregister;
  479. i : integer;
  480. instr : taicpu;
  481. paraloc1,paraloc2 : TCGPara;
  482. l1,l2 : tasmlabel;
  483. pd : tprocdef;
  484. hovloc: tlocation;
  485. { NextRegDst* is sometimes called before the register usage and sometimes afterwards }
  486. procedure NextSrcDstPreInc;
  487. begin
  488. if i=5 then
  489. begin
  490. dst:=dsthi;
  491. src:=srchi;
  492. end
  493. else
  494. begin
  495. dst:=GetNextReg(dst);
  496. src:=GetNextReg(src);
  497. end;
  498. end;
  499. procedure NextSrcDstPostInc;
  500. begin
  501. if i=4 then
  502. begin
  503. dst:=dsthi;
  504. src:=srchi;
  505. end
  506. else
  507. begin
  508. dst:=GetNextReg(dst);
  509. src:=GetNextReg(src);
  510. end;
  511. end;
  512. { iterates TmpReg through all registers of dst }
  513. procedure NextTmp;
  514. begin
  515. if i=4 then
  516. tmpreg:=dsthi
  517. else
  518. tmpreg:=GetNextReg(tmpreg);
  519. end;
  520. begin
  521. case op of
  522. OP_ADD:
  523. begin
  524. list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
  525. for i:=2 to tcgsize2size[size] do
  526. begin
  527. NextSrcDstPreInc;
  528. list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
  529. end;
  530. end;
  531. OP_SUB:
  532. begin
  533. list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
  534. for i:=2 to tcgsize2size[size] do
  535. begin
  536. NextSrcDstPreInc;
  537. list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
  538. end;
  539. end;
  540. OP_NEG:
  541. begin
  542. if src<>dst then
  543. begin
  544. if size in [OS_S64,OS_64] then
  545. begin
  546. a_load_reg_reg(list,OS_32,OS_32,src,dst);
  547. a_load_reg_reg(list,OS_32,OS_32,srchi,dsthi);
  548. end
  549. else
  550. a_load_reg_reg(list,size,size,src,dst);
  551. end;
  552. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  553. begin
  554. tmpreg:=GetNextReg(dst);
  555. for i:=2 to tcgsize2size[size] do
  556. begin
  557. list.concat(taicpu.op_reg(A_COM,tmpreg));
  558. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  559. if i<tcgsize2size[size] then
  560. NextTmp;
  561. end;
  562. list.concat(taicpu.op_reg(A_NEG,dst));
  563. tmpreg:=GetNextReg(dst);
  564. for i:=2 to tcgsize2size[size] do
  565. begin
  566. list.concat(taicpu.op_reg_const(A_SBCI,tmpreg,-1));
  567. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  568. if i<tcgsize2size[size] then
  569. NextTmp;
  570. end;
  571. end
  572. else if size in [OS_S8,OS_8] then
  573. list.concat(taicpu.op_reg(A_NEG,dst))
  574. else
  575. Internalerror(2018030401);
  576. end;
  577. OP_NOT:
  578. begin
  579. for i:=1 to tcgsize2size[size] do
  580. begin
  581. if src<>dst then
  582. a_load_reg_reg(list,OS_8,OS_8,src,dst);
  583. list.concat(taicpu.op_reg(A_COM,dst));
  584. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  585. if i<tcgsize2size[size] then
  586. NextSrcDstPostInc;
  587. end;
  588. end;
  589. OP_MUL,OP_IMUL:
  590. begin
  591. tmpreg:=dst;
  592. if size in [OS_16,OS_S16] then
  593. begin
  594. tmpreg:=getintregister(list,size);
  595. a_load_reg_reg(list,size,size,dst,tmpreg);
  596. end;
  597. gen_multiply(list,op,size,src,tmpreg,dst,false,hovloc);
  598. end;
  599. OP_DIV,OP_IDIV:
  600. { special stuff, needs separate handling inside code }
  601. { generator }
  602. internalerror(2011022001);
  603. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  604. begin
  605. current_asmdata.getjumplabel(l1);
  606. current_asmdata.getjumplabel(l2);
  607. countreg:=getintregister(list,OS_8);
  608. a_load_reg_reg(list,size,OS_8,src,countreg);
  609. list.concat(taicpu.op_reg(A_TST,countreg));
  610. a_jmp_flags(list,F_EQ,l2);
  611. cg.a_label(list,l1);
  612. case op of
  613. OP_SHR:
  614. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  615. OP_SHL:
  616. list.concat(taicpu.op_reg(A_LSL,dst));
  617. OP_SAR:
  618. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  619. OP_ROR:
  620. begin
  621. { load carry? }
  622. if not(size in [OS_8,OS_S8]) then
  623. begin
  624. list.concat(taicpu.op_none(A_CLC));
  625. list.concat(taicpu.op_reg_const(A_SBRC,dst,0));
  626. list.concat(taicpu.op_none(A_SEC));
  627. end;
  628. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  629. end;
  630. OP_ROL:
  631. begin
  632. { load carry? }
  633. if not(size in [OS_8,OS_S8]) then
  634. begin
  635. list.concat(taicpu.op_none(A_CLC));
  636. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
  637. list.concat(taicpu.op_none(A_SEC));
  638. end;
  639. list.concat(taicpu.op_reg(A_ROL,dst))
  640. end;
  641. else
  642. internalerror(2011030901);
  643. end;
  644. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  645. begin
  646. for i:=2 to tcgsize2size[size] do
  647. begin
  648. case op of
  649. OP_ROR,
  650. OP_SHR:
  651. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  652. OP_ROL,
  653. OP_SHL:
  654. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
  655. OP_SAR:
  656. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  657. else
  658. internalerror(2011030902);
  659. end;
  660. end;
  661. end;
  662. list.concat(taicpu.op_reg(A_DEC,countreg));
  663. a_jmp_flags(list,F_NE,l1);
  664. { keep registers alive }
  665. a_reg_sync(list,countreg);
  666. cg.a_label(list,l2);
  667. end;
  668. OP_AND,OP_OR,OP_XOR:
  669. begin
  670. for i:=1 to tcgsize2size[size] do
  671. begin
  672. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  673. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  674. if i<tcgsize2size[size] then
  675. NextSrcDstPostInc;
  676. end;
  677. end;
  678. else
  679. internalerror(2011022004);
  680. end;
  681. end;
  682. procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  683. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  684. var
  685. mask : qword;
  686. shift : byte;
  687. i,j : byte;
  688. tmpreg : tregister;
  689. tmpreg64 : tregister64;
  690. { NextReg* is sometimes called before the register usage and sometimes afterwards }
  691. procedure NextRegPreInc;
  692. begin
  693. if i=5 then
  694. reg:=reghi
  695. else
  696. reg:=GetNextReg(reg);
  697. end;
  698. procedure NextRegPostInc;
  699. begin
  700. if i=4 then
  701. reg:=reghi
  702. else
  703. reg:=GetNextReg(reg);
  704. end;
  705. var
  706. curvalue : byte;
  707. l1: TAsmLabel;
  708. begin
  709. optimize_op_const(size,op,a);
  710. mask:=$ff;
  711. shift:=0;
  712. case op of
  713. OP_NONE:
  714. begin
  715. { Opcode is optimized away }
  716. end;
  717. OP_MOVE:
  718. begin
  719. { Optimized, replaced with a simple load }
  720. a_load_const_reg(list,size,a,reg);
  721. end;
  722. OP_OR:
  723. begin
  724. for i:=1 to tcgsize2size[size] do
  725. begin
  726. if ((qword(a) and mask) shr shift)<>0 then
  727. list.concat(taicpu.op_reg_const(A_ORI,reg,(qword(a) and mask) shr shift));
  728. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  729. if i<tcgsize2size[size] then
  730. NextRegPostInc;
  731. mask:=mask shl 8;
  732. inc(shift,8);
  733. end;
  734. end;
  735. OP_AND:
  736. begin
  737. for i:=1 to tcgsize2size[size] do
  738. begin
  739. if ((qword(a) and mask) shr shift)=0 then
  740. list.concat(taicpu.op_reg_reg(A_MOV,reg,GetDefaultZeroReg))
  741. else if ((qword(a) and mask) shr shift)<>$ff then
  742. begin
  743. getcpuregister(list,NR_R26);
  744. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
  745. list.concat(taicpu.op_reg_reg(A_AND,reg,NR_R26));
  746. ungetcpuregister(list,NR_R26);
  747. end;
  748. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  749. if i<tcgsize2size[size] then
  750. NextRegPostInc;
  751. mask:=mask shl 8;
  752. inc(shift,8);
  753. end;
  754. end;
  755. OP_SUB:
  756. begin
  757. if ((a and mask)=1) and (tcgsize2size[size]=1) then
  758. list.concat(taicpu.op_reg(A_DEC,reg))
  759. else
  760. begin
  761. getcpuregister(list,NR_R26);
  762. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,a and mask));
  763. list.concat(taicpu.op_reg_reg(A_SUB,reg,NR_R26));
  764. ungetcpuregister(list,NR_R26);
  765. end;
  766. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  767. begin
  768. for i:=2 to tcgsize2size[size] do
  769. begin
  770. NextRegPreInc;
  771. mask:=mask shl 8;
  772. inc(shift,8);
  773. curvalue:=(qword(a) and mask) shr shift;
  774. { decrease pressure on upper half of registers by using SBC ...,R1 instead
  775. of SBCI ...,0 }
  776. if curvalue=0 then
  777. list.concat(taicpu.op_reg_reg(A_SBC,reg,GetDefaultZeroReg))
  778. else
  779. list.concat(taicpu.op_reg_const(A_SBCI,reg,curvalue));
  780. end;
  781. end;
  782. end;
  783. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  784. begin
  785. if (op=OP_SAR) and (a>=(tcgsize2size[size]*8-1)) then
  786. begin
  787. current_asmdata.getjumplabel(l1);
  788. list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  789. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1));
  790. a_jmp_flags(list,F_PL,l1);
  791. list.concat(taicpu.op_reg(A_DEC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  792. cg.a_label(list,l1);
  793. for i:=2 to tcgsize2size[size] do
  794. a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),GetOffsetReg64(reg,reghi,tcgsize2size[size]-i));
  795. end
  796. else if (op=OP_SHR) and (a=(tcgsize2size[size]*8-1)) then
  797. begin
  798. current_asmdata.getjumplabel(l1);
  799. list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  800. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,0));
  801. a_jmp_flags(list,F_PL,l1);
  802. list.concat(taicpu.op_reg(A_INC,GetOffsetReg64(reg,reghi,0)));
  803. cg.a_label(list,l1);
  804. for i:=1 to tcgsize2size[size]-1 do
  805. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,i));
  806. end
  807. else if a*tcgsize2size[size]<=8 then
  808. begin
  809. for j:=1 to a do
  810. begin
  811. case op of
  812. OP_SHR:
  813. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  814. OP_SHL:
  815. list.concat(taicpu.op_reg(A_LSL,reg));
  816. OP_SAR:
  817. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  818. OP_ROR:
  819. begin
  820. { load carry? }
  821. if not(size in [OS_8,OS_S8]) then
  822. begin
  823. list.concat(taicpu.op_none(A_CLC));
  824. list.concat(taicpu.op_reg_const(A_SBRC,reg,0));
  825. list.concat(taicpu.op_none(A_SEC));
  826. end;
  827. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  828. end;
  829. OP_ROL:
  830. begin
  831. { load carry? }
  832. if not(size in [OS_8,OS_S8]) then
  833. begin
  834. list.concat(taicpu.op_none(A_CLC));
  835. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),7));
  836. list.concat(taicpu.op_none(A_SEC));
  837. end;
  838. list.concat(taicpu.op_reg(A_ROL,reg))
  839. end;
  840. else
  841. internalerror(2011030901);
  842. end;
  843. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  844. begin
  845. for i:=2 to tcgsize2size[size] do
  846. begin
  847. case op of
  848. OP_ROR,
  849. OP_SHR:
  850. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  851. OP_ROL,
  852. OP_SHL:
  853. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(reg,reghi,i-1)));
  854. OP_SAR:
  855. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  856. else
  857. internalerror(2011030902);
  858. end;
  859. end;
  860. end;
  861. end;
  862. end
  863. else
  864. begin
  865. tmpreg:=getintregister(list,size);
  866. a_load_const_reg(list,size,a,tmpreg);
  867. a_op_reg_reg(list,op,size,tmpreg,reg);
  868. end;
  869. end;
  870. OP_ADD:
  871. begin
  872. curvalue:=a and mask;
  873. if curvalue=0 then
  874. list.concat(taicpu.op_reg_reg(A_ADD,reg,GetDefaultZeroReg))
  875. else if (curvalue=1) and (tcgsize2size[size]=1) then
  876. list.concat(taicpu.op_reg(A_INC,reg))
  877. else
  878. begin
  879. tmpreg:=getintregister(list,OS_8);
  880. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  881. list.concat(taicpu.op_reg_reg(A_ADD,reg,tmpreg));
  882. end;
  883. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  884. begin
  885. for i:=2 to tcgsize2size[size] do
  886. begin
  887. NextRegPreInc;
  888. mask:=mask shl 8;
  889. inc(shift,8);
  890. curvalue:=(qword(a) and mask) shr shift;
  891. { decrease pressure on upper half of registers by using ADC ...,R1 instead
  892. of ADD ...,0 }
  893. if curvalue=0 then
  894. list.concat(taicpu.op_reg_reg(A_ADC,reg,GetDefaultZeroReg))
  895. else
  896. begin
  897. tmpreg:=getintregister(list,OS_8);
  898. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  899. list.concat(taicpu.op_reg_reg(A_ADC,reg,tmpreg));
  900. end;
  901. end;
  902. end;
  903. end;
  904. else
  905. begin
  906. if size in [OS_64,OS_S64] then
  907. begin
  908. tmpreg64.reglo:=getintregister(list,OS_32);
  909. tmpreg64.reghi:=getintregister(list,OS_32);
  910. cg64.a_load64_const_reg(list,a,tmpreg64);
  911. cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  912. end
  913. else
  914. begin
  915. {$if 0}
  916. { code not working yet }
  917. if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  918. begin
  919. tmpreg:=reg;
  920. for i:=1 to 4 do
  921. begin
  922. list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,GetDefaultZeroReg));
  923. tmpreg:=GetNextReg(tmpreg);
  924. end;
  925. end
  926. else
  927. {$endif}
  928. begin
  929. tmpreg:=getintregister(list,size);
  930. a_load_const_reg(list,size,a,tmpreg);
  931. a_op_reg_reg(list,op,size,tmpreg,reg);
  932. end;
  933. end;
  934. end;
  935. end;
  936. end;
  937. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  938. var
  939. mask : qword;
  940. shift : byte;
  941. i : byte;
  942. begin
  943. mask:=$ff;
  944. shift:=0;
  945. for i:=1 to tcgsize2size[size] do
  946. begin
  947. if ((qword(a) and mask) shr shift)=0 then
  948. emit_mov(list,reg,GetDefaultZeroReg)
  949. else
  950. begin
  951. getcpuregister(list,NR_R26);
  952. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
  953. a_load_reg_reg(list,OS_8,OS_8,NR_R26,reg);
  954. ungetcpuregister(list,NR_R26);
  955. end;
  956. mask:=mask shl 8;
  957. inc(shift,8);
  958. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  959. if i<tcgsize2size[size] then
  960. reg:=GetNextReg(reg);
  961. end;
  962. end;
  963. procedure tcgavr.maybegetcpuregister(list:tasmlist;reg : tregister);
  964. begin
  965. { allocate the register only, if a cpu register is passed }
  966. if getsupreg(reg)<first_int_imreg then
  967. getcpuregister(list,reg);
  968. end;
  969. function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
  970. var
  971. tmpref : treference;
  972. l : tasmlabel;
  973. begin
  974. Result:=ref;
  975. if ref.addressmode<>AM_UNCHANGED then
  976. internalerror(2011021701);
  977. { Be sure to have a base register }
  978. if (ref.base=NR_NO) then
  979. begin
  980. ref.base:=ref.index;
  981. ref.index:=NR_NO;
  982. end;
  983. { can we take advantage of adiw/sbiw? }
  984. if (current_settings.cputype>=cpu_avr2) and not(assigned(ref.symbol)) and (ref.offset<>0) and (ref.offset>=-63) and (ref.offset<=63) and
  985. ((tmpreg=NR_R24) or (tmpreg=NR_R26) or (tmpreg=NR_R28) or (tmpreg=NR_R30)) and (ref.base<>NR_NO) then
  986. begin
  987. maybegetcpuregister(list,tmpreg);
  988. emit_mov(list,tmpreg,ref.base);
  989. maybegetcpuregister(list,GetNextReg(tmpreg));
  990. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  991. if ref.index<>NR_NO then
  992. begin
  993. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  994. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  995. end;
  996. if ref.offset>0 then
  997. list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
  998. else
  999. list.concat(taicpu.op_reg_const(A_SBIW,tmpreg,-ref.offset));
  1000. ref.offset:=0;
  1001. ref.base:=tmpreg;
  1002. ref.index:=NR_NO;
  1003. end
  1004. else if assigned(ref.symbol) or (ref.offset<>0) then
  1005. begin
  1006. reference_reset(tmpref,0,[]);
  1007. tmpref.symbol:=ref.symbol;
  1008. tmpref.offset:=ref.offset;
  1009. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1010. tmpref.refaddr:=addr_lo8_gs
  1011. else
  1012. tmpref.refaddr:=addr_lo8;
  1013. maybegetcpuregister(list,tmpreg);
  1014. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  1015. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1016. tmpref.refaddr:=addr_hi8_gs
  1017. else
  1018. tmpref.refaddr:=addr_hi8;
  1019. maybegetcpuregister(list,GetNextReg(tmpreg));
  1020. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  1021. if (ref.base<>NR_NO) then
  1022. begin
  1023. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  1024. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  1025. end;
  1026. if (ref.index<>NR_NO) then
  1027. begin
  1028. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1029. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1030. end;
  1031. ref.symbol:=nil;
  1032. ref.offset:=0;
  1033. ref.base:=tmpreg;
  1034. ref.index:=NR_NO;
  1035. end
  1036. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  1037. begin
  1038. maybegetcpuregister(list,tmpreg);
  1039. emit_mov(list,tmpreg,ref.base);
  1040. maybegetcpuregister(list,GetNextReg(tmpreg));
  1041. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1042. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1043. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1044. ref.base:=tmpreg;
  1045. ref.index:=NR_NO;
  1046. end
  1047. else if (ref.base<>NR_NO) then
  1048. begin
  1049. maybegetcpuregister(list,tmpreg);
  1050. emit_mov(list,tmpreg,ref.base);
  1051. maybegetcpuregister(list,GetNextReg(tmpreg));
  1052. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1053. ref.base:=tmpreg;
  1054. ref.index:=NR_NO;
  1055. end
  1056. else if (ref.index<>NR_NO) then
  1057. begin
  1058. maybegetcpuregister(list,tmpreg);
  1059. emit_mov(list,tmpreg,ref.index);
  1060. maybegetcpuregister(list,GetNextReg(tmpreg));
  1061. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
  1062. ref.base:=tmpreg;
  1063. ref.index:=NR_NO;
  1064. end
  1065. else
  1066. Internalerror(2020011901);
  1067. Result:=ref;
  1068. end;
  1069. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1070. var
  1071. href : treference;
  1072. conv_done: boolean;
  1073. tmpreg : tregister;
  1074. i : integer;
  1075. QuickRef,ungetcpuregister_z: Boolean;
  1076. begin
  1077. QuickRef:=false;
  1078. ungetcpuregister_z:=false;
  1079. href:=Ref;
  1080. { ensure, href.base contains a valid register if there is any register used }
  1081. if href.base=NR_NO then
  1082. begin
  1083. href.base:=href.index;
  1084. href.index:=NR_NO;
  1085. end;
  1086. { try to use std/sts }
  1087. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1088. begin
  1089. if not((href.addressmode=AM_UNCHANGED) and
  1090. (href.symbol=nil) and
  1091. (href.Index=NR_NO) and
  1092. (href.Offset in [0..64-tcgsize2size[fromsize]])) or
  1093. (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  1094. begin
  1095. href:=normalize_ref(list,href,NR_R30);
  1096. getcpuregister(list,NR_R30);
  1097. getcpuregister(list,NR_R31);
  1098. ungetcpuregister_z:=true;
  1099. end
  1100. else
  1101. begin
  1102. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1103. begin
  1104. getcpuregister(list,NR_R30);
  1105. emit_mov(list,NR_R30,href.base);
  1106. getcpuregister(list,NR_R31);
  1107. emit_mov(list,NR_R31,GetNextReg(href.base));
  1108. href.base:=NR_R30;
  1109. ungetcpuregister_z:=true;
  1110. end;
  1111. QuickRef:=true;
  1112. end;
  1113. end
  1114. else
  1115. QuickRef:=true;
  1116. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1117. internalerror(2011021307);
  1118. conv_done:=false;
  1119. if tosize<>fromsize then
  1120. begin
  1121. conv_done:=true;
  1122. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1123. fromsize:=tosize;
  1124. case fromsize of
  1125. OS_8:
  1126. begin
  1127. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1128. href.addressmode:=AM_POSTINCREMENT;
  1129. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1130. for i:=2 to tcgsize2size[tosize] do
  1131. begin
  1132. if QuickRef then
  1133. inc(href.offset);
  1134. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1135. href.addressmode:=AM_POSTINCREMENT
  1136. else
  1137. href.addressmode:=AM_UNCHANGED;
  1138. list.concat(taicpu.op_ref_reg(GetStore(href),href,GetDefaultZeroReg));
  1139. end;
  1140. end;
  1141. OS_S8:
  1142. begin
  1143. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1144. href.addressmode:=AM_POSTINCREMENT;
  1145. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1146. if tcgsize2size[tosize]>1 then
  1147. begin
  1148. tmpreg:=getintregister(list,OS_8);
  1149. emit_mov(list,tmpreg,GetDefaultZeroReg);
  1150. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1151. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1152. for i:=2 to tcgsize2size[tosize] do
  1153. begin
  1154. if QuickRef then
  1155. inc(href.offset);
  1156. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1157. href.addressmode:=AM_POSTINCREMENT
  1158. else
  1159. href.addressmode:=AM_UNCHANGED;
  1160. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1161. end;
  1162. end;
  1163. end;
  1164. OS_16:
  1165. begin
  1166. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1167. href.addressmode:=AM_POSTINCREMENT;
  1168. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1169. if QuickRef then
  1170. inc(href.offset)
  1171. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1172. href.addressmode:=AM_POSTINCREMENT
  1173. else
  1174. href.addressmode:=AM_UNCHANGED;
  1175. reg:=GetNextReg(reg);
  1176. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1177. for i:=3 to tcgsize2size[tosize] do
  1178. begin
  1179. if QuickRef then
  1180. inc(href.offset);
  1181. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1182. href.addressmode:=AM_POSTINCREMENT
  1183. else
  1184. href.addressmode:=AM_UNCHANGED;
  1185. list.concat(taicpu.op_ref_reg(GetStore(href),href,GetDefaultZeroReg));
  1186. end;
  1187. end;
  1188. OS_S16:
  1189. begin
  1190. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1191. href.addressmode:=AM_POSTINCREMENT;
  1192. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1193. if QuickRef then
  1194. inc(href.offset)
  1195. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1196. href.addressmode:=AM_POSTINCREMENT
  1197. else
  1198. href.addressmode:=AM_UNCHANGED;
  1199. reg:=GetNextReg(reg);
  1200. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1201. if tcgsize2size[tosize]>2 then
  1202. begin
  1203. tmpreg:=getintregister(list,OS_8);
  1204. emit_mov(list,tmpreg,GetDefaultZeroReg);
  1205. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1206. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1207. for i:=3 to tcgsize2size[tosize] do
  1208. begin
  1209. if QuickRef then
  1210. inc(href.offset);
  1211. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1212. href.addressmode:=AM_POSTINCREMENT
  1213. else
  1214. href.addressmode:=AM_UNCHANGED;
  1215. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1216. end;
  1217. end;
  1218. end;
  1219. else
  1220. conv_done:=false;
  1221. end;
  1222. end;
  1223. if not conv_done then
  1224. begin
  1225. // CC
  1226. // Write to 16 bit ioreg, first high byte then low byte
  1227. // sequence required for 16 bit timer registers
  1228. // See e.g. atmega328p manual para 15.3 Accessing 16 bit registers
  1229. // Avrxmega3: write low byte first then high byte
  1230. // See e.g. megaAVR-0 family data sheet 7.5.6 Accessing 16-bit registers
  1231. if (current_settings.cputype <> cpu_avrxmega3) and
  1232. (fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31) and
  1233. (href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  1234. begin
  1235. tmpreg:=GetNextReg(reg);
  1236. href.addressmode:=AM_UNCHANGED;
  1237. inc(href.offset);
  1238. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1239. dec(href.offset);
  1240. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1241. end
  1242. else
  1243. begin
  1244. for i:=1 to tcgsize2size[fromsize] do
  1245. begin
  1246. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1247. href.addressmode:=AM_POSTINCREMENT
  1248. else
  1249. href.addressmode:=AM_UNCHANGED;
  1250. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1251. if QuickRef then
  1252. inc(href.offset);
  1253. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1254. if i<tcgsize2size[fromsize] then
  1255. reg:=GetNextReg(reg);
  1256. end;
  1257. end;
  1258. end;
  1259. if not(QuickRef) or ungetcpuregister_z then
  1260. begin
  1261. ungetcpuregister(list,href.base);
  1262. ungetcpuregister(list,GetNextReg(href.base));
  1263. end;
  1264. end;
  1265. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1266. const Ref : treference;reg : tregister);
  1267. var
  1268. href : treference;
  1269. conv_done: boolean;
  1270. tmpreg : tregister;
  1271. i : integer;
  1272. QuickRef,ungetcpuregister_z: boolean;
  1273. begin
  1274. QuickRef:=false;
  1275. ungetcpuregister_z:=false;
  1276. href:=Ref;
  1277. { ensure, href.base contains a valid register if there is any register used }
  1278. if href.base=NR_NO then
  1279. begin
  1280. href.base:=href.index;
  1281. href.index:=NR_NO;
  1282. end;
  1283. { try to use ldd/lds }
  1284. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1285. begin
  1286. if not((href.addressmode=AM_UNCHANGED) and
  1287. (href.symbol=nil) and
  1288. (href.Index=NR_NO) and
  1289. (href.Offset in [0..64-tcgsize2size[fromsize]])) or
  1290. (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  1291. begin
  1292. href:=normalize_ref(list,href,NR_R30);
  1293. getcpuregister(list,NR_R30);
  1294. getcpuregister(list,NR_R31);
  1295. ungetcpuregister_z:=true;
  1296. end
  1297. else
  1298. begin
  1299. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1300. begin
  1301. getcpuregister(list,NR_R30);
  1302. emit_mov(list,NR_R30,href.base);
  1303. getcpuregister(list,NR_R31);
  1304. emit_mov(list,NR_R31,GetNextReg(href.base));
  1305. href.base:=NR_R30;
  1306. ungetcpuregister_z:=true;
  1307. end;
  1308. QuickRef:=true;
  1309. end;
  1310. end
  1311. else
  1312. QuickRef:=true;
  1313. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1314. internalerror(2011021307);
  1315. conv_done:=false;
  1316. if tosize<>fromsize then
  1317. begin
  1318. conv_done:=true;
  1319. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1320. fromsize:=tosize;
  1321. case fromsize of
  1322. OS_8:
  1323. begin
  1324. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1325. for i:=2 to tcgsize2size[tosize] do
  1326. begin
  1327. reg:=GetNextReg(reg);
  1328. emit_mov(list,reg,GetDefaultZeroReg);
  1329. end;
  1330. end;
  1331. OS_S8:
  1332. begin
  1333. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1334. tmpreg:=reg;
  1335. if tcgsize2size[tosize]>1 then
  1336. begin
  1337. reg:=GetNextReg(reg);
  1338. emit_mov(list,reg,GetDefaultZeroReg);
  1339. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1340. list.concat(taicpu.op_reg(A_COM,reg));
  1341. tmpreg:=reg;
  1342. for i:=3 to tcgsize2size[tosize] do
  1343. begin
  1344. reg:=GetNextReg(reg);
  1345. emit_mov(list,reg,tmpreg);
  1346. end;
  1347. end;
  1348. end;
  1349. OS_16:
  1350. begin
  1351. if not(QuickRef) then
  1352. href.addressmode:=AM_POSTINCREMENT;
  1353. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1354. if QuickRef then
  1355. inc(href.offset);
  1356. href.addressmode:=AM_UNCHANGED;
  1357. reg:=GetNextReg(reg);
  1358. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1359. for i:=3 to tcgsize2size[tosize] do
  1360. begin
  1361. reg:=GetNextReg(reg);
  1362. emit_mov(list,reg,GetDefaultZeroReg);
  1363. end;
  1364. end;
  1365. OS_S16:
  1366. begin
  1367. if not(QuickRef) then
  1368. href.addressmode:=AM_POSTINCREMENT;
  1369. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1370. if QuickRef then
  1371. inc(href.offset);
  1372. href.addressmode:=AM_UNCHANGED;
  1373. reg:=GetNextReg(reg);
  1374. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1375. tmpreg:=reg;
  1376. reg:=GetNextReg(reg);
  1377. emit_mov(list,reg,GetDefaultZeroReg);
  1378. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1379. list.concat(taicpu.op_reg(A_COM,reg));
  1380. tmpreg:=reg;
  1381. for i:=4 to tcgsize2size[tosize] do
  1382. begin
  1383. reg:=GetNextReg(reg);
  1384. emit_mov(list,reg,tmpreg);
  1385. end;
  1386. end;
  1387. else
  1388. conv_done:=false;
  1389. end;
  1390. end;
  1391. if not conv_done then
  1392. begin
  1393. for i:=1 to tcgsize2size[fromsize] do
  1394. begin
  1395. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1396. href.addressmode:=AM_POSTINCREMENT
  1397. else
  1398. href.addressmode:=AM_UNCHANGED;
  1399. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1400. if QuickRef then
  1401. inc(href.offset);
  1402. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1403. if i<tcgsize2size[fromsize] then
  1404. reg:=GetNextReg(reg);
  1405. end;
  1406. end;
  1407. if ungetcpuregister_z then
  1408. begin
  1409. ungetcpuregister(list,href.base);
  1410. ungetcpuregister(list,GetNextReg(href.base));
  1411. end;
  1412. end;
  1413. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1414. var
  1415. conv_done: boolean;
  1416. tmpreg : tregister;
  1417. i : integer;
  1418. begin
  1419. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1420. internalerror(2011021310);
  1421. conv_done:=false;
  1422. if tosize<>fromsize then
  1423. begin
  1424. conv_done:=true;
  1425. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1426. fromsize:=tosize;
  1427. case fromsize of
  1428. OS_8:
  1429. begin
  1430. emit_mov(list,reg2,reg1);
  1431. for i:=2 to tcgsize2size[tosize] do
  1432. begin
  1433. reg2:=GetNextReg(reg2);
  1434. emit_mov(list,reg2,GetDefaultZeroReg);
  1435. end;
  1436. end;
  1437. OS_S8:
  1438. begin
  1439. emit_mov(list,reg2,reg1);
  1440. if tcgsize2size[tosize]>1 then
  1441. begin
  1442. reg2:=GetNextReg(reg2);
  1443. emit_mov(list,reg2,GetDefaultZeroReg);
  1444. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1445. list.concat(taicpu.op_reg(A_COM,reg2));
  1446. tmpreg:=reg2;
  1447. for i:=3 to tcgsize2size[tosize] do
  1448. begin
  1449. reg2:=GetNextReg(reg2);
  1450. emit_mov(list,reg2,tmpreg);
  1451. end;
  1452. end;
  1453. end;
  1454. OS_16:
  1455. begin
  1456. emit_mov(list,reg2,reg1);
  1457. reg1:=GetNextReg(reg1);
  1458. reg2:=GetNextReg(reg2);
  1459. emit_mov(list,reg2,reg1);
  1460. for i:=3 to tcgsize2size[tosize] do
  1461. begin
  1462. reg2:=GetNextReg(reg2);
  1463. emit_mov(list,reg2,GetDefaultZeroReg);
  1464. end;
  1465. end;
  1466. OS_S16:
  1467. begin
  1468. emit_mov(list,reg2,reg1);
  1469. reg1:=GetNextReg(reg1);
  1470. reg2:=GetNextReg(reg2);
  1471. emit_mov(list,reg2,reg1);
  1472. if tcgsize2size[tosize]>2 then
  1473. begin
  1474. reg2:=GetNextReg(reg2);
  1475. emit_mov(list,reg2,GetDefaultZeroReg);
  1476. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1477. list.concat(taicpu.op_reg(A_COM,reg2));
  1478. tmpreg:=reg2;
  1479. for i:=4 to tcgsize2size[tosize] do
  1480. begin
  1481. reg2:=GetNextReg(reg2);
  1482. emit_mov(list,reg2,tmpreg);
  1483. end;
  1484. end;
  1485. end;
  1486. else
  1487. conv_done:=false;
  1488. end;
  1489. end;
  1490. if not conv_done and (reg1<>reg2) then
  1491. begin
  1492. for i:=1 to tcgsize2size[fromsize] do
  1493. begin
  1494. emit_mov(list,reg2,reg1);
  1495. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1496. if i<tcgsize2size[fromsize] then
  1497. begin
  1498. reg1:=GetNextReg(reg1);
  1499. reg2:=GetNextReg(reg2);
  1500. end;
  1501. end;
  1502. end;
  1503. end;
  1504. procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1505. begin
  1506. internalerror(2012010702);
  1507. end;
  1508. procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1509. begin
  1510. internalerror(2012010703);
  1511. end;
  1512. procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1513. begin
  1514. internalerror(2012010704);
  1515. end;
  1516. { comparison operations }
  1517. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1518. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1519. var
  1520. swapped , test_msb: boolean;
  1521. tmpreg : tregister;
  1522. i : byte;
  1523. begin
  1524. if a=0 then
  1525. begin
  1526. swapped:=false;
  1527. { swap parameters? }
  1528. case cmp_op of
  1529. OC_GT:
  1530. begin
  1531. swapped:=true;
  1532. cmp_op:=OC_LT;
  1533. end;
  1534. OC_LTE:
  1535. begin
  1536. swapped:=true;
  1537. cmp_op:=OC_GTE;
  1538. end;
  1539. OC_BE:
  1540. begin
  1541. swapped:=true;
  1542. cmp_op:=OC_AE;
  1543. end;
  1544. OC_A:
  1545. begin
  1546. swapped:=true;
  1547. cmp_op:=OC_B;
  1548. end;
  1549. end;
  1550. { If doing a signed test for x<0, we can simply test the sign bit
  1551. of the most significant byte }
  1552. if (cmp_op in [OC_LT,OC_GTE]) and
  1553. (not swapped) then
  1554. begin
  1555. for i:=2 to tcgsize2size[size] do
  1556. reg:=GetNextReg(reg);
  1557. list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
  1558. end
  1559. else
  1560. begin
  1561. if swapped then
  1562. list.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,reg))
  1563. else
  1564. list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
  1565. for i:=2 to tcgsize2size[size] do
  1566. begin
  1567. reg:=GetNextReg(reg);
  1568. if swapped then
  1569. list.concat(taicpu.op_reg_reg(A_CPC,GetDefaultZeroReg,reg))
  1570. else
  1571. list.concat(taicpu.op_reg_reg(A_CPC,reg,GetDefaultZeroReg));
  1572. end;
  1573. end;
  1574. a_jmp_cond(list,cmp_op,l);
  1575. end
  1576. else
  1577. inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1578. end;
  1579. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1580. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1581. var
  1582. swapped : boolean;
  1583. tmpreg : tregister;
  1584. i : byte;
  1585. begin
  1586. swapped:=false;
  1587. { swap parameters? }
  1588. case cmp_op of
  1589. OC_GT:
  1590. begin
  1591. swapped:=true;
  1592. cmp_op:=OC_LT;
  1593. end;
  1594. OC_LTE:
  1595. begin
  1596. swapped:=true;
  1597. cmp_op:=OC_GTE;
  1598. end;
  1599. OC_BE:
  1600. begin
  1601. swapped:=true;
  1602. cmp_op:=OC_AE;
  1603. end;
  1604. OC_A:
  1605. begin
  1606. swapped:=true;
  1607. cmp_op:=OC_B;
  1608. end;
  1609. end;
  1610. if swapped then
  1611. begin
  1612. tmpreg:=reg1;
  1613. reg1:=reg2;
  1614. reg2:=tmpreg;
  1615. end;
  1616. list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1617. for i:=2 to tcgsize2size[size] do
  1618. begin
  1619. reg1:=GetNextReg(reg1);
  1620. reg2:=GetNextReg(reg2);
  1621. list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1622. end;
  1623. a_jmp_cond(list,cmp_op,l);
  1624. end;
  1625. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  1626. var
  1627. ai : taicpu;
  1628. begin
  1629. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1630. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION))
  1631. else
  1632. ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1633. ai.is_jmp:=true;
  1634. list.concat(ai);
  1635. end;
  1636. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  1637. var
  1638. ai : taicpu;
  1639. begin
  1640. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1641. ai:=taicpu.op_sym(A_JMP,l)
  1642. else
  1643. ai:=taicpu.op_sym(A_RJMP,l);
  1644. ai.is_jmp:=true;
  1645. list.concat(ai);
  1646. end;
  1647. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1648. var
  1649. ai : taicpu;
  1650. begin
  1651. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  1652. ai.is_jmp:=true;
  1653. list.concat(ai);
  1654. end;
  1655. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1656. var
  1657. l : TAsmLabel;
  1658. tmpflags : TResFlags;
  1659. i: Integer;
  1660. hreg: TRegister;
  1661. begin
  1662. current_asmdata.getjumplabel(l);
  1663. {
  1664. if flags_to_cond(f) then
  1665. begin
  1666. tmpflags:=f;
  1667. inverse_flags(tmpflags);
  1668. emit_mov(reg,GetDefaultZeroReg);
  1669. a_jmp_flags(list,tmpflags,l);
  1670. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1671. end
  1672. else
  1673. }
  1674. begin
  1675. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1676. hreg:=reg;
  1677. for i:=2 to tcgsize2size[size] do
  1678. begin
  1679. hreg:=GetNextReg(hreg);
  1680. emit_mov(list,hreg,GetDefaultZeroReg);
  1681. end;
  1682. a_jmp_flags(list,f,l);
  1683. emit_mov(list,reg,GetDefaultZeroReg);
  1684. end;
  1685. cg.a_label(list,l);
  1686. end;
  1687. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  1688. var
  1689. i : integer;
  1690. begin
  1691. case value of
  1692. 0:
  1693. ;
  1694. {-14..-1:
  1695. begin
  1696. if ((-value) mod 2)<>0 then
  1697. list.concat(taicpu.op_reg(A_PUSH,GetDefaultTmpReg));
  1698. for i:=1 to (-value) div 2 do
  1699. list.concat(taicpu.op_const(A_RCALL,0));
  1700. end;
  1701. 1..7:
  1702. begin
  1703. for i:=1 to value do
  1704. list.concat(taicpu.op_reg(A_POP,GetDefaultTmpReg));
  1705. end;}
  1706. else
  1707. begin
  1708. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1709. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1710. // get SREG
  1711. list.concat(taicpu.op_reg_const(A_IN,GetDefaultTmpReg,NIO_SREG));
  1712. // block interrupts
  1713. list.concat(taicpu.op_none(A_CLI));
  1714. // write high SP
  1715. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1716. // release interrupts
  1717. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,GetDefaultTmpReg));
  1718. // write low SP
  1719. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1720. end;
  1721. end;
  1722. end;
  1723. function tcgavr.GetLoad(const ref: treference) : tasmop;
  1724. begin
  1725. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1726. result:=A_LDS
  1727. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1728. result:=A_LDD
  1729. else
  1730. result:=A_LD;
  1731. end;
  1732. function tcgavr.GetStore(const ref: treference) : tasmop;
  1733. begin
  1734. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1735. result:=A_STS
  1736. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1737. result:=A_STD
  1738. else
  1739. result:=A_ST;
  1740. end;
  1741. procedure tcgavr.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean; var ovloc: tlocation);
  1742. procedure perform_r1_check(overflow_label: TAsmLabel; other_reg: TRegister=NR_R1);
  1743. var
  1744. ai: taicpu;
  1745. begin
  1746. if check_overflow then
  1747. begin
  1748. list.concat(taicpu.op_reg_reg(A_OR,NR_R1,other_reg));
  1749. ai:=Taicpu.Op_Sym(A_BRxx,overflow_label);
  1750. ai.SetCondition(C_NE);
  1751. ai.is_jmp:=true;
  1752. list.concat(ai);
  1753. end;
  1754. end;
  1755. procedure perform_ovf_check(overflow_label: TAsmLabel);
  1756. var
  1757. ai: taicpu;
  1758. begin
  1759. if check_overflow then
  1760. begin
  1761. ai:=Taicpu.Op_Sym(A_BRxx,overflow_label);
  1762. ai.SetCondition(C_CS);
  1763. ai.is_jmp:=true;
  1764. list.concat(ai);
  1765. end;
  1766. end;
  1767. var
  1768. pd: tprocdef;
  1769. paraloc1, paraloc2: tcgpara;
  1770. ai: taicpu;
  1771. hl, no_overflow: TAsmLabel;
  1772. name: String;
  1773. begin
  1774. ovloc.loc:=LOC_VOID;
  1775. if size in [OS_8,OS_S8] then
  1776. begin
  1777. if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1778. (op=OP_MUL) then
  1779. begin
  1780. cg.a_reg_alloc(list,NR_R0);
  1781. cg.a_reg_alloc(list,NR_R1);
  1782. list.concat(taicpu.op_reg_reg(topcg2asmop[op],src1,src2));
  1783. // Check overflow
  1784. if check_overflow then
  1785. begin
  1786. current_asmdata.getjumplabel(hl);
  1787. list.concat(taicpu.op_reg_reg(A_AND,NR_R1,NR_R1));
  1788. { Clear carry as it's not affected by any of the instructions }
  1789. list.concat(taicpu.op_none(A_CLC));
  1790. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1791. ai.SetCondition(C_EQ);
  1792. ai.is_jmp:=true;
  1793. list.concat(ai);
  1794. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1795. list.concat(taicpu.op_none(A_SEC));
  1796. a_label(list,hl);
  1797. ovloc.loc:=LOC_FLAGS;
  1798. end
  1799. else
  1800. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1801. cg.a_reg_dealloc(list,NR_R1);
  1802. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  1803. cg.a_reg_dealloc(list,NR_R0);
  1804. end
  1805. else if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1806. (op=OP_IMUL) then
  1807. begin
  1808. cg.a_reg_alloc(list,NR_R0);
  1809. cg.a_reg_alloc(list,NR_R1);
  1810. list.concat(taicpu.op_reg_reg(A_MULS,src1,src2));
  1811. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  1812. // Check overflow
  1813. if check_overflow then
  1814. begin
  1815. current_asmdata.getjumplabel(no_overflow);
  1816. list.concat(taicpu.op_reg_const(A_SBRC,NR_R0,7));
  1817. list.concat(taicpu.op_reg(A_INC,NR_R1));
  1818. list.concat(taicpu.op_reg(A_TST,NR_R1));
  1819. ai:=Taicpu.Op_Sym(A_BRxx,no_overflow);
  1820. ai.SetCondition(C_EQ);
  1821. ai.is_jmp:=true;
  1822. list.concat(ai);
  1823. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1824. a_call_name(list,'FPC_OVERFLOW',false);
  1825. a_label(list,no_overflow);
  1826. ovloc.loc:=LOC_VOID;
  1827. end
  1828. else
  1829. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1830. cg.a_reg_dealloc(list,NR_R1);
  1831. cg.a_reg_dealloc(list,NR_R0);
  1832. end
  1833. else
  1834. begin
  1835. if size=OS_8 then
  1836. name:='fpc_mul_byte'
  1837. else
  1838. name:='fpc_mul_shortint';
  1839. if check_overflow then
  1840. name:=name+'_checkoverflow';
  1841. pd:=search_system_proc(name);
  1842. paraloc1.init;
  1843. paraloc2.init;
  1844. paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1845. paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1846. a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  1847. a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  1848. paramanager.freecgpara(list,paraloc2);
  1849. paramanager.freecgpara(list,paraloc1);
  1850. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1851. a_call_name(list,upper(name),false);
  1852. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1853. cg.a_reg_alloc(list,NR_R24);
  1854. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  1855. cg.a_reg_dealloc(list,NR_R24);
  1856. paraloc2.done;
  1857. paraloc1.done;
  1858. end;
  1859. end
  1860. else if size in [OS_16,OS_S16] then
  1861. begin
  1862. if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1863. ((not check_overflow) or
  1864. (size=OS_16)) then
  1865. begin
  1866. if check_overflow then
  1867. begin
  1868. current_asmdata.getjumplabel(hl);
  1869. current_asmdata.getjumplabel(no_overflow);
  1870. end;
  1871. cg.a_reg_alloc(list,NR_R0);
  1872. cg.a_reg_alloc(list,NR_R1);
  1873. list.concat(taicpu.op_reg_reg(A_MUL,src2,src1));
  1874. emit_mov(list,dst,NR_R0);
  1875. emit_mov(list,GetNextReg(dst),NR_R1);
  1876. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),src2));
  1877. perform_r1_check(hl);
  1878. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  1879. perform_ovf_check(hl);
  1880. list.concat(taicpu.op_reg_reg(A_MUL,src1,GetNextReg(src2)));
  1881. perform_r1_check(hl);
  1882. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  1883. perform_ovf_check(hl);
  1884. if check_overflow then
  1885. begin
  1886. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),GetNextReg(src2)));
  1887. perform_r1_check(hl,NR_R0);
  1888. end;
  1889. cg.a_reg_dealloc(list,NR_R0);
  1890. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1891. if check_overflow then
  1892. begin
  1893. {
  1894. CLV/CLC
  1895. JMP no_overflow
  1896. .hl:
  1897. CLR R1
  1898. SEV/SEC
  1899. .no_overflow:
  1900. }
  1901. if op=OP_MUL then
  1902. list.concat(taicpu.op_none(A_CLC))
  1903. else
  1904. list.concat(taicpu.op_none(A_CLV));
  1905. a_jmp_always(list,no_overflow);
  1906. a_label(list,hl);
  1907. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1908. if op=OP_MUL then
  1909. list.concat(taicpu.op_none(A_SEC))
  1910. else
  1911. list.concat(taicpu.op_none(A_SEV));
  1912. a_label(list,no_overflow);
  1913. ovloc.loc:=LOC_FLAGS;
  1914. end;
  1915. cg.a_reg_dealloc(list,NR_R1);
  1916. end
  1917. else
  1918. begin
  1919. if size=OS_16 then
  1920. name:='fpc_mul_word'
  1921. else
  1922. name:='fpc_mul_integer';
  1923. if check_overflow then
  1924. name:=name+'_checkoverflow';
  1925. pd:=search_system_proc(name);
  1926. paraloc1.init;
  1927. paraloc2.init;
  1928. paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1929. paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1930. a_load_reg_cgpara(list,OS_16,src1,paraloc2);
  1931. a_load_reg_cgpara(list,OS_16,src2,paraloc1);
  1932. paramanager.freecgpara(list,paraloc2);
  1933. paramanager.freecgpara(list,paraloc1);
  1934. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1935. a_call_name(list,upper(name),false);
  1936. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1937. cg.a_reg_alloc(list,NR_R24);
  1938. cg.a_reg_alloc(list,NR_R25);
  1939. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  1940. cg.a_reg_dealloc(list,NR_R24);
  1941. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R25,GetNextReg(dst));
  1942. cg.a_reg_dealloc(list,NR_R25);
  1943. paraloc2.done;
  1944. paraloc1.done;
  1945. end;
  1946. end
  1947. else
  1948. internalerror(2011022002);
  1949. end;
  1950. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1951. var
  1952. regs : tcpuregisterset;
  1953. reg : tsuperregister;
  1954. begin
  1955. if current_procinfo.procdef.isempty then
  1956. exit;
  1957. if (po_interrupt in current_procinfo.procdef.procoptions) and
  1958. (not nostackframe) then
  1959. begin
  1960. { check if the framepointer is actually used, this is done here because
  1961. we have to know the size of the locals (must be 0), avr does not know
  1962. an sp based stack }
  1963. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1964. (localsize=0) then
  1965. current_procinfo.framepointer:=NR_NO;
  1966. { save int registers,
  1967. but only if the procedure returns }
  1968. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1969. regs:=rg[R_INTREGISTER].used_in_proc
  1970. else
  1971. regs:=[];
  1972. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1973. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1974. an outer stackframe }
  1975. if current_procinfo.framepointer<>NR_NO then
  1976. regs:=regs+[RS_R28,RS_R29];
  1977. { we clear r1 }
  1978. include(regs,getsupreg(GetDefaultZeroReg));
  1979. regs:=regs+[getsupreg(GetDefaultTmpReg)];
  1980. if current_settings.cputype=cpu_avr1 then
  1981. message1(cg_w_interrupt_does_not_save_registers,current_procinfo.procdef.fullprocname(false))
  1982. else
  1983. begin
  1984. for reg:=RS_R31 downto RS_R0 do
  1985. if reg in regs then
  1986. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1987. { Save SREG }
  1988. cg.getcpuregister(list,GetDefaultTmpReg);
  1989. list.concat(taicpu.op_reg_const(A_IN, GetDefaultTmpReg, $3F));
  1990. list.concat(taicpu.op_reg(A_PUSH, GetDefaultTmpReg));
  1991. cg.ungetcpuregister(list,GetDefaultTmpReg);
  1992. end;
  1993. list.concat(taicpu.op_reg(A_CLR,GetDefaultZeroReg));
  1994. if current_procinfo.framepointer<>NR_NO then
  1995. begin
  1996. cg.getcpuregister(list,NR_R28);
  1997. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1998. cg.getcpuregister(list,NR_R29);
  1999. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  2000. a_adjust_sp(list,-localsize);
  2001. end;
  2002. end
  2003. else if not(nostackframe) then
  2004. begin
  2005. { check if the framepointer is actually used, this is done here because
  2006. we have to know the size of the locals (must be 0), avr does not know
  2007. an sp based stack }
  2008. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  2009. (localsize=0) then
  2010. current_procinfo.framepointer:=NR_NO;
  2011. { save int registers,
  2012. but only if the procedure returns }
  2013. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  2014. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)
  2015. else
  2016. regs:=[];
  2017. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  2018. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  2019. an outer stackframe }
  2020. if current_procinfo.framepointer<>NR_NO then
  2021. regs:=regs+[RS_R28,RS_R29];
  2022. for reg:=RS_R31 downto RS_R0 do
  2023. if reg in regs then
  2024. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2025. if current_procinfo.framepointer<>NR_NO then
  2026. begin
  2027. cg.getcpuregister(list,NR_R28);
  2028. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  2029. cg.getcpuregister(list,NR_R29);
  2030. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  2031. a_adjust_sp(list,-localsize);
  2032. end;
  2033. end;
  2034. end;
  2035. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  2036. var
  2037. regs : tcpuregisterset;
  2038. reg : TSuperRegister;
  2039. LocalSize : longint;
  2040. begin
  2041. { every byte counts for avr, so if a subroutine is marked as non-returning, we do
  2042. not generate any exit code, so we really trust the noreturn directive
  2043. }
  2044. if po_noreturn in current_procinfo.procdef.procoptions then
  2045. exit;
  2046. if po_interrupt in current_procinfo.procdef.procoptions then
  2047. begin
  2048. if not(current_procinfo.procdef.isempty) and
  2049. (not nostackframe) then
  2050. begin
  2051. regs:=rg[R_INTREGISTER].used_in_proc;
  2052. if current_procinfo.framepointer<>NR_NO then
  2053. begin
  2054. regs:=regs+[RS_R28,RS_R29];
  2055. LocalSize:=current_procinfo.calc_stackframe_size;
  2056. a_adjust_sp(list,LocalSize);
  2057. end;
  2058. { we clear r1 }
  2059. include(regs,getsupreg(GetDefaultZeroReg));
  2060. if current_settings.cputype<>cpu_avr1 then
  2061. begin
  2062. { Reload SREG }
  2063. regs:=regs+[getsupreg(GetDefaultTmpReg)];
  2064. cg.getcpuregister(list,GetDefaultTmpReg);
  2065. list.concat(taicpu.op_reg(A_POP, GetDefaultTmpReg));
  2066. list.concat(taicpu.op_const_reg(A_OUT, $3F, GetDefaultTmpReg));
  2067. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2068. for reg:=RS_R0 to RS_R31 do
  2069. if reg in regs then
  2070. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2071. end;
  2072. end;
  2073. list.concat(taicpu.op_none(A_RETI));
  2074. end
  2075. else if not(nostackframe) and not(current_procinfo.procdef.isempty) then
  2076. begin
  2077. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  2078. if current_procinfo.framepointer<>NR_NO then
  2079. begin
  2080. regs:=regs+[RS_R28,RS_R29];
  2081. LocalSize:=current_procinfo.calc_stackframe_size;
  2082. a_adjust_sp(list,LocalSize);
  2083. end;
  2084. for reg:=RS_R0 to RS_R31 do
  2085. if reg in regs then
  2086. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2087. list.concat(taicpu.op_none(A_RET));
  2088. end
  2089. else
  2090. list.concat(taicpu.op_none(A_RET));
  2091. end;
  2092. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  2093. var
  2094. tmpref : treference;
  2095. begin
  2096. if ref.addressmode<>AM_UNCHANGED then
  2097. internalerror(2011021701);
  2098. if assigned(ref.symbol) or (ref.offset<>0) then
  2099. begin
  2100. reference_reset(tmpref,0,[]);
  2101. tmpref.symbol:=ref.symbol;
  2102. tmpref.offset:=ref.offset;
  2103. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  2104. tmpref.refaddr:=addr_lo8_gs
  2105. else
  2106. tmpref.refaddr:=addr_lo8;
  2107. list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  2108. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  2109. tmpref.refaddr:=addr_hi8_gs
  2110. else
  2111. tmpref.refaddr:=addr_hi8;
  2112. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  2113. if (ref.base<>NR_NO) then
  2114. begin
  2115. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  2116. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  2117. end;
  2118. if (ref.index<>NR_NO) then
  2119. begin
  2120. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  2121. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  2122. end;
  2123. end
  2124. else if (ref.base<>NR_NO)then
  2125. begin
  2126. emit_mov(list,r,ref.base);
  2127. emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  2128. if (ref.index<>NR_NO) then
  2129. begin
  2130. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  2131. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  2132. end;
  2133. end
  2134. else if (ref.index<>NR_NO) then
  2135. begin
  2136. emit_mov(list,r,ref.index);
  2137. emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  2138. end;
  2139. end;
  2140. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  2141. begin
  2142. internalerror(2011021320);
  2143. end;
  2144. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  2145. var
  2146. paraloc1,paraloc2,paraloc3 : TCGPara;
  2147. pd : tprocdef;
  2148. begin
  2149. pd:=search_system_proc('MOVE');
  2150. paraloc1.init;
  2151. paraloc2.init;
  2152. paraloc3.init;
  2153. paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  2154. paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  2155. paramanager.getcgtempparaloc(list,pd,3,paraloc3);
  2156. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  2157. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  2158. a_loadaddr_ref_cgpara(list,source,paraloc1);
  2159. paramanager.freecgpara(list,paraloc3);
  2160. paramanager.freecgpara(list,paraloc2);
  2161. paramanager.freecgpara(list,paraloc1);
  2162. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  2163. a_call_name_static(list,'FPC_MOVE');
  2164. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  2165. paraloc3.done;
  2166. paraloc2.done;
  2167. paraloc1.done;
  2168. end;
  2169. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  2170. var
  2171. countreg,tmpreg,tmpreg2: tregister;
  2172. srcref,dstref : treference;
  2173. copysize,countregsize : tcgsize;
  2174. l : TAsmLabel;
  2175. i : longint;
  2176. SrcQuickRef, DestQuickRef : Boolean;
  2177. begin
  2178. if len>16 then
  2179. begin
  2180. current_asmdata.getjumplabel(l);
  2181. reference_reset(srcref,source.alignment,source.volatility);
  2182. reference_reset(dstref,dest.alignment,source.volatility);
  2183. srcref.base:=NR_R30;
  2184. srcref.addressmode:=AM_POSTINCREMENT;
  2185. dstref.base:=NR_R26;
  2186. dstref.addressmode:=AM_POSTINCREMENT;
  2187. copysize:=OS_8;
  2188. if len<256 then
  2189. countregsize:=OS_8
  2190. else if len<65536 then
  2191. countregsize:=OS_16
  2192. else
  2193. internalerror(2011022007);
  2194. countreg:=getintregister(list,countregsize);
  2195. a_load_const_reg(list,countregsize,len,countreg);
  2196. cg.getcpuregister(list,NR_R30);
  2197. cg.getcpuregister(list,NR_R31);
  2198. a_loadaddr_ref_reg(list,source,NR_R30);
  2199. { only base or index register in dest? }
  2200. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  2201. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  2202. begin
  2203. if dest.base<>NR_NO then
  2204. tmpreg:=dest.base
  2205. else if dest.index<>NR_NO then
  2206. tmpreg:=dest.index
  2207. else
  2208. internalerror(2016112001);
  2209. end
  2210. else
  2211. begin
  2212. tmpreg:=getaddressregister(list);
  2213. a_loadaddr_ref_reg(list,dest,tmpreg);
  2214. end;
  2215. { X is used for spilling code so we can load it
  2216. only by a push/pop sequence, this can be
  2217. optimized later on by the peephole optimizer
  2218. }
  2219. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  2220. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  2221. cg.getcpuregister(list,NR_R27);
  2222. list.concat(taicpu.op_reg(A_POP,NR_R27));
  2223. cg.getcpuregister(list,NR_R26);
  2224. list.concat(taicpu.op_reg(A_POP,NR_R26));
  2225. cg.a_label(list,l);
  2226. cg.getcpuregister(list,GetDefaultTmpReg);
  2227. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2228. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2229. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2230. if tcgsize2size[countregsize] = 1 then
  2231. list.concat(taicpu.op_reg(A_DEC,countreg))
  2232. else
  2233. begin
  2234. list.concat(taicpu.op_reg_const(A_SUBI,countreg,1));
  2235. list.concat(taicpu.op_reg_reg(A_SBC,GetNextReg(countreg),GetDefaultZeroReg));
  2236. end;
  2237. a_jmp_flags(list,F_NE,l);
  2238. cg.ungetcpuregister(list,NR_R26);
  2239. cg.ungetcpuregister(list,NR_R27);
  2240. cg.ungetcpuregister(list,NR_R30);
  2241. cg.ungetcpuregister(list,NR_R31);
  2242. { keep registers alive }
  2243. a_reg_sync(list,countreg);
  2244. end
  2245. else
  2246. begin
  2247. SrcQuickRef:=false;
  2248. DestQuickRef:=false;
  2249. if ((CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) and
  2250. not((source.Base=NR_NO) and (source.Index=NR_NO) and (source.symbol=nil) and (source.Offset in [0..192-len]))) or
  2251. (
  2252. not((source.addressmode=AM_UNCHANGED) and
  2253. (source.symbol=nil) and
  2254. ((source.base=NR_R28) or
  2255. (source.base=NR_R30)) and
  2256. (source.Index=NR_NO) and
  2257. (source.Offset in [0..64-len])) and
  2258. not((source.Base=NR_NO) and (source.Index=NR_NO))
  2259. ) then
  2260. begin
  2261. cg.getcpuregister(list,NR_R30);
  2262. cg.getcpuregister(list,NR_R31);
  2263. srcref:=normalize_ref(list,source,NR_R30);
  2264. end
  2265. else
  2266. begin
  2267. SrcQuickRef:=true;
  2268. srcref:=source;
  2269. end;
  2270. if ((CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) and
  2271. not((dest.Base=NR_NO) and (dest.Index=NR_NO) and (dest.symbol=nil) and (dest.Offset in [0..192-len]))) or
  2272. (
  2273. not((dest.addressmode=AM_UNCHANGED) and
  2274. (dest.symbol=nil) and
  2275. ((dest.base=NR_R28) or
  2276. (dest.base=NR_R30)) and
  2277. (dest.Index=NR_No) and
  2278. (dest.Offset in [0..64-len])) and
  2279. not((dest.Base=NR_NO) and (dest.Index=NR_NO))
  2280. ) then
  2281. begin
  2282. if not(SrcQuickRef) then
  2283. begin
  2284. { only base or index register in dest? }
  2285. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  2286. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  2287. begin
  2288. if dest.base<>NR_NO then
  2289. tmpreg:=dest.base
  2290. else if dest.index<>NR_NO then
  2291. tmpreg:=dest.index
  2292. else
  2293. internalerror(2016112002);
  2294. end
  2295. else
  2296. tmpreg:=getaddressregister(list);
  2297. dstref:=normalize_ref(list,dest,tmpreg);
  2298. { X is used for spilling code so we can load it
  2299. only by a push/pop sequence, this can be
  2300. optimized later on by the peephole optimizer
  2301. }
  2302. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  2303. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  2304. cg.getcpuregister(list,NR_R27);
  2305. list.concat(taicpu.op_reg(A_POP,NR_R27));
  2306. cg.getcpuregister(list,NR_R26);
  2307. list.concat(taicpu.op_reg(A_POP,NR_R26));
  2308. dstref.base:=NR_R26;
  2309. end
  2310. else
  2311. begin
  2312. cg.getcpuregister(list,NR_R30);
  2313. cg.getcpuregister(list,NR_R31);
  2314. dstref:=normalize_ref(list,dest,NR_R30);
  2315. end;
  2316. end
  2317. else
  2318. begin
  2319. DestQuickRef:=true;
  2320. dstref:=dest;
  2321. end;
  2322. // CC
  2323. // If dest is an ioreg (31 < offset < srambase) and size = 16 bit then
  2324. // write high byte first, then low byte
  2325. // but not for avrxmega3
  2326. if (len = 2) and DestQuickRef and (current_settings.cputype <> cpu_avrxmega3) and
  2327. (dest.offset > 31) and
  2328. (dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  2329. begin
  2330. // If src is also a 16 bit ioreg then read low byte then high byte
  2331. if SrcQuickRef and (srcref.offset > 31)
  2332. and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  2333. begin
  2334. // First read source into temp registers
  2335. tmpreg:=getintregister(list, OS_16);
  2336. list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg,srcref));
  2337. inc(srcref.offset);
  2338. tmpreg2:=GetNextReg(tmpreg);
  2339. list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg2,srcref));
  2340. // then move temp registers to dest in reverse order
  2341. inc(dstref.offset);
  2342. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg2));
  2343. dec(dstref.offset);
  2344. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg));
  2345. end
  2346. else
  2347. begin
  2348. srcref.addressmode:=AM_UNCHANGED;
  2349. inc(srcref.offset);
  2350. dstref.addressmode:=AM_UNCHANGED;
  2351. inc(dstref.offset);
  2352. cg.getcpuregister(list,GetDefaultTmpReg);
  2353. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2354. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2355. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2356. if not(SrcQuickRef) then
  2357. srcref.addressmode:=AM_POSTINCREMENT
  2358. else
  2359. srcref.addressmode:=AM_UNCHANGED;
  2360. dec(srcref.offset);
  2361. dec(dstref.offset);
  2362. cg.getcpuregister(list,GetDefaultTmpReg);
  2363. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2364. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2365. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2366. end;
  2367. end
  2368. else
  2369. for i:=1 to len do
  2370. begin
  2371. if not(SrcQuickRef) and (i<len) then
  2372. srcref.addressmode:=AM_POSTINCREMENT
  2373. else
  2374. srcref.addressmode:=AM_UNCHANGED;
  2375. if not(DestQuickRef) and (i<len) then
  2376. dstref.addressmode:=AM_POSTINCREMENT
  2377. else
  2378. dstref.addressmode:=AM_UNCHANGED;
  2379. cg.getcpuregister(list,GetDefaultTmpReg);
  2380. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2381. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2382. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2383. if SrcQuickRef then
  2384. inc(srcref.offset);
  2385. if DestQuickRef then
  2386. inc(dstref.offset);
  2387. end;
  2388. if not(SrcQuickRef) then
  2389. begin
  2390. ungetcpuregister(list,srcref.base);
  2391. ungetcpuregister(list,TRegister(ord(srcref.base)+1));
  2392. end;
  2393. if not(DestQuickRef) then
  2394. begin
  2395. ungetcpuregister(list,dstref.base);
  2396. ungetcpuregister(list,TRegister(ord(dstref.base)+1));
  2397. end;
  2398. end;
  2399. end;
  2400. procedure tcgavr.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2401. var
  2402. hl : tasmlabel;
  2403. ai : taicpu;
  2404. cond : TAsmCond;
  2405. begin
  2406. if not(cs_check_overflow in current_settings.localswitches) then
  2407. exit;
  2408. current_asmdata.getjumplabel(hl);
  2409. if not ((def.typ=pointerdef) or
  2410. ((def.typ=orddef) and
  2411. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2412. pasbool1,pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2413. cond:=C_VC
  2414. else
  2415. cond:=C_CC;
  2416. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2417. ai.SetCondition(cond);
  2418. ai.is_jmp:=true;
  2419. list.concat(ai);
  2420. a_call_name(list,'FPC_OVERFLOW',false);
  2421. a_label(list,hl);
  2422. end;
  2423. procedure tcgavr.g_overflowCheck_loc(List: TAsmList; const Loc: TLocation; def: TDef; ovloc: tlocation);
  2424. var
  2425. hl : tasmlabel;
  2426. ai : taicpu;
  2427. cond : TAsmCond;
  2428. begin
  2429. if not(cs_check_overflow in current_settings.localswitches) then
  2430. exit;
  2431. case ovloc.loc of
  2432. LOC_FLAGS:
  2433. begin
  2434. current_asmdata.getjumplabel(hl);
  2435. if not ((def.typ=pointerdef) or
  2436. ((def.typ=orddef) and
  2437. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2438. pasbool1,pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2439. cond:=C_VC
  2440. else
  2441. cond:=C_CC;
  2442. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2443. ai.SetCondition(cond);
  2444. ai.is_jmp:=true;
  2445. list.concat(ai);
  2446. a_call_name(list,'FPC_OVERFLOW',false);
  2447. a_label(list,hl);
  2448. end;
  2449. end;
  2450. end;
  2451. procedure tcgavr.g_save_registers(list: TAsmList);
  2452. begin
  2453. { this is done by the entry code }
  2454. end;
  2455. procedure tcgavr.g_restore_registers(list: TAsmList);
  2456. begin
  2457. { this is done by the exit code }
  2458. end;
  2459. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2460. var
  2461. ai1,ai2 : taicpu;
  2462. hl : TAsmLabel;
  2463. begin
  2464. ai1:=Taicpu.Op_sym(A_BRxx,l);
  2465. ai1.is_jmp:=true;
  2466. hl:=nil;
  2467. case cond of
  2468. OC_EQ:
  2469. ai1.SetCondition(C_EQ);
  2470. OC_GT:
  2471. begin
  2472. { emulate GT }
  2473. current_asmdata.getjumplabel(hl);
  2474. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2475. ai2.SetCondition(C_EQ);
  2476. ai2.is_jmp:=true;
  2477. list.concat(ai2);
  2478. ai1.SetCondition(C_GE);
  2479. end;
  2480. OC_LT:
  2481. ai1.SetCondition(C_LT);
  2482. OC_GTE:
  2483. ai1.SetCondition(C_GE);
  2484. OC_LTE:
  2485. begin
  2486. { emulate LTE }
  2487. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2488. ai2.SetCondition(C_EQ);
  2489. ai2.is_jmp:=true;
  2490. list.concat(ai2);
  2491. ai1.SetCondition(C_LT);
  2492. end;
  2493. OC_NE:
  2494. ai1.SetCondition(C_NE);
  2495. OC_BE:
  2496. begin
  2497. { emulate BE }
  2498. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2499. ai2.SetCondition(C_EQ);
  2500. ai2.is_jmp:=true;
  2501. list.concat(ai2);
  2502. ai1.SetCondition(C_LO);
  2503. end;
  2504. OC_B:
  2505. ai1.SetCondition(C_LO);
  2506. OC_AE:
  2507. ai1.SetCondition(C_SH);
  2508. OC_A:
  2509. begin
  2510. { emulate A (unsigned GT) }
  2511. current_asmdata.getjumplabel(hl);
  2512. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2513. ai2.SetCondition(C_EQ);
  2514. ai2.is_jmp:=true;
  2515. list.concat(ai2);
  2516. ai1.SetCondition(C_SH);
  2517. end;
  2518. else
  2519. internalerror(2011082501);
  2520. end;
  2521. list.concat(ai1);
  2522. if assigned(hl) then
  2523. a_label(list,hl);
  2524. end;
  2525. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2526. var
  2527. instr: taicpu;
  2528. begin
  2529. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  2530. list.Concat(instr);
  2531. { Notify the register allocator that we have written a move instruction so
  2532. it can try to eliminate it. }
  2533. add_move_instruction(instr);
  2534. end;
  2535. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2536. begin
  2537. if not(size in [OS_S64,OS_64]) then
  2538. internalerror(2012102402);
  2539. tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2540. end;
  2541. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2542. begin
  2543. tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2544. end;
  2545. procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize;value: int64;src,dst : tregister64);
  2546. begin
  2547. if op in [OP_SHL,OP_SHR] then
  2548. tcgavr(cg).a_op_const_reg_reg_internal(list,Op,size,value,src.reglo,src.reghi,dst.reglo,dst.reghi)
  2549. else
  2550. Inherited a_op64_const_reg_reg(list,op,size,value,src,dst);
  2551. end;
  2552. procedure create_codegen;
  2553. begin
  2554. cg:=tcgavr.create;
  2555. cg64:=tcg64favr.create;
  2556. end;
  2557. end.