cgcpu.pas 99 KB

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