📄 uc51.cc
字号:
return(iram->get_cell(addr)); else return(sfr->get_cell(addr));}/* * Calculating address of specified register cell in IRAM */class cl_cell *t_uc51::get_reg(uchar regnum){ t_addr a= (psw->get() & (bmRS0|bmRS1)) | (regnum & 0x07); return(iram->get_cell(a));}/* * Fetching one instruction and executing it */intt_uc51::exec_inst(void){ t_mem code; int res; //pr_inst(); instPC= PC; if (fetch(&code)) return(resBREAKPOINT); //tick_hw(1); tick(1); switch (code) { case 0x00: res= inst_nop(code); break; case 0x01: case 0x21: case 0x41: case 0x61: case 0x81: case 0xa1: case 0xc1: case 0xe1:res=inst_ajmp_addr(code);break; case 0x02: res= inst_ljmp(code); break; case 0x03: res= inst_rr(code); break; case 0x04: res= inst_inc_a(code); break; case 0x05: res= inst_inc_addr(code); break; case 0x06: case 0x07: res= inst_inc_Sri(code); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: res= inst_inc_rn(code); break; case 0x10: res= inst_jbc_bit_addr(code); break; case 0x11: case 0x31: case 0x51: case 0x71: case 0x91: case 0xb1: case 0xd1: case 0xf1:res=inst_acall_addr(code);break; case 0x12: res= inst_lcall(code, 0); break; case 0x13: res= inst_rrc(code); break; case 0x14: res= inst_dec_a(code); break; case 0x15: res= inst_dec_addr(code); break; case 0x16: case 0x17: res= inst_dec_Sri(code); break; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: res= inst_dec_rn(code); break; case 0x20: res= inst_jb_bit_addr(code); break; case 0x22: res= inst_ret(code); break; case 0x23: res= inst_rl(code); break; case 0x24: res= inst_add_a_Sdata(code); break; case 0x25: res= inst_add_a_addr(code); break; case 0x26: case 0x27: res= inst_add_a_Sri(code); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:res= inst_add_a_rn(code);break; case 0x30: res= inst_jnb_bit_addr(code); break; case 0x32: res= inst_reti(code); break; case 0x33: res= inst_rlc(code); break; case 0x34: res= inst_addc_a_Sdata(code); break; case 0x35: res= inst_addc_a_addr(code); break; case 0x36: case 0x37: res= inst_addc_a_Sri(code); break; case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:res= inst_addc_a_rn(code);break; case 0x40: res= inst_jc_addr(code); break; case 0x42: res= inst_orl_addr_a(code); break; case 0x43: res= inst_orl_addr_Sdata(code); break; case 0x44: res= inst_orl_a_Sdata(code); break; case 0x45: res= inst_orl_a_addr(code); break; case 0x46: case 0x47: res= inst_orl_a_Sri(code); break; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: res= inst_orl_a_rn(code);break; case 0x50: res= inst_jnc_addr(code); break; case 0x52: res= inst_anl_addr_a(code); break; case 0x53: res= inst_anl_addr_Sdata(code); break; case 0x54: res= inst_anl_a_Sdata(code); break; case 0x55: res= inst_anl_a_addr(code); break; case 0x56: case 0x57: res= inst_anl_a_Sri(code); break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: res= inst_anl_a_rn(code);break; case 0x60: res= inst_jz_addr(code); break; case 0x62: res= inst_xrl_addr_a(code); break; case 0x63: res= inst_xrl_addr_Sdata(code); break; case 0x64: res= inst_xrl_a_Sdata(code); break; case 0x65: res= inst_xrl_a_addr(code); break; case 0x66: case 0x67: res= inst_xrl_a_Sri(code); break; case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: res= inst_xrl_a_rn(code);break; case 0x70: res= inst_jnz_addr(code); break; case 0x72: res= inst_orl_c_bit(code); break; case 0x73: res= inst_jmp_Sa_dptr(code); break; case 0x74: res= inst_mov_a_Sdata(code); break; case 0x75: res= inst_mov_addr_Sdata(code); break; case 0x76: case 0x77: res= inst_mov_Sri_Sdata(code); break; case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_Sdata(code); break; case 0x80: res= inst_sjmp(code); break; case 0x82: res= inst_anl_c_bit(code); break; case 0x83: res= inst_movc_a_Sa_pc(code); break; case 0x84: res= inst_div_ab(code); break; case 0x85: res= inst_mov_addr_addr(code); break; case 0x86: case 0x87: res= inst_mov_addr_Sri(code); break; case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:res=inst_mov_addr_rn(code);break; case 0x90: res= inst_mov_dptr_Sdata(code); break; case 0x92: res= inst_mov_bit_c(code); break; case 0x93: res= inst_movc_a_Sa_dptr(code); break; case 0x94: res= inst_subb_a_Sdata(code); break; case 0x95: res= inst_subb_a_addr(code); break; case 0x96: case 0x97: res= inst_subb_a_Sri(code); break; case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:res= inst_subb_a_rn(code);break; case 0xa2: res= inst_mov_c_bit(code); break; case 0xa3: res= inst_inc_dptr(code); break; case 0xa4: res= inst_mul_ab(code); break; case 0xa5: res= inst_unknown(code); break; case 0xa6: case 0xa7: res= inst_mov_Sri_addr(code); break; case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:res=inst_mov_rn_addr(code);break; case 0xb0: res= inst_anl_c_Sbit(code); break; case 0xb2: res= inst_cpl_bit(code); break; case 0xb3: res= inst_cpl_c(code); break; case 0xb4: res= inst_cjne_a_Sdata_addr(code); break; case 0xb5: res= inst_cjne_a_addr_addr(code); break; case 0xb6: case 0xb7: res= inst_cjne_Sri_Sdata_addr(code); break; case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_Sdata_addr(code); break; case 0xc0: res= inst_push(code); break; case 0xc2: res= inst_clr_bit(code); break; case 0xc3: res= inst_clr_c(code); break; case 0xc4: res= inst_swap(code); break; case 0xc5: res= inst_xch_a_addr(code); break; case 0xc6: case 0xc7: res= inst_xch_a_Sri(code); break; case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: res= inst_xch_a_rn(code);break; case 0xd0: res= inst_pop(code); break; case 0xd2: res= inst_setb_bit(code); break; case 0xd3: res= inst_setb_c(code); break; case 0xd4: res= inst_da_a(code); break; case 0xd5: res= inst_djnz_addr_addr(code); break; case 0xd6: case 0xd7: res= inst_xchd_a_Sri(code); break; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: res=inst_djnz_rn_addr(code); break; case 0xe0: res= inst_movx_a_Sdptr(code); break; case 0xe2: case 0xe3: res= inst_movx_a_Sri(code); break; case 0xe4: res= inst_clr_a(code); break; case 0xe5: res= inst_mov_a_addr(code); break; case 0xe6: case 0xe7: res= inst_mov_a_Sri(code); break; case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: res= inst_mov_a_rn(code);break; case 0xf0: res= inst_movx_Sdptr_a(code); break; case 0xf2: case 0xf3: res= inst_movx_Sri_a(code); break; case 0xf4: res= inst_cpl_a(code); break; case 0xf5: res= inst_mov_addr_a(code); break; case 0xf6: case 0xf7: res= inst_mov_Sri_a(code); break; case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: res= inst_mov_rn_a(code);break; default: res= inst_unknown(code); break; } //post_inst(); return(res);}/* * Simulating execution of next instruction * * This is an endless loop if requested number of steps is negative. * In this case execution is stopped if an instruction results other * status than GO. Execution can be stopped if `cmd_in' is not NULL * and there is input available on that file. It is usefull if the * command console is on a terminal. If input is available then a * complete line is read and dropped out because input is buffered * (inp_avail will be TRUE if ENTER is pressed) and it can confuse * command interepter. */intt_uc51::do_inst(int step){ result= resGO; while ((result == resGO) && (state != stPD) && (step != 0)) { if (step > 0) step--; if (state == stGO) { interrupt->was_reti= DD_FALSE; pre_inst(); result= exec_inst(); post_inst(); /*if (result == resGO) result= check_events();*/ } else { // tick hw in idle state post_inst(); tick(1); } if (result == resGO) { int res; if ((res= do_interrupt()) != resGO) result= res; else result= idle_pd(); } if ((step < 0) && ((ticks->ticks % 100000) < 50)) { if (sim->app->get_commander()->input_avail_on_frozen()) { result= resUSER; } else if (sim->app->get_commander()->input_avail()) break; } if (((result == resINTERRUPT) && stop_at_it) || result >= resSTOP) { sim->stop(result); break; } } if (state == stPD) { //FIXME: tick outsiders eg. watchdog if (sim->app->get_commander()->input_avail_on_frozen()) { //fprintf(stderr,"uc: inp avail in PD mode, user stop\n"); result= resUSER; sim->stop(result); } } return(result);}/*voidt_uc51::post_inst(void){*/ //uint tcon= sfr->get(TCON); //uint p3= sfr->read(P3); //cl_uc::post_inst(); //set_p_flag(); // Setting up external interrupt request bits (IEx) /*if ((tcon & bmIT0)) { // IE0 edge triggered if (p3_int0_edge) { // falling edge on INT0 sim->app->get_commander()-> debug("%g sec (%d clks): Falling edge detected on INT0 (P3.2)\n", get_rtime(), ticks->ticks); sfr->set_bit1(TCON, bmIE0); p3_int0_edge= 0; } } else { // IE0 level triggered if (p3 & bm_INT0) sfr->set_bit0(TCON, bmIE0); else sfr->set_bit1(TCON, bmIE0); } if ((tcon & bmIT1)) { // IE1 edge triggered if (p3_int1_edge) { // falling edge on INT1 sfr->set_bit1(TCON, bmIE1); p3_int1_edge= 0; } } else { // IE1 level triggered if (p3 & bm_INT1) sfr->set_bit0(TCON, bmIE1); else sfr->set_bit1(TCON, bmIE1); }*/ //prev_p3= p3 & port_pins[3]; //prev_p1= p3 & port_pins[1];//}/* * Abstract method to handle WDT *//*intt_uc51::do_wdt(int cycles){ return(resGO);}*//* * Checking for interrupt requests and accept one if needed */intt_uc51::do_interrupt(void){ int i, ie= 0; if (interrupt->was_reti) { interrupt->was_reti= DD_FALSE; return(resGO); } if (!((ie= sfr->get(IE)) & bmEA)) return(resGO); class it_level *il= (class it_level *)(it_levels->top()), *IL= 0; for (i= 0; i < it_sources->count; i++) { class cl_it_src *is= (class cl_it_src *)(it_sources->at(i)); if (is->is_active() && (ie & is->ie_mask) && (sfr->get(is->src_reg) & is->src_mask)) { int pr= it_priority(is->ie_mask); if (il->level >= 0 && pr <= il->level) continue; if (state == stIDLE) { state= stGO; sfr->set_bit0(PCON, bmIDL); interrupt->was_reti= DD_TRUE; return(resGO); } if (is->clr_bit) sfr->set_bit0(is->src_reg, is->src_mask); sim->app->get_commander()-> debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n", get_rtime(), ticks->ticks, object_name(is), PC); IL= new it_level(pr, is->addr, PC, is); return(accept_it(IL)); } } return(resGO);}intt_uc51::it_priority(uchar ie_mask){ if (sfr->get(IP) & ie_mask) return(1); return(0);}/* * Accept an interrupt */intt_uc51::accept_it(class it_level *il){ state= stGO; sfr->set_bit0(PCON, bmIDL); it_levels->push(il); tick(1); int res= inst_lcall(0, il->addr); if (res != resGO) return(res); else return(resINTERRUPT);}/* * Checking if Idle or PowerDown mode should be activated */intt_uc51::idle_pd(void){ uint pcon= sfr->get(PCON); if (technology != CPU_CMOS) return(resGO); if (pcon & bmIDL) { if (state != stIDLE) sim->app->get_commander()-> debug("%g sec (%d clks): CPU in Idle mode\n", get_rtime(), ticks->ticks); state= stIDLE; //was_reti= 1; } if (pcon & bmPD) { if (state != stPD) sim->app->get_commander()-> debug("%g sec (%d clks): CPU in PowerDown mode\n", get_rtime(), ticks->ticks); state= stPD; } return(resGO);}/* * Checking if EVENT break happened *//*intt_uc51::check_events(void){ int i; class cl_ev_brk *eb; if (!ebrk->count) return(resGO); for (i= 0; i < ebrk->count; i++) { eb= (class cl_ev_brk *)(ebrk->at(i)); if (eb->match(&event_at)) return(resBREAKPOINT); } return(resGO);}*//* */voidt_uc51::mem_cell_changed(class cl_mem *mem, t_addr addr){ if (mem == sfr) switch (addr) { case ACC: acc= mem->get_cell(ACC); break; case PSW: psw= mem->get_cell(PSW); break; } cl_uc::mem_cell_changed(mem, addr);}/* * Simulating an unknown instruction * * Normally this function is called for unimplemented instructions, because * every instruction must be known! */intt_uc51::inst_unknown(uchar code){ PC--; if (1)//debug)// && sim->cmd_out()) sim->app->get_commander()-> debug("Unknown instruction %02x at %06x\n", code, PC); return(resHALT);}/* * 0x00 1 12 NOP */intt_uc51::inst_nop(uchar code){ return(resGO);}/* * 0xe4 1 12 CLR A */intt_uc51::inst_clr_a(uchar code){ acc->write(0); return(resGO);}/* * 0xc4 1 1 SWAP A */intt_uc51::inst_swap(uchar code){ uchar temp; temp= (acc->read() >> 4) & 0x0f; sfr->write(ACC, (acc->get() << 4) | temp); return(resGO);}/* */cl_uc51_dummy_hw::cl_uc51_dummy_hw(class cl_uc *auc): cl_hw(auc, HW_DUMMY, 0, "_51_dummy"){ //uc51= (class t_uc51 *)uc;}intcl_uc51_dummy_hw::init(void){ class cl_mem *sfr= uc->mem(MEM_SFR); if (!sfr) { fprintf(stderr, "No SFR to register %s[%d] into\n", id_string, id); } //acc= sfr->register_hw(ACC, this, 0); //sp = sfr->register_hw(SP , this, 0); use_cell(sfr, PSW, &cell_psw, wtd_restore); register_cell(sfr, ACC, &cell_acc, wtd_restore_write); register_cell(sfr, SP , &cell_sp , wtd_restore); return(0);}voidcl_uc51_dummy_hw::write(class cl_cell *cell, t_mem *val){ if (cell == cell_acc) { bool p; int i; uchar uc; p = DD_FALSE; uc= *val; for (i= 0; i < 8; i++) { if (uc & 1) p= !p; uc>>= 1; } if (p) cell_psw->set_bit1(bmP); else cell_psw->set_bit0(bmP); } else if (cell == cell_sp) { if (*val > uc->sp_max) uc->sp_max= *val; uc->sp_avg= (uc->sp_avg+(*val))/2; }}/*voidcl_uc51_dummy_hw::happen(class cl_hw *where, enum hw_event he, void *params){ struct ev_port_changed *ep= (struct ev_port_changed *)params; if (where->cathegory == HW_PORT && he == EV_PORT_CHANGED && ep->id == 3) { t_mem p3o= ep->pins & ep->prev_value; t_mem p3n= ep->new_pins & ep->new_value; if ((p3o & bm_INT0) && !(p3n & bm_INT0)) uc51->p3_int0_edge++; if ((p3o & bm_INT1) && !(p3n & bm_INT1)) uc51->p3_int1_edge++; }}*//* End of s51.src/uc51.cc */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -