diff options
-rw-r--r-- | etc/oemu/test-00.s | 3 | ||||
-rw-r--r-- | sys/include/sys/queue.h | 5 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/emit.h | 20 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/label.h | 55 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/lex.h | 1 | ||||
-rw-r--r-- | usr.bin/oasm/label.c | 166 | ||||
-rw-r--r-- | usr.bin/oasm/parse.c | 3 | ||||
-rw-r--r-- | usr.bin/oemu/cpu.c | 7 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/osmx64.h | 20 |
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 |