cgcpu.pas 103 KB

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