Exemple #1
0
unsigned long MemoryForCpu::read16_se(unsigned long addr)
{
	warnOddAddress(addr);

	unsigned short c;

	if(port->read16(addr, &c))
		return signExtend16(c);
	if(ifont->read16(addr, &c))
		return signExtend16(c);
	if(rommmp->read16(addr, &c))
		return signExtend16(c);


	return signExtend16(readMemory16(addr));
}
    void Simulator::_lh(instruction instr) {
        int offset = (int) signExtend16(instr.ci);
        int base = (int) reg[instr.rs];

        // write to $0
        this->checkWriteToRegZeroError(instr.rt);
        // Check number overflow
        if ((getSign(base) == getSign(offset)) && (getSign(base) != getSign(base+offset))) {
            fprintf(errordump, "Number overflow in cycle: %d\n", cycleCounter);
            runtimeStatus = (runtimeStatus == STATUS_NORMAL)?STATUS_CONTINUE:runtimeStatus;
        }
        // Check address overflow
        if (base + offset >= 1024 || base + offset < 0) {
            fprintf(errordump, "Address overflow in cycle: %d\n", cycleCounter);
            runtimeStatus = STATUS_HALT;
        }
        // Check misalignment error
        if ((base + offset) % 2 != 0) {
            fprintf(errordump, "Misalignment error in cycle: %d\n", cycleCounter);
            runtimeStatus = STATUS_HALT;
        }

        // Check if the error happens or not
        if (runtimeStatus == STATUS_HALT || runtimeStatus == STATUS_SKIP) {
            return;
        }
        uint_32t_word tmp = dmemory[(base+offset)/4];
        // Check if the location is in middle. If yes, shift it.
        if ((base + offset) % 4 != 0) {
            tmp = tmp >> 16;
        }
/*
 * Function to produce a formatted string with the assembly language
 * representation of a decoded instruction.
 */
string Instruction::str() {
  char buf[64];
  switch (format) {
  case R_TYPE:
    switch (xtype) {
    case ALU:
      sprintf(buf, "%08x  %s $%u, $%u, $%u", raw, ITokenName[token], rd, rs, rt);
      break;
    case SHIFT:
      sprintf(buf, "%08x  %s $%u, $%u, $%u", raw, ITokenName[token], rd, rt, shamt);
      break;
    case JUMP:
      sprintf(buf, "%08x  %s $%u", raw, ITokenName[token], rs);
      break;
    default:
      sprintf(buf, "%08x  %s", raw, ITokenName[token]);
    }
    break;
  case I_TYPE:
    switch (xtype) {
    case ALU:
      sprintf(buf, "%08x  %s $%u, $%u, %d", raw, ITokenName[token], rt, rs, signExtend16(imm));
      break;
    case LOAD:
    case STORE:
      sprintf(buf, "%08x  %s $%u, %d($%u)", raw, ITokenName[token], rt, signExtend16(imm), rs);
      break;
    case BRANCH:
      sprintf(buf, "%08x  %s $%u, $%u, %d", raw, ITokenName[token], rs, rt, signExtend16(imm));
      break;
    default:
      sprintf(buf, "%08x  %s", raw, ITokenName[token]);
    }
    break;
  case J_TYPE:
    sprintf(buf, "%08x  %s 0x%x", raw, ITokenName[token], target<<2);
    break;
  default:
    sprintf(buf, "%08x  %s", raw, ITokenName[token]);
  }
  string s(buf);
  s.insert(s.end(), 32 - s.size(), ' ');
  return s;
}
    void Simulator::_addi(instruction instr) {
        int s = (int)reg[instr.rs];
        int ci = (int)signExtend16(instr.ci);

        // write to $0
        this->checkWriteToRegZeroError(instr.rt);
        // Check number overflow
        if ((getSign(s) == getSign(ci)) && (getSign(s) != getSign(s+ci))) {
            fprintf(errordump, "Number overflow in cycle: %d\n", cycleCounter);
            runtimeStatus = (runtimeStatus == STATUS_NORMAL)?STATUS_CONTINUE:runtimeStatus;
        }
        // check if the error happens or not
        if (runtimeStatus == STATUS_HALT || runtimeStatus == STATUS_SKIP) {
            return;
        }
        reg[instr.rt] = s+ci;
    }
Exemple #5
0
void insn_DisassemblePCode(FILE* lfile, OPTYPE *pop)
{
  /* Indent, comment or label */

  switch (opTable[pop->op].format)
    {
    case LABEL_DEC :
      fprintf(lfile, "L%04x:  ", pop->arg2);
      break;
    case COMMENT   :
      fprintf(lfile, "; ");
      break;
    default   :
      fprintf(lfile, "        ");
    } /* end switch */

  /* Special Case Comment line format */

  if (opTable[pop->op].format == COMMENT)
    {
      fprintf(lfile, "%s ", opTable[pop->op].opName);
      if (pop->op & o8)
        {
          fprintf(lfile, "%d", pop->arg1);
          if (pop->op & o16)
            fprintf(lfile, ":%d", pop->arg2);
        } /* end if */
      else if (pop->op & o16)
        fprintf(lfile, "%d", pop->arg2);
    } /* end if */

  /* Print normal opCode mnemonic */

  else
    {
      fprintf(lfile, "%s ", opTable[pop->op].opName);

      /* Print pop->arg1 (if present) */

      if (pop->op & o8) fprintf(lfile, "%d", pop->arg1);

      /* Print ar16 (if present) */

      if (pop->op & o16)
        {
          switch (opTable[pop->op].format)
            {
            case HEX       :
              if (pop->op & o8) fprintf(lfile, ", ");
              fprintf(lfile, "0x%04x", pop->arg2);
              break;

            case COMMENT   :
            case DECIMAL   :
              if (pop->op & o8) fprintf(lfile, ", ");
              fprintf(lfile, "%ld", signExtend16(pop->arg2));
              break;

            case UDECIMAL   :
              if (pop->op & o8) fprintf(lfile, ", ");
              fprintf(lfile, "%u", pop->arg2);
              break;

            case fpOP       :
              if ((pop->arg1 & fpMASK) < MAX_FOP)
                fprintf(lfile, " %s", fpName[(pop->arg1 & 0x3f)]);
              else
                fprintf(lfile, " %s", invFpOp);
              break;

            case xOP       :
              if (pop->arg2 < MAX_XOP)
                fprintf(lfile, ", %s", xName[pop->arg2]);
              else
                fprintf(lfile, ", %s", invXOp);
              break;

            case lbOP :
              if (pop->arg2 < MAX_LBOP)
                fprintf(lfile, "%s", lbName[pop->arg2]);
              else
                fprintf(lfile, "%s", invLbOp);
              break;

            case LABEL_DEC :
            default        :
              break;
            } /* end switch */
        } /* end if */
    } /* end else */

  /* Don't forget the newline! */

  fputc('\n', lfile);

} /* end dissassemblePcode */
        // Check misalignment error
        if ((base + offset) % 2 != 0) {
            fprintf(errordump, "Misalignment error in cycle: %d\n", cycleCounter);
            runtimeStatus = STATUS_HALT;
        }

        // Check if the error happens or not
        if (runtimeStatus == STATUS_HALT || runtimeStatus == STATUS_SKIP) {
            return;
        }
        uint_32t_word tmp = dmemory[(base+offset)/4];
        // Check if the location is in middle. If yes, shift it.
        if ((base + offset) % 4 != 0) {
            tmp = tmp >> 16;
        }
        reg[instr.rt] = signExtend16(tmp & 0x0000FFFF);
    }

    void Simulator::_lb(instruction instr) {
        int offset = (int) signExtend16(instr.ci);
        int base = (int) reg[instr.rs];

        // write to $0
        this->checkWriteToRegZeroError(instr.rt);
        // Check number overflow
        if ((getSign(base) == getSign(offset)) && (getSign(base) != getSign(base+offset))) {
            fprintf(errordump, "Number overflow in cycle: %d\n", cycleCounter);
            runtimeStatus = (runtimeStatus == STATUS_NORMAL)?STATUS_CONTINUE:runtimeStatus;
        }
        // Check address overflow
        if (base + offset >= 1024 || base + offset < 0) {
/*
 * Function to produce a formatted string with the assembly language
 * representation of a decoded instruction.
 */
string Instruction::str() {
	char buf[64];
	switch (format) {
		case R_TYPE:
			switch (xtype) {
				case ALU:
					if (token == MULT || token == MULTU || token == DIV || token == DIVU) {
						sprintf(buf, "%08x  %s $%u, $%u", raw, ITokenName[token], rs, rt);
					}
					else if (token == MTHI || token == MTLO) {
						sprintf(buf, "%08x  %s $%u", raw, ITokenName[token], rs);
					}
					else if (token == MFHI || token == MFLO) {
						sprintf(buf, "%08x  %s $%u", raw, ITokenName[token], rd);
					}
					else {
						sprintf(buf, "%08x  %s $%u, $%u, $%u", raw, ITokenName[token], rd, rs, rt);
					}
					break;
				case SHIFT:
					if (token == SLLV || token == SRLV || token == SRAV) {
						sprintf(buf, "%08x  %s $%u, $%u, $%u", raw, ITokenName[token], rd, rs, rt);
					}
					else
					{
						sprintf(buf, "%08x  %s $%u, $%u, %u", raw, ITokenName[token], rd, rt, shamt);
					}
					break;
				case JUMP:
					sprintf(buf, "%08x  %s $%u", raw, ITokenName[token], rs);
					break;
				default:
					sprintf(buf, "%08x  %s", raw, ITokenName[token]);
					break;
			}
			break;
		case I_TYPE:
			switch (xtype) {
				case ALU:
					sprintf(buf, "%08x  %s $%u, $%u, %d", raw, ITokenName[token], rt, rs, signExtend16(imm));
					break;
				case LOAD:
				case STORE:
					sprintf(buf, "%08x  %s $%u, %d($%u)", raw, ITokenName[token], rt, signExtend16(imm), rs);
					break;
				case BRANCH:
					if (token == BGEZ || token == BGTZ || token == BLEZ || token == BLTZ) {
						sprintf(buf, "%08x  %s $%u, %d", raw, ITokenName[token], rs, signExtend16(imm));
					}
					else {
						sprintf(buf, "%08x  %s $%u, $%u, %d", raw, ITokenName[token], rs, rt, signExtend16(imm));
					}
					break;
				default:
					sprintf(buf, "%08x  %s", raw, ITokenName[token]);
					break;
			}
			break;
		case J_TYPE:
			sprintf(buf, "%08x  %s 0x%x", raw, ITokenName[token], target<<2);
			break;
		default:
			sprintf(buf, "%08x  %s", raw, ITokenName[token]);
			break;
	}
	string s(buf);
	s.insert(s.end(), 36 - s.size(), ' ');
	return s;
}
bool Instruction::exec() {
	//
	// NOTE: Assumes pc has been pre-incremented
	// Important for branch instruction operation
	//
	uint64_t p;  // product for mult, div
	bool keepGoing = true;
	pc += 4;
	switch(token) {
		case SLL:
			reg[rd] = reg[rt] << shamt;
			break;
		case SRL:
			reg[rd] = reg[rt] >> shamt;
			break;
		case SRA:
			reg[rd] = (int) reg[rt] >> shamt;
			break;
		case SLLV:
			reg[rd] = reg[rt] << reg[rs];
			break;
		case SRLV:
			reg[rd] = reg[rt] >> reg[rs];
			break;
		case SRAV:
			reg[rd] = (int) reg[rt] >> reg[rs];
			break;
		case ADD:
			reg[rd] = reg[rs] + reg[rt];
			break;
		case ADDU:
			reg[rd] = reg[rs] + reg[rt];
			break;
		case SUB:
			reg[rd] = reg[rs] - reg[rt];
			break;
		case SUBU:
			reg[rd] = reg[rs] - reg[rt];
			break;
		case AND:
			reg[rd] = reg[rs] & reg[rt];
			break;
		case OR:
			reg[rd] = reg[rs] | reg[rt];
			break;
		case XOR:
			reg[rd] = reg[rs] ^ reg[rt];
			break;
		case NOR:
			reg[rd] = ~(reg[rs] | reg[rt]);
			break;
		case MULT:
			p = (int) reg[rs] * (int) reg[rt];
			hi = p >> 32L;
			lo = p & 0x00000000ffffffffL;
			break;
		case MULTU:
			p = (uint64_t) reg[rs] * (uint64_t) reg[rt];
			hi = p >> 32L;
			lo = p & 0x00000000ffffffffL;
			break;
		case DIV:
			lo = (int) reg[rs] / (int) reg[rt];
			hi = (int) reg[rs] % (int) reg[rt];
			break;
		case DIVU:
			lo = reg[rs] / reg[rt];
			hi = reg[rs] % reg[rt];
			break;
		case SLT:
			reg[rd] = ((int) reg[rs] < (int) reg[rt]) ? 1 : 0;
			break;
		case SLTU:
			reg[rd] = (reg[rs] < reg[rt]) ? 1 : 0;
			break;
		case MFHI:
			reg[rd] = hi;
			break;
		case MFLO:
			reg[rd] = lo;
			break;
		case MTHI:
			hi = reg[rs];
			break;
		case MTLO:
			lo = reg[rs];
			break;
		case JR:
			pc = reg[rs];
			break;
		case J:
			pc = (target << 2) | (pc & 0xf0000000);
			break;
		case JAL:
			reg[31] = pc;   // pc has been pre-incremented
			pc = (target << 2) | (pc & 0xf0000000);
			break;
		case JALR:
			reg[31] = pc;
			pc = reg[rs];
			break;
		case BEQ:
			// note pc was pre-incremented
			pc = (reg[rs] == reg[rt]) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case BNE:
			pc = (reg[rs] != reg[rt]) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case BGEZ:
			pc = ((int) reg[rs] >= 0) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case BGTZ:
			pc = ((int) reg[rs] > 0) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case BLEZ:
			pc = ((int) reg[rs] <= 0) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case BLTZ:
			pc = ((int) reg[rs] < 0) ? pc + (signExtend16(imm) << 2) - 4 : pc;
			break;
		case ADDI:
			reg[rt] = reg[rs] + signExtend16(imm);
			break;
		case ADDIU:
			reg[rt] = reg[rs] + signExtend16(imm);;
			break;
		case SLTI:
			reg[rt] = ((int) reg[rs] < (int) signExtend16(imm)) ? 1 : 0;
			break;
		case SLTIU:
			reg[rt] = (reg[rs] < signExtend16(imm)) ? 1 : 0;
			break;
		case ANDI:
			reg[rt] = reg[rs] & imm;
			break;
		case ORI:
			reg[rt] = reg[rs] | imm;
			break;
		case XORI:
			reg[rt] = reg[rs] ^ imm;
			break;
		case LUI:
			reg[rt] = (imm << 16);
			break;
		case LB:
			reg[rt] = signExtend8(M.read8(reg[rs] + signExtend16(imm)));
			break;
		case LH:
			reg[rt] = signExtend16(M.read16(reg[rs] + signExtend16(imm)));
			break;
		case LW:
			reg[rt] = M.read32(reg[rs] + signExtend16(imm));
			break;
		case LBU:
			reg[rt] = M.read8(reg[rs] + signExtend16(imm));
			break;
		case LHU:
			reg[rt] = M.read16(reg[rs] + signExtend16(imm));
			break;
		case SB:
			M.write8(reg[rt], reg[rs] + signExtend16(imm));
			break;
		case SH:
			M.write16(reg[rt], reg[rs] + signExtend16(imm));
			break;
		case SW:
			M.write32(reg[rt], reg[rs] + signExtend16(imm));
			break;
		case SYSCALL:
			switch (reg[2]) {
				case 1:
					printf("%d", reg[4]);
					break;
				case 4:
					printf("%s", M.getMemoryPtr(reg[4]));
					break;
				case 9:
					reg[2] = M.alloc(reg[4]);
					break;
				case 10:
					keepGoing = false;
					break;
				case 11:
					printf("%c", reg[4]);
					break;
				default:
					printf("Undefined syscall code: %d\n", reg[2]);
					//      assert(false && "undefined syscall code");
					break;
			}
			break;
		default:
			printf("undefined opcode: %u\n", opcode);
			assert(false);
			break;
	}
	++instructionCount;
	++itokenCounts[token];
	++xtypeCounts[xtype];
	return keepGoing;
}