summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-07-23 18:38:09 -0400
committerIan Moffett <ian@osmora.org>2025-07-23 18:47:57 -0400
commit729a19a6b7e636a8af3a15f7fe5204cc0d59dbf7 (patch)
tree9dc5dbacd0576f1aa369e9442f442e6a117865bc
parentf9a78caefd6f254e854fd6cdf64a8642ccddc34e (diff)
oasm: Add initial support for labels
A label is like a pin on a map with a number attached to it. OASM keeps track of a number referred to as the psuedo instruction pointer (PIP). This value is initially zero by default and is incremented every instruction. The purpose of this value is to pin a location in the code and mark it to be at a specific address so that further references to that label would be translated to the previous PIP value at the time of encountering the label. Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--etc/oemu/test-00.s27
-rw-r--r--usr.bin/oasm/include/oasm/lex.h1
-rw-r--r--usr.bin/oasm/include/oasm/state.h4
-rw-r--r--usr.bin/oasm/lex.c32
-rw-r--r--usr.bin/oasm/parse.c5
5 files changed, 53 insertions, 16 deletions
diff --git a/etc/oemu/test-00.s b/etc/oemu/test-00.s
index b34c099..1fa7ff1 100644
--- a/etc/oemu/test-00.s
+++ b/etc/oemu/test-00.s
@@ -1,13 +1,14 @@
-mov x0, #1 ! ~ 0x00000000
-mov x1, #2 ! ~ 0x00000004
-mov x2, #3 ! ~ 0x00000008
- ! X
-mov x2, #20 ! ~ 0x0000000C
-br x2 ! ~ 0x00000010 -----+
-!!!!!!!!!!!!!! X |
-!!!!!!!!!!!!!! X |
- ! X |
-dec x0 ! ~ 0x00000014 <----+
-inc x1 ! ~ 0x00000018
-add x2, #3 ! ~ 0x0000001C
-hlt ! ~ 0x00000020
+mov x0, #1 ! ~ 0x00000000
+mov x1, #2 ! ~ 0x00000004
+mov x2, #3 ! ~ 0x00000008
+ ! X
+some_label: ! X
+ mov x2, #20 ! ~ 0x0000000C
+ br x2 ! ~ 0x00000010 -----+
+ !!!!!!!!!!!!!! X |
+ !!!!!!!!!!!!!! X |
+ ! X |
+ dec x0 ! ~ 0x00000014 <----+
+ inc x1 ! ~ 0x00000018
+ add x2, #3 ! ~ 0x0000001C
+ hlt ! ~ 0x00000020
diff --git a/usr.bin/oasm/include/oasm/lex.h b/usr.bin/oasm/include/oasm/lex.h
index 62183e0..69e50a1 100644
--- a/usr.bin/oasm/include/oasm/lex.h
+++ b/usr.bin/oasm/include/oasm/lex.h
@@ -103,6 +103,7 @@ typedef enum {
TT_INC, /* 'inc' */
TT_DEC, /* 'dec' */
TT_IMM, /* #<n> */
+ TT_LABEL, /* 'label: ...' */
/* Register sets */
__XN_REGS, /* x0-x15 */
diff --git a/usr.bin/oasm/include/oasm/state.h b/usr.bin/oasm/include/oasm/state.h
index 5f58144..6dd2435 100644
--- a/usr.bin/oasm/include/oasm/state.h
+++ b/usr.bin/oasm/include/oasm/state.h
@@ -39,6 +39,8 @@
* OASM state:
*
* @filename: Filname of unit we are parsing
+ * @pip: Pseudo instruction pointer
+ * @label_ip: IP at current label start
* @in_fd: Input file descriptor
* @out_fd: Resulting binary output file descriptor
* @line: Current line number
@@ -46,6 +48,8 @@
*/
struct oasm_state {
char *filename;
+ off_t pip;
+ off_t label_ip;
int in_fd;
int out_fd;
off_t line;
diff --git a/usr.bin/oasm/lex.c b/usr.bin/oasm/lex.c
index a33a570..87ac464 100644
--- a/usr.bin/oasm/lex.c
+++ b/usr.bin/oasm/lex.c
@@ -50,6 +50,20 @@ static char putback = '\0';
#define S_IMN_HLT "hlt"
#define S_IMN_BR "br"
+/* Instruction length */
+#define OSMX64_INST_LEN 4
+
+/*
+ * Update the state when the caller encounters
+ * a newline.
+ */
+static inline void
+lex_newline(struct oasm_state *state)
+{
+ ++state->line;
+ state->pip += OSMX64_INST_LEN;
+}
+
/*
* Returns 0 if a char is counted as a
* skippable token. Otherwise, -1
@@ -63,7 +77,7 @@ lex_skippable(struct oasm_state *state, char c)
case '\t': return 0;
case '\r': return 0;
case '\n':
- ++state->line;
+ lex_newline(state);
return 0;
}
@@ -154,6 +168,10 @@ lex_nomstr(struct oasm_state *state, char **res)
retval = tmp;
break;
}
+ if (tmp == ':') {
+ retval = tmp;
+ break;
+ }
if (tmp == '\n') {
++state->line;
retval = tmp;
@@ -295,7 +313,7 @@ lex_tok(struct oasm_state *state, struct oasm_token *ttp)
switch (c) {
case '\n':
- ++state->line;
+ lex_newline(state);
return 0;
case '\0':
return -1;
@@ -306,7 +324,14 @@ lex_tok(struct oasm_state *state, struct oasm_token *ttp)
ttp->raw = NULL;
lex_putback(c);
- lex_nomstr(state, &p);
+ c = lex_nomstr(state, &p);
+
+ while (c == ':') {
+ ttp->type = TT_LABEL;
+ ttp->raw = p;
+ state->label_ip = state->pip;
+ return 0;
+ }
/* Arithmetic operation? */
if ((tok = token_arith(p)) != TT_UNKNOWN) {
@@ -340,6 +365,7 @@ lex_tok(struct oasm_state *state, struct oasm_token *ttp)
ttp->raw = p;
return 0;
}
+
oasm_err("bad token \"%s\"\n", p);
lex_try_free(p);
return -1;
diff --git a/usr.bin/oasm/parse.c b/usr.bin/oasm/parse.c
index 673fbcd..113671f 100644
--- a/usr.bin/oasm/parse.c
+++ b/usr.bin/oasm/parse.c
@@ -49,6 +49,8 @@ static const char *tokstr[] = {
[ TT_DEC ] = "dec",
[ TT_MOV ] = "mov",
[ TT_IMM ] = "<imm>",
+ [ TT_LABEL] = "<label>",
+
/* X<n> registers */
[ TT_X0 ] = "x0",
@@ -150,6 +152,9 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok)
state->last = tok->type;
emit_osmx64(&emit_state, tok);
break;
+ case TT_LABEL:
+ state->last = tok->type;
+ break;
case TT_HLT:
state->last = tok->type;
emit_osmx64(&emit_state, tok);