cgcpu.pas 94 KB

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