kvisc/pc/decd.c

138 lines
2.6 KiB
C
Raw Normal View History

2019-05-15 20:06:45 +02:00
// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2019-05-15 19:26:40 +02:00
#include "arch.h"
2019-05-16 21:42:23 +02:00
#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)
2019-05-15 19:26:40 +02:00
{
ushort c;
reg_t *r;
c = ctx->get(ctx);
2019-05-22 18:39:46 +02:00
if (A_IS_MEM(c)) {
2019-05-15 19:26:40 +02:00
p->mem = 1;
2019-05-16 16:48:45 +02:00
p->off = 0;
2019-05-29 16:57:22 +02:00
p->mlen = c & 0xF;
2019-05-16 16:48:45 +02:00
c = ctx->get(ctx);
}
2019-05-22 18:39:46 +02:00
else if (A_IS_OFF(c)) {
2019-05-16 16:48:45 +02:00
p->mem = 1;
2019-05-29 16:57:22 +02:00
p->mlen = c & 0xF;
2019-05-16 16:48:45 +02:00
p->off = (short)ctx->get(ctx);
2019-05-15 19:26:40 +02:00
c = ctx->get(ctx);
}
if (c >= A_IMM16) {
2019-05-16 21:42:23 +02:00
// Check for double access code
if (p->type != A_REG)
_except(ctx, E_ILL, "Bad access code");
2019-05-15 19:26:40 +02:00
p->type = c;
c = ctx->get(ctx);
}
p->val = c;
if (p->type == A_IMM32) {
2019-05-29 16:57:22 +02:00
p->ilen = 4;
p->val = p->val | ((ulong)ctx->get(ctx) << 16);
2019-05-15 19:26:40 +02:00
}
else if (p->type == A_IMM64) {
2019-05-29 16:57:22 +02:00
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);
2019-05-15 19:26:40 +02:00
}
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)) {
2019-05-22 18:39:46 +02:00
_except(ctx, E_ACC, "Reserved REG: %s", r->name);
2019-05-15 19:26:40 +02:00
}
}
}
2019-05-16 21:42:23 +02:00
#ifndef _NEED_DISASM
2019-05-15 19:26:40 +02:00
void decode(ctx_t *ctx)
2019-05-16 21:42:23 +02:00
#else
void disasm(ctx_t *ctx)
#endif
2019-05-15 19:26:40 +02:00
{
instr_t *i;
acc_t p1 = { 0 }, p2 = { 0 };
2019-05-16 10:03:01 +02:00
2019-05-29 16:57:22 +02:00
uint rep = 0;
2019-05-16 10:03:01 +02:00
ulong rip = ctx->r[RIP].val;
2019-05-15 19:26:40 +02:00
ushort c = ctx->get(ctx);
2019-05-16 21:42:23 +02:00
if (ISPREF(c)) {
2019-05-29 16:57:22 +02:00
if (c == PREF_REP) {
rep = 1;
c = ctx->get(ctx);
}
2019-05-15 19:26:40 +02:00
}
else if (!ISINSTR(c)) {
2019-05-22 18:39:46 +02:00
_except(ctx, E_ILL, "Bad opcode: 0x%04hX", c);
2019-05-15 19:26:40 +02:00
}
i = &ctx->i[c];
// Scan for parameters
2019-05-15 21:47:08 +02:00
if (i->prm1 != NOPRM) {
2019-05-15 19:26:40 +02:00
scan_param(ctx, &p1);
2019-05-15 21:47:08 +02:00
if (i->prm2 != NOPRM) {
2019-05-15 19:26:40 +02:00
scan_param(ctx, &p2);
}
}
2019-05-16 21:42:23 +02:00
2019-05-29 18:26:28 +02:00
#ifdef _NEED_DISASM
2019-05-29 16:57:22 +02:00
dumpinstr(ctx, rip, rep, c, &p1, &p2);
2019-05-29 18:26:28 +02:00
#else
2019-05-16 21:42:23 +02:00
2019-05-29 16:57:22 +02:00
do_rep:
2019-05-30 11:19:16 +02:00
dumpinstr(ctx, rip, rep, c, &p1, &p2);
2019-05-15 19:26:40 +02:00
i->func(ctx, &p1, &p2);
2019-05-29 16:57:22 +02:00
2019-05-29 18:26:28 +02:00
2019-05-29 16:57:22 +02:00
if (rep && ctx->r[RCX].val > 0) {
2019-05-29 18:26:28 +02:00
log("rcx::%lu\n", ctx->r[RCX].val);
2019-05-29 16:57:22 +02:00
ctx->r[RCX].val--;
goto do_rep;
}
2019-05-16 21:42:23 +02:00
#endif
2019-05-15 19:26:40 +02:00
}