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-22 18:39:46 +02:00
|
|
|
p->len = 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-22 18:39:46 +02:00
|
|
|
p->len = 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) {
|
|
|
|
p->val = (p->val << 16) | ctx->get(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (p->type == A_IMM64) {
|
|
|
|
p->val = (p->val << 16) | ctx->get(ctx);
|
|
|
|
p->val = (p->val << 16) | ctx->get(ctx);
|
|
|
|
p->val = (p->val << 16) | ctx->get(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
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-15 19:26:40 +02:00
|
|
|
// nothing for now
|
|
|
|
}
|
|
|
|
|
|
|
|
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-16 10:03:01 +02:00
|
|
|
dumpinstr(ctx, rip, c, &p1, &p2);
|
2019-05-16 21:42:23 +02:00
|
|
|
|
|
|
|
#ifndef _NEED_DISASM
|
2019-05-15 19:26:40 +02:00
|
|
|
i->func(ctx, &p1, &p2);
|
2019-05-16 21:42:23 +02:00
|
|
|
#endif
|
2019-05-15 19:26:40 +02:00
|
|
|
}
|
|
|
|
|