cgcpu.pas 105 KB

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