[ucsim] Update email and file info, fix stm8 flash controller
[sdcc.git] / sdcc / sim / ucsim / src / sims / mos6502.src / mos65c02.cc
blobd69a9c81b29a78ab5979bb9fa3772051e0d099f3
1 /*
2 * Simulator of microcontrollers (mos65c02.cc)
4 * Copyright (C) 2020 Drotos Daniel
5 *
6 * To contact author send email to dr.dkdb@gmail.com
8 */
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
28 #include <stdlib.h>
29 #include <ctype.h>
31 #include "glob.h"
33 #include "mos65c02cl.h"
36 cl_mos65c02::cl_mos65c02(class cl_sim *asim):
37 cl_mos6502(asim)
39 *my_id= "MOS65C02";
42 int
43 cl_mos65c02::init(void)
45 int i;
46 cl_mos6502::init();
47 // Map all 0x_3 into NOP 1,1
48 for (i=0x13; i<=0xf3; i+= 0x10)
49 itab[i]= instruction_wrapper_03;
50 // Map all 0x_b into NOP 1,1
51 for (i=0x0b; i<=0xfb; i+= 0x10)
52 itab[i]= instruction_wrapper_03;
53 return 0;
56 void
57 cl_mos65c02::reset(void)
59 cl_mos6502::reset();
60 CC&= ~flagD;
63 struct dis_entry *
64 cl_mos65c02::get_dis_entry(t_addr addr)
66 struct dis_entry *de= cl_mos6502::get_dis_entry(addr);
67 if (de != NULL)
68 return de;
70 t_mem code= rom->get(addr);
71 for (de = disass_mos65c02; de && de->mnemonic; de++)
73 if ((code & de->mask) == de->code)
74 return de;
76 return NULL;
79 int
80 cl_mos65c02::inst_length(t_addr addr)
82 struct dis_entry *de= get_dis_entry(addr);
83 if (!de)
84 return 1;
85 return (de->mnemonic)?(de->length):1;
89 int
90 cl_mos65c02::accept_it(class it_level *il)
92 class cl_it_src *is= il->source;
94 tick(2);
95 push_addr(PC);
96 rom->write(0x0100 + rSP, rF|0x20);
97 if (set_b)
98 rF&= ~flagB;
99 // All interrupts (incl BRK) clear D flag
100 rF&= ~flagD;
101 cSP.W(rSP-1);
102 tick(1);
103 vc.wr++;
105 t_addr a= read_addr(rom, is->addr);
106 tick(2);
107 vc.rd+= 2;
108 PC= a;
110 rF|= flagI;
111 is->clear();
112 it_levels->push(il);
114 return resGO;
119 cl_mos65c02::nopft(int nuof_fetches, int nuof_ticks)
121 while (nuof_fetches--)
122 fetch();
123 if (nuof_ticks) tick(nuof_ticks);
124 return resGO;
128 cl_mos65c02::BIT8(t_mem code)
130 u8_t v= fetch();
131 u8_t f= rF & ~(flagZ);
132 if (!(rA & v)) f|= flagZ;
133 cF.W(f);
134 return resGO;
138 cl_mos65c02::DEA(t_mem code)
140 cA.W(rA-1);
141 rF&= ~(flagZ|flagS);
142 if (!rA) rF|= flagZ;
143 if (rA & 0x80) rF|= flagS;
144 cF.W(rF);
145 tick(1);
146 return resGO;
150 cl_mos65c02::INA(t_mem code)
152 cA.W(rA+1);
153 rF&= ~(flagZ|flagS);
154 if (!rA) rF|= flagZ;
155 if (rA & 0x80) rF|= flagS;
156 cF.W(rF);
157 tick(1);
158 return resGO;
162 cl_mos65c02::JMP7c(t_mem code)
164 u16_t a1= i16();
165 u16_t a2= a1 + rX;
166 u16_t a= read_addr(rom, a2);
167 PC= a;
168 tick(5);
169 return resGO;
173 cl_mos65c02::tsb(class cl_cell8 &op)
175 u8_t o= op.R();
176 u8_t r1= o & rA, r2= o | rA;
177 u8_t f= rF & ~flagZ;
178 if (!r1) f|= flagZ;
179 op.W(r2);
180 cF.W(f);
181 tick(2);
182 return resGO;
186 cl_mos65c02::trb(class cl_cell8 &op)
188 u8_t o= op.R();
189 u8_t r1= o & rA, r2= o & ~rA;
190 u8_t f= rF & ~flagZ;
191 if (!r1) f|= flagZ;
192 op.W(r2);
193 cF.W(f);
194 tick(2);
195 return resGO;
199 cl_mos65c02::stz(class cl_cell8 &op)
201 op.W(0);
202 return resGO;
206 cl_mos65c02::PHY(t_mem code)
208 rom->write(0x0100 + rSP, rY);
209 vc.wr++;
210 t_addr spbef= rSP;
211 cSP.W(rSP-1);
212 class cl_stack_push *op= new cl_stack_push(instPC, rY, spbef, rSP);
213 op->init();
214 stack_write(op);
215 tick(2);
216 return resGO;
220 cl_mos65c02::PLY(t_mem code)
222 t_addr spbef= rSP;
223 cSP.W(rSP+1);
224 cY.W(rom->read(0x0100 + rSP));
225 class cl_stack_pop *op= new cl_stack_pop(instPC, rY, spbef, rSP);
226 op->init();
227 stack_read(op);
228 u8_t f= rF & ~(flagN|flagZ);
229 if (!rY) f|= flagZ;
230 if (rY&0x80) f|= flagN;
231 cF.W(f);
232 vc.rd++;
233 tick(3);
234 return resGO;
238 cl_mos65c02::PHX(t_mem code)
240 rom->write(0x0100 + rSP, rX);
241 vc.wr++;
242 t_addr spbef= rSP;
243 cSP.W(rSP-1);
244 class cl_stack_push *op= new cl_stack_push(instPC, rX, spbef, rSP);
245 op->init();
246 stack_write(op);
247 tick(2);
248 return resGO;
252 cl_mos65c02::PLX(t_mem code)
254 t_addr spbef= rSP;
255 cSP.W(rSP+1);
256 cX.W(rom->read(0x0100 + rSP));
257 class cl_stack_pop *op= new cl_stack_pop(instPC, rX, spbef, rSP);
258 op->init();
259 stack_read(op);
260 u8_t f= rF & ~(flagN|flagZ);
261 if (!rX) f|= flagZ;
262 if (rX&0x80) f|= flagN;
263 cF.W(f);
264 vc.rd++;
265 tick(3);
266 return resGO;
270 /* End of mos6502.src/mos65c02.cc */