Simulate non-memory MOVs
This commit is contained in:
parent
0b57a4fed2
commit
6794570362
2
.vscode/c_cpp_properties.json
vendored
2
.vscode/c_cpp_properties.json
vendored
@ -15,7 +15,7 @@
|
|||||||
"windowsSdkVersion": "10.0.22000.0",
|
"windowsSdkVersion": "10.0.22000.0",
|
||||||
"compilerPath": "C:/MinGW/bin/gcc.exe",
|
"compilerPath": "C:/MinGW/bin/gcc.exe",
|
||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++17",
|
"cppStandard": "c++11",
|
||||||
"intelliSenseMode": "windows-gcc-x86",
|
"intelliSenseMode": "windows-gcc-x86",
|
||||||
"configurationProvider": "ms-vscode.makefile-tools"
|
"configurationProvider": "ms-vscode.makefile-tools"
|
||||||
}
|
}
|
||||||
|
27
examples/immediate_movs.asm
Normal file
27
examples/immediate_movs.asm
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||||||
|
;
|
||||||
|
; This software is provided 'as-is', without any express or implied
|
||||||
|
; warranty. In no event will the authors be held liable for any damages
|
||||||
|
; arising from the use of this software.
|
||||||
|
;
|
||||||
|
; Please see https://computerenhance.com for further information
|
||||||
|
;
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
; ========================================================================
|
||||||
|
; LISTING 43
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
mov ax, 1
|
||||||
|
mov bx, 2
|
||||||
|
mov cx, 3
|
||||||
|
mov dx, 4
|
||||||
|
|
||||||
|
mov sp, 5
|
||||||
|
mov bp, 6
|
||||||
|
mov si, 7
|
||||||
|
mov di, 8
|
19
examples/immediate_movs.txt
Normal file
19
examples/immediate_movs.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
--- test\listing_0043_immediate_movs execution ---
|
||||||
|
mov ax, 1 ; ax:0x0->0x1
|
||||||
|
mov bx, 2 ; bx:0x0->0x2
|
||||||
|
mov cx, 3 ; cx:0x0->0x3
|
||||||
|
mov dx, 4 ; dx:0x0->0x4
|
||||||
|
mov sp, 5 ; sp:0x0->0x5
|
||||||
|
mov bp, 6 ; bp:0x0->0x6
|
||||||
|
mov si, 7 ; si:0x0->0x7
|
||||||
|
mov di, 8 ; di:0x0->0x8
|
||||||
|
|
||||||
|
Final registers:
|
||||||
|
ax: 0x0001 (1)
|
||||||
|
bx: 0x0002 (2)
|
||||||
|
cx: 0x0003 (3)
|
||||||
|
dx: 0x0004 (4)
|
||||||
|
sp: 0x0005 (5)
|
||||||
|
bp: 0x0006 (6)
|
||||||
|
si: 0x0007 (7)
|
||||||
|
di: 0x0008 (8)
|
32
examples/register_movs.asm
Normal file
32
examples/register_movs.asm
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||||||
|
;
|
||||||
|
; This software is provided 'as-is', without any express or implied
|
||||||
|
; warranty. In no event will the authors be held liable for any damages
|
||||||
|
; arising from the use of this software.
|
||||||
|
;
|
||||||
|
; Please see https://computerenhance.com for further information
|
||||||
|
;
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
; ========================================================================
|
||||||
|
; LISTING 44
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
mov ax, 1
|
||||||
|
mov bx, 2
|
||||||
|
mov cx, 3
|
||||||
|
mov dx, 4
|
||||||
|
|
||||||
|
mov sp, ax
|
||||||
|
mov bp, bx
|
||||||
|
mov si, cx
|
||||||
|
mov di, dx
|
||||||
|
|
||||||
|
mov dx, sp
|
||||||
|
mov cx, bp
|
||||||
|
mov bx, si
|
||||||
|
mov ax, di
|
23
examples/register_movs.txt
Normal file
23
examples/register_movs.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
--- test\listing_0044_register_movs execution ---
|
||||||
|
mov ax, 1 ; ax:0x0->0x1
|
||||||
|
mov bx, 2 ; bx:0x0->0x2
|
||||||
|
mov cx, 3 ; cx:0x0->0x3
|
||||||
|
mov dx, 4 ; dx:0x0->0x4
|
||||||
|
mov sp, ax ; sp:0x0->0x1
|
||||||
|
mov bp, bx ; bp:0x0->0x2
|
||||||
|
mov si, cx ; si:0x0->0x3
|
||||||
|
mov di, dx ; di:0x0->0x4
|
||||||
|
mov dx, sp ; dx:0x4->0x1
|
||||||
|
mov cx, bp ; cx:0x3->0x2
|
||||||
|
mov bx, si ; bx:0x2->0x3
|
||||||
|
mov ax, di ; ax:0x1->0x4
|
||||||
|
|
||||||
|
Final registers:
|
||||||
|
ax: 0x0004 (4)
|
||||||
|
bx: 0x0003 (3)
|
||||||
|
cx: 0x0002 (2)
|
||||||
|
dx: 0x0001 (1)
|
||||||
|
sp: 0x0001 (1)
|
||||||
|
bp: 0x0002 (2)
|
||||||
|
si: 0x0003 (3)
|
||||||
|
di: 0x0004 (4)
|
24
src/main.c
24
src/main.c
@ -107,7 +107,29 @@ int dissassemble(FILE *src, FILE *dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int simulate(FILE *src) {
|
int simulate(FILE *src) {
|
||||||
todo("simulate");
|
struct cpu_state state = { 0 };
|
||||||
|
struct instruction inst;
|
||||||
|
int counter = 1;
|
||||||
|
while (true) {
|
||||||
|
enum decode_error err = decode_instruction(src, &inst);
|
||||||
|
if (err == DECODE_ERR_EOF) break;
|
||||||
|
if (err != DECODE_OK) {
|
||||||
|
fprintf(stderr, "ERROR: Failed to decode %d instruction: %s\n", counter, decode_error_to_str(err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
execute_instruction(&state, &inst);
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Final registers:\n");
|
||||||
|
printf(" ax: 0x%04x (%d)\n", state.ax, state.ax);
|
||||||
|
printf(" bx: 0x%04x (%d)\n", state.bx, state.bx);
|
||||||
|
printf(" cx: 0x%04x (%d)\n", state.cx, state.cx);
|
||||||
|
printf(" sp: 0x%04x (%d)\n", state.sp, state.sp);
|
||||||
|
printf(" bp: 0x%04x (%d)\n", state.bp, state.bp);
|
||||||
|
printf(" si: 0x%04x (%d)\n", state.si, state.si);
|
||||||
|
printf(" di: 0x%04x (%d)\n", state.di, state.di);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_usage(const char *program) {
|
void print_usage(const char *program) {
|
||||||
|
@ -99,4 +99,15 @@ struct instruction {
|
|||||||
struct reg_or_mem_value dest;
|
struct reg_or_mem_value dest;
|
||||||
struct src_value src;
|
struct src_value src;
|
||||||
i8 jmp_offset;
|
i8 jmp_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpu_state {
|
||||||
|
u16 ax;
|
||||||
|
u16 bx;
|
||||||
|
u16 cx;
|
||||||
|
u16 dx;
|
||||||
|
u16 sp;
|
||||||
|
u16 bp;
|
||||||
|
u16 si;
|
||||||
|
u16 di;
|
||||||
};
|
};
|
@ -114,6 +114,7 @@ static void deocde_reg_or_mem_to_src(struct src_value *value, FILE *src, u8 rm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: change to readinf from a byte buffer
|
||||||
// TODO: add handling for 'DECODE_ERR_MISSING_BYTES'
|
// TODO: add handling for 'DECODE_ERR_MISSING_BYTES'
|
||||||
// Handy reference: Table 4-12. 8086 Instruction Encoding
|
// Handy reference: Table 4-12. 8086 Instruction Encoding
|
||||||
enum decode_error decode_instruction(FILE *src, struct instruction *output) {
|
enum decode_error decode_instruction(FILE *src, struct instruction *output) {
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
u16 get_register_value(struct cpu_state *state, enum reg_value reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case REG_AL: return state->ax & 0xFF;
|
||||||
|
case REG_CL: return state->cx & 0xFF;
|
||||||
|
case REG_DL: return state->dx & 0xFF;
|
||||||
|
case REG_BL: return state->bx & 0xFF;
|
||||||
|
case REG_AH: return (state->ax >> 8) & 0xFF;
|
||||||
|
case REG_CH: return (state->cx >> 8) & 0xFF;
|
||||||
|
case REG_DH: return (state->dx >> 8) & 0xFF;
|
||||||
|
case REG_BH: return (state->bx >> 8) & 0xFF;
|
||||||
|
case REG_AX: return state->ax;
|
||||||
|
case REG_CX: return state->cx;
|
||||||
|
case REG_DX: return state->dx;
|
||||||
|
case REG_BX: return state->bx;
|
||||||
|
case REG_SP: return state->sp;
|
||||||
|
case REG_BP: return state->bp;
|
||||||
|
case REG_SI: return state->si;
|
||||||
|
case REG_DI: return state->di;
|
||||||
|
default: panic("Unhandled register '%s'", reg_to_str(reg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_register_value(struct cpu_state *state, enum reg_value reg, u16 value)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case REG_AL:
|
||||||
|
state->ax = (state->ax & 0xFF00) & value;
|
||||||
|
break;
|
||||||
|
case REG_CL:
|
||||||
|
state->cx = (state->cx & 0xFF00) & value;
|
||||||
|
break;
|
||||||
|
case REG_DL:
|
||||||
|
state->dx = (state->dx & 0xFF00) & value;
|
||||||
|
break;
|
||||||
|
case REG_BL:
|
||||||
|
state->bx = (state->bx & 0xFF00) & value;
|
||||||
|
break;
|
||||||
|
case REG_AH:
|
||||||
|
state->ax = (state->ax & 0x00FF) & (value << 8);
|
||||||
|
break;
|
||||||
|
case REG_CH:
|
||||||
|
state->cx = (state->cx & 0x00FF) & (value << 8);
|
||||||
|
break;
|
||||||
|
case REG_DH:
|
||||||
|
state->dx = (state->dx & 0x00FF) & (value << 8);
|
||||||
|
break;
|
||||||
|
case REG_BH:
|
||||||
|
state->bx = (state->bx & 0x00FF) & (value << 8);
|
||||||
|
break;
|
||||||
|
case REG_AX:
|
||||||
|
state->ax = value;
|
||||||
|
break;
|
||||||
|
case REG_CX:
|
||||||
|
state->cx = value;
|
||||||
|
break;
|
||||||
|
case REG_DX:
|
||||||
|
state->dx = value;
|
||||||
|
break;
|
||||||
|
case REG_BX:
|
||||||
|
state->bx = value;
|
||||||
|
break;
|
||||||
|
case REG_SP:
|
||||||
|
state->sp = value;
|
||||||
|
break;
|
||||||
|
case REG_BP:
|
||||||
|
state->bp = value;
|
||||||
|
break;
|
||||||
|
case REG_SI:
|
||||||
|
state->si = value;
|
||||||
|
break;
|
||||||
|
case REG_DI:
|
||||||
|
state->di = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("Unhandled register '%s'", reg_to_str(reg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_instruction(struct cpu_state *state, struct instruction *inst) {
|
||||||
|
switch (inst->op)
|
||||||
|
{
|
||||||
|
case OP_MOV:
|
||||||
|
if (!inst->dest.is_reg) {
|
||||||
|
todo("Handle MOV to memory");
|
||||||
|
}
|
||||||
|
if (inst->src.variant == SRC_VALUE_MEM) {
|
||||||
|
todo("Handle MOV from memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 src_value;
|
||||||
|
if (inst->src.variant == SRC_VALUE_REG) {
|
||||||
|
src_value = get_register_value(state, inst->src.reg);
|
||||||
|
} else if (inst->src.variant == SRC_VALUE_IMMEDIATE8 || inst->src.variant == SRC_VALUE_IMMEDIATE16) {
|
||||||
|
src_value = inst->src.immediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_register_value(state, inst->dest.reg, src_value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
todo("Unhandled instruction execution '%s'\n", operation_to_str(inst->op));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user