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. //
  724. // OP_DIV,OP_IDIV:
  725. // { special stuff, needs separate handling inside code
  726. // generator }
  727. // internalerror(2017032604);
  728. //
  729. // OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  730. // begin
  731. // current_asmdata.getjumplabel(l1);
  732. // current_asmdata.getjumplabel(l2);
  733. // getcpuregister(list,NR_B);
  734. // emit_mov(list,NR_B,src);
  735. // list.concat(taicpu.op_reg(A_INC,NR_B));
  736. // list.concat(taicpu.op_reg(A_DEC,NR_B));
  737. // a_jmp_flags(list,F_E,l2);
  738. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  739. // case op of
  740. // OP_ROL:
  741. // begin
  742. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  743. // list.concat(taicpu.op_reg(A_RLC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  744. // end;
  745. // OP_ROR:
  746. // begin
  747. // list.concat(taicpu.op_reg(A_RLC,dst));
  748. // list.concat(taicpu.op_reg(A_RRC,dst));
  749. // end;
  750. // else
  751. // ;
  752. // end;
  753. // cg.a_label(list,l1);
  754. // case op of
  755. // OP_SHL:
  756. // list.concat(taicpu.op_reg(A_SLA,dst));
  757. // OP_SHR:
  758. // list.concat(taicpu.op_reg(A_SRL,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  759. // OP_SAR:
  760. // list.concat(taicpu.op_reg(A_SRA,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  761. // OP_ROL:
  762. // if size in [OS_8,OS_S8] then
  763. // list.concat(taicpu.op_reg(A_RLC,dst))
  764. // else
  765. // list.concat(taicpu.op_reg(A_RL,dst));
  766. // OP_ROR:
  767. // if size in [OS_8,OS_S8] then
  768. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)))
  769. // else
  770. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
  771. // else
  772. // internalerror(2020040903);
  773. // end;
  774. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  775. // begin
  776. // for i:=2 to tcgsize2size[size] do
  777. // begin
  778. // case op of
  779. // OP_ROR,
  780. // OP_SHR,
  781. // OP_SAR:
  782. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
  783. // OP_ROL,
  784. // OP_SHL:
  785. // list.concat(taicpu.op_reg(A_RL,GetOffsetReg64(dst,dsthi,i-1)));
  786. // else
  787. // internalerror(2020040904);
  788. // end;
  789. // end;
  790. // end;
  791. // instr:=taicpu.op_sym(A_DJNZ,l1);
  792. // instr.is_jmp:=true;
  793. // list.concat(instr);
  794. // ungetcpuregister(list,NR_B);
  795. // cg.a_label(list,l2);
  796. // end;
  797. OP_AND,OP_OR,OP_XOR:
  798. begin
  799. getcpuregister(list,NR_A);
  800. for i:=1 to tcgsize2size[size] do
  801. begin
  802. if i<>1 then
  803. NextSrcDst;
  804. a_load_reg_reg(list,OS_8,OS_8,dst,NR_A);
  805. list.concat(taicpu.op_reg(topcg2asmop[op],src));
  806. a_load_reg_reg(list,OS_8,OS_8,NR_A,dst);
  807. end;
  808. ungetcpuregister(list,NR_A);
  809. end;
  810. else
  811. begin
  812. list.Concat(tai_comment.Create(strpnew('TODO: a_op_reg_reg_internal '+topcg2str(Op))));
  813. //internalerror(2011022004);
  814. end;
  815. end;
  816. end;
  817. procedure tcgmos6502.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
  818. size: TCGSize; a: tcgint; reg, reghi: TRegister);
  819. var
  820. i : byte;
  821. procedure NextReg;
  822. begin
  823. if i=4 then
  824. reg:=reghi
  825. else
  826. reg:=GetNextReg(reg);
  827. end;
  828. //var
  829. // mask : qword;
  830. // shift : byte;
  831. // curvalue : byte;
  832. // tmpop: TAsmOp;
  833. // l1: TAsmLabel;
  834. // instr: taicpu;
  835. // tmpreg : tregister;
  836. // tmpreg64 : tregister64;
  837. begin
  838. // optimize_op_const(size,op,a);
  839. // mask:=$ff;
  840. // shift:=0;
  841. // l1:=nil;
  842. // case op of
  843. // OP_NONE:
  844. // begin
  845. // { Opcode is optimized away }
  846. // end;
  847. // OP_MOVE:
  848. // begin
  849. // { Optimized, replaced with a simple load }
  850. // a_load_const_reg(list,size,a,reg);
  851. // end;
  852. // OP_AND:
  853. // begin
  854. // curvalue:=a and mask;
  855. // for i:=1 to tcgsize2size[size] do
  856. // begin
  857. // case curvalue of
  858. // 0:
  859. // list.concat(taicpu.op_reg_const(A_LD,reg,0));
  860. // $ff:
  861. // {nothing};
  862. // else
  863. // begin
  864. // getcpuregister(list,NR_A);
  865. // emit_mov(list,NR_A,reg);
  866. // list.concat(taicpu.op_reg_const(A_AND,NR_A,curvalue));
  867. // emit_mov(list,reg,NR_A);
  868. // ungetcpuregister(list,NR_A);
  869. // end;
  870. // end;
  871. // if i<>tcgsize2size[size] then
  872. // begin
  873. // NextReg;
  874. // mask:=mask shl 8;
  875. // inc(shift,8);
  876. // curvalue:=(qword(a) and mask) shr shift;
  877. // end;
  878. // end;
  879. // end;
  880. // OP_OR:
  881. // begin
  882. // curvalue:=a and mask;
  883. // for i:=1 to tcgsize2size[size] do
  884. // begin
  885. // case curvalue of
  886. // 0:
  887. // {nothing};
  888. // $ff:
  889. // list.concat(taicpu.op_reg_const(A_LD,reg,$ff));
  890. // else
  891. // begin
  892. // getcpuregister(list,NR_A);
  893. // emit_mov(list,NR_A,reg);
  894. // list.concat(taicpu.op_reg_const(A_OR,NR_A,curvalue));
  895. // emit_mov(list,reg,NR_A);
  896. // ungetcpuregister(list,NR_A);
  897. // end;
  898. // end;
  899. // if i<>tcgsize2size[size] then
  900. // begin
  901. // NextReg;
  902. // mask:=mask shl 8;
  903. // inc(shift,8);
  904. // curvalue:=(qword(a) and mask) shr shift;
  905. // end;
  906. // end;
  907. // end;
  908. // OP_XOR:
  909. // begin
  910. // curvalue:=a and mask;
  911. // for i:=1 to tcgsize2size[size] do
  912. // begin
  913. // case curvalue of
  914. // 0:
  915. // {nothing};
  916. // $ff:
  917. // begin
  918. // getcpuregister(list,NR_A);
  919. // emit_mov(list,NR_A,reg);
  920. // list.concat(taicpu.op_none(A_CPL));
  921. // emit_mov(list,reg,NR_A);
  922. // ungetcpuregister(list,NR_A);
  923. // end;
  924. // else
  925. // begin
  926. // getcpuregister(list,NR_A);
  927. // emit_mov(list,NR_A,reg);
  928. // list.concat(taicpu.op_reg_const(A_XOR,NR_A,curvalue));
  929. // emit_mov(list,reg,NR_A);
  930. // ungetcpuregister(list,NR_A);
  931. // end;
  932. // end;
  933. // if i<>tcgsize2size[size] then
  934. // begin
  935. // NextReg;
  936. // mask:=mask shl 8;
  937. // inc(shift,8);
  938. // curvalue:=(qword(a) and mask) shr shift;
  939. // end;
  940. // end;
  941. // end;
  942. // OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  943. // begin
  944. // if size in [OS_64,OS_S64] then
  945. // a:=a and 63
  946. // else
  947. // a:=a and 31;
  948. // if a<>0 then
  949. // begin
  950. // if a>1 then
  951. // begin
  952. // current_asmdata.getjumplabel(l1);
  953. // getcpuregister(list,NR_B);
  954. // list.concat(taicpu.op_reg_const(A_LD,NR_B,a));
  955. // end;
  956. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  957. // case op of
  958. // OP_ROL:
  959. // begin
  960. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  961. // list.concat(taicpu.op_reg(A_RLC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  962. // end;
  963. // OP_ROR:
  964. // begin
  965. // list.concat(taicpu.op_reg(A_RLC,reg));
  966. // list.concat(taicpu.op_reg(A_RRC,reg));
  967. // end;
  968. // else
  969. // ;
  970. // end;
  971. // if a>1 then
  972. // cg.a_label(list,l1);
  973. // case op of
  974. // OP_SHL:
  975. // list.concat(taicpu.op_reg(A_SLA,reg));
  976. // OP_SHR:
  977. // list.concat(taicpu.op_reg(A_SRL,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  978. // OP_SAR:
  979. // list.concat(taicpu.op_reg(A_SRA,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  980. // OP_ROL:
  981. // if size in [OS_8,OS_S8] then
  982. // list.concat(taicpu.op_reg(A_RLC,reg))
  983. // else
  984. // list.concat(taicpu.op_reg(A_RL,reg));
  985. // OP_ROR:
  986. // if size in [OS_8,OS_S8] then
  987. // list.concat(taicpu.op_reg(A_RRC,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)))
  988. // else
  989. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-1)));
  990. // else
  991. // internalerror(2020040905);
  992. // end;
  993. // if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  994. // begin
  995. // for i:=2 to tcgsize2size[size] do
  996. // begin
  997. // case op of
  998. // OP_ROR,
  999. // OP_SHR,
  1000. // OP_SAR:
  1001. // list.concat(taicpu.op_reg(A_RR,GetOffsetReg64(reg,reghi,tcgsize2size[size]-i)));
  1002. // OP_ROL,
  1003. // OP_SHL:
  1004. // list.concat(taicpu.op_reg(A_RL,GetOffsetReg64(reg,reghi,i-1)));
  1005. // else
  1006. // internalerror(2020040906);
  1007. // end;
  1008. // end;
  1009. // end;
  1010. // if a>1 then
  1011. // begin
  1012. // instr:=taicpu.op_sym(A_DJNZ,l1);
  1013. // instr.is_jmp:=true;
  1014. // list.concat(instr);
  1015. // ungetcpuregister(list,NR_B);
  1016. // end;
  1017. // end;
  1018. // end;
  1019. // OP_ADD:
  1020. // begin
  1021. // curvalue:=a and mask;
  1022. // tmpop:=A_NONE;
  1023. // for i:=1 to tcgsize2size[size] do
  1024. // begin
  1025. // if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  1026. // tmpop:=A_INC
  1027. // else if (tmpop=A_NONE) and (curvalue=255) and (i=tcgsize2size[size]) then
  1028. // tmpop:=A_DEC
  1029. // else if (tmpop=A_NONE) and (curvalue<>0) then
  1030. // tmpop:=A_ADD
  1031. // else if tmpop=A_ADD then
  1032. // tmpop:=A_ADC;
  1033. // case tmpop of
  1034. // A_NONE:
  1035. // {nothing};
  1036. // A_INC,A_DEC:
  1037. // list.concat(taicpu.op_reg(tmpop,reg));
  1038. // A_ADD,A_ADC:
  1039. // begin
  1040. // getcpuregister(list,NR_A);
  1041. // emit_mov(list,NR_A,reg);
  1042. // list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  1043. // emit_mov(list,reg,NR_A);
  1044. // ungetcpuregister(list,NR_A);
  1045. // end;
  1046. // else
  1047. // internalerror(2020040901);
  1048. // end;
  1049. // if i<>tcgsize2size[size] then
  1050. // begin
  1051. // NextReg;
  1052. // mask:=mask shl 8;
  1053. // inc(shift,8);
  1054. // curvalue:=(qword(a) and mask) shr shift;
  1055. // end;
  1056. // end;
  1057. // end;
  1058. // OP_SUB:
  1059. // begin
  1060. // curvalue:=a and mask;
  1061. // tmpop:=A_NONE;
  1062. // for i:=1 to tcgsize2size[size] do
  1063. // begin
  1064. // if (tmpop=A_NONE) and (curvalue=1) and (i=tcgsize2size[size]) then
  1065. // tmpop:=A_DEC
  1066. // else if (tmpop=A_NONE) and (curvalue=255) and (i=tcgsize2size[size]) then
  1067. // tmpop:=A_INC
  1068. // else if (tmpop=A_NONE) and (curvalue<>0) then
  1069. // tmpop:=A_SUB
  1070. // else if tmpop=A_SUB then
  1071. // tmpop:=A_SBC;
  1072. // case tmpop of
  1073. // A_NONE:
  1074. // {nothing};
  1075. // A_DEC,A_INC:
  1076. // list.concat(taicpu.op_reg(tmpop,reg));
  1077. // A_SUB,A_SBC:
  1078. // begin
  1079. // getcpuregister(list,NR_A);
  1080. // emit_mov(list,NR_A,reg);
  1081. // list.concat(taicpu.op_reg_const(tmpop,NR_A,curvalue));
  1082. // emit_mov(list,reg,NR_A);
  1083. // ungetcpuregister(list,NR_A);
  1084. // end;
  1085. // else
  1086. // internalerror(2020040902);
  1087. // end;
  1088. // if i<>tcgsize2size[size] then
  1089. // begin
  1090. // NextReg;
  1091. // mask:=mask shl 8;
  1092. // inc(shift,8);
  1093. // curvalue:=(qword(a) and mask) shr shift;
  1094. // end;
  1095. // end;
  1096. // end;
  1097. // else
  1098. // begin
  1099. // if size in [OS_64,OS_S64] then
  1100. // begin
  1101. // tmpreg64.reglo:=getintregister(list,OS_32);
  1102. // tmpreg64.reghi:=getintregister(list,OS_32);
  1103. // cg64.a_load64_const_reg(list,a,tmpreg64);
  1104. // cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
  1105. // end
  1106. // else
  1107. // begin
  1108. {$if 0}//
  1109. // { code not working yet }
  1110. // if (op=OP_SAR) and (a=31) and (size in [OS_32,OS_S32]) then
  1111. // begin
  1112. // tmpreg:=reg;
  1113. // for i:=1 to 4 do
  1114. // begin
  1115. // list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
  1116. // tmpreg:=GetNextReg(tmpreg);
  1117. // end;
  1118. // end
  1119. // else
  1120. {$endif//}
  1121. // begin
  1122. // tmpreg:=getintregister(list,size);
  1123. // a_load_const_reg(list,size,a,tmpreg);
  1124. // a_op_reg_reg(list,op,size,tmpreg,reg);
  1125. // end;
  1126. // end;
  1127. // end;
  1128. //end;
  1129. end;
  1130. procedure tcgmos6502.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
  1131. //var
  1132. // pd: tprocdef;
  1133. // paraloc1, paraloc2: tcgpara;
  1134. // ai: taicpu;
  1135. // hl, no_overflow: TAsmLabel;
  1136. // name: String;
  1137. begin
  1138. //if size in [OS_8,OS_S8] then
  1139. // begin
  1140. // if size=OS_8 then
  1141. // name:='fpc_mul_byte'
  1142. // else
  1143. // name:='fpc_mul_shortint';
  1144. //
  1145. // if check_overflow then
  1146. // name:=name+'_checkoverflow';
  1147. //
  1148. // pd:=search_system_proc(name);
  1149. // paraloc1.init;
  1150. // paraloc2.init;
  1151. // paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1152. // paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1153. // a_load_reg_cgpara(list,OS_8,src1,paraloc2);
  1154. // a_load_reg_cgpara(list,OS_8,src2,paraloc1);
  1155. // paramanager.freecgpara(list,paraloc2);
  1156. // paramanager.freecgpara(list,paraloc1);
  1157. // alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1158. // a_call_name(list,upper(name),false);
  1159. // dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1160. // cg.a_reg_alloc(list,NR_L);
  1161. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
  1162. // cg.a_reg_dealloc(list,NR_L);
  1163. // paraloc2.done;
  1164. // paraloc1.done;
  1165. // end
  1166. //else if size in [OS_16,OS_S16] then
  1167. // begin
  1168. // if size=OS_16 then
  1169. // name:='fpc_mul_word'
  1170. // else
  1171. // name:='fpc_mul_integer';
  1172. //
  1173. // if check_overflow then
  1174. // name:=name+'_checkoverflow';
  1175. //
  1176. // pd:=search_system_proc(name);
  1177. // paraloc1.init;
  1178. // paraloc2.init;
  1179. // paramanager.getcgtempparaloc(list,pd,1,paraloc1);
  1180. // paramanager.getcgtempparaloc(list,pd,2,paraloc2);
  1181. // a_load_reg_cgpara(list,OS_16,src1,paraloc2);
  1182. // a_load_reg_cgpara(list,OS_16,src2,paraloc1);
  1183. // paramanager.freecgpara(list,paraloc2);
  1184. // paramanager.freecgpara(list,paraloc1);
  1185. // alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1186. // a_call_name(list,upper(name),false);
  1187. // dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1188. // cg.a_reg_alloc(list,NR_L);
  1189. // cg.a_reg_alloc(list,NR_H);
  1190. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
  1191. // cg.a_reg_dealloc(list,NR_L);
  1192. // cg.a_load_reg_reg(list,OS_8,OS_8,NR_H,GetNextReg(dst));
  1193. // cg.a_reg_dealloc(list,NR_H);
  1194. // paraloc2.done;
  1195. // paraloc1.done;
  1196. // end
  1197. //else
  1198. // internalerror(2011022002);
  1199. end;
  1200. procedure tcgmos6502.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
  1201. var
  1202. mask : qword;
  1203. shift : byte;
  1204. i : byte;
  1205. begin
  1206. list.Concat(tai_comment.Create(strpnew('TODO: a_load_const_reg '+tcgsize2str(size)+' '+tostr(a)+' '+std_regname(reg))));
  1207. if is_6502_general_purpose_register(reg) then
  1208. begin
  1209. if not (size in [OS_8,OS_S8]) then
  1210. internalerror(2024040704);
  1211. if reg=NR_A then
  1212. list.Concat(taicpu.op_const(A_LDA,byte(a)))
  1213. else if reg=NR_X then
  1214. list.Concat(taicpu.op_const(A_LDX,byte(a)))
  1215. else if reg=NR_Y then
  1216. list.Concat(taicpu.op_const(A_LDY,byte(a)))
  1217. else
  1218. internalerror(2024040705);
  1219. end
  1220. else
  1221. begin
  1222. getcpuregister(list,NR_A);
  1223. mask:=$ff;
  1224. shift:=0;
  1225. for i:=tcgsize2size[size] downto 1 do
  1226. begin
  1227. list.Concat(taicpu.op_const(A_LDA,(qword(a) and mask) shr shift));
  1228. list.Concat(taicpu.op_reg(A_STA,reg));
  1229. if i<>1 then
  1230. begin
  1231. mask:=mask shl 8;
  1232. inc(shift,8);
  1233. reg:=GetNextReg(reg);
  1234. end;
  1235. end;
  1236. ungetcpuregister(list,NR_A);
  1237. end;
  1238. end;
  1239. procedure tcgmos6502.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
  1240. var
  1241. mask : qword;
  1242. shift : byte;
  1243. href: treference;
  1244. i: Integer;
  1245. begin
  1246. list.Concat(tai_comment.Create(strpnew('TODO: a_load_const_ref '+tcgsize2str(size) + ' '+tostr(a)+' '+ref2string(ref))));
  1247. mask:=$ff;
  1248. shift:=0;
  1249. href:=ref;
  1250. if (href.base=NR_NO) and (href.index=NR_NO) then
  1251. begin
  1252. { TODO: get/unget register A }
  1253. for i:=tcgsize2size[size] downto 1 do
  1254. begin
  1255. list.Concat(taicpu.op_const(A_LDA,(qword(a) and mask) shr shift));
  1256. list.Concat(taicpu.op_ref(A_STA,href));
  1257. if i<>1 then
  1258. begin
  1259. mask:=mask shl 8;
  1260. inc(shift,8);
  1261. inc(href.offset);
  1262. end;
  1263. end;
  1264. end;
  1265. //if (href.base=NR_NO) and (href.index<>NR_NO) then
  1266. // begin
  1267. // href.base:=href.index;
  1268. // href.index:=NR_NO;
  1269. // end;
  1270. //if is_ref_in_opertypes(href,[OT_REF_IX_d,OT_REF_IY_d]) or
  1271. // (is_ref_hl(href) and (size in [OS_8,OS_S8])) then
  1272. // begin
  1273. // for i:=tcgsize2size[size] downto 1 do
  1274. // begin
  1275. // list.Concat(taicpu.op_ref_const(A_LD,href,(qword(a) and mask) shr shift));
  1276. // if i<>1 then
  1277. // begin
  1278. // mask:=mask shl 8;
  1279. // inc(shift,8);
  1280. // inc(href.offset);
  1281. // end;
  1282. // end;
  1283. // end
  1284. //else
  1285. // inherited;
  1286. end;
  1287. //function tcgmos6502.normalize_ref(list: TAsmList; ref: treference;
  1288. // const refopertypes: trefoperandtypes; out allocatedregs: tregisterlist): treference;
  1289. // var
  1290. // tmpref : treference;
  1291. // l : tasmlabel;
  1292. // begin
  1293. // SetLength(allocatedregs,0);
  1294. //
  1295. // if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=1) then
  1296. // begin
  1297. // ref.base:=ref.index;
  1298. // ref.index:=NR_NO;
  1299. // end;
  1300. //
  1301. // if is_ref_in_opertypes(ref,refopertypes) then
  1302. // begin
  1303. // Result:=ref;
  1304. // exit;
  1305. // end;
  1306. //
  1307. // { can we use the HL register? }
  1308. // if OT_REF_HL in refopertypes then
  1309. // begin
  1310. // SetLength(allocatedregs,2);
  1311. // allocatedregs[0]:=NR_H;
  1312. // allocatedregs[1]:=NR_L;
  1313. // getcpuregisters(list,allocatedregs);
  1314. // if assigned(ref.symbol) or (ref.offset<>0) then
  1315. // begin
  1316. // if assigned(ref.symbol) then
  1317. // begin
  1318. // reference_reset(tmpref,0,[]);
  1319. // tmpref.symbol:=ref.symbol;
  1320. // tmpref.offset:=ref.offset;
  1321. //
  1322. // tmpref.refaddr:=addr_full;
  1323. // list.concat(taicpu.op_reg_ref(A_LD,NR_HL,tmpref));
  1324. // end
  1325. // else
  1326. // list.concat(taicpu.op_reg_const(A_LD,NR_HL,ref.offset));
  1327. // if (ref.base=NR_IX) or (ref.base=NR_IY) then
  1328. // begin
  1329. // getcpuregister(list,NR_D);
  1330. // getcpuregister(list,NR_E);
  1331. // list.concat(taicpu.op_reg(A_PUSH,ref.base));
  1332. // list.concat(taicpu.op_reg(A_POP,NR_DE));
  1333. // list.concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_DE));
  1334. // ungetcpuregister(list,NR_E);
  1335. // ungetcpuregister(list,NR_D);
  1336. // end
  1337. // else if ref.base<>NR_NO then
  1338. // begin
  1339. // getcpuregister(list,NR_A);
  1340. // emit_mov(list,NR_A,NR_L);
  1341. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.base));
  1342. // emit_mov(list,NR_L,NR_A);
  1343. // emit_mov(list,NR_A,NR_H);
  1344. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.base)));
  1345. // emit_mov(list,NR_H,NR_A);
  1346. // ungetcpuregister(list,NR_A);
  1347. // end;
  1348. // if ref.index<>NR_NO then
  1349. // begin
  1350. // if ref.scalefactor>1 then
  1351. // internalerror(2020042002);
  1352. // getcpuregister(list,NR_A);
  1353. // emit_mov(list,NR_A,NR_L);
  1354. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.index));
  1355. // emit_mov(list,NR_L,NR_A);
  1356. // emit_mov(list,NR_A,NR_H);
  1357. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.index)));
  1358. // emit_mov(list,NR_H,NR_A);
  1359. // ungetcpuregister(list,NR_A);
  1360. // end;
  1361. // end
  1362. // else
  1363. // begin
  1364. // { not assigned(ref.symbol) and (ref.offset=0) }
  1365. // if (ref.base=NR_IX) or (ref.base=NR_IY) then
  1366. // begin
  1367. // list.concat(taicpu.op_reg(A_PUSH,ref.base));
  1368. // list.concat(taicpu.op_reg(A_POP,NR_HL));
  1369. // end
  1370. // else if ref.base<>NR_NO then
  1371. // begin
  1372. // emit_mov(list,NR_L,ref.base);
  1373. // emit_mov(list,NR_H,GetNextReg(ref.base));
  1374. // end;
  1375. // if ref.index<>NR_NO then
  1376. // begin
  1377. // if ref.scalefactor>1 then
  1378. // internalerror(2020042003);
  1379. // getcpuregister(list,NR_A);
  1380. // emit_mov(list,NR_A,NR_L);
  1381. // list.concat(taicpu.op_reg_reg(A_ADD,NR_A,ref.index));
  1382. // emit_mov(list,NR_L,NR_A);
  1383. // emit_mov(list,NR_A,NR_H);
  1384. // list.concat(taicpu.op_reg_reg(A_ADC,NR_A,GetNextReg(ref.index)));
  1385. // emit_mov(list,NR_H,NR_A);
  1386. // ungetcpuregister(list,NR_A);
  1387. // end;
  1388. // end;
  1389. // reference_reset_base(result,NR_HL,0,ctempposinvalid,0,[]);
  1390. // end
  1391. // else
  1392. // internalerror(2020042001);
  1393. // end;
  1394. procedure tcgmos6502.adjust_normalized_ref(list: TAsmList; var ref: treference; value: longint);
  1395. //var
  1396. // i: Integer;
  1397. begin
  1398. inc(ref.offset,value);
  1399. //if is_ref_addr16(ref) then
  1400. // Inc(ref.offset,value)
  1401. //else if is_ref_hl(ref) then
  1402. // begin
  1403. // if value>0 then
  1404. // for i:=1 to value do
  1405. // list.concat(taicpu.op_reg(A_INC,NR_HL))
  1406. // else
  1407. // for i:=-1 downto value do
  1408. // list.concat(taicpu.op_reg(A_DEC,NR_HL));
  1409. // end
  1410. //else if is_ref_ix_d(ref) then
  1411. // begin
  1412. // if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1413. // inc(ref.offset,value)
  1414. // else
  1415. // begin
  1416. // { todo: IX is the frame pointer, we cannot change it, so we }
  1417. // { think of another mechanism to deal with this situation }
  1418. // internalerror(2020042101);
  1419. // //if value>0 then
  1420. // // for i:=1 to value do
  1421. // // list.concat(taicpu.op_reg(A_INC,NR_IX))
  1422. // //else
  1423. // // for i:=-1 downto value do
  1424. // // list.concat(taicpu.op_reg(A_DEC,NR_IX));
  1425. // end;
  1426. // end
  1427. //else if is_ref_iy_d(ref) then
  1428. // begin
  1429. // if ((ref.offset+value)<=127) and ((ref.offset+value)>=-128) then
  1430. // inc(ref.offset,value)
  1431. // else
  1432. // if value>0 then
  1433. // for i:=1 to value do
  1434. // list.concat(taicpu.op_reg(A_INC,NR_IY))
  1435. // else
  1436. // for i:=-1 downto value do
  1437. // list.concat(taicpu.op_reg(A_DEC,NR_IY));
  1438. // end;
  1439. end;
  1440. procedure tcgmos6502.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  1441. var
  1442. href : treference;
  1443. i : integer;
  1444. // regsused: tregisterlist;
  1445. begin
  1446. list.Concat(tai_comment.Create(strpnew('TODO: a_load_reg_ref '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg)+' '+ref2string(ref))));
  1447. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1448. internalerror(2011021307);
  1449. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1450. internalerror(2020040802);
  1451. //href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1452. href:=ref;
  1453. if (href.base=NR_NO) and (href.index=NR_NO) and
  1454. ((tcgsize2size[fromsize]=tcgsize2size[tosize]) or (fromsize in [OS_8,OS_16,OS_32])) then
  1455. begin
  1456. getcpuregister(list,NR_A);
  1457. for i:=1 to tcgsize2size[fromsize] do
  1458. begin
  1459. a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1460. list.concat(taicpu.op_ref(A_STA,href));
  1461. if i<>tcgsize2size[fromsize] then
  1462. reg:=GetNextReg(reg);
  1463. if i<>tcgsize2size[tosize] then
  1464. adjust_normalized_ref(list,href,1);
  1465. end;
  1466. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1467. begin
  1468. if i=(tcgsize2size[fromsize]+1) then
  1469. list.concat(taicpu.op_const(A_LDA,0));
  1470. list.concat(taicpu.op_ref(A_STA,href));
  1471. if i<>tcgsize2size[tosize] then
  1472. begin
  1473. adjust_normalized_ref(list,href,1);
  1474. reg:=GetNextReg(reg);
  1475. end;
  1476. end;
  1477. ungetcpuregister(list,NR_A);
  1478. end
  1479. //else
  1480. // begin
  1481. // getcpuregister(list,NR_A);
  1482. // for i:=1 to tcgsize2size[fromsize] do
  1483. // begin
  1484. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1485. // list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1486. // if i<>tcgsize2size[fromsize] then
  1487. // reg:=GetNextReg(reg);
  1488. // if i<>tcgsize2size[tosize] then
  1489. // adjust_normalized_ref(list,href,1);
  1490. // end;
  1491. // list.concat(taicpu.op_none(A_RLA));
  1492. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1493. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1494. // begin
  1495. // list.concat(taicpu.op_ref_reg(A_LD,href,NR_A));
  1496. // if i<>tcgsize2size[tosize] then
  1497. // begin
  1498. // adjust_normalized_ref(list,href,1);
  1499. // reg:=GetNextReg(reg);
  1500. // end;
  1501. // end;
  1502. // ungetcpuregister(list,NR_A);
  1503. // end;
  1504. //ungetcpuregisters(list,regsused);
  1505. end;
  1506. procedure tcgmos6502.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  1507. const Ref : treference;reg : tregister);
  1508. var
  1509. href : treference;
  1510. i : integer;
  1511. // regsused: tregisterlist;
  1512. begin
  1513. list.Concat(tai_comment.Create(strpnew('TODO: a_load_ref_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+ref2string(Ref)+' '+std_regname(reg))));
  1514. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1515. internalerror(2011021301);
  1516. if tcgsize2size[fromsize]>=tcgsize2size[tosize] then
  1517. fromsize:=tosize;
  1518. //href:=normalize_ref(list,Ref,[OT_REF_ADDR16,OT_REF_HL,OT_REF_IX_d,OT_REF_IY_d],regsused);
  1519. href:=Ref;
  1520. if (href.base=NR_NO) and (href.index=NR_NO) and
  1521. ((tcgsize2size[tosize]=tcgsize2size[fromsize]) or (fromsize in [OS_8,OS_16,OS_32])) then
  1522. begin
  1523. getcpuregister(list,NR_A);
  1524. for i:=1 to tcgsize2size[fromsize] do
  1525. begin
  1526. list.concat(taicpu.op_ref(A_LDA,href));
  1527. list.concat(taicpu.op_reg(A_STA,reg));
  1528. //a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1529. //if i<>tcgsize2size[fromsize] then
  1530. // adjust_normalized_ref(list,href,1);
  1531. if i<>tcgsize2size[tosize] then
  1532. reg:=GetNextReg(reg);
  1533. end;
  1534. //ungetcpuregisters(list,regsused);
  1535. ungetcpuregister(list,NR_A);
  1536. //for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1537. // begin
  1538. // list.concat(taicpu.op_reg_const(A_LD,reg,0));
  1539. // if i<>tcgsize2size[tosize] then
  1540. // reg:=GetNextReg(reg);
  1541. // end;
  1542. end
  1543. //else
  1544. // begin
  1545. // getcpuregister(list,NR_A);
  1546. // for i:=1 to tcgsize2size[fromsize] do
  1547. // begin
  1548. // list.concat(taicpu.op_reg_ref(A_LD,NR_A,href));
  1549. // a_load_reg_reg(list,OS_8,OS_8,NR_A,reg);
  1550. //
  1551. // if i<>tcgsize2size[fromsize] then
  1552. // adjust_normalized_ref(list,href,1);
  1553. // if i<>tcgsize2size[tosize] then
  1554. // reg:=GetNextReg(reg);
  1555. // end;
  1556. // ungetcpuregisters(list,regsused);
  1557. // list.concat(taicpu.op_none(A_RLA));
  1558. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1559. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1560. // begin
  1561. // emit_mov(list,reg,NR_A);
  1562. // if i<>tcgsize2size[tosize] then
  1563. // reg:=GetNextReg(reg);
  1564. // end;
  1565. // ungetcpuregister(list,NR_A);
  1566. // end;
  1567. end;
  1568. procedure tcgmos6502.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  1569. var
  1570. // conv_done: boolean;
  1571. // tmpreg : tregister;
  1572. i : integer;
  1573. begin
  1574. { sign extend
  1575. AND #$80
  1576. ASL A -> sign bit goes to the Carry flag
  1577. SBC #$01
  1578. ADC #$FF
  1579. EOR #$FF
  1580. }
  1581. list.Concat(tai_comment.Create(strpnew('TODO: a_load_reg_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg1)+' '+std_regname(reg2))));
  1582. Writeln('TODO: a_load_reg_reg '+tcgsize2str(fromsize)+' '+tcgsize2str(tosize)+' '+std_regname(reg1)+' '+std_regname(reg2));
  1583. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1584. internalerror(2011021310);
  1585. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1586. fromsize:=tosize;
  1587. if (tcgsize2size[tosize]=tcgsize2size[fromsize]) or (fromsize in [OS_8,OS_16,OS_32]) then
  1588. begin
  1589. if reg1<>reg2 then
  1590. for i:=1 to tcgsize2size[fromsize] do
  1591. begin
  1592. emit_mov(list,reg2,reg1);
  1593. if i<>tcgsize2size[fromsize] then
  1594. reg1:=GetNextReg(reg1);
  1595. if i<>tcgsize2size[tosize] then
  1596. reg2:=GetNextReg(reg2);
  1597. end
  1598. else
  1599. for i:=1 to tcgsize2size[fromsize] do
  1600. if i<>tcgsize2size[tosize] then
  1601. reg2:=GetNextReg(reg2);
  1602. if tcgsize2size[tosize]>tcgsize2size[fromsize] then
  1603. begin
  1604. getcpuregister(list,NR_A);
  1605. list.Concat(taicpu.op_const(A_LDA,0));
  1606. for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1607. begin
  1608. list.Concat(taicpu.op_reg(A_STA,reg2));
  1609. if i<>tcgsize2size[tosize] then
  1610. reg2:=GetNextReg(reg2);
  1611. end;
  1612. ungetcpuregister(list,NR_A);
  1613. end;
  1614. end
  1615. //else
  1616. // begin
  1617. // if reg1<>reg2 then
  1618. // for i:=1 to tcgsize2size[fromsize]-1 do
  1619. // begin
  1620. // emit_mov(list,reg2,reg1);
  1621. // reg1:=GetNextReg(reg1);
  1622. // reg2:=GetNextReg(reg2);
  1623. // end
  1624. // else
  1625. // for i:=1 to tcgsize2size[fromsize]-1 do
  1626. // reg2:=GetNextReg(reg2);
  1627. // emit_mov(list,reg2,reg1);
  1628. // getcpuregister(list,NR_A);
  1629. // emit_mov(list,NR_A,reg2);
  1630. // reg2:=GetNextReg(reg2);
  1631. // list.concat(taicpu.op_none(A_RLA));
  1632. // list.concat(taicpu.op_reg_reg(A_SBC,NR_A,NR_A));
  1633. // for i:=tcgsize2size[fromsize]+1 to tcgsize2size[tosize] do
  1634. // begin
  1635. // emit_mov(list,reg2,NR_A);
  1636. // if i<>tcgsize2size[tosize] then
  1637. // reg2:=GetNextReg(reg2);
  1638. // end;
  1639. // ungetcpuregister(list,NR_A);
  1640. // end;
  1641. end;
  1642. procedure tcgmos6502.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
  1643. begin
  1644. internalerror(2012010702);
  1645. end;
  1646. procedure tcgmos6502.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
  1647. begin
  1648. internalerror(2012010703);
  1649. end;
  1650. procedure tcgmos6502.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
  1651. begin
  1652. internalerror(2012010704);
  1653. end;
  1654. { comparison operations }
  1655. procedure tcgmos6502.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
  1656. cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
  1657. //var
  1658. // swapped : boolean;
  1659. // tmpreg : tregister;
  1660. // i : byte;
  1661. // tmpl: TAsmLabel;
  1662. begin
  1663. //tmpl:=nil;
  1664. //if size in [OS_8,OS_S8]then
  1665. // begin
  1666. // if cmp_op in [OC_EQ,OC_NE,OC_B,OC_AE] then
  1667. // begin
  1668. // getcpuregister(list,NR_A);
  1669. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1670. // list.concat(taicpu.op_reg_const(A_CP,NR_A,a));
  1671. // case cmp_op of
  1672. // OC_EQ:
  1673. // a_jmp_flags(list,F_E,l);
  1674. // OC_NE:
  1675. // a_jmp_flags(list,F_NE,l);
  1676. // OC_B:
  1677. // a_jmp_flags(list,F_C,l);
  1678. // OC_AE:
  1679. // a_jmp_flags(list,F_NC,l);
  1680. // else
  1681. // internalerror(2020042206);
  1682. // end;
  1683. // ungetcpuregister(list,NR_A);
  1684. // end
  1685. // else if cmp_op in [OC_A,OC_BE] then
  1686. // begin
  1687. // getcpuregister(list,NR_A);
  1688. // a_load_const_reg(list,OS_8,a,NR_A);
  1689. // list.concat(taicpu.op_reg_reg(A_CP,NR_A,reg));
  1690. // case cmp_op of
  1691. // OC_A:
  1692. // a_jmp_flags(list,F_C,l);
  1693. // OC_BE:
  1694. // a_jmp_flags(list,F_NC,l);
  1695. // else
  1696. // internalerror(2020042218);
  1697. // end;
  1698. // ungetcpuregister(list,NR_A);
  1699. // end
  1700. // else if cmp_op in [OC_LT,OC_GTE] then
  1701. // begin
  1702. // getcpuregister(list,NR_A);
  1703. // a_load_reg_reg(list,OS_8,OS_8,reg,NR_A);
  1704. // list.concat(taicpu.op_reg_const(A_SUB,NR_A,a));
  1705. // current_asmdata.getjumplabel(tmpl);
  1706. // a_jmp_flags(list,F_PO,tmpl);
  1707. // current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1708. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1709. // case cmp_op of
  1710. // OC_LT:
  1711. // a_jmp_flags(list,F_M,l);
  1712. // OC_GTE:
  1713. // a_jmp_flags(list,F_P,l);
  1714. // else
  1715. // internalerror(2020042219);
  1716. // end;
  1717. // ungetcpuregister(list,NR_A);
  1718. // end
  1719. // else if cmp_op in [OC_GT,OC_LTE] then
  1720. // begin
  1721. // getcpuregister(list,NR_A);
  1722. // a_load_const_reg(list,OS_8,a,NR_A);
  1723. // list.concat(taicpu.op_reg_reg(A_SUB,NR_A,reg));
  1724. // current_asmdata.getjumplabel(tmpl);
  1725. // a_jmp_flags(list,F_PO,tmpl);
  1726. // current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
  1727. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1728. // case cmp_op of
  1729. // OC_GT:
  1730. // a_jmp_flags(list,F_M,l);
  1731. // OC_LTE:
  1732. // a_jmp_flags(list,F_P,l);
  1733. // else
  1734. // internalerror(2020042220);
  1735. // end;
  1736. // ungetcpuregister(list,NR_A);
  1737. // end;
  1738. // end
  1739. //else if cmp_op in [OC_EQ,OC_NE] then
  1740. // begin
  1741. // if cmp_op=OC_EQ then
  1742. // current_asmdata.getjumplabel(tmpl);
  1743. // for i:=0 to tcgsize2size[size]-1 do
  1744. // begin
  1745. // a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1746. // list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1747. // case cmp_op of
  1748. // OC_EQ:
  1749. // if i<>(tcgsize2size[size]-1) then
  1750. // a_jmp_flags(list,F_NE,tmpl)
  1751. // else
  1752. // a_jmp_flags(list,F_E,l);
  1753. // OC_NE:
  1754. // a_jmp_flags(list,F_NE,l);
  1755. // else
  1756. // internalerror(2020042221);
  1757. // end;
  1758. // end;
  1759. // if cmp_op=OC_EQ then
  1760. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1761. // end
  1762. //else if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE,OC_BE,OC_B,OC_AE,OC_A] then
  1763. // begin
  1764. // getcpuregister(list,NR_A);
  1765. // current_asmdata.getjumplabel(tmpl);
  1766. // for i:=tcgsize2size[size]-1 downto 0 do
  1767. // begin
  1768. // a_load_reg_reg(list,OS_8,OS_8,GetOffsetReg(reg,i),NR_A);
  1769. // list.concat(taicpu.op_reg_const(A_CP,NR_A,Byte(a shr (8*i))));
  1770. // if (i=(tcgsize2size[size]-1)) and (cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE]) then
  1771. // case cmp_op of
  1772. // OC_GTE,
  1773. // OC_GT:
  1774. // a_jmp_signed_cmp_3way(list,tmpl,nil,l);
  1775. // OC_LT,
  1776. // OC_LTE:
  1777. // a_jmp_signed_cmp_3way(list,l,nil,tmpl);
  1778. // else
  1779. // internalerror(2020042222);
  1780. // end
  1781. // else if i<>0 then
  1782. // case cmp_op of
  1783. // OC_AE,
  1784. // OC_A,
  1785. // OC_GTE,
  1786. // OC_GT:
  1787. // a_jmp_unsigned_cmp_3way(list,tmpl,nil,l);
  1788. // OC_BE,
  1789. // OC_B,
  1790. // OC_LT,
  1791. // OC_LTE:
  1792. // a_jmp_unsigned_cmp_3way(list,l,nil,tmpl);
  1793. // else
  1794. // internalerror(2020042223);
  1795. // end
  1796. // else
  1797. // case cmp_op of
  1798. // OC_A,
  1799. // OC_GT:
  1800. // a_jmp_unsigned_cmp_3way(list,nil,nil,l);
  1801. // OC_B,
  1802. // OC_LT:
  1803. // a_jmp_unsigned_cmp_3way(list,l,nil,nil);
  1804. // OC_AE,
  1805. // OC_GTE:
  1806. // a_jmp_unsigned_cmp_3way(list,nil,l,l);
  1807. // OC_BE,
  1808. // OC_LTE:
  1809. // a_jmp_unsigned_cmp_3way(list,l,l,nil);
  1810. // else
  1811. // internalerror(2020042224);
  1812. // end;
  1813. // end;
  1814. // cg.a_label(current_asmdata.CurrAsmList,tmpl);
  1815. // ungetcpuregister(list,NR_A);
  1816. // end
  1817. //else
  1818. // internalerror(2020042205);
  1819. end;
  1820. procedure tcgmos6502.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  1821. begin
  1822. internalerror(2020042301);
  1823. end;
  1824. procedure tcgmos6502.a_jmp_name(list : TAsmList;const s : string);
  1825. var
  1826. ai : taicpu;
  1827. begin
  1828. ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s,AT_FUNCTION));
  1829. ai.is_jmp:=true;
  1830. list.concat(ai);
  1831. end;
  1832. procedure tcgmos6502.a_jmp_always(list : TAsmList;l: tasmlabel);
  1833. var
  1834. ai : taicpu;
  1835. begin
  1836. ai:=taicpu.op_sym(A_JMP,l);
  1837. ai.is_jmp:=true;
  1838. list.concat(ai);
  1839. end;
  1840. procedure tcgmos6502.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  1841. var
  1842. ai : taicpu;
  1843. begin
  1844. ai:=taicpu.op_cond_sym(A_Bxx,flags_to_cond(f),l);
  1845. ai.is_jmp:=true;
  1846. list.concat(ai);
  1847. end;
  1848. procedure tcgmos6502.a_jmp_unsigned_cmp_3way(list: TAsmList; onbelow, onequal, onabove: tasmlabel);
  1849. var
  1850. skiplabel: TAsmLabel;
  1851. begin
  1852. if (onbelow= nil) and (onequal= nil) and (onabove= nil) then
  1853. {nothing}
  1854. else if (onbelow= nil) and (onequal= nil) and (onabove<>nil) then
  1855. begin
  1856. current_asmdata.getjumplabel(skiplabel);
  1857. a_jmp_flags(list,F_EQ,skiplabel);
  1858. a_jmp_flags(list,F_CS,onabove);
  1859. cg.a_label(list,skiplabel);
  1860. end
  1861. else if (onbelow= nil) and (onequal<>nil) and (onabove= nil) then
  1862. a_jmp_flags(list,F_EQ,onequal)
  1863. else if (onbelow= nil) and (onequal<>nil) and (onabove<>nil) then
  1864. begin
  1865. if onequal<>onabove then
  1866. a_jmp_flags(list,F_EQ,onequal);
  1867. a_jmp_flags(list,F_CS,onabove);
  1868. end
  1869. else if (onbelow<>nil) and (onequal= nil) and (onabove= nil) then
  1870. a_jmp_flags(list,F_CC,onbelow)
  1871. else if (onbelow<>nil) and (onequal= nil) and (onabove<>nil) then
  1872. begin
  1873. if onbelow<>onabove then
  1874. a_jmp_flags(list,F_CC,onbelow);
  1875. a_jmp_flags(list,F_NE,onabove);
  1876. end
  1877. else if (onbelow<>nil) and (onequal<>nil) and (onabove= nil) then
  1878. begin
  1879. a_jmp_flags(list,F_CC,onbelow);
  1880. a_jmp_flags(list,F_EQ,onequal);
  1881. end
  1882. else if (onbelow<>nil) and (onequal<>nil) and (onabove<>nil) then
  1883. begin
  1884. if (onbelow=onequal) and (onequal=onabove) then
  1885. a_jmp_always(list,onbelow)
  1886. else if onequal=onabove then
  1887. begin
  1888. a_jmp_flags(list,F_CC,onbelow);
  1889. a_jmp_always(list,onabove);
  1890. end
  1891. else if onbelow=onequal then
  1892. begin
  1893. a_jmp_flags(list,F_CC,onbelow);
  1894. a_jmp_flags(list,F_EQ,onequal);
  1895. a_jmp_always(list,onabove);
  1896. end
  1897. else if onbelow=onabove then
  1898. begin
  1899. a_jmp_flags(list,F_EQ,onequal);
  1900. a_jmp_always(list,onabove);
  1901. end
  1902. else
  1903. begin
  1904. { the generic case - all 3 are different labels }
  1905. a_jmp_flags(list,F_CC,onbelow);
  1906. a_jmp_flags(list,F_EQ,onequal);
  1907. a_jmp_always(list,onabove);
  1908. end;
  1909. end
  1910. else
  1911. begin
  1912. { Shouldn't happen! All possible combinations are handled by the above code. }
  1913. internalerror(2020042201);
  1914. end;
  1915. end;
  1916. procedure tcgmos6502.a_jmp_signed_cmp_3way(list: TAsmList; onless, onequal, ongreater: tasmlabel);
  1917. var
  1918. skiplabel: TAsmLabel;
  1919. begin
  1920. if (onless= nil) and (onequal= nil) and (ongreater= nil) then
  1921. {nothing}
  1922. else if (onless= nil) and (onequal= nil) and (ongreater<>nil) then
  1923. begin
  1924. current_asmdata.getjumplabel(skiplabel);
  1925. a_jmp_flags(list,F_EQ,skiplabel);
  1926. a_jmp_flags(list,F_PL,ongreater);
  1927. cg.a_label(list,skiplabel);
  1928. end
  1929. else if (onless= nil) and (onequal<>nil) and (ongreater= nil) then
  1930. a_jmp_flags(list,F_EQ,onequal)
  1931. else if (onless= nil) and (onequal<>nil) and (ongreater<>nil) then
  1932. begin
  1933. if onequal<>ongreater then
  1934. a_jmp_flags(list,F_EQ,onequal);
  1935. a_jmp_flags(list,F_PL,ongreater);
  1936. end
  1937. else if (onless<>nil) and (onequal= nil) and (ongreater= nil) then
  1938. a_jmp_flags(list,F_MI,onless)
  1939. else if (onless<>nil) and (onequal= nil) and (ongreater<>nil) then
  1940. begin
  1941. if onless<>ongreater then
  1942. a_jmp_flags(list,F_MI,onless);
  1943. a_jmp_flags(list,F_NE,ongreater);
  1944. end
  1945. else if (onless<>nil) and (onequal<>nil) and (ongreater= nil) then
  1946. begin
  1947. a_jmp_flags(list,F_MI,onless);
  1948. a_jmp_flags(list,F_EQ,onequal);
  1949. end
  1950. else if (onless<>nil) and (onequal<>nil) and (ongreater<>nil) then
  1951. begin
  1952. if (onless=onequal) and (onequal=ongreater) then
  1953. a_jmp_always(list,onless)
  1954. else if onequal=ongreater then
  1955. begin
  1956. a_jmp_flags(list,F_MI,onless);
  1957. a_jmp_always(list,ongreater);
  1958. end
  1959. else if onless=onequal then
  1960. begin
  1961. a_jmp_flags(list,F_MI,onless);
  1962. a_jmp_flags(list,F_EQ,onequal);
  1963. a_jmp_always(list,ongreater);
  1964. end
  1965. else if onless=ongreater then
  1966. begin
  1967. a_jmp_flags(list,F_EQ,onequal);
  1968. a_jmp_always(list,ongreater);
  1969. end
  1970. else
  1971. begin
  1972. { the generic case - all 3 are different labels }
  1973. a_jmp_flags(list,F_MI,onless);
  1974. a_jmp_flags(list,F_EQ,onequal);
  1975. a_jmp_always(list,ongreater);
  1976. end;
  1977. end
  1978. else
  1979. begin
  1980. { Shouldn't happen! All possible combinations are handled by the above code. }
  1981. internalerror(2020042204);
  1982. end;
  1983. end;
  1984. procedure tcgmos6502.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  1985. //var
  1986. // l : TAsmLabel;
  1987. // tmpflags : TResFlags;
  1988. begin
  1989. //if f in [F_C,F_NC] then
  1990. // begin
  1991. // a_load_const_reg(list,size,0,reg);
  1992. // if f=F_NC then
  1993. // list.concat(taicpu.op_none(A_CCF));
  1994. // list.concat(taicpu.op_reg(A_RL,reg));
  1995. // end
  1996. //else
  1997. // begin
  1998. // current_asmdata.getjumplabel(l);
  1999. // a_load_const_reg(list,size,0,reg);
  2000. // tmpflags:=f;
  2001. // inverse_flags(tmpflags);
  2002. // a_jmp_flags(list,tmpflags,l);
  2003. // list.concat(taicpu.op_reg(A_INC,reg));
  2004. // cg.a_label(list,l);
  2005. // end;
  2006. end;
  2007. procedure tcgmos6502.g_stackpointer_alloc(list: TAsmList; localsize: longint);
  2008. begin
  2009. //if localsize>0 then
  2010. // begin
  2011. // list.Concat(taicpu.op_reg_const(A_LD,NR_HL,-localsize));
  2012. // list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  2013. // list.Concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  2014. // end;
  2015. end;
  2016. //procedure tcgmos6502.a_adjust_sp(list : TAsmList; value : longint);
  2017. // var
  2018. // i : integer;
  2019. // sym: TAsmSymbol;
  2020. // ref: treference;
  2021. // begin
  2022. // case value of
  2023. // 0:
  2024. // ;
  2025. // -7..-1:
  2026. // begin
  2027. // for i:=value to -1 do
  2028. // list.concat(taicpu.op_reg(A_DEC,NR_SP));
  2029. // end;
  2030. // 1..7:
  2031. // begin
  2032. // for i:=1 to value do
  2033. // list.concat(taicpu.op_reg(A_INC,NR_SP));
  2034. // end;
  2035. // else
  2036. // begin
  2037. // sym:=current_asmdata.RefAsmSymbol('FPC_Z80_SAVE_HL',AT_DATA);
  2038. // reference_reset_symbol(ref,sym,0,1,[]);
  2039. //
  2040. // // block interrupts
  2041. // list.concat(taicpu.op_none(A_DI));
  2042. //
  2043. // // save HL
  2044. // list.concat(taicpu.op_ref_reg(A_LD,ref,NR_HL));
  2045. //
  2046. // // adjust SP
  2047. // list.concat(taicpu.op_reg_const(A_LD,NR_HL,value));
  2048. // list.concat(taicpu.op_reg_reg(A_ADD,NR_HL,NR_SP));
  2049. // list.concat(taicpu.op_reg_reg(A_LD,NR_SP,NR_HL));
  2050. //
  2051. // // restore HL
  2052. // list.concat(taicpu.op_reg_ref(A_LD,NR_HL,ref));
  2053. //
  2054. // // release interrupts
  2055. // list.concat(taicpu.op_none(A_EI));
  2056. // end;
  2057. // end;
  2058. // end;
  2059. procedure tcgmos6502.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  2060. //var
  2061. // regsize,stackmisalignment: longint;
  2062. begin
  2063. //regsize:=0;
  2064. //stackmisalignment:=0;
  2065. //{ save old framepointer }
  2066. //if not nostackframe then
  2067. // begin
  2068. // { return address }
  2069. // inc(stackmisalignment,2);
  2070. // list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
  2071. // if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
  2072. // begin
  2073. // { push <frame_pointer> }
  2074. // inc(stackmisalignment,2);
  2075. // include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
  2076. // list.concat(Taicpu.op_reg(A_PUSH,NR_FRAME_POINTER_REG));
  2077. // { Return address and FP are both on stack }
  2078. // current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*2);
  2079. // current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*2));
  2080. // if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
  2081. // begin
  2082. // list.concat(Taicpu.op_reg_const(A_LD,NR_FRAME_POINTER_REG,0));
  2083. // list.concat(Taicpu.op_reg_reg(A_ADD,NR_FRAME_POINTER_REG,NR_STACK_POINTER_REG))
  2084. // end
  2085. // else
  2086. // begin
  2087. // internalerror(2020040301);
  2088. // (*push_regs;
  2089. // gen_load_frame_for_exceptfilter(list);
  2090. // { Need only as much stack space as necessary to do the calls.
  2091. // Exception filters don't have own local vars, and temps are 'mapped'
  2092. // to the parent procedure.
  2093. // maxpushedparasize is already aligned at least on x86_64. }
  2094. // localsize:=current_procinfo.maxpushedparasize;*)
  2095. // end;
  2096. // current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
  2097. // end
  2098. // else
  2099. // begin
  2100. // CGmessage(cg_d_stackframe_omited);
  2101. // end;
  2102. //
  2103. // { allocate stackframe space }
  2104. // if (localsize<>0) or
  2105. // ((target_info.stackalign>sizeof(pint)) and
  2106. // (stackmisalignment <> 0) and
  2107. // ((pi_do_call in current_procinfo.flags) or
  2108. // (po_assembler in current_procinfo.procdef.procoptions))) then
  2109. // begin
  2110. // if target_info.stackalign>sizeof(pint) then
  2111. // localsize := align(localsize+stackmisalignment,target_info.stackalign)-stackmisalignment;
  2112. // g_stackpointer_alloc(list,localsize);
  2113. // if current_procinfo.framepointer=NR_STACK_POINTER_REG then
  2114. // current_asmdata.asmcfi.cfa_def_cfa_offset(list,regsize+localsize+sizeof(pint));
  2115. // current_procinfo.final_localsize:=localsize;
  2116. // end
  2117. // end;
  2118. end;
  2119. procedure tcgmos6502.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  2120. //var
  2121. // regs : tcpuregisterset;
  2122. // reg : TSuperRegister;
  2123. // LocalSize : longint;
  2124. // stacksize : longint;
  2125. begin
  2126. //{ every byte counts for Z80, so if a subroutine is marked as non-returning, we do
  2127. // not generate any exit code, so we really trust the noreturn directive
  2128. //}
  2129. //if po_noreturn in current_procinfo.procdef.procoptions then
  2130. // exit;
  2131. //
  2132. //{ remove stackframe }
  2133. //if not nostackframe then
  2134. // begin
  2135. // stacksize:=current_procinfo.calc_stackframe_size;
  2136. // if (target_info.stackalign>4) and
  2137. // ((stacksize <> 0) or
  2138. // (pi_do_call in current_procinfo.flags) or
  2139. // { can't detect if a call in this case -> use nostackframe }
  2140. // { if you (think you) know what you are doing }
  2141. // (po_assembler in current_procinfo.procdef.procoptions)) then
  2142. // stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  2143. // if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  2144. // begin
  2145. // if stacksize<>0 then
  2146. // a_adjust_sp(list,stacksize);
  2147. // end
  2148. // else
  2149. // begin
  2150. // list.Concat(taicpu.op_reg_reg(A_LD,NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG));
  2151. // list.Concat(taicpu.op_reg(A_POP,NR_FRAME_POINTER_REG));
  2152. // end;
  2153. // list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  2154. // end;
  2155. list.concat(taicpu.op_none(A_RTS));
  2156. end;
  2157. procedure tcgmos6502.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  2158. //var
  2159. // tmpref : treference;
  2160. begin
  2161. //if assigned(ref.symbol) then
  2162. // begin
  2163. // reference_reset(tmpref,0,[]);
  2164. // tmpref.symbol:=ref.symbol;
  2165. // tmpref.offset:=ref.offset;
  2166. //
  2167. // tmpref.refaddr:=addr_lo8;
  2168. // list.concat(taicpu.op_reg_ref(A_LD,r,tmpref));
  2169. //
  2170. // tmpref.refaddr:=addr_hi8;
  2171. // list.concat(taicpu.op_reg_ref(A_LD,GetNextReg(r),tmpref));
  2172. //
  2173. // if (ref.base<>NR_NO) then
  2174. // a_op_reg_reg(list,OP_ADD,OS_16,ref.base,r);
  2175. // if (ref.index<>NR_NO) then
  2176. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2177. // end
  2178. //else if ref.base=NR_IX then
  2179. // begin
  2180. // list.concat(taicpu.op_reg(A_PUSH,NR_IX));
  2181. // getcpuregister(list,NR_H);
  2182. // getcpuregister(list,NR_L);
  2183. // list.concat(taicpu.op_reg(A_POP,NR_HL));
  2184. // emit_mov(list,r,NR_L);
  2185. // ungetcpuregister(list,NR_L);
  2186. // emit_mov(list,GetNextReg(r),NR_H);
  2187. // ungetcpuregister(list,NR_H);
  2188. // if (ref.index<>NR_NO) then
  2189. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2190. // if ref.offset<>0 then
  2191. // a_op_const_reg(list,OP_ADD,OS_16,ref.offset,r);
  2192. // end
  2193. //else if (ref.base=NR_SP) or (ref.base=NR_BC) or (ref.base=NR_DE) then
  2194. // begin
  2195. // getcpuregister(list,NR_H);
  2196. // getcpuregister(list,NR_L);
  2197. // list.Concat(taicpu.op_reg_const(A_LD,NR_HL,ref.offset));
  2198. // list.Concat(taicpu.op_reg_reg(A_ADD,NR_HL,ref.base));
  2199. // emit_mov(list,r,NR_L);
  2200. // ungetcpuregister(list,NR_L);
  2201. // emit_mov(list,GetNextReg(r),NR_H);
  2202. // ungetcpuregister(list,NR_H);
  2203. // if (ref.index<>NR_NO) then
  2204. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2205. // end
  2206. //else if ref.base<>NR_NO then
  2207. // begin
  2208. // a_op_const_reg_reg(list,OP_ADD,OS_16,ref.offset,ref.base,r);
  2209. // if (ref.index<>NR_NO) then
  2210. // a_op_reg_reg(list,OP_ADD,OS_16,ref.index,r);
  2211. // end
  2212. //else if ref.index<>NR_NO then
  2213. // a_op_const_reg_reg(list,OP_ADD,OS_16,ref.offset,ref.index,r)
  2214. //else
  2215. // a_load_const_reg(list,OS_16,ref.offset,r);
  2216. end;
  2217. procedure tcgmos6502.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
  2218. //var
  2219. // tmpreg,srcreg,dstreg: tregister;
  2220. // srcref,dstref : treference;
  2221. // i: Integer;
  2222. begin
  2223. //if (len<=2) and
  2224. // is_ref_in_opertypes(source,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) and
  2225. // is_ref_in_opertypes(dest,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
  2226. // begin
  2227. // srcref:=source;
  2228. // dstref:=dest;
  2229. // tmpreg:=getintregister(list,OS_8);
  2230. // for i:=1 to len do
  2231. // begin
  2232. // list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  2233. // list.concat(taicpu.op_ref_reg(A_LD,dstref,tmpreg));
  2234. // if i<>len then
  2235. // begin
  2236. // adjust_normalized_ref(list,srcref,1);
  2237. // adjust_normalized_ref(list,dstref,1);
  2238. // end;
  2239. // end;
  2240. // end
  2241. //else
  2242. // begin
  2243. // srcreg:=getintregister(list,OS_16);
  2244. // a_loadaddr_ref_reg(list,source,srcreg);
  2245. // dstreg:=getintregister(list,OS_16);
  2246. // a_loadaddr_ref_reg(list,dest,dstreg);
  2247. // getcpuregister(list,NR_L);
  2248. // a_load_reg_reg(list,OS_8,OS_8,srcreg,NR_L);
  2249. // getcpuregister(list,NR_H);
  2250. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(srcreg),NR_H);
  2251. // getcpuregister(list,NR_E);
  2252. // a_load_reg_reg(list,OS_8,OS_8,dstreg,NR_E);
  2253. // getcpuregister(list,NR_D);
  2254. // a_load_reg_reg(list,OS_8,OS_8,GetNextReg(dstreg),NR_D);
  2255. // getcpuregister(list,NR_B);
  2256. // getcpuregister(list,NR_C);
  2257. // list.concat(taicpu.op_reg_const(A_LD,NR_BC,len));
  2258. // list.concat(taicpu.op_none(A_LDIR));
  2259. // ungetcpuregister(list,NR_B);
  2260. // ungetcpuregister(list,NR_C);
  2261. // ungetcpuregister(list,NR_D);
  2262. // ungetcpuregister(list,NR_E);
  2263. // ungetcpuregister(list,NR_H);
  2264. // ungetcpuregister(list,NR_L);
  2265. // end;
  2266. end;
  2267. procedure tcgmos6502.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
  2268. var
  2269. hl : tasmlabel;
  2270. ai : taicpu;
  2271. cond : TAsmCond;
  2272. begin
  2273. list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: g_overflowCheck')));
  2274. //if not(cs_check_overflow in current_settings.localswitches) then
  2275. // exit;
  2276. //current_asmdata.getjumplabel(hl);
  2277. //if not ((def.typ=pointerdef) or
  2278. // ((def.typ=orddef) and
  2279. // (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  2280. // pasbool8,pasbool16,pasbool32,pasbool64]))) then
  2281. // cond:=C_VC
  2282. //else
  2283. // cond:=C_CC;
  2284. //ai:=Taicpu.Op_Sym(A_BRxx,hl);
  2285. //ai.SetCondition(cond);
  2286. //ai.is_jmp:=true;
  2287. //list.concat(ai);
  2288. //
  2289. //a_call_name(list,'FPC_OVERFLOW',false);
  2290. //a_label(list,hl);
  2291. end;
  2292. procedure tcgmos6502.g_save_registers(list: TAsmList);
  2293. begin
  2294. { this is done by the entry code }
  2295. end;
  2296. procedure tcgmos6502.g_restore_registers(list: TAsmList);
  2297. begin
  2298. { this is done by the exit code }
  2299. end;
  2300. procedure tcgmos6502.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  2301. begin
  2302. //case cond of
  2303. // OC_EQ:
  2304. // a_jmp_unsigned_cmp_3way(list,nil,l,nil);
  2305. // OC_NE:
  2306. // a_jmp_unsigned_cmp_3way(list,l,nil,l);
  2307. // OC_A:
  2308. // a_jmp_unsigned_cmp_3way(list,nil,nil,l);
  2309. // OC_B:
  2310. // a_jmp_unsigned_cmp_3way(list,l,nil,nil);
  2311. // OC_AE:
  2312. // a_jmp_unsigned_cmp_3way(list,nil,l,l);
  2313. // OC_BE:
  2314. // a_jmp_unsigned_cmp_3way(list,l,l,nil);
  2315. // OC_GT:
  2316. // a_jmp_signed_cmp_3way(list,nil,nil,l);
  2317. // OC_LT:
  2318. // a_jmp_signed_cmp_3way(list,l,nil,nil);
  2319. // OC_GTE:
  2320. // a_jmp_signed_cmp_3way(list,nil,l,l);
  2321. // OC_LTE:
  2322. // a_jmp_signed_cmp_3way(list,l,l,nil);
  2323. // else
  2324. // internalerror(2011082501);
  2325. //end;
  2326. end;
  2327. procedure tcgmos6502.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  2328. //var
  2329. // instr: taicpu;
  2330. begin
  2331. if reg1=reg2 then
  2332. exit;
  2333. if reg1=NR_A then
  2334. begin
  2335. if reg2=NR_X then
  2336. list.Concat(taicpu.op_none(A_TAX))
  2337. else if reg2=NR_Y then
  2338. list.Concat(taicpu.op_none(A_TAY))
  2339. else
  2340. list.Concat(taicpu.op_reg(A_STA,reg2));
  2341. end
  2342. else if reg1=NR_X then
  2343. begin
  2344. if reg2=NR_A then
  2345. list.Concat(taicpu.op_none(A_TXA))
  2346. else if reg2=NR_Y then
  2347. begin
  2348. getcpuregister(list,NR_A);
  2349. list.Concat(taicpu.op_none(A_TXA));
  2350. list.Concat(taicpu.op_none(A_TAY));
  2351. ungetcpuregister(list,NR_A);
  2352. end
  2353. else
  2354. list.Concat(taicpu.op_reg(A_STX,reg2));
  2355. end
  2356. else if reg1=NR_Y then
  2357. begin
  2358. if reg2=NR_A then
  2359. list.Concat(taicpu.op_none(A_TYA))
  2360. else if reg2=NR_Y then
  2361. begin
  2362. getcpuregister(list,NR_A);
  2363. list.Concat(taicpu.op_none(A_TYA));
  2364. list.Concat(taicpu.op_none(A_TAX));
  2365. ungetcpuregister(list,NR_A);
  2366. end
  2367. else
  2368. list.Concat(taicpu.op_reg(A_STY,reg2));
  2369. end
  2370. else if reg2=NR_A then
  2371. list.Concat(taicpu.op_reg(A_LDA,reg1))
  2372. else if reg2=NR_X then
  2373. list.Concat(taicpu.op_reg(A_LDX,reg1))
  2374. else if reg2=NR_Y then
  2375. list.Concat(taicpu.op_reg(A_LDY,reg1))
  2376. else
  2377. begin
  2378. getcpuregister(list,NR_A);
  2379. list.Concat(taicpu.op_reg(A_LDA,reg1));
  2380. list.Concat(taicpu.op_reg(A_STA,reg2));
  2381. ungetcpuregister(list,NR_A);
  2382. end;
  2383. //instr:=taicpu.op_reg_reg(A_LD,reg2,reg1);
  2384. //list.Concat(instr);
  2385. { Notify the register allocator that we have written a move instruction so
  2386. it can try to eliminate it. }
  2387. //add_move_instruction(instr);
  2388. end;
  2389. procedure tcg64fmos6502.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2390. begin
  2391. 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))));
  2392. if not(size in [OS_S64,OS_64]) then
  2393. internalerror(2012102402);
  2394. tcgmos6502(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
  2395. end;
  2396. procedure tcg64fmos6502.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2397. begin
  2398. 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))));
  2399. tcgmos6502(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
  2400. end;
  2401. procedure create_codegen;
  2402. begin
  2403. cg:=tcgmos6502.create;
  2404. cg64:=tcg64fmos6502.create;
  2405. end;
  2406. end.