⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uc51.cc

📁 Small Device C Compiler 面向Inter8051
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * 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"// sim#include "optioncl.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"/* * Making a new micro-controller and reset it */t_uc51::t_uc51(int Itype, int Itech, class cl_sim *asim):  cl_uc(asim){  //int i;  /*  struct termios tattr;  */    type= Itype;  technology= Itech;  debug= asim->app->args->get_iarg('V', 0);  stop_at_it= DD_FALSE;  /*class cl_option *opt;  options->add(opt= new cl_bool_opt("verbose", "Verbose flag."));  opt->init();  opt->set_value((bool)debug);  options->add(opt= new cl_bool_opt("stopit", "Stop if interrupt accepted."));  opt->init();  opt->set_value((bool)stop_at_it);  options->add(new cl_cons_debug_opt(asim->app, "debug",  "Debug messages appears on this console."));*/  /*  serial_in = (FILE*)asim->app->args->get_parg(0, "Ser_in");  serial_out= (FILE*)asim->app->args->get_parg(0, "Ser_out");  if (serial_in)    {      // making `serial' unbuffered      if (setvbuf(serial_in, NULL, _IONBF, 0))	perror("Unbuffer serial input channel");      // setting O_NONBLOCK      if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)	perror("Get flags of serial input");      i|= O_NONBLOCK;      if (fcntl(fileno(serial_in), F_SETFL, i) < 0)	perror("Set flags of serial input");      // switching terminal to noncanonical mode      if (isatty(fileno(serial_in)))	{	  tcgetattr(fileno(serial_in), &saved_attributes_in);	  tcgetattr(fileno(serial_in), &tattr);	  tattr.c_lflag&= ~(ICANON|ECHO);	  tattr.c_cc[VMIN] = 1;	  tattr.c_cc[VTIME]= 0;	  tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);	}      else	fprintf(stderr, "Warning: serial input interface connected to a "		"non-terminal file.\n");    }  if (serial_out)    {      // making `serial' unbuffered      if (setvbuf(serial_out, NULL, _IONBF, 0))	perror("Unbuffer serial output channel");      // setting O_NONBLOCK      if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)	perror("Get flags of serial output");      i|= O_NONBLOCK;      if (fcntl(fileno(serial_out), F_SETFL, i) < 0)	perror("Set flags of serial output");      // switching terminal to noncanonical mode      if (isatty(fileno(serial_out)))	{	  tcgetattr(fileno(serial_out), &saved_attributes_out);	  tcgetattr(fileno(serial_out), &tattr);	  tattr.c_lflag&= ~(ICANON|ECHO);	  tattr.c_cc[VMIN] = 1;	  tattr.c_cc[VTIME]= 0;	  tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);	}      else	fprintf(stderr, "Warning: serial output interface connected to a "		"non-terminal file.\n");    }  */  /*for (i= 0; i < 4; i++)    port_pins[i]= 0xff;*/  /*it_sources->add(new cl_it_src(bmEX0, TCON, bmIE0, 0x0003, true,    "external #0"));*/  /*it_sources->add(new cl_it_src(bmET0, TCON, bmTF0, 0x000b, true,    "timer #0"));*/  /*it_sources->add(new cl_it_src(bmEX1, TCON, bmIE1, 0x0013, true,    "external #1"));*/  /*it_sources->add(new cl_it_src(bmET1, TCON, bmTF1, 0x001b, true,    "timer #1"));*/  /*it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,				"serial transmit"));  it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,  "serial receive"));*/}/* * Initializing. Virtual calls go here * This method must be called first after object creation. */intt_uc51::init(void){  cl_uc::init();  reset();  return(0);}static char id_string_51[100];char *t_uc51::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);}voidt_uc51::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);  */}class cl_mem *t_uc51::mk_mem(enum mem_class type, char *class_name){  class cl_mem *m= cl_uc::mk_mem(type, class_name);  if (type == MEM_SFR)    sfr= m;  if (type == MEM_IRAM)    iram= m;  return(m);}/* * Destroying the micro-controller object */t_uc51::~t_uc51(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);    }  */}/* * Writing data to EROM */voidt_uc51::write_rom(t_addr addr, ulong data){  if (addr < EROM_SIZE)    set_mem(MEM_ROM, addr, data);}/* * Disassembling an instruction */struct dis_entry *t_uc51::dis_tbl(void){  return(disass_51);}struct name_entry *t_uc51::sfr_tbl(void){  return(sfr_tab51);}struct name_entry *t_uc51::bit_tbl(void){  return(bit_tab51);}char *t_uc51::disass(t_addr addr, char *sep){  char work[256], temp[20], c[2];  char *buf, *p, *b, *t;  t_mem code= get_mem(MEM_ROM, 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 +			      get_mem(MEM_ROM, addr+1))));	      break;	    case 'l': // long address	      sprintf(temp, "%04"_A_"x",		      t_addr(get_mem(MEM_ROM, addr+1)*256 +			     get_mem(MEM_ROM, addr+2)));	      break;	    case 'a': // addr8 (direct address) at 2nd byte 	      if (!get_name(get_mem(MEM_ROM, addr+1), sfr_tbl(), temp))		sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));	      break;	    case '8': // addr8 (direct address) at 3rd byte 	      if (!get_name(get_mem(MEM_ROM, addr+2), sfr_tbl(), temp))		sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));	      //sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));	      break;	    case 'b': // bitaddr at 2nd byte	      {		t_addr ba= get_mem(MEM_ROM, 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)(get_mem(MEM_ROM, addr+1))));	      break;	    case 'R': // rel8 address at 3rd byte	      sprintf(temp, "%04"_A_"x",		      t_addr(addr+3+(signed char)(get_mem(MEM_ROM, addr+2))));	      break;	    case 'd': // data8 at 2nd byte	      sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));	      break;	    case 'D': // data8 at 3rd byte	      sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));	      break;	    case '6': // data16 at 2nd(H)-3rd(L) byte	      sprintf(temp, "%04"_A_"x",		      t_addr(get_mem(MEM_ROM, addr+1)*256 +			     get_mem(MEM_ROM, 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);}voidt_uc51::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= get_mem(MEM_XRAM, 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_mem *t_uc51::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask){  class cl_mem *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);}/* * Resetting the micro-controller */voidt_uc51::reset(void){  cl_uc::reset();  clear_sfr();  result= resGO;  //was_reti= DD_FALSE;}/* * Setting up SFR area to reset value */voidt_uc51::clear_sfr(void){  int i;    for (i= 0; i < SFR_SIZE; 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);  sfr->/*set*/write(SP, 7);  prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1);  prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3);  sfr->set_nuof_writes(0);  sfr->set_nuof_reads(0);}/* * Analyzing code and settig up instruction map */voidt_uc51::analyze(t_addr addr){  uint code;  struct dis_entry *tabl;  code= get_mem(MEM_ROM, 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)|		  ((get_mem(MEM_ROM, addr+1)&0x07)*256+		   get_mem(MEM_ROM, addr+2)));	  analyze(addr+tabl->length);	  break;	case 'A': // ajmp	  addr= (addr & 0xf800)|	    ((get_mem(MEM_ROM, addr+1) & 0x07)*256 + get_mem(MEM_ROM, addr+2));	  break;	case 'l': // lcall	  analyze(get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));	  analyze(addr+tabl->length);	  break;	case 'L': // ljmp	  addr= get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2);	  break;	case 'r': // reljmp (2nd byte)	  analyze((addr + (signed char)(get_mem(MEM_ROM, addr+1))) &		  (EROM_SIZE - 1));	  analyze(addr+tabl->length);	  break;	case 'R': // reljmp (3rd byte)	  analyze((addr+		   (signed char)(get_mem(MEM_ROM, addr+2)))&(EROM_SIZE-1));	  analyze(addr+tabl->length);	  break;	case 's': // sjmp	  {	    signed char target;	    target= get_mem(MEM_ROM, addr+1);	    addr+= 2;	    addr= (addr+target)&(EROM_SIZE-1);	    break;	  }	case '_':	  return;	default:	  addr= (addr+tabl->length) & (EROM_SIZE - 1);	  break;	}      code= get_mem(MEM_ROM, addr);      tabl= &(dis_tbl()[code]);    }}/* * Inform hardware elements that `cycles' machine cycles have elapsed *//*intt_uc51::tick_hw(int cycles){  cl_uc::tick_hw(cycles);  //do_hardware(cycles);  return(0);}*//*intt_uc51::tick(int cycles){  cl_uc::tick(cycles);  //do_hardware(cycles);  return(0);}*//* * Correcting direct address * * This function returns address of addressed element which can be an IRAM * or an SFR. */class cl_cell *t_uc51::get_direct(t_mem addr){  if (addr < SFR_START)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -