2 * Simulator of microcontrollers (i8080.cc)
4 * Copyright (C) 2022 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
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
41 cl_f8::cl_f8(class cl_sim
*asim
):
50 fill_def_wrappers(itab
);
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
);
74 cl_f8::id_string(void)
88 cl_f8::set_PC(t_addr addr
)
95 cl_f8::mk_hw_elements(void)
98 cl_uc::mk_hw_elements();
100 add_hw(h
= new cl_dreg(this, 0, "dreg"));
105 cl_f8::make_cpu_hw(void)
107 cpu
= new cl_f8_cpu(this);
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);
122 address_spaces
->add(as
);
125 ram_chip
= new cl_chip8("ram_chip", 0x2000, 8);
127 memchips
->add(ram_chip
);
128 ad
= new cl_address_decoder(as
= rom
,
129 ram_chip
, 0x2000, 0x3fff, 0);
131 as
->decoders
->add(ad
);
135 prom_chip
= new cl_chip8("prom_chip", 0xc000, 8);
137 memchips
->add(prom_chip
);
138 ad
= new cl_address_decoder(as
= rom
,
139 prom_chip
, 0x4000, 0xffff, 0);
141 as
->decoders
->add(ad
);
143 rom
->set_cell_flag(0x4000, 0xffff, true, CELL_READ_ONLY
);
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
):'.');
164 con
->dd_cprintf("answer", "SP= ");
165 con
->dd_cprintf("dump_address", "0x%04x ->", rSP
);
166 for (i
= 0; i
< 18; i
++)
170 con
->dd_cprintf("dump_number", " %02x",
171 (u8_t
)(rom
->read(al
)));
173 con
->dd_printf("\n");
175 print_disass(PC
, con
);
183 if (v
& 0x80) v
|= 0xff00;
190 t_addr sp_before
= rSP
;
191 rom
->write(--rSP
, v
);
194 stack_write(sp_before
);
198 cl_f8::push2(u16_t v
)
200 t_addr sp_before
= rSP
;
201 rom
->write(--rSP
, v
>>8);
202 rom
->write(--rSP
, v
);
205 stack_write(sp_before
);
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
);
216 stack_write(sp_before
);
222 u8_t v
= rom
->read(rSP
++);
240 cl_f8::stack_check_overflow(t_addr sp_before
)
244 class cl_error_stack_overflow
*e
=
245 new cl_error_stack_overflow(instPC
, sp_before
, rSP
);
252 // Memory cells according to 8 bit addressing modes
257 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(PC
);
267 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(a
);
276 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(a
);
286 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(a
);
293 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(rY
);
302 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(a
);
309 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(rZ
);
365 cl_f8::a_n_acc16(void)
368 return n
+ acc16
->get();
372 cl_f8::a_nn_acc16(void)
376 return nn
+ acc16
->get();
381 cl_f8::clear_prefixes()
389 cl_f8::exec_inst(void)
396 return resBREAKPOINT
;
397 while (code
== PREF_SWAPOP
|| code
== PREF_ALT1
|| code
== PREF_ALT2
|| code
== PREF_ALT3
|| code
== PREF_ALT4
|| code
== PREF_ALT5
)
401 case PREF_SWAPOP
: // swapop
404 case PREF_ALT1
: // altacc1
407 case PREF_ALT2
: // altacc2
410 case PREF_ALT3
: // altacc3
413 case PREF_ALT4
: // altacc4
416 case PREF_ALT5
: // altacc5
421 return resBREAKPOINT
;
423 prefixes
&= allowed_prefs
[code
]; // drop swap if not allowed!
424 // select accumulators according to prefixes
425 if (prefixes
& P_ALT1
)
430 else if (prefixes
& P_ALT2
)
435 else if (prefixes
& P_ALT3
)
440 else if (prefixes
& P_ALT4
)
445 else if (prefixes
& P_ALT5
)
451 // clear_prefixes() prepares this state
458 if (itab
[code
] == NULL
)
465 res
= itab
[code
](this, code
);
466 if (res
== resNOT_DONE
)
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)
492 uc
->vars
->add(v
= new cl_var("sp_limit", cfg
, f8cpu_sp_limit
,
493 cfg_help(f8cpu_sp_limit
)));
500 cl_f8_cpu::cfg_help(t_addr addr
)
505 return "Stack overflows when SP is below this limit";
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
;
516 switch ((enum f8cpu_confs
)addr
)
520 u
->sp_limit
= *val
& 0xffff;
522 cell
->set(u
->sp_limit
);
524 case f8cpu_nuof
: break;
530 /* End of f8.src/f8.cc */