cgcpu.pas 97 KB

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