cgcpu.pas 95 KB

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