2 * Simulator of microcontrollers (m68hc12.cc)
4 * Copyright (C) 2020 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
40 #include "m68hc12cl.h"
50 cl_ccr::write(t_mem val
)
56 return cl_cell8::write(val
);
65 cl_m68hc12::proba(int i
, t_mem code
)
72 cl_m68hc12::cl_m68hc12(class cl_sim
*asim
):
83 memcpy((void*)&cCC
, (void*)&c
, sizeof(class cl_cell8
));
84 hc12wrap
= new cl_12wrap();
91 cl_m68hc12::init(void)
96 #define RCV(R) reg_cell_var(&c ## R , &r ## R , "" #R "" , "CPU register " #R "")
102 for (i
= 0; i
<=255; i
++)
103 itab
[i
]= instruction_wrapper_invalid
;
108 tex_cells
[3]= &cTMP3
;
117 tex_names
[3]= "TMP3";
146 cl_m68hc12::id_string(void)
152 cl_m68hc12::reset(void)
154 cl_m68hcbase::reset();
155 rCC
= flagStop
|flagX
|flagI
;
161 cl_m68hc12::make_memories(void)
163 class cl_address_space
*as
;
164 class cl_address_decoder
*ad
;
165 class cl_memory_chip
*chip
;
167 rom
= as
= new cl_address_space("rom", 0, 0x10000, 8);
169 address_spaces
->add(as
);
171 chip
= new cl_chip8("rom_chip", 0x400000, 8);
174 ad
= new cl_address_decoder(as
= rom
,
177 as
->decoders
->add(ad
);
182 cl_m68hc12::make_cpu_hw(void)
184 add_hw(cpu12
= new cl_hc12_cpu(this));
192 cl_m68hcbase::pre_inst();
202 cl_m68hcbase::pre_emu();
210 CL12::exec_inst(void)
214 hcwrapper_fn fn
= NULL
;
218 return resBREAKPOINT
;
222 fn
= hc12wrap
->page0x18
[code
];
223 inst_ticks
= ticks12p18
[code
];
225 else if (code
== 0x04)
233 fn
= hc12wrap
->page0
[code
];
234 inst_ticks
= ticks12p0
[code
];
238 if (res
!= resNOT_DONE
)
241 inst_unknown(rom
->read(instPC
));
246 CL12::post_inst(void)
248 if (inst_ticks
& 0xf00)
249 inst_ticks
= (inst_ticks
>>(4*xb_tick_shift
)) & 0xf;
253 cl_m68hcbase::post_inst();
259 if (inst_ticks
& 0xf00)
260 inst_ticks
= (inst_ticks
>>(4*xb_tick_shift
)) & 0xf;
264 cl_m68hcbase::post_emu();
276 CL12::xb_type(u8_t p
)
279 // 1. rr0n nnnn n5,r rr={X,Y,SP,PC}
281 if ((p
&0xe7) == 0xe7)
282 // 6. 111r r111 [D,r] rr={X,Y,SP,PC}
284 if ((p
&0xe7) == 0xe3)
285 // 5. 111r r011 [n16,r] rr={X,Y,SP,PC}
287 if ((p
&0xc0) != 0xc0)
288 // 3. rr1p nnnn n4,+-r+- rr={X,Y,SP}
290 if ((p
&0xe4) == 0xe0)
291 // 2. 111r r0zs n9/16,r rr={X,Y,SP,PC}
293 // if ((p&0xe4) == 0xe4)
294 // 4. 111r r1aa {A,B,D},r rr={X,Y,SP,PC}
299 CL12::xb_indirect(u8_t p
)
301 if ((p
& 0x20) == 0) return false;
302 if ((p
&0xe7) == 0xe7) return true;
303 if ((p
&0xe7) == 0xe3) return true;
313 case 1: return (p
&0xc0)==0xc0;
314 case 6: return (p
&0x18)==0x18;
315 case 5: return (p
&0x18)==0x18;
316 case 3: return false;
317 case 2: return (p
&0x18)==0x18;
318 case 4: return (p
&0x18)==0x18;
324 CL12::naddr(t_addr
*addr
/* of xb */, u8_t
*pg
, u32_t use_PC
)
331 //i8_t post_inc_dec= 0;
332 class cl_cell16
*post_idx_reg
= NULL
;
345 case 1: // 1. rr0n nnnn n5,r rr={X,Y,SP,PC}
348 case 0x00: ival
= rX
; break;
349 case 0x40: ival
= rY
; break;
350 case 0x80: ival
= rSP
; break;
355 ival
= (*addr
)&0xffff;
361 if (p
&0x10) ioffset
|= 0xffe0;
363 return (u16_t
)(ival
+ioffset
);
366 case 6: // 6. 111r r111 [D,r] rr={X,Y,SP,PC}
369 case 0x00: ival
= rX
; break;
370 case 0x10: ival
= rY
; break;
371 case 0x08: ival
= rSP
; break;
376 ival
= (*addr
)&0xffff;
382 a
= (u16_t
)(ival
+ioffset
);
386 return (u16_t
)read_addr(rom
, a
);
389 case 5: // 5. 111r r011 [n16,r] rr={X,Y,SP,PC}
392 case 0x00: ival
= rX
; break;
393 case 0x10: ival
= rY
; break;
394 case 0x08: ival
= rSP
; break;
399 ival
= (*addr
)&0xffff;
417 a
= (u16_t
)(ival
+ioffset
);
421 return (u16_t
)read_addr(rom
, a
);
424 case 3: // 3. rr1p nnnn n4,+-r+- rr={X,Y,SP}
427 case 0x00: ival
= rX
; post_idx_reg
= &cX
; break;
428 case 0x40: ival
= rY
; post_idx_reg
= &cY
; break;
429 case 0x80: ival
= rSP
; post_idx_reg
= &cSP
; break;
432 if (n
&0x08) n
|= 0xf0; else n
++;
436 ival
= (post_idx_reg
->R() + (int)n
);
440 post_idx_reg
->W(ival
);
447 post_idx_reg
->W(ival
);
448 ival
= (post_idx_reg
->R() + (int)n
);
454 case 2: // 2. 111r r0zs n9/16,r rr={X,Y,SP,PC}
457 case 0x00: ival
= rX
; break;
458 case 0x10: ival
= rY
; break;
459 case 0x08: ival
= rSP
; break;
464 ival
= (*addr
)&0xffff;
469 if ((p
&0x02) == 0x00)
474 ioffset
= rom
->read(*addr
);
479 if (p
&0x01) ioffset
|= 0xff00;
500 return (u16_t
)(ival
+ioffset
);
503 default: // 4. 111r r1aa {A,B,D},r rr={X,Y,SP,PC}
506 case 0x00: ival
= rX
; break;
507 case 0x08: ival
= rY
; break;
508 case 0x10: ival
= rSP
; break;
513 ival
= (*addr
)&0xffff;
520 case 0x00: uoffset
= rA
; break;
521 case 0x01: uoffset
= rB
; break;
522 case 0x02: uoffset
= rD
; break;
525 return (u16_t
)(ival
+uoffset
);
535 u16_t a
= naddr(NULL
, NULL
);
542 u16_t a
= naddr(NULL
, NULL
);
549 class cl_memory_cell
&
552 t_addr a
= naddr(NULL
, NULL
);
553 class cl_cell8
*c
= (class cl_cell8
*)rom
->get_cell(a
);
558 CL12::push_regs(bool inst_part
)
560 rom
->write(--rSP
, PC
&0xff);
561 rom
->write(--rSP
, PC
>>8);
562 rom
->write(--rSP
, rIY
&0xff);
563 rom
->write(--rSP
, rIY
>>8);
564 rom
->write(--rSP
, rIX
&0xff);
565 rom
->write(--rSP
, rIX
>>8);
566 rom
->write(--rSP
, rA
);
567 rom
->write(--rSP
, rB
);
568 rom
->write(--rSP
, rCC
);
572 CL12::pull_regs(bool inst_part
)
575 rCC
= rom
->read(rSP
++);
576 rB
= rom
->read(rSP
++);
577 rA
= rom
->read(rSP
++);
590 CL12::trap(t_mem code
)
593 PC
= read_addr(rom
, TRAP_AT
);
599 cl_m68hc12::print_regs(class cl_console_base
*con
)
601 con
->dd_color("answer");
602 con
->dd_printf("A= $%02x %3d %+4d %c ", rA
, rA
, (i8_t
)rA
, isprint(rA
)?rA
:'.');
603 con
->dd_printf("B= $%02x %3d %+4d %c ", rB
, rB
, (i8_t
)rB
, isprint(rB
)?rB
:'.');
604 con
->dd_printf(" D= $%04x %5d %+5d ", rD
, rD
, (i16_t
)rD
);
605 con
->dd_printf("\n");
606 con
->dd_printf("CC= "); con
->print_bin(rF
, 8);
607 con
->dd_printf(" TMP2= $%04x %5d %+5d",
608 rTMP2
, rTMP2
, rTMP2
);
609 con
->dd_printf("\n");
610 con
->dd_printf(" SXHINZVC");
611 con
->dd_printf(" TMP3= $%04x %5d %+5d",
612 rTMP3
, rTMP3
, rTMP3
);
613 con
->dd_printf("\n");
615 con
->dd_printf("IX= ");
616 class cl_dump_ads
ads(IX
, IX
+7);
617 rom
->dump(0, /*IX, IX+7*/&ads
, 8, con
);
618 con
->dd_color("answer");
620 con
->dd_printf("IY= ");
622 rom
->dump(0, /*IY, IY+7*/&ads
, 8, con
);
623 con
->dd_color("answer");
625 con
->dd_printf("SP= ");
627 rom
->dump(0, /*SP, SP+7*/&ads
, 8, con
);
628 con
->dd_color("answer");
630 print_disass(PC
, con
);
635 * CPU peripheral for HC12 cpu
638 cl_hc12_cpu::cl_hc12_cpu(class cl_uc
*auc
):
639 cl_hw(auc
, HW_CPU
, 0, "cpu")
641 muc
= (class cl_m68hc12
*)auc
;
645 cl_hc12_cpu::init(void)
650 ppage
= register_cell(muc
->rom
, 0x0035);
651 dpage
= register_cell(muc
->rom
, 0x0034);
652 epage
= register_cell(muc
->rom
, 0x0036);
653 windef
= register_cell(muc
->rom
, 0x0037);
655 uc
->vars
->add(v
= new cl_var("PPAGE", muc
->rom
, 0x0035,
656 "Program page register"));
658 uc
->vars
->add(v
= new cl_var("DPAGE", muc
->rom
, 0x0034,
659 "Data page register"));
661 uc
->vars
->add(v
= new cl_var("EPAGE", muc
->rom
, 0x0036,
662 "Extra page register"));
664 uc
->vars
->add(v
= new cl_var("WINDEF", muc
->rom
, 0x0037,
665 "Window definition register"));
671 cl_hc12_cpu::reset(void)
680 cl_hc12_cpu::print_info(class cl_console_base
*con
)
682 con
->dd_color("answer");
683 con
->dd_printf("PPAGE= $%02x\n", ppage
->read());
684 con
->dd_printf("DPAGE= $%02x\n", dpage
->read());
685 con
->dd_printf("EPAGE= $%02x\n", epage
->read());
686 u8_t w
= windef
->read();
687 con
->dd_printf("PWEN= %d\n", (w
&0x40)?1:0);
688 con
->dd_printf("DWEN= %d\n", (w
&0x80)?1:0);
689 con
->dd_printf("EWEN= %d\n", (w
&0x20)?1:0);
693 cl_hc12_cpu::ppage_write(u8_t val
)
695 return ppage
->write(val
);
699 /* End of m68hc12.src/m68hc12.cc */