cgcpu.pas 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407
  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. else if size in [OS_S8,OS_8] then
  492. list.concat(taicpu.op_reg(A_NEG,dst))
  493. else
  494. Internalerror(2018030401);
  495. end;
  496. OP_NOT:
  497. begin
  498. for i:=1 to tcgsize2size[size] do
  499. begin
  500. if src<>dst then
  501. a_load_reg_reg(list,OS_8,OS_8,src,dst);
  502. list.concat(taicpu.op_reg(A_COM,dst));
  503. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  504. if i<tcgsize2size[size] then
  505. NextSrcDstPostInc;
  506. end;
  507. end;
  508. OP_MUL,OP_IMUL:
  509. begin
  510. if size in [OS_8,OS_S8] then
  511. begin
  512. if CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype] then
  513. begin
  514. cg.a_reg_alloc(list,NR_R0);
  515. cg.a_reg_alloc(list,NR_R1);
  516. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  517. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  518. cg.a_reg_dealloc(list,NR_R1);
  519. list.concat(taicpu.op_reg_reg(A_MOV,dst,NR_R0));
  520. cg.a_reg_dealloc(list,NR_R0);
  521. end
  522. else
  523. begin
  524. if size=OS_8 then
  525. pd:=search_system_proc('fpc_mul_byte')
  526. else
  527. pd:=search_system_proc('fpc_mul_shortint');
  528. paraloc1.init;
  529. paraloc2.init;
  530. paramanager.getintparaloc(list,pd,1,paraloc1);
  531. paramanager.getintparaloc(list,pd,2,paraloc2);
  532. a_load_reg_cgpara(list,OS_8,src,paraloc2);
  533. a_load_reg_cgpara(list,OS_8,dst,paraloc1);
  534. paramanager.freecgpara(list,paraloc2);
  535. paramanager.freecgpara(list,paraloc1);
  536. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  537. if size=OS_8 then
  538. a_call_name(list,'FPC_MUL_BYTE',false)
  539. else
  540. a_call_name(list,'FPC_MUL_SHORTINT',false);
  541. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  542. cg.a_reg_alloc(list,NR_R24);
  543. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  544. cg.a_reg_dealloc(list,NR_R24);
  545. paraloc2.done;
  546. paraloc1.done;
  547. end;
  548. end
  549. else if size in [OS_16,OS_S16] then
  550. begin
  551. if CPUAVR_HAS_MUL in cpu_capabilities[current_settings.cputype] then
  552. begin
  553. tmpreg:=getintregister(list,OS_16);
  554. emit_mov(list,tmpreg,dst);
  555. emit_mov(list,GetNextReg(tmpreg),GetNextReg(dst));
  556. list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,src));
  557. emit_mov(list,dst,NR_R0);
  558. emit_mov(list,GetNextReg(dst),NR_R1);
  559. list.concat(taicpu.op_reg_reg(A_MUL,GetNextReg(tmpreg),src));
  560. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  561. list.concat(taicpu.op_reg_reg(A_MUL,tmpreg,GetNextReg(src)));
  562. list.concat(taicpu.op_reg_reg(A_ADD,GetNextReg(dst),NR_R0));
  563. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  564. end
  565. else
  566. begin
  567. if size=OS_16 then
  568. pd:=search_system_proc('fpc_mul_word')
  569. else
  570. pd:=search_system_proc('fpc_mul_integer');
  571. paraloc1.init;
  572. paraloc2.init;
  573. paramanager.getintparaloc(list,pd,1,paraloc1);
  574. paramanager.getintparaloc(list,pd,2,paraloc2);
  575. a_load_reg_cgpara(list,OS_16,src,paraloc2);
  576. a_load_reg_cgpara(list,OS_16,dst,paraloc1);
  577. paramanager.freecgpara(list,paraloc2);
  578. paramanager.freecgpara(list,paraloc1);
  579. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  580. if size=OS_16 then
  581. a_call_name(list,'FPC_MUL_WORD',false)
  582. else
  583. a_call_name(list,'FPC_MUL_INTEGER',false);
  584. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  585. cg.a_reg_alloc(list,NR_R24);
  586. cg.a_reg_alloc(list,NR_R25);
  587. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R24,dst);
  588. cg.a_reg_dealloc(list,NR_R24);
  589. cg.a_load_reg_reg(list,OS_8,OS_8,NR_R25,GetNextReg(dst));
  590. cg.a_reg_dealloc(list,NR_R25);
  591. paraloc2.done;
  592. paraloc1.done;
  593. end;
  594. end
  595. else
  596. internalerror(2011022002);
  597. end;
  598. OP_DIV,OP_IDIV:
  599. { special stuff, needs separate handling inside code }
  600. { generator }
  601. internalerror(2011022001);
  602. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  603. begin
  604. current_asmdata.getjumplabel(l1);
  605. current_asmdata.getjumplabel(l2);
  606. countreg:=getintregister(list,OS_8);
  607. a_load_reg_reg(list,size,OS_8,src,countreg);
  608. list.concat(taicpu.op_reg(A_TST,countreg));
  609. a_jmp_flags(list,F_EQ,l2);
  610. cg.a_label(list,l1);
  611. case op of
  612. OP_SHR:
  613. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  614. OP_SHL:
  615. list.concat(taicpu.op_reg(A_LSL,dst));
  616. OP_SAR:
  617. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  618. OP_ROR:
  619. begin
  620. { load carry? }
  621. if not(size in [OS_8,OS_S8]) then
  622. begin
  623. list.concat(taicpu.op_none(A_CLC));
  624. list.concat(taicpu.op_reg_const(A_SBRC,src,0));
  625. list.concat(taicpu.op_none(A_SEC));
  626. end;
  627. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  628. end;
  629. OP_ROL:
  630. begin
  631. { load carry? }
  632. if not(size in [OS_8,OS_S8]) then
  633. begin
  634. list.concat(taicpu.op_none(A_CLC));
  635. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
  636. list.concat(taicpu.op_none(A_SEC));
  637. end;
  638. list.concat(taicpu.op_reg(A_ROL,dst))
  639. end;
  640. else
  641. internalerror(2011030901);
  642. end;
  643. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  644. begin
  645. for i:=2 to tcgsize2size[size] do
  646. begin
  647. case op of
  648. OP_ROR,
  649. OP_SHR:
  650. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  651. OP_ROL,
  652. OP_SHL:
  653. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
  654. OP_SAR:
  655. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  656. else
  657. internalerror(2011030902);
  658. end;
  659. end;
  660. end;
  661. list.concat(taicpu.op_reg(A_DEC,countreg));
  662. a_jmp_flags(list,F_NE,l1);
  663. // keep registers alive
  664. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  665. cg.a_label(list,l2);
  666. end;
  667. OP_AND,OP_OR,OP_XOR:
  668. begin
  669. for i:=1 to tcgsize2size[size] do
  670. begin
  671. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  672. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  673. if i<tcgsize2size[size] then
  674. NextSrcDstPostInc;
  675. end;
  676. end;
  677. else
  678. internalerror(2011022004);
  679. end;
  680. end;
  681. procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  682. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  683. var
  684. mask : qword;
  685. shift : byte;
  686. i,j : byte;
  687. tmpreg : tregister;
  688. tmpreg64 : tregister64;
  689. { NextReg* is sometimes called before the register usage and sometimes afterwards }
  690. procedure NextRegPreInc;
  691. begin
  692. if i=5 then
  693. reg:=reghi
  694. else
  695. reg:=GetNextReg(reg);
  696. end;
  697. procedure NextRegPostInc;
  698. begin
  699. if i=4 then
  700. reg:=reghi
  701. else
  702. reg:=GetNextReg(reg);
  703. end;
  704. var
  705. curvalue : byte;
  706. l1: TAsmLabel;
  707. begin
  708. optimize_op_const(size,op,a);
  709. mask:=$ff;
  710. shift:=0;
  711. case op of
  712. OP_NONE:
  713. begin
  714. { Opcode is optimized away }
  715. end;
  716. OP_MOVE:
  717. begin
  718. { Optimized, replaced with a simple load }
  719. a_load_const_reg(list,size,a,reg);
  720. end;
  721. OP_OR:
  722. begin
  723. for i:=1 to tcgsize2size[size] do
  724. begin
  725. if ((qword(a) and mask) shr shift)<>0 then
  726. list.concat(taicpu.op_reg_const(A_ORI,reg,(qword(a) and mask) shr shift));
  727. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  728. if i<tcgsize2size[size] then
  729. NextRegPostInc;
  730. mask:=mask shl 8;
  731. inc(shift,8);
  732. end;
  733. end;
  734. OP_AND:
  735. begin
  736. for i:=1 to tcgsize2size[size] do
  737. begin
  738. if ((qword(a) and mask) shr shift)=0 then
  739. list.concat(taicpu.op_reg_reg(A_MOV,reg,NR_R1))
  740. else if ((qword(a) and mask) shr shift)<>$ff then
  741. list.concat(taicpu.op_reg_const(A_ANDI,reg,(qword(a) and mask) shr shift));
  742. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  743. if i<tcgsize2size[size] then
  744. NextRegPostInc;
  745. mask:=mask shl 8;
  746. inc(shift,8);
  747. end;
  748. end;
  749. OP_SUB:
  750. begin
  751. if ((a and mask)=1) and (tcgsize2size[size]=1) then
  752. list.concat(taicpu.op_reg(A_DEC,reg))
  753. else
  754. list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
  755. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  756. begin
  757. for i:=2 to tcgsize2size[size] do
  758. begin
  759. NextRegPreInc;
  760. mask:=mask shl 8;
  761. inc(shift,8);
  762. curvalue:=(qword(a) and mask) shr shift;
  763. { decrease pressure on upper half of registers by using SBC ...,R1 instead
  764. of SBCI ...,0 }
  765. if curvalue=0 then
  766. list.concat(taicpu.op_reg_reg(A_SBC,reg,NR_R1))
  767. else
  768. list.concat(taicpu.op_reg_const(A_SBCI,reg,curvalue));
  769. end;
  770. end;
  771. end;
  772. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  773. begin
  774. if (op=OP_SAR) and (a>=(tcgsize2size[size]*8-1)) then
  775. begin
  776. current_asmdata.getjumplabel(l1);
  777. list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  778. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1));
  779. a_jmp_flags(list,F_PL,l1);
  780. list.concat(taicpu.op_reg(A_DEC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  781. cg.a_label(list,l1);
  782. for i:=2 to tcgsize2size[size] do
  783. a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),GetOffsetReg64(reg,reghi,tcgsize2size[size]-i));
  784. end
  785. else if (op=OP_SHR) and (a=(tcgsize2size[size]*8-1)) then
  786. begin
  787. current_asmdata.getjumplabel(l1);
  788. list.concat(taicpu.op_reg(A_TST,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  789. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,0));
  790. a_jmp_flags(list,F_PL,l1);
  791. list.concat(taicpu.op_reg(A_INC,GetOffsetReg64(reg,reghi,0)));
  792. cg.a_label(list,l1);
  793. for i:=1 to tcgsize2size[size]-1 do
  794. a_load_const_reg(list,OS_8,0,GetOffsetReg64(reg,reghi,i));
  795. end
  796. else if a*tcgsize2size[size]<=8 then
  797. begin
  798. for j:=1 to a do
  799. begin
  800. case op of
  801. OP_SHR:
  802. list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  803. OP_SHL:
  804. list.concat(taicpu.op_reg(A_LSL,reg));
  805. OP_SAR:
  806. list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  807. OP_ROR:
  808. begin
  809. { load carry? }
  810. if not(size in [OS_8,OS_S8]) then
  811. begin
  812. list.concat(taicpu.op_none(A_CLC));
  813. list.concat(taicpu.op_reg_const(A_SBRC,reg,0));
  814. list.concat(taicpu.op_none(A_SEC));
  815. end;
  816. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  817. end;
  818. OP_ROL:
  819. begin
  820. { load carry? }
  821. if not(size in [OS_8,OS_S8]) then
  822. begin
  823. list.concat(taicpu.op_none(A_CLC));
  824. list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1),7));
  825. list.concat(taicpu.op_none(A_SEC));
  826. end;
  827. list.concat(taicpu.op_reg(A_ROL,reg))
  828. end;
  829. else
  830. internalerror(2011030901);
  831. end;
  832. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  833. begin
  834. for i:=2 to tcgsize2size[size] do
  835. begin
  836. case op of
  837. OP_ROR,
  838. OP_SHR:
  839. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  840. OP_ROL,
  841. OP_SHL:
  842. list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(reg,reghi,i-1)));
  843. OP_SAR:
  844. list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  845. else
  846. internalerror(2011030902);
  847. end;
  848. end;
  849. end;
  850. end;
  851. end
  852. else
  853. begin
  854. tmpreg:=getintregister(list,size);
  855. a_load_const_reg(list,size,a,tmpreg);
  856. a_op_reg_reg(list,op,size,tmpreg,reg);
  857. end;
  858. end;
  859. OP_ADD:
  860. begin
  861. curvalue:=a and mask;
  862. if curvalue=0 then
  863. list.concat(taicpu.op_reg_reg(A_ADD,reg,NR_R1))
  864. else if (curvalue=1) and (tcgsize2size[size]=1) then
  865. list.concat(taicpu.op_reg(A_INC,reg))
  866. else
  867. begin
  868. tmpreg:=getintregister(list,OS_8);
  869. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  870. list.concat(taicpu.op_reg_reg(A_ADD,reg,tmpreg));
  871. end;
  872. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  873. begin
  874. for i:=2 to tcgsize2size[size] do
  875. begin
  876. NextRegPreInc;
  877. mask:=mask shl 8;
  878. inc(shift,8);
  879. curvalue:=(qword(a) and mask) shr shift;
  880. { decrease pressure on upper half of registers by using ADC ...,R1 instead
  881. of ADD ...,0 }
  882. if curvalue=0 then
  883. list.concat(taicpu.op_reg_reg(A_ADC,reg,NR_R1))
  884. else
  885. begin
  886. tmpreg:=getintregister(list,OS_8);
  887. a_load_const_reg(list,OS_8,curvalue,tmpreg);
  888. list.concat(taicpu.op_reg_reg(A_ADC,reg,tmpreg));
  889. end;
  890. end;
  891. end;
  892. end;
  893. else
  894. begin
  895. if size in [OS_64,OS_S64] then
  896. begin
  897. tmpreg64.reglo:=getintregister(list,OS_32);
  898. tmpreg64.reghi:=getintregister(list,OS_32);
  899. cg64.a_load64_const_reg(list,a,tmpreg64);
  900. cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  901. end
  902. else
  903. begin
  904. {$if 0}
  905. { code not working yet }
  906. if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  907. begin
  908. tmpreg:=reg;
  909. for i:=1 to 4 do
  910. begin
  911. list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  912. tmpreg:=GetNextReg(tmpreg);
  913. end;
  914. end
  915. else
  916. {$endif}
  917. begin
  918. tmpreg:=getintregister(list,size);
  919. a_load_const_reg(list,size,a,tmpreg);
  920. a_op_reg_reg(list,op,size,tmpreg,reg);
  921. end;
  922. end;
  923. end;
  924. end;
  925. end;
  926. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  927. var
  928. mask : qword;
  929. shift : byte;
  930. i : byte;
  931. begin
  932. mask:=$ff;
  933. shift:=0;
  934. for i:=1 to tcgsize2size[size] do
  935. begin
  936. if ((qword(a) and mask) shr shift)=0 then
  937. emit_mov(list,reg,NR_R1)
  938. else
  939. begin
  940. getcpuregister(list,NR_R26);
  941. list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
  942. a_load_reg_reg(list,OS_8,OS_8,NR_R26,reg);
  943. ungetcpuregister(list,NR_R26);
  944. end;
  945. mask:=mask shl 8;
  946. inc(shift,8);
  947. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  948. if i<tcgsize2size[size] then
  949. reg:=GetNextReg(reg);
  950. end;
  951. end;
  952. procedure tcgavr.maybegetcpuregister(list:tasmlist;reg : tregister);
  953. begin
  954. { allocate the register only, if a cpu register is passed }
  955. if getsupreg(reg)<first_int_imreg then
  956. getcpuregister(list,reg);
  957. end;
  958. function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
  959. var
  960. tmpref : treference;
  961. l : tasmlabel;
  962. begin
  963. Result:=ref;
  964. if ref.addressmode<>AM_UNCHANGED then
  965. internalerror(2011021701);
  966. { Be sure to have a base register }
  967. if (ref.base=NR_NO) then
  968. begin
  969. { only symbol+offset? }
  970. if ref.index=NR_NO then
  971. exit;
  972. ref.base:=ref.index;
  973. ref.index:=NR_NO;
  974. end;
  975. { can we take advantage of adiw/sbiw? }
  976. if (current_settings.cputype>=cpu_avr2) and not(assigned(ref.symbol)) and (ref.offset<>0) and (ref.offset>=-63) and (ref.offset<=63) and
  977. ((tmpreg=NR_R24) or (tmpreg=NR_R26) or (tmpreg=NR_R28) or (tmpreg=NR_R30)) and (ref.base<>NR_NO) then
  978. begin
  979. maybegetcpuregister(list,tmpreg);
  980. emit_mov(list,tmpreg,ref.base);
  981. maybegetcpuregister(list,GetNextReg(tmpreg));
  982. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  983. if ref.index<>NR_NO then
  984. begin
  985. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  986. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  987. end;
  988. if ref.offset>0 then
  989. list.concat(taicpu.op_reg_const(A_ADIW,tmpreg,ref.offset))
  990. else
  991. list.concat(taicpu.op_reg_const(A_SBIW,tmpreg,-ref.offset));
  992. ref.offset:=0;
  993. ref.base:=tmpreg;
  994. ref.index:=NR_NO;
  995. end
  996. else if assigned(ref.symbol) or (ref.offset<>0) then
  997. begin
  998. reference_reset(tmpref,0,[]);
  999. tmpref.symbol:=ref.symbol;
  1000. tmpref.offset:=ref.offset;
  1001. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1002. tmpref.refaddr:=addr_lo8_gs
  1003. else
  1004. tmpref.refaddr:=addr_lo8;
  1005. maybegetcpuregister(list,tmpreg);
  1006. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  1007. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1008. tmpref.refaddr:=addr_hi8_gs
  1009. else
  1010. tmpref.refaddr:=addr_hi8;
  1011. maybegetcpuregister(list,GetNextReg(tmpreg));
  1012. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  1013. if (ref.base<>NR_NO) then
  1014. begin
  1015. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  1016. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  1017. end;
  1018. if (ref.index<>NR_NO) then
  1019. begin
  1020. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1021. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1022. end;
  1023. ref.symbol:=nil;
  1024. ref.offset:=0;
  1025. ref.base:=tmpreg;
  1026. ref.index:=NR_NO;
  1027. end
  1028. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  1029. begin
  1030. maybegetcpuregister(list,tmpreg);
  1031. emit_mov(list,tmpreg,ref.base);
  1032. maybegetcpuregister(list,GetNextReg(tmpreg));
  1033. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1034. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
  1035. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
  1036. ref.base:=tmpreg;
  1037. ref.index:=NR_NO;
  1038. end
  1039. else if (ref.base<>NR_NO) then
  1040. begin
  1041. maybegetcpuregister(list,tmpreg);
  1042. emit_mov(list,tmpreg,ref.base);
  1043. maybegetcpuregister(list,GetNextReg(tmpreg));
  1044. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
  1045. ref.base:=tmpreg;
  1046. ref.index:=NR_NO;
  1047. end
  1048. else if (ref.index<>NR_NO) then
  1049. begin
  1050. maybegetcpuregister(list,tmpreg);
  1051. emit_mov(list,tmpreg,ref.index);
  1052. maybegetcpuregister(list,GetNextReg(tmpreg));
  1053. emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
  1054. ref.base:=tmpreg;
  1055. ref.index:=NR_NO;
  1056. end;
  1057. Result:=ref;
  1058. end;
  1059. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1060. var
  1061. href : treference;
  1062. conv_done: boolean;
  1063. tmpreg : tregister;
  1064. i : integer;
  1065. QuickRef : Boolean;
  1066. begin
  1067. QuickRef:=false;
  1068. href:=Ref;
  1069. { ensure, href.base contains a valid register if there is any register used }
  1070. if href.base=NR_NO then
  1071. begin
  1072. href.base:=href.index;
  1073. href.index:=NR_NO;
  1074. end;
  1075. { try to use std/sts }
  1076. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1077. begin
  1078. if not((href.addressmode=AM_UNCHANGED) and
  1079. (href.symbol=nil) and
  1080. (href.Index=NR_NO) and
  1081. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1082. href:=normalize_ref(list,href,NR_R30)
  1083. else
  1084. begin
  1085. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1086. begin
  1087. maybegetcpuregister(list,NR_R30);
  1088. emit_mov(list,NR_R30,href.base);
  1089. maybegetcpuregister(list,NR_R31);
  1090. emit_mov(list,NR_R31,GetNextReg(href.base));
  1091. href.base:=NR_R30;
  1092. end;
  1093. QuickRef:=true;
  1094. end;
  1095. end
  1096. else
  1097. QuickRef:=true;
  1098. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1099. internalerror(2011021307);
  1100. conv_done:=false;
  1101. if tosize<>fromsize then
  1102. begin
  1103. conv_done:=true;
  1104. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1105. fromsize:=tosize;
  1106. case fromsize of
  1107. OS_8:
  1108. begin
  1109. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1110. href.addressmode:=AM_POSTINCREMENT;
  1111. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1112. for i:=2 to tcgsize2size[tosize] do
  1113. begin
  1114. if QuickRef then
  1115. inc(href.offset);
  1116. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1117. href.addressmode:=AM_POSTINCREMENT
  1118. else
  1119. href.addressmode:=AM_UNCHANGED;
  1120. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1121. end;
  1122. end;
  1123. OS_S8:
  1124. begin
  1125. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1126. href.addressmode:=AM_POSTINCREMENT;
  1127. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1128. if tcgsize2size[tosize]>1 then
  1129. begin
  1130. tmpreg:=getintregister(list,OS_8);
  1131. emit_mov(list,tmpreg,NR_R1);
  1132. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1133. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1134. for i:=2 to tcgsize2size[tosize] do
  1135. begin
  1136. if QuickRef then
  1137. inc(href.offset);
  1138. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1139. href.addressmode:=AM_POSTINCREMENT
  1140. else
  1141. href.addressmode:=AM_UNCHANGED;
  1142. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1143. end;
  1144. end;
  1145. end;
  1146. OS_16:
  1147. begin
  1148. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1149. href.addressmode:=AM_POSTINCREMENT;
  1150. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1151. if QuickRef then
  1152. inc(href.offset)
  1153. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1154. href.addressmode:=AM_POSTINCREMENT
  1155. else
  1156. href.addressmode:=AM_UNCHANGED;
  1157. reg:=GetNextReg(reg);
  1158. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1159. for i:=3 to tcgsize2size[tosize] do
  1160. begin
  1161. if QuickRef then
  1162. inc(href.offset);
  1163. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1164. href.addressmode:=AM_POSTINCREMENT
  1165. else
  1166. href.addressmode:=AM_UNCHANGED;
  1167. list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
  1168. end;
  1169. end;
  1170. OS_S16:
  1171. begin
  1172. if not(QuickRef) and (tcgsize2size[tosize]>1) then
  1173. href.addressmode:=AM_POSTINCREMENT;
  1174. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1175. if QuickRef then
  1176. inc(href.offset)
  1177. else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
  1178. href.addressmode:=AM_POSTINCREMENT
  1179. else
  1180. href.addressmode:=AM_UNCHANGED;
  1181. reg:=GetNextReg(reg);
  1182. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1183. if tcgsize2size[tosize]>2 then
  1184. begin
  1185. tmpreg:=getintregister(list,OS_8);
  1186. emit_mov(list,tmpreg,NR_R1);
  1187. list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
  1188. list.concat(taicpu.op_reg(A_COM,tmpreg));
  1189. for i:=3 to tcgsize2size[tosize] do
  1190. begin
  1191. if QuickRef then
  1192. inc(href.offset);
  1193. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1194. href.addressmode:=AM_POSTINCREMENT
  1195. else
  1196. href.addressmode:=AM_UNCHANGED;
  1197. list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
  1198. end;
  1199. end;
  1200. end;
  1201. else
  1202. conv_done:=false;
  1203. end;
  1204. end;
  1205. if not conv_done then
  1206. begin
  1207. for i:=1 to tcgsize2size[fromsize] do
  1208. begin
  1209. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1210. href.addressmode:=AM_POSTINCREMENT
  1211. else
  1212. href.addressmode:=AM_UNCHANGED;
  1213. list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
  1214. if QuickRef then
  1215. inc(href.offset);
  1216. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1217. if i<tcgsize2size[fromsize] then
  1218. reg:=GetNextReg(reg);
  1219. end;
  1220. end;
  1221. if not(QuickRef) then
  1222. begin
  1223. ungetcpuregister(list,href.base);
  1224. ungetcpuregister(list,GetNextReg(href.base));
  1225. end;
  1226. end;
  1227. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1228. const Ref : treference;reg : tregister);
  1229. var
  1230. href : treference;
  1231. conv_done: boolean;
  1232. tmpreg : tregister;
  1233. i : integer;
  1234. QuickRef : boolean;
  1235. begin
  1236. QuickRef:=false;
  1237. href:=Ref;
  1238. { ensure, href.base contains a valid register if there is any register used }
  1239. if href.base=NR_NO then
  1240. begin
  1241. href.base:=href.index;
  1242. href.index:=NR_NO;
  1243. end;
  1244. { try to use ldd/lds }
  1245. if not((href.Base=NR_NO) and (href.Index=NR_NO)) then
  1246. begin
  1247. if not((href.addressmode=AM_UNCHANGED) and
  1248. (href.symbol=nil) and
  1249. (href.Index=NR_NO) and
  1250. (href.Offset in [0..64-tcgsize2size[fromsize]])) then
  1251. href:=normalize_ref(list,href,NR_R30)
  1252. else
  1253. begin
  1254. if (href.base<>NR_R28) and (href.base<>NR_R30) then
  1255. begin
  1256. maybegetcpuregister(list,NR_R30);
  1257. emit_mov(list,NR_R30,href.base);
  1258. maybegetcpuregister(list,NR_R31);
  1259. emit_mov(list,NR_R31,GetNextReg(href.base));
  1260. href.base:=NR_R30;
  1261. end;
  1262. QuickRef:=true;
  1263. end;
  1264. end
  1265. else
  1266. QuickRef:=true;
  1267. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1268. internalerror(2011021307);
  1269. conv_done:=false;
  1270. if tosize<>fromsize then
  1271. begin
  1272. conv_done:=true;
  1273. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1274. fromsize:=tosize;
  1275. case fromsize of
  1276. OS_8:
  1277. begin
  1278. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1279. for i:=2 to tcgsize2size[tosize] do
  1280. begin
  1281. reg:=GetNextReg(reg);
  1282. emit_mov(list,reg,NR_R1);
  1283. end;
  1284. end;
  1285. OS_S8:
  1286. begin
  1287. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1288. tmpreg:=reg;
  1289. if tcgsize2size[tosize]>1 then
  1290. begin
  1291. reg:=GetNextReg(reg);
  1292. emit_mov(list,reg,NR_R1);
  1293. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1294. list.concat(taicpu.op_reg(A_COM,reg));
  1295. tmpreg:=reg;
  1296. for i:=3 to tcgsize2size[tosize] do
  1297. begin
  1298. reg:=GetNextReg(reg);
  1299. emit_mov(list,reg,tmpreg);
  1300. end;
  1301. end;
  1302. end;
  1303. OS_16:
  1304. begin
  1305. if not(QuickRef) then
  1306. href.addressmode:=AM_POSTINCREMENT;
  1307. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1308. if QuickRef then
  1309. inc(href.offset);
  1310. href.addressmode:=AM_UNCHANGED;
  1311. reg:=GetNextReg(reg);
  1312. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1313. for i:=3 to tcgsize2size[tosize] do
  1314. begin
  1315. reg:=GetNextReg(reg);
  1316. emit_mov(list,reg,NR_R1);
  1317. end;
  1318. end;
  1319. OS_S16:
  1320. begin
  1321. if not(QuickRef) then
  1322. href.addressmode:=AM_POSTINCREMENT;
  1323. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1324. if QuickRef then
  1325. inc(href.offset);
  1326. href.addressmode:=AM_UNCHANGED;
  1327. reg:=GetNextReg(reg);
  1328. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1329. tmpreg:=reg;
  1330. reg:=GetNextReg(reg);
  1331. emit_mov(list,reg,NR_R1);
  1332. list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
  1333. list.concat(taicpu.op_reg(A_COM,reg));
  1334. tmpreg:=reg;
  1335. for i:=4 to tcgsize2size[tosize] do
  1336. begin
  1337. reg:=GetNextReg(reg);
  1338. emit_mov(list,reg,tmpreg);
  1339. end;
  1340. end;
  1341. else
  1342. conv_done:=false;
  1343. end;
  1344. end;
  1345. if not conv_done then
  1346. begin
  1347. for i:=1 to tcgsize2size[fromsize] do
  1348. begin
  1349. if not(QuickRef) and (i<tcgsize2size[fromsize]) then
  1350. href.addressmode:=AM_POSTINCREMENT
  1351. else
  1352. href.addressmode:=AM_UNCHANGED;
  1353. list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
  1354. if QuickRef then
  1355. inc(href.offset);
  1356. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1357. if i<tcgsize2size[fromsize] then
  1358. reg:=GetNextReg(reg);
  1359. end;
  1360. end;
  1361. if not(QuickRef) then
  1362. begin
  1363. ungetcpuregister(list,href.base);
  1364. ungetcpuregister(list,GetNextReg(href.base));
  1365. end;
  1366. end;
  1367. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1368. var
  1369. conv_done: boolean;
  1370. tmpreg : tregister;
  1371. i : integer;
  1372. begin
  1373. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1374. internalerror(2011021310);
  1375. conv_done:=false;
  1376. if tosize<>fromsize then
  1377. begin
  1378. conv_done:=true;
  1379. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1380. fromsize:=tosize;
  1381. case fromsize of
  1382. OS_8:
  1383. begin
  1384. emit_mov(list,reg2,reg1);
  1385. for i:=2 to tcgsize2size[tosize] do
  1386. begin
  1387. reg2:=GetNextReg(reg2);
  1388. emit_mov(list,reg2,NR_R1);
  1389. end;
  1390. end;
  1391. OS_S8:
  1392. begin
  1393. emit_mov(list,reg2,reg1);
  1394. if tcgsize2size[tosize]>1 then
  1395. begin
  1396. reg2:=GetNextReg(reg2);
  1397. emit_mov(list,reg2,NR_R1);
  1398. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1399. list.concat(taicpu.op_reg(A_COM,reg2));
  1400. tmpreg:=reg2;
  1401. for i:=3 to tcgsize2size[tosize] do
  1402. begin
  1403. reg2:=GetNextReg(reg2);
  1404. emit_mov(list,reg2,tmpreg);
  1405. end;
  1406. end;
  1407. end;
  1408. OS_16:
  1409. begin
  1410. emit_mov(list,reg2,reg1);
  1411. reg1:=GetNextReg(reg1);
  1412. reg2:=GetNextReg(reg2);
  1413. emit_mov(list,reg2,reg1);
  1414. for i:=3 to tcgsize2size[tosize] do
  1415. begin
  1416. reg2:=GetNextReg(reg2);
  1417. emit_mov(list,reg2,NR_R1);
  1418. end;
  1419. end;
  1420. OS_S16:
  1421. begin
  1422. emit_mov(list,reg2,reg1);
  1423. reg1:=GetNextReg(reg1);
  1424. reg2:=GetNextReg(reg2);
  1425. emit_mov(list,reg2,reg1);
  1426. if tcgsize2size[tosize]>2 then
  1427. begin
  1428. reg2:=GetNextReg(reg2);
  1429. emit_mov(list,reg2,NR_R1);
  1430. list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
  1431. list.concat(taicpu.op_reg(A_COM,reg2));
  1432. tmpreg:=reg2;
  1433. for i:=4 to tcgsize2size[tosize] do
  1434. begin
  1435. reg2:=GetNextReg(reg2);
  1436. emit_mov(list,reg2,tmpreg);
  1437. end;
  1438. end;
  1439. end;
  1440. else
  1441. conv_done:=false;
  1442. end;
  1443. end;
  1444. if not conv_done and (reg1<>reg2) then
  1445. begin
  1446. for i:=1 to tcgsize2size[fromsize] do
  1447. begin
  1448. emit_mov(list,reg2,reg1);
  1449. { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
  1450. if i<tcgsize2size[fromsize] then
  1451. begin
  1452. reg1:=GetNextReg(reg1);
  1453. reg2:=GetNextReg(reg2);
  1454. end;
  1455. end;
  1456. end;
  1457. end;
  1458. procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1459. begin
  1460. internalerror(2012010702);
  1461. end;
  1462. procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1463. begin
  1464. internalerror(2012010703);
  1465. end;
  1466. procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1467. begin
  1468. internalerror(2012010704);
  1469. end;
  1470. { comparison operations }
  1471. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1472. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1473. var
  1474. swapped : boolean;
  1475. tmpreg : tregister;
  1476. i : byte;
  1477. begin
  1478. if a=0 then
  1479. begin
  1480. swapped:=false;
  1481. { swap parameters? }
  1482. case cmp_op of
  1483. OC_GT:
  1484. begin
  1485. swapped:=true;
  1486. cmp_op:=OC_LT;
  1487. end;
  1488. OC_LTE:
  1489. begin
  1490. swapped:=true;
  1491. cmp_op:=OC_GTE;
  1492. end;
  1493. OC_BE:
  1494. begin
  1495. swapped:=true;
  1496. cmp_op:=OC_AE;
  1497. end;
  1498. OC_A:
  1499. begin
  1500. swapped:=true;
  1501. cmp_op:=OC_B;
  1502. end;
  1503. end;
  1504. if swapped then
  1505. list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
  1506. else
  1507. list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
  1508. for i:=2 to tcgsize2size[size] do
  1509. begin
  1510. reg:=GetNextReg(reg);
  1511. if swapped then
  1512. list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
  1513. else
  1514. list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
  1515. end;
  1516. a_jmp_cond(list,cmp_op,l);
  1517. end
  1518. else
  1519. inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
  1520. end;
  1521. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
  1522. cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1523. var
  1524. swapped : boolean;
  1525. tmpreg : tregister;
  1526. i : byte;
  1527. begin
  1528. swapped:=false;
  1529. { swap parameters? }
  1530. case cmp_op of
  1531. OC_GT:
  1532. begin
  1533. swapped:=true;
  1534. cmp_op:=OC_LT;
  1535. end;
  1536. OC_LTE:
  1537. begin
  1538. swapped:=true;
  1539. cmp_op:=OC_GTE;
  1540. end;
  1541. OC_BE:
  1542. begin
  1543. swapped:=true;
  1544. cmp_op:=OC_AE;
  1545. end;
  1546. OC_A:
  1547. begin
  1548. swapped:=true;
  1549. cmp_op:=OC_B;
  1550. end;
  1551. end;
  1552. if swapped then
  1553. begin
  1554. tmpreg:=reg1;
  1555. reg1:=reg2;
  1556. reg2:=tmpreg;
  1557. end;
  1558. list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
  1559. for i:=2 to tcgsize2size[size] do
  1560. begin
  1561. reg1:=GetNextReg(reg1);
  1562. reg2:=GetNextReg(reg2);
  1563. list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
  1564. end;
  1565. a_jmp_cond(list,cmp_op,l);
  1566. end;
  1567. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  1568. var
  1569. ai : taicpu;
  1570. begin
  1571. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1572. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION))
  1573. else
  1574. ai:=taicpu.op_sym(A_RJMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1575. ai.is_jmp:=true;
  1576. list.concat(ai);
  1577. end;
  1578. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  1579. var
  1580. ai : taicpu;
  1581. begin
  1582. if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
  1583. ai:=taicpu.op_sym(A_JMP,l)
  1584. else
  1585. ai:=taicpu.op_sym(A_RJMP,l);
  1586. ai.is_jmp:=true;
  1587. list.concat(ai);
  1588. end;
  1589. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1590. var
  1591. ai : taicpu;
  1592. begin
  1593. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  1594. ai.is_jmp:=true;
  1595. list.concat(ai);
  1596. end;
  1597. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1598. var
  1599. l : TAsmLabel;
  1600. tmpflags : TResFlags;
  1601. begin
  1602. current_asmdata.getjumplabel(l);
  1603. {
  1604. if flags_to_cond(f) then
  1605. begin
  1606. tmpflags:=f;
  1607. inverse_flags(tmpflags);
  1608. emit_mov(reg,NR_R1);
  1609. a_jmp_flags(list,tmpflags,l);
  1610. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1611. end
  1612. else
  1613. }
  1614. begin
  1615. list.concat(taicpu.op_reg_const(A_LDI,reg,1));
  1616. a_jmp_flags(list,f,l);
  1617. emit_mov(list,reg,NR_R1);
  1618. end;
  1619. cg.a_label(list,l);
  1620. end;
  1621. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  1622. var
  1623. i : integer;
  1624. begin
  1625. case value of
  1626. 0:
  1627. ;
  1628. {-14..-1:
  1629. begin
  1630. if ((-value) mod 2)<>0 then
  1631. list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  1632. for i:=1 to (-value) div 2 do
  1633. list.concat(taicpu.op_const(A_RCALL,0));
  1634. end;
  1635. 1..7:
  1636. begin
  1637. for i:=1 to value do
  1638. list.concat(taicpu.op_reg(A_POP,NR_R0));
  1639. end;}
  1640. else
  1641. begin
  1642. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  1643. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  1644. // get SREG
  1645. list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  1646. // block interrupts
  1647. list.concat(taicpu.op_none(A_CLI));
  1648. // write high SP
  1649. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  1650. // release interrupts
  1651. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  1652. // write low SP
  1653. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  1654. end;
  1655. end;
  1656. end;
  1657. function tcgavr.GetLoad(const ref: treference) : tasmop;
  1658. begin
  1659. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1660. result:=A_LDS
  1661. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1662. result:=A_LDD
  1663. else
  1664. result:=A_LD;
  1665. end;
  1666. function tcgavr.GetStore(const ref: treference) : tasmop;
  1667. begin
  1668. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  1669. result:=A_STS
  1670. else if (ref.base<>NR_NO) and (ref.offset<>0) then
  1671. result:=A_STD
  1672. else
  1673. result:=A_ST;
  1674. end;
  1675. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  1676. var
  1677. regs : tcpuregisterset;
  1678. reg : tsuperregister;
  1679. begin
  1680. if current_procinfo.procdef.isempty then
  1681. exit;
  1682. if po_interrupt in current_procinfo.procdef.procoptions then
  1683. begin
  1684. { check if the framepointer is actually used, this is done here because
  1685. we have to know the size of the locals (must be 0), avr does not know
  1686. an sp based stack }
  1687. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1688. (localsize=0) then
  1689. current_procinfo.framepointer:=NR_NO;
  1690. { save int registers,
  1691. but only if the procedure returns }
  1692. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1693. regs:=rg[R_INTREGISTER].used_in_proc
  1694. else
  1695. regs:=[];
  1696. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1697. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1698. an outer stackframe }
  1699. if current_procinfo.framepointer<>NR_NO then
  1700. regs:=regs+[RS_R28,RS_R29];
  1701. { we clear r1 }
  1702. include(regs,RS_R1);
  1703. regs:=regs+[RS_R0];
  1704. for reg:=RS_R31 downto RS_R0 do
  1705. if reg in regs then
  1706. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1707. { Save SREG }
  1708. list.concat(taicpu.op_reg_const(A_IN, NR_R0, $3F));
  1709. list.concat(taicpu.op_reg(A_PUSH, NR_R0));
  1710. list.concat(taicpu.op_reg(A_CLR,NR_R1));
  1711. if current_procinfo.framepointer<>NR_NO then
  1712. begin
  1713. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1714. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1715. a_adjust_sp(list,-localsize);
  1716. end;
  1717. end
  1718. else if not(nostackframe) then
  1719. begin
  1720. { check if the framepointer is actually used, this is done here because
  1721. we have to know the size of the locals (must be 0), avr does not know
  1722. an sp based stack }
  1723. if not(current_procinfo.procdef.stack_tainting_parameter(calleeside)) and
  1724. (localsize=0) then
  1725. current_procinfo.framepointer:=NR_NO;
  1726. { save int registers,
  1727. but only if the procedure returns }
  1728. if not(po_noreturn in current_procinfo.procdef.procoptions) then
  1729. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)
  1730. else
  1731. regs:=[];
  1732. { if the framepointer is potentially used, save it always because we need a proper stack frame,
  1733. even if the procedure never returns, the procedure could be e.g. a nested one accessing
  1734. an outer stackframe }
  1735. if current_procinfo.framepointer<>NR_NO then
  1736. regs:=regs+[RS_R28,RS_R29];
  1737. for reg:=RS_R31 downto RS_R0 do
  1738. if reg in regs then
  1739. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1740. if current_procinfo.framepointer<>NR_NO then
  1741. begin
  1742. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  1743. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  1744. a_adjust_sp(list,-localsize);
  1745. end;
  1746. end;
  1747. end;
  1748. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  1749. var
  1750. regs : tcpuregisterset;
  1751. reg : TSuperRegister;
  1752. LocalSize : longint;
  1753. begin
  1754. { every byte counts for avr, so if a subroutine is marked as non-returning, we do
  1755. not generate any exit code, so we really trust the noreturn directive
  1756. }
  1757. if po_noreturn in current_procinfo.procdef.procoptions then
  1758. exit;
  1759. if po_interrupt in current_procinfo.procdef.procoptions then
  1760. begin
  1761. if not(current_procinfo.procdef.isempty) then
  1762. begin
  1763. regs:=rg[R_INTREGISTER].used_in_proc;
  1764. if current_procinfo.framepointer<>NR_NO then
  1765. begin
  1766. regs:=regs+[RS_R28,RS_R29];
  1767. LocalSize:=current_procinfo.calc_stackframe_size;
  1768. a_adjust_sp(list,LocalSize);
  1769. end;
  1770. { we clear r1 }
  1771. include(regs,RS_R1);
  1772. { Reload SREG }
  1773. regs:=regs+[RS_R0];
  1774. list.concat(taicpu.op_reg(A_POP, NR_R0));
  1775. list.concat(taicpu.op_const_reg(A_OUT, $3F, NR_R0));
  1776. for reg:=RS_R0 to RS_R31 do
  1777. if reg in regs then
  1778. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1779. end;
  1780. list.concat(taicpu.op_none(A_RETI));
  1781. end
  1782. else if not(nostackframe) and not(current_procinfo.procdef.isempty) then
  1783. begin
  1784. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  1785. if current_procinfo.framepointer<>NR_NO then
  1786. begin
  1787. regs:=regs+[RS_R28,RS_R29];
  1788. LocalSize:=current_procinfo.calc_stackframe_size;
  1789. a_adjust_sp(list,LocalSize);
  1790. end;
  1791. for reg:=RS_R0 to RS_R31 do
  1792. if reg in regs then
  1793. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  1794. list.concat(taicpu.op_none(A_RET));
  1795. end
  1796. else
  1797. list.concat(taicpu.op_none(A_RET));
  1798. end;
  1799. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  1800. var
  1801. tmpref : treference;
  1802. begin
  1803. if ref.addressmode<>AM_UNCHANGED then
  1804. internalerror(2011021701);
  1805. if assigned(ref.symbol) or (ref.offset<>0) then
  1806. begin
  1807. reference_reset(tmpref,0,[]);
  1808. tmpref.symbol:=ref.symbol;
  1809. tmpref.offset:=ref.offset;
  1810. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1811. tmpref.refaddr:=addr_lo8_gs
  1812. else
  1813. tmpref.refaddr:=addr_lo8;
  1814. list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
  1815. if assigned(ref.symbol) and (ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) then
  1816. tmpref.refaddr:=addr_hi8_gs
  1817. else
  1818. tmpref.refaddr:=addr_hi8;
  1819. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
  1820. if (ref.base<>NR_NO) then
  1821. begin
  1822. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
  1823. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
  1824. end;
  1825. if (ref.index<>NR_NO) then
  1826. begin
  1827. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1828. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1829. end;
  1830. end
  1831. else if (ref.base<>NR_NO)then
  1832. begin
  1833. emit_mov(list,r,ref.base);
  1834. emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
  1835. if (ref.index<>NR_NO) then
  1836. begin
  1837. list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
  1838. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
  1839. end;
  1840. end
  1841. else if (ref.index<>NR_NO) then
  1842. begin
  1843. emit_mov(list,r,ref.index);
  1844. emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
  1845. end;
  1846. end;
  1847. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  1848. begin
  1849. internalerror(2011021320);
  1850. end;
  1851. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  1852. var
  1853. paraloc1,paraloc2,paraloc3 : TCGPara;
  1854. pd : tprocdef;
  1855. begin
  1856. pd:=search_system_proc('MOVE');
  1857. paraloc1.init;
  1858. paraloc2.init;
  1859. paraloc3.init;
  1860. paramanager.getintparaloc(list,pd,1,paraloc1);
  1861. paramanager.getintparaloc(list,pd,2,paraloc2);
  1862. paramanager.getintparaloc(list,pd,3,paraloc3);
  1863. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  1864. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  1865. a_loadaddr_ref_cgpara(list,source,paraloc1);
  1866. paramanager.freecgpara(list,paraloc3);
  1867. paramanager.freecgpara(list,paraloc2);
  1868. paramanager.freecgpara(list,paraloc1);
  1869. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1870. a_call_name_static(list,'FPC_MOVE');
  1871. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1872. paraloc3.done;
  1873. paraloc2.done;
  1874. paraloc1.done;
  1875. end;
  1876. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  1877. var
  1878. countreg,tmpreg : tregister;
  1879. srcref,dstref : treference;
  1880. copysize,countregsize : tcgsize;
  1881. l : TAsmLabel;
  1882. i : longint;
  1883. SrcQuickRef, DestQuickRef : Boolean;
  1884. begin
  1885. if len>16 then
  1886. begin
  1887. current_asmdata.getjumplabel(l);
  1888. reference_reset(srcref,source.alignment,source.volatility);
  1889. reference_reset(dstref,dest.alignment,source.volatility);
  1890. srcref.base:=NR_R30;
  1891. srcref.addressmode:=AM_POSTINCREMENT;
  1892. dstref.base:=NR_R26;
  1893. dstref.addressmode:=AM_POSTINCREMENT;
  1894. copysize:=OS_8;
  1895. if len<256 then
  1896. countregsize:=OS_8
  1897. else if len<65536 then
  1898. countregsize:=OS_16
  1899. else
  1900. internalerror(2011022007);
  1901. countreg:=getintregister(list,countregsize);
  1902. a_load_const_reg(list,countregsize,len,countreg);
  1903. a_loadaddr_ref_reg(list,source,NR_R30);
  1904. { only base or index register in dest? }
  1905. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1906. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1907. begin
  1908. if dest.base<>NR_NO then
  1909. tmpreg:=dest.base
  1910. else if dest.index<>NR_NO then
  1911. tmpreg:=dest.index
  1912. else
  1913. internalerror(2016112001);
  1914. end
  1915. else
  1916. begin
  1917. tmpreg:=getaddressregister(list);
  1918. a_loadaddr_ref_reg(list,dest,tmpreg);
  1919. end;
  1920. { X is used for spilling code so we can load it
  1921. only by a push/pop sequence, this can be
  1922. optimized later on by the peephole optimizer
  1923. }
  1924. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1925. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1926. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1927. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1928. cg.a_label(list,l);
  1929. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  1930. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  1931. list.concat(taicpu.op_reg(A_DEC,countreg));
  1932. a_jmp_flags(list,F_NE,l);
  1933. // keep registers alive
  1934. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  1935. end
  1936. else
  1937. begin
  1938. SrcQuickRef:=false;
  1939. DestQuickRef:=false;
  1940. if not((source.addressmode=AM_UNCHANGED) and
  1941. (source.symbol=nil) and
  1942. ((source.base=NR_R28) or
  1943. (source.base=NR_R30)) and
  1944. (source.Index=NR_NO) and
  1945. (source.Offset in [0..64-len])) and
  1946. not((source.Base=NR_NO) and (source.Index=NR_NO)) then
  1947. srcref:=normalize_ref(list,source,NR_R30)
  1948. else
  1949. begin
  1950. SrcQuickRef:=true;
  1951. srcref:=source;
  1952. end;
  1953. if not((dest.addressmode=AM_UNCHANGED) and
  1954. (dest.symbol=nil) and
  1955. ((dest.base=NR_R28) or
  1956. (dest.base=NR_R30)) and
  1957. (dest.Index=NR_No) and
  1958. (dest.Offset in [0..64-len])) and
  1959. not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
  1960. begin
  1961. if not(SrcQuickRef) then
  1962. begin
  1963. { only base or index register in dest? }
  1964. if ((dest.addressmode=AM_UNCHANGED) and (dest.offset=0) and not(assigned(dest.symbol))) and
  1965. ((dest.base<>NR_NO) xor (dest.index<>NR_NO)) then
  1966. begin
  1967. if dest.base<>NR_NO then
  1968. tmpreg:=dest.base
  1969. else if dest.index<>NR_NO then
  1970. tmpreg:=dest.index
  1971. else
  1972. internalerror(2016112002);
  1973. end
  1974. else
  1975. tmpreg:=getaddressregister(list);
  1976. dstref:=normalize_ref(list,dest,tmpreg);
  1977. { X is used for spilling code so we can load it
  1978. only by a push/pop sequence, this can be
  1979. optimized later on by the peephole optimizer
  1980. }
  1981. list.concat(taicpu.op_reg(A_PUSH,tmpreg));
  1982. list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
  1983. list.concat(taicpu.op_reg(A_POP,NR_R27));
  1984. list.concat(taicpu.op_reg(A_POP,NR_R26));
  1985. dstref.base:=NR_R26;
  1986. end
  1987. else
  1988. dstref:=normalize_ref(list,dest,NR_R30);
  1989. end
  1990. else
  1991. begin
  1992. DestQuickRef:=true;
  1993. dstref:=dest;
  1994. end;
  1995. for i:=1 to len do
  1996. begin
  1997. if not(SrcQuickRef) and (i<len) then
  1998. srcref.addressmode:=AM_POSTINCREMENT
  1999. else
  2000. srcref.addressmode:=AM_UNCHANGED;
  2001. if not(DestQuickRef) and (i<len) then
  2002. dstref.addressmode:=AM_POSTINCREMENT
  2003. else
  2004. dstref.addressmode:=AM_UNCHANGED;
  2005. list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
  2006. list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
  2007. if SrcQuickRef then
  2008. inc(srcref.offset);
  2009. if DestQuickRef then
  2010. inc(dstref.offset);
  2011. end;
  2012. if not(SrcQuickRef) then
  2013. begin
  2014. ungetcpuregister(list,srcref.base);
  2015. ungetcpuregister(list,TRegister(ord(srcref.base)+1));
  2016. end;
  2017. end;
  2018. end;
  2019. procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  2020. var
  2021. hl : tasmlabel;
  2022. ai : taicpu;
  2023. cond : TAsmCond;
  2024. begin
  2025. if not(cs_check_overflow in current_settings.localswitches) then
  2026. exit;
  2027. current_asmdata.getjumplabel(hl);
  2028. if not ((def.typ=pointerdef) or
  2029. ((def.typ=orddef) and
  2030. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2031. pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2032. cond:=C_VC
  2033. else
  2034. cond:=C_CC;
  2035. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2036. ai.SetCondition(cond);
  2037. ai.is_jmp:=true;
  2038. list.concat(ai);
  2039. a_call_name(list,'FPC_OVERFLOW',false);
  2040. a_label(list,hl);
  2041. end;
  2042. procedure tcgavr.g_save_registers(list: TAsmList);
  2043. begin
  2044. { this is done by the entry code }
  2045. end;
  2046. procedure tcgavr.g_restore_registers(list: TAsmList);
  2047. begin
  2048. { this is done by the exit code }
  2049. end;
  2050. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2051. var
  2052. ai1,ai2 : taicpu;
  2053. hl : TAsmLabel;
  2054. begin
  2055. ai1:=Taicpu.Op_sym(A_BRxx,l);
  2056. ai1.is_jmp:=true;
  2057. hl:=nil;
  2058. case cond of
  2059. OC_EQ:
  2060. ai1.SetCondition(C_EQ);
  2061. OC_GT:
  2062. begin
  2063. { emulate GT }
  2064. current_asmdata.getjumplabel(hl);
  2065. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2066. ai2.SetCondition(C_EQ);
  2067. ai2.is_jmp:=true;
  2068. list.concat(ai2);
  2069. ai1.SetCondition(C_GE);
  2070. end;
  2071. OC_LT:
  2072. ai1.SetCondition(C_LT);
  2073. OC_GTE:
  2074. ai1.SetCondition(C_GE);
  2075. OC_LTE:
  2076. begin
  2077. { emulate LTE }
  2078. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2079. ai2.SetCondition(C_EQ);
  2080. ai2.is_jmp:=true;
  2081. list.concat(ai2);
  2082. ai1.SetCondition(C_LT);
  2083. end;
  2084. OC_NE:
  2085. ai1.SetCondition(C_NE);
  2086. OC_BE:
  2087. begin
  2088. { emulate BE }
  2089. ai2:=Taicpu.Op_Sym(A_BRxx,l);
  2090. ai2.SetCondition(C_EQ);
  2091. ai2.is_jmp:=true;
  2092. list.concat(ai2);
  2093. ai1.SetCondition(C_LO);
  2094. end;
  2095. OC_B:
  2096. ai1.SetCondition(C_LO);
  2097. OC_AE:
  2098. ai1.SetCondition(C_SH);
  2099. OC_A:
  2100. begin
  2101. { emulate A (unsigned GT) }
  2102. current_asmdata.getjumplabel(hl);
  2103. ai2:=Taicpu.Op_Sym(A_BRxx,hl);
  2104. ai2.SetCondition(C_EQ);
  2105. ai2.is_jmp:=true;
  2106. list.concat(ai2);
  2107. ai1.SetCondition(C_SH);
  2108. end;
  2109. else
  2110. internalerror(2011082501);
  2111. end;
  2112. list.concat(ai1);
  2113. if assigned(hl) then
  2114. a_label(list,hl);
  2115. end;
  2116. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2117. var
  2118. instr: taicpu;
  2119. begin
  2120. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  2121. list.Concat(instr);
  2122. { Notify the register allocator that we have written a move instruction so
  2123. it can try to eliminate it. }
  2124. add_move_instruction(instr);
  2125. end;
  2126. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2127. begin
  2128. if not(size in [OS_S64,OS_64]) then
  2129. internalerror(2012102402);
  2130. tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2131. end;
  2132. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2133. begin
  2134. tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2135. end;
  2136. procedure create_codegen;
  2137. begin
  2138. cg:=tcgavr.create;
  2139. cg64:=tcg64favr.create;
  2140. end;
  2141. end.