📄 isa.c
字号:
#include <stdlib.h>#include <ctype.h>#include <stdio.h>#include <string.h>#include "isa.h"/* Are we running in GUI mode? */extern int gui_mode;/* Bytes Per Line = Block size of memory */#define BPL 32struct { char *name; int id;} reg_table[REG_NONE+1] = { {"%eax", REG_EAX}, {"%ecx", REG_ECX}, {"%edx", REG_EDX}, {"%ebx", REG_EBX}, {"%esp", REG_ESP}, {"%ebp", REG_EBP}, {"%esi", REG_ESI}, {"%edi", REG_EDI}, {"----", REG_NONE}};reg_id_t find_register(char *name){ int i; for (i = 0; i < REG_NONE; i++) if (!strcmp(name, reg_table[i].name)) return reg_table[i].id; return REG_NONE;}char *reg_name(reg_id_t id){ if (id < REG_NONE) return reg_table[id].name; else return reg_table[REG_NONE].name;}instr_t instruction_set[] = { {"nop", HPACK(I_NOP, 0), 1, NO_ARG, 0, 0, NO_ARG, 0, 0 }, {"halt", HPACK(I_HALT, 0), 1, NO_ARG, 0, 0, NO_ARG, 0, 0 }, {"rrmovl", HPACK(I_RRMOVL, 0), 2, R_ARG, 1, 1, R_ARG, 1, 0 }, /* arg1hi indicates number of bytes */ {"irmovl", HPACK(I_IRMOVL, 0), 6, I_ARG, 2, 4, R_ARG, 1, 0 }, {"rmmovl", HPACK(I_RMMOVL, 0), 6, R_ARG, 1, 1, M_ARG, 1, 0 }, {"mrmovl", HPACK(I_MRMOVL, 0), 6, M_ARG, 1, 0, R_ARG, 1, 1 }, {"addl", HPACK(I_ALU, A_ADD), 2, R_ARG, 1, 1, R_ARG, 1, 0 }, {"subl", HPACK(I_ALU, A_SUB), 2, R_ARG, 1, 1, R_ARG, 1, 0 }, {"andl", HPACK(I_ALU, A_AND), 2, R_ARG, 1, 1, R_ARG, 1, 0 }, {"xorl", HPACK(I_ALU, A_XOR), 2, R_ARG, 1, 1, R_ARG, 1, 0 }, /* arg1hi indicates number of bytes */ {"jmp", HPACK(I_JMP, J_YES), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"jle", HPACK(I_JMP, J_LE), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"jl", HPACK(I_JMP, J_L), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"je", HPACK(I_JMP, J_E), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"jne", HPACK(I_JMP, J_NE), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"jge", HPACK(I_JMP, J_GE), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"jg", HPACK(I_JMP, J_G), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"call", HPACK(I_CALL, 0), 5, I_ARG, 1, 4, NO_ARG, 0, 0 }, {"ret", HPACK(I_RET, 0), 1, NO_ARG, 0, 0, NO_ARG, 0, 0 }, {"pushl", HPACK(I_PUSHL, 0) , 2, R_ARG, 1, 1, NO_ARG, 0, 0 }, {"popl", HPACK(I_POPL, 0) , 2, R_ARG, 1, 1, NO_ARG, 0, 0 }, {"iaddl", HPACK(I_IADDL, 0), 6, I_ARG, 2, 4, R_ARG, 1, 0 }, {"leave", HPACK(I_LEAVE, 0), 1, NO_ARG, 0, 0, NO_ARG, 0, 0 }, /* this is just a hack to make the I_POP2 code have an associated name */ {"pop2", HPACK(I_POP2, 0) , 0, NO_ARG, 0, 0, NO_ARG, 0, 0 }, /* For allocation instructions, arg1hi indicates number of bytes */ {".byte", 0x00, 1, I_ARG, 0, 1, NO_ARG, 0, 0 }, {".word", 0x00, 2, I_ARG, 0, 2, NO_ARG, 0, 0 }, {".long", 0x00, 4, I_ARG, 0, 4, NO_ARG, 0, 0 }, {NULL, 0 , 0, NO_ARG, 0, 0, NO_ARG, 0, 0 }};instr_t invalid_instr = {"XXX", 0 , 0, NO_ARG, 0, 0, NO_ARG, 0, 0 };instr_ptr find_instr(char *name){ int i; for (i = 0; instruction_set[i].name; i++) if (strcmp(instruction_set[i].name,name) == 0) return &instruction_set[i]; return NULL;}/* Return name of instruction given its encoding */char *iname(int instr) { int i; for (i = 0; instruction_set[i].name; i++) { if (instr == instruction_set[i].code) return instruction_set[i].name; } return "<bad>";}instr_ptr bad_instr(){ return &invalid_instr;}mem_t init_mem(int len){ mem_t result = (mem_t) malloc(sizeof(mem_rec)); len = ((len+BPL-1)/BPL)*BPL; result->len = len; result->contents = (byte_t *) calloc(len, 1); return result;}void clear_mem(mem_t m){ memset(m->contents, 0, m->len);}void free_mem(mem_t m){ free((void *) m->contents); free((void *) m);}mem_t copy_mem(mem_t oldm){ mem_t newm = init_mem(oldm->len); memcpy(newm->contents, oldm->contents, oldm->len); return newm;}bool_t diff_mem(mem_t oldm, mem_t newm, FILE *outfile){ word_t pos; int len = oldm->len; bool_t diff = FALSE; if (newm->len < len) len = newm->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { word_t ov, nv; get_word_val(oldm, pos, &ov); get_word_val(newm, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "0x%.4x:\t0x%.8x\t0x%.8x\n", pos, ov, nv); } } return diff;}int hex2dig(char c){ if (isdigit((int)c)) return c - '0'; if (isupper((int)c)) return c - 'A' + 10; else return c - 'a' + 10;}#define LINELEN 4096int load_mem(mem_t m, FILE *infile, int report_error){ /* Read contents of .yo file */ char buf[LINELEN]; char c, ch, cl; int byte_cnt = 0; int lineno = 0; word_t bytepos = 0; int empty_line = 1; int addr = 0; char hexcode[15];#ifdef HAS_GUI /* For display */ int line_no = 0; char line[LINELEN];#endif /* HAS_GUI */ int index = 0; while (fgets(buf, LINELEN, infile)) { int cpos = 0; empty_line = 1; lineno++; /* Skip white space */ while (isspace((int)buf[cpos])) cpos++; if (buf[cpos] != '0' || (buf[cpos+1] != 'x' && buf[cpos+1] != 'X')) continue; /* Skip this line */ cpos+=2; /* Get address */ bytepos = 0; while (isxdigit((int)(c=buf[cpos]))) { cpos++; bytepos = bytepos*16 + hex2dig(c); } while (isspace((int)buf[cpos])) cpos++; if (buf[cpos++] != ':') { if (report_error) { fprintf(stderr, "Error reading file. Expected colon\n"); fprintf(stderr, "Line %d:%s\n", lineno, buf); fprintf(stderr, "Reading '%c' at position %d\n", buf[cpos], cpos); } return 0; } addr = bytepos; while (isspace((int)buf[cpos])) cpos++; index = 0; /* Get code */ while (isxdigit((int)(ch=buf[cpos++])) && isxdigit((int)(cl=buf[cpos++]))) { byte_t byte = 0; if (bytepos >= m->len) { if (report_error) { fprintf(stderr, "Error reading file. Invalid address. 0x%x\n", bytepos); fprintf(stderr, "Line %d:%s\n", lineno, buf); } return 0; } byte = hex2dig(ch)*16+hex2dig(cl); m->contents[bytepos++] = byte; byte_cnt++; empty_line = 0; hexcode[index++] = ch; hexcode[index++] = cl; } /* Fill rest of hexcode with blanks */ for (; index < 12; index++) hexcode[index] = ' '; hexcode[index] = '\0';#ifdef HAS_GUI if (gui_mode) { /* Now get the rest of the line */ while (isspace((int)buf[cpos])) cpos++; cpos++; /* Skip over '|' */ index = 0; while ((c = buf[cpos++]) != '\0' && c != '\n') { line[index++] = c; } line[index] = '\0'; if (!empty_line) report_line(line_no++, addr, hexcode, line); }#endif /* HAS_GUI */ } return byte_cnt;}bool_t get_byte_val(mem_t m, word_t pos, byte_t *dest){ if (pos < 0 || pos >= m->len) return FALSE; *dest = m->contents[pos]; return TRUE;}bool_t get_word_val(mem_t m, word_t pos, word_t *dest){ int i; word_t val; if (pos < 0 || pos + 4 > m->len) return FALSE; val = 0; for (i = 0; i < 4; i++) val = val | m->contents[pos+i]<<(8*i); *dest = val; return TRUE;}bool_t set_byte_val(mem_t m, word_t pos, byte_t val){ if (pos < 0 || pos >= m->len) return FALSE; m->contents[pos] = val; return TRUE;}bool_t set_word_val(mem_t m, word_t pos, word_t val){ int i; if (pos < 0 || pos + 4 > m->len) return FALSE; for (i = 0; i < 4; i++) { m->contents[pos+i] = val & 0xFF; val >>= 8; } return TRUE;}void dump_memory(FILE *outfile, mem_t m, word_t pos, int len){ int i, j; while (pos % BPL) { pos --; len ++; } len = ((len+BPL-1)/BPL)*BPL; if (pos+len > m->len) len = m->len-pos; for (i = 0; i < len; i+=BPL) { word_t val = 0; fprintf(outfile, "0x%.4x:", pos+i); for (j = 0; j < BPL; j+= 4) { get_word_val(m, pos+i+j, &val); fprintf(outfile, " %.8x", val); } }}mem_t init_reg(){ return init_mem(32);}void free_reg(mem_t r){ free_mem(r);}mem_t copy_reg(mem_t oldr){ return copy_mem(oldr);}bool_t diff_reg(mem_t oldr, mem_t newr, FILE *outfile){ word_t pos; int len = oldr->len; bool_t diff = FALSE; if (newr->len < len) len = newr->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { word_t ov, nv; get_word_val(oldr, pos, &ov); get_word_val(newr, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "%s:\t0x%.8x\t0x%.8x\n", reg_table[pos/4].name, ov, nv); } } return diff;}word_t get_reg_val(mem_t r, reg_id_t id){ word_t val; if (id >= REG_NONE) return 0; get_word_val(r,id*4, &val); return val;}void set_reg_val(mem_t r, reg_id_t id, word_t val){ if (id < REG_NONE) { set_word_val(r,id*4,val);#ifdef HAS_GUI if (gui_mode) { signal_register_update(id, val); }#endif /* HAS_GUI */ }} void dump_reg(FILE *outfile, mem_t r) { reg_id_t id; for (id = 0; id < 8; id++) { fprintf(outfile, " %s ", reg_table[id].name); } fprintf(outfile, "\n"); for (id = 0; id < 8; id++) { word_t val; get_word_val(r, id*4, &val); fprintf(outfile, " %x", val); } fprintf(outfile, "\n");}struct { char symbol; int id;} alu_table[A_NONE+1] = { {'+', A_ADD}, {'-', A_SUB}, {'^', A_XOR}, {'&', A_AND}, {'?', A_NONE}};char op_name(alu_t op){ if (op < A_NONE) return alu_table[op].symbol; else return alu_table[A_NONE].symbol;}word_t compute_alu(alu_t op, word_t argA, word_t argB){ word_t val; switch(op) { case A_ADD: val = argA+argB; break; case A_SUB: val = argB-argA; break; case A_AND: val = argA&argB; break; case A_XOR: val = argA^argB; break; default: val = 0; } return val;}cc_t compute_cc(alu_t op, word_t argA, word_t argB){ word_t val = compute_alu(op, argA, argB); bool_t zero = (val == 0); bool_t sign = ((int)val < 0); bool_t ovf; switch(op) { case A_ADD: ovf = ((int)argA < 0 == (int)argB < 0) && ((int)val < 0 != (int)argA < 0); break; case A_SUB:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -