📄 avr.cc
字号:
/* * Simulator of microcontrollers (avr.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 "i_string.h"// prj#include "pobjcl.h"// sim#include "simcl.h"#include "memcl.h"// local#include "portcl.h"#include "avrcl.h"#include "glob.h"#include "regsavr.h"/* * Base type of AVR microcontrollers */cl_avr::cl_avr(class cl_sim *asim): cl_uc(asim){ type= CPU_AVR; sleep_executed= 0;}intcl_avr::init(void){ cl_uc::init(); /* Memories now exist */ ram= address_space(MEM_IRAM_ID); rom= address_space(MEM_ROM_ID); return(0);}char *cl_avr::id_string(void){ return("unspecified AVR");}/* * Making elements of the controller *//*t_addrcl_avr::get_mem_size(enum mem_class type){ switch(type) { case MEM_ROM: return(8*1024); case MEM_IRAM: return(0x10000); default: return(0); } //return(0); //return(cl_uc::get_mem_size(type));}*//*intcl_avr::get_mem_width(enum mem_class type){ if (type == MEM_ROM) return(16); return(cl_uc::get_mem_width(type));}*/voidcl_avr::mk_hw_elements(void){ class cl_base *o; /* t_uc::mk_hw() does nothing */ hws->add(o= new cl_port(this)); o->init();}voidcl_avr::make_memories(void){ class cl_address_space *as; rom= as= new cl_address_space(MEM_ROM_ID, 0, 0x10000, 16); as->init(); address_spaces->add(as); ram= as= new cl_address_space(MEM_IRAM_ID, 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, 16); 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= ram/*address_space(MEM_IRAM_ID)*/, chip, 0, 0x7f, 0); ad->init(); as->decoders->add(ad); ad->activate(0);}/* * Help command interpreter */struct dis_entry *cl_avr::dis_tbl(void){ return(disass_avr);}struct name_entry *cl_avr::sfr_tbl(void){ return(sfr_tabl);}struct name_entry *cl_avr::bit_tbl(void){ //FIXME return(0);}char *cl_avr::disass(t_addr addr, char *sep){ char work[256], temp[20]; char *buf, *p, *b, *t; uint code, data= 0; int i; p= work; code= get_mem(MEM_ROM_ID, addr); i= 0; while ((code & dis_tbl()[i].mask) != dis_tbl()[i].code && dis_tbl()[i].mnemonic) i++; if (dis_tbl()[i].mnemonic == NULL) { buf= (char*)malloc(30); strcpy(buf, "UNKNOWN/INVALID"); return(buf); } b= dis_tbl()[i].mnemonic; while (*b) { if (*b == '%') { b++; switch (*(b++)) { case 'd': // Rd .... ...d dddd .... 0<=d<=31 if (!get_name(data= (code&0x01f0)>>4, sfr_tbl(), temp)) sprintf(temp, "r%d", data); break; case 'D': // Rd .... .... dddd .... 16<=d<=31 if (!get_name(data= 16+((code&0xf0)>>4), sfr_tbl(), temp)) sprintf(temp, "r%d", data); break; case 'K': // K .... KKKK .... KKKK 0<=K<=255 sprintf(temp, "%d", ((code&0xf00)>>4)|(code&0xf)); break; case 'r': // Rr .... ..r. .... rrrr 0<=r<=31 if (!get_name(data= ((code&0x0200)>>5)|(code&0x000f), sfr_tbl(), temp)) sprintf(temp, "r%d", data); break; case '2': // Rdl .... .... ..dd .... dl= {24,26,28,30} if (!get_name(data= 24+(2*((code&0x0030)>>4)), sfr_tbl(), temp)) sprintf(temp, "r%d", data); break; case '6': // K .... .... KK.. KKKK 0<=K<=63 sprintf(temp, "%d", ((code&0xc0)>>2)|(code&0xf)); break; case 's': // s .... .... .sss .... 0<=s<=7 sprintf(temp, "%d", (code&0x70)>>4); break; case 'b': // b .... .... .... .bbb 0<=b<=7 sprintf(temp, "%d", code&0x7); break; case 'k': // k .... ..kk kkkk k... -64<=k<=+63 { int k= (code&0x3f8)>>3; if (code&0x200) k|= -128; sprintf(temp, "0x%06x", k+1+(signed int)addr); break; } case 'A': // k .... ...k kkkk ...k 0<=k<=64K // kkkk kkkk kkkk kkkk 0<=k<=4M sprintf(temp, "0x%06x", (((code&0x1f0)>>3)|(code&1))*0x10000+ (uint)get_mem(MEM_ROM_ID, addr+1)); break; case 'P': // P .... .... pppp p... 0<=P<=31 data= (code&0xf8)>>3; if (!get_name(data+0x20, sfr_tbl(), temp)) sprintf(temp, "%d", data); break; case 'p': // P .... .PP. .... PPPP 0<=P<=63 data= ((code&0x600)>>5)|(code&0xf); if (!get_name(data+0x20, sfr_tbl(), temp)) sprintf(temp, "%d", data); break; case 'q': // q ..q. qq.. .... .qqq 0<=q<=63 sprintf(temp, "%d", ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&7)); break; case 'R': // k SRAM address on second word 0<=k<=65535 sprintf(temp, "0x%06x", (uint)get_mem(MEM_ROM_ID, addr+1)); break; case 'a': // k .... kkkk kkkk kkkk -2k<=k<=2k { int k= code&0xfff; if (code&0x800) k|= -4096; sprintf(temp, "0x%06"_A_"x", rom->validate_address(k+1+(signed int)addr)); 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_avr::print_regs(class cl_console *con){ uchar data, sreg= ram->get(SREG); uint x, y, z; ram->dump(0, 31, 16, con); con->dd_printf("ITHSVNZC SREG= 0x%02x %3d %c\n", sreg, sreg, isprint(sreg)?sreg:'.'); con->dd_printf("%c%c%c%c%c%c%c%c ", (sreg&BIT_I)?'1':'0', (sreg&BIT_T)?'1':'0', (sreg&BIT_H)?'1':'0', (sreg&BIT_S)?'1':'0', (sreg&BIT_V)?'1':'0', (sreg&BIT_N)?'1':'0', (sreg&BIT_Z)?'1':'0', (sreg&BIT_C)?'1':'0'); con->dd_printf("SP = 0x%06x\n", ram->get(SPH)*256+ram->get(SPL)); x= ram->get(XH)*256 + ram->get(XL); data= ram->get(x); con->dd_printf("X= 0x%04x [X]= 0x%02x %3d %c ", x, data, data, isprint(data)?data:'.'); y= ram->get(YH)*256 + ram->get(YL); data= ram->get(y); con->dd_printf("Y= 0x%04x [Y]= 0x%02x %3d %c ", y, data, data, isprint(data)?data:'.'); z= ram->get(ZH)*256 + ram->get(ZL); data= ram->get(z); con->dd_printf("Z= 0x%04x [Z]= 0x%02x %3d %c\n", z, data, data, isprint(data)?data:'.'); print_disass(PC, con);}/* * Execution */intcl_avr::exec_inst(void){ t_mem code; instPC= PC; if (fetch(&code)) return(resBREAKPOINT); tick(1); switch (code) { case 0x9419: return(eijmp(code)); case 0x9519: return(eicall(code)); case 0x9508: case 0x9528: case 0x9548: case 0x9568: return(ret(code)); case 0x9518: case 0x9538: case 0x9558: case 0x9578: return(reti(code)); case 0x95c8: return(lpm(code)); case 0x95d8: return(elpm(code)); // in some devices equal to lpm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -