simulate add, sub and cmp
This commit is contained in:
parent
6794570362
commit
5ba1f1f948
28
examples/add_sub_cmp.asm
Normal file
28
examples/add_sub_cmp.asm
Normal file
@ -0,0 +1,28 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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 46
|
||||
; ========================================================================
|
||||
|
||||
bits 16
|
||||
|
||||
mov bx, -4093
|
||||
mov cx, 3841
|
||||
sub bx, cx
|
||||
|
||||
mov sp, 998
|
||||
mov bp, 999
|
||||
cmp bp, sp
|
||||
|
||||
add bp, 1027
|
||||
sub bp, 2026
|
15
examples/add_sub_cmp.txt
Normal file
15
examples/add_sub_cmp.txt
Normal file
@ -0,0 +1,15 @@
|
||||
--- test\listing_0046_add_sub_cmp execution ---
|
||||
mov bx, 61443 ; bx:0x0->0xf003
|
||||
mov cx, 3841 ; cx:0x0->0xf01
|
||||
sub bx, cx ; bx:0xf003->0xe102 flags:->S
|
||||
mov sp, 998 ; sp:0x0->0x3e6
|
||||
mov bp, 999 ; bp:0x0->0x3e7
|
||||
cmp bp, sp ; flags:S->
|
||||
add bp, 1027 ; bp:0x3e7->0x7ea
|
||||
sub bp, 2026 ; bp:0x7ea->0x0 flags:->PZ
|
||||
|
||||
Final registers:
|
||||
bx: 0xe102 (57602)
|
||||
cx: 0x0f01 (3841)
|
||||
sp: 0x03e6 (998)
|
||||
flags: PZ
|
@ -129,6 +129,7 @@ int simulate(FILE *src) {
|
||||
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);
|
||||
printf(" flags: %s%s\n", state.flags.sign ? "S" : "", state.flags.zero ? "Z" : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -110,4 +110,10 @@ struct cpu_state {
|
||||
u16 bp;
|
||||
u16 si;
|
||||
u16 di;
|
||||
|
||||
struct {
|
||||
bool zero;
|
||||
bool sign;
|
||||
// TODO: Add all flags
|
||||
} flags;
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
|
||||
u16 get_register_value(struct cpu_state *state, enum reg_value reg)
|
||||
u16 read_reg_value(struct cpu_state *state, enum reg_value reg)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
@ -23,7 +23,7 @@ u16 get_register_value(struct cpu_state *state, enum reg_value reg)
|
||||
}
|
||||
}
|
||||
|
||||
void set_register_value(struct cpu_state *state, enum reg_value reg, u16 value)
|
||||
void write_reg_value(struct cpu_state *state, enum reg_value reg, u16 value)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
@ -80,26 +80,122 @@ void set_register_value(struct cpu_state *state, enum reg_value reg, u16 value)
|
||||
}
|
||||
}
|
||||
|
||||
u16 read_src_value(struct cpu_state *state, struct src_value *src) {
|
||||
switch (src->variant)
|
||||
{
|
||||
case SRC_VALUE_REG:
|
||||
return read_reg_value(state, src->reg);
|
||||
case SRC_VALUE_IMMEDIATE8:
|
||||
case SRC_VALUE_IMMEDIATE16:
|
||||
return src->immediate;
|
||||
case SRC_VALUE_MEM:
|
||||
todo("Handle read from memory");
|
||||
default:
|
||||
panic("Unhandled src variant %d\n", src->variant);
|
||||
}
|
||||
}
|
||||
|
||||
u16 read_src_or_mem_value(struct cpu_state *state, struct reg_or_mem_value *reg_or_mem) {
|
||||
if (reg_or_mem->is_reg) {
|
||||
return read_reg_value(state, reg_or_mem->reg);
|
||||
} else {
|
||||
todo("Handle read from memory");
|
||||
}
|
||||
}
|
||||
void write_src_or_mem_value(struct cpu_state *state, struct reg_or_mem_value *reg_or_mem, u16 value) {
|
||||
if (reg_or_mem->is_reg) {
|
||||
write_reg_value(state, reg_or_mem->reg, value);
|
||||
} else {
|
||||
todo("Handle write to memory");
|
||||
}
|
||||
}
|
||||
|
||||
bool is_reg_16bit(enum reg_value reg) {
|
||||
switch (reg)
|
||||
{
|
||||
case REG_AL:
|
||||
case REG_CL:
|
||||
case REG_DL:
|
||||
case REG_BL:
|
||||
case REG_AH:
|
||||
case REG_CH:
|
||||
case REG_DH:
|
||||
case REG_BH:
|
||||
return false;
|
||||
case REG_AX:
|
||||
case REG_CX:
|
||||
case REG_DX:
|
||||
case REG_BX:
|
||||
case REG_SP:
|
||||
case REG_BP:
|
||||
case REG_SI:
|
||||
case REG_DI:
|
||||
return true;
|
||||
default: panic("Unhandled register '%s'", reg_to_str(reg));
|
||||
}
|
||||
}
|
||||
|
||||
bool are_instruction_operands_16bit(struct instruction *inst) {
|
||||
if (inst->dest.is_reg) {
|
||||
return is_reg_16bit(inst->dest.reg);
|
||||
} else if (inst->src.variant == SRC_VALUE_REG) {
|
||||
return is_reg_16bit(inst->src.reg);
|
||||
} else {
|
||||
return inst->src.variant == SRC_VALUE_IMMEDIATE16;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
case OP_MOV: {
|
||||
u16 src_value = read_src_value(state, &inst->src);
|
||||
write_src_or_mem_value(state, &inst->dest, src_value);
|
||||
break;
|
||||
}
|
||||
case OP_ADD: {
|
||||
u16 dest_value = read_src_or_mem_value(state, &inst->dest);
|
||||
u16 src_value = read_src_value(state, &inst->src);
|
||||
u16 result = dest_value + src_value;
|
||||
|
||||
state->flags.zero = result == 0;
|
||||
if (are_instruction_operands_16bit(inst)) {
|
||||
state->flags.sign = (result >> 15) & 0b1;
|
||||
} else {
|
||||
state->flags.sign = (result >> 7) & 0b1;
|
||||
}
|
||||
|
||||
write_src_or_mem_value(state, &inst->dest, result);
|
||||
break;
|
||||
}
|
||||
case OP_SUB: {
|
||||
u16 dest_value = read_src_or_mem_value(state, &inst->dest);
|
||||
u16 src_value = read_src_value(state, &inst->src);
|
||||
u16 result = dest_value - src_value;
|
||||
|
||||
state->flags.zero = result == 0;
|
||||
if (are_instruction_operands_16bit(inst)) {
|
||||
state->flags.sign = (result >> 15) & 0b1;
|
||||
} else {
|
||||
state->flags.sign = (result >> 7) & 0b1;
|
||||
}
|
||||
|
||||
write_src_or_mem_value(state, &inst->dest, result);
|
||||
break;
|
||||
}
|
||||
case OP_CMP: {
|
||||
u16 dest_value = read_src_or_mem_value(state, &inst->dest);
|
||||
u16 src_value = read_src_value(state, &inst->src);
|
||||
u16 result = dest_value - src_value;
|
||||
|
||||
state->flags.zero = result == 0;
|
||||
if (are_instruction_operands_16bit(inst)) {
|
||||
state->flags.sign = (result >> 15) & 0b1;
|
||||
} else {
|
||||
state->flags.sign = (result >> 7) & 0b1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
todo("Unhandled instruction execution '%s'\n", operation_to_str(inst->op));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user