cgcpu.pas 85 KB

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