cgcpu.pas 86 KB

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