// 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 #ifdef _NEED_DISASM #define _except __except static inline void _except(ctx_t *ctx, int x, char *fmt, ...) { va_list ap; log("Disassembly error: "); va_start(ap, fmt); vlog(fmt, ap); va_end(ap); log("\n"); if (ctx->disf) fclose(ctx->disf); exit(-1); } #endif static void scan_param(ctx_t *ctx, acc_t *p) { ushort c; reg_t *r; c = ctx->get(ctx); if (A_IS_MEM(c)) { p->mem = 1; p->off = 0; p->mlen = c & 0xF; c = ctx->get(ctx); } else if (A_IS_OFF(c)) { p->mem = 1; p->mlen = c & 0xF; p->off = (short)ctx->get(ctx); p->offreg = ctx->get(ctx); if (p->offreg > NREGS) { _except(ctx, E_ILL, "Inexistent REG (offreg)"); } if (p->offreg != INV) { r = &ctx->r[p->offreg]; if (r->flags & (RES | CTL)) { _except(ctx, E_ACC, "Reserved REG (offreg): %s", r->name); } } c = ctx->get(ctx); } if (c >= A_IMM16) { // Check for double access code if (p->type != A_REG) _except(ctx, E_ILL, "Bad access code"); p->type = c; c = ctx->get(ctx); } p->val = c; if (p->type == A_IMM32) { p->ilen = 4; p->val = p->val | ((ulong)ctx->get(ctx) << 16); } else if (p->type == A_IMM64) { p->ilen = 8; p->val = p->val | ((ulong)ctx->get(ctx) << 16); p->val = p->val | ((ulong)ctx->get(ctx) << 32); p->val = p->val | ((ulong)ctx->get(ctx) << 48); } else if (p->type == A_REG) { if (p->val > NREGS) { _except(ctx, E_ILL, "Inexistent REG"); } r = &ctx->r[p->val]; if (r->flags & (RES | CTL)) { _except(ctx, E_ACC, "Reserved REG: %s", r->name); } } } #ifndef _NEED_DISASM void decode(ctx_t *ctx) #else void disasm(ctx_t *ctx) #endif { instr_t *i; acc_t p1 = { 0 }, p2 = { 0 }; uint rep = 0; ulong orig_rip = rip; ushort c = ctx->get(ctx); if (ISPREF(c)) { if (c == PREF_REP) { rep = 1; c = ctx->get(ctx); } } else if (!ISINSTR(c)) { _except(ctx, E_ILL, "Bad opcode: 0x%04hX", c); } i = &ctx->i[c]; // Scan for parameters if (i->prm1 != NOPRM) { scan_param(ctx, &p1); if (i->prm2 != NOPRM) { scan_param(ctx, &p2); } } #ifdef _NEED_DISASM dumpinstr(ctx, orig_rip, rep, c, &p1, &p2); #else do_rep: dumpinstr(ctx, orig_rip, rep, c, &p1, &p2); i->func(ctx, &p1, &p2); if (rep && rcx > 0) { rcx--; goto do_rep; } #endif }