diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-24 03:52:32 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-24 03:52:32 -0400 |
commit | 6bd0f17304d78e2b7e37684a672f59c9cc2444d0 (patch) | |
tree | afbf63814ace772361edd5ac8de46c98d86afe19 | |
parent | af7a0cf9b65d6fee20029fe67c95c494f4b402a7 (diff) |
oemu: cpu: Add decoding logic of MRO instructions
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | usr.bin/oemu/cpu.c | 96 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/osmx64.h | 4 |
2 files changed, 100 insertions, 0 deletions
diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c index 07ddc7b..5a2c761 100644 --- a/usr.bin/oemu/cpu.c +++ b/usr.bin/oemu/cpu.c @@ -27,15 +27,35 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> #include <sys/param.h> #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <stdbool.h> #include <oemu/cpu.h> #include <oemu/types.h> #include <oemu/osmx64.h> /* + * Return true if the instruction is an + * MRO type instruction. + */ +static bool +cpu_is_mro(inst_t *inst) +{ + switch (inst->opcode) { + case INST_MROB: + case INST_MROW: + case INST_MROD: + case INST_MROQ: + return true; + } + + return false; +} + +/* * Decode the INST_MOV_IMM instruction * * @cpu: CPU that is executing @@ -225,6 +245,77 @@ cpu_br(struct oemu_cpu *cpu, inst_t *inst) } /* + * Decode MRO type instructions + */ +static void +cpu_mro(struct oemu_cpu *cpu, inst_t *inst) +{ + inst_t *next_inst; + struct cpu_regs *regs = &cpu->regs; + char *inst_str = "bad"; + uint64_t mask = 0; + bool set_mask = false; + imm_t imm; + + switch (inst->imm) { + case 0: break; + case 1: + set_mask = true; + break; + default: + imm = inst->imm & 1; + if (inst->imm == 1) { + set_mask = true; + } + break; + } + + switch (inst->opcode) { + case INST_MROB: + inst_str = "mrob"; + if (!set_mask) { + break; + } + mask |= MASK(8); + break; + case INST_MROW: + inst_str = "mrow"; + if (!set_mask) { + break; + } + mask |= MASK(16); + break; + case INST_MROD: + inst_str = "mrod"; + if (!set_mask) { + break; + } + mask |= MASK(32); + break; + case INST_MROQ: + inst_str = "mroq"; + if (!set_mask) { + break; + } + mask |= __UINT64_MAX; + break; + } + + if (inst->rd > NELEM(regs->xreg)) { + printf("bad register operand for '%s'\n", inst_str); + return; + } + + if (set_mask) { + imm = regs->xreg[inst->rd] |= mask; + printf("set %x->x%d, new=%x\n", mask, inst->rd, imm); + } else { + imm = regs->xreg[inst->rd] &= ~mask; + printf("cleared %x->x%d, new=%x\n", mask, inst->rd, imm); + } +} + +/* * Reset a CPU to a default state */ void @@ -310,6 +401,11 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) case INST_BR: cpu_br(cpu, inst); break; + default: + if (cpu_is_mro(inst)) { + cpu_mro(cpu, inst); + } + break; } /* Is this a halt instruction? */ diff --git a/usr.bin/oemu/include/oemu/osmx64.h b/usr.bin/oemu/include/oemu/osmx64.h index b1df5d3..81940f1 100644 --- a/usr.bin/oemu/include/oemu/osmx64.h +++ b/usr.bin/oemu/include/oemu/osmx64.h @@ -49,6 +49,10 @@ #define INST_MOV_IMM 0x13 /* Data move operation from IMM */ #define INST_HLT 0x14 /* Halt */ #define INST_BR 0x15 /* Branch */ +#define INST_MROB 0x16 /* Mask register over byte */ +#define INST_MROW 0x17 /* Mask register over word */ +#define INST_MROD 0x18 /* Mask register over dword */ +#define INST_MROQ 0x19 /* Mask register over qword */ /* Registers */ #define REG_X0 0x00 |