Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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;
}