2 * Simulator of microcontrollers (gb80.cc)
4 * Copyright (C) 2021 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
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
28 //#include "ddconfig.h"
47 //#define uint32 t_addr
48 //#define uint8 unsigned char
50 /*******************************************************************/
52 cl_gb80::cl_gb80(struct cpu_entry
*Itype
, class cl_sim
*asim
):
60 BIT_ALL
= (BIT_C
|BIT_N
|BIT_A
|BIT_Z
);
70 /*cl_uc*/cl_z80::init(); /* Memories now exist */
79 cl_gb80::id_string(void)
86 cl_gb80::mk_hw_elements(void)
88 cl_uc::mk_hw_elements();
92 cl_gb80::make_memories(void)
94 class cl_memory_chip
*chip
;
95 class cl_address_decoder
*ad
;
96 class cl_address_space
*as
;
98 chip
= new cl_chip8("rom_chip", 0x10000, 8, 0);
102 rom
= new cl_address_space("rom",
103 0,//lr35902_rom_start,
104 0x10000,//lr35902_rom_size,
107 address_spaces
->add(rom
);
109 ad
= new cl_address_decoder(as
= address_space("rom"),
111 0,//lr35902_rom_start,
112 0xffff,//lr35902_rom_size-1,
116 as
->decoders
->add(ad
);
120 rom
->altname
= "xram";
122 regs8
= new cl_address_space("regs8", 0, 16, 8);
124 regs8
->get_cell(0)->decode((t_mem
*)®s
.raf
.A
);
125 regs8
->get_cell(1)->decode((t_mem
*)®s
.raf
.F
);
126 regs8
->get_cell(2)->decode((t_mem
*)®s
.bc
.h
);
127 regs8
->get_cell(3)->decode((t_mem
*)®s
.bc
.l
);
128 regs8
->get_cell(4)->decode((t_mem
*)®s
.de
.h
);
129 regs8
->get_cell(5)->decode((t_mem
*)®s
.de
.l
);
130 regs8
->get_cell(6)->decode((t_mem
*)®s
.hl
.h
);
131 regs8
->get_cell(7)->decode((t_mem
*)®s
.hl
.l
);
133 regs8
->get_cell(8)->decode((t_mem
*)®s
.ralt_af
.aA
);
134 regs8
->get_cell(9)->decode((t_mem
*)®s
.ralt_af
.aF
);
135 regs8
->get_cell(10)->decode((t_mem
*)®s
.a_bc
.h
);
136 regs8
->get_cell(11)->decode((t_mem
*)®s
.a_bc
.l
);
137 regs8
->get_cell(12)->decode((t_mem
*)®s
.a_de
.h
);
138 regs8
->get_cell(13)->decode((t_mem
*)®s
.a_de
.l
);
139 regs8
->get_cell(14)->decode((t_mem
*)®s
.a_hl
.h
);
140 regs8
->get_cell(15)->decode((t_mem
*)®s
.a_hl
.l
);
142 regs16
= new cl_address_space("regs16", 0, 11, 16);
145 regs16
->get_cell(0)->decode((t_mem
*)®s
.AF
);
146 regs16
->get_cell(1)->decode((t_mem
*)®s
.BC
);
147 regs16
->get_cell(2)->decode((t_mem
*)®s
.DE
);
148 regs16
->get_cell(3)->decode((t_mem
*)®s
.HL
);
149 regs16
->get_cell(4)->decode((t_mem
*)®s
.IX
);
150 regs16
->get_cell(5)->decode((t_mem
*)®s
.IY
);
151 regs16
->get_cell(6)->decode((t_mem
*)®s
.SP
);
152 regs16
->get_cell(7)->decode((t_mem
*)®s
.aAF
);
153 regs16
->get_cell(8)->decode((t_mem
*)®s
.aBC
);
154 regs16
->get_cell(9)->decode((t_mem
*)®s
.aDE
);
155 regs16
->get_cell(10)->decode((t_mem
*)®s
.aHL
);
157 address_spaces
->add(regs8
);
158 address_spaces
->add(regs16
);
161 vars
->add(v
= new cl_var("A", regs8
, 0, ""));
163 vars
->add(v
= new cl_var("F", regs8
, 1, ""));
165 vars
->add(v
= new cl_var("B", regs8
, 2, ""));
167 vars
->add(v
= new cl_var("C", regs8
, 3, ""));
169 vars
->add(v
= new cl_var("D", regs8
, 4, ""));
171 vars
->add(v
= new cl_var("E", regs8
, 5, ""));
173 vars
->add(v
= new cl_var("H", regs8
, 6, ""));
175 vars
->add(v
= new cl_var("L", regs8
, 7, ""));
178 vars
->add(v
= new cl_var("AF", regs16
, 0, ""));
180 vars
->add(v
= new cl_var("BC", regs16
, 1, ""));
182 vars
->add(v
= new cl_var("DE", regs16
, 2, ""));
184 vars
->add(v
= new cl_var("HL", regs16
, 3, ""));
186 vars
->add(v
= new cl_var("IX", regs16
, 4, ""));
188 vars
->add(v
= new cl_var("IY", regs16
, 5, ""));
190 vars
->add(v
= new cl_var("SP", regs16
, 6, ""));
195 cl_gb80::store1(u16_t addr
, t_mem val
)
197 rom
->write(addr
, val
);
201 cl_gb80::store2(u16_t addr
, u16_t val
)
203 rom
->write(addr
, val
);
204 rom
->write(addr
+1, val
>>8);
208 cl_gb80::get1(u16_t addr
)
210 return rom
->read(addr
);
214 cl_gb80::get2(u16_t addr
)
216 u8_t l
= rom
->read(addr
);
217 u8_t h
= rom
->read(addr
+1);
223 * Help command interpreter
227 cl_gb80::dis_tbl(void)
234 cl_gb80::inst_length(t_addr addr
)
238 get_disasm_info(addr
, &len
, NULL
, NULL
);
244 cl_gb80::inst_branch(t_addr addr
)
248 get_disasm_info(addr
, NULL
, &b
, NULL
);
254 cl_gb80::longest_inst(void)
261 cl_gb80::get_disasm_info(t_addr addr
,
266 const char *b
= NULL
;
271 int start_addr
= addr
;
272 struct dis_entry
*dis_e
;
274 code
= rom
->get(addr
++);
278 case 0xcb: /* ESC code to lots of op-codes, all 2-byte */
279 code
= rom
->get(addr
++);
281 while ((code
& disass_gb80_cb
[i
].mask
) != disass_gb80_cb
[i
].code
&&
282 disass_gb80_cb
[i
].mnemonic
)
284 dis_e
= &disass_gb80_cb
[i
];
285 b
= disass_gb80_cb
[i
].mnemonic
;
287 len
+= (disass_gb80_cb
[i
].length
+ 1);
292 while ((code
& disass_gb80
[i
].mask
) != disass_gb80
[i
].code
&&
293 disass_gb80
[i
].mnemonic
)
295 dis_e
= &disass_gb80
[i
];
296 b
= disass_gb80
[i
].mnemonic
;
298 len
+= (disass_gb80
[i
].length
);
304 *ret_branch
= dis_e
->branch
;
309 *immed_offset
= immed_n
;
310 else *immed_offset
= (addr
- start_addr
);
323 cl_gb80::disass(t_addr addr
)
328 int immed_offset
= 0;
332 b
= get_disasm_info(addr
, &len
, NULL
, &immed_offset
);
335 return strdup("UNKNOWN/INVALID");
340 if ((*b
== ' ') && first
)
343 while (work
.len() < 6) work
.append(' ');
351 case 'd': // d jump relative target, signed? byte immediate operand
352 temp
.format("#%d", (char)rom
->get(addr
+immed_offset
));
355 case 'w': // w word immediate operand
356 temp
.format("#0x%04x",
357 (uint
)((rom
->get(addr
+immed_offset
)) |
358 (rom
->get(addr
+immed_offset
+1)<<8)) );
362 case 'b': // b byte immediate operand
363 temp
.format("#0x%02x", (uint
)rom
->get(addr
+immed_offset
));
375 return strdup(work
.c_str());
380 cl_gb80::print_regs(class cl_console_base
*con
)
382 con
->dd_color("answer");
383 con
->dd_printf("ZNHC---- Flags= 0x%02x %3d %c ",
384 regs
.raf
.F
, regs
.raf
.F
, isprint(regs
.raf
.F
)?regs
.raf
.F
:'.');
385 con
->dd_printf("A= 0x%02x %3d %c\n",
386 regs
.raf
.A
, regs
.raf
.A
, isprint(regs
.raf
.A
)?regs
.raf
.A
:'.');
387 con
->dd_printf("%s\n", cbin(regs
.raf
.F
,8).c_str());
389 con
->dd_printf("BC= 0x%04x [BC]= %02x %3d %c ",
390 regs
.BC
, get1(regs
.BC
), get1(regs
.BC
),
391 isprint(get1(regs
.BC
))?get1(regs
.BC
):'.');
392 con
->dd_printf("DE= 0x%04x [DE]= %02x %3d %c ",
393 regs
.DE
, get1(regs
.DE
), get1(regs
.DE
),
394 isprint(get1(regs
.DE
))?get1(regs
.DE
):'.');
395 con
->dd_printf("HL= 0x%04x [HL]= %02x %3d %c\n",
396 regs
.HL
, get1(regs
.HL
), get1(regs
.HL
),
397 isprint(get1(regs
.HL
))?get1(regs
.HL
):'.');
398 con
->dd_printf("SP= 0x%04x [SP]= %02x %3d %c\n",
399 regs
.SP
, get1(regs
.SP
), get1(regs
.SP
),
400 isprint(get1(regs
.SP
))?get1(regs
.SP
):'.');
402 print_disass(PC
, con
);
410 cl_gb80::exec_inst(void)
418 return(resBREAKPOINT
);
425 case 0x00: res
= (inst_nop(code
)); break;
427 case 0x02: case 0x06: res
= (inst_ld(code
)); break;
429 case 0x04: res
= (inst_inc(code
)); break;
430 case 0x05: res
= (inst_dec(code
)); break;
432 int ret
= (inst_rlca(code
));
433 regs
.raf
.F
&= ~(BIT_Z
|BIT_A
|BIT_N
);
437 case 0x08: res
= (inst_st_sp_abs(code
)); break;
438 case 0x09: res
= (inst_add(code
)); break;
439 case 0x0a: case 0x0e: res
= (inst_ld(code
)); break;
441 case 0x0d: res
= (inst_dec(code
)); break;
442 case 0x0c: res
= (inst_inc(code
)); break;
444 int ret
= (inst_rrca(code
));
445 regs
.raf
.F
&= ~(BIT_Z
|BIT_A
|BIT_N
);
450 case 0x10: res
= (inst_stop0(code
)); break;
452 case 0x12: case 0x16: res
= (inst_ld(code
)); break;
454 case 0x14: res
= (inst_inc(code
)); break;
455 case 0x15: res
= (inst_dec(code
)); break;
457 int ret
= (inst_rla(code
));
458 regs
.raf
.F
&= ~(BIT_Z
|BIT_A
|BIT_N
);
462 case 0x18: res
= (inst_jr(code
)); break;
463 case 0x19: res
= (inst_add(code
)); break;
464 case 0x1a: case 0x1e: res
= (inst_ld(code
)); break;
466 case 0x1d: res
= (inst_dec(code
)); break;
467 case 0x1c: res
= (inst_inc(code
)); break;
469 int ret
= (inst_rra(code
));
470 regs
.raf
.F
&= ~(BIT_Z
|BIT_A
|BIT_N
);
475 case 0x20: res
= (inst_jr(code
)); break;
477 case 0x26: res
= (inst_ld(code
)); break;
478 case 0x22: res
= inst_ldi(code
); break;
480 case 0x24: res
= (inst_inc(code
)); break;
481 case 0x25: res
= (inst_dec(code
)); break;
482 case 0x27: res
= (inst_daa(code
)); break;
484 case 0x28: res
= (inst_jr(code
)); break;
485 case 0x29: res
= (inst_add(code
)); break;
486 case 0x2a: res
= (inst_ldi(code
)); break;
488 case 0x2d: res
= (inst_dec(code
)); break;
489 case 0x2c: res
= (inst_inc(code
)); break;
490 case 0x2e: res
= (inst_ld(code
)); break;
491 case 0x2f: res
= (inst_cpl(code
)); break;
493 case 0x30: res
= (inst_jr(code
)); break;
494 case 0x31: case 0x36: res
= (inst_ld(code
)); break;
495 case 0x32: res
= (inst_ldd(code
)); break;
497 case 0x34: res
= (inst_inc(code
)); break;
498 case 0x35: res
= (inst_dec(code
)); break;
499 case 0x37: res
= (inst_scf(code
)); break;
501 case 0x38: res
= (inst_jr(code
)); break;
502 case 0x39: res
= (inst_add(code
)); break;
503 case 0x3a: res
= inst_ldd(code
); break;
505 case 0x3d: res
= (inst_dec(code
)); break;
506 case 0x3c: res
= (inst_inc(code
)); break;
507 case 0x3e: res
= (inst_ld(code
)); break;
508 case 0x3f: res
= (inst_ccf(code
)); break;
510 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47:
511 case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4f:
512 res
= (inst_ld(code
));
514 case 0x46: case 0x4e: res
= (inst_ld(code
)); break;
516 case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x57:
517 case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5f:
518 res
= (inst_ld(code
));
520 case 0x56: case 0x5e: res
= (inst_ld(code
)); break;
522 case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x67:
523 case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6f:
524 res
= (inst_ld(code
));
526 case 0x66: case 0x6e: res
= (inst_ld(code
)); break;
528 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x77: case 0x7e:
529 res
= (inst_ld(code
));
531 case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7f:
532 res
= (inst_ld(code
));
534 case 0x76: res
= (inst_halt(code
)); break;
536 case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x87:
537 res
= (inst_add(code
));
539 case 0x86: res
= (inst_add(code
)); break;
540 case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8f:
541 res
= (inst_adc(code
));
543 case 0x8e: res
= (inst_adc(code
)); break;
545 case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x97:
546 res
= (inst_sub(code
));
548 case 0x96: res
= (inst_sub(code
)); break;
549 case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9f:
550 res
= (inst_sbc(code
));
552 case 0x9e: res
= (inst_sbc(code
)); break;
554 case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa7:
555 res
= (inst_and(code
));
557 case 0xa6: res
= (inst_and(code
)); break;
558 case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xaf:
559 res
= (inst_xor(code
));
561 case 0xae: res
= (inst_xor(code
)); break;
563 case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb7:
564 res
= (inst_or(code
));
566 case 0xb6: res
= (inst_or(code
)); break;
567 case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbf:
568 res
= (inst_cp(code
));
570 case 0xbe: res
= (inst_cp(code
)); break;
572 case 0xc0: res
= (inst_ret(code
)); break;
573 case 0xc1: res
= (inst_pop(code
)); break;
574 case 0xc2: res
= (inst_jp(code
)); break;
575 case 0xc3: res
= (inst_jp(code
)); break;
576 case 0xc4: res
= (inst_call(code
)); break;
577 case 0xc5: res
= (inst_push(code
)); break;
578 case 0xc6: res
= (inst_add(code
)); break;
579 case 0xc7: res
= (inst_rst(code
)); break;
581 case 0xc8: res
= (inst_ret(code
)); break;
582 case 0xc9: res
= (inst_ret(code
)); break;
583 case 0xca: res
= (inst_jp(code
)); break;
585 /* CB escapes out to 2 byte opcodes(CB include), opcodes
586 to do register bit manipulations */
587 case 0xcb: res
= (inst_cb( )); break;
588 case 0xcc: res
= (inst_call(code
)); break;
589 case 0xcd: res
= (inst_call(code
)); break;
590 case 0xce: res
= (inst_adc(code
)); break;
591 case 0xcf: res
= (inst_rst(code
)); break;
593 case 0xd0: res
= (inst_ret(code
)); break;
594 case 0xd1: res
= (inst_pop(code
)); break;
595 case 0xd2: res
= (inst_jp(code
)); break;
597 case 0xd4: res
= (inst_call(code
)); break;
598 case 0xd5: res
= (inst_push(code
)); break;
599 case 0xd6: res
= (inst_sub(code
)); break;
600 case 0xd7: res
= (inst_rst(code
)); break;
602 case 0xd8: res
= (inst_ret(code
)); break;
603 case 0xd9: res
= (inst_reti(code
)); break;
604 case 0xda: res
= (inst_jp(code
)); break;
606 case 0xdc: res
= (inst_call(code
)); break;
608 case 0xdd: break; /* IX register doesn't exist on the GB80 */
609 case 0xde: res
= (inst_sbc(code
)); break;
610 case 0xdf: res
= (inst_rst(code
)); break;
613 case 0xe0: res
= (inst_ldh(code
)); break;
614 case 0xe1: res
= (inst_pop(code
)); break;
615 case 0xe2: res
= (inst_ldh(code
)); break;
618 case 0xe5: res
= (inst_push(code
)); break;
619 case 0xe6: res
= (inst_and(code
)); break;
620 case 0xe7: res
= (inst_rst(code
)); break;
622 case 0xe8: res
= (inst_add_sp_d(code
)); break;
623 case 0xe9: res
= (inst_jp(code
)); break;
624 case 0xea: res
= (inst_ld16(code
)); break;
626 case 0xec: case 0xed: break;
627 case 0xee: res
= (inst_xor(code
)); break;
628 case 0xef: res
= (inst_rst(code
)); break;
630 case 0xf0: res
= (inst_ldh(code
)); break;
632 int ret
= (inst_pop(code
));
638 case 0xf2: res
= (inst_ldh(code
)); break;
639 case 0xf3: res
= (inst_di(code
)); break;
641 case 0xf5: res
= (inst_push(code
)); break;
642 case 0xf6: res
= (inst_or(code
)); break;
643 case 0xf7: res
= (inst_rst(code
)); break;
645 case 0xf8: res
= (inst_ldhl_sp(code
)); break;
646 case 0xf9: res
= (inst_ld(code
)); break;
647 case 0xfa: res
= (inst_ld16(code
)); break;
648 case 0xfb: res
= (inst_ei(code
)); break;
651 case 0xfe: res
= (inst_cp(code
)); break;
652 case 0xff: res
= (inst_rst(code
)); break;
665 cl_gb80::tickt(t_mem code
)
667 // special cases: dd, cb, ed, ddcb, fd, fdcb
673 c2
= rom
->read(instPC
+1);
689 /* End of z80.src/gb80.cc */