/* instruction-level simulator for LC-897 */ #include #include #define NUMREGS 8 /* number of machine registers */ #define MAXLINELENGTH 1000 #define MEMSIZE 0x7fff /* maximum number of memory words */ #define OP_SHIFT 13 #define A_SHIFT 10 #define B_SHIFT 7 #define C_SHIFT 0 #define ADD 0 #define ADDI 1 #define NAND 2 #define LUI 3 #define SW 4 #define LW 5 #define BEQ 6 #define JALR 7 #define NOPINSTRUCTION (short)0x0 #define HALTINSTRUCTION (short)0xe071 typedef struct stateStruct { short pc; short mem[MEMSIZE]; short reg[NUMREGS]; short numMemory; } stateType; void printState(stateType); void run(stateType); short convertNum(short); int Instructions=0; short opcode(short instruction) { return (instruction >> OP_SHIFT) & 0x7; } short field_ra(short instruction) { return (instruction >> A_SHIFT) & 0x7; } short field_rb(short instruction) { return (instruction >> B_SHIFT) & 0x7; } short field_rc(short instruction) { return (instruction >> C_SHIFT) & 0x7; } short field_imm(short instruction) { return (instruction & 0x7F); } short offset(short instruction) { return convertNum(field_imm(instruction)); } char PRINT_INSTRUCTION[100]; void print_RRR(instr, name) short instr; char *name; { sprintf(PRINT_INSTRUCTION, "%s %hd,%hd,%hd", name, field_ra(instr), field_rb(instr), field_rc(instr)); } void print_RRI(instr, name) short instr; char *name; { sprintf(PRINT_INSTRUCTION, "%s %hd,%hd,%hd", name, field_ra(instr), field_rb(instr), offset(instr)); } void print_RR(instr, name) short instr; char *name; { sprintf(PRINT_INSTRUCTION, "%s %hd,%hd", name, field_ra(instr), field_rb(instr)); } void print_RI(instr, name) short instr; char *name; { sprintf(PRINT_INSTRUCTION, "%s %hd,0x%hx", name, field_ra(instr), instr & 0x3ff); } char * printInstruction(short instr) { if (instr == NOPINSTRUCTION) { sprintf(PRINT_INSTRUCTION, "nop"); } else if (instr == HALTINSTRUCTION) { sprintf(PRINT_INSTRUCTION, "halt"); } else if (opcode(instr) == ADD) { print_RRR(instr, "add"); } else if (opcode(instr) == ADDI) { print_RRI(instr, "addi"); } else if (opcode(instr) == NAND) { print_RRR(instr, "nand"); } else if (opcode(instr) == LUI) { print_RI(instr, "lui"); } else if (opcode(instr) == LW) { print_RRI(instr, "lw"); } else if (opcode(instr) == SW) { print_RRI(instr, "sw"); } else if (opcode(instr) == BEQ) { print_RRI(instr, "beq"); } else if (opcode(instr) == JALR) { print_RR(instr, "jalr"); } else { sprintf(PRINT_INSTRUCTION, "data: %hd", instr); } return PRINT_INSTRUCTION; } main(int argc, char *argv[]) { short i, j; char line[MAXLINELENGTH]; stateType state; FILE *filePtr; if (argc != 2) { printf("error: usage: %s \n", argv[0]); exit(1); } /* initialize memories and registers */ for (i=0; i> OP_SHIFT) & 0x7; arg0 = (instr >> A_SHIFT) & 0x7; arg1 = (instr >> B_SHIFT) & 0x7; arg2 = instr & 0x7; /* only for add, nand */ imm7 = convertNum(instr & 0x7F); /* only for addi, beq, lw, sw */ imm10 = instr & 0x3FF; /* only for lui */ //printf("DEBUG: decoding %s\n", printInstruction(state.mem[state.pc])); /* * note: PC already == PC+1 at this point, * so if we want pc + 1 + immediate, we only need to calculate pc + immediate */ state.pc++; if (instr == HALTINSTRUCTION) { printf("Machine Halted\n"); printf("Total of %d instructions executed\n", Instructions+1); printState(state); exit(0); } else if (opcode == ADD) { state.reg[arg0] = state.reg[arg1] + state.reg[arg2]; printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else if (opcode == ADDI) { state.reg[arg0] = state.reg[arg1] + imm7; printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else if (opcode == NAND) { state.reg[arg0] = ~(state.reg[arg1] & state.reg[arg2]); printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else if (opcode == LUI) { state.reg[arg0] = (imm10 << 6) & 0xFFC0; printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else if (opcode == LW) { state.reg[arg0] = state.mem[state.reg[arg1] + imm7]; printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else if (opcode == SW) { state.mem[state.reg[arg1] + imm7] = state.reg[arg0]; printf("m[%04hx] <- %04hx\n", state.reg[arg1] + imm7, state.reg[arg0]); } else if (opcode == BEQ) { if (state.reg[arg0] == state.reg[arg1]) { state.pc += imm7; } } else if (opcode == JALR) { short tmp = state.pc; state.pc = state.reg[arg1]; state.reg[arg0] = tmp; printf("r%d <- %04hx\n", arg0, state.reg[arg0]); } else { printf("error: illegal opcode %x\n", opcode); exit(1); } state.reg[0] = 0; // printState(state); } } void printState(stateType state) { int i; printf("State at the end of cycle %ld\n", Instructions); printf(" PC = %hd\n", state.pc); printf(" Regs:\n"); for (i=0; i<8; i++) { printf(" %02d %hd\n", i, state.reg[i]); } // printf(" Memory:\n"); // for (i=0; i