summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/oemu/cpu.c96
-rw-r--r--usr.bin/oemu/include/oemu/osmx64.h4
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