int run(int argc, char** argv) { char* file; cpu_t cpu; int i; int j; int ninstr; unsigned instr; unsigned opcode; unsigned source_reg1; int constant; unsigned dest_reg; int source1; int source2; int dest; unsigned data; bool proceed; bool increment_pc; bool writeback; if (argc > 1) file = argv[1]; else file = "fac.s"; read_program(file, memory, &ninstr); /* First instruction to execute is at address 0. */ cpu.pc = 0; cpu.reg[0] = 0; proceed = true; while (proceed) { /* Fetch next instruction to execute. */ instr = read_memory(memory, cpu.pc); /* Decode the instruction. */ opcode = extract_opcode(instr); source_reg1 = extract_source1(instr); constant = extract_constant(instr); dest_reg = extract_dest(instr); /* Fetch operands. */ source1 = cpu.reg[source_reg1]; source2 = cpu.reg[constant & (NREG-1)]; increment_pc = true; writeback = true; printf("pc = %3d: ", cpu.pc); switch (opcode) { case ADD: puts("ADD"); dest = source1 + source2; break; case ADDI: puts("ADDI"); dest = source1 + constant; break; case SUB: puts("SUB"); dest = source1 - source2; break; case SUBI: puts("SUBI"); dest = source1 - constant; break; case MUL: puts("MUL"); dest = source1 * source2; break; case SGE: puts("SGE"); dest = source1 >= source2; break; case SGT: puts("SGT"); dest = source1 > source2; break; case SEQ: puts("SEQ"); dest = source1 == source2; break; case SEQI: puts("SEQI"); dest = source1 == constant; break; case BT: puts("BT"); writeback = false; if (source1 != 0) { cpu.pc = constant; increment_pc = false; } break; case BF: puts("BF"); writeback = false; if (source1 == 0) { cpu.pc = constant; increment_pc = false; } break; case BA: puts("BA"); writeback = false; increment_pc = false; cpu.pc = constant; break; case LD: puts("LD"); data = read_memory(memory, source1 + constant); dest = data; break; case ST: puts("ST"); data = cpu.reg[dest_reg]; write_memory(memory, source1 + constant, data); writeback = false; break; case CALL: puts("CALL"); increment_pc = false; dest = cpu.pc + 1; dest_reg = 31; cpu.pc = constant; break; case JMP: puts("JMP"); increment_pc = false; writeback = false; cpu.pc = source1; break; case HALT: puts("HALT"); increment_pc = false; writeback = false; proceed = false; break; default: error("illegal instruction at pc = %d: opcode = %d\n", cpu.pc, opcode); } if (writeback && dest_reg != 0) cpu.reg[dest_reg] = dest; if (increment_pc) cpu.pc += 1; #ifdef DEBUG i = 0; while (i < NREG) { for (j = 0; j < 4; ++j, ++i) { if (j > 0) printf("| "); printf("R%02d = %-12d", i, cpu.reg[i]); } printf("\n"); } #endif } i = 0; while (i < NREG) { for (j = 0; j < 4; ++j, ++i) { if (j > 0) printf("| "); printf("R%02d = %-12d", i, cpu.reg[i]); } printf("\n"); } return 0; }
static int r_asm_lm32_decode(RAsmLm32Instruction *instr) { instr->op = extract_opcode (instr->value); if (instr->op >= RAsmLm32OpcodeNumber) return -1; instr->op_decode = RAsmLm32OpcodeList[instr->op]; switch (instr->op_decode.type) { case reg_imm16_signextend: instr->dest_reg = extract_reg_v (instr->value); instr->src0_reg = extract_reg_u (instr->value); instr->immediate = shift_and_signextend (0, RAsmLm32Imm16SignBitPos, extract_imm16 (instr->value)); break; case reg_imm16_shift2_signextend: instr->dest_reg = extract_reg_v (instr->value); instr->src0_reg = extract_reg_u (instr->value); instr->immediate = shift_and_signextend (2, RAsmLm32Imm16SignBitPos, extract_imm16 (instr->value)); break; case reg_imm16_zeroextend: instr->dest_reg = extract_reg_v (instr->value); instr->src0_reg = extract_reg_u (instr->value); instr->immediate = extract_imm16 (instr->value); break; case reg_imm5: if (is_invalid_imm5_instr (instr)) return -1; instr->dest_reg = extract_reg_v (instr->value); instr->src0_reg = extract_reg_u (instr->value); instr->immediate = extract_imm5 (instr->value); break; case raise_instr: if (is_invalid_imm5_instr (instr)) return -1; //might be less bits used, but this shouldn't hurt //invalid parameters are catched in print_pseudo_instruction anyway instr->immediate = extract_imm5 (instr->value); break; case one_reg: if (is_invalid_one_reg_instr (instr)) return -1; instr->src0_reg = extract_reg_u (instr->value); break; case two_regs: if (is_invalid_two_reg_instr (instr)) return -1; instr->dest_reg = extract_reg_w (instr->value); instr->src0_reg = extract_reg_u (instr->value); break; case three_regs: instr->dest_reg = extract_reg_w (instr->value); instr->src0_reg = extract_reg_v (instr->value); instr->src1_reg = extract_reg_u (instr->value); break; case reg_csr: //wcsr if (is_invalid_wcsr_instr (instr)) return -1; instr->src0_reg = extract_reg_v (instr->value); instr->csr = extract_reg_u (instr->value); break; case csr_reg: //rcsr //bitmask is the same as the two register one if (is_invalid_two_reg_instr (instr)) return -1; instr->dest_reg = extract_reg_w (instr->value); instr->csr = extract_reg_u (instr->value); break; case imm26: instr->immediate = shift_and_signextend (2, RAsmLm32Imm26SignBitPos, extract_imm26 (instr->value)); break; case reserved: default: return -1; } //see if the instruction corresponds to a pseudo-instruction instr->pseudoInstruction = is_pseudo_instr_ret (instr) || is_pseudo_instr_mv (instr) || is_pseudo_instr_mvhi (instr) || is_pseudo_instr_not (instr) || is_pseudo_instr_mvi (instr) || is_pseudo_instr_nop (instr) || is_pseudo_instr_raise (instr); return 0; }