1
0
8086/src/sim8086.c

127 lines
3.7 KiB
C

static const char *reg_to_str(enum reg_value reg) {
const char *reg_value_str[__REG_COUNT] = {
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"
};
assert(0 <= reg && reg <= __REG_COUNT);
return reg_value_str[reg];
}
static void mem_to_str(char *buff, size_t max_size, struct mem_value *mem) {
const char *mem_base_str[8] = {
"bx + si",
"bx + di",
"bp + si",
"bp + di",
"si",
"di",
"bp",
"bx"
};
assert(0 <= mem->base && mem->base <= __MEM_BASE_COUNT);
if (mem->base == MEM_BASE_DIRECT_ADDRESS) {
snprintf(buff, max_size, "[%d]", (u16)mem->disp);
} else if (mem->disp > 0) {
snprintf(buff, max_size, "[%s + %d]", mem_base_str[mem->base], mem->disp);
} else if (mem->disp < 0) {
snprintf(buff, max_size, "[%s - %d]", mem_base_str[mem->base], -mem->disp);
} else {
snprintf(buff, max_size, "[%s]", mem_base_str[mem->base]);
}
}
static void reg_or_mem_to_str(char *buff, size_t max_size, struct reg_or_mem_value *value) {
if (value->is_reg) {
strncpy(buff, reg_to_str(value->reg), max_size);
} else {
mem_to_str(buff, max_size, &value->mem);
}
}
static void src_to_str(char *buff, size_t max_size, struct src_value *value) {
switch (value->variant) {
case SRC_VALUE_REG:
strncpy(buff, reg_to_str(value->reg), max_size);
break;
case SRC_VALUE_MEM:
mem_to_str(buff, max_size, &value->mem);
break;
case SRC_VALUE_IMMEDIATE16:
snprintf(buff, max_size, "%d", value->immediate);
break;
case SRC_VALUE_IMMEDIATE8:
snprintf(buff, max_size, "%d", (u8)value->immediate);
break;
}
}
static const char *operation_to_str(enum operation op) {
const char *operation_str[__OP_COUNT] = {
"mov", "add", "sub", "cmp", "je", "jl", "jle", "jb", "jbe", "jp", "jo",
"js", "jne", "jnl","jnle", "jnb", "jnbe", "jnp", "jno", "jns", "loop",
"loopz", "loopnz", "jcxz"
};
assert(0 <= op && op <= __OP_COUNT);
return operation_str[op];
}
static void instruction_to_str(char *buff, size_t max_size, struct instruction *inst) {
switch (inst->op) {
case OP_MOV:
case OP_CMP:
case OP_SUB:
case OP_ADD: {
char dest[32];
char src[32];
const char *opcode = operation_to_str(inst->op);
reg_or_mem_to_str(dest, sizeof(dest), &inst->dest);
src_to_str(src, sizeof(src), &inst->src);
bool is_dest_mem = !inst->dest.is_reg;
if (is_dest_mem && inst->src.variant == SRC_VALUE_IMMEDIATE16) {
snprintf(buff, max_size, "%s %s, word %s", opcode, dest, src);
} else if (is_dest_mem && inst->src.variant == SRC_VALUE_IMMEDIATE8) {
snprintf(buff, max_size, "%s %s, byte %s", opcode, dest, src);
} else {
snprintf(buff, max_size, "%s %s, %s", opcode, dest, src);
}
break;
}
case OP_JE:
case OP_JL:
case OP_JLE:
case OP_JB:
case OP_JBE:
case OP_JP:
case OP_JO:
case OP_JS:
case OP_JNE:
case OP_JNL:
case OP_JNLE:
case OP_JNB:
case OP_JNBE:
case OP_JNP:
case OP_JNO:
case OP_LOOP:
case OP_LOOPZ:
case OP_LOOPNZ:
case OP_JCXZ:
case OP_JNS: {
const char *opcode = operation_to_str(inst->op);
i8 offset = inst->jmp_offset+2;
if (offset >= 0) {
snprintf(buff, max_size, "%s $+%d", opcode, offset);
} else {
snprintf(buff, max_size, "%s $%d", opcode, offset);
}
break;
}
default:
panic("Invalid instruction opcode %d\n", inst->op);
}
}