cgcpu.pas 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573
  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 MOS Technology 65
  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. tregisterlist = array of tregister;
  29. { tcgmos6502 }
  30. tcgmos6502 = class(tcg)
  31. { true, if the next arithmetic operation should modify the flags }
  32. cgsetflags : boolean;
  33. procedure init_register_allocators;override;
  34. procedure done_register_allocators;override;
  35. procedure getcpuregisters(list:TAsmList;regs:tregisterlist);
  36. procedure ungetcpuregisters(list:TAsmList;regs:tregisterlist);
  37. function getaddressregister(list:TAsmList):TRegister;override;
  38. function GetOffsetReg(const r: TRegister;ofs : shortint): TRegister;override;
  39. function GetOffsetReg64(const r,rhi: TRegister;ofs : shortint): TRegister;override;
  40. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
  41. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);override;
  42. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
  43. procedure a_load_reg_cgpara(list : TAsmList; size : tcgsize;r : tregister; const cgpara : tcgpara);override;
  44. procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);override;
  45. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  46. procedure a_call_reg(list : TAsmList;reg: tregister);override;
  47. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
  48. procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
  49. { move instructions }
  50. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
  51. procedure a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : treference);override;
  52. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  53. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  54. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  55. { fpu move instructions }
  56. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
  57. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
  58. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
  59. { comparison operations }
  60. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  61. l : tasmlabel);override;
  62. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  63. procedure a_jmp_name(list : TAsmList;const s : string); override;
  64. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  65. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  66. { 6502-specific unsigned comparison code generation jmp helper }
  67. procedure a_jmp_unsigned_cmp_3way(list : TAsmList;onbelow,onequal,onabove: tasmlabel);
  68. { 6502-specific signed comparison code generation jmp helper }
  69. procedure a_jmp_signed_cmp_3way(list : TAsmList;onless,onequal,ongreater: tasmlabel);
  70. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  71. procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
  72. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  73. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  74. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  75. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
  76. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  77. procedure g_save_registers(list : TAsmList);override;
  78. procedure g_restore_registers(list : TAsmList);override;
  79. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  80. //function normalize_ref(list : TAsmList;ref : treference; const refopertypes:trefoperandtypes; out allocatedregs:tregisterlist) : treference;
  81. procedure adjust_normalized_ref(list: TAsmList;var ref: treference; value: longint);
  82. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  83. //procedure a_adjust_sp(list: TAsmList; value: longint);
  84. protected
  85. //procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  86. //procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
  87. procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
  88. end;
  89. tcg64fmos6502 = class(tcg64f32)
  90. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  91. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  92. end;
  93. procedure create_codegen;
  94. //const
  95. // TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_LD,A_ADD,A_AND,A_NONE,
  96. // A_NONE,A_NONE,A_NONE,A_NEG,A_CPL,A_OR,
  97. // A_SRA,A_SLA,A_SRL,A_SUB,A_XOR,A_RLCA,A_RRCA);
  98. implementation
  99. uses
  100. globals,verbose,systems,cutils,
  101. fmodule,
  102. symconst,symsym,symtable,
  103. tgobj,rgobj,
  104. procinfo,cpupi,
  105. paramgr;
  106. function ref2string(const ref : treference) : string;
  107. begin
  108. result:='[base:'+std_regname(ref.base)+' index:'+std_regname(ref.index)+' refaddr:' + tostr(ord(ref.refaddr)) + ' offset:' + tostr(ref.offset) + ' symbol:';
  109. if (assigned(ref.symbol)) then
  110. result := result + ref.symbol.name;
  111. result:=result+']';
  112. end;
  113. function use_push(const cgpara:tcgpara):boolean;
  114. begin
  115. result:=(not paramanager.use_fixed_stack) and
  116. assigned(cgpara.location) and
  117. (cgpara.location^.loc=LOC_REFERENCE) and
  118. (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
  119. end;
  120. procedure tcgmos6502.init_register_allocators;
  121. begin
  122. inherited init_register_allocators;
  123. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  124. [RS_RZB0,RS_RZB1,RS_RZB2,RS_RZB3,RS_RZB4,RS_RZB5,RS_RZB6,RS_RZB7,RS_RZB8,RS_RZB9,RS_RZB10,RS_RZB11,RS_RZB249,
  125. RS_RZW187,RS_RZW243,RS_RZW245,RS_RZW247],first_int_imreg,[]);
  126. end;
  127. procedure tcgmos6502.done_register_allocators;
  128. begin
  129. rg[R_INTREGISTER].free;
  130. inherited done_register_allocators;
  131. end;
  132. procedure tcgmos6502.getcpuregisters(list: TAsmList; regs: tregisterlist);
  133. var
  134. r: tregister;
  135. begin
  136. for r in regs do
  137. getcpuregister(list,r);
  138. end;
  139. procedure tcgmos6502.ungetcpuregisters(list: TAsmList; regs: tregisterlist);
  140. var
  141. r: tregister;
  142. begin
  143. for r in regs do
  144. ungetcpuregister(list,r);
  145. end;
  146. function tcgmos6502.getaddressregister(list: TAsmList): TRegister;
  147. begin
  148. Result:=getintregister(list,OS_ADDR);
  149. end;
  150. function tcgmos6502.GetOffsetReg(const r: TRegister; ofs: shortint): TRegister;
  151. var
  152. i: Integer;
  153. begin
  154. result:=r;
  155. for i:=1 to ofs do
  156. result:=GetNextReg(result);
  157. end;
  158. function tcgmos6502.GetOffsetReg64(const r, rhi: TRegister; ofs: shortint): TRegister;
  159. var
  160. i: Integer;
  161. begin
  162. if ofs>=4 then
  163. begin
  164. result:=rhi;
  165. dec(ofs,4);
  166. end
  167. else
  168. result:=r;
  169. for i:=1 to ofs do
  170. result:=GetNextReg(result);
  171. end;
  172. procedure tcgmos6502.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  173. //procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  174. // var
  175. // ref : treference;
  176. // begin
  177. // paramanager.allocparaloc(list,paraloc);
  178. // case paraloc^.loc of
  179. // LOC_REGISTER,LOC_CREGISTER:
  180. // a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  181. // LOC_REFERENCE,LOC_CREFERENCE:
  182. // begin
  183. // reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
  184. // a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
  185. // end;
  186. // else
  187. // internalerror(2002071003);
  188. // end;
  189. // end;
  190. //
  191. //var
  192. // i, i2 : longint;
  193. // hp : PCGParaLocation;
  194. begin
  195. //if use_push(cgpara) then
  196. // begin
  197. // case tcgsize2size[cgpara.Size] of
  198. // 1:
  199. // begin
  200. // cgpara.check_simple_location;
  201. // getcpuregister(list,NR_A);
  202. // a_load_reg_reg(list,OS_8,OS_8,r,NR_A);
  203. // list.concat(taicpu.op_reg(A_PUSH,NR_AF));
  204. // list.concat(taicpu.op_reg(A_INC,NR_SP));
  205. // ungetcpuregister(list,NR_A);
  206. // end;
  207. // 2:
  208. // begin
  209. // cgpara.check_simple_location;
  210. // getcpuregister(list,NR_L);
  211. // a_load_reg_reg(list,OS_8,OS_8,r,NR_L);
  212. // getcpuregister(list,NR_H);
  213. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(r),NR_H);
  214. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  215. // getcpuregister(list,NR_H);
  216. // getcpuregister(list,NR_L);
  217. // end;
  218. // 4:
  219. // begin
  220. // cgpara.check_simple_location;
  221. //
  222. // getcpuregister(list,NR_L);
  223. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(GetNextReg(r)),NR_L);
  224. // getcpuregister(list,NR_H);
  225. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(GetNextReg(GetNextReg(r))),NR_H);
  226. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  227. // getcpuregister(list,NR_H);
  228. // getcpuregister(list,NR_L);
  229. //
  230. // getcpuregister(list,NR_L);
  231. // a_load_reg_reg(list,OS_8,OS_8,r,NR_L);
  232. // getcpuregister(list,NR_H);
  233. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(r),NR_H);
  234. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  235. // getcpuregister(list,NR_H);
  236. // getcpuregister(list,NR_L);
  237. // end;
  238. // else
  239. // internalerror(2020040801);
  240. // end;
  241. // end
  242. //else
  243. // begin
  244. // if not(tcgsize2size[cgpara.Size] in [1..4]) then
  245. // internalerror(2014011101);
  246. //
  247. // hp:=cgpara.location;
  248. //
  249. // i:=0;
  250. // while i<tcgsize2size[cgpara.Size] do
  251. // begin
  252. // if not(assigned(hp)) then
  253. // internalerror(2014011102);
  254. //
  255. // inc(i, tcgsize2size[hp^.Size]);
  256. //
  257. // if hp^.Loc=LOC_REGISTER then
  258. // begin
  259. // load_para_loc(r,hp);
  260. // hp:=hp^.Next;
  261. // r:=GetNextReg(r);
  262. // end
  263. // else
  264. // begin
  265. // load_para_loc(r,hp);
  266. //
  267. // for i2:=1 to tcgsize2size[hp^.Size] do
  268. // r:=GetNextReg(r);
  269. //
  270. // hp:=hp^.Next;
  271. // end;
  272. // end;
  273. // if assigned(hp) then
  274. // internalerror(2014011103);
  275. // end;
  276. end;
  277. procedure tcgmos6502.a_loadfpu_ref_cgpara(list: TAsmList; size: tcgsize; const ref: treference; const cgpara: TCGPara);
  278. var
  279. href: treference;
  280. curloc: PCGParaLocation;
  281. i: Integer;
  282. begin
  283. case cgpara.location^.loc of
  284. LOC_REGISTER,LOC_CREGISTER:
  285. begin
  286. case size of
  287. OS_F32:
  288. begin
  289. curloc:=cgpara.location;
  290. href:=ref;
  291. for i:=1 to 4 do
  292. begin
  293. if not assigned(curloc) then
  294. internalerror(2020042303);
  295. if not (curloc^.Loc in [LOC_REGISTER,LOC_CREGISTER]) then
  296. internalerror(2020042304);
  297. a_load_ref_reg(list,OS_8,OS_8,href,curloc^.register);
  298. curloc:=curloc^.Next;
  299. end;
  300. if assigned(curloc) then
  301. internalerror(2020042305);
  302. end;
  303. else
  304. internalerror(2020042302);
  305. end;
  306. end;
  307. else
  308. inherited;
  309. end;
  310. end;
  311. procedure tcgmos6502.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
  312. //var
  313. // i : longint;
  314. // hp : PCGParaLocation;
  315. // ref: treference;
  316. begin
  317. //if not(tcgsize2size[paraloc.Size] in [1..4]) then
  318. // internalerror(2014011104);
  319. //
  320. //if use_push(paraloc) then
  321. // begin
  322. // case tcgsize2size[paraloc.Size] of
  323. // 1:
  324. // begin
  325. // getcpuregister(list,NR_A);
  326. // a_load_const_reg(list,OS_8,a,NR_A);
  327. // list.Concat(taicpu.op_reg(A_PUSH,NR_AF));
  328. // list.Concat(taicpu.op_reg(A_INC,NR_SP));
  329. // ungetcpuregister(list,NR_A);
  330. // end;
  331. // 2:
  332. // begin
  333. // getcpuregister(list,NR_IY);
  334. // list.Concat(taicpu.op_reg_const(A_LD,NR_IY,a));
  335. // list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  336. // ungetcpuregister(list,NR_IY);
  337. // end;
  338. // 4:
  339. // begin
  340. // getcpuregister(list,NR_IY);
  341. // list.Concat(taicpu.op_reg_const(A_LD,NR_IY,Word(a shr 16)));
  342. // list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  343. // if Word(a)<>Word(a shr 16) then
  344. // list.Concat(taicpu.op_reg_const(A_LD,NR_IY,Word(a)));
  345. // list.Concat(taicpu.op_reg(A_PUSH,NR_IY));
  346. // ungetcpuregister(list,NR_IY);
  347. // end;
  348. // else
  349. // internalerror(2020040701);
  350. // end;
  351. // end
  352. //else
  353. // begin
  354. // hp:=paraloc.location;
  355. //
  356. // i:=1;
  357. // while i<=tcgsize2size[paraloc.Size] do
  358. // begin
  359. // if not(assigned(hp)) then
  360. // internalerror(2014011105);
  361. // //paramanager.allocparaloc(list,hp);
  362. // case hp^.loc of
  363. // LOC_REGISTER,LOC_CREGISTER:
  364. // begin
  365. // if (tcgsize2size[hp^.size]<>1) or
  366. // (hp^.shiftval<>0) then
  367. // internalerror(2015041101);
  368. // a_load_const_reg(list,hp^.size,(a shr (8*(i-1))) and $ff,hp^.register);
  369. //
  370. // inc(i,tcgsize2size[hp^.size]);
  371. // hp:=hp^.Next;
  372. // end;
  373. // LOC_REFERENCE,LOC_CREFERENCE:
  374. // begin
  375. // reference_reset(ref,paraloc.alignment,[]);
  376. // ref.base:=hp^.reference.index;
  377. // ref.offset:=hp^.reference.offset;
  378. // a_load_const_ref(list,hp^.size,a shr (8*(i-1)),ref);
  379. //
  380. // inc(i,tcgsize2size[hp^.size]);
  381. // hp:=hp^.Next;
  382. // end;
  383. // else
  384. // internalerror(2002071005);
  385. // end;
  386. // end;
  387. // end;
  388. end;
  389. procedure tcgmos6502.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);
  390. //procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
  391. //var
  392. // pushsize : tcgsize;
  393. // opsize : topsize;
  394. // tmpreg : tregister;
  395. // href,tmpref: treference;
  396. //begin
  397. // if not assigned(paraloc) then
  398. // exit;
  399. // if (paraloc^.loc<>LOC_REFERENCE) or
  400. // (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  401. // (tcgsize2size[paraloc^.size]>4) then
  402. // internalerror(200501162);
  403. // { Pushes are needed in reverse order, add the size of the
  404. // current location to the offset where to load from. This
  405. // prevents wrong calculations for the last location when
  406. // the size is not a power of 2 }
  407. // if assigned(paraloc^.next) then
  408. // pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  409. // { Push the data starting at ofs }
  410. // href:=r;
  411. // inc(href.offset,ofs);
  412. // {if tcgsize2size[paraloc^.size]>cgpara.alignment then}
  413. // pushsize:=paraloc^.size
  414. // {else
  415. // pushsize:=int_cgsize(cgpara.alignment)};
  416. // {Writeln(pushsize);}
  417. // case tcgsize2size[pushsize] of
  418. // 1:
  419. // begin
  420. // tmpreg:=getintregister(list,OS_8);
  421. // a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  422. // getcpuregister(list,NR_A);
  423. // a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_A);
  424. // list.concat(taicpu.op_reg(A_PUSH,NR_AF));
  425. // list.concat(taicpu.op_reg(A_INC,NR_SP));
  426. // ungetcpuregister(list,NR_A);
  427. // end;
  428. // 2:
  429. // begin
  430. // tmpreg:=getintregister(list,OS_16);
  431. // a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  432. // getcpuregister(list,NR_L);
  433. // a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_L);
  434. // getcpuregister(list,NR_H);
  435. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(tmpreg),NR_H);
  436. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  437. // ungetcpuregister(list,NR_H);
  438. // ungetcpuregister(list,NR_L);
  439. // end;
  440. // 4:
  441. // begin
  442. // tmpreg:=getintregister(list,OS_16);
  443. // inc(href.offset,2);
  444. // a_load_ref_reg(list,OS_16,OS_16,href,tmpreg);
  445. // getcpuregister(list,NR_L);
  446. // a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_L);
  447. // getcpuregister(list,NR_H);
  448. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(tmpreg),NR_H);
  449. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  450. // ungetcpuregister(list,NR_H);
  451. // ungetcpuregister(list,NR_L);
  452. // dec(href.offset,2);
  453. // a_load_ref_reg(list,OS_16,OS_16,href,tmpreg);
  454. // getcpuregister(list,NR_L);
  455. // a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_L);
  456. // getcpuregister(list,NR_H);
  457. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(tmpreg),NR_H);
  458. // list.concat(taicpu.op_reg(A_PUSH,NR_HL));
  459. // ungetcpuregister(list,NR_H);
  460. // ungetcpuregister(list,NR_L);
  461. // end;
  462. // else
  463. // internalerror(2020040803);
  464. // end;
  465. //end;
  466. //var
  467. // tmpref, ref, href: treference;
  468. // location: pcgparalocation;
  469. // sizeleft: tcgint;
  470. // len: tcgint;
  471. begin
  472. //{ cgpara.size=OS_NO requires a copy on the stack }
  473. //if use_push(cgpara) then
  474. // begin
  475. // { Record copy? }
  476. // if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
  477. // begin
  478. // cgpara.check_simple_location;
  479. // len:=align(cgpara.intsize,cgpara.alignment);
  480. // g_stackpointer_alloc(list,len);
  481. // reference_reset_base(href,NR_STACK_POINTER_REG,0,ctempposinvalid,4,[]);
  482. // g_concatcopy(list,r,href,len);
  483. // end
  484. // else
  485. // begin
  486. // if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  487. // internalerror(200501161);
  488. // { We need to push the data in reverse order,
  489. // therefor we use a recursive algorithm }
  490. // pushdata(cgpara.location,0);
  491. // end
  492. // end
  493. //else
  494. // begin
  495. // location := cgpara.location;
  496. // tmpref := r;
  497. // sizeleft := cgpara.intsize;
  498. // while assigned(location) do
  499. // begin
  500. // paramanager.allocparaloc(list,location);
  501. // case location^.loc of
  502. // LOC_REGISTER,LOC_CREGISTER:
  503. // a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  504. // LOC_REFERENCE:
  505. // begin
  506. // reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,cgpara.alignment,[]);
  507. // { doubles in softemu mode have a strange order of registers and references }
  508. // if location^.size=OS_32 then
  509. // g_concatcopy(list,tmpref,ref,4)
  510. // else
  511. // begin
  512. // g_concatcopy(list,tmpref,ref,sizeleft);
  513. // if assigned(location^.next) then
  514. // internalerror(2005010710);
  515. // end;
  516. // end;
  517. // LOC_VOID:
  518. // begin
  519. // // nothing to do
  520. // end;
  521. // else
  522. // internalerror(2002081103);
  523. // end;
  524. // inc(tmpref.offset,tcgsize2size[location^.size]);
  525. // dec(sizeleft,tcgsize2size[location^.size]);
  526. // location := location^.next;
  527. // end;
  528. // end;
  529. end;
  530. procedure tcgmos6502.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  531. var
  532. tmpreg: tregister;
  533. begin
  534. tmpreg:=getaddressregister(list);
  535. a_loadaddr_ref_reg(list,r,tmpreg);
  536. a_load_reg_cgpara(list,OS_ADDR,tmpreg,paraloc);
  537. end;
  538. procedure tcgmos6502.a_call_name(list : TAsmList;const s : string; weak: boolean);
  539. var
  540. sym: TAsmSymbol;
  541. begin
  542. if weak then
  543. sym:=current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION)
  544. else
  545. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION);
  546. list.concat(taicpu.op_sym(A_JSR,sym));
  547. include(current_procinfo.flags,pi_do_call);
  548. end;
  549. procedure tcgmos6502.a_call_reg(list : TAsmList;reg: tregister);
  550. //var
  551. // l : TAsmLabel;
  552. // ref : treference;
  553. begin
  554. //{ HACK: at this point all registers are allocated, due to the way the
  555. // calling convention works, but we need to free some registers, in order
  556. // for the following code to work, so we do it here }
  557. //dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  558. //
  559. //getcpuregister(list,NR_L);
  560. //a_load_reg_reg(list,OS_8,OS_8,reg,NR_L);
  561. //getcpuregister(list,NR_H);
  562. //a_load_reg_reg(list,OS_8,OS_8,GetNextReg(reg),NR_H);
  563. //current_asmdata.getjumplabel(l);
  564. //reference_reset(ref,0,[]);
  565. //ref.symbol:=l;
  566. //list.concat(taicpu.op_ref_reg(A_LD,ref,NR_HL));
  567. //ungetcpuregister(list,NR_H);
  568. //ungetcpuregister(list,NR_L);
  569. //
  570. //{ allocate them again, right before the actual call instruction }
  571. //alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  572. //
  573. //list.concat(tai_const.Create_8bit($CD)); { $CD is the opcode of the call instruction }
  574. //list.concat(tai_label.Create(l));
  575. //list.concat(tai_const.Create_16bit(0));
  576. //include(current_procinfo.flags,pi_do_call);
  577. end;
  578. procedure tcgmos6502.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
  579. begin
  580. list.Concat(tai_comment.Create(strpnew('TODO: a_op_const_reg '+topcg2str(Op)+' '+tcgsize2str(size)+' '+tostr(a)+' '+std_regname(reg))));
  581. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  582. internalerror(2012102403);
  583. //a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
  584. end;
  585. procedure tcgmos6502.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
  586. begin
  587. list.Concat(tai_comment.Create(strpnew('TODO: a_op_reg_reg '+topcg2str(Op)+' '+tcgsize2str(size)+' '+std_regname(src)+' '+std_regname(dst))));
  588. if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
  589. internalerror(2012102401);
  590. //a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
  591. end;
  592. //procedure tcgmos6502.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
  593. // var
  594. // i : integer;
  595. //
  596. // procedure NextSrcDst;
  597. // begin
  598. // if i=5 then
  599. // begin
  600. // dst:=dsthi;
  601. // src:=srchi;
  602. // end
  603. // else
  604. // begin
  605. // dst:=GetNextReg(dst);
  606. // src:=GetNextReg(src);
  607. // end;
  608. // end;
  609. //
  610. // var
  611. // tmpreg,tmpreg2: tregister;
  612. // instr : taicpu;
  613. // l1,l2 : tasmlabel;
  614. //
  615. // begin
  616. // case op of
  617. // OP_ADD:
  618. // begin
  619. // getcpuregister(list,NR_A);
  620. // a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  621. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,src));
  622. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  623. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  624. // begin
  625. // for i:=2 to tcgsize2size[size] do
  626. // begin
  627. // NextSrcDst;
  628. // a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  629. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,src));
  630. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  631. // end;
  632. // end;
  633. // ungetcpuregister(list,NR_A);
  634. // end;
  635. //
  636. // OP_SUB:
  637. // begin
  638. // getcpuregister(list,NR_A);
  639. // a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  640. // list.concat(taicpu.op_reg_reg(A_SUB,NR_A,src));
  641. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  642. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  643. // begin
  644. // for i:=2 to tcgsize2size[size] do
  645. // begin
  646. // NextSrcDst;
  647. // a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  648. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,src));
  649. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  650. // end;
  651. // end;
  652. // ungetcpuregister(list,NR_A);
  653. // end;
  654. //
  655. // OP_NEG:
  656. // begin
  657. // getcpuregister(list,NR_A);
  658. // if tcgsize2size[size]>=2 then
  659. // begin
  660. // tmpreg:=GetNextReg(src);
  661. // tmpreg2:=GetNextReg(dst);
  662. // for i:=2 to tcgsize2size[size] do
  663. // begin
  664. // a_load_reg_reg(list,OS_8,OS_8,tmpreg,NR_A);
  665. // list.concat(taicpu.op_none(A_CPL));
  666. // a_load_reg_reg(list,OS_8,OS_8,NR_A,tmpreg2);
  667. // if i<>tcgsize2size[size] then
  668. // begin
  669. // if i=4 then
  670. // begin
  671. // tmpreg:=srchi;
  672. // tmpreg2:=dsthi;
  673. // end
  674. // else
  675. // begin
  676. // tmpreg:=GetNextReg(tmpreg);
  677. // tmpreg2:=GetNextReg(tmpreg2);
  678. // end;
  679. // end;
  680. // end;
  681. // end;
  682. // a_load_reg_reg(list,OS_8,OS_8,src,NR_A);
  683. // list.concat(taicpu.op_none(A_NEG));
  684. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  685. // if tcgsize2size[size]>=2 then
  686. // begin
  687. // tmpreg2:=GetNextReg(dst);
  688. // for i:=2 to tcgsize2size[size] do
  689. // begin
  690. // a_load_reg_reg(list,OS_8,OS_8,tmpreg2,NR_A);
  691. // list.concat(taicpu.op_reg_const(A_SBC,NR_A,-1));
  692. // a_load_reg_reg(list,OS_8,OS_8,NR_A,tmpreg2);
  693. // if i<>tcgsize2size[size] then
  694. // begin
  695. // if i=4 then
  696. // begin
  697. // tmpreg2:=dsthi;
  698. // end
  699. // else
  700. // begin
  701. // tmpreg2:=GetNextReg(tmpreg2);
  702. // end;
  703. // end;
  704. // end;
  705. // end;
  706. // ungetcpuregister(list,NR_A);
  707. // end;
  708. //
  709. // OP_NOT:
  710. // begin
  711. // getcpuregister(list,NR_A);
  712. // for i:=1 to tcgsize2size[size] do
  713. // begin
  714. // if i<>1 then
  715. // NextSrcDst;
  716. // a_load_reg_reg(list,OS_8,OS_8,src,NR_A);
  717. // list.concat(taicpu.op_none(A_CPL));
  718. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  719. // end;
  720. // ungetcpuregister(list,NR_A);
  721. // end;
  722. //
  723. // OP_MUL,OP_IMUL:
  724. // begin
  725. // tmpreg:=dst;
  726. // if size in [OS_16,OS_S16] then
  727. // begin
  728. // tmpreg:=getintregister(list,size);
  729. // a_load_reg_reg(list,size,size,dst,tmpreg);
  730. // end;
  731. // gen_multiply(list,op,size,src,tmpreg,dst,false);
  732. // end;
  733. //
  734. // OP_DIV,OP_IDIV:
  735. // { special stuff, needs separate handling inside code
  736. // generator }
  737. // internalerror(2017032604);
  738. //
  739. // OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  740. // begin
  741. // current_asmdata.getjumplabel(l1);
  742. // current_asmdata.getjumplabel(l2);
  743. // getcpuregister(list,NR_B);
  744. // emit_mov(list,NR_B,src);
  745. // list.concat(taicpu.op_reg(A_INC,NR_B));
  746. // list.concat(taicpu.op_reg(A_DEC,NR_B));
  747. // a_jmp_flags(list,F_E,l2);
  748. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  749. // case op of
  750. // OP_ROL:
  751. // begin
  752. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  753. // list.concat(taicpu.op_reg(A_RLC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  754. // end;
  755. // OP_ROR:
  756. // begin
  757. // list.concat(taicpu.op_reg(A_RLC,dst));
  758. // list.concat(taicpu.op_reg(A_RRC,dst));
  759. // end;
  760. // else
  761. // ;
  762. // end;
  763. // cg.a_label(list,l1);
  764. // case op of
  765. // OP_SHL:
  766. // list.concat(taicpu.op_reg(A_SLA,dst));
  767. // OP_SHR:
  768. // list.concat(taicpu.op_reg(A_SRL,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  769. // OP_SAR:
  770. // list.concat(taicpu.op_reg(A_SRA,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  771. // OP_ROL:
  772. // if size in [OS_8,OS_S8] then
  773. // list.concat(taicpu.op_reg(A_RLC,dst))
  774. // else
  775. // list.concat(taicpu.op_reg(A_RL,dst));
  776. // OP_ROR:
  777. // if size in [OS_8,OS_S8] then
  778. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)))
  779. // else
  780. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  781. // else
  782. // internalerror(2020040903);
  783. // end;
  784. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  785. // begin
  786. // for i:=2 to tcgsize2size[size] do
  787. // begin
  788. // case op of
  789. // OP_ROR,
  790. // OP_SHR,
  791. // OP_SAR:
  792. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  793. // OP_ROL,
  794. // OP_SHL:
  795. // list.concat(taicpu.op_reg(A_RL,GetOffsetReg64(dst,dsthi,i-1)));
  796. // else
  797. // internalerror(2020040904);
  798. // end;
  799. // end;
  800. // end;
  801. // instr:=taicpu.op_sym(A_DJNZ,l1);
  802. // instr.is_jmp:=true;
  803. // list.concat(instr);
  804. // ungetcpuregister(list,NR_B);
  805. // cg.a_label(list,l2);
  806. // end;
  807. //
  808. // OP_AND,OP_OR,OP_XOR:
  809. // begin
  810. // getcpuregister(list,NR_A);
  811. // for i:=1 to tcgsize2size[size] do
  812. // begin
  813. // if i<>1 then
  814. // NextSrcDst;
  815. // a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  816. // list.concat(taicpu.op_reg_reg(topcg2asmop[op],NR_A,src));
  817. // a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  818. // end;
  819. // ungetcpuregister(list,NR_A);
  820. // end;
  821. // else
  822. // internalerror(2011022004);
  823. // end;
  824. // end;
  825. //
  826. //procedure tcgmos6502.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  827. // size: TCGSize; a: tcgint; reg, reghi: TRegister);
  828. //
  829. // var
  830. // i : byte;
  831. //
  832. // procedure NextReg;
  833. // begin
  834. // if i=4 then
  835. // reg:=reghi
  836. // else
  837. // reg:=GetNextReg(reg);
  838. // end;
  839. //
  840. // var
  841. // mask : qword;
  842. // shift : byte;
  843. // curvalue : byte;
  844. // tmpop: TAsmOp;
  845. // l1: TAsmLabel;
  846. // instr: taicpu;
  847. // tmpreg : tregister;
  848. // tmpreg64 : tregister64;
  849. //
  850. // begin
  851. // optimize_op_const(size,op,a);
  852. // mask:=$ff;
  853. // shift:=0;
  854. // l1:=nil;
  855. // case op of
  856. // OP_NONE:
  857. // begin
  858. // { Opcode is optimized away }
  859. // end;
  860. // OP_MOVE:
  861. // begin
  862. // { Optimized, replaced with a simple load }
  863. // a_load_const_reg(list,size,a,reg);
  864. // end;
  865. // OP_AND:
  866. // begin
  867. // curvalue:=a and mask;
  868. // for i:=1 to tcgsize2size[size] do
  869. // begin
  870. // case curvalue of
  871. // 0:
  872. // list.concat(taicpu.op_reg_const(A_LD,reg,0));
  873. // $ff:
  874. // {nothing};
  875. // else
  876. // begin
  877. // getcpuregister(list,NR_A);
  878. // emit_mov(list,NR_A,reg);
  879. // list.concat(taicpu.op_reg_const(A_AND,NR_A,curvalue));
  880. // emit_mov(list,reg,NR_A);
  881. // ungetcpuregister(list,NR_A);
  882. // end;
  883. // end;
  884. // if i<>tcgsize2size[size] then
  885. // begin
  886. // NextReg;
  887. // mask:=mask shl 8;
  888. // inc(shift,8);
  889. // curvalue:=(qword(a) and mask) shr shift;
  890. // end;
  891. // end;
  892. // end;
  893. // OP_OR:
  894. // begin
  895. // curvalue:=a and mask;
  896. // for i:=1 to tcgsize2size[size] do
  897. // begin
  898. // case curvalue of
  899. // 0:
  900. // {nothing};
  901. // $ff:
  902. // list.concat(taicpu.op_reg_const(A_LD,reg,$ff));
  903. // else
  904. // begin
  905. // getcpuregister(list,NR_A);
  906. // emit_mov(list,NR_A,reg);
  907. // list.concat(taicpu.op_reg_const(A_OR,NR_A,curvalue));
  908. // emit_mov(list,reg,NR_A);
  909. // ungetcpuregister(list,NR_A);
  910. // end;
  911. // end;
  912. // if i<>tcgsize2size[size] then
  913. // begin
  914. // NextReg;
  915. // mask:=mask shl 8;
  916. // inc(shift,8);
  917. // curvalue:=(qword(a) and mask) shr shift;
  918. // end;
  919. // end;
  920. // end;
  921. // OP_XOR:
  922. // begin
  923. // curvalue:=a and mask;
  924. // for i:=1 to tcgsize2size[size] do
  925. // begin
  926. // case curvalue of
  927. // 0:
  928. // {nothing};
  929. // $ff:
  930. // begin
  931. // getcpuregister(list,NR_A);
  932. // emit_mov(list,NR_A,reg);
  933. // list.concat(taicpu.op_none(A_CPL));
  934. // emit_mov(list,reg,NR_A);
  935. // ungetcpuregister(list,NR_A);
  936. // end;
  937. // else
  938. // begin
  939. // getcpuregister(list,NR_A);
  940. // emit_mov(list,NR_A,reg);
  941. // list.concat(taicpu.op_reg_const(A_XOR,NR_A,curvalue));
  942. // emit_mov(list,reg,NR_A);
  943. // ungetcpuregister(list,NR_A);
  944. // end;
  945. // end;
  946. // if i<>tcgsize2size[size] then
  947. // begin
  948. // NextReg;
  949. // mask:=mask shl 8;
  950. // inc(shift,8);
  951. // curvalue:=(qword(a) and mask) shr shift;
  952. // end;
  953. // end;
  954. // end;
  955. // OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  956. // begin
  957. // if size in [OS_64,OS_S64] then
  958. // a:=a and 63
  959. // else
  960. // a:=a and 31;
  961. // if a<>0 then
  962. // begin
  963. // if a>1 then
  964. // begin
  965. // current_asmdata.getjumplabel(l1);
  966. // getcpuregister(list,NR_B);
  967. // list.concat(taicpu.op_reg_const(A_LD,NR_B,a));
  968. // end;
  969. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  970. // case op of
  971. // OP_ROL:
  972. // begin
  973. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  974. // list.concat(taicpu.op_reg(A_RLC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  975. // end;
  976. // OP_ROR:
  977. // begin
  978. // list.concat(taicpu.op_reg(A_RLC,reg));
  979. // list.concat(taicpu.op_reg(A_RRC,reg));
  980. // end;
  981. // else
  982. // ;
  983. // end;
  984. // if a>1 then
  985. // cg.a_label(list,l1);
  986. // case op of
  987. // OP_SHL:
  988. // list.concat(taicpu.op_reg(A_SLA,reg));
  989. // OP_SHR:
  990. // list.concat(taicpu.op_reg(A_SRL,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  991. // OP_SAR:
  992. // list.concat(taicpu.op_reg(A_SRA,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  993. // OP_ROL:
  994. // if size in [OS_8,OS_S8] then
  995. // list.concat(taicpu.op_reg(A_RLC,reg))
  996. // else
  997. // list.concat(taicpu.op_reg(A_RL,reg));
  998. // OP_ROR:
  999. // if size in [OS_8,OS_S8] then
  1000. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)))
  1001. // else
  1002. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  1003. // else
  1004. // internalerror(2020040905);
  1005. // end;
  1006. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  1007. // begin
  1008. // for i:=2 to tcgsize2size[size] do
  1009. // begin
  1010. // case op of
  1011. // OP_ROR,
  1012. // OP_SHR,
  1013. // OP_SAR:
  1014. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  1015. // OP_ROL,
  1016. // OP_SHL:
  1017. // list.concat(taicpu.op_reg(A_RL,GetOffsetReg64(reg,reghi,i-1)));
  1018. // else
  1019. // internalerror(2020040906);
  1020. // end;
  1021. // end;
  1022. // end;
  1023. // if a>1 then
  1024. // begin
  1025. // instr:=taicpu.op_sym(A_DJNZ,l1);
  1026. // instr.is_jmp:=true;
  1027. // list.concat(instr);
  1028. // ungetcpuregister(list,NR_B);
  1029. // end;
  1030. // end;
  1031. // end;
  1032. // OP_ADD:
  1033. // begin
  1034. // curvalue:=a and mask;
  1035. // tmpop:=A_NONE;
  1036. // for i:=1 to tcgsize2size[size] do
  1037. // begin
  1038. // if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  1039. // tmpop:=A_INC
  1040. // else if (tmpop=A_NONE) and (curvalue=255) and (i=tcgsize2size[size]) then
  1041. // tmpop:=A_DEC
  1042. // else if (tmpop=A_NONE) and (curvalue<>0) then
  1043. // tmpop:=A_ADD
  1044. // else if tmpop=A_ADD then
  1045. // tmpop:=A_ADC;
  1046. // case tmpop of
  1047. // A_NONE:
  1048. // {nothing};
  1049. // A_INC,A_DEC:
  1050. // list.concat(taicpu.op_reg(tmpop,reg));
  1051. // A_ADD,A_ADC:
  1052. // begin
  1053. // getcpuregister(list,NR_A);
  1054. // emit_mov(list,NR_A,reg);
  1055. // list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  1056. // emit_mov(list,reg,NR_A);
  1057. // ungetcpuregister(list,NR_A);
  1058. // end;
  1059. // else
  1060. // internalerror(2020040901);
  1061. // end;
  1062. // if i<>tcgsize2size[size] then
  1063. // begin
  1064. // NextReg;
  1065. // mask:=mask shl 8;
  1066. // inc(shift,8);
  1067. // curvalue:=(qword(a) and mask) shr shift;
  1068. // end;
  1069. // end;
  1070. // end;
  1071. // OP_SUB:
  1072. // begin
  1073. // curvalue:=a and mask;
  1074. // tmpop:=A_NONE;
  1075. // for i:=1 to tcgsize2size[size] do
  1076. // begin
  1077. // if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  1078. // tmpop:=A_DEC
  1079. // else if (tmpop=A_NONE) and (curvalue=255) and (i=tcgsize2size[size]) then
  1080. // tmpop:=A_INC
  1081. // else if (tmpop=A_NONE) and (curvalue<>0) then
  1082. // tmpop:=A_SUB
  1083. // else if tmpop=A_SUB then
  1084. // tmpop:=A_SBC;
  1085. // case tmpop of
  1086. // A_NONE:
  1087. // {nothing};
  1088. // A_DEC,A_INC:
  1089. // list.concat(taicpu.op_reg(tmpop,reg));
  1090. // A_SUB,A_SBC:
  1091. // begin
  1092. // getcpuregister(list,NR_A);
  1093. // emit_mov(list,NR_A,reg);
  1094. // list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  1095. // emit_mov(list,reg,NR_A);
  1096. // ungetcpuregister(list,NR_A);
  1097. // end;
  1098. // else
  1099. // internalerror(2020040902);
  1100. // end;
  1101. // if i<>tcgsize2size[size] then
  1102. // begin
  1103. // NextReg;
  1104. // mask:=mask shl 8;
  1105. // inc(shift,8);
  1106. // curvalue:=(qword(a) and mask) shr shift;
  1107. // end;
  1108. // end;
  1109. // end;
  1110. // else
  1111. // begin
  1112. // if size in [OS_64,OS_S64] then
  1113. // begin
  1114. // tmpreg64.reglo:=getintregister(list,OS_32);
  1115. // tmpreg64.reghi:=getintregister(list,OS_32);
  1116. // cg64.a_load64_const_reg(list,a,tmpreg64);
  1117. // cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  1118. // end
  1119. // else
  1120. // begin
  1121. {$if 0}
  1122. // { code not working yet }
  1123. // if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  1124. // begin
  1125. // tmpreg:=reg;
  1126. // for i:=1 to 4 do
  1127. // begin
  1128. // list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  1129. // tmpreg:=GetNextReg(tmpreg);
  1130. // end;
  1131. // end
  1132. // else
  1133. {$endif}
  1134. // begin
  1135. // tmpreg:=getintregister(list,size);
  1136. // a_load_const_reg(list,size,a,tmpreg);
  1137. // a_op_reg_reg(list,op,size,tmpreg,reg);
  1138. // end;
  1139. // end;
  1140. // end;
  1141. // end;
  1142. //end;
  1143. procedure tcgmos6502.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
  1144. //var
  1145. // pd: tprocdef;
  1146. // paraloc1, paraloc2: tcgpara;
  1147. // ai: taicpu;
  1148. // hl, no_overflow: TAsmLabel;
  1149. // name: String;
  1150. begin
  1151. //if size in [OS_8,OS_S8] then
  1152. // begin
  1153. // if size=OS_8 then
  1154. // name:='fpc_mul_byte'
  1155. // else
  1156. // name:='fpc_mul_shortint';
  1157. //
  1158. // if check_overflow then
  1159. // name:=name+'_checkoverflow';
  1160. //
  1161. // pd:=search_system_proc(name);
  1162. // paraloc1.init;
  1163. // paraloc2.init;
  1164. // paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1165. // paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1166. // a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  1167. // a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  1168. // paramanager.freecgpara(list,paraloc2);
  1169. // paramanager.freecgpara(list,paraloc1);
  1170. // alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1171. // a_call_name(list,upper(name),false);
  1172. // dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1173. // cg.a_reg_alloc(list,NR_L);
  1174. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
  1175. // cg.a_reg_dealloc(list,NR_L);
  1176. // paraloc2.done;
  1177. // paraloc1.done;
  1178. // end
  1179. //else if size in [OS_16,OS_S16] then
  1180. // begin
  1181. // if size=OS_16 then
  1182. // name:='fpc_mul_word'
  1183. // else
  1184. // name:='fpc_mul_integer';
  1185. //
  1186. // if check_overflow then
  1187. // name:=name+'_checkoverflow';
  1188. //
  1189. // pd:=search_system_proc(name);
  1190. // paraloc1.init;
  1191. // paraloc2.init;
  1192. // paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1193. // paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1194. // a_load_reg_cgpara(list,OS_16,src1,paraloc2);
  1195. // a_load_reg_cgpara(list,OS_16,src2,paraloc1);
  1196. // paramanager.freecgpara(list,paraloc2);
  1197. // paramanager.freecgpara(list,paraloc1);
  1198. // alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1199. // a_call_name(list,upper(name),false);
  1200. // dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1201. // cg.a_reg_alloc(list,NR_L);
  1202. // cg.a_reg_alloc(list,NR_H);
  1203. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
  1204. // cg.a_reg_dealloc(list,NR_L);
  1205. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_H,GetNextReg(dst));
  1206. // cg.a_reg_dealloc(list,NR_H);
  1207. // paraloc2.done;
  1208. // paraloc1.done;
  1209. // end
  1210. //else
  1211. // internalerror(2011022002);
  1212. end;
  1213. procedure tcgmos6502.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  1214. var
  1215. mask : qword;
  1216. shift : byte;
  1217. i : byte;
  1218. begin
  1219. list.Concat(tai_comment.Create(strpnew('TODO: a_load_const_reg '+tcgsize2str(size)+' '+tostr(a)+' '+std_regname(reg))));
  1220. if is_6502_general_purpose_register(reg) then
  1221. begin
  1222. if not (size in [OS_8,OS_S8]) then
  1223. internalerror(2024040704);
  1224. if reg=NR_A then
  1225. taicpu.op_const(A_LDA,byte(a))
  1226. else if reg=NR_X then
  1227. taicpu.op_const(A_LDX,byte(a))
  1228. else if reg=NR_Y then
  1229. taicpu.op_const(A_LDY,byte(a))
  1230. else
  1231. internalerror(2024040705);
  1232. end
  1233. else
  1234. begin
  1235. getcpuregister(list,NR_A);
  1236. mask:=$ff;
  1237. shift:=0;
  1238. for i:=tcgsize2size[size] downto 1 do
  1239. begin
  1240. list.Concat(taicpu.op_const(A_LDA,(qword(a) and mask) shr shift));
  1241. list.Concat(taicpu.op_reg(A_STA,reg));
  1242. if i<>1 then
  1243. begin
  1244. mask:=mask shl 8;
  1245. inc(shift,8);
  1246. reg:=GetNextReg(reg);
  1247. end;
  1248. end;
  1249. ungetcpuregister(list,NR_A);
  1250. end;
  1251. end;
  1252. procedure tcgmos6502.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
  1253. var
  1254. mask : qword;
  1255. shift : byte;
  1256. href: treference;
  1257. i: Integer;
  1258. begin
  1259. list.Concat(tai_comment.Create(strpnew('TODO: a_load_const_ref '+tcgsize2str(size) + ' '+tostr(a)+' '+ref2string(ref))));
  1260. mask:=$ff;
  1261. shift:=0;
  1262. href:=ref;
  1263. if (href.base=NR_NO) and (href.index=NR_NO) then
  1264. begin
  1265. { TODO: get/unget register A }
  1266. for i:=tcgsize2size[size] downto 1 do
  1267. begin
  1268. list.Concat(taicpu.op_const(A_LDA,(qword(a) and mask) shr shift));
  1269. list.Concat(taicpu.op_ref(A_STA,href));
  1270. if i<>1 then
  1271. begin
  1272. mask:=mask shl 8;
  1273. inc(shift,8);
  1274. inc(href.offset);
  1275. end;
  1276. end;
  1277. end;
  1278. //if (href.base=NR_NO) and (href.index<>NR_NO) then
  1279. // begin
  1280. // href.base:=href.index;
  1281. // href.index:=NR_NO;
  1282. // end;
  1283. //if is_ref_in_opertypes(href,[OT_REF_IX_d,OT_REF_IY_d]) or
  1284. // (is_ref_hl(href) and (size in [OS_8,OS_S8])) then
  1285. // begin
  1286. // for i:=tcgsize2size[size] downto 1 do
  1287. // begin
  1288. // list.Concat(taicpu.op_ref_const(A_LD,href,(qword(a) and mask) shr shift));
  1289. // if i<>1 then
  1290. // begin
  1291. // mask:=mask shl 8;
  1292. // inc(shift,8);
  1293. // inc(href.offset);
  1294. // end;
  1295. // end;
  1296. // end
  1297. //else
  1298. // inherited;
  1299. end;
  1300. //function tcgmos6502.normalize_ref(list: TAsmList; ref: treference;
  1301. // const refopertypes: trefoperandtypes; out allocatedregs: tregisterlist): treference;
  1302. // var
  1303. // tmpref : treference;
  1304. // l : tasmlabel;
  1305. // begin
  1306. // SetLength(allocatedregs,0);
  1307. //
  1308. // if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=1) then
  1309. // begin
  1310. // ref.base:=ref.index;
  1311. // ref.index:=NR_NO;
  1312. // end;
  1313. //
  1314. // if is_ref_in_opertypes(ref,refopertypes) then
  1315. // begin
  1316. // Result:=ref;
  1317. // exit;
  1318. // end;
  1319. //
  1320. // { can we use the HL register? }
  1321. // if OT_REF_HL in refopertypes then
  1322. // begin
  1323. // SetLength(allocatedregs,2);
  1324. // allocatedregs[0]:=NR_H;
  1325. // allocatedregs[1]:=NR_L;
  1326. // getcpuregisters(list,allocatedregs);
  1327. // if assigned(ref.symbol) or (ref.offset<>0) then
  1328. // begin
  1329. // if assigned(ref.symbol) then
  1330. // begin
  1331. // reference_reset(tmpref,0,[]);
  1332. // tmpref.symbol:=ref.symbol;
  1333. // tmpref.offset:=ref.offset;
  1334. //
  1335. // tmpref.refaddr:=addr_full;
  1336. // list.concat(taicpu.op_reg_ref(A_LD,NR_HL,tmpref));
  1337. // end
  1338. // else
  1339. // list.concat(taicpu.op_reg_const(A_LD,NR_HL,ref.offset));
  1340. // if (ref.base=NR_IX) or (ref.base=NR_IY) then
  1341. // begin
  1342. // getcpuregister(list,NR_D);
  1343. // getcpuregister(list,NR_E);
  1344. // list.concat(taicpu.op_reg(A_PUSH,ref.base));
  1345. // list.concat(taicpu.op_reg(A_POP,NR_DE));
  1346. // list.concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_DE));
  1347. // ungetcpuregister(list,NR_E);
  1348. // ungetcpuregister(list,NR_D);
  1349. // end
  1350. // else if ref.base<>NR_NO then
  1351. // begin
  1352. // getcpuregister(list,NR_A);
  1353. // emit_mov(list,NR_A,NR_L);
  1354. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.base));
  1355. // emit_mov(list,NR_L,NR_A);
  1356. // emit_mov(list,NR_A,NR_H);
  1357. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.base)));
  1358. // emit_mov(list,NR_H,NR_A);
  1359. // ungetcpuregister(list,NR_A);
  1360. // end;
  1361. // if ref.index<>NR_NO then
  1362. // begin
  1363. // if ref.scalefactor>1 then
  1364. // internalerror(2020042002);
  1365. // getcpuregister(list,NR_A);
  1366. // emit_mov(list,NR_A,NR_L);
  1367. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.index));
  1368. // emit_mov(list,NR_L,NR_A);
  1369. // emit_mov(list,NR_A,NR_H);
  1370. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.index)));
  1371. // emit_mov(list,NR_H,NR_A);
  1372. // ungetcpuregister(list,NR_A);
  1373. // end;
  1374. // end
  1375. // else
  1376. // begin
  1377. // { not assigned(ref.symbol) and (ref.offset=0) }
  1378. // if (ref.base=NR_IX) or (ref.base=NR_IY) then
  1379. // begin
  1380. // list.concat(taicpu.op_reg(A_PUSH,ref.base));
  1381. // list.concat(taicpu.op_reg(A_POP,NR_HL));
  1382. // end
  1383. // else if ref.base<>NR_NO then
  1384. // begin
  1385. // emit_mov(list,NR_L,ref.base);
  1386. // emit_mov(list,NR_H,GetNextReg(ref.base));
  1387. // end;
  1388. // if ref.index<>NR_NO then
  1389. // begin
  1390. // if ref.scalefactor>1 then
  1391. // internalerror(2020042003);
  1392. // getcpuregister(list,NR_A);
  1393. // emit_mov(list,NR_A,NR_L);
  1394. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.index));
  1395. // emit_mov(list,NR_L,NR_A);
  1396. // emit_mov(list,NR_A,NR_H);
  1397. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.index)));
  1398. // emit_mov(list,NR_H,NR_A);
  1399. // ungetcpuregister(list,NR_A);
  1400. // end;
  1401. // end;
  1402. // reference_reset_base(result,NR_HL,0,ctempposinvalid,0,[]);
  1403. // end
  1404. // else
  1405. // internalerror(2020042001);
  1406. // end;
  1407. procedure tcgmos6502.adjust_normalized_ref(list: TAsmList; var ref: treference; value: longint);
  1408. //var
  1409. // i: Integer;
  1410. begin
  1411. inc(ref.offset,value);
  1412. //if is_ref_addr16(ref) then
  1413. // Inc(ref.offset,value)
  1414. //else if is_ref_hl(ref) then
  1415. // begin
  1416. // if value>0 then
  1417. // for i:=1 to value do
  1418. // list.concat(taicpu.op_reg(A_INC,NR_HL))
  1419. // else
  1420. // for i:=-1 downto value do
  1421. // list.concat(taicpu.op_reg(A_DEC,NR_HL));
  1422. // end
  1423. //else if is_ref_ix_d(ref) then
  1424. // begin
  1425. // if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1426. // inc(ref.offset,value)
  1427. // else
  1428. // begin
  1429. // { todo: IX is the frame pointer, we cannot change it, so we }
  1430. // { think of another mechanism to deal with this situation }
  1431. // internalerror(2020042101);
  1432. // //if value>0 then
  1433. // // for i:=1 to value do
  1434. // // list.concat(taicpu.op_reg(A_INC,NR_IX))
  1435. // //else
  1436. // // for i:=-1 downto value do
  1437. // // list.concat(taicpu.op_reg(A_DEC,NR_IX));
  1438. // end;
  1439. // end
  1440. //else if is_ref_iy_d(ref) then
  1441. // begin
  1442. // if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1443. // inc(ref.offset,value)
  1444. // else
  1445. // if value>0 then
  1446. // for i:=1 to value do
  1447. // list.concat(taicpu.op_reg(A_INC,NR_IY))
  1448. // else
  1449. // for i:=-1 downto value do
  1450. // list.concat(taicpu.op_reg(A_DEC,NR_IY));
  1451. // end;
  1452. end;
  1453. procedure tcgmos6502.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1454. var
  1455. href : treference;
  1456. i : integer;
  1457. // regsused: tregisterlist;
  1458. begin
  1459. list.Concat(tai_comment.Create(strpnew('TODO: a_load_reg_ref '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg)+' '+ref2string(ref))));
  1460. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1461. internalerror(2011021307);
  1462. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1463. internalerror(2020040802);
  1464. //href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1465. href:=ref;
  1466. if (href.base=NR_NO) and (href.index=NR_NO) and
  1467. ((tcgsize2size[fromsize]=tcgsize2size[tosize]) or (fromsize in [OS_8,OS_16,OS_32])) then
  1468. begin
  1469. getcpuregister(list,NR_A);
  1470. for i:=1 to tcgsize2size[fromsize] do
  1471. begin
  1472. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1473. list.concat(taicpu.op_ref(A_STA,href));
  1474. if i<>tcgsize2size[fromsize] then
  1475. reg:=GetNextReg(reg);
  1476. if i<>tcgsize2size[tosize] then
  1477. adjust_normalized_ref(list,href,1);
  1478. end;
  1479. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1480. begin
  1481. if i=(tcgsize2size[fromsize]+1) then
  1482. list.concat(taicpu.op_const(A_LDA,0));
  1483. list.concat(taicpu.op_ref(A_STA,href));
  1484. if i<>tcgsize2size[tosize] then
  1485. begin
  1486. adjust_normalized_ref(list,href,1);
  1487. reg:=GetNextReg(reg);
  1488. end;
  1489. end;
  1490. ungetcpuregister(list,NR_A);
  1491. end
  1492. //else
  1493. // begin
  1494. // getcpuregister(list,NR_A);
  1495. // for i:=1 to tcgsize2size[fromsize] do
  1496. // begin
  1497. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1498. // list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1499. // if i<>tcgsize2size[fromsize] then
  1500. // reg:=GetNextReg(reg);
  1501. // if i<>tcgsize2size[tosize] then
  1502. // adjust_normalized_ref(list,href,1);
  1503. // end;
  1504. // list.concat(taicpu.op_none(A_RLA));
  1505. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1506. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1507. // begin
  1508. // list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1509. // if i<>tcgsize2size[tosize] then
  1510. // begin
  1511. // adjust_normalized_ref(list,href,1);
  1512. // reg:=GetNextReg(reg);
  1513. // end;
  1514. // end;
  1515. // ungetcpuregister(list,NR_A);
  1516. // end;
  1517. //ungetcpuregisters(list,regsused);
  1518. end;
  1519. procedure tcgmos6502.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1520. const Ref : treference;reg : tregister);
  1521. var
  1522. href : treference;
  1523. i : integer;
  1524. // regsused: tregisterlist;
  1525. begin
  1526. list.Concat(tai_comment.Create(strpnew('TODO: a_load_ref_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+ref2string(Ref)+' '+std_regname(reg))));
  1527. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1528. internalerror(2011021301);
  1529. if tcgsize2size[fromsize]>=tcgsize2size[tosize] then
  1530. fromsize:=tosize;
  1531. //href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1532. href:=Ref;
  1533. if (href.base=NR_NO) and (href.index=NR_NO) and
  1534. ((tcgsize2size[tosize]=tcgsize2size[fromsize]) or (fromsize in [OS_8,OS_16,OS_32])) then
  1535. begin
  1536. getcpuregister(list,NR_A);
  1537. for i:=1 to tcgsize2size[fromsize] do
  1538. begin
  1539. list.concat(taicpu.op_ref(A_LDA,href));
  1540. list.concat(taicpu.op_reg(A_STA,reg));
  1541. //a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1542. //if i<>tcgsize2size[fromsize] then
  1543. // adjust_normalized_ref(list,href,1);
  1544. if i<>tcgsize2size[tosize] then
  1545. reg:=GetNextReg(reg);
  1546. end;
  1547. //ungetcpuregisters(list,regsused);
  1548. ungetcpuregister(list,NR_A);
  1549. //for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1550. // begin
  1551. // list.concat(taicpu.op_reg_const(A_LD,reg,0));
  1552. // if i<>tcgsize2size[tosize] then
  1553. // reg:=GetNextReg(reg);
  1554. // end;
  1555. end
  1556. //else
  1557. // begin
  1558. // getcpuregister(list,NR_A);
  1559. // for i:=1 to tcgsize2size[fromsize] do
  1560. // begin
  1561. // list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1562. // a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1563. //
  1564. // if i<>tcgsize2size[fromsize] then
  1565. // adjust_normalized_ref(list,href,1);
  1566. // if i<>tcgsize2size[tosize] then
  1567. // reg:=GetNextReg(reg);
  1568. // end;
  1569. // ungetcpuregisters(list,regsused);
  1570. // list.concat(taicpu.op_none(A_RLA));
  1571. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1572. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1573. // begin
  1574. // emit_mov(list,reg,NR_A);
  1575. // if i<>tcgsize2size[tosize] then
  1576. // reg:=GetNextReg(reg);
  1577. // end;
  1578. // ungetcpuregister(list,NR_A);
  1579. // end;
  1580. end;
  1581. procedure tcgmos6502.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1582. var
  1583. // conv_done: boolean;
  1584. // tmpreg : tregister;
  1585. i : integer;
  1586. begin
  1587. { sign extend
  1588. AND #$80
  1589. ASL A -> sign bit goes to the Carry flag
  1590. SBC #$01
  1591. ADC #$FF
  1592. EOR #$FF
  1593. }
  1594. list.Concat(tai_comment.Create(strpnew('TODO: a_load_reg_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg1)+' '+std_regname(reg2))));
  1595. Writeln('TODO: a_load_reg_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg1)+' '+std_regname(reg2));
  1596. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1597. internalerror(2011021310);
  1598. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1599. fromsize:=tosize;
  1600. if (tcgsize2size[tosize]=tcgsize2size[fromsize]) or (fromsize in [OS_8,OS_16,OS_32]) then
  1601. begin
  1602. if reg1<>reg2 then
  1603. for i:=1 to tcgsize2size[fromsize] do
  1604. begin
  1605. emit_mov(list,reg2,reg1);
  1606. if i<>tcgsize2size[fromsize] then
  1607. reg1:=GetNextReg(reg1);
  1608. if i<>tcgsize2size[tosize] then
  1609. reg2:=GetNextReg(reg2);
  1610. end
  1611. else
  1612. for i:=1 to tcgsize2size[fromsize] do
  1613. if i<>tcgsize2size[tosize] then
  1614. reg2:=GetNextReg(reg2);
  1615. if tcgsize2size[tosize]>tcgsize2size[fromsize] then
  1616. begin
  1617. getcpuregister(list,NR_A);
  1618. list.Concat(taicpu.op_const(A_LDA,0));
  1619. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1620. begin
  1621. list.Concat(taicpu.op_reg(A_STA,reg2));
  1622. if i<>tcgsize2size[tosize] then
  1623. reg2:=GetNextReg(reg2);
  1624. end;
  1625. ungetcpuregister(list,NR_A);
  1626. end;
  1627. end
  1628. //else
  1629. // begin
  1630. // if reg1<>reg2 then
  1631. // for i:=1 to tcgsize2size[fromsize]-1 do
  1632. // begin
  1633. // emit_mov(list,reg2,reg1);
  1634. // reg1:=GetNextReg(reg1);
  1635. // reg2:=GetNextReg(reg2);
  1636. // end
  1637. // else
  1638. // for i:=1 to tcgsize2size[fromsize]-1 do
  1639. // reg2:=GetNextReg(reg2);
  1640. // emit_mov(list,reg2,reg1);
  1641. // getcpuregister(list,NR_A);
  1642. // emit_mov(list,NR_A,reg2);
  1643. // reg2:=GetNextReg(reg2);
  1644. // list.concat(taicpu.op_none(A_RLA));
  1645. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1646. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1647. // begin
  1648. // emit_mov(list,reg2,NR_A);
  1649. // if i<>tcgsize2size[tosize] then
  1650. // reg2:=GetNextReg(reg2);
  1651. // end;
  1652. // ungetcpuregister(list,NR_A);
  1653. // end;
  1654. end;
  1655. procedure tcgmos6502.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1656. begin
  1657. internalerror(2012010702);
  1658. end;
  1659. procedure tcgmos6502.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1660. begin
  1661. internalerror(2012010703);
  1662. end;
  1663. procedure tcgmos6502.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1664. begin
  1665. internalerror(2012010704);
  1666. end;
  1667. { comparison operations }
  1668. procedure tcgmos6502.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1669. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1670. //var
  1671. // swapped : boolean;
  1672. // tmpreg : tregister;
  1673. // i : byte;
  1674. // tmpl: TAsmLabel;
  1675. begin
  1676. //tmpl:=nil;
  1677. //if size in [OS_8,OS_S8]then
  1678. // begin
  1679. // if cmp_op in [OC_EQ,OC_NE,OC_B,OC_AE] then
  1680. // begin
  1681. // getcpuregister(list,NR_A);
  1682. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1683. // list.concat(taicpu.op_reg_const(A_CP,NR_A,a));
  1684. // case cmp_op of
  1685. // OC_EQ:
  1686. // a_jmp_flags(list,F_E,l);
  1687. // OC_NE:
  1688. // a_jmp_flags(list,F_NE,l);
  1689. // OC_B:
  1690. // a_jmp_flags(list,F_C,l);
  1691. // OC_AE:
  1692. // a_jmp_flags(list,F_NC,l);
  1693. // else
  1694. // internalerror(2020042206);
  1695. // end;
  1696. // ungetcpuregister(list,NR_A);
  1697. // end
  1698. // else if cmp_op in [OC_A,OC_BE] then
  1699. // begin
  1700. // getcpuregister(list,NR_A);
  1701. // a_load_const_reg(list,OS_8,a,NR_A);
  1702. // list.concat(taicpu.op_reg_reg(A_CP,NR_A,reg));
  1703. // case cmp_op of
  1704. // OC_A:
  1705. // a_jmp_flags(list,F_C,l);
  1706. // OC_BE:
  1707. // a_jmp_flags(list,F_NC,l);
  1708. // else
  1709. // internalerror(2020042218);
  1710. // end;
  1711. // ungetcpuregister(list,NR_A);
  1712. // end
  1713. // else if cmp_op in [OC_LT,OC_GTE] then
  1714. // begin
  1715. // getcpuregister(list,NR_A);
  1716. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1717. // list.concat(taicpu.op_reg_const(A_SUB,NR_A,a));
  1718. // current_asmdata.getjumplabel(tmpl);
  1719. // a_jmp_flags(list,F_PO,tmpl);
  1720. // current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1721. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1722. // case cmp_op of
  1723. // OC_LT:
  1724. // a_jmp_flags(list,F_M,l);
  1725. // OC_GTE:
  1726. // a_jmp_flags(list,F_P,l);
  1727. // else
  1728. // internalerror(2020042219);
  1729. // end;
  1730. // ungetcpuregister(list,NR_A);
  1731. // end
  1732. // else if cmp_op in [OC_GT,OC_LTE] then
  1733. // begin
  1734. // getcpuregister(list,NR_A);
  1735. // a_load_const_reg(list,OS_8,a,NR_A);
  1736. // list.concat(taicpu.op_reg_reg(A_SUB,NR_A,reg));
  1737. // current_asmdata.getjumplabel(tmpl);
  1738. // a_jmp_flags(list,F_PO,tmpl);
  1739. // current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1740. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1741. // case cmp_op of
  1742. // OC_GT:
  1743. // a_jmp_flags(list,F_M,l);
  1744. // OC_LTE:
  1745. // a_jmp_flags(list,F_P,l);
  1746. // else
  1747. // internalerror(2020042220);
  1748. // end;
  1749. // ungetcpuregister(list,NR_A);
  1750. // end;
  1751. // end
  1752. //else if cmp_op in [OC_EQ,OC_NE] then
  1753. // begin
  1754. // if cmp_op=OC_EQ then
  1755. // current_asmdata.getjumplabel(tmpl);
  1756. // for i:=0 to tcgsize2size[size]-1 do
  1757. // begin
  1758. // a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1759. // list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1760. // case cmp_op of
  1761. // OC_EQ:
  1762. // if i<>(tcgsize2size[size]-1) then
  1763. // a_jmp_flags(list,F_NE,tmpl)
  1764. // else
  1765. // a_jmp_flags(list,F_E,l);
  1766. // OC_NE:
  1767. // a_jmp_flags(list,F_NE,l);
  1768. // else
  1769. // internalerror(2020042221);
  1770. // end;
  1771. // end;
  1772. // if cmp_op=OC_EQ then
  1773. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1774. // end
  1775. //else if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE,OC_BE,OC_B,OC_AE,OC_A] then
  1776. // begin
  1777. // getcpuregister(list,NR_A);
  1778. // current_asmdata.getjumplabel(tmpl);
  1779. // for i:=tcgsize2size[size]-1 downto 0 do
  1780. // begin
  1781. // a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1782. // list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1783. // if (i=(tcgsize2size[size]-1)) and (cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE]) then
  1784. // case cmp_op of
  1785. // OC_GTE,
  1786. // OC_GT:
  1787. // a_jmp_signed_cmp_3way(list,tmpl,nil,l);
  1788. // OC_LT,
  1789. // OC_LTE:
  1790. // a_jmp_signed_cmp_3way(list,l,nil,tmpl);
  1791. // else
  1792. // internalerror(2020042222);
  1793. // end
  1794. // else if i<>0 then
  1795. // case cmp_op of
  1796. // OC_AE,
  1797. // OC_A,
  1798. // OC_GTE,
  1799. // OC_GT:
  1800. // a_jmp_unsigned_cmp_3way(list,tmpl,nil,l);
  1801. // OC_BE,
  1802. // OC_B,
  1803. // OC_LT,
  1804. // OC_LTE:
  1805. // a_jmp_unsigned_cmp_3way(list,l,nil,tmpl);
  1806. // else
  1807. // internalerror(2020042223);
  1808. // end
  1809. // else
  1810. // case cmp_op of
  1811. // OC_A,
  1812. // OC_GT:
  1813. // a_jmp_unsigned_cmp_3way(list,nil,nil,l);
  1814. // OC_B,
  1815. // OC_LT:
  1816. // a_jmp_unsigned_cmp_3way(list,l,nil,nil);
  1817. // OC_AE,
  1818. // OC_GTE:
  1819. // a_jmp_unsigned_cmp_3way(list,nil,l,l);
  1820. // OC_BE,
  1821. // OC_LTE:
  1822. // a_jmp_unsigned_cmp_3way(list,l,l,nil);
  1823. // else
  1824. // internalerror(2020042224);
  1825. // end;
  1826. // end;
  1827. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1828. // ungetcpuregister(list,NR_A);
  1829. // end
  1830. //else
  1831. // internalerror(2020042205);
  1832. end;
  1833. procedure tcgmos6502.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1834. begin
  1835. internalerror(2020042301);
  1836. end;
  1837. procedure tcgmos6502.a_jmp_name(list : TAsmList;const s : string);
  1838. var
  1839. ai : taicpu;
  1840. begin
  1841. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1842. ai.is_jmp:=true;
  1843. list.concat(ai);
  1844. end;
  1845. procedure tcgmos6502.a_jmp_always(list : TAsmList;l: tasmlabel);
  1846. var
  1847. ai : taicpu;
  1848. begin
  1849. ai:=taicpu.op_sym(A_JMP,l);
  1850. ai.is_jmp:=true;
  1851. list.concat(ai);
  1852. end;
  1853. procedure tcgmos6502.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1854. var
  1855. ai : taicpu;
  1856. begin
  1857. ai:=taicpu.op_cond_sym(A_Bxx,flags_to_cond(f),l);
  1858. ai.is_jmp:=true;
  1859. list.concat(ai);
  1860. end;
  1861. procedure tcgmos6502.a_jmp_unsigned_cmp_3way(list: TAsmList; onbelow, onequal, onabove: tasmlabel);
  1862. var
  1863. skiplabel: TAsmLabel;
  1864. begin
  1865. if (onbelow= nil) and (onequal= nil) and (onabove= nil) then
  1866. {nothing}
  1867. else if (onbelow= nil) and (onequal= nil) and (onabove<>nil) then
  1868. begin
  1869. current_asmdata.getjumplabel(skiplabel);
  1870. a_jmp_flags(list,F_EQ,skiplabel);
  1871. a_jmp_flags(list,F_CS,onabove);
  1872. cg.a_label(list,skiplabel);
  1873. end
  1874. else if (onbelow= nil) and (onequal<>nil) and (onabove= nil) then
  1875. a_jmp_flags(list,F_EQ,onequal)
  1876. else if (onbelow= nil) and (onequal<>nil) and (onabove<>nil) then
  1877. begin
  1878. if onequal<>onabove then
  1879. a_jmp_flags(list,F_EQ,onequal);
  1880. a_jmp_flags(list,F_CS,onabove);
  1881. end
  1882. else if (onbelow<>nil) and (onequal= nil) and (onabove= nil) then
  1883. a_jmp_flags(list,F_CC,onbelow)
  1884. else if (onbelow<>nil) and (onequal= nil) and (onabove<>nil) then
  1885. begin
  1886. if onbelow<>onabove then
  1887. a_jmp_flags(list,F_CC,onbelow);
  1888. a_jmp_flags(list,F_NE,onabove);
  1889. end
  1890. else if (onbelow<>nil) and (onequal<>nil) and (onabove= nil) then
  1891. begin
  1892. a_jmp_flags(list,F_CC,onbelow);
  1893. a_jmp_flags(list,F_EQ,onequal);
  1894. end
  1895. else if (onbelow<>nil) and (onequal<>nil) and (onabove<>nil) then
  1896. begin
  1897. if (onbelow=onequal) and (onequal=onabove) then
  1898. a_jmp_always(list,onbelow)
  1899. else if onequal=onabove then
  1900. begin
  1901. a_jmp_flags(list,F_CC,onbelow);
  1902. a_jmp_always(list,onabove);
  1903. end
  1904. else if onbelow=onequal then
  1905. begin
  1906. a_jmp_flags(list,F_CC,onbelow);
  1907. a_jmp_flags(list,F_EQ,onequal);
  1908. a_jmp_always(list,onabove);
  1909. end
  1910. else if onbelow=onabove then
  1911. begin
  1912. a_jmp_flags(list,F_EQ,onequal);
  1913. a_jmp_always(list,onabove);
  1914. end
  1915. else
  1916. begin
  1917. { the generic case - all 3 are different labels }
  1918. a_jmp_flags(list,F_CC,onbelow);
  1919. a_jmp_flags(list,F_EQ,onequal);
  1920. a_jmp_always(list,onabove);
  1921. end;
  1922. end
  1923. else
  1924. begin
  1925. { Shouldn't happen! All possible combinations are handled by the above code. }
  1926. internalerror(2020042201);
  1927. end;
  1928. end;
  1929. procedure tcgmos6502.a_jmp_signed_cmp_3way(list: TAsmList; onless, onequal, ongreater: tasmlabel);
  1930. var
  1931. skiplabel: TAsmLabel;
  1932. begin
  1933. if (onless= nil) and (onequal= nil) and (ongreater= nil) then
  1934. {nothing}
  1935. else if (onless= nil) and (onequal= nil) and (ongreater<>nil) then
  1936. begin
  1937. current_asmdata.getjumplabel(skiplabel);
  1938. a_jmp_flags(list,F_EQ,skiplabel);
  1939. a_jmp_flags(list,F_PL,ongreater);
  1940. cg.a_label(list,skiplabel);
  1941. end
  1942. else if (onless= nil) and (onequal<>nil) and (ongreater= nil) then
  1943. a_jmp_flags(list,F_EQ,onequal)
  1944. else if (onless= nil) and (onequal<>nil) and (ongreater<>nil) then
  1945. begin
  1946. if onequal<>ongreater then
  1947. a_jmp_flags(list,F_EQ,onequal);
  1948. a_jmp_flags(list,F_PL,ongreater);
  1949. end
  1950. else if (onless<>nil) and (onequal= nil) and (ongreater= nil) then
  1951. a_jmp_flags(list,F_MI,onless)
  1952. else if (onless<>nil) and (onequal= nil) and (ongreater<>nil) then
  1953. begin
  1954. if onless<>ongreater then
  1955. a_jmp_flags(list,F_MI,onless);
  1956. a_jmp_flags(list,F_NE,ongreater);
  1957. end
  1958. else if (onless<>nil) and (onequal<>nil) and (ongreater= nil) then
  1959. begin
  1960. a_jmp_flags(list,F_MI,onless);
  1961. a_jmp_flags(list,F_EQ,onequal);
  1962. end
  1963. else if (onless<>nil) and (onequal<>nil) and (ongreater<>nil) then
  1964. begin
  1965. if (onless=onequal) and (onequal=ongreater) then
  1966. a_jmp_always(list,onless)
  1967. else if onequal=ongreater then
  1968. begin
  1969. a_jmp_flags(list,F_MI,onless);
  1970. a_jmp_always(list,ongreater);
  1971. end
  1972. else if onless=onequal then
  1973. begin
  1974. a_jmp_flags(list,F_MI,onless);
  1975. a_jmp_flags(list,F_EQ,onequal);
  1976. a_jmp_always(list,ongreater);
  1977. end
  1978. else if onless=ongreater then
  1979. begin
  1980. a_jmp_flags(list,F_EQ,onequal);
  1981. a_jmp_always(list,ongreater);
  1982. end
  1983. else
  1984. begin
  1985. { the generic case - all 3 are different labels }
  1986. a_jmp_flags(list,F_MI,onless);
  1987. a_jmp_flags(list,F_EQ,onequal);
  1988. a_jmp_always(list,ongreater);
  1989. end;
  1990. end
  1991. else
  1992. begin
  1993. { Shouldn't happen! All possible combinations are handled by the above code. }
  1994. internalerror(2020042204);
  1995. end;
  1996. end;
  1997. procedure tcgmos6502.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1998. //var
  1999. // l : TAsmLabel;
  2000. // tmpflags : TResFlags;
  2001. begin
  2002. //if f in [F_C,F_NC] then
  2003. // begin
  2004. // a_load_const_reg(list,size,0,reg);
  2005. // if f=F_NC then
  2006. // list.concat(taicpu.op_none(A_CCF));
  2007. // list.concat(taicpu.op_reg(A_RL,reg));
  2008. // end
  2009. //else
  2010. // begin
  2011. // current_asmdata.getjumplabel(l);
  2012. // a_load_const_reg(list,size,0,reg);
  2013. // tmpflags:=f;
  2014. // inverse_flags(tmpflags);
  2015. // a_jmp_flags(list,tmpflags,l);
  2016. // list.concat(taicpu.op_reg(A_INC,reg));
  2017. // cg.a_label(list,l);
  2018. // end;
  2019. end;
  2020. procedure tcgmos6502.g_stackpointer_alloc(list: TAsmList; localsize: longint);
  2021. begin
  2022. //if localsize>0 then
  2023. // begin
  2024. // list.Concat(taicpu.op_reg_const(A_LD,NR_HL,-localsize));
  2025. // list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  2026. // list.Concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  2027. // end;
  2028. end;
  2029. //procedure tcgmos6502.a_adjust_sp(list : TAsmList; value : longint);
  2030. // var
  2031. // i : integer;
  2032. // sym: TAsmSymbol;
  2033. // ref: treference;
  2034. // begin
  2035. // case value of
  2036. // 0:
  2037. // ;
  2038. // -7..-1:
  2039. // begin
  2040. // for i:=value to -1 do
  2041. // list.concat(taicpu.op_reg(A_DEC,NR_SP));
  2042. // end;
  2043. // 1..7:
  2044. // begin
  2045. // for i:=1 to value do
  2046. // list.concat(taicpu.op_reg(A_INC,NR_SP));
  2047. // end;
  2048. // else
  2049. // begin
  2050. // sym:=current_asmdata.RefAsmSymbol('FPC_Z80_SAVE_HL',AT_DATA);
  2051. // reference_reset_symbol(ref,sym,0,1,[]);
  2052. //
  2053. // // block interrupts
  2054. // list.concat(taicpu.op_none(A_DI));
  2055. //
  2056. // // save HL
  2057. // list.concat(taicpu.op_ref_reg(A_LD,ref,NR_HL));
  2058. //
  2059. // // adjust SP
  2060. // list.concat(taicpu.op_reg_const(A_LD,NR_HL,value));
  2061. // list.concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  2062. // list.concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  2063. //
  2064. // // restore HL
  2065. // list.concat(taicpu.op_reg_ref(A_LD,NR_HL,ref));
  2066. //
  2067. // // release interrupts
  2068. // list.concat(taicpu.op_none(A_EI));
  2069. // end;
  2070. // end;
  2071. // end;
  2072. procedure tcgmos6502.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  2073. //var
  2074. // regsize,stackmisalignment: longint;
  2075. begin
  2076. //regsize:=0;
  2077. //stackmisalignment:=0;
  2078. //{ save old framepointer }
  2079. //if not nostackframe then
  2080. // begin
  2081. // { return address }
  2082. // inc(stackmisalignment,2);
  2083. // list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
  2084. // if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
  2085. // begin
  2086. // { push <frame_pointer> }
  2087. // inc(stackmisalignment,2);
  2088. // include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
  2089. // list.concat(Taicpu.op_reg(A_PUSH,NR_FRAME_POINTER_REG));
  2090. // { Return address and FP are both on stack }
  2091. // current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*2);
  2092. // current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*2));
  2093. // if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
  2094. // begin
  2095. // list.concat(Taicpu.op_reg_const(A_LD,NR_FRAME_POINTER_REG,0));
  2096. // list.concat(Taicpu.op_reg_reg(A_ADD,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG))
  2097. // end
  2098. // else
  2099. // begin
  2100. // internalerror(2020040301);
  2101. // (*push_regs;
  2102. // gen_load_frame_for_exceptfilter(list);
  2103. // { Need only as much stack space as necessary to do the calls.
  2104. // Exception filters don't have own local vars, and temps are 'mapped'
  2105. // to the parent procedure.
  2106. // maxpushedparasize is already aligned at least on x86_64. }
  2107. // localsize:=current_procinfo.maxpushedparasize;*)
  2108. // end;
  2109. // current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
  2110. // end
  2111. // else
  2112. // begin
  2113. // CGmessage(cg_d_stackframe_omited);
  2114. // end;
  2115. //
  2116. // { allocate stackframe space }
  2117. // if (localsize<>0) or
  2118. // ((target_info.stackalign>sizeof(pint)) and
  2119. // (stackmisalignment <> 0) and
  2120. // ((pi_do_call in current_procinfo.flags) or
  2121. // (po_assembler in current_procinfo.procdef.procoptions))) then
  2122. // begin
  2123. // if target_info.stackalign>sizeof(pint) then
  2124. // localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment;
  2125. // g_stackpointer_alloc(list,localsize);
  2126. // if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  2127. // current_asmdata.asmcfi.cfa_def_cfa_offset(list,regsize+localsize+sizeof(pint));
  2128. // current_procinfo.final_localsize:=localsize;
  2129. // end
  2130. // end;
  2131. end;
  2132. procedure tcgmos6502.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  2133. //var
  2134. // regs : tcpuregisterset;
  2135. // reg : TSuperRegister;
  2136. // LocalSize : longint;
  2137. // stacksize : longint;
  2138. begin
  2139. //{ every byte counts for Z80, so if a subroutine is marked as non-returning, we do
  2140. // not generate any exit code, so we really trust the noreturn directive
  2141. //}
  2142. //if po_noreturn in current_procinfo.procdef.procoptions then
  2143. // exit;
  2144. //
  2145. //{ remove stackframe }
  2146. //if not nostackframe then
  2147. // begin
  2148. // stacksize:=current_procinfo.calc_stackframe_size;
  2149. // if (target_info.stackalign>4) and
  2150. // ((stacksize <> 0) or
  2151. // (pi_do_call in current_procinfo.flags) or
  2152. // { can't detect if a call in this case -> use nostackframe }
  2153. // { if you (think you) know what you are doing }
  2154. // (po_assembler in current_procinfo.procdef.procoptions)) then
  2155. // stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  2156. // if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  2157. // begin
  2158. // if stacksize<>0 then
  2159. // a_adjust_sp(list,stacksize);
  2160. // end
  2161. // else
  2162. // begin
  2163. // list.Concat(taicpu.op_reg_reg(A_LD,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
  2164. // list.Concat(taicpu.op_reg(A_POP,NR_FRAME_POINTER_REG));
  2165. // end;
  2166. // list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  2167. // end;
  2168. list.concat(taicpu.op_none(A_RTS));
  2169. end;
  2170. procedure tcgmos6502.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  2171. //var
  2172. // tmpref : treference;
  2173. begin
  2174. //if assigned(ref.symbol) then
  2175. // begin
  2176. // reference_reset(tmpref,0,[]);
  2177. // tmpref.symbol:=ref.symbol;
  2178. // tmpref.offset:=ref.offset;
  2179. //
  2180. // tmpref.refaddr:=addr_lo8;
  2181. // list.concat(taicpu.op_reg_ref(A_LD,r,tmpref));
  2182. //
  2183. // tmpref.refaddr:=addr_hi8;
  2184. // list.concat(taicpu.op_reg_ref(A_LD,GetNextReg(r),tmpref));
  2185. //
  2186. // if (ref.base<>NR_NO) then
  2187. // a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  2188. // if (ref.index<>NR_NO) then
  2189. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2190. // end
  2191. //else if ref.base=NR_IX then
  2192. // begin
  2193. // list.concat(taicpu.op_reg(A_PUSH,NR_IX));
  2194. // getcpuregister(list,NR_H);
  2195. // getcpuregister(list,NR_L);
  2196. // list.concat(taicpu.op_reg(A_POP,NR_HL));
  2197. // emit_mov(list,r,NR_L);
  2198. // ungetcpuregister(list,NR_L);
  2199. // emit_mov(list,GetNextReg(r),NR_H);
  2200. // ungetcpuregister(list,NR_H);
  2201. // if (ref.index<>NR_NO) then
  2202. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2203. // if ref.offset<>0 then
  2204. // a_op_const_reg(list,OP_ADD,OS_16,ref.offset,r);
  2205. // end
  2206. //else if (ref.base=NR_SP) or (ref.base=NR_BC) or (ref.base=NR_DE) then
  2207. // begin
  2208. // getcpuregister(list,NR_H);
  2209. // getcpuregister(list,NR_L);
  2210. // list.Concat(taicpu.op_reg_const(A_LD,NR_HL,ref.offset));
  2211. // list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,ref.base));
  2212. // emit_mov(list,r,NR_L);
  2213. // ungetcpuregister(list,NR_L);
  2214. // emit_mov(list,GetNextReg(r),NR_H);
  2215. // ungetcpuregister(list,NR_H);
  2216. // if (ref.index<>NR_NO) then
  2217. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2218. // end
  2219. //else if ref.base<>NR_NO then
  2220. // begin
  2221. // a_op_const_reg_reg(list,OP_ADD,OS_16,ref.offset,ref.base,r);
  2222. // if (ref.index<>NR_NO) then
  2223. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2224. // end
  2225. //else if ref.index<>NR_NO then
  2226. // a_op_const_reg_reg(list,OP_ADD,OS_16,ref.offset,ref.index,r)
  2227. //else
  2228. // a_load_const_reg(list,OS_16,ref.offset,r);
  2229. end;
  2230. procedure tcgmos6502.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  2231. //var
  2232. // tmpreg,srcreg,dstreg: tregister;
  2233. // srcref,dstref : treference;
  2234. // i: Integer;
  2235. begin
  2236. //if (len<=2) and
  2237. // is_ref_in_opertypes(source,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) and
  2238. // is_ref_in_opertypes(dest,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  2239. // begin
  2240. // srcref:=source;
  2241. // dstref:=dest;
  2242. // tmpreg:=getintregister(list,OS_8);
  2243. // for i:=1 to len do
  2244. // begin
  2245. // list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  2246. // list.concat(taicpu.op_ref_reg(A_LD,dstref,tmpreg));
  2247. // if i<>len then
  2248. // begin
  2249. // adjust_normalized_ref(list,srcref,1);
  2250. // adjust_normalized_ref(list,dstref,1);
  2251. // end;
  2252. // end;
  2253. // end
  2254. //else
  2255. // begin
  2256. // srcreg:=getintregister(list,OS_16);
  2257. // a_loadaddr_ref_reg(list,source,srcreg);
  2258. // dstreg:=getintregister(list,OS_16);
  2259. // a_loadaddr_ref_reg(list,dest,dstreg);
  2260. // getcpuregister(list,NR_L);
  2261. // a_load_reg_reg(list,OS_8,OS_8,srcreg,NR_L);
  2262. // getcpuregister(list,NR_H);
  2263. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(srcreg),NR_H);
  2264. // getcpuregister(list,NR_E);
  2265. // a_load_reg_reg(list,OS_8,OS_8,dstreg,NR_E);
  2266. // getcpuregister(list,NR_D);
  2267. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(dstreg),NR_D);
  2268. // getcpuregister(list,NR_B);
  2269. // getcpuregister(list,NR_C);
  2270. // list.concat(taicpu.op_reg_const(A_LD,NR_BC,len));
  2271. // list.concat(taicpu.op_none(A_LDIR));
  2272. // ungetcpuregister(list,NR_B);
  2273. // ungetcpuregister(list,NR_C);
  2274. // ungetcpuregister(list,NR_D);
  2275. // ungetcpuregister(list,NR_E);
  2276. // ungetcpuregister(list,NR_H);
  2277. // ungetcpuregister(list,NR_L);
  2278. // end;
  2279. end;
  2280. procedure tcgmos6502.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2281. var
  2282. hl : tasmlabel;
  2283. ai : taicpu;
  2284. cond : TAsmCond;
  2285. begin
  2286. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_overflowCheck')));
  2287. //if not(cs_check_overflow in current_settings.localswitches) then
  2288. // exit;
  2289. //current_asmdata.getjumplabel(hl);
  2290. //if not ((def.typ=pointerdef) or
  2291. // ((def.typ=orddef) and
  2292. // (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2293. // pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2294. // cond:=C_VC
  2295. //else
  2296. // cond:=C_CC;
  2297. //ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2298. //ai.SetCondition(cond);
  2299. //ai.is_jmp:=true;
  2300. //list.concat(ai);
  2301. //
  2302. //a_call_name(list,'FPC_OVERFLOW',false);
  2303. //a_label(list,hl);
  2304. end;
  2305. procedure tcgmos6502.g_save_registers(list: TAsmList);
  2306. begin
  2307. { this is done by the entry code }
  2308. end;
  2309. procedure tcgmos6502.g_restore_registers(list: TAsmList);
  2310. begin
  2311. { this is done by the exit code }
  2312. end;
  2313. procedure tcgmos6502.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2314. begin
  2315. //case cond of
  2316. // OC_EQ:
  2317. // a_jmp_unsigned_cmp_3way(list,nil,l,nil);
  2318. // OC_NE:
  2319. // a_jmp_unsigned_cmp_3way(list,l,nil,l);
  2320. // OC_A:
  2321. // a_jmp_unsigned_cmp_3way(list,nil,nil,l);
  2322. // OC_B:
  2323. // a_jmp_unsigned_cmp_3way(list,l,nil,nil);
  2324. // OC_AE:
  2325. // a_jmp_unsigned_cmp_3way(list,nil,l,l);
  2326. // OC_BE:
  2327. // a_jmp_unsigned_cmp_3way(list,l,l,nil);
  2328. // OC_GT:
  2329. // a_jmp_signed_cmp_3way(list,nil,nil,l);
  2330. // OC_LT:
  2331. // a_jmp_signed_cmp_3way(list,l,nil,nil);
  2332. // OC_GTE:
  2333. // a_jmp_signed_cmp_3way(list,nil,l,l);
  2334. // OC_LTE:
  2335. // a_jmp_signed_cmp_3way(list,l,l,nil);
  2336. // else
  2337. // internalerror(2011082501);
  2338. //end;
  2339. end;
  2340. procedure tcgmos6502.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2341. //var
  2342. // instr: taicpu;
  2343. begin
  2344. if reg1=reg2 then
  2345. exit;
  2346. if reg1=NR_A then
  2347. begin
  2348. if reg2=NR_X then
  2349. list.Concat(taicpu.op_none(A_TAX))
  2350. else if reg2=NR_Y then
  2351. list.Concat(taicpu.op_none(A_TAY))
  2352. else
  2353. list.Concat(taicpu.op_reg(A_STA,reg2));
  2354. end
  2355. else if reg1=NR_X then
  2356. begin
  2357. if reg2=NR_A then
  2358. list.Concat(taicpu.op_none(A_TXA))
  2359. else if reg2=NR_Y then
  2360. begin
  2361. getcpuregister(list,NR_A);
  2362. list.Concat(taicpu.op_none(A_TXA));
  2363. list.Concat(taicpu.op_none(A_TAY));
  2364. ungetcpuregister(list,NR_A);
  2365. end
  2366. else
  2367. list.Concat(taicpu.op_reg(A_STX,reg2));
  2368. end
  2369. else if reg1=NR_Y then
  2370. begin
  2371. if reg2=NR_A then
  2372. list.Concat(taicpu.op_none(A_TYA))
  2373. else if reg2=NR_Y then
  2374. begin
  2375. getcpuregister(list,NR_A);
  2376. list.Concat(taicpu.op_none(A_TYA));
  2377. list.Concat(taicpu.op_none(A_TAX));
  2378. ungetcpuregister(list,NR_A);
  2379. end
  2380. else
  2381. list.Concat(taicpu.op_reg(A_STY,reg2));
  2382. end
  2383. else if reg2=NR_A then
  2384. list.Concat(taicpu.op_reg(A_LDA,reg1))
  2385. else if reg2=NR_X then
  2386. list.Concat(taicpu.op_reg(A_LDX,reg1))
  2387. else if reg2=NR_Y then
  2388. list.Concat(taicpu.op_reg(A_LDY,reg1))
  2389. else
  2390. begin
  2391. getcpuregister(list,NR_A);
  2392. list.Concat(taicpu.op_reg(A_LDA,reg1));
  2393. list.Concat(taicpu.op_reg(A_STA,reg2));
  2394. ungetcpuregister(list,NR_A);
  2395. end;
  2396. //instr:=taicpu.op_reg_reg(A_LD,reg2,reg1);
  2397. //list.Concat(instr);
  2398. { Notify the register allocator that we have written a move instruction so
  2399. it can try to eliminate it. }
  2400. //add_move_instruction(instr);
  2401. end;
  2402. procedure tcg64fmos6502.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2403. begin
  2404. list.Concat(tai_comment.Create(strpnew('TODO: a_op64_reg_reg '+topcg2str(Op)+' '+tcgsize2str(size)+' '+std_regname(regsrc.reghi)+':'+std_regname(regsrc.reglo)+' '+std_regname(regdst.reghi)+':'+std_regname(regdst.reglo))));
  2405. if not(size in [OS_S64,OS_64]) then
  2406. internalerror(2012102402);
  2407. //tcgmos6502(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2408. end;
  2409. procedure tcg64fmos6502.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2410. begin
  2411. list.Concat(tai_comment.Create(strpnew('TODO: a_op64_const_reg '+topcg2str(Op)+' '+tcgsize2str(size)+' '+tostr(value)+' '+std_regname(reg.reghi)+':'+std_regname(reg.reglo))));
  2412. //tcgmos6502(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2413. end;
  2414. procedure create_codegen;
  2415. begin
  2416. cg:=tcgmos6502.create;
  2417. cg64:=tcg64fmos6502.create;
  2418. end;
  2419. end.