cgcpu.pas 99 KB

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