ADD instruction sign extension bit handled and deleting old code
This commit is contained in:
parent
26c07aee61
commit
021c4573fa
175
decode.c
175
decode.c
@ -30,12 +30,6 @@ static char* reg_name(Register reg, char wide)
|
||||
return wide == 1 ? reg.fullname : reg.bytename;
|
||||
}
|
||||
|
||||
static i16 get_data(unsigned char* buf, char wide)
|
||||
{
|
||||
// Cast buf[0] to sbyte if not the conversion to i16 won't detect signedness
|
||||
return wide == 1 ? (i16)buf[1] << 8 | buf[0] : (sbyte)buf[0];
|
||||
}
|
||||
|
||||
static u8 mask_and_shift(u8 value, u8 mask)
|
||||
{
|
||||
value &= mask;
|
||||
@ -101,10 +95,19 @@ ParsedInstruction parse_instruction(u8* buf)
|
||||
// This is a trick because mod == 1 and mod == 2 will displace one and two bytes
|
||||
// respectively but mod == 3 wraps to 0 since it doesn't displace
|
||||
if (fmt.has_displacement) idx += mod_opt.value % 3;
|
||||
u16 data = w_opt.value != 0 ? (i16)buf[idx+1] << 8 | buf[idx] : (sbyte)buf[idx];
|
||||
data_opt = some_u16(data);
|
||||
u16 data;
|
||||
if (fmt.has_s && s_opt.value == 1)
|
||||
{
|
||||
data = (sbyte)buf[idx];
|
||||
bytes_read += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = w_opt.value != 0 ? (i16)buf[idx+1] << 8 | buf[idx] : (sbyte)buf[idx];
|
||||
bytes_read += w_opt.value == 0 ? 1 : 2;
|
||||
}
|
||||
data_opt = some_u16(data);
|
||||
}
|
||||
if (fmt.has_displacement && mod_opt.value % 3 > 0)
|
||||
{
|
||||
u16 disp = mod_opt.value == MODE_MEM_DIS_16
|
||||
@ -153,7 +156,8 @@ Instruction decode_instruction(ParsedInstruction inst)
|
||||
opr1.tag = OPR_T_IMMEDIATE;
|
||||
opr1.imm.value = inst.data.value;
|
||||
// TODO: This is dumb, we shouldn't do it this way
|
||||
opr1.imm.direct = inst.w.value + 1;
|
||||
if (inst.s.value == 1) opr1.imm.direct = 0;
|
||||
else opr1.imm.direct = inst.w.value + 1;
|
||||
}
|
||||
if (mod == MODE_RGSTR_MODE)
|
||||
{
|
||||
@ -247,159 +251,6 @@ void get_instr_string(char* str_buf, Instruction inst)
|
||||
sprintf(str_buf, "%s %s, %s", inst.operation, dst_str, src_str);
|
||||
}
|
||||
|
||||
bool mov_inst(FILE* f, unsigned char* buf, char inst)
|
||||
{
|
||||
size_t bytes_read;
|
||||
// Register/memory to/from register
|
||||
if ((inst & ~0x3) == (char)0b10001000)
|
||||
{
|
||||
// TODO: We should add some form of error handling here
|
||||
bytes_read = fread(buf, sizeof(char), 1, f);
|
||||
char next_byte = buf[0];
|
||||
char w = inst & 0b00000001;
|
||||
char d = (inst & 0b00000010) >> 1;
|
||||
char mod = (next_byte & 0b11000000) >> 6;
|
||||
char reg = (next_byte & 0b00111000) >> 3;
|
||||
char rm = (next_byte & 0b00000111);
|
||||
if (mod == MODE_RGSTR_MODE)
|
||||
{
|
||||
Register src_reg = d == 0 ? registers[(size_t)reg] : registers[(size_t)rm];
|
||||
Register dst_reg = d == 0 ? registers[(size_t)rm] : registers[(size_t)reg];
|
||||
printf("mov %s, %s ;0", reg_name(dst_reg, w), reg_name(src_reg, w));
|
||||
}
|
||||
else
|
||||
{
|
||||
bool is_direct_addr = mod == 0 && rm == 0b110;
|
||||
int bytes_to_read = is_direct_addr ? 2 : mod % 3;
|
||||
bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
char* eac_name = is_direct_addr ? "" : get_eac_register(rm);
|
||||
char disp_buf[16] = {'\0'};
|
||||
if (bytes_to_read > 0)
|
||||
{
|
||||
i16 disp = get_data(buf, bytes_to_read - 1);
|
||||
if (is_direct_addr) sprintf(disp_buf, "%d", abs(disp));
|
||||
else sprintf(disp_buf, " %s %d", disp >= 0 ? "+" : "-", abs(disp));
|
||||
}
|
||||
Register rgstr = registers[(size_t)reg];
|
||||
if (d) printf("mov %s, [%s%s] ;1", reg_name(rgstr, w), eac_name, disp_buf);
|
||||
else printf("mov [%s%s], %s ;2", eac_name, disp_buf, reg_name(rgstr, w));
|
||||
}
|
||||
}
|
||||
// Immediate to register/memory
|
||||
else if ((inst & ~0x1) == (char)0b11000110)
|
||||
{
|
||||
bytes_read = fread(buf, sizeof(char), 1, f);
|
||||
char w = inst & 0b00000001;
|
||||
char mod = (buf[0] & 0b11000000) >> 6;
|
||||
char rm = (buf[0] & 0b00000111);
|
||||
int bytes_to_read = 1;
|
||||
bytes_to_read += w == 0 ? 0 : 1;
|
||||
// Same trick from earlier, see comment
|
||||
bytes_to_read += mod % 3;
|
||||
bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
char *eac_name = get_eac_register(rm);
|
||||
i16 data = get_data(buf + (char)bytes_to_read - (w == 0 ? 1 : 2), w);
|
||||
char *word_str = w == 0 ? "byte" : "word";
|
||||
char disp_str[16] = {'\0'};
|
||||
if (mod % 3 > 1) sprintf(disp_str, " + %d", get_data(buf, (mod % 3) - 1));
|
||||
printf("mov [%s%s], %s %d ;3", eac_name, disp_str, word_str, data);
|
||||
}
|
||||
// Immediate to register
|
||||
else if ((inst & ~0xF) == (char)0b10110000)
|
||||
{
|
||||
char w = (inst & 0b00001000) >> 3;
|
||||
Register reg = registers[(size_t)inst & 0b00000111];
|
||||
char bytes_to_read = w == 1 ? 2 : 1;
|
||||
bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
printf("mov %s, %d ;4", reg_name(reg, w), get_data(buf, w));
|
||||
}
|
||||
// Memory/accumulator to accumulator/memory
|
||||
else if ((inst & ~0x3) == (char)0b10100000)
|
||||
{
|
||||
// This instruction uses AX/AL register exclusively
|
||||
Register ax_al = registers[0];
|
||||
char w = (inst & 0b00000001);
|
||||
// The manual doesn't refer to this as `d` but it acts similarly in that this bit
|
||||
// swaps the accumulator's src/dst position
|
||||
char d = (inst & 0b00000010) >> 1;
|
||||
char bytes_to_read = w == 1 ? 2 : 1;
|
||||
bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
if (d) printf("mov [%d], %s ;5", get_data(buf, w), reg_name(ax_al, w));
|
||||
else printf("mov %s, [%d] ;6", reg_name(ax_al, w), get_data(buf, w));
|
||||
}
|
||||
// Register/memory to segment register or segment register to register/memory
|
||||
else if ((inst & ~0x3) == (char)0b10001100)
|
||||
{
|
||||
// Manual doesn't refer to this as `d` but swaps like in the previous instruction
|
||||
char d = (inst & 0b00000010) >> 1;
|
||||
(void)d;
|
||||
printf("mov regmem to segreg");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return bytes_read > 0;
|
||||
}
|
||||
|
||||
bool add_inst(FILE* f, unsigned char* buf, char inst)
|
||||
{
|
||||
size_t bytes_read;
|
||||
if ((inst & ~0x3) == (char)0b00000000)
|
||||
{
|
||||
bytes_read = fread(buf, sizeof(char), 1, f);
|
||||
char next_byte = buf[0];
|
||||
char w = inst & 0b00000001;
|
||||
char d = (inst & 0b00000010) >> 1;
|
||||
char mod = (next_byte & 0b11000000) >> 6;
|
||||
char reg = (next_byte & 0b00111000) >> 3;
|
||||
char rm = (next_byte & 0b00000111);
|
||||
// Same trick from earlier, see comment
|
||||
int bytes_to_read = mod % 3;
|
||||
if (bytes_to_read > 0) bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
Register rgstr = registers[(size_t)reg];
|
||||
(void)rm;
|
||||
if (mod == MODE_RGSTR_MODE)
|
||||
{
|
||||
if (d) printf("add %s, [%d] ;7", reg_name(rgstr, w), get_data(buf, w));
|
||||
else printf("add [%d], %s ;8", get_data(buf, w), reg_name(rgstr, w));
|
||||
}
|
||||
else if (mod == MODE_MEM_NO_DIS)
|
||||
{
|
||||
if (d) printf("add %s, [%s] ;9", reg_name(rgstr, w), get_eac_register(rm));
|
||||
else printf("add [%s], %s ;10", get_eac_register(rm), reg_name(rgstr, w));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d) printf("add %s, [%s] ;11", reg_name(rgstr, w), get_eac_register(rm));
|
||||
else printf("add [%s], %s ;12", get_eac_register(rm), reg_name(rgstr, w));
|
||||
}
|
||||
}
|
||||
else if ((inst & ~0x3) == (char)0b10000000)
|
||||
{
|
||||
bytes_read = fread(buf, sizeof(char), 1, f);
|
||||
char w = inst & 0b00000001;
|
||||
char mod = (buf[0] & 0b11000000) >> 6;
|
||||
char rm = (buf[0] & 0b00000111);
|
||||
int bytes_to_read = 1;
|
||||
bytes_to_read += w == 0 ? 1 : 2;
|
||||
// Same trick from earlier, see comment
|
||||
bytes_to_read += mod % 3;
|
||||
bytes_read = fread(buf, sizeof(char), bytes_to_read, f);
|
||||
char *eac_name = get_eac_register(rm);
|
||||
i16 data = get_data(buf + (char)bytes_to_read - (w == 0 ? 1 : 2), w);
|
||||
char *word_str = w == 0 ? "byte" : "word";
|
||||
char disp_str[16] = {'\0'};
|
||||
if (mod % 3 > 1) sprintf(disp_str, " + %d", get_data(buf, (mod % 3) - 1));
|
||||
printf("add [%s%s], %s %d ;13", eac_name, disp_str, word_str, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return bytes_read > 0;
|
||||
}
|
||||
|
||||
char *memory[65536];
|
||||
// Keep this global for debugging purposes
|
||||
u16 inst_count = 1;
|
||||
|
3
decode.h
3
decode.h
@ -145,7 +145,8 @@ InstFormat inst_formats[] =
|
||||
.has_rm=true, .parse_reg={.tag = P_REG_MASK, .mask=0b00111000}},
|
||||
// Immediate to register/memory
|
||||
{.id=7, .name="add", .inst_enc=0b10000000, .mask_inst=0x3, .mask_w=0x1, .has_w=true,
|
||||
.has_operands=true, .has_displacement=true, .has_data=true, .has_mod=true, .has_rm=true},
|
||||
.has_s=true, .has_operands=true, .has_displacement=true,
|
||||
.has_data=true, .has_mod=true, .has_rm=true},
|
||||
{.id=8, .name="add", .inst_enc=0b00000100, .mask_inst=0x1, .mask_w=0x1,
|
||||
.has_data=true, .has_w=true, .parse_reg={.tag = P_REG_FIXED, .fixed=0x0}},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user