Ejemplo n.º 1
0
// Register fetch and decode stage.
static inline int rsp_rd_stage(struct rsp *rsp) {
  struct rsp_rdex_latch *rdex_latch = &rsp->pipeline.rdex_latch;
  struct rsp_ifrd_latch *ifrd_latch = &rsp->pipeline.ifrd_latch;

  uint32_t previous_insn_flags = rdex_latch->opcode.flags;
  uint32_t iw = ifrd_latch->iw;

  rdex_latch->common = ifrd_latch->common;
  rdex_latch->opcode = ifrd_latch->opcode;
  rdex_latch->iw = iw;

  // Check for load-use stalls.
  if (previous_insn_flags & OPCODE_INFO_LOAD) {
    const struct rsp_opcode *opcode = &rdex_latch->opcode;
    unsigned dest = rsp->pipeline.exdf_latch.result.dest;
    unsigned rs = GET_RS(iw);
    unsigned rt = GET_RT(iw);

    if (unlikely(dest && (
      (dest == rs && (opcode->flags & OPCODE_INFO_NEEDRS)) ||
      (dest == rt && (opcode->flags & OPCODE_INFO_NEEDRT))
    ))) {
      static const struct rsp_opcode rsp_rf_kill_op = {RSP_OPCODE_SLL, 0x0};

      rdex_latch->opcode = rsp_rf_kill_op;
      rdex_latch->iw = 0x00000000U;

      return 1;
    }
  }

  return 0;
}
Ejemplo n.º 2
0
// Execution stage.
cen64_flatten static inline void rsp_ex_stage(struct rsp *rsp) {
  struct rsp_dfwb_latch *dfwb_latch = &rsp->pipeline.dfwb_latch;
  struct rsp_exdf_latch *exdf_latch = &rsp->pipeline.exdf_latch;
  struct rsp_rdex_latch *rdex_latch = &rsp->pipeline.rdex_latch;

  uint32_t rs_reg, rt_reg, temp;
  unsigned rs, rt;
  uint32_t iw;

  exdf_latch->common = rdex_latch->common;

  if (rdex_latch->opcode.flags & OPCODE_INFO_VECTOR)
    return;

  iw = rdex_latch->iw;
  rs = GET_RS(iw);
  rt = GET_RT(iw);

  // Forward results from DF/WB.
  temp = rsp->regs[dfwb_latch->result.dest];
  rsp->regs[dfwb_latch->result.dest] = dfwb_latch->result.result;
  rsp->regs[RSP_REGISTER_R0] = 0x00000000U;

  rs_reg = rsp->regs[rs];
  rt_reg = rsp->regs[rt];

  rsp->regs[dfwb_latch->result.dest] = temp;

  // Finally, execute the instruction.
#ifdef PRINT_EXEC
  debug("%.8X: %s\n", rdex_latch->common.pc,
    rsp_opcode_mnemonics[rdex_latch->opcode.id]);
#endif

  return rsp_function_table[rdex_latch->opcode.id](
    rsp, iw, rs_reg, rt_reg);
}
Ejemplo n.º 3
0
int interp_control() {
    uint32_t opcode = GET_OPCODE(if_id.inst);
    uint32_t address;
    switch (opcode) {

    case OPCODE_R :
        id_ex.reg_write     = true;
        id_ex.reg_dst       = GET_RD(if_id.inst);
        id_ex.rt            = GET_RT(if_id.inst);
        id_ex.rs_value      = regs[GET_RS(if_id.inst)];
        id_ex.rt_value      = regs[id_ex.rt];
        id_ex.funct         = GET_FUNCT(if_id.inst);
        id_ex.shamt         = GET_SHAMT(if_id.inst);
        if (id_ex.funct == FUNCT_JR) {
            id_ex.jump        = true;
            id_ex.jump_target = id_ex.rs_value;
        }
        break;

    case OPCODE_BEQ :
        id_ex.branch        = true;
        id_ex.beq           = true;
        id_ex.rt            = GET_RT(if_id.inst);
        id_ex.rs_value      = regs[GET_RS(if_id.inst)];
        id_ex.rt_value      = regs[id_ex.rt];
        id_ex.sign_ext_imm  = SIGN_EXTEND(GET_IMM(if_id.inst));
        // INSTRUKTOR 0: no reason to updates fields that you dont use
        id_ex.funct         = FUNCT_SUB;
        break;

    case OPCODE_BNE :
        id_ex.branch        = true;
        id_ex.beq           = false;
        id_ex.rt            = GET_RT(if_id.inst);
        id_ex.rs_value      = regs[GET_RS(if_id.inst)];
        id_ex.rt_value      = regs[id_ex.rt];
        id_ex.sign_ext_imm  = SIGN_EXTEND(GET_IMM(if_id.inst));
        id_ex.funct         = FUNCT_SUB;
        break;

    case OPCODE_LW :
        id_ex.mem_read      = true;
        id_ex.reg_write     = true;
        id_ex.alu_src       = true;
        id_ex.mem_to_reg    = true;
        id_ex.reg_dst       = GET_RT(if_id.inst);
        id_ex.rt            = GET_RT(if_id.inst);
        id_ex.rs_value      = regs[GET_RS(if_id.inst)];
        id_ex.rt_value      = regs[id_ex.rt];
        id_ex.sign_ext_imm  = SIGN_EXTEND(GET_IMM(if_id.inst));
        id_ex.funct         = FUNCT_ADD;
        break;

    case OPCODE_SW :
        id_ex.mem_write     = true;
        id_ex.alu_src       = true;
        id_ex.rt            = GET_RT(if_id.inst);
        id_ex.rs_value      = regs[GET_RS(if_id.inst)];
        id_ex.rt_value      = regs[id_ex.rt];
        id_ex.sign_ext_imm  = SIGN_EXTEND(GET_IMM(if_id.inst));
        id_ex.funct         = FUNCT_ADD;
        break;

    case OPCODE_J :
        id_ex.jump          = true;
        address             = GET_ADDRESS(if_id.inst);
        id_ex.jump_target   = (if_id.next_pc & MS_4B) | (address << 2);
        break;

    case OPCODE_JAL :
        id_ex.reg_write     = true;
        id_ex.jump          = true;
        address             = GET_ADDRESS(if_id.inst);
        id_ex.jump_target   = (if_id.next_pc & MS_4B) | (address << 2);
        id_ex.rs_value      = 0;
        id_ex.rt_value      = if_id.next_pc;
        id_ex.reg_dst       = 31;
        id_ex.funct         = FUNCT_ADD;
        break;

    // INSTRUKTOR -2: Make cases for all I-type and J-type instructions
    default:
        printf("ERROR: Unknown opcode in interp_control()\n");
        return ERROR_UNKNOWN_OPCODE;
    }
    return 0;
}
Ejemplo n.º 4
0
int mipsasm_resolve_labels(uint32_t *code, uint32_t *size, uint32_t offset)
{
	uint32_t i = offset;
	uint32_t labels[MAX_LABEL_NUM];
	memset(labels, 0xff, sizeof(labels));

	while (i < *size) {
		uint32_t opcode = ntohl(code[i / 4]);
		if (GET_OP(opcode) != ASM_LABEL_OPCODE 
				|| GET_RS(opcode) 
				|| GET_RT(opcode)
				|| !(opcode & ASM_LABEL_MARKER)) {
			i += 4;
			continue;
		}

		uint32_t label = opcode & ASM_LABEL_MASK;
		if (label >= MAX_LABEL_NUM) {
			fprintf(stderr, "%s: %02x: label %u exeeds %u\n", 
					__func__, i, label, MAX_LABEL_NUM);
			return 1;
		}

#ifdef MIPSASM_DEBUG
		printf("%s: %02x: label %u (opcode %08x)\n", __func__, i, label, opcode);
#endif

		labels[label] = i / 4;
		*size -= 4;
		uint32_t *dest = code + (i / 4);
		memmove(dest, dest + 1, *size - i);
	}

	for (i = offset; i < *size; i += 4) {
		uint32_t opcode = ntohl(code[i / 4]);
		uint32_t op = GET_OP(opcode);
		switch (op) {
			case 0x01:
			case 0x04:
			case 0x05:
			case 0x06:
			case 0x07:
				break;
			default:
				continue;
		}

		uint32_t imm = opcode & 0xffff;
		if (!(imm & ASM_LABEL_MARKER)) {
#ifdef MIPSASM_DEBUG
			printf("%s: %02x: skiping non-labeled branch to %02x\n", __func__, i, imm);
#endif
			// skip unlabeled branchp instruction
			continue;
		}

		imm &= ASM_LABEL_MASK;
		if (imm > MAX_LABEL_NUM) {
			fprintf(stderr, "%s: %02x: branch refers to out-of-range label %u\n",
					__func__, i, imm);
			return 1;
		}

		uint32_t instr = labels[imm];
		if (instr == UINT32_MAX) {
			fprintf(stderr, "%s: %02x: branch refers to undefined label %u\n",
					__func__, i, imm);
			return 1;
		}

		int32_t diff = (instr - (i / 4)) - 1;
		if (diff < INT16_MIN || diff > INT16_MAX) {
			fprintf(stderr, "%s: %02x: branch target %x out of range\n", __func__, i, diff);
			return 1;
		}
		opcode &= 0xffff0000;
		opcode |= (diff & 0xffff);
		code[i / 4] = htonl(opcode);
#ifdef MIPSASM_DEBUG
		printf("%s: %02x: branch to %02x\n", __func__, i, (diff * 4) & 0xffff);
#endif
	}

	return 0;
}