diff options
Diffstat (limited to 'usr.bin/oemu')
-rw-r--r-- | usr.bin/oemu/cpu.c | 107 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/osmx64.h | 16 |
2 files changed, 117 insertions, 6 deletions
diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c index 07ddc7b..49d4671 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 @@ -286,6 +377,10 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) inst = (inst_t *)&memp[regs->ip]; switch (inst->opcode) { + case INST_NOP: + /* NOP */ + regs->ip += sizeof(*inst); + continue; case INST_MOV_IMM: cpu_mov_imm(cpu, inst); break; @@ -310,8 +405,20 @@ 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; } + /* + * X0 is readonly and should always be zero, undo + * any writes or side effects from any operations + * upon this register. + */ + regs->xreg[0] = 0; + /* Is this a halt instruction? */ if (inst->opcode == INST_HLT) { printf("HALTED\n"); diff --git a/usr.bin/oemu/include/oemu/osmx64.h b/usr.bin/oemu/include/oemu/osmx64.h index b1df5d3..ffd6156 100644 --- a/usr.bin/oemu/include/oemu/osmx64.h +++ b/usr.bin/oemu/include/oemu/osmx64.h @@ -43,12 +43,16 @@ #define INST_OR 0x07 /* Bitwise OR operation */ #define INST_XOR 0x08 /* Bitwise XOR operation */ #define INST_AND 0x09 /* Bitwise AND operation */ -#define INST_NOT 0x10 /* Bitwise NOT operation */ -#define INST_SLL 0x11 /* Shift left logical operation */ -#define INST_SRL 0x12 /* Shift right logical operation */ -#define INST_MOV_IMM 0x13 /* Data move operation from IMM */ -#define INST_HLT 0x14 /* Halt */ -#define INST_BR 0x15 /* Branch */ +#define INST_NOT 0x0A /* Bitwise NOT operation */ +#define INST_SLL 0x0B /* Shift left logical operation */ +#define INST_SRL 0x0C /* Shift right logical operation */ +#define INST_MOV_IMM 0x0D /* Data move operation from IMM */ +#define INST_HLT 0x0E /* Halt */ +#define INST_BR 0x0F /* Branch */ +#define INST_MROB 0x10 /* Mask register over byte */ +#define INST_MROW 0x11 /* Mask register over word */ +#define INST_MROD 0x12 /* Mask register over dword */ +#define INST_MROQ 0x13 /* Mask register over qword */ /* Registers */ #define REG_X0 0x00 |