📄 xa.cc
字号:
/* * Simulator of microcontrollers (xa.cc) * * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt. * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * Other contributors include: * Karl Bongers karl@turbobit.com, * Johan Knol johan.knol@iduna.nl *//* 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"// local#include "xacl.h"#include "glob.h"#include "regsxa.h"/* * Base type of xa controllers */cl_xa::cl_xa(class cl_sim *asim): cl_uc(asim){ type= CPU_XA;}intcl_xa::init(void){ cl_uc::init(); /* Memories now exist */ ram= address_space(MEM_XRAM_ID); rom= address_space(MEM_ROM_ID); /* set SCR to osc/4, native XA mode, flat 24 */ set_scr(0); /* initialize SP to 100H */ set_reg2(7, 0x100); /* set PSW from reset vector */ set_psw(getcode2(0)); /* set PC from reset vector */ PC = getcode2(2); printf("The XA Simulator is in development, UNSTABLE, DEVELOPERS ONLY!\n"); return(0);}/*class cl_m *cl_xa::mk_mem(enum mem_class type, char *class_name){ class cl_m *m= cl_uc::mk_mem(type, class_name); if (type == MEM_SFR) sfr= m; if (type == MEM_IRAM) iram= m; return(m);}*/char *cl_xa::id_string(void){ return("unspecified XA");}/* * Making elements of the controller *//*t_addrcl_xa::get_mem_size(enum mem_class type){ switch(type) { case MEM_IRAM: return(0x2000); case MEM_SFR: return(0x2000); case MEM_ROM: return(0x10000); case MEM_XRAM: return(0x10000); default: return(0); } return(cl_uc::get_mem_size(type));}*/voidcl_xa::mk_hw_elements(void){ //class cl_base *o; /* t_uc::mk_hw() does nothing */}voidcl_xa::make_memories(void){ class cl_address_space *as; as= rom= new cl_address_space("rom", 0, 0x10000, 8); as->init(); address_spaces->add(as); as= iram= new cl_address_space("iram", 0, 0x2000, 8); as->init(); address_spaces->add(as); as= sfr= new cl_address_space("sfr", 0x0, 0x2000, 8); as->init(); address_spaces->add(as); as= ram= new cl_address_space("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); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= address_space("rom"), chip, 0, 0xffff, 0); ad->init(); as->decoders->add(ad); ad->activate(0); chip= new cl_memory_chip("iram_chip", 0x2000, 8); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= address_space("iram"), chip, 0, 0x1fff, 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= address_space("xram"), chip, 0, 0xffff, 0); ad->init(); as->decoders->add(ad); ad->activate(0); chip= new cl_memory_chip("sfr_chip", 0x2000, 8); chip->init(); memchips->add(chip); ad= new cl_address_decoder(as= address_space("sfr"), chip, 0x0, 0x1fff, 0); ad->init(); as->decoders->add(ad); ad->activate(0);}/* * Help command interpreter */struct dis_entry *cl_xa::dis_tbl(void){ // this should be unused, we need to make main prog code // independent of any array thing. printf("ERROR - Using disass[] table in XA sim code!\n"); return(glob_disass_xa);}struct name_entry *cl_xa::sfr_tbl(void){ return(sfr_tabXA51);}struct name_entry *cl_xa::bit_tbl(void){ return(bit_tabXA51);}intcl_xa::inst_length(t_addr addr){ int len = 0; get_disasm_info(addr, &len, NULL, NULL, NULL, NULL); return len;}intcl_xa::inst_branch(t_addr addr){ int b; get_disasm_info(addr, NULL, &b, NULL, NULL, NULL); return b;}intcl_xa::longest_inst(void){ return 6;}static char dir_name[64];char *cl_xa::get_dir_name(short addr) { if (!get_name(addr, sfr_tbl(), dir_name)) { sprintf (dir_name, "0x%03x", addr); } return dir_name;}static char bit_name[64];char *cl_xa::get_bit_name(short addr) { if (!get_name(addr, bit_tbl(), bit_name)) { sprintf (bit_name, "0x%03x", addr); } return bit_name;}/*--------------------------------------------------------------------get_disasm_info - Given an address, return information about the opcode which resides there. addr - address of opcode we want information on. ret_len - return length of opcode. ret_branch - return a character which indicates if we are a branching opcode. Used by main app to implement "Next" function which steps over functions. immed_offset - return a number which represents the number of bytes offset to where any immediate data is(tail end of opcode). Used for printing disassembly. operands - return a key indicating the form of the operands, used for printing the disassembly. mnemonic - return a key indicating the mnemonic of the instruction. Return value: Return the operand code formed by either the single byte opcode or 2 bytes of the opcode for multi-byte opcodes. Note: Any of the return pointer parameters can be set to NULL to indicate the caller does not want the information.|--------------------------------------------------------------------*/intcl_xa::get_disasm_info(t_addr addr, int *ret_len, int *ret_branch, int *immed_offset, int *parms, int *mnemonic){ uint code; int len = 0; int immed_n = 0; int i; int start_addr = addr; code= get_mem(MEM_ROM_ID, addr++); if (code == 0x00) { i= 0; while (disass_xa[i].mnemonic != NOP) i++; } else { len = 2; code = (code << 8) | get_mem(MEM_ROM_ID, addr++); i= 0; while ((code & disass_xa[i].mask) != disass_xa[i].code && disass_xa[i].mnemonic != BAD_OPCODE) i++; } if (ret_len) *ret_len = disass_xa[i].length; if (ret_branch) *ret_branch = disass_xa[i].branch; if (immed_offset) { if (immed_n > 0) *immed_offset = immed_n; else *immed_offset = (addr - start_addr); } if (parms) { *parms = disass_xa[i].operands; } if (mnemonic) { *mnemonic = disass_xa[i].mnemonic; } return code;}static char *w_reg_strs[] = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};static char *b_reg_strs[] = { "R0l", "R0h", "R1l", "R1h", "R2l", "R2h", "R3l", "R3h", "R4l", "R4h", "R5l", "R5h", "R6l", "R6h", "R7l", "R7h"};/*--------------------------------------------------------------------disass - Disassemble an opcode. addr - address of opcode to disassemble/print. sep - optionally points to string(tab) to use as separator.|--------------------------------------------------------------------*/char *cl_xa::disass(t_addr addr, char *sep){ char work[256], parm_str[40]; char *buf, *p, *b; int code; int len = 0; int immed_offset = 0; int operands; int mnemonic; char **reg_strs; p= work; code = get_disasm_info(addr, &len, NULL, &immed_offset, &operands, &mnemonic); if (mnemonic == BAD_OPCODE) { buf= (char*)malloc(30); strcpy(buf, "UNKNOWN/INVALID"); return(buf); } if (code & 0x0800) reg_strs = w_reg_strs; else reg_strs = b_reg_strs; switch(operands) { // the repeating common parameter encoding for ADD, ADDC, SUB, AND... case REG_REG : sprintf(parm_str, "%s,%s", reg_strs[((code >> 4) & 0xf)], reg_strs[(code & 0xf)]); break; case REG_IREG : sprintf(parm_str, "%s,[%s]", reg_strs[((code >> 4) & 0xf)], w_reg_strs[(code & 0xf)]); break; case IREG_REG : sprintf(parm_str, "[%s],%s", w_reg_strs[(code & 0x7)], reg_strs[((code >> 4) & 0xf)] ); break; case REG_IREGOFF8 : sprintf(parm_str, "%s,[%s+%02x]", reg_strs[((code >> 4) & 0xf)], w_reg_strs[(code & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset)); ++immed_offset; break; case IREGOFF8_REG : sprintf(parm_str, "[%s+%02x],%s", w_reg_strs[(code & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset), reg_strs[((code >> 4) & 0xf)] ); ++immed_offset; break; case REG_IREGOFF16 : sprintf(parm_str, "%s,[%s+%04x]", reg_strs[((code >> 4) & 0xf)], w_reg_strs[(code & 0x7)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset)<<8)) ); ++immed_offset; ++immed_offset; break; case IREGOFF16_REG : sprintf(parm_str, "[%s+%04x],%s", w_reg_strs[(code & 0x7)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset)<<8)), reg_strs[((code >> 4) & 0xf)] ); ++immed_offset; ++immed_offset; break; case REG_IREGINC : sprintf(parm_str, "%s,[%s+]", reg_strs[((code >> 4) & 0xf)], w_reg_strs[(code & 0xf)]); break; case IREGINC_REG : sprintf(parm_str, "[%s+],%s", w_reg_strs[(code & 0x7)], reg_strs[((code >> 4) & 0xf)] ); break; case DIRECT_REG : sprintf(parm_str, "%s,%s", get_dir_name(((code & 0x7) << 8) | get_mem(MEM_ROM_ID, addr+immed_offset)), reg_strs[((code >> 4) & 0xf)] ); ++immed_offset; break; case REG_DIRECT : sprintf(parm_str, "%s,%s", reg_strs[((code >> 4) & 0xf)], get_dir_name(((code & 0x7) << 8) | get_mem(MEM_ROM_ID, addr+immed_offset))); ++immed_offset; break; case REG_DATA8 : sprintf(parm_str, "%s,#0x%02x", b_reg_strs[((code >> 4) & 0xf)], get_mem(MEM_ROM_ID, addr+immed_offset) ); ++immed_offset; break; case REG_DATA16 : sprintf(parm_str, "%s,#0x%04x", reg_strs[((code >> 4) & 0xf)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset)<<8)) ); ++immed_offset; ++immed_offset; break; case IREG_DATA8 : sprintf(parm_str, "[%s], 0x%02x", w_reg_strs[((code >> 4) & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset) ); ++immed_offset; break; case IREG_DATA16 : sprintf(parm_str, "[%s], 0x%04x", w_reg_strs[((code >> 4) & 0x7)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset)<<8)) ); ++immed_offset; ++immed_offset; break; case IREGINC_DATA8 : sprintf(parm_str, "[%s+], 0x%02x", w_reg_strs[((code >> 4) & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset) ); ++immed_offset; break; case IREGINC_DATA16 : sprintf(parm_str, "[%s+], 0x%04x", w_reg_strs[((code >> 4) & 0x7)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset)<<8)) ); ++immed_offset; ++immed_offset; break; case IREGOFF8_DATA8 : sprintf(parm_str, "[%s+%02x], 0x%02x", w_reg_strs[((code >> 4) & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset), get_mem(MEM_ROM_ID, addr+immed_offset+1) ); immed_offset += 2; break; case IREGOFF8_DATA16 : sprintf(parm_str, "[%s+%02x], 0x%04x", w_reg_strs[((code >> 4) & 0x7)], get_mem(MEM_ROM_ID, addr+immed_offset), (short)((get_mem(MEM_ROM_ID, addr+immed_offset+2)) | (get_mem(MEM_ROM_ID, addr+immed_offset+1)<<8)) ); immed_offset += 3; break; case IREGOFF16_DATA8 : sprintf(parm_str, "[%s+%04x], 0x%02x", w_reg_strs[((code >> 4) & 0x7)], (short)((get_mem(MEM_ROM_ID, addr+immed_offset+1)) | (get_mem(MEM_ROM_ID, addr+immed_offset+0)<<8)), get_mem(MEM_ROM_ID, addr+immed_offset+2) ); immed_offset += 3; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -