summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/oemu/test-00.s3
-rw-r--r--sys/include/sys/queue.h5
-rw-r--r--usr.bin/oasm/include/oasm/emit.h20
-rw-r--r--usr.bin/oasm/include/oasm/label.h55
-rw-r--r--usr.bin/oasm/include/oasm/lex.h1
-rw-r--r--usr.bin/oasm/label.c166
-rw-r--r--usr.bin/oasm/parse.c3
-rw-r--r--usr.bin/oemu/cpu.c7
-rw-r--r--usr.bin/oemu/include/oemu/osmx64.h20
9 files changed, 259 insertions, 21 deletions
diff --git a/etc/oemu/test-00.s b/etc/oemu/test-00.s
index 1fa7ff1..ca0094d 100644
--- a/etc/oemu/test-00.s
+++ b/etc/oemu/test-00.s
@@ -11,4 +11,5 @@ some_label: ! X
dec x0 ! ~ 0x00000014 <----+
inc x1 ! ~ 0x00000018
add x2, #3 ! ~ 0x0000001C
- hlt ! ~ 0x00000020
+ mrow x4, #0 ! ~ 0x00000020
+ hlt ! ~ 0x00000024
diff --git a/sys/include/sys/queue.h b/sys/include/sys/queue.h
index e5d607d..92c1ff2 100644
--- a/sys/include/sys/queue.h
+++ b/sys/include/sys/queue.h
@@ -27,7 +27,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if !defined(_KERNEL)
+#include <stdint.h>
+#include <stddef.h>
+#else
#include <sys/types.h>
+#endif /* !_KERNEL */
#ifndef _QUEUE_H_
#define _QUEUE_H_
diff --git a/usr.bin/oasm/include/oasm/emit.h b/usr.bin/oasm/include/oasm/emit.h
index 0236967..3fc2674 100644
--- a/usr.bin/oasm/include/oasm/emit.h
+++ b/usr.bin/oasm/include/oasm/emit.h
@@ -56,16 +56,16 @@
#define OSMX64_OR 0x07 /* Bitwise OR operation */
#define OSMX64_XOR 0x08 /* Bitwise XOR operation */
#define OSMX64_AND 0x09 /* Bitwise AND operation */
-#define OSMX64_NOT 0x10 /* Bitwise NOT operation */
-#define OSMX64_SLL 0x11 /* Shift left logical operation */
-#define OSMX64_SRL 0x12 /* Shift right logical operation */
-#define OSMX64_MOV_IMM 0x13 /* Data move operation from IMM */
-#define OSMX64_HLT 0x14 /* Halt the processor */
-#define OSMX64_BR 0x15 /* Branch */
-#define OSMX64_MROB 0x16 /* Mask register over byte */
-#define OSMX64_MROW 0x17 /* Mask register over word */
-#define OSMX64_MROD 0x18 /* Mask register over dword */
-#define OSMX64_MROQ 0x19 /* Mask register over qword */
+#define OSMX64_NOT 0x0A /* Bitwise NOT operation */
+#define OSMX64_SLL 0x0B /* Shift left logical operation */
+#define OSMX64_SRL 0x0C /* Shift right logical operation */
+#define OSMX64_MOV_IMM 0x0D /* Data move operation from IMM */
+#define OSMX64_HLT 0x0E /* Halt the processor */
+#define OSMX64_BR 0x0F /* Branch */
+#define OSMX64_MROB 0x10 /* Mask register over byte */
+#define OSMX64_MROW 0x11 /* Mask register over word */
+#define OSMX64_MROD 0x12 /* Mask register over dword */
+#define OSMX64_MROQ 0x13 /* Mask register over qword */
/*
* OSMX64 register definitions
diff --git a/usr.bin/oasm/include/oasm/label.h b/usr.bin/oasm/include/oasm/label.h
new file mode 100644
index 0000000..8acb369
--- /dev/null
+++ b/usr.bin/oasm/include/oasm/label.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _OASM_LABEL_H_
+#define _OASM_LABEL_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#define MAX_LABELS 128
+
+/*
+ * Represents a label
+ *
+ * @name: Label name (e.g., _start)
+ * @ip: Address at which label code starts
+ */
+struct oasm_label {
+ char *name;
+ uintptr_t ip;
+ TAILQ_ENTRY(oasm_label) link;
+ TAILQ_HEAD(, oasm_label) buckets;
+};
+
+void labels_destroy(void);
+int label_enter(const char *name, uintptr_t ip);
+struct oasm_label *label_lookup(const char *name);
+
+#endif /* !_OASM_LABEL_H_ */
diff --git a/usr.bin/oasm/include/oasm/lex.h b/usr.bin/oasm/include/oasm/lex.h
index fa82398..b392403 100644
--- a/usr.bin/oasm/include/oasm/lex.h
+++ b/usr.bin/oasm/include/oasm/lex.h
@@ -33,6 +33,7 @@
#include <sys/queue.h>
#include <sys/cdefs.h>
#include <stdint.h>
+#include <stdbool.h>
struct oasm_state;
diff --git a/usr.bin/oasm/label.c b/usr.bin/oasm/label.c
new file mode 100644
index 0000000..2647bb9
--- /dev/null
+++ b/usr.bin/oasm/label.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/queue.h>
+#include <oasm/label.h>
+#include <oasm/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+static struct oasm_label *labels[MAX_LABELS];
+static size_t label_count = 0;
+
+static uint32_t
+fnv1_hash(const char *s)
+{
+ uint32_t hash = 2166136261UL;
+ const uint8_t *p = (uint8_t *)s;
+
+ while (*p != '\0') {
+ hash ^= *p;
+ hash = hash * 0x01000193;
+ ++p;
+ }
+
+ return hash;
+}
+
+/*
+ * The label table is a big hashmap containing
+ * label entries. This function creates and add
+ * a new label into the table.
+ *
+ * @name: Name of the label (e.g., _start)
+ * @ip: Instruction pointer
+ */
+int
+label_enter(const char *name, uintptr_t ip)
+{
+ uint32_t hash = fnv1_hash(name);
+ uint32_t idx = hash % MAX_LABELS;
+ struct oasm_label *lp, *lp_new;
+
+ if (label_count >= MAX_LABELS) {
+ oasm_err("[internal error]: too many labels\n");
+ return -EIO;
+ }
+
+ lp_new = malloc(sizeof(*lp_new));
+ if (lp_new == NULL) {
+ oasm_err("[internal error]: out of memory\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the label */
+ lp_new->name = strdup(name);
+ lp_new->ip = ip;
+ TAILQ_INIT(&lp_new->buckets);
+
+ /*
+ * If there is no existing entry here, we
+ * can take this slot.
+ */
+ lp = labels[idx];
+ if (lp == NULL) {
+ labels[idx] = lp_new;
+ ++label_count;
+ return 0;
+ }
+
+ /*
+ * To prevent collisions in our table here,
+ * we must check if the name matches at all.
+ * If it does not, there is a collision and
+ * we'll have to add this to a bucket.
+ */
+ if (strcmp(name, lp->name) != 0) {
+ TAILQ_INSERT_TAIL(&lp->buckets, lp_new, link);
+ ++label_count;
+ return 0;
+ }
+
+ /* Can't put the same entry in twice */
+ oasm_err("[internal error]: duplicate labels\n");
+ return -EEXIST;
+}
+
+/*
+ * Find a label entry in the label table.
+ *
+ * @name: Name of the label to lookup (e.g., _start)
+ */
+struct oasm_label *
+label_lookup(const char *name)
+{
+ uint32_t hash = fnv1_hash(name);
+ uint32_t idx = hash % MAX_LABELS;
+ struct oasm_label *lp, *lp_tmp;
+
+ lp = labels[idx];
+ if (lp == NULL) {
+ return NULL;
+ }
+
+ /* Is this the label we are looking up? */
+ if (strcmp(name, lp->name) == 0) {
+ return lp;
+ }
+
+ /* Maybe there was a collision? */
+ TAILQ_FOREACH(lp_tmp, &lp->buckets, link) {
+ if (strcmp(name, lp_tmp->name) == 0) {
+ return lp_tmp;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Clean up all allocated labels by
+ * calling free() on each entry of
+ * the queue.
+ */
+void
+labels_destroy(void)
+{
+ struct oasm_label *lp;
+
+ for (size_t i = 0; i < MAX_LABELS; ++i) {
+ lp = labels[i];
+ if (lp != NULL) {
+ free(lp->name);
+ free(lp);
+ }
+ }
+}
diff --git a/usr.bin/oasm/parse.c b/usr.bin/oasm/parse.c
index ff3c9d2..229455b 100644
--- a/usr.bin/oasm/parse.c
+++ b/usr.bin/oasm/parse.c
@@ -34,6 +34,7 @@
#include <oasm/lex.h>
#include <oasm/parse.h>
#include <oasm/log.h>
+#include <oasm/label.h>
static struct emit_state emit_state;
static const char *tokstr[] = {
@@ -159,6 +160,7 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok)
break;
case TT_LABEL:
state->last = tok->type;
+ label_enter(tok->raw, state->pip);
break;
case TT_HLT:
state->last = tok->type;
@@ -246,4 +248,5 @@ parse_enter(struct oasm_state *state)
/* Process then destroy the emit state */
emit_process(state, &emit_state);
emit_destroy(&emit_state);
+ labels_destroy();
}
diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c
index 5a2c761..fefdd4c 100644
--- a/usr.bin/oemu/cpu.c
+++ b/usr.bin/oemu/cpu.c
@@ -408,6 +408,13 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem)
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 81940f1..ffd6156 100644
--- a/usr.bin/oemu/include/oemu/osmx64.h
+++ b/usr.bin/oemu/include/oemu/osmx64.h
@@ -43,16 +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_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 */
+#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