summaryrefslogtreecommitdiff
path: root/usr.bin/oasm/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/oasm/parse.c')
-rw-r--r--usr.bin/oasm/parse.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/usr.bin/oasm/parse.c b/usr.bin/oasm/parse.c
new file mode 100644
index 0000000..9a4dd0e
--- /dev/null
+++ b/usr.bin/oasm/parse.c
@@ -0,0 +1,227 @@
+/* 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 <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <oasm/emit.h>
+#include <oasm/state.h>
+#include <oasm/lex.h>
+#include <oasm/parse.h>
+#include <oasm/log.h>
+
+static struct emit_state emit_state;
+static const char *tokstr[] = {
+ [ TT_UNKNOWN] = "bad",
+ [ TT_ADD ] = "add",
+ [ TT_SUB ] = "sub",
+ [ TT_MUL ] = "mul",
+ [ TT_DIV ] = "div",
+ [ TT_HLT ] = "hlt",
+ [ TT_COMMA ] = ",",
+ [ TT_INC ] = "inc",
+ [ TT_DEC ] = "dec",
+ [ TT_MOV ] = "mov",
+ [ TT_IMM ] = "<imm>",
+
+ /* X<n> registers */
+ [ TT_X0 ] = "x0",
+ [ TT_X1 ] = "x1",
+ [ TT_X2 ] = "x2",
+ [ TT_X3 ] = "x3",
+ [ TT_X4 ] = "x4",
+ [ TT_X5 ] = "x5",
+ [ TT_X6 ] = "x6",
+ [ TT_X7 ] = "x7",
+ [ TT_X8 ] = "x8",
+ [ TT_X9 ] = "x9",
+ [ TT_X10 ] = "x10",
+ [ TT_X11 ] = "x11",
+ [ TT_X12 ] = "x12",
+ [ TT_X13 ] = "x13",
+ [ TT_X14 ] = "x14",
+ [ TT_X15 ] = "x15",
+
+ /* V<n> registers */
+ [ TT_F0 ] = "v0",
+ [ TT_F1 ] = "v1",
+ [ TT_F2 ] = "v2",
+ [ TT_F3 ] = "v3",
+ [ TT_F4 ] = "v4",
+ [ TT_F5 ] = "v5",
+ [ TT_F6 ] = "v6",
+ [ TT_F7 ] = "v7",
+
+ /* D<n> registers */
+ [ TT_D0 ] = "d0",
+ [ TT_D1 ] = "d1",
+ [ TT_D2 ] = "d2",
+ [ TT_D3 ] = "d3",
+ [ TT_D4 ] = "d4",
+ [ TT_D5 ] = "d5",
+ [ TT_D6 ] = "d6",
+ [ TT_D7 ] = "d7",
+
+ /* V<n> registers */
+ [ TT_V0 ] = "v0",
+ [ TT_V1 ] = "v1",
+ [ TT_V2 ] = "v2",
+ [ TT_V3 ] = "v3",
+ [ TT_V4 ] = "v4",
+ [ TT_V5 ] = "v5",
+ [ TT_V6 ] = "v6",
+ [ TT_V7 ] = "v7",
+};
+
+static int
+parse_reg(struct oasm_state *state, struct oasm_token *tok)
+{
+ const char *p;
+
+ /* Valid instructions that go with regs */
+ switch (state->last) {
+ case TT_MOV:
+ case TT_DEC:
+ case TT_INC:
+ case TT_ADD:
+ case TT_SUB:
+ case TT_MUL:
+ case TT_DIV:
+ state->last = tok->type;
+ break;
+ default:
+ p = tokstr[state->last];
+ oasm_err("bad instruction '%s' for regop\n", p);
+ return -1;
+ }
+
+ if (!tok_is_xreg(tok->type)) {
+ p = tokstr[tok->type];
+ oasm_err("bad register \"%s\"\n", p);
+ return -1;
+ }
+
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ return 0;
+}
+
+static int
+parse_imm(struct oasm_token *tok, tt_t last)
+{
+ return 0;
+}
+
+static int
+parse_tok(struct oasm_state *state, struct oasm_token *tok)
+{
+ const char *p;
+ int error;
+
+ switch (tok->type) {
+ case TT_HLT:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_MUL:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_DIV:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_MOV:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_ADD:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_SUB:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_DEC:
+ case TT_INC:
+ state->last = tok->type;
+ emit_osmx64(&emit_state, tok);
+ break;
+ case TT_IMM:
+ p = tokstr[state->last];
+ if (!tok_is_xreg(state->last)) {
+ printf("expected X<n> but got %s\n", p);
+ return -1;
+ }
+ emit_osmx64(&emit_state, tok);
+ break;
+ default:
+ if (!tok->is_reg) {
+ oasm_err("syntax error\n");
+ return -1;
+ }
+
+ error = parse_reg(state, tok);
+ if (error < 0) {
+ return error;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void
+parse_enter(struct oasm_state *state)
+{
+ struct oasm_token tok;
+ const char *type, *raw;
+ int error = 0;
+
+ emit_init(&emit_state);
+
+ for (;;) {
+ error = lex_tok(state, &tok);
+ if (error < 0) {
+ break;
+ }
+
+ if (parse_tok(state, &tok) < 0) {
+ break;
+ }
+
+ type = tokstr[tok.type];
+ raw = tok.raw;
+ oasm_debug("got token type %s (%s)\n", type, raw);
+ }
+
+ /* Process then destroy the emit state */
+ emit_process(state, &emit_state);
+ emit_destroy(&emit_state);
+}