cgcpu.pas 106 KB

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