cgcpu.pas 86 KB

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