cgcpu.pas 98 KB

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