diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-24 03:41:39 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-24 03:50:04 -0400 |
commit | af7a0cf9b65d6fee20029fe67c95c494f4b402a7 (patch) | |
tree | bef5ae96cde9bad9cad5f3350a92072f58d594dd | |
parent | 2de38a06acd1f8a392f1c6ea74a7b0aaa0de3692 (diff) |
oasm: Add encoding for MRO type instructions
This commit introduces encoding logic for 4 additional instructions:
- MROB (Mask Register Over [byte])
- MROW (Mask Register Over [word])
- MROD (Mask Register Over [dword])
- MROQ (Mask Register Over [qword])
This instruction is used to fill a register with a specific length of
zeros or ones. For example, to fill a register (e.g., x2) with 16-bits
of 1s:
--
!!
!! Clear bits x2[7:0]... Mrrp,,
!! mrow!!
!!
mrow x2, #1
--
Similarly, an operand of zero sets it to zero. For example, to clear an
entire 64-bit register with zeros. Something like this can be done:
--
mroq x1, #0
--
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | usr.bin/oasm/emit.c | 65 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/emit.h | 4 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/lex.h | 22 | ||||
-rw-r--r-- | usr.bin/oasm/lex.c | 45 | ||||
-rw-r--r-- | usr.bin/oasm/parse.c | 17 |
5 files changed, 153 insertions, 0 deletions
diff --git a/usr.bin/oasm/emit.c b/usr.bin/oasm/emit.c index eb38779..3261522 100644 --- a/usr.bin/oasm/emit.c +++ b/usr.bin/oasm/emit.c @@ -296,6 +296,67 @@ emit_encode_br(struct emit_state *state, struct oasm_token *tok) return TAILQ_NEXT(tok, link); } +/* + * Encode the MRO type instructions + * + * mrob x1[7:0] + * mrow x1[15:0] ! Mrowwww :3333 + * mrod x1[31:0] + * mroq x[63:0] + * + * Returns the next token on success, + * otherwise NULL. + */ +static struct oasm_token * +emit_encode_mro(struct emit_state *state, struct oasm_token *tok) +{ + inst_t curinst; + reg_t rd; + uint8_t opcode = OSMX64_MROB; + char *inst_str = "mrob"; + + switch (tok->type) { + case TT_MROW: + opcode = OSMX64_MROW; + inst_str = "mrow"; + break; + case TT_MROD: + opcode = OSMX64_MROD; + inst_str = "mrod"; + break; + case TT_MROQ: + opcode = OSMX64_MROQ; + inst_str = "mroq"; + break; + } + + /* Next token should be a register */ + tok = TAILQ_NEXT(tok, link); + if (!tok_is_xreg(tok->type)) { + oasm_err("[emit error]: expected register in '%s'\n", inst_str); + return NULL; + } + + rd = ir_to_reg(tok->type); + if (rd == OSMX64_R_BAD) { + oasm_err("[emit error]: got bad register in '%s'\n", inst_str); + return NULL; + } + + /* Next token should be an IMM */ + tok = TAILQ_NEXT(tok, link); + if (tok->type != TT_IMM) { + oasm_err("[emit error]: expected <imm> after reg in '%s'\n", inst_str); + return NULL; + } + + curinst.opcode = opcode; + curinst.rd = rd; + curinst.imm = tok->imm; + emit_bytes(state, &curinst, sizeof(curinst)); + return TAILQ_NEXT(tok, link); +} + int emit_osmx64(struct emit_state *state, struct oasm_token *tp) { @@ -387,6 +448,10 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) curtok = emit_encode_hlt(emit, curtok); break; default: + if (lex_is_mro(curtok->type)) { + curtok = emit_encode_mro(emit, curtok); + break; + } curtok = TAILQ_NEXT(curtok, link); break; } diff --git a/usr.bin/oasm/include/oasm/emit.h b/usr.bin/oasm/include/oasm/emit.h index dab63d0..0236967 100644 --- a/usr.bin/oasm/include/oasm/emit.h +++ b/usr.bin/oasm/include/oasm/emit.h @@ -62,6 +62,10 @@ #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 */ /* * OSMX64 register definitions diff --git a/usr.bin/oasm/include/oasm/lex.h b/usr.bin/oasm/include/oasm/lex.h index 69e50a1..fa82398 100644 --- a/usr.bin/oasm/include/oasm/lex.h +++ b/usr.bin/oasm/include/oasm/lex.h @@ -97,6 +97,10 @@ typedef enum { TT_DIV, /* 'div' */ TT_HLT, /* 'hlt' */ TT_BR, /* 'br' */ + TT_MROB, /* 'mrob' */ + TT_MROW, /* 'mrow' */ + TT_MROD, /* 'mrod' */ + TT_MROQ, /* 'mroq' */ /* Register ops */ TT_MOV, /* 'mov' */ @@ -156,4 +160,22 @@ tok_is_xreg(tt_t tok) return false; } +/* + * Check if a token is of an MRO type + * instruction. Returns true on match. + */ +__always_inline static inline bool +lex_is_mro(tt_t tok) +{ + switch (tok) { + case TT_MROB: + case TT_MROW: + case TT_MROD: + case TT_MROQ: + return true; + } + + return false; +} + #endif /* !_OASM_LEX_H_ */ diff --git a/usr.bin/oasm/lex.c b/usr.bin/oasm/lex.c index 87ac464..dcd7c1f 100644 --- a/usr.bin/oasm/lex.c +++ b/usr.bin/oasm/lex.c @@ -49,6 +49,10 @@ static char putback = '\0'; #define S_IMN_DEC "dec" #define S_IMN_HLT "hlt" #define S_IMN_BR "br" +#define S_IMN_MROB "mrob" +#define S_IMN_MROW "mrow" +#define S_IMN_MROD "mrod" +#define S_IMN_MROQ "mroq" /* Instruction length */ #define OSMX64_INST_LEN 4 @@ -223,6 +227,41 @@ token_cfi(char *p) return TT_UNKNOWN; } +/* + * Bitwise MRO instructions + */ +static tt_t +token_bitw_mro(char *p) +{ + if (strcmp(p, S_IMN_MROB) == 0) { + return TT_MROB; + } else if (strcmp(p, S_IMN_MROW) == 0) { + return TT_MROW; + } else if (strcmp(p, S_IMN_MROD) == 0) { + return TT_MROD; + } else if (strcmp(p, S_IMN_MROQ) == 0) { + return TT_MROQ; + } + + return TT_UNKNOWN; +} + +/* + * Bitwise instructions + */ +static tt_t +token_bitw(char *p) +{ + tt_t token; + + token = token_bitw_mro(p); + if (token != TT_UNKNOWN) { + return token; + } + + return TT_UNKNOWN; +} + static tt_t token_xreg(char *p) { @@ -355,6 +394,12 @@ lex_tok(struct oasm_state *state, struct oasm_token *ttp) return 0; } + if ((tok = token_bitw(p)) != TT_UNKNOWN) { + ttp->type = tok; + ttp->raw = p; + return 0; + } + /* Immediate operand? */ if ((tok = token_operand(p)) != TT_UNKNOWN) { if (tok == TT_IMM) { diff --git a/usr.bin/oasm/parse.c b/usr.bin/oasm/parse.c index 4651b55..ff3c9d2 100644 --- a/usr.bin/oasm/parse.c +++ b/usr.bin/oasm/parse.c @@ -51,6 +51,12 @@ static const char *tokstr[] = { [ TT_IMM ] = "<imm>", [ TT_LABEL] = "<label>", + /* Bitwise */ + [ TT_MROB ] = "mrob", + [ TT_MROW ] = "mrow", + [ TT_MROD ] = "mrod", + [ TT_MROQ ] = "mroq", + /* X<n> registers */ [ TT_X0 ] = "x0", @@ -119,6 +125,11 @@ parse_reg(struct oasm_state *state, struct oasm_token *tok) state->last = tok->type; break; default: + if (lex_is_mro(state->last)) { + state->last = tok->type; + break; + } + p = tokstr[state->last]; oasm_err("bad instruction '%s' for regop\n", p); return -1; @@ -187,6 +198,12 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok) emit_osmx64(&emit_state, tok); break; default: + if (lex_is_mro(tok->type)) { + state->last = tok->type; + emit_osmx64(&emit_state, tok); + return 0; + } + if (!tok->is_reg) { oasm_err("syntax error\n"); return -1; |