[ucsim-f8] Update to latest
[sdcc.git] / sdcc / sim / ucsim / f8.src / f8.cc
blobee0fcce830cbaf118c8b7eadf3626a858146d8d2
1 /*
2 * Simulator of microcontrollers (i8080.cc)
4 * Copyright (C) 2022 Drotos Daniel, Talker Bt.
5 *
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
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 <ctype.h>
30 #include "utils.h"
32 #include "dregcl.h"
34 #include "f8cl.h"
37 /*
38 * CPU
41 cl_f8::cl_f8(class cl_sim *asim):
42 cl_uc(asim)
46 int
47 cl_f8::init(void)
49 cl_uc::init();
50 fill_def_wrappers(itab);
51 //set_xtal(25000000);
53 #define RCV(R) reg_cell_var(&c ## R , &r ## R , "" #R "" , "CPU register " #R "")
54 RCV(X); RCV(XH); RCV(XL);
55 RCV(Y); RCV(YH); RCV(YL);
56 RCV(Z); RCV(ZH); RCV(ZL);
57 RCV(SP);
58 RCV(F);
59 #undef RCV
60 sp_limit= 0;
61 prefixes= P_NONE;
63 cF.W(urnd());
64 cX.W(urnd());
65 cY.W(urnd());
66 cZ.W(urnd());
67 cSP.W(urnd());
69 reset();
70 return 0;
73 const char *
74 cl_f8::id_string(void)
76 return "F8";
79 void
80 cl_f8::reset(void)
82 cl_uc::reset();
83 clear_prefixes();
84 PC= 0x4000;
87 void
88 cl_f8::set_PC(t_addr addr)
90 PC= addr&0xffff;
94 void
95 cl_f8::mk_hw_elements(void)
97 class cl_hw *h;
98 cl_uc::mk_hw_elements();
100 add_hw(h= new cl_dreg(this, 0, "dreg"));
101 h->init();
104 void
105 cl_f8::make_cpu_hw(void)
107 cpu= new cl_f8_cpu(this);
108 add_hw(cpu);
109 cpu->init();
112 void
113 cl_f8::make_memories(void)
115 class cl_address_space *as;
116 class cl_address_decoder *ad;
117 class cl_memory_chip *ram_chip, *prom_chip;
119 // Flat address space
120 rom= as= new cl_address_space("rom", 0, 0x10000, 8);
121 as->init();
122 address_spaces->add(as);
124 // RAM
125 ram_chip= new cl_chip8("ram_chip", 0x2000, 8);
126 ram_chip->init();
127 memchips->add(ram_chip);
128 ad= new cl_address_decoder(as= rom,
129 ram_chip, 0x2000, 0x3fff, 0);
130 ad->init();
131 as->decoders->add(ad);
132 ad->activate(0);
134 // PROM
135 prom_chip= new cl_chip8("prom_chip", 0xc000, 8);
136 prom_chip->init();
137 memchips->add(prom_chip);
138 ad= new cl_address_decoder(as= rom,
139 prom_chip, 0x4000, 0xffff, 0);
140 ad->init();
141 as->decoders->add(ad);
142 ad->activate(0);
143 rom->set_cell_flag(0x4000, 0xffff, true, CELL_READ_ONLY);
147 void
148 cl_f8::print_regs(class cl_console_base *con)
150 con->dd_color("answer");
151 con->dd_printf("---HCNZO Flags= 0x%02x\n", rF);
152 con->dd_printf("%s\n", cbin(rF, 8).c_str());
153 con->dd_printf("X= 0x%04x [X]= 0x%02x %3d %c\n",
154 rX, rom->get(rX), rom->get(rX),
155 isprint(rom->get(rX))?rom->get(rX):'.');
156 con->dd_printf("Y= 0x%04x [Y]= 0x%02x %3d %c\n",
157 rY, rom->get(rY), rom->get(rY),
158 isprint(rom->get(rY))?rom->get(rY):'.');
159 con->dd_printf("Z= 0x%04x [Z]= 0x%02x %3d %c\n",
160 rZ, rom->get(rZ), rom->get(rZ),
161 isprint(rom->get(rZ))?rom->get(rZ):'.');
163 int i;
164 con->dd_cprintf("answer", "SP= ");
165 con->dd_cprintf("dump_address", "0x%04x ->", rSP);
166 for (i= 0; i < 18; i++)
168 t_addr al;
169 al= (rSP+i)&0xffff;
170 con->dd_cprintf("dump_number", " %02x",
171 (u8_t)(rom->read(al)));
173 con->dd_printf("\n");
175 print_disass(PC, con);
179 i16_t
180 cl_f8::sexd(void)
182 i16_t v= fetch();
183 if (v & 0x80) v|= 0xff00;
184 return v;
187 void
188 cl_f8::push1(u8_t v)
190 t_addr sp_before= rSP;
191 rom->write(--rSP, v);
192 cSP.W(rSP);
193 vc.wr++;
194 stack_write(sp_before);
197 void
198 cl_f8::push2(u16_t v)
200 t_addr sp_before= rSP;
201 rom->write(--rSP, v>>8);
202 rom->write(--rSP, v);
203 vc.wr+= 2;
204 cSP.W(rSP);
205 stack_write(sp_before);
208 void
209 cl_f8::push2(u8_t h, u8_t l)
211 t_addr sp_before= rSP;
212 rom->write(--rSP, h);
213 rom->write(--rSP, l);
214 vc.wr+= 2;
215 cSP.W(rSP);
216 stack_write(sp_before);
219 u8_t
220 cl_f8::pop1(void)
222 u8_t v= rom->read(rSP++);
223 cSP.W(rSP);
224 vc.rd++;
225 return v;
228 u16_t
229 cl_f8::pop2(void)
231 u8_t h, l;
232 l= rom->read(rSP++);
233 h= rom->read(rSP++);
234 cSP.W(rSP);
235 vc.rd+= 2;
236 return h*256+l;
239 void
240 cl_f8::stack_check_overflow(t_addr sp_before)
242 if (rSP < sp_limit)
244 class cl_error_stack_overflow *e=
245 new cl_error_stack_overflow(instPC, sp_before, rSP);
246 e->init();
247 error(e);
252 // Memory cells according to 8 bit addressing modes
254 class cl_cell8 &
255 cl_f8::m_i(void)
257 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(PC);
258 fetch();
259 return *c;
262 class cl_cell8 &
263 cl_f8::m_mm(void)
265 u16_t a= fetch();
266 a+= fetch()*256;
267 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(a);
268 return *c;
271 class cl_cell8 &
272 cl_f8::m_n_sp(void)
274 u8_t n= fetch();
275 u16_t a= rSP+n;
276 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(a);
277 return *c;
280 class cl_cell8 &
281 cl_f8::m_nn_z(void)
283 u16_t nn= fetch();
284 nn+= fetch()*256;
285 u16_t a= nn+rZ;
286 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(a);
287 return *c;
290 class cl_cell8 &
291 cl_f8::m_y(void)
293 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(rY);
294 return *c;
297 class cl_cell8 &
298 cl_f8::m_n_y(void)
300 i8_t n= fetch();
301 u16_t a= rY+n;
302 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(a);
303 return *c;
306 class cl_cell8 &
307 cl_f8::m_z(void)
309 class cl_cell8 *c= (class cl_cell8 *)rom->get_cell(rZ);
310 return *c;
313 u16_t
314 cl_f8::a_i()
316 u16_t a= PC;
317 fetch();
318 fetch();
319 return a;
322 u16_t
323 cl_f8::a_mm(void)
325 u16_t a= fetch();
326 a+= fetch()*256;
327 return a;
330 u16_t
331 cl_f8::a_n_sp(void)
333 u8_t n= fetch();
334 return n + rSP;
337 u16_t
338 cl_f8::a_nn_z(void)
340 u16_t nn= fetch();
341 nn+= fetch()*256;
342 return nn + rZ;
345 u16_t
346 cl_f8::a_y(void)
348 return rY;
351 u16_t
352 cl_f8::a_n_y(void)
354 u8_t n= fetch();
355 return n + rY;
358 u16_t
359 cl_f8::a_acc16(void)
361 return acc16->get();
364 u16_t
365 cl_f8::a_n_acc16(void)
367 u8_t n= fetch();
368 return n + acc16->get();
371 u16_t
372 cl_f8::a_nn_acc16(void)
374 u16_t nn= fetch();
375 nn+= fetch()*256;
376 return nn + acc16->get();
380 void
381 cl_f8::clear_prefixes()
383 prefixes= P_NONE;
384 acc8= &cXL;
385 acc16= &cY;
389 cl_f8::exec_inst(void)
391 int res= resGO;
392 t_mem code;
394 instPC= PC;
395 if (fetch(&code))
396 return resBREAKPOINT;
397 while (code == PREF_SWAPOP || code == PREF_ALT1 || code == PREF_ALT2 || code == PREF_ALT3 || code == PREF_ALT4 || code == PREF_ALT5)
399 switch (code)
401 case PREF_SWAPOP: // swapop
402 prefixes|= P_SWAP;
403 break;
404 case PREF_ALT1: // altacc1
405 prefixes|= P_ALT1;
406 break;
407 case PREF_ALT2: // altacc2
408 prefixes|= P_ALT2;
409 break;
410 case PREF_ALT3: // altacc3
411 prefixes|= P_ALT3;
412 break;
413 case PREF_ALT4: // altacc4
414 prefixes|= P_ALT4;
415 break;
416 case PREF_ALT5: // altacc5
417 prefixes|= P_ALT5;
418 break;
420 if (fetch(&code))
421 return resBREAKPOINT;
423 prefixes&= allowed_prefs[code]; // drop swap if not allowed!
424 // select accumulators according to prefixes
425 if (prefixes & P_ALT1)
427 acc8 = &cXH;
428 acc16= &cY;
430 else if (prefixes & P_ALT2)
432 acc8 = &cYL;
433 acc16= &cZ;
435 else if (prefixes & P_ALT3)
437 acc8 = &cZL;
438 acc16= &cX;
440 else if (prefixes & P_ALT4)
442 acc8 = &cYH;
443 acc16= &cZ;
445 else if (prefixes & P_ALT5)
447 acc8 = &cZH;
448 acc16= &cY;
451 // clear_prefixes() prepares this state
452 else
454 acc8 = &cXL;
455 acc16= &cY;
458 if (itab[code] == NULL)
460 PC= instPC;
461 clear_prefixes();
462 return resNOT_DONE;
464 tick(1);
465 res= itab[code](this, code);
466 if (res == resNOT_DONE)
468 //PC= instPC;
469 clear_prefixes();
470 return res;
472 clear_prefixes();
473 return res;
478 * CPU hw
481 cl_f8_cpu::cl_f8_cpu(class cl_uc *auc):
482 cl_hw(auc, HW_CPU, 0, "cpu")
487 cl_f8_cpu::init(void)
489 cl_hw::init();
491 cl_var *v;
492 uc->vars->add(v= new cl_var("sp_limit", cfg, f8cpu_sp_limit,
493 cfg_help(f8cpu_sp_limit)));
494 v->init();
496 return 0;
499 const char *
500 cl_f8_cpu::cfg_help(t_addr addr)
502 switch (addr)
504 case f8cpu_sp_limit:
505 return "Stack overflows when SP is below this limit";
507 return "Not used";
510 t_mem
511 cl_f8_cpu::conf_op(cl_memory_cell *cell, t_addr addr, t_mem *val)
513 class cl_f8 *u= (class cl_f8 *)uc;
514 if (val)
515 cell->set(*val);
516 switch ((enum f8cpu_confs)addr)
518 case f8cpu_sp_limit:
519 if (val)
520 u->sp_limit= *val & 0xffff;
521 else
522 cell->set(u->sp_limit);
523 break;
524 case f8cpu_nuof: break;
526 return cell->get();
530 /* End of f8.src/f8.cc */