From e8d3885204ab7a86a447dac8c13166ffe49d9fa3 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 10 Jul 2023 17:34:30 +0900 Subject: [PATCH] Implement ret and pop --- src/instructions.c | 30 +++++++++++++++--------------- src/instructions.h | 2 ++ src/instructions/memory.c | 27 ++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/instructions.c b/src/instructions.c index e616861..a812fbd 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -31,7 +31,7 @@ const instruction_t instructions[] = { {.opcode = 0x04, .extended = -1, .name = "add", .mode = {OPREG8, IMM8, END}, .exec = &add}, {.opcode = 0x05, .extended = -1, .name = "add", .mode = {OPREG16, IMM16, END}, .exec = &add}, {.opcode = 0x06, .extended = -1, .name = "push es", .mode = {END}, .exec = &push}, - {.opcode = 0x07, .extended = -1, .name = "pop es", .mode = {END}, .exec = NULL}, + {.opcode = 0x07, .extended = -1, .name = "pop es", .mode = {END}, .exec = &pop}, {.opcode = 0x08, .extended = -1, .name = "or", .mode = {R_M8, REG8, END}, .exec = NULL}, {.opcode = 0x09, .extended = -1, .name = "or", .mode = {R_M16, REG16, END}, .exec = NULL}, {.opcode = 0x0A, .extended = -1, .name = "or", .mode = {REG8, R_M8, END}, .exec = NULL}, @@ -47,7 +47,7 @@ const instruction_t instructions[] = { {.opcode = 0x14, .extended = -1, .name = "adc", .mode = {OPREG8, IMM8, END}, .exec = NULL}, {.opcode = 0x15, .extended = -1, .name = "adc", .mode = {OPREG16, IMM16, END}, .exec = NULL}, {.opcode = 0x16, .extended = -1, .name = "push ss", .mode = {END}, .exec = &push}, - {.opcode = 0x17, .extended = -1, .name = "pop ss", .mode = {END}, .exec = NULL}, + {.opcode = 0x17, .extended = -1, .name = "pop ss", .mode = {END}, .exec = &pop}, {.opcode = 0x18, .extended = -1, .name = "sbb", .mode = {R_M8, REG8, END}, .exec = NULL}, {.opcode = 0x19, .extended = -1, .name = "sbb", .mode = {R_M16, REG16, END}, .exec = NULL}, {.opcode = 0x1A, .extended = -1, .name = "sbb", .mode = {REG8, R_M8, END}, .exec = NULL}, @@ -55,7 +55,7 @@ const instruction_t instructions[] = { {.opcode = 0x1C, .extended = -1, .name = "sbb", .mode = {OPREG8, IMM8, END}, .exec = NULL}, {.opcode = 0x1D, .extended = -1, .name = "sbb", .mode = {OPREG16, IMM16, END}, .exec = NULL}, {.opcode = 0x1E, .extended = -1, .name = "push ds", .mode = {END}, .exec = &push}, - {.opcode = 0x1F, .extended = -1, .name = "pop ds", .mode = {END}, .exec = NULL}, + {.opcode = 0x1F, .extended = -1, .name = "pop ds", .mode = {END}, .exec = &pop}, {.opcode = 0x20, .extended = -1, .name = "and", .mode = {R_M8, REG8, END}, .exec = NULL}, {.opcode = 0x21, .extended = -1, .name = "and", .mode = {R_M16, REG16, END}, .exec = NULL}, {.opcode = 0x22, .extended = -1, .name = "and", .mode = {REG8, R_M8, END}, .exec = NULL}, @@ -112,14 +112,14 @@ const instruction_t instructions[] = { {.opcode = 0x55, .extended = -1, .name = "push", .mode = {OPREG16, END}, .exec = &push}, {.opcode = 0x56, .extended = -1, .name = "push", .mode = {OPREG16, END}, .exec = &push}, {.opcode = 0x57, .extended = -1, .name = "push", .mode = {OPREG16, END}, .exec = &push}, - {.opcode = 0x58, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x59, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5A, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5B, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5C, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5D, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5E, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, - {.opcode = 0x5F, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = NULL}, + {.opcode = 0x58, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x59, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5A, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5B, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5C, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5D, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5E, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, + {.opcode = 0x5F, .extended = -1, .name = "pop", .mode = {OPREG16, END}, .exec = &pop}, {.opcode = 0x70, .extended = -1, .name = "jo", .mode = {REL8, END}, .exec = &jo}, {.opcode = 0x71, .extended = -1, .name = "jno", .mode = {REL8, END}, .exec = &jno}, {.opcode = 0x72, .extended = -1, .name = "jb", .mode = {REL8, END}, .exec = &jb}, @@ -151,7 +151,7 @@ const instruction_t instructions[] = { // {.opcode = 0x8C, .extended = -1, .name = "mov", .mode = {R_M16, sreg, END}, .exec = &mov}, {.opcode = 0x8D, .extended = -1, .name = "lea", .mode = {REG16, R_M16, END}, .exec = &lea}, // {.opcode = 0x8E, .extended = -1, .name = "mov", .mode = {sreg, R_M16, END}, .exec = &mov}, - {.opcode = 0x8F, .extended = -1, .name = "pop", .mode = {R_M16, END}, .exec = NULL}, + {.opcode = 0x8F, .extended = -1, .name = "pop", .mode = {R_M16, END}, .exec = &pop}, {.opcode = 0x90, .extended = -1, .name = "xchg ax, ax", .mode = {END}, .exec = NULL}, {.opcode = 0x91, .extended = -1, .name = "xchg cx, ax", .mode = {END}, .exec = NULL}, {.opcode = 0x92, .extended = -1, .name = "xchg dx, ax", .mode = {END}, .exec = NULL}, @@ -165,7 +165,7 @@ const instruction_t instructions[] = { // {.opcode = 0x9A, .extended = -1, .name = "call", .mode = {CALL_INTER, END}, .exec = &call}, {.opcode = 0x9B, .extended = -1, .name = "wait", .mode = {END}, .exec = NULL}, {.opcode = 0x9C, .extended = -1, .name = "pushf", .mode = {END}, .exec = &push}, - {.opcode = 0x9D, .extended = -1, .name = "popf", .mode = {END}, .exec = NULL}, + {.opcode = 0x9D, .extended = -1, .name = "popf", .mode = {END}, .exec = &pop}, {.opcode = 0x9E, .extended = -1, .name = "sahf", .mode = {END}, .exec = NULL}, {.opcode = 0x9F, .extended = -1, .name = "lahf", .mode = {END}, .exec = NULL}, // {.opcode = 0xA0, .extended = -1, .name = "mov al", .mode = {moffs16, END}, .exec = &mov}, @@ -201,8 +201,8 @@ const instruction_t instructions[] = { {.opcode = 0xBE, .extended = -1, .name = "mov", .mode = {OPREG16, IMM16, END}, .exec = &mov}, {.opcode = 0xBF, .extended = -1, .name = "mov", .mode = {OPREG16, IMM16, END}, .exec = &mov}, - {.opcode = 0xC2, .extended = -1, .name = "ret", .mode = {IMM16, END}, .exec = NULL}, - {.opcode = 0xC3, .extended = -1, .name = "ret", .mode = {END}, .exec = NULL}, + {.opcode = 0xC2, .extended = -1, .name = "ret", .mode = {IMM16, END}, .exec = &ret}, + {.opcode = 0xC3, .extended = -1, .name = "ret", .mode = {END}, .exec = &ret}, {.opcode = 0xC4, .extended = -1, .name = "les", .mode = {REG16, R_M16, END}, .exec = NULL}, {.opcode = 0xC5, .extended = -1, .name = "lds", .mode = {R_M16, REG16, END}, .exec = NULL}, {.opcode = 0xC6, .extended = -1, .name = "mov", .mode = {R_M16, IMM8, END}, .exec = &mov}, diff --git a/src/instructions.h b/src/instructions.h index 503c3ee..b6d7679 100644 --- a/src/instructions.h +++ b/src/instructions.h @@ -5,8 +5,10 @@ void mov(const instruction_t *self, state_t *state); void push(const instruction_t *self, state_t *state); +void pop(const instruction_t *self, state_t *state); void call(const instruction_t *self, state_t *state); +void ret(const instruction_t *self, state_t *state); void jmp(const instruction_t *self, state_t *state); void jo(const instruction_t *self, state_t *state); void jno(const instruction_t *self, state_t *state); diff --git a/src/instructions/memory.c b/src/instructions/memory.c index 2bfb087..d0ff373 100644 --- a/src/instructions/memory.c +++ b/src/instructions/memory.c @@ -24,13 +24,38 @@ void push(const instruction_t *self, state_t *state) state->memory[--state->sp] = what & 0xFF; } +void pop(const instruction_t *self, state_t *state) +{ + operand_t where = get_operand(self, 0, state); + unsigned what = 0; + + what |= state->memory[state->sp++]; + if (is_operand_wide(self, 0)) + what |= state->memory[state->sp++] << 8; + write_op(where, what); +} + void call(const instruction_t *self, state_t *state) { uint16_t pc = read_op(get_operand(self, 0, state)); + unsigned inst_size = get_inst_size(*self, state->binary + state->pc, state->binary_size - state->pc); + state->pc += inst_size - 1; state->memory[--state->sp] = state->pc >> 8; state->memory[--state->sp] = state->pc & 0xFF; - state->pc = pc - get_inst_size(*self, state->binary + state->pc, state->binary_size - state->pc); + state->pc = pc - inst_size; +} + +void ret(const instruction_t *self, state_t *state) +{ + uint16_t spmin = self->mode[0] != END ? read_op(get_operand(self, 0, state)) : 0; + unsigned what = 0; + + what |= state->memory[state->sp++]; + if (is_operand_wide(self, 0)) + what |= state->memory[state->sp++] << 8; + state->pc = what; + state->sp += spmin; } void jmp(const instruction_t *self, state_t *state)