diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-23 18:38:09 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-23 18:47:57 -0400 |
commit | 729a19a6b7e636a8af3a15f7fe5204cc0d59dbf7 (patch) | |
tree | 9dc5dbacd0576f1aa369e9442f442e6a117865bc | |
parent | f9a78caefd6f254e854fd6cdf64a8642ccddc34e (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.s | 27 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/lex.h | 1 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/state.h | 4 | ||||
-rw-r--r-- | usr.bin/oasm/lex.c | 32 | ||||
-rw-r--r-- | usr.bin/oasm/parse.c | 5 |
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); |