cgcpu.pas 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883
  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,src,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. if (fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31)
  1230. and (href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  1231. begin
  1232. tmpreg:=GetNextReg(reg);
  1233. href.addressmode:=AM_UNCHANGED;
  1234. inc(href.offset);
  1235. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1236. dec(href.offset);
  1237. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1238. end
  1239. else
  1240. begin
  1241. for i:=1 to tcgsize2size[fromsize] do
  1242. begin
  1243. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1244. href.addressmode:=AM_POSTINCREMENT
  1245. else
  1246. href.addressmode:=AM_UNCHANGED;
  1247. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1248. if QuickRef then
  1249. inc(href.offset);
  1250. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1251. if i<tcgsize2size[fromsize] then
  1252. reg:=GetNextReg(reg);
  1253. end;
  1254. end;
  1255. end;
  1256. if not(QuickRef) or ungetcpuregister_z then
  1257. begin
  1258. ungetcpuregister(list,href.base);
  1259. ungetcpuregister(list,GetNextReg(href.base));
  1260. end;
  1261. end;
  1262. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1263. const Ref : treference;reg : tregister);
  1264. var
  1265. href : treference;
  1266. conv_done: boolean;
  1267. tmpreg : tregister;
  1268. i : integer;
  1269. QuickRef,ungetcpuregister_z: boolean;
  1270. begin
  1271. QuickRef:=false;
  1272. ungetcpuregister_z:=false;
  1273. href:=Ref;
  1274. { ensure, href.base contains a valid register if there is any register used }
  1275. if href.base=NR_NO then
  1276. begin
  1277. href.base:=href.index;
  1278. href.index:=NR_NO;
  1279. end;
  1280. { try to use ldd/lds }
  1281. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1282. begin
  1283. if not((href.addressmode=AM_UNCHANGED) and
  1284. (href.symbol=nil) and
  1285. (href.Index=NR_NO) and
  1286. (href.Offset in [0..64-tcgsize2size[fromsize]])) or
  1287. (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  1288. begin
  1289. href:=normalize_ref(list,href,NR_R30);
  1290. getcpuregister(list,NR_R30);
  1291. getcpuregister(list,NR_R31);
  1292. ungetcpuregister_z:=true;
  1293. end
  1294. else
  1295. begin
  1296. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1297. begin
  1298. getcpuregister(list,NR_R30);
  1299. emit_mov(list,NR_R30,href.base);
  1300. getcpuregister(list,NR_R31);
  1301. emit_mov(list,NR_R31,GetNextReg(href.base));
  1302. href.base:=NR_R30;
  1303. ungetcpuregister_z:=true;
  1304. end;
  1305. QuickRef:=true;
  1306. end;
  1307. end
  1308. else
  1309. QuickRef:=true;
  1310. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1311. internalerror(2011021307);
  1312. conv_done:=false;
  1313. if tosize<>fromsize then
  1314. begin
  1315. conv_done:=true;
  1316. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1317. fromsize:=tosize;
  1318. case fromsize of
  1319. OS_8:
  1320. begin
  1321. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1322. for i:=2 to tcgsize2size[tosize] do
  1323. begin
  1324. reg:=GetNextReg(reg);
  1325. emit_mov(list,reg,GetDefaultZeroReg);
  1326. end;
  1327. end;
  1328. OS_S8:
  1329. begin
  1330. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1331. tmpreg:=reg;
  1332. if tcgsize2size[tosize]>1 then
  1333. begin
  1334. reg:=GetNextReg(reg);
  1335. emit_mov(list,reg,GetDefaultZeroReg);
  1336. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1337. list.concat(taicpu.op_reg(A_COM,reg));
  1338. tmpreg:=reg;
  1339. for i:=3 to tcgsize2size[tosize] do
  1340. begin
  1341. reg:=GetNextReg(reg);
  1342. emit_mov(list,reg,tmpreg);
  1343. end;
  1344. end;
  1345. end;
  1346. OS_16:
  1347. begin
  1348. if not(QuickRef) then
  1349. href.addressmode:=AM_POSTINCREMENT;
  1350. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1351. if QuickRef then
  1352. inc(href.offset);
  1353. href.addressmode:=AM_UNCHANGED;
  1354. reg:=GetNextReg(reg);
  1355. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1356. for i:=3 to tcgsize2size[tosize] do
  1357. begin
  1358. reg:=GetNextReg(reg);
  1359. emit_mov(list,reg,GetDefaultZeroReg);
  1360. end;
  1361. end;
  1362. OS_S16:
  1363. begin
  1364. if not(QuickRef) then
  1365. href.addressmode:=AM_POSTINCREMENT;
  1366. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1367. if QuickRef then
  1368. inc(href.offset);
  1369. href.addressmode:=AM_UNCHANGED;
  1370. reg:=GetNextReg(reg);
  1371. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1372. tmpreg:=reg;
  1373. reg:=GetNextReg(reg);
  1374. emit_mov(list,reg,GetDefaultZeroReg);
  1375. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1376. list.concat(taicpu.op_reg(A_COM,reg));
  1377. tmpreg:=reg;
  1378. for i:=4 to tcgsize2size[tosize] do
  1379. begin
  1380. reg:=GetNextReg(reg);
  1381. emit_mov(list,reg,tmpreg);
  1382. end;
  1383. end;
  1384. else
  1385. conv_done:=false;
  1386. end;
  1387. end;
  1388. if not conv_done then
  1389. begin
  1390. for i:=1 to tcgsize2size[fromsize] do
  1391. begin
  1392. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1393. href.addressmode:=AM_POSTINCREMENT
  1394. else
  1395. href.addressmode:=AM_UNCHANGED;
  1396. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1397. if QuickRef then
  1398. inc(href.offset);
  1399. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1400. if i<tcgsize2size[fromsize] then
  1401. reg:=GetNextReg(reg);
  1402. end;
  1403. end;
  1404. if ungetcpuregister_z then
  1405. begin
  1406. ungetcpuregister(list,href.base);
  1407. ungetcpuregister(list,GetNextReg(href.base));
  1408. end;
  1409. end;
  1410. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1411. var
  1412. conv_done: boolean;
  1413. tmpreg : tregister;
  1414. i : integer;
  1415. begin
  1416. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1417. internalerror(2011021310);
  1418. conv_done:=false;
  1419. if tosize<>fromsize then
  1420. begin
  1421. conv_done:=true;
  1422. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1423. fromsize:=tosize;
  1424. case fromsize of
  1425. OS_8:
  1426. begin
  1427. emit_mov(list,reg2,reg1);
  1428. for i:=2 to tcgsize2size[tosize] do
  1429. begin
  1430. reg2:=GetNextReg(reg2);
  1431. emit_mov(list,reg2,GetDefaultZeroReg);
  1432. end;
  1433. end;
  1434. OS_S8:
  1435. begin
  1436. emit_mov(list,reg2,reg1);
  1437. if tcgsize2size[tosize]>1 then
  1438. begin
  1439. reg2:=GetNextReg(reg2);
  1440. emit_mov(list,reg2,GetDefaultZeroReg);
  1441. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1442. list.concat(taicpu.op_reg(A_COM,reg2));
  1443. tmpreg:=reg2;
  1444. for i:=3 to tcgsize2size[tosize] do
  1445. begin
  1446. reg2:=GetNextReg(reg2);
  1447. emit_mov(list,reg2,tmpreg);
  1448. end;
  1449. end;
  1450. end;
  1451. OS_16:
  1452. begin
  1453. emit_mov(list,reg2,reg1);
  1454. reg1:=GetNextReg(reg1);
  1455. reg2:=GetNextReg(reg2);
  1456. emit_mov(list,reg2,reg1);
  1457. for i:=3 to tcgsize2size[tosize] do
  1458. begin
  1459. reg2:=GetNextReg(reg2);
  1460. emit_mov(list,reg2,GetDefaultZeroReg);
  1461. end;
  1462. end;
  1463. OS_S16:
  1464. begin
  1465. emit_mov(list,reg2,reg1);
  1466. reg1:=GetNextReg(reg1);
  1467. reg2:=GetNextReg(reg2);
  1468. emit_mov(list,reg2,reg1);
  1469. if tcgsize2size[tosize]>2 then
  1470. begin
  1471. reg2:=GetNextReg(reg2);
  1472. emit_mov(list,reg2,GetDefaultZeroReg);
  1473. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1474. list.concat(taicpu.op_reg(A_COM,reg2));
  1475. tmpreg:=reg2;
  1476. for i:=4 to tcgsize2size[tosize] do
  1477. begin
  1478. reg2:=GetNextReg(reg2);
  1479. emit_mov(list,reg2,tmpreg);
  1480. end;
  1481. end;
  1482. end;
  1483. else
  1484. conv_done:=false;
  1485. end;
  1486. end;
  1487. if not conv_done and (reg1<>reg2) then
  1488. begin
  1489. for i:=1 to tcgsize2size[fromsize] do
  1490. begin
  1491. emit_mov(list,reg2,reg1);
  1492. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1493. if i<tcgsize2size[fromsize] then
  1494. begin
  1495. reg1:=GetNextReg(reg1);
  1496. reg2:=GetNextReg(reg2);
  1497. end;
  1498. end;
  1499. end;
  1500. end;
  1501. procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1502. begin
  1503. internalerror(2012010702);
  1504. end;
  1505. procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1506. begin
  1507. internalerror(2012010703);
  1508. end;
  1509. procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1510. begin
  1511. internalerror(2012010704);
  1512. end;
  1513. { comparison operations }
  1514. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1515. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1516. var
  1517. swapped , test_msb: boolean;
  1518. tmpreg : tregister;
  1519. i : byte;
  1520. begin
  1521. if a=0 then
  1522. begin
  1523. swapped:=false;
  1524. { swap parameters? }
  1525. case cmp_op of
  1526. OC_GT:
  1527. begin
  1528. swapped:=true;
  1529. cmp_op:=OC_LT;
  1530. end;
  1531. OC_LTE:
  1532. begin
  1533. swapped:=true;
  1534. cmp_op:=OC_GTE;
  1535. end;
  1536. OC_BE:
  1537. begin
  1538. swapped:=true;
  1539. cmp_op:=OC_AE;
  1540. end;
  1541. OC_A:
  1542. begin
  1543. swapped:=true;
  1544. cmp_op:=OC_B;
  1545. end;
  1546. end;
  1547. { If doing a signed test for x<0, we can simply test the sign bit
  1548. of the most significant byte }
  1549. if (cmp_op in [OC_LT,OC_GTE]) and
  1550. (not swapped) then
  1551. begin
  1552. for i:=2 to tcgsize2size[size] do
  1553. reg:=GetNextReg(reg);
  1554. list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
  1555. end
  1556. else
  1557. begin
  1558. if swapped then
  1559. list.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,reg))
  1560. else
  1561. list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
  1562. for i:=2 to tcgsize2size[size] do
  1563. begin
  1564. reg:=GetNextReg(reg);
  1565. if swapped then
  1566. list.concat(taicpu.op_reg_reg(A_CPC,GetDefaultZeroReg,reg))
  1567. else
  1568. list.concat(taicpu.op_reg_reg(A_CPC,reg,GetDefaultZeroReg));
  1569. end;
  1570. end;
  1571. a_jmp_cond(list,cmp_op,l);
  1572. end
  1573. else
  1574. inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1575. end;
  1576. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1577. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1578. var
  1579. swapped : boolean;
  1580. tmpreg : tregister;
  1581. i : byte;
  1582. begin
  1583. swapped:=false;
  1584. { swap parameters? }
  1585. case cmp_op of
  1586. OC_GT:
  1587. begin
  1588. swapped:=true;
  1589. cmp_op:=OC_LT;
  1590. end;
  1591. OC_LTE:
  1592. begin
  1593. swapped:=true;
  1594. cmp_op:=OC_GTE;
  1595. end;
  1596. OC_BE:
  1597. begin
  1598. swapped:=true;
  1599. cmp_op:=OC_AE;
  1600. end;
  1601. OC_A:
  1602. begin
  1603. swapped:=true;
  1604. cmp_op:=OC_B;
  1605. end;
  1606. end;
  1607. if swapped then
  1608. begin
  1609. tmpreg:=reg1;
  1610. reg1:=reg2;
  1611. reg2:=tmpreg;
  1612. end;
  1613. list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1614. for i:=2 to tcgsize2size[size] do
  1615. begin
  1616. reg1:=GetNextReg(reg1);
  1617. reg2:=GetNextReg(reg2);
  1618. list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1619. end;
  1620. a_jmp_cond(list,cmp_op,l);
  1621. end;
  1622. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  1623. var
  1624. ai : taicpu;
  1625. begin
  1626. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1627. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION))
  1628. else
  1629. ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1630. ai.is_jmp:=true;
  1631. list.concat(ai);
  1632. end;
  1633. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  1634. var
  1635. ai : taicpu;
  1636. begin
  1637. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1638. ai:=taicpu.op_sym(A_JMP,l)
  1639. else
  1640. ai:=taicpu.op_sym(A_RJMP,l);
  1641. ai.is_jmp:=true;
  1642. list.concat(ai);
  1643. end;
  1644. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1645. var
  1646. ai : taicpu;
  1647. begin
  1648. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  1649. ai.is_jmp:=true;
  1650. list.concat(ai);
  1651. end;
  1652. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1653. var
  1654. l : TAsmLabel;
  1655. tmpflags : TResFlags;
  1656. i: Integer;
  1657. hreg: TRegister;
  1658. begin
  1659. current_asmdata.getjumplabel(l);
  1660. {
  1661. if flags_to_cond(f) then
  1662. begin
  1663. tmpflags:=f;
  1664. inverse_flags(tmpflags);
  1665. emit_mov(reg,GetDefaultZeroReg);
  1666. a_jmp_flags(list,tmpflags,l);
  1667. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1668. end
  1669. else
  1670. }
  1671. begin
  1672. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1673. hreg:=reg;
  1674. for i:=2 to tcgsize2size[size] do
  1675. begin
  1676. hreg:=GetNextReg(hreg);
  1677. emit_mov(list,hreg,GetDefaultZeroReg);
  1678. end;
  1679. a_jmp_flags(list,f,l);
  1680. emit_mov(list,reg,GetDefaultZeroReg);
  1681. end;
  1682. cg.a_label(list,l);
  1683. end;
  1684. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  1685. var
  1686. i : integer;
  1687. begin
  1688. case value of
  1689. 0:
  1690. ;
  1691. {-14..-1:
  1692. begin
  1693. if ((-value) mod 2)<>0 then
  1694. list.concat(taicpu.op_reg(A_PUSH,GetDefaultTmpReg));
  1695. for i:=1 to (-value) div 2 do
  1696. list.concat(taicpu.op_const(A_RCALL,0));
  1697. end;
  1698. 1..7:
  1699. begin
  1700. for i:=1 to value do
  1701. list.concat(taicpu.op_reg(A_POP,GetDefaultTmpReg));
  1702. end;}
  1703. else
  1704. begin
  1705. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1706. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1707. // get SREG
  1708. list.concat(taicpu.op_reg_const(A_IN,GetDefaultTmpReg,NIO_SREG));
  1709. // block interrupts
  1710. list.concat(taicpu.op_none(A_CLI));
  1711. // write high SP
  1712. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1713. // release interrupts
  1714. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,GetDefaultTmpReg));
  1715. // write low SP
  1716. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1717. end;
  1718. end;
  1719. end;
  1720. function tcgavr.GetLoad(const ref: treference) : tasmop;
  1721. begin
  1722. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1723. result:=A_LDS
  1724. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1725. result:=A_LDD
  1726. else
  1727. result:=A_LD;
  1728. end;
  1729. function tcgavr.GetStore(const ref: treference) : tasmop;
  1730. begin
  1731. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1732. result:=A_STS
  1733. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1734. result:=A_STD
  1735. else
  1736. result:=A_ST;
  1737. end;
  1738. procedure tcgavr.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean; var ovloc: tlocation);
  1739. procedure perform_r1_check(overflow_label: TAsmLabel; other_reg: TRegister=NR_R1);
  1740. var
  1741. ai: taicpu;
  1742. begin
  1743. if check_overflow then
  1744. begin
  1745. list.concat(taicpu.op_reg_reg(A_OR,NR_R1,other_reg));
  1746. ai:=Taicpu.Op_Sym(A_BRxx,overflow_label);
  1747. ai.SetCondition(C_NE);
  1748. ai.is_jmp:=true;
  1749. list.concat(ai);
  1750. end;
  1751. end;
  1752. procedure perform_ovf_check(overflow_label: TAsmLabel);
  1753. var
  1754. ai: taicpu;
  1755. begin
  1756. if check_overflow then
  1757. begin
  1758. ai:=Taicpu.Op_Sym(A_BRxx,overflow_label);
  1759. ai.SetCondition(C_CS);
  1760. ai.is_jmp:=true;
  1761. list.concat(ai);
  1762. end;
  1763. end;
  1764. var
  1765. pd: tprocdef;
  1766. paraloc1, paraloc2: tcgpara;
  1767. ai: taicpu;
  1768. hl, no_overflow: TAsmLabel;
  1769. name: String;
  1770. begin
  1771. ovloc.loc:=LOC_VOID;
  1772. if size in [OS_8,OS_S8] then
  1773. begin
  1774. if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1775. (op=OP_MUL) then
  1776. begin
  1777. cg.a_reg_alloc(list,NR_R0);
  1778. cg.a_reg_alloc(list,NR_R1);
  1779. list.concat(taicpu.op_reg_reg(topcg2asmop[op],src1,src2));
  1780. // Check overflow
  1781. if check_overflow then
  1782. begin
  1783. current_asmdata.getjumplabel(hl);
  1784. list.concat(taicpu.op_reg_reg(A_AND,NR_R1,NR_R1));
  1785. { Clear carry as it's not affected by any of the instructions }
  1786. list.concat(taicpu.op_none(A_CLC));
  1787. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1788. ai.SetCondition(C_EQ);
  1789. ai.is_jmp:=true;
  1790. list.concat(ai);
  1791. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1792. list.concat(taicpu.op_none(A_SEC));
  1793. a_label(list,hl);
  1794. ovloc.loc:=LOC_FLAGS;
  1795. end
  1796. else
  1797. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1798. cg.a_reg_dealloc(list,NR_R1);
  1799. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  1800. cg.a_reg_dealloc(list,NR_R0);
  1801. end
  1802. else if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1803. (op=OP_IMUL) then
  1804. begin
  1805. cg.a_reg_alloc(list,NR_R0);
  1806. cg.a_reg_alloc(list,NR_R1);
  1807. list.concat(taicpu.op_reg_reg(A_MULS,src1,src2));
  1808. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  1809. // Check overflow
  1810. if check_overflow then
  1811. begin
  1812. current_asmdata.getjumplabel(no_overflow);
  1813. list.concat(taicpu.op_reg_const(A_SBRC,NR_R0,7));
  1814. list.concat(taicpu.op_reg(A_INC,NR_R1));
  1815. list.concat(taicpu.op_reg(A_TST,NR_R1));
  1816. ai:=Taicpu.Op_Sym(A_BRxx,no_overflow);
  1817. ai.SetCondition(C_EQ);
  1818. ai.is_jmp:=true;
  1819. list.concat(ai);
  1820. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1821. a_call_name(list,'FPC_OVERFLOW',false);
  1822. a_label(list,no_overflow);
  1823. ovloc.loc:=LOC_VOID;
  1824. end
  1825. else
  1826. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1827. cg.a_reg_dealloc(list,NR_R1);
  1828. cg.a_reg_dealloc(list,NR_R0);
  1829. end
  1830. else
  1831. begin
  1832. if size=OS_8 then
  1833. name:='fpc_mul_byte'
  1834. else
  1835. name:='fpc_mul_shortint';
  1836. if check_overflow then
  1837. name:=name+'_checkoverflow';
  1838. pd:=search_system_proc(name);
  1839. paraloc1.init;
  1840. paraloc2.init;
  1841. paramanager.getintparaloc(list,pd,1,paraloc1);
  1842. paramanager.getintparaloc(list,pd,2,paraloc2);
  1843. a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  1844. a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  1845. paramanager.freecgpara(list,paraloc2);
  1846. paramanager.freecgpara(list,paraloc1);
  1847. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1848. a_call_name(list,upper(name),false);
  1849. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1850. cg.a_reg_alloc(list,NR_R24);
  1851. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  1852. cg.a_reg_dealloc(list,NR_R24);
  1853. paraloc2.done;
  1854. paraloc1.done;
  1855. end;
  1856. end
  1857. else if size in [OS_16,OS_S16] then
  1858. begin
  1859. if (CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype]) and
  1860. ((not check_overflow) or
  1861. (size=OS_16)) then
  1862. begin
  1863. if check_overflow then
  1864. begin
  1865. current_asmdata.getjumplabel(hl);
  1866. current_asmdata.getjumplabel(no_overflow);
  1867. end;
  1868. cg.a_reg_alloc(list,NR_R0);
  1869. cg.a_reg_alloc(list,NR_R1);
  1870. list.concat(taicpu.op_reg_reg(A_MUL,src2,src1));
  1871. emit_mov(list,dst,NR_R0);
  1872. emit_mov(list,GetNextReg(dst),NR_R1);
  1873. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),src2));
  1874. perform_r1_check(hl);
  1875. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  1876. perform_ovf_check(hl);
  1877. list.concat(taicpu.op_reg_reg(A_MUL,src1,GetNextReg(src2)));
  1878. perform_r1_check(hl);
  1879. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  1880. perform_ovf_check(hl);
  1881. if check_overflow then
  1882. begin
  1883. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(src1),GetNextReg(src2)));
  1884. perform_r1_check(hl,NR_R0);
  1885. end;
  1886. cg.a_reg_dealloc(list,NR_R0);
  1887. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1888. if check_overflow then
  1889. begin
  1890. {
  1891. CLV/CLC
  1892. JMP no_overflow
  1893. .hl:
  1894. CLR R1
  1895. SEV/SEC
  1896. .no_overflow:
  1897. }
  1898. if op=OP_MUL then
  1899. list.concat(taicpu.op_none(A_CLC))
  1900. else
  1901. list.concat(taicpu.op_none(A_CLV));
  1902. a_jmp_always(list,no_overflow);
  1903. a_label(list,hl);
  1904. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1905. if op=OP_MUL then
  1906. list.concat(taicpu.op_none(A_SEC))
  1907. else
  1908. list.concat(taicpu.op_none(A_SEV));
  1909. a_label(list,no_overflow);
  1910. ovloc.loc:=LOC_FLAGS;
  1911. end;
  1912. cg.a_reg_dealloc(list,NR_R1);
  1913. end
  1914. else
  1915. begin
  1916. if size=OS_16 then
  1917. name:='fpc_mul_word'
  1918. else
  1919. name:='fpc_mul_integer';
  1920. if check_overflow then
  1921. name:=name+'_checkoverflow';
  1922. pd:=search_system_proc(name);
  1923. paraloc1.init;
  1924. paraloc2.init;
  1925. paramanager.getintparaloc(list,pd,1,paraloc1);
  1926. paramanager.getintparaloc(list,pd,2,paraloc2);
  1927. a_load_reg_cgpara(list,OS_16,src1,paraloc2);
  1928. a_load_reg_cgpara(list,OS_16,src2,paraloc1);
  1929. paramanager.freecgpara(list,paraloc2);
  1930. paramanager.freecgpara(list,paraloc1);
  1931. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1932. a_call_name(list,upper(name),false);
  1933. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1934. cg.a_reg_alloc(list,NR_R24);
  1935. cg.a_reg_alloc(list,NR_R25);
  1936. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  1937. cg.a_reg_dealloc(list,NR_R24);
  1938. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R25,GetNextReg(dst));
  1939. cg.a_reg_dealloc(list,NR_R25);
  1940. paraloc2.done;
  1941. paraloc1.done;
  1942. end;
  1943. end
  1944. else
  1945. internalerror(2011022002);
  1946. end;
  1947. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1948. var
  1949. regs : tcpuregisterset;
  1950. reg : tsuperregister;
  1951. begin
  1952. if current_procinfo.procdef.isempty then
  1953. exit;
  1954. if (po_interrupt in current_procinfo.procdef.procoptions) and
  1955. (not nostackframe) then
  1956. begin
  1957. { check if the framepointer is actually used, this is done here because
  1958. we have to know the size of the locals (must be 0), avr does not know
  1959. an sp based stack }
  1960. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1961. (localsize=0) then
  1962. current_procinfo.framepointer:=NR_NO;
  1963. { save int registers,
  1964. but only if the procedure returns }
  1965. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1966. regs:=rg[R_INTREGISTER].used_in_proc
  1967. else
  1968. regs:=[];
  1969. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1970. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1971. an outer stackframe }
  1972. if current_procinfo.framepointer<>NR_NO then
  1973. regs:=regs+[RS_R28,RS_R29];
  1974. { we clear r1 }
  1975. include(regs,RS_R1);
  1976. regs:=regs+[RS_R0];
  1977. for reg:=RS_R31 downto RS_R0 do
  1978. if reg in regs then
  1979. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1980. { Save SREG }
  1981. cg.getcpuregister(list,GetDefaultTmpReg);
  1982. list.concat(taicpu.op_reg_const(A_IN, GetDefaultTmpReg, $3F));
  1983. list.concat(taicpu.op_reg(A_PUSH, GetDefaultTmpReg));
  1984. cg.ungetcpuregister(list,GetDefaultTmpReg);
  1985. list.concat(taicpu.op_reg(A_CLR,GetDefaultZeroReg));
  1986. if current_procinfo.framepointer<>NR_NO then
  1987. begin
  1988. cg.getcpuregister(list,NR_R28);
  1989. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1990. cg.getcpuregister(list,NR_R29);
  1991. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1992. a_adjust_sp(list,-localsize);
  1993. end;
  1994. end
  1995. else if not(nostackframe) then
  1996. begin
  1997. { check if the framepointer is actually used, this is done here because
  1998. we have to know the size of the locals (must be 0), avr does not know
  1999. an sp based stack }
  2000. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  2001. (localsize=0) then
  2002. current_procinfo.framepointer:=NR_NO;
  2003. { save int registers,
  2004. but only if the procedure returns }
  2005. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  2006. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)
  2007. else
  2008. regs:=[];
  2009. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  2010. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  2011. an outer stackframe }
  2012. if current_procinfo.framepointer<>NR_NO then
  2013. regs:=regs+[RS_R28,RS_R29];
  2014. for reg:=RS_R31 downto RS_R0 do
  2015. if reg in regs then
  2016. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2017. if current_procinfo.framepointer<>NR_NO then
  2018. begin
  2019. cg.getcpuregister(list,NR_R28);
  2020. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  2021. cg.getcpuregister(list,NR_R29);
  2022. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  2023. a_adjust_sp(list,-localsize);
  2024. end;
  2025. end;
  2026. end;
  2027. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  2028. var
  2029. regs : tcpuregisterset;
  2030. reg : TSuperRegister;
  2031. LocalSize : longint;
  2032. begin
  2033. { every byte counts for avr, so if a subroutine is marked as non-returning, we do
  2034. not generate any exit code, so we really trust the noreturn directive
  2035. }
  2036. if po_noreturn in current_procinfo.procdef.procoptions then
  2037. exit;
  2038. if po_interrupt in current_procinfo.procdef.procoptions then
  2039. begin
  2040. if not(current_procinfo.procdef.isempty) and
  2041. (not nostackframe) then
  2042. begin
  2043. regs:=rg[R_INTREGISTER].used_in_proc;
  2044. if current_procinfo.framepointer<>NR_NO then
  2045. begin
  2046. regs:=regs+[RS_R28,RS_R29];
  2047. LocalSize:=current_procinfo.calc_stackframe_size;
  2048. a_adjust_sp(list,LocalSize);
  2049. end;
  2050. { we clear r1 }
  2051. include(regs,RS_R1);
  2052. { Reload SREG }
  2053. regs:=regs+[getsupreg(GetDefaultTmpReg)];
  2054. cg.getcpuregister(list,GetDefaultTmpReg);
  2055. list.concat(taicpu.op_reg(A_POP, GetDefaultTmpReg));
  2056. list.concat(taicpu.op_const_reg(A_OUT, $3F, GetDefaultTmpReg));
  2057. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2058. for reg:=RS_R0 to RS_R31 do
  2059. if reg in regs then
  2060. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2061. end;
  2062. list.concat(taicpu.op_none(A_RETI));
  2063. end
  2064. else if not(nostackframe) and not(current_procinfo.procdef.isempty) then
  2065. begin
  2066. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  2067. if current_procinfo.framepointer<>NR_NO then
  2068. begin
  2069. regs:=regs+[RS_R28,RS_R29];
  2070. LocalSize:=current_procinfo.calc_stackframe_size;
  2071. a_adjust_sp(list,LocalSize);
  2072. end;
  2073. for reg:=RS_R0 to RS_R31 do
  2074. if reg in regs then
  2075. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  2076. list.concat(taicpu.op_none(A_RET));
  2077. end
  2078. else
  2079. list.concat(taicpu.op_none(A_RET));
  2080. end;
  2081. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  2082. var
  2083. tmpref : treference;
  2084. begin
  2085. if ref.addressmode<>AM_UNCHANGED then
  2086. internalerror(2011021701);
  2087. if assigned(ref.symbol) or (ref.offset<>0) then
  2088. begin
  2089. reference_reset(tmpref,0,[]);
  2090. tmpref.symbol:=ref.symbol;
  2091. tmpref.offset:=ref.offset;
  2092. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  2093. tmpref.refaddr:=addr_lo8_gs
  2094. else
  2095. tmpref.refaddr:=addr_lo8;
  2096. list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  2097. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  2098. tmpref.refaddr:=addr_hi8_gs
  2099. else
  2100. tmpref.refaddr:=addr_hi8;
  2101. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  2102. if (ref.base<>NR_NO) then
  2103. begin
  2104. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  2105. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  2106. end;
  2107. if (ref.index<>NR_NO) then
  2108. begin
  2109. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  2110. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  2111. end;
  2112. end
  2113. else if (ref.base<>NR_NO)then
  2114. begin
  2115. emit_mov(list,r,ref.base);
  2116. emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  2117. if (ref.index<>NR_NO) then
  2118. begin
  2119. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  2120. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  2121. end;
  2122. end
  2123. else if (ref.index<>NR_NO) then
  2124. begin
  2125. emit_mov(list,r,ref.index);
  2126. emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  2127. end;
  2128. end;
  2129. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  2130. begin
  2131. internalerror(2011021320);
  2132. end;
  2133. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  2134. var
  2135. paraloc1,paraloc2,paraloc3 : TCGPara;
  2136. pd : tprocdef;
  2137. begin
  2138. pd:=search_system_proc('MOVE');
  2139. paraloc1.init;
  2140. paraloc2.init;
  2141. paraloc3.init;
  2142. paramanager.getintparaloc(list,pd,1,paraloc1);
  2143. paramanager.getintparaloc(list,pd,2,paraloc2);
  2144. paramanager.getintparaloc(list,pd,3,paraloc3);
  2145. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  2146. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  2147. a_loadaddr_ref_cgpara(list,source,paraloc1);
  2148. paramanager.freecgpara(list,paraloc3);
  2149. paramanager.freecgpara(list,paraloc2);
  2150. paramanager.freecgpara(list,paraloc1);
  2151. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  2152. a_call_name_static(list,'FPC_MOVE');
  2153. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  2154. paraloc3.done;
  2155. paraloc2.done;
  2156. paraloc1.done;
  2157. end;
  2158. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  2159. var
  2160. countreg,tmpreg,tmpreg2: tregister;
  2161. srcref,dstref : treference;
  2162. copysize,countregsize : tcgsize;
  2163. l : TAsmLabel;
  2164. i : longint;
  2165. SrcQuickRef, DestQuickRef : Boolean;
  2166. begin
  2167. if len>16 then
  2168. begin
  2169. current_asmdata.getjumplabel(l);
  2170. reference_reset(srcref,source.alignment,source.volatility);
  2171. reference_reset(dstref,dest.alignment,source.volatility);
  2172. srcref.base:=NR_R30;
  2173. if not(CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  2174. srcref.addressmode:=AM_POSTINCREMENT;
  2175. dstref.base:=NR_R26;
  2176. if not(CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  2177. dstref.addressmode:=AM_POSTINCREMENT;
  2178. copysize:=OS_8;
  2179. if len<256 then
  2180. countregsize:=OS_8
  2181. else if len<65536 then
  2182. countregsize:=OS_16
  2183. else
  2184. internalerror(2011022007);
  2185. countreg:=getintregister(list,countregsize);
  2186. a_load_const_reg(list,countregsize,len,countreg);
  2187. cg.getcpuregister(list,NR_R30);
  2188. cg.getcpuregister(list,NR_R31);
  2189. a_loadaddr_ref_reg(list,source,NR_R30);
  2190. { only base or index register in dest? }
  2191. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  2192. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  2193. begin
  2194. if dest.base<>NR_NO then
  2195. tmpreg:=dest.base
  2196. else if dest.index<>NR_NO then
  2197. tmpreg:=dest.index
  2198. else
  2199. internalerror(2016112001);
  2200. end
  2201. else
  2202. begin
  2203. tmpreg:=getaddressregister(list);
  2204. a_loadaddr_ref_reg(list,dest,tmpreg);
  2205. end;
  2206. { X is used for spilling code so we can load it
  2207. only by a push/pop sequence, this can be
  2208. optimized later on by the peephole optimizer
  2209. }
  2210. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  2211. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  2212. cg.getcpuregister(list,NR_R27);
  2213. list.concat(taicpu.op_reg(A_POP,NR_R27));
  2214. cg.getcpuregister(list,NR_R26);
  2215. list.concat(taicpu.op_reg(A_POP,NR_R26));
  2216. cg.a_label(list,l);
  2217. cg.getcpuregister(list,GetDefaultTmpReg);
  2218. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2219. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2220. if CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype] then
  2221. begin
  2222. list.concat(taicpu.op_reg_const(A_SUBI,NR_R30,$ff));
  2223. list.concat(taicpu.op_reg_const(A_SBCI,NR_R31,$ff));
  2224. list.concat(taicpu.op_reg_const(A_SUBI,NR_R26,$ff));
  2225. list.concat(taicpu.op_reg_const(A_SBCI,NR_R27,$ff));
  2226. end;
  2227. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2228. if tcgsize2size[countregsize] = 1 then
  2229. list.concat(taicpu.op_reg(A_DEC,countreg))
  2230. else
  2231. begin
  2232. list.concat(taicpu.op_reg_const(A_SUBI,countreg,1));
  2233. list.concat(taicpu.op_reg_reg(A_SBC,GetNextReg(countreg),GetDefaultZeroReg));
  2234. end;
  2235. a_jmp_flags(list,F_NE,l);
  2236. cg.ungetcpuregister(list,NR_R26);
  2237. cg.ungetcpuregister(list,NR_R27);
  2238. cg.ungetcpuregister(list,NR_R30);
  2239. cg.ungetcpuregister(list,NR_R31);
  2240. { keep registers alive }
  2241. a_reg_sync(list,countreg);
  2242. end
  2243. else
  2244. begin
  2245. SrcQuickRef:=false;
  2246. DestQuickRef:=false;
  2247. if (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) or
  2248. (
  2249. not((source.addressmode=AM_UNCHANGED) and
  2250. (source.symbol=nil) and
  2251. ((source.base=NR_R28) or
  2252. (source.base=NR_R30)) and
  2253. (source.Index=NR_NO) and
  2254. (source.Offset in [0..64-len])) and
  2255. not((source.Base=NR_NO) and (source.Index=NR_NO))
  2256. ) then
  2257. begin
  2258. cg.getcpuregister(list,NR_R30);
  2259. cg.getcpuregister(list,NR_R31);
  2260. srcref:=normalize_ref(list,source,NR_R30);
  2261. end
  2262. else
  2263. begin
  2264. SrcQuickRef:=true;
  2265. srcref:=source;
  2266. end;
  2267. if (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) or
  2268. (
  2269. not((dest.addressmode=AM_UNCHANGED) and
  2270. (dest.symbol=nil) and
  2271. ((dest.base=NR_R28) or
  2272. (dest.base=NR_R30)) and
  2273. (dest.Index=NR_No) and
  2274. (dest.Offset in [0..64-len])) and
  2275. not((dest.Base=NR_NO) and (dest.Index=NR_NO))
  2276. ) then
  2277. begin
  2278. if not(SrcQuickRef) then
  2279. begin
  2280. { only base or index register in dest? }
  2281. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  2282. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  2283. begin
  2284. if dest.base<>NR_NO then
  2285. tmpreg:=dest.base
  2286. else if dest.index<>NR_NO then
  2287. tmpreg:=dest.index
  2288. else
  2289. internalerror(2016112002);
  2290. end
  2291. else
  2292. tmpreg:=getaddressregister(list);
  2293. dstref:=normalize_ref(list,dest,tmpreg);
  2294. { X is used for spilling code so we can load it
  2295. only by a push/pop sequence, this can be
  2296. optimized later on by the peephole optimizer
  2297. }
  2298. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  2299. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  2300. cg.getcpuregister(list,NR_R27);
  2301. list.concat(taicpu.op_reg(A_POP,NR_R27));
  2302. cg.getcpuregister(list,NR_R26);
  2303. list.concat(taicpu.op_reg(A_POP,NR_R26));
  2304. dstref.base:=NR_R26;
  2305. end
  2306. else
  2307. begin
  2308. cg.getcpuregister(list,NR_R30);
  2309. cg.getcpuregister(list,NR_R31);
  2310. dstref:=normalize_ref(list,dest,NR_R30);
  2311. end;
  2312. end
  2313. else
  2314. begin
  2315. DestQuickRef:=true;
  2316. dstref:=dest;
  2317. end;
  2318. // CC
  2319. // If dest is an ioreg (31 < offset < srambase) and size = 16 bit then
  2320. // load high byte first, then low byte
  2321. if (len = 2) and DestQuickRef
  2322. and (dest.offset > 31)
  2323. and (dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  2324. begin
  2325. // If src is also a 16 bit ioreg then read low byte then high byte
  2326. if SrcQuickRef and (srcref.offset > 31)
  2327. and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
  2328. begin
  2329. // First read source into temp registers
  2330. tmpreg:=getintregister(list, OS_16);
  2331. list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg,srcref));
  2332. inc(srcref.offset);
  2333. tmpreg2:=GetNextReg(tmpreg);
  2334. list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg2,srcref));
  2335. // then move temp registers to dest in reverse order
  2336. inc(dstref.offset);
  2337. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg2));
  2338. dec(dstref.offset);
  2339. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg));
  2340. end
  2341. else
  2342. begin
  2343. srcref.addressmode:=AM_UNCHANGED;
  2344. inc(srcref.offset);
  2345. dstref.addressmode:=AM_UNCHANGED;
  2346. inc(dstref.offset);
  2347. cg.getcpuregister(list,GetDefaultTmpReg);
  2348. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2349. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2350. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2351. if not(SrcQuickRef) then
  2352. srcref.addressmode:=AM_POSTINCREMENT
  2353. else
  2354. srcref.addressmode:=AM_UNCHANGED;
  2355. dec(srcref.offset);
  2356. dec(dstref.offset);
  2357. cg.getcpuregister(list,GetDefaultTmpReg);
  2358. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2359. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2360. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2361. end;
  2362. end
  2363. else
  2364. for i:=1 to len do
  2365. begin
  2366. if not(SrcQuickRef) and (i<len) and not(CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  2367. srcref.addressmode:=AM_POSTINCREMENT
  2368. else
  2369. srcref.addressmode:=AM_UNCHANGED;
  2370. if not(DestQuickRef) and (i<len) and not(CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
  2371. dstref.addressmode:=AM_POSTINCREMENT
  2372. else
  2373. dstref.addressmode:=AM_UNCHANGED;
  2374. cg.getcpuregister(list,GetDefaultTmpReg);
  2375. list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
  2376. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
  2377. cg.ungetcpuregister(list,GetDefaultTmpReg);
  2378. if (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) and (i<len) then
  2379. begin
  2380. list.concat(taicpu.op_reg_const(A_SUBI,srcref.base,$ff));
  2381. list.concat(taicpu.op_reg_const(A_SBCI,TRegister(ord(srcref.base)+1),$ff));
  2382. list.concat(taicpu.op_reg_const(A_SUBI,dstref.base,$ff));
  2383. list.concat(taicpu.op_reg_const(A_SBCI,TRegister(ord(dstref.base)+1),$ff));
  2384. end;
  2385. if SrcQuickRef then
  2386. inc(srcref.offset);
  2387. if DestQuickRef then
  2388. inc(dstref.offset);
  2389. end;
  2390. if not(SrcQuickRef) then
  2391. begin
  2392. ungetcpuregister(list,srcref.base);
  2393. ungetcpuregister(list,TRegister(ord(srcref.base)+1));
  2394. end;
  2395. if not(DestQuickRef) then
  2396. begin
  2397. ungetcpuregister(list,dstref.base);
  2398. ungetcpuregister(list,TRegister(ord(dstref.base)+1));
  2399. end;
  2400. end;
  2401. end;
  2402. procedure tcgavr.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2403. var
  2404. hl : tasmlabel;
  2405. ai : taicpu;
  2406. cond : TAsmCond;
  2407. begin
  2408. if not(cs_check_overflow in current_settings.localswitches) then
  2409. exit;
  2410. current_asmdata.getjumplabel(hl);
  2411. if not ((def.typ=pointerdef) or
  2412. ((def.typ=orddef) and
  2413. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2414. pasbool1,pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2415. cond:=C_VC
  2416. else
  2417. cond:=C_CC;
  2418. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2419. ai.SetCondition(cond);
  2420. ai.is_jmp:=true;
  2421. list.concat(ai);
  2422. a_call_name(list,'FPC_OVERFLOW',false);
  2423. a_label(list,hl);
  2424. end;
  2425. procedure tcgavr.g_overflowCheck_loc(List: TAsmList; const Loc: TLocation; def: TDef; ovloc: tlocation);
  2426. var
  2427. hl : tasmlabel;
  2428. ai : taicpu;
  2429. cond : TAsmCond;
  2430. begin
  2431. if not(cs_check_overflow in current_settings.localswitches) then
  2432. exit;
  2433. case ovloc.loc of
  2434. LOC_FLAGS:
  2435. begin
  2436. current_asmdata.getjumplabel(hl);
  2437. if not ((def.typ=pointerdef) or
  2438. ((def.typ=orddef) and
  2439. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2440. pasbool1,pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2441. cond:=C_VC
  2442. else
  2443. cond:=C_CC;
  2444. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2445. ai.SetCondition(cond);
  2446. ai.is_jmp:=true;
  2447. list.concat(ai);
  2448. a_call_name(list,'FPC_OVERFLOW',false);
  2449. a_label(list,hl);
  2450. end;
  2451. end;
  2452. end;
  2453. procedure tcgavr.g_save_registers(list: TAsmList);
  2454. begin
  2455. { this is done by the entry code }
  2456. end;
  2457. procedure tcgavr.g_restore_registers(list: TAsmList);
  2458. begin
  2459. { this is done by the exit code }
  2460. end;
  2461. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2462. var
  2463. ai1,ai2 : taicpu;
  2464. hl : TAsmLabel;
  2465. begin
  2466. ai1:=Taicpu.Op_sym(A_BRxx,l);
  2467. ai1.is_jmp:=true;
  2468. hl:=nil;
  2469. case cond of
  2470. OC_EQ:
  2471. ai1.SetCondition(C_EQ);
  2472. OC_GT:
  2473. begin
  2474. { emulate GT }
  2475. current_asmdata.getjumplabel(hl);
  2476. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2477. ai2.SetCondition(C_EQ);
  2478. ai2.is_jmp:=true;
  2479. list.concat(ai2);
  2480. ai1.SetCondition(C_GE);
  2481. end;
  2482. OC_LT:
  2483. ai1.SetCondition(C_LT);
  2484. OC_GTE:
  2485. ai1.SetCondition(C_GE);
  2486. OC_LTE:
  2487. begin
  2488. { emulate LTE }
  2489. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2490. ai2.SetCondition(C_EQ);
  2491. ai2.is_jmp:=true;
  2492. list.concat(ai2);
  2493. ai1.SetCondition(C_LT);
  2494. end;
  2495. OC_NE:
  2496. ai1.SetCondition(C_NE);
  2497. OC_BE:
  2498. begin
  2499. { emulate BE }
  2500. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2501. ai2.SetCondition(C_EQ);
  2502. ai2.is_jmp:=true;
  2503. list.concat(ai2);
  2504. ai1.SetCondition(C_LO);
  2505. end;
  2506. OC_B:
  2507. ai1.SetCondition(C_LO);
  2508. OC_AE:
  2509. ai1.SetCondition(C_SH);
  2510. OC_A:
  2511. begin
  2512. { emulate A (unsigned GT) }
  2513. current_asmdata.getjumplabel(hl);
  2514. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2515. ai2.SetCondition(C_EQ);
  2516. ai2.is_jmp:=true;
  2517. list.concat(ai2);
  2518. ai1.SetCondition(C_SH);
  2519. end;
  2520. else
  2521. internalerror(2011082501);
  2522. end;
  2523. list.concat(ai1);
  2524. if assigned(hl) then
  2525. a_label(list,hl);
  2526. end;
  2527. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2528. var
  2529. instr: taicpu;
  2530. begin
  2531. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  2532. list.Concat(instr);
  2533. { Notify the register allocator that we have written a move instruction so
  2534. it can try to eliminate it. }
  2535. add_move_instruction(instr);
  2536. end;
  2537. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2538. begin
  2539. if not(size in [OS_S64,OS_64]) then
  2540. internalerror(2012102402);
  2541. tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2542. end;
  2543. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2544. begin
  2545. tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2546. end;
  2547. procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize;value: int64;src,dst : tregister64);
  2548. begin
  2549. if op in [OP_SHL,OP_SHR] then
  2550. tcgavr(cg).a_op_const_reg_reg_internal(list,Op,size,value,src.reglo,src.reghi,dst.reglo,dst.reghi)
  2551. else
  2552. Inherited a_op64_const_reg_reg(list,op,size,value,src,dst);
  2553. end;
  2554. procedure create_codegen;
  2555. begin
  2556. cg:=tcgavr.create;
  2557. cg64:=tcg64favr.create;
  2558. end;
  2559. end.