cgcpu.pas 97 KB

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