2 * Simulator of microcontrollers (uc51.cc)
4 * Copyright (C) 1999,99 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
37 #include <sys/types.h>
55 #include "interruptcl.h"
60 * Making a new micro-controller and reset it
63 t_uc51::t_uc51(int Itype, int Itech, class cl_sim *asim):
73 debug= asim->app->args->get_iarg('V', 0);
75 options->add(new cl_bool_opt(&debug, "verbose", "Verbose flag."));
76 options->add(new cl_bool_opt(&stop_at_it, "stopit",
77 "Stop if interrupt accepted."));
78 options->add(new cl_cons_debug_opt(asim->app, "debug",
79 "Debug messages appears on this console."));
82 serial_in = (FILE*)asim->app->args->get_parg(0, "Ser_in");
83 serial_out= (FILE*)asim->app->args->get_parg(0, "Ser_out");
86 // making `serial' unbuffered
87 if (setvbuf(serial_in, NULL, _IONBF, 0))
88 perror("Unbuffer serial input channel");
90 if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)
91 perror("Get flags of serial input");
93 if (fcntl(fileno(serial_in), F_SETFL, i) < 0)
94 perror("Set flags of serial input");
95 // switching terminal to noncanonical mode
96 if (isatty(fileno(serial_in)))
98 tcgetattr(fileno(serial_in), &saved_attributes_in);
99 tcgetattr(fileno(serial_in), &tattr);
100 tattr.c_lflag&= ~(ICANON|ECHO);
101 tattr.c_cc[VMIN] = 1;
102 tattr.c_cc[VTIME]= 0;
103 tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
106 fprintf(stderr, "Warning: serial input interface connected to a "
107 "non-terminal file.\n");
111 // making `serial' unbuffered
112 if (setvbuf(serial_out, NULL, _IONBF, 0))
113 perror("Unbuffer serial output channel");
114 // setting O_NONBLOCK
115 if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)
116 perror("Get flags of serial output");
118 if (fcntl(fileno(serial_out), F_SETFL, i) < 0)
119 perror("Set flags of serial output");
120 // switching terminal to noncanonical mode
121 if (isatty(fileno(serial_out)))
123 tcgetattr(fileno(serial_out), &saved_attributes_out);
124 tcgetattr(fileno(serial_out), &tattr);
125 tattr.c_lflag&= ~(ICANON|ECHO);
126 tattr.c_cc[VMIN] = 1;
127 tattr.c_cc[VTIME]= 0;
128 tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
131 fprintf(stderr, "Warning: serial output interface connected to a "
132 "non-terminal file.\n");
136 /*for (i= 0; i < 4; i++)
137 port_pins[i]= 0xff;*/
138 /*it_sources->add(new cl_it_src(bmEX0, TCON, bmIE0, 0x0003, true,
140 /*it_sources->add(new cl_it_src(bmET0, TCON, bmTF0, 0x000b, true,
142 /*it_sources->add(new cl_it_src(bmEX1, TCON, bmIE1, 0x0013, true,
144 /*it_sources->add(new cl_it_src(bmET1, TCON, bmTF1, 0x001b, true,
146 /*it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,
148 it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,
149 "serial receive"));*/
154 * Initializing. Virtual calls go here
155 * This method must be called first after object creation.
166 static char id_string_51[100];
169 t_uc51::id_string(void)
173 for (i= 0; cpus_51[i].type_str != NULL && cpus_51[i].type != type; i++) ;
174 sprintf(id_string_51, "%s %s",
175 cpus_51[i].type_str?cpus_51[i].type_str:"51",
176 (technology==CPU_HMOS)?"HMOS":"CMOS");
177 return(id_string_51);
181 t_uc51::mk_hw_elements(void)
185 acc= sfr->get_cell(ACC);
186 psw= sfr->get_cell(PSW);
188 hws->add(h= new cl_timer0(this, 0, "timer0"));
190 hws->add(h= new cl_timer1(this, 1, "timer1"));
192 hws->add(h= new cl_serial(this));
194 hws->add(h= new cl_port(this, 0));
196 hws->add(h= new cl_port(this, 1));
198 hws->add(h= new cl_port(this, 2));
200 hws->add(h= new cl_port(this, 3));
202 hws->add(interrupt= new cl_interrupt(this));
204 hws->add(h= new cl_uc51_dummy_hw(this));
207 acc= sfr->get_cell(ACC);
208 psw= sfr->get_cell(PSW);
213 t_uc51::mk_mem(enum mem_class type, char *class_name)
215 class cl_mem *m= cl_uc::mk_mem(type, class_name);
218 if (type == MEM_IRAM)
225 * Destroying the micro-controller object
228 t_uc51::~t_uc51(void)
233 if (isatty(fileno(serial_out)))
234 tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
239 if (isatty(fileno(serial_in)))
240 tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
248 * Writing data to EROM
252 t_uc51::write_rom(t_addr addr, ulong data)
254 if (addr < EROM_SIZE)
255 set_mem(MEM_ROM, addr, data);
260 * Disassembling an instruction
264 t_uc51::dis_tbl(void)
270 t_uc51::sfr_tbl(void)
276 t_uc51::bit_tbl(void)
282 t_uc51::disass(t_addr addr, char *sep)
284 char work[256], temp[20], c[2];
285 char *buf, *p, *b, *t;
286 t_mem code= get_mem(MEM_ROM, addr);
289 b= dis_tbl()[code].mnemonic;
297 case 'A': // absolute address
298 sprintf(temp, "%04"_A_"x",
299 t_addr((addr&0xf800)|
300 (((code>>5)&0x07)*256 +
301 get_mem(MEM_ROM, addr+1))));
303 case 'l': // long address
304 sprintf(temp, "%04"_A_"x",
305 t_addr(get_mem(MEM_ROM, addr+1)*256 +
306 get_mem(MEM_ROM, addr+2)));
308 case 'a': // addr8 (direct address) at 2nd byte
309 if (!get_name(get_mem(MEM_ROM, addr+1), sfr_tbl(), temp))
310 sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));
312 case '8': // addr8 (direct address) at 3rd byte
313 if (!get_name(get_mem(MEM_ROM, addr+2), sfr_tbl(), temp))
314 sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));
315 //sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));
317 case 'b': // bitaddr at 2nd byte
319 t_addr ba= get_mem(MEM_ROM, addr+1);
320 if (get_name(ba, bit_tbl(), temp))
322 if (get_name((ba<128)?((ba/8)+32):(ba&0xf8), sfr_tbl(), temp))
325 sprintf(c, "%1"_M_"d", ba & 0x07);
329 sprintf(temp, "%02x.%"_M_"d", (ba<128)?((ba/8)+32):(ba&0xf8),
333 case 'r': // rel8 address at 2nd byte
334 sprintf(temp, "%04"_A_"x",
335 t_addr(addr+2+(signed char)(get_mem(MEM_ROM, addr+1))));
337 case 'R': // rel8 address at 3rd byte
338 sprintf(temp, "%04"_A_"x",
339 t_addr(addr+3+(signed char)(get_mem(MEM_ROM, addr+2))));
341 case 'd': // data8 at 2nd byte
342 sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));
344 case 'D': // data8 at 3rd byte
345 sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));
347 case '6': // data16 at 2nd(H)-3rd(L) byte
348 sprintf(temp, "%04"_A_"x",
349 t_addr(get_mem(MEM_ROM, addr+1)*256 +
350 get_mem(MEM_ROM, addr+2)));
365 p= strchr(work, ' ');
372 buf= (char *)malloc(6+strlen(p)+1);
374 buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
375 for (p= work, b= buf; *p != ' '; p++, b++)
381 while (strlen(buf) < 6)
392 t_uc51::print_regs(class cl_console *con)
397 start= psw->get() & 0x18;
398 //dump_memory(iram, &start, start+7, 8, /*sim->cmd_out()*/con, sim);
399 iram->dump(start, start+7, 8, con);
400 start= psw->get() & 0x18;
401 data= iram->get(iram->get(start));
402 con->dd_printf("%06x %02x %c",
403 iram->get(start), data, isprint(data)?data:'.');
405 con->dd_printf(" ACC= 0x%02x %3d %c B= 0x%02x", sfr->get(ACC), sfr->get(ACC),
406 isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B));
408 data= get_mem(MEM_XRAM, sfr->get(DPH)*256+sfr->get(DPL));
409 con->dd_printf(" DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH),
410 sfr->get(DPL), data, data, isprint(data)?data:'.');
412 data= iram->get(iram->get(start+1));
413 con->dd_printf("%06x %02x %c", iram->get(start+1), data,
414 isprint(data)?data:'.');
416 con->dd_printf(" PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data,
417 (data&bmCY)?'1':'0', (data&bmAC)?'1':'0',
418 (data&bmOV)?'1':'0', (data&bmP)?'1':'0');
420 print_disass(PC, con);
425 * Converting bit address into real memory
429 t_uc51::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
438 ma= bitaddr/8 + 0x20;
448 *bitmask= 1 << (bitaddr & 0x7);
454 * Resetting the micro-controller
466 //was_reti= DD_FALSE;
471 * Setting up SFR area to reset value
475 t_uc51::clear_sfr(void)
479 for (i= 0; i < SFR_SIZE; i++)
481 sfr->/*set*/write(P0, 0xff);
482 sfr->/*set*/write(P1, 0xff);
483 sfr->/*set*/write(P2, 0xff);
484 sfr->/*set*/write(P3, 0xff);
485 sfr->/*set*/write(SP, 7);
486 prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1);
487 prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3);
492 * Analyzing code and settig up instruction map
496 t_uc51::analyze(t_addr addr)
499 struct dis_entry *tabl;
501 code= get_mem(MEM_ROM, addr);
502 tabl= &(dis_tbl()[code]);
503 while (!inst_at(addr) &&
504 code != 0xa5 /* break point */)
507 switch (tabl->branch)
510 analyze((addr & 0xf800)|
511 ((get_mem(MEM_ROM, addr+1)&0x07)*256+
512 get_mem(MEM_ROM, addr+2)));
513 analyze(addr+tabl->length);
516 addr= (addr & 0xf800)|
517 ((get_mem(MEM_ROM, addr+1) & 0x07)*256 + get_mem(MEM_ROM, addr+2));
520 analyze(get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));
521 analyze(addr+tabl->length);
524 addr= get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2);
526 case 'r': // reljmp (2nd byte)
527 analyze((addr + (signed char)(get_mem(MEM_ROM, addr+1))) &
529 analyze(addr+tabl->length);
531 case 'R': // reljmp (3rd byte)
533 (signed char)(get_mem(MEM_ROM, addr+2)))&(EROM_SIZE-1));
534 analyze(addr+tabl->length);
539 target= get_mem(MEM_ROM, addr+1);
541 addr= (addr+target)&(EROM_SIZE-1);
547 addr= (addr+tabl->length) & (EROM_SIZE - 1);
550 code= get_mem(MEM_ROM, addr);
551 tabl= &(dis_tbl()[code]);
557 * Inform hardware elements that `cycles' machine cycles have elapsed
561 t_uc51::tick_hw(int cycles)
563 cl_uc::tick_hw(cycles);
564 //do_hardware(cycles);
569 t_uc51::tick(int cycles)
572 //do_hardware(cycles);
578 * Correcting direct address
580 * This function returns address of addressed element which can be an IRAM
585 t_uc51::get_direct(t_mem addr)
587 if (addr < SFR_START)
588 return(iram->get_cell(addr));
590 return(sfr->get_cell(addr));
595 * Calculating address of specified register cell in IRAM
599 t_uc51::get_reg(uchar regnum)
601 t_addr a= (psw->get() & (bmRS0|bmRS1)) | (regnum & 0x07);
602 return(iram->get_cell(a));
607 * Fetching one instruction and executing it
611 t_uc51::exec_inst(void)
619 return(resBREAKPOINT);
624 case 0x00: res= inst_nop(code); break;
625 case 0x01: case 0x21: case 0x41: case 0x61:
626 case 0x81: case 0xa1: case 0xc1: case 0xe1:res=inst_ajmp_addr(code);break;
627 case 0x02: res= inst_ljmp(code); break;
628 case 0x03: res= inst_rr(code); break;
629 case 0x04: res= inst_inc_a(code); break;
630 case 0x05: res= inst_inc_addr(code); break;
631 case 0x06: case 0x07: res= inst_inc_$ri(code); break;
632 case 0x08: case 0x09: case 0x0a: case 0x0b:
633 case 0x0c: case 0x0d: case 0x0e: case 0x0f: res= inst_inc_rn(code); break;
634 case 0x10: res= inst_jbc_bit_addr(code); break;
635 case 0x11: case 0x31: case 0x51: case 0x71:
636 case 0x91: case 0xb1: case 0xd1: case 0xf1:res=inst_acall_addr(code);break;
637 case 0x12: res= inst_lcall(code, 0); break;
638 case 0x13: res= inst_rrc(code); break;
639 case 0x14: res= inst_dec_a(code); break;
640 case 0x15: res= inst_dec_addr(code); break;
641 case 0x16: case 0x17: res= inst_dec_$ri(code); break;
642 case 0x18: case 0x19: case 0x1a: case 0x1b:
643 case 0x1c: case 0x1d: case 0x1e: case 0x1f: res= inst_dec_rn(code); break;
644 case 0x20: res= inst_jb_bit_addr(code); break;
645 case 0x22: res= inst_ret(code); break;
646 case 0x23: res= inst_rl(code); break;
647 case 0x24: res= inst_add_a_$data(code); break;
648 case 0x25: res= inst_add_a_addr(code); break;
649 case 0x26: case 0x27: res= inst_add_a_$ri(code); break;
650 case 0x28: case 0x29: case 0x2a: case 0x2b:
651 case 0x2c: case 0x2d: case 0x2e: case 0x2f:res= inst_add_a_rn(code);break;
652 case 0x30: res= inst_jnb_bit_addr(code); break;
653 case 0x32: res= inst_reti(code); break;
654 case 0x33: res= inst_rlc(code); break;
655 case 0x34: res= inst_addc_a_$data(code); break;
656 case 0x35: res= inst_addc_a_addr(code); break;
657 case 0x36: case 0x37: res= inst_addc_a_$ri(code); break;
658 case 0x38: case 0x39: case 0x3a: case 0x3b:
659 case 0x3c: case 0x3d: case 0x3e: case 0x3f:res= inst_addc_a_rn(code);break;
660 case 0x40: res= inst_jc_addr(code); break;
661 case 0x42: res= inst_orl_addr_a(code); break;
662 case 0x43: res= inst_orl_addr_$data(code); break;
663 case 0x44: res= inst_orl_a_$data(code); break;
664 case 0x45: res= inst_orl_a_addr(code); break;
665 case 0x46: case 0x47: res= inst_orl_a_$ri(code); break;
666 case 0x48: case 0x49: case 0x4a: case 0x4b:
667 case 0x4c: case 0x4d: case 0x4e: case 0x4f: res= inst_orl_a_rn(code);break;
668 case 0x50: res= inst_jnc_addr(code); break;
669 case 0x52: res= inst_anl_addr_a(code); break;
670 case 0x53: res= inst_anl_addr_$data(code); break;
671 case 0x54: res= inst_anl_a_$data(code); break;
672 case 0x55: res= inst_anl_a_addr(code); break;
673 case 0x56: case 0x57: res= inst_anl_a_$ri(code); break;
674 case 0x58: case 0x59: case 0x5a: case 0x5b:
675 case 0x5c: case 0x5d: case 0x5e: case 0x5f: res= inst_anl_a_rn(code);break;
676 case 0x60: res= inst_jz_addr(code); break;
677 case 0x62: res= inst_xrl_addr_a(code); break;
678 case 0x63: res= inst_xrl_addr_$data(code); break;
679 case 0x64: res= inst_xrl_a_$data(code); break;
680 case 0x65: res= inst_xrl_a_addr(code); break;
681 case 0x66: case 0x67: res= inst_xrl_a_$ri(code); break;
682 case 0x68: case 0x69: case 0x6a: case 0x6b:
683 case 0x6c: case 0x6d: case 0x6e: case 0x6f: res= inst_xrl_a_rn(code);break;
684 case 0x70: res= inst_jnz_addr(code); break;
685 case 0x72: res= inst_orl_c_bit(code); break;
686 case 0x73: res= inst_jmp_$a_dptr(code); break;
687 case 0x74: res= inst_mov_a_$data(code); break;
688 case 0x75: res= inst_mov_addr_$data(code); break;
689 case 0x76: case 0x77: res= inst_mov_$ri_$data(code); break;
690 case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
691 case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_$data(code); break;
692 case 0x80: res= inst_sjmp(code); break;
693 case 0x82: res= inst_anl_c_bit(code); break;
694 case 0x83: res= inst_movc_a_$a_pc(code); break;
695 case 0x84: res= inst_div_ab(code); break;
696 case 0x85: res= inst_mov_addr_addr(code); break;
697 case 0x86: case 0x87: res= inst_mov_addr_$ri(code); break;
698 case 0x88: case 0x89: case 0x8a: case 0x8b:
699 case 0x8c: case 0x8d: case 0x8e: case 0x8f:res=inst_mov_addr_rn(code);break;
700 case 0x90: res= inst_mov_dptr_$data(code); break;
701 case 0x92: res= inst_mov_bit_c(code); break;
702 case 0x93: res= inst_movc_a_$a_dptr(code); break;
703 case 0x94: res= inst_subb_a_$data(code); break;
704 case 0x95: res= inst_subb_a_addr(code); break;
705 case 0x96: case 0x97: res= inst_subb_a_$ri(code); break;
706 case 0x98: case 0x99: case 0x9a: case 0x9b:
707 case 0x9c: case 0x9d: case 0x9e: case 0x9f:res= inst_subb_a_rn(code);break;
708 case 0xa2: res= inst_mov_c_bit(code); break;
709 case 0xa3: res= inst_inc_dptr(code); break;
710 case 0xa4: res= inst_mul_ab(code); break;
711 case 0xa5: res= inst_unknown(code); break;
712 case 0xa6: case 0xa7: res= inst_mov_$ri_addr(code); break;
713 case 0xa8: case 0xa9: case 0xaa: case 0xab:
714 case 0xac: case 0xad: case 0xae: case 0xaf:res=inst_mov_rn_addr(code);break;
715 case 0xb0: res= inst_anl_c_$bit(code); break;
716 case 0xb2: res= inst_cpl_bit(code); break;
717 case 0xb3: res= inst_cpl_c(code); break;
718 case 0xb4: res= inst_cjne_a_$data_addr(code); break;
719 case 0xb5: res= inst_cjne_a_addr_addr(code); break;
720 case 0xb6: case 0xb7: res= inst_cjne_$ri_$data_addr(code); break;
721 case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc:
722 case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_$data_addr(code); break;
723 case 0xc0: res= inst_push(code); break;
724 case 0xc2: res= inst_clr_bit(code); break;
725 case 0xc3: res= inst_clr_c(code); break;
726 case 0xc4: res= inst_swap(code); break;
727 case 0xc5: res= inst_xch_a_addr(code); break;
728 case 0xc6: case 0xc7: res= inst_xch_a_$ri(code); break;
729 case 0xc8: case 0xc9: case 0xca: case 0xcb:
730 case 0xcc: case 0xcd: case 0xce: case 0xcf: res= inst_xch_a_rn(code);break;
731 case 0xd0: res= inst_pop(code); break;
732 case 0xd2: res= inst_setb_bit(code); break;
733 case 0xd3: res= inst_setb_c(code); break;
734 case 0xd4: res= inst_da_a(code); break;
735 case 0xd5: res= inst_djnz_addr_addr(code); break;
736 case 0xd6: case 0xd7: res= inst_xchd_a_$ri(code); break;
737 case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc:
738 case 0xdd: case 0xde: case 0xdf: res=inst_djnz_rn_addr(code); break;
739 case 0xe0: res= inst_movx_a_$dptr(code); break;
740 case 0xe2: case 0xe3: res= inst_movx_a_$ri(code); break;
741 case 0xe4: res= inst_clr_a(code); break;
742 case 0xe5: res= inst_mov_a_addr(code); break;
743 case 0xe6: case 0xe7: res= inst_mov_a_$ri(code); break;
744 case 0xe8: case 0xe9: case 0xea: case 0xeb:
745 case 0xec: case 0xed: case 0xee: case 0xef: res= inst_mov_a_rn(code);break;
746 case 0xf0: res= inst_movx_$dptr_a(code); break;
747 case 0xf2: case 0xf3: res= inst_movx_$ri_a(code); break;
748 case 0xf4: res= inst_cpl_a(code); break;
749 case 0xf5: res= inst_mov_addr_a(code); break;
750 case 0xf6: case 0xf7: res= inst_mov_$ri_a(code); break;
751 case 0xf8: case 0xf9: case 0xfa: case 0xfb:
752 case 0xfc: case 0xfd: case 0xfe: case 0xff: res= inst_mov_rn_a(code);break;
754 res= inst_unknown(code);
763 * Simulating execution of next instruction
765 * This is an endless loop if requested number of steps is negative.
766 * In this case execution is stopped if an instruction results other
767 * status than GO. Execution can be stopped if `cmd_in' is not NULL
768 * and there is input available on that file. It is usefull if the
769 * command console is on a terminal. If input is available then a
770 * complete line is read and dropped out because input is buffered
771 * (inp_avail will be TRUE if ENTER is pressed) and it can confuse
772 * command interepter.
776 t_uc51::do_inst(int step)
779 while ((result == resGO) &&
787 interrupt->was_reti= DD_FALSE;
791 /*if (result == resGO)
792 result= check_events();*/
796 // tick hw in idle state
803 if ((res= do_interrupt()) != resGO)
809 ((ticks->ticks % 100000) < 50))
811 if (sim->app->get_commander()->input_avail_on_frozen())
816 if (sim->app->get_commander()->input_avail())
819 if (((result == resINTERRUPT) &&
829 //FIXME: tick outsiders eg. watchdog
830 if (sim->app->get_commander()->input_avail_on_frozen())
832 //fprintf(stderr,"uc: inp avail in PD mode, user stop\n");
841 t_uc51::post_inst(void)
843 //uint tcon= sfr->get(TCON);
844 //uint p3= sfr->read(P3);
846 //cl_uc::post_inst();
849 // Setting up external interrupt request bits (IEx)
850 /*if ((tcon & bmIT0))
852 // IE0 edge triggered
855 // falling edge on INT0
856 sim->app->get_commander()->
857 debug("%g sec (%d clks): Falling edge detected on INT0 (P3.2)\n",
858 get_rtime(), ticks->ticks);
859 sfr->set_bit1(TCON, bmIE0);
865 // IE0 level triggered
867 sfr->set_bit0(TCON, bmIE0);
869 sfr->set_bit1(TCON, bmIE0);
873 // IE1 edge triggered
876 // falling edge on INT1
877 sfr->set_bit1(TCON, bmIE1);
883 // IE1 level triggered
885 sfr->set_bit0(TCON, bmIE1);
887 sfr->set_bit1(TCON, bmIE1);
889 //prev_p3= p3 & port_pins[3];
890 //prev_p1= p3 & port_pins[1];
895 * Abstract method to handle WDT
899 t_uc51::do_wdt(int cycles)
906 * Checking for interrupt requests and accept one if needed
910 t_uc51::do_interrupt(void)
914 if (interrupt->was_reti)
916 interrupt->was_reti= DD_FALSE;
919 if (!((ie= sfr->get(IE)) & bmEA))
921 class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
922 for (i= 0; i < it_sources->count; i++)
924 class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
925 if (is->is_active() &&
926 (ie & is->ie_mask) &&
927 (sfr->get(is->src_reg) & is->src_mask))
929 int pr= it_priority(is->ie_mask);
930 if (il->level >= 0 &&
936 sfr->set_bit0(PCON, bmIDL);
937 interrupt->was_reti= DD_TRUE;
941 sfr->set_bit0(is->src_reg, is->src_mask);
942 sim->app->get_commander()->
943 debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
944 get_rtime(), ticks->ticks, is->name, PC);
945 IL= new it_level(pr, is->addr, PC, is);
946 return(accept_it(IL));
953 t_uc51::it_priority(uchar ie_mask)
955 if (sfr->get(IP) & ie_mask)
962 * Accept an interrupt
966 t_uc51::accept_it(class it_level *il)
969 sfr->set_bit0(PCON, bmIDL);
972 int res= inst_lcall(0, il->addr);
976 return(resINTERRUPT);
981 * Checking if Idle or PowerDown mode should be activated
985 t_uc51::idle_pd(void)
987 uint pcon= sfr->get(PCON);
989 if (technology != CPU_CMOS)
994 sim->app->get_commander()->
995 debug("%g sec (%d clks): CPU in Idle mode\n",
996 get_rtime(), ticks->ticks);
1003 sim->app->get_commander()->
1004 debug("%g sec (%d clks): CPU in PowerDown mode\n",
1005 get_rtime(), ticks->ticks);
1013 * Checking if EVENT break happened
1017 t_uc51::check_events(void)
1020 class cl_ev_brk *eb;
1024 for (i= 0; i < ebrk->count; i++)
1026 eb= (class cl_ev_brk *)(ebrk->at(i));
1027 if (eb->match(&event_at))
1028 return(resBREAKPOINT);
1038 t_uc51::mem_cell_changed(class cl_mem *mem, t_addr addr)
1043 case ACC: acc= mem->get_cell(ACC); break;
1044 case PSW: psw= mem->get_cell(PSW); break;
1046 cl_uc::mem_cell_changed(mem, addr);
1051 * Simulating an unknown instruction
1053 * Normally this function is called for unimplemented instructions, because
1054 * every instruction must be known!
1058 t_uc51::inst_unknown(uchar code)
1061 if (1)//debug)// && sim->cmd_out())
1062 sim->app->get_commander()->
1063 debug("Unknown instruction %02x at %06x\n", code, PC);
1073 t_uc51::inst_nop(uchar code)
1084 t_uc51::inst_clr_a(uchar code)
1096 t_uc51::inst_swap(uchar code)
1100 temp= (acc->read() >> 4) & 0x0f;
1101 sfr->write(ACC, (acc->get() << 4) | temp);
1109 cl_uc51_dummy_hw::cl_uc51_dummy_hw(class cl_uc *auc):
1110 cl_hw(auc, HW_DUMMY, 0, "_51_dummy")
1112 //uc51= (class t_uc51 *)uc;
1116 cl_uc51_dummy_hw::init(void)
1118 class cl_mem *sfr= uc->mem(MEM_SFR);
1121 fprintf(stderr, "No SFR to register %s[%d] into\n", id_string, id);
1123 //acc= sfr->register_hw(ACC, this, 0);
1124 //sp = sfr->register_hw(SP , this, 0);
1125 use_cell(sfr, PSW, &cell_psw, wtd_restore);
1126 register_cell(sfr, ACC, &cell_acc, wtd_restore_write);
1127 register_cell(sfr, SP , &cell_sp , wtd_restore);
1132 cl_uc51_dummy_hw::write(class cl_cell *cell, t_mem *val)
1134 if (cell == cell_acc)
1142 for (i= 0; i < 8; i++)
1149 cell_psw->set_bit1(bmP);
1151 cell_psw->set_bit0(bmP);
1153 else if (cell == cell_sp)
1155 if (*val > uc->sp_max)
1157 uc->sp_avg= (uc->sp_avg+(*val))/2;
1162 cl_uc51_dummy_hw::happen(class cl_hw *where, enum hw_event he, void *params)
1164 struct ev_port_changed *ep= (struct ev_port_changed *)params;
1166 if (where->cathegory == HW_PORT &&
1167 he == EV_PORT_CHANGED &&
1170 t_mem p3o= ep->pins & ep->prev_value;
1171 t_mem p3n= ep->new_pins & ep->new_value;
1172 if ((p3o & bm_INT0) &&
1174 uc51->p3_int0_edge++;
1175 if ((p3o & bm_INT1) &&
1177 uc51->p3_int1_edge++;
1182 /* End of s51.src/uc51.cc */