// The OS/K Team licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include bool eval_cond(ctx_t *ctx, uint cond) { bool neg = cond & (1 << 4); bool ok; cond &= ~(1 << 4); switch (cond) { case CD_NONE: ok = 1; break; case CD_C: ok = flg&CF; break; case CD_O: ok = flg&OF; break; case CD_Z: ok = flg&ZF; break; case CD_S: ok = flg&SF; break; case CD_P: ok = flg&PF; break; case CD_A: ok = !(flg&CF || flg&ZF); break; case CD_AE: ok = !(flg&CF); break; case CD_B: ok = flg&CF; break; case CD_BE: ok = flg&CF || flg&ZF; break; case CD_G: ok = !(flg&ZF) && (!(flg&SF) == !(flg&OF)); break; case CD_GE: ok = !(flg&SF) == !(flg&OF); break; case CD_L: ok = !(flg&SF) != !(flg&OF); break; case CD_LE: ok = flg&ZF || (!(flg&SF) != !(flg&OF)); break; case CD_CXZ: ok = !rcx; break; default: _except(ctx, E_ILL, "Invalid COND value: 0x%x", (neg?cond|(1<<4):cond)); } return neg ? !ok : !!ok; } // // Executes an instruction // void exec_instr(ctx_t *ctx, instr_t *in, acc_t *p1, acc_t *p2, bool lock, bool rep, uint cond) { bool out; ulong r1 = 0, r2 = 0; // Global instruction counter ctx->ninstrs++; // Current frame instruction counter rx2++; // since last frame change rx1++; // since startup // // For REPs we evaluate the condition AFTER running the instruction, // in a do ... while(cond) fashion // if (!rep && !eval_cond(ctx, cond)) { #ifndef NDEBUG // Say something about ignored instruction? //trace("0x%lX:\n", rpc); #endif return; } #ifndef NDEBUG dump_instr(ctx, in, p1, p2, lock, rep, cond); #endif do_rep: out = in->func(ctx, p1, p2, &r1, &r2); if (out) { if (p1->type == A_REG) R(p1->reg) = r1; else if (p1->type == A_IMM64) _except(ctx, E_ACC, "Trying to output to an IMM64"); else { assert(ACC_IS_MEM(p1)); writemem(ctx, r1, p1->addr, p1->mlen); } } if (out == 2) { if (p2->type == A_REG) R(p2->reg) = r2; else if (p2->type == A_IMM64) _except(ctx, E_ACC, "Trying to output to an IMM64"); else { assert(ACC_IS_MEM(p2)); writemem(ctx, r2, p2->addr, p2->mlen); } } if (rep) { // RCX remains untouched when condition fails if (!eval_cond(ctx, cond)) return; if (rcx > 0) rcx--; if (rcx == 0) return; ctx->ninstrs++; #ifndef NDEBUG // Show that we're REP'ing dump_instr(ctx, in, p1, p2, lock, rep, cond); #endif goto do_rep; } }