long_t get_reg_val(mem_t *r, regid_t id) { long_t val = 0; if (id >= REG_NONE) return 0; get_long_val(r, id*4, &val); return val; }
bool_t diff_mem(mem_t *oldm, mem_t *newm, FILE *outfile) { long_t pos; int len = oldm->len; bool_t diff = FALSE; if (newm->len < len) len = newm->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { long_t ov = 0; long_t nv = 0; get_long_val(oldm, pos, &ov); get_long_val(newm, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "0x%.4x:\t0x%.8x\t0x%.8x\n", pos, ov, nv); } } return diff; }
bool_t diff_reg(mem_t *oldr, mem_t *newr, FILE *outfile) { long_t pos; int len = oldr->len; bool_t diff = FALSE; if (newr->len < len) len = newr->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { long_t ov = 0; long_t nv = 0; get_long_val(oldr, pos, &ov); get_long_val(newr, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "%s:\t0x%.8x\t0x%.8x\n", reg_table[pos/4].name, ov, nv); } } return diff; }
/* * 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; }
int eval_options (int argc, char **argv, struct target_opts* defaults, const char** exe_opts) { const char opt_timeout[] = "-t"; const char opt_data_dir[] = "-d"; const char opt_t_flags[] = "-x"; const char opt_compat[] = "--compat"; const char opt_exit[] = "--exit"; const char opt_help[] = "--help"; const char opt_ignore[] = "--ignore"; const char opt_nocompat[] = "--nocompat"; const char opt_signal[] = "--signal"; const char opt_sleep[] = "--sleep"; const char opt_ulimit[] = "--ulimit"; const char opt_verbose[] = "--verbose"; const char opt_warn[] = "--warn"; int i; assert (0 != argv); assert (0 != defaults); memset (defaults, 0, sizeof (target_opts)); /* The chain of preprocesor logic below initializes the defaults->c_warn and defaults->l_warn values. */ #ifdef __GNUG__ parse_warn_opts ("Gcc", defaults); #elif defined (__HP_aCC) parse_warn_opts ("Acc", defaults); #elif defined (__IBMCPP__) parse_warn_opts ("Xlc", defaults); #elif defined (__SUNPRO_CC) parse_warn_opts ("Sunpro", defaults); #elif defined (SNI) parse_warn_opts ("Cds", defaults); #elif defined (__APOGEE__) /* EDG variant that doesn't define __EDG__. */ parse_warn_opts ("Como", defaults); /* The following are EDG variants, that define __EDG__ */ #elif defined (__DECCXX) parse_warn_opts ("Cxx", defaults); #elif defined (_SGI_COMPILER_VERSION) parse_warn_opts ("Mipspro", defaults); #elif defined (__INTEL_COMPILER) parse_warn_opts ("Icc", defaults); /* So we need to check for __EDG__ after we check for them. */ #elif defined (__EDG__) parse_warn_opts ("Eccp", defaults); #endif if (1 == argc || '-' != argv [1][0]) return 1; for (i = 1; i < argc && '-' == argv [i][0]; ++i) { /* the name of the option being processed */ const char* optname = argv [i]; /* the option's argument, if any */ const char* optarg = 0; char* end = 0; switch (argv [i][1]) { case '?': /* display help and exit with status of 0 */ case 'h': show_usage (0); case 'r': ++i; /* Ignore -r option (makefile compat) */ break; case 't': /* executable timeout in seconds */ optname = opt_timeout; optarg = get_short_val (argv, &i); if (optarg) { if (!isdigit (*optarg)) bad_value (optname, optarg); errno = 0; defaults->timeout = strtol (optarg, &end, 10); if (*end || errno) bad_value (optname, optarg); } else missing_value (optname); break; case 'd': /* directory containing example reference files */ optname = opt_data_dir; defaults->data_dir = get_short_val (argv, &i); if (!defaults->data_dir) missing_value (optname); break; case 'v': /* enable verbose mode */ optname = opt_verbose; ++defaults->verbose; break; case 'x': /* command line options to pass to targets */ optname = opt_t_flags; *exe_opts = get_short_val (argv, &i); if (!*exe_opts) missing_value (optname); break; case '-': /* long options */ { const size_t arglen = strlen (argv [i]); /* abort processing on --, eat token */ if ('\0' == argv [i][2]) return i+1; if ( sizeof opt_compat - 1 == arglen && !memcmp (opt_compat, argv [i], sizeof opt_compat)) { /* enter compatibility mode */ defaults->compat = 1; break; } else if ( sizeof opt_nocompat - 1 == arglen && !memcmp (opt_nocompat, argv [i], sizeof opt_nocompat)) { /* exit compatibility mode */ defaults->compat = 0; break; } else if ( sizeof opt_exit - 1 <= arglen && !memcmp (opt_exit, argv [i], sizeof opt_exit - 1)) { /* exit immediately with the specified status */ optname = opt_exit; optarg = get_long_val (argv, &i, sizeof opt_exit - 1); if (optarg && *optarg) { if (!isdigit (*optarg)) bad_value (optname, optarg); errno = 0; const long code = strtol (optarg, &end, 10); if ('\0' == *end && !errno) exit (code); } } else if ( sizeof opt_help - 1 == arglen && !memcmp (opt_help, argv [i], sizeof opt_help - 1)) { /* display help and exit with status of 0 */ optname = opt_help; show_usage (0); break; } else if ( sizeof opt_sleep - 1 <= arglen && !memcmp (opt_sleep, argv [i], sizeof opt_sleep - 1)) { /* sleep for the specified number of seconds */ optname = opt_sleep; optarg = get_long_val (argv, &i, sizeof opt_sleep - 1); if (optarg && *optarg) { if (!isdigit (*optarg)) bad_value (optname, optarg); errno = 0; const long nsec = strtol (optarg, &end, 10); if ('\0' == *end && 0 <= nsec && !errno) { rw_sleep (nsec); break; } } } else if ( sizeof opt_signal - 1 <= arglen && !memcmp (opt_signal, argv [i], sizeof opt_signal - 1)) { /* send ourselves the specified signal */ optname = opt_signal; optarg = get_long_val (argv, &i, sizeof opt_signal - 1); if (optarg && *optarg) { const int signo = get_signo (optarg); if (0 <= signo) { if (0 > raise (signo)) terminate (1, "raise(%s) failed: %s\n", get_signame (signo), strerror (errno)); break; } } } else if ( sizeof opt_ignore - 1 <= arglen && !memcmp (opt_ignore, argv [i], sizeof opt_ignore - 1)) { /* ignore the specified signal */ optname = opt_ignore; optarg = get_long_val (argv, &i, sizeof opt_ignore - 1); if (optarg && *optarg) { const int signo = get_signo (optarg); if (0 <= signo) { if (rw_signal (signo, 0 /* SIG_IGN */)) terminate (1, "rw_signal(%s, ...) failed: %s\n", get_signame (signo), strerror (errno)); break; } } } else if ( sizeof opt_ulimit - 1 <= arglen && !memcmp (opt_ulimit, argv [i], sizeof opt_ulimit - 1)) { /* set child process resource utilization limits */ optname = opt_ulimit; optarg = get_long_val (argv, &i, sizeof opt_ulimit - 1); if (optarg && *optarg) { if (!parse_limit_opts (optarg, defaults)) { break; } } } else if ( sizeof opt_warn - 1 <= arglen && !memcmp (opt_warn, argv [i], sizeof opt_warn - 1)) { /* set compiler warning mode */ optname = opt_warn; optarg = get_long_val (argv, &i, sizeof opt_warn - 1); if (optarg && *optarg) { if (!parse_warn_opts (optarg, defaults)) { break; } } } /* fall through */ } default: if (optarg) { if (*optarg) bad_value (optname, optarg); else missing_value (optname); } if (argv [i]) bad_option (argv [i]); else missing_value (optname); } } return i; }
/* * 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; }
/* * 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; }