2
0

cgcpu.pas 101 KB

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