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; }
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; }