cgcpu.pas 84 KB

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