// 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 #define rfx R(RFX) 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 = rfx&CF; break; case CD_O: ok = rfx&OF; break; case CD_Z: ok = rfx&ZF; break; case CD_S: ok = rfx&SF; break; case CD_P: ok = rfx&PF; break; case CD_BE: ok = rfx&CF || rfx&ZF; break; case CD_L: ok = !(rfx&SF) != !(rfx&OF); break; case CD_LE: ok = rfx&ZF || (!(rfx&SF) != !(rfx&OF)); break; case CD_AXZ: ok = !R(RAX); break; case CD_BXZ: ok = !R(RBX); break; case CD_CXZ: ok = !R(RCX); break; case CD_DXZ: ok = !R(RDX); break; default: _except(ctx, E_ILL, "Invalid COND value: 0x%x", (neg?cond|(1<<4):cond)); } return neg ? !ok : !!ok; } #define OUTPUT(p, r) { \ if (p->type == A_REG) \ R(p->reg) = r; \ else if (p1->type == A_IMM64) \ _except(ctx, E_ACC, "Trying to output to an IMM64"); \ else { \ assert(ACC_IS_MEM(p)); \ writemem(ctx, r, p->addr, p->mlen); \ } } // // Executes an instruction // void exec_instr(ctx_t *ctx, instr_t *in, acc_t *p1, acc_t *p2, acc_t *p3, bool lock, bool rep) { uint out; ulong r1 = 0, r2 = 0, r3 = 0; // Global instruction counter ctx->ninstrs++; // // For REPs we evaluate the condition AFTER running the instruction, // in a do ... while(cond) fashion // if (ctx->cond && in->func != i_b) // 'B' instruction is special if (!rep && !eval_cond(ctx, ctx->cond)) return; if (ctx->dumpsw) dump_instr(ctx, in, p1, p2, p3, lock, rep); do_rep: out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3); if (out) { OUTPUT(p1, r1); if (out >= 2) OUTPUT(p2, r2); if (out >= 3) OUTPUT(p3, r3); R(RZX) = 0; } if (rep) { // RCX remains untouched when condition fails if (!eval_cond(ctx, ctx->cond)) return; if (R(RCX) > 0) R(RCX)--; if (R(RCX) == 0) return; // Should we really count REP's in instruction count? ctx->ninstrs++; #if 0 // Show that we're REP'ing if (ctx->dumpsw) dump_instr(ctx, in, p1, p2, p3, lock, rep); #endif goto do_rep; } }