summaryrefslogtreecommitdiff
path: root/usr.bin/oemu
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/oemu')
-rw-r--r--usr.bin/oemu/cpu.c107
-rw-r--r--usr.bin/oemu/include/oemu/osmx64.h16
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