/* * nexti: execute single instruction and return status. * args * sim: the y86 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address, data address, stack address, ... * STAT_INS: invalid instruction, register id, ... */ stat_t nexti(y86sim_t *sim) { byte_t codefun = 0; itype_t icode; alu_t ifun; long_t valP = sim->pc; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, valP, &codefun)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); valP++; /* get registers if needed (1 byte) */ byte_t byte; long_t valA, valB, valC, val; regid_t regA, regB; if ((icode>1 && icode<7) || icode==I_PUSHL || icode==I_POPL) { if (!get_byte_val(sim->m, valP, &byte)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP++; regA = HIGH(byte); regB = LOW(byte); } /* get immediate if needed (4 bytes) */ if (icode>=3 && icode<=8 && icode!=I_ALU) { if (!get_long_val(sim->m, valP, &valC)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP+=4; } /* execute the instruction */ switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = valP; break; case I_RRMOVL: sim->pc = valP; if (!cond_doit(sim->cc,ifun)) break; val = get_reg_val(sim->r, regA); set_reg_val(sim->r, regB, val); break; /* 2:x regA:regB */ case I_IRMOVL: set_reg_val(sim->r, regB, valC); sim->pc = valP; break; /* 3:0 F:regB imm */ case I_RMMOVL: valC += get_reg_val(sim->r, regB); val = get_reg_val(sim->r, regA); set_long_val(sim->m, valC, val); sim->pc = valP; break; /* 4:0 regA:regB imm */ case I_MRMOVL: valC += get_reg_val(sim->r, regB); if (!get_long_val(sim->m, valC, &val)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } set_reg_val(sim->r, regA, val); sim->pc = valP; break; /* 5:0 regB:regA imm */ case I_ALU: valA = get_reg_val(sim->r,regA); valB = get_reg_val(sim->r,regB); val = compute_alu(ifun, valA, valB); set_reg_val(sim->r, regB, val); sim->cc = compute_cc(ifun, valA, valB, val); sim->pc = valP; break; /* 6:x regA:regB */ case I_JMP: sim->pc = (cond_doit(sim->cc,ifun))?valC:valP; break; /* 7:x imm */ case I_CALL: val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valP)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valC; break; /* 8:x imm */ case I_RET: valA = get_reg_val(sim->r, REG_ESP); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, REG_ESP, valA+4); sim->pc = valB; break; /* 9:0 */ case I_PUSHL: valA = get_reg_val(sim->r, regA); val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valA)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valP; break; /* A:0 regA:F */ case I_POPL: valA = get_reg_val(sim->r, REG_ESP); set_reg_val(sim->r, REG_ESP, valA+4); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, regA, valB); sim->pc = valP; break; /* B:0 regA:F */ default: err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }
/* * nexti: execute single instruction and return status. * args * sim: the y86 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address * STAT_INS: invalid instruction, register id, data address, stack address, ... */ stat_t nexti(y86sim_t *sim) { byte_t codefun = 0; itype_t icode; alu_t ifun; long_t next_pc = sim->pc; regid_t rA = REG_NONE; regid_t rB = REG_NONE; long_t im_value = 0; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, next_pc, &codefun)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); next_pc++; /* get registers if needed (1 byte) */ byte_t reg = 0; switch (icode) { case I_RRMOVL: case I_IRMOVL: case I_RMMOVL: case I_MRMOVL: case I_ALU: case I_PUSHL: case I_POPL: if(!get_byte_val(sim->m, next_pc, ®)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } rA = GET_REGA(reg); rB = GET_REGB(reg); next_pc++; case I_HALT:case I_NOP:case I_JMP:case I_CALL:case I_RET:default: break; } /* get immediate if needed (4 bytes) */ switch(icode) { case I_IRMOVL: case I_RMMOVL: case I_MRMOVL: case I_JMP: case I_CALL: if(!get_long_val(sim->m, next_pc, &im_value)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } next_pc += 4; case I_HALT:case I_NOP:case I_RRMOVL:case I_ALU: case I_RET:case I_PUSHL:case I_POPL:default: break; } /* execute the instruction */ switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = next_pc; break; case I_RRMOVL:/* 2:x regA:regB */ { long_t rr_temp = get_reg_val(sim->r, rA); if (cond_doit(sim->cc, ifun)) set_reg_val(sim->r, rB, rr_temp); sim->pc = next_pc; break; } case I_IRMOVL: /* 3:0 F:regB imm */ { set_reg_val(sim->r, rB, im_value); sim->pc = next_pc; break; } case I_RMMOVL: /* 4:0 regA:regB imm */ { long_t rm_temp_rA = get_reg_val(sim->r, rA); long_t rm_temp_rB = get_reg_val(sim->r, rB); set_long_val(sim->m, im_value+rm_temp_rB, rm_temp_rA); sim->pc = next_pc; break; } case I_MRMOVL: /* 5:0 regB:regA imm */ { long_t mr_temp_rB = get_reg_val(sim->r, rB); long_t temp_val = 0; if(!get_long_val(sim->m, im_value+mr_temp_rB, &temp_val)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, im_value+mr_temp_rB); return STAT_ADR; } set_reg_val(sim->r, rA, temp_val); sim->pc = next_pc; break; } case I_ALU: /* 6:x regA:regB */ { long_t rA_val = get_reg_val(sim->r, rA); long_t rB_val = get_reg_val(sim->r, rB); long_t alu_result = 0; switch (ifun) { case A_ADD:case A_SUB:case A_AND:case A_XOR: alu_result = compute_alu(ifun, rA_val, rB_val); set_reg_val(sim->r, rB, alu_result); break; case A_NONE:default: return STAT_INS; } sim->cc = compute_cc(ifun, rA_val, rB_val, alu_result); sim->pc = next_pc; break; } case I_JMP: /* 7:x imm */ { if (cond_doit(sim->cc, ifun)) sim->pc = im_value; else sim->pc=next_pc; break; } case I_CALL: /* 8:x imm */ { long_t esp = get_reg_val(sim->r, REG_ESP); esp -= 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_long_val(sim->m, esp, next_pc); sim->pc = im_value; break; } case I_RET: /* 9:0 */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t return_value = 0; if(!get_long_val(sim->m, esp, &return_value)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, esp); return STAT_ADR; } esp += 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } sim->pc = return_value; break; } case I_PUSHL: /* A:0 regA:F */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t rA_value = get_reg_val(sim->r, rA); esp -= 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_long_val(sim->m, esp, rA_value); sim->pc = next_pc; break; } case I_POPL: /* B:0 regA:F */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t temp_value = 0; if(!get_long_val(sim->m, esp, &temp_value)) { err_print("PC = 0x%x, Invalid instruction address", esp); return STAT_ADR; } esp += 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_reg_val(sim->r, rA, temp_value); sim->pc = next_pc; break; } return STAT_INS; /* unsupported now, replace it with your implementation */ break; default: err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }
void set_reg_val(mem_t *r, regid_t id, long_t val) { if (id < REG_NONE) set_long_val(r, id*4, val); }
/* * nexti: execute single instruction and return status. * args * sim: the y64 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address * STAT_INS: invalid instruction, register id, data address, stack address, ... */ stat_t nexti(y64sim_t *sim) { byte_t codefun = 0; /* 1 byte */ itype_t icode; alu_t ifun; long_t next_pc = sim->pc; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, next_pc, &codefun)) { err_print("PC = 0x%lx, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); next_pc++; /* get registers if needed (1 byte) */ byte_t rArB = 0; regid_t rA = REG_ERR, rB = REG_ERR; if((icode == I_RRMOVQ) || (icode == I_ALU) || (icode == I_RMMOVQ) || (icode == I_PUSHQ) || (icode == I_POPQ) || (icode == I_IRMOVQ) || (icode == I_MRMOVQ) ){ get_byte_val(sim->m, next_pc, &rArB); rA = GET_REGA(rArB); rB = GET_REGB(rArB); next_pc++; } /* get immediate if needed (8 bytes) */ long_t valC; if(icode == I_IRMOVQ || icode == I_RMMOVQ ||icode == I_MRMOVQ || icode == I_JMP || icode == I_CALL){ get_long_val(sim->m,next_pc,&valC); next_pc += 8; } /* execute the instruction*/ long_t valA,valB,valE,valM; switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = next_pc; break; case I_RRMOVQ: /* 2:x regA:regB */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r,rA); valE = valA + 0; if(cond_doit(sim->cc, ifun)) set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_IRMOVQ: /* 3:0 F:regB imm */ if(!NORM_REG(rB) || !NONE_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = 0 + valC; set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_RMMOVQ: /* 4:0 regA:regB imm */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = valB + valC; if(!set_long_val(sim->m, valE, valA)){ err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = next_pc; break; case I_MRMOVQ: /* 5:0 regB:regA imm */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = valB + valC; if(!get_long_val(sim->m, valE, &valM)){ err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE); return STAT_ADR; } set_reg_val(sim->r, rA, valM); sim->pc = next_pc; break; case I_ALU: /* 6:x regA:regB */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = compute_alu(ifun, valA, valB); sim->cc = compute_cc(ifun, valA, valB, valE); set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_JMP: /* 7:x imm */ if(ifun > 6){ err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } sim->pc = cond_doit(sim->cc,ifun)? valC : next_pc; break; case I_CALL: /* 8:x imm */ valB = get_reg_val(sim->r, REG_RSP); valE = valB + (-8); set_reg_val(sim->r, REG_RSP, valE); if(!set_long_val(sim->m, valE, next_pc)){ err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = valC; break; case I_RET: /* 9:0 */ valA = get_reg_val(sim->r, REG_RSP); valB = valA; valE = valB + 8; get_long_val(sim->m, valA, &valM); set_reg_val(sim->r, REG_RSP, valE); sim->pc = valM; break; case I_PUSHQ: /* A:0 regA:F */ if(!NORM_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, REG_RSP); valE = valB + (-8); set_reg_val(sim->r, REG_RSP, valE); if(!set_long_val(sim->m, valE, valA)){ err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = next_pc; break; case I_POPQ: /* B:0 regA:F */ if(!NORM_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, REG_RSP); valB = valA; valE = valB + 8; get_long_val(sim->m, valA, &valM); set_reg_val(sim->r, REG_RSP, valE); set_reg_val(sim->r, rA, valM); sim->pc = next_pc; break; // return STAT_INS; /* unsupported now, replace it with your implementation */ default: err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }