cgcpu.pas 106 KB

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