📄 uc51.cc
字号:
/* * Simulator of microcontrollers (uc51.cc) * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * *//* This file is part of microcontroller simulator: ucsim.UCSIM is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.UCSIM is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with UCSIM; see the file COPYING. If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. *//*@1@*/#include "ddconfig.h"#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <termios.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/time.h>#if FD_HEADER_OK# include HEADER_FD#endif#include "i_string.h"// prj#include "utils.h"#include "globals.h"// sim#include "optioncl.h"//cmd.src#include "cmduccl.h"// local#include "uc51cl.h"#include "glob.h"#include "regs51.h"#include "timer0cl.h"#include "timer1cl.h"#include "serialcl.h"#include "portcl.h"#include "interruptcl.h"#include "types51.h"/* * Options of uc51 */cl_irq_stop_option::cl_irq_stop_option(class cl_51core *the_uc51): cl_optref(the_uc51){ uc51= the_uc51;}intcl_irq_stop_option::init(void){ cl_optref::init(); create(uc51, bool_opt, "irq_stop", "Stop when IRQ accepted"); return(0);}voidcl_irq_stop_option::option_changed(void){ if (!uc51) return; bool b; option->get_value(&b); uc51->stop_at_it= b;}/* * Making a new micro-controller and reset it */cl_51core::cl_51core(int Itype, int Itech, class cl_sim *asim): cl_uc(asim){ type= Itype; technology= Itech; irq_stop_option= new cl_irq_stop_option(this); stop_at_it= DD_FALSE;}/* * Initializing. Virtual calls go here * This method must be called first after object creation. */intcl_51core::init(void){ irq_stop_option->init(); cl_uc::init(); set_name("mcs51_controller"); reset(); return(0);}static char id_string_51[100];char *cl_51core::id_string(void){ int i; for (i= 0; cpus_51[i].type_str != NULL && cpus_51[i].type != type; i++) ; sprintf(id_string_51, "%s %s", cpus_51[i].type_str?cpus_51[i].type_str:"51", (technology==CPU_HMOS)?"HMOS":"CMOS"); return(id_string_51);}voidcl_51core::mk_hw_elements(void){ class cl_hw *h; acc= sfr->get_cell(ACC); psw= sfr->get_cell(PSW); hws->add(h= new cl_timer0(this, 0, "timer0")); h->init(); hws->add(h= new cl_timer1(this, 1, "timer1")); h->init(); hws->add(h= new cl_serial(this)); h->init(); hws->add(h= new cl_port(this, 0)); h->init(); hws->add(h= new cl_port(this, 1)); h->init(); hws->add(h= new cl_port(this, 2)); h->init(); hws->add(h= new cl_port(this, 3)); h->init(); hws->add(interrupt= new cl_interrupt(this)); interrupt->init(); hws->add(h= new cl_uc51_dummy_hw(this)); h->init(); /* acc= sfr->get_cell(ACC); psw= sfr->get_cell(PSW); */}voidcl_51core::build_cmdset(class cl_cmdset *cmdset){ class cl_cmd *cmd; //class cl_super_cmd *super_cmd; //class cl_cmdset *cset; cl_uc::build_cmdset(cmdset); cmdset->add(cmd= new cl_di_cmd("di", DD_TRUE,"di [start [stop]] Dump Internal RAM","long help of di")); cmd->init(); cmdset->add(cmd= new cl_dx_cmd("dx", DD_TRUE,"dx [start [stop]] Dump External RAM","long help of dx")); cmd->init(); cmdset->add(cmd= new cl_ds_cmd("ds", DD_TRUE,"ds [start [stop]] Dump SFR","long help of ds")); cmd->init();}/*class cl_m *cl_51core::mk_mem(enum mem_class type, char *class_name){ class cl_address_space *m= cl_uc::mk_mem(type, class_name); if (type == MEM_SFR) sfr= m; if (type == MEM_IRAM) iram= m; return(m);}*/voidcl_51core::make_memories(void){ class cl_address_space *as; rom= as= new cl_address_space(MEM_ROM_ID/*"rom"*/, 0, 0x10000, 8); as->init(); address_spaces->add(as); iram= as= new cl_address_space(MEM_IRAM_ID/*"iram"*/, 0, 0x80, 8); as->init(); address_spaces->add(as); sfr= as= new cl_address_space(MEM_SFR_ID/*"sfr"*/, 0x80, 0x80, 8); as->init(); address_spaces->add(as); xram= as= new cl_address_space(MEM_XRAM_ID/*"xram"*/, 0, 0x10000, 8); as->init(); address_spaces->add(as); class cl_address_decoder *ad; class cl_memory_chip *chip; chip= new cl_memory_chip("rom_chip", 0x10000, 8/*, 0xff*/); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= rom/*address_space(MEM_ROM_ID)*/, chip, 0, 0xffff, 0); ad->init(); as->decoders->add(ad); ad->activate(0); chip= new cl_memory_chip("iram_chip", 0x80, 8); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= iram/*address_space(MEM_IRAM_ID)*/, chip, 0, 0x7f, 0); ad->init(); as->decoders->add(ad); ad->activate(0); chip= new cl_memory_chip("xram_chip", 0x10000, 8); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= xram/*address_space(MEM_XRAM_ID)*/, chip, 0, 0xffff, 0); ad->init(); as->decoders->add(ad); ad->activate(0); chip= new cl_memory_chip("sfr_chip", 0x80, 8, 0); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= sfr/*address_space(MEM_SFR_ID)*/, chip, 0x80, 0xff, 0); ad->init(); as->decoders->add(ad); ad->activate(0); acc= sfr->get_cell(ACC); psw= sfr->get_cell(PSW);}/* * Destroying the micro-controller object */cl_51core::~cl_51core(void){ /* if (serial_out) { if (isatty(fileno(serial_out))) tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out); fclose(serial_out); } if (serial_in) { if (isatty(fileno(serial_in))) tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in); fclose(serial_in); } */ delete irq_stop_option;}/* * Disassembling an instruction */struct dis_entry *cl_51core::dis_tbl(void){ return(disass_51);}struct name_entry *cl_51core::sfr_tbl(void){ return(sfr_tab51);}struct name_entry *cl_51core::bit_tbl(void){ return(bit_tab51);}char *cl_51core::disass(t_addr addr, char *sep){ char work[256], temp[20], c[2]; char *buf, *p, *b, *t; t_mem code= rom->get(addr); p= work; b= dis_tbl()[code].mnemonic; while (*b) { if (*b == '%') { b++; switch (*(b++)) { case 'A': // absolute address sprintf(temp, "%04"_A_"x", t_addr((addr&0xf800)| (((code>>5)&0x07)*256 + rom->get(addr+1)))); break; case 'l': // long address sprintf(temp, "%04"_A_"x", t_addr(rom->get(addr+1)*256 + rom->get(addr+2))); break; case 'a': // addr8 (direct address) at 2nd byte if (!get_name(rom->get(addr+1), sfr_tbl(), temp)) sprintf(temp, "%02"_M_"x", rom->get(addr+1)); break; case '8': // addr8 (direct address) at 3rd byte if (!get_name(rom->get(addr+2), sfr_tbl(), temp)) sprintf(temp, "%02"_M_"x", rom->get(addr+2)); //sprintf(temp, "%02"_M_"x", rom->get(addr+2)); break; case 'b': // bitaddr at 2nd byte { t_addr ba= rom->get(addr+1); if (get_name(ba, bit_tbl(), temp)) break; if (get_name((ba<128)?((ba/8)+32):(ba&0xf8), sfr_tbl(), temp)) { strcat(temp, "."); sprintf(c, "%1"_M_"d", ba & 0x07); strcat(temp, c); break; } sprintf(temp, "%02x.%"_M_"d", (ba<128)?((ba/8)+32):(ba&0xf8), ba & 0x07); break; } case 'r': // rel8 address at 2nd byte sprintf(temp, "%04"_A_"x", t_addr(addr+2+(signed char)(rom->get(addr+1)))); break; case 'R': // rel8 address at 3rd byte sprintf(temp, "%04"_A_"x", t_addr(addr+3+(signed char)(rom->get(addr+2)))); break; case 'd': // data8 at 2nd byte sprintf(temp, "%02"_M_"x", rom->get(addr+1)); break; case 'D': // data8 at 3rd byte sprintf(temp, "%02"_M_"x", rom->get(addr+2)); break; case '6': // data16 at 2nd(H)-3rd(L) byte sprintf(temp, "%04"_A_"x", t_addr(rom->get(addr+1)*256 + rom->get(addr+2))); break; default: strcpy(temp, "?"); break; } t= temp; while (*t) *(p++)= *(t++); } else *(p++)= *(b++); } *p= '\0'; p= strchr(work, ' '); if (!p) { buf= strdup(work); return(buf); } if (sep == NULL) buf= (char *)malloc(6+strlen(p)+1); else buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1); for (p= work, b= buf; *p != ' '; p++, b++) *b= *p; p++; *b= '\0'; if (sep == NULL) { while (strlen(buf) < 6) strcat(buf, " "); } else strcat(buf, sep); strcat(buf, p); return(buf);}voidcl_51core::print_regs(class cl_console *con){ t_addr start; uchar data; start= psw->get() & 0x18; //dump_memory(iram, &start, start+7, 8, /*sim->cmd_out()*/con, sim); iram->dump(start, start+7, 8, con); start= psw->get() & 0x18; data= iram->get(iram->get(start)); con->dd_printf("%06x %02x %c", iram->get(start), data, isprint(data)?data:'.'); con->dd_printf(" ACC= 0x%02x %3d %c B= 0x%02x", sfr->get(ACC), sfr->get(ACC), isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); //eram2xram(); data= xram->get(sfr->get(DPH)*256+sfr->get(DPL)); con->dd_printf(" DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH), sfr->get(DPL), data, data, isprint(data)?data:'.'); data= iram->get(iram->get(start+1)); con->dd_printf("%06x %02x %c", iram->get(start+1), data, isprint(data)?data:'.'); data= psw->get(); con->dd_printf(" PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data, (data&bmCY)?'1':'0', (data&bmAC)?'1':'0', (data&bmOV)?'1':'0', (data&bmP)?'1':'0'); print_disass(PC, con);}/* * Converting bit address into real memory */class cl_address_space *cl_51core::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask){ class cl_address_space *m; t_addr ma; bitaddr&= 0xff; if (bitaddr < 128) { m= iram; ma= bitaddr/8 + 0x20; } else { m= sfr; ma= bitaddr & 0xf8; } if (memaddr) *memaddr= ma; if (bitmask) *bitmask= 1 << (bitaddr & 0x7); return(m);}t_addrcl_51core::bit_address(class cl_memory *mem, t_addr mem_address, int bit_number){ if (bit_number < 0 || bit_number > 7 || mem_address < 0) return(-1); class cl_memory *sfrchip= memory("sfr_chip"); if (mem == sfrchip) { mem= sfr; mem_address+= sfr->start_address; } if (mem == sfr) { if (mem_address < 128 || mem_address % 8 != 0 || mem_address > 255) return(-1); return(128 + (mem_address-128) + bit_number); } if (mem == iram) { if (mem_address < 0x20 || mem_address >= 0x20+32) return(-1); return((mem_address-0x20)*8 + bit_number); } return(-1);}/* * Resetting the micro-controller */voidcl_51core::reset(void){ cl_uc::reset(); clear_sfr(); result= resGO; //was_reti= DD_FALSE;}/* * Setting up SFR area to reset value */voidcl_51core::clear_sfr(void){ int i; for (i= 0x80; i <= 0xff; i++) sfr->set(i, 0); sfr->/*set*/write(P0, 0xff); sfr->/*set*/write(P1, 0xff); sfr->/*set*/write(P2, 0xff); sfr->/*set*/write(P3, 0xff); prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1); prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3); sfr->write(ACC, 0); sfr->write(B, 0); sfr->write(PSW, 0); sfr->write(SP, 7); sfr->write(DPL, 0); sfr->write(DPH, 0); sfr->write(IP, 0); sfr->write(IE, 0); sfr->write(TMOD, 0); sfr->write(TCON, 0); sfr->write(TH0, 0); sfr->write(TL0, 0); sfr->write(TH1, 0); sfr->write(TL1, 0); sfr->write(SCON, 0); sfr->write(PCON, 0); sfr->set_nuof_writes(0); sfr->set_nuof_reads(0);}/* * Analyzing code and settig up instruction map */voidcl_51core::analyze(t_addr addr){ uint code; struct dis_entry *tabl; code= rom->get(addr); tabl= &(dis_tbl()[code]); while (!inst_at(addr) && code != 0xa5 /* break point */) { set_inst_at(addr); switch (tabl->branch) { case 'a': // acall analyze((addr & 0xf800)| ((rom->get(addr+1)&0x07)*256+ rom->get(addr+2))); analyze(addr+tabl->length); break; case 'A': // ajmp addr= (addr & 0xf800)| ((rom->get(addr+1) & 0x07)*256 + rom->get(addr+2)); break; case 'l': // lcall analyze(rom->get(addr+1)*256 + rom->get(addr+2)); analyze(addr+tabl->length); break; case 'L': // ljmp addr= rom->get(addr+1)*256 + rom->get(addr+2); break; case 'r': // reljmp (2nd byte) analyze(rom->validate_address(addr+(signed char)(rom->get(addr+1)))); analyze(addr+tabl->length); break; case 'R': // reljmp (3rd byte) analyze(rom->validate_address(addr+(signed char)(rom->get(addr+2)))); analyze(addr+tabl->length); break; case 's': // sjmp { signed char target; target= rom->get(addr+1); addr+= 2; addr= rom->validate_address(addr+target); break; } case '_': return; default: addr= rom->validate_address(addr+tabl->length); break; } code= rom->get(addr); tabl= &(dis_tbl()[code]); }}/* * Inform hardware elements that `cycles' machine cycles have elapsed *//*intcl_51core::tick_hw(int cycles){ cl_uc::tick_hw(cycles); //do_hardware(cycles);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -