cgcpu.pas 106 KB

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