diff options
Diffstat (limited to 'usr.bin/oasm')
-rw-r--r-- | usr.bin/oasm/emit.c | 101 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/emit.h | 3 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/lex.h | 1 | ||||
-rw-r--r-- | usr.bin/oasm/lex.c | 6 | ||||
-rw-r--r-- | usr.bin/oasm/parse.c | 33 |
5 files changed, 136 insertions, 8 deletions
diff --git a/usr.bin/oasm/emit.c b/usr.bin/oasm/emit.c index 4bad76b..0e8ad4e 100644 --- a/usr.bin/oasm/emit.c +++ b/usr.bin/oasm/emit.c @@ -103,7 +103,6 @@ emit_encode_mov(struct emit_state *state, struct oasm_token *tok) return NULL; } - /* Next token should be an IMM */ tok = TAILQ_NEXT(tok, link); if (tok == NULL) { @@ -170,8 +169,96 @@ emit_encode_incdec(struct emit_state *state, struct oasm_token *tok) return TAILQ_NEXT(tok, link); } +/* + * Encode an arithmetic instruction + * + * add [r], <imm> + * + * Returns the next token on success, + * otherwise NULL. + */ +static struct oasm_token * +emit_encode_arith(struct emit_state *state, struct oasm_token *tok) +{ + inst_t curinst; + reg_t rd; + uint8_t opcode = OSMX64_ADD; + char *inst_str = "add"; + + switch (tok->type) { + case TT_SUB: + inst_str = "sub"; + opcode = OSMX64_SUB; + break; + case TT_MUL: + inst_str = "mul"; + opcode = OSMX64_MUL; + break; + case TT_DIV: + inst_str = "div"; + opcode = OSMX64_DIV; + break; + } + + /* + * The next operand must be an X<n> + * register. + */ + tok = TAILQ_NEXT(tok, link); + if (tok == NULL) { + return NULL; + } + if (!tok_is_xreg(tok->type)) { + oasm_err("[emit error]: bad '%s' order\n", inst_str); + return NULL; + } + + /* Get the register and validate it */ + rd = ir_to_reg(tok->type); + if (rd == OSMX64_R_BAD) { + oasm_err("[emit error]: got bad reg in '%s'\n", inst_str); + return NULL; + } + + /* The next token should be an <imm> */ + tok = TAILQ_NEXT(tok, link); + if (tok == NULL) { + return NULL; + } + if (tok->type != TT_IMM) { + oasm_err("[emit error]: expected <imm> 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); +} + +/* + * Encode a HLT instruction + * + * 'hlt' - no operands + * + * Returns the next token on success, + * otherwise NULL. + */ +static struct oasm_token * +emit_encode_hlt(struct emit_state *state, struct oasm_token *tok) +{ + inst_t curinst; + + curinst.opcode = OSMX64_HLT; + curinst.rd = 0; + curinst.unused = 0; + emit_bytes(state, &curinst, sizeof(curinst)); + return TAILQ_NEXT(tok, link); +} + int -emit_osxm64(struct emit_state *state, struct oasm_token *tp) +emit_osmx64(struct emit_state *state, struct oasm_token *tp) { struct oasm_token *toknew; @@ -248,11 +335,19 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) case TT_DEC: curtok = emit_encode_incdec(emit, curtok); break; + case TT_ADD: + case TT_SUB: + case TT_MUL: + case TT_DIV: + curtok = emit_encode_arith(emit, curtok); + break; + case TT_HLT: + curtok = emit_encode_hlt(emit, curtok); + break; default: curtok = TAILQ_NEXT(curtok, link); break; } - } return 0; diff --git a/usr.bin/oasm/include/oasm/emit.h b/usr.bin/oasm/include/oasm/emit.h index f4b4f77..d289adb 100644 --- a/usr.bin/oasm/include/oasm/emit.h +++ b/usr.bin/oasm/include/oasm/emit.h @@ -60,6 +60,7 @@ #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 */ /* * OSMX64 register definitions @@ -107,6 +108,6 @@ struct emit_state { int emit_init(struct emit_state *state); int emit_destroy(struct emit_state *state); int emit_process(struct oasm_state *oasm, struct emit_state *emit); -int emit_osxm64(struct emit_state *state, struct oasm_token *tp); +int emit_osmx64(struct emit_state *state, struct oasm_token *tp); #endif /* !_EMIT_H_ */ diff --git a/usr.bin/oasm/include/oasm/lex.h b/usr.bin/oasm/include/oasm/lex.h index 28ad52c..6ffaf79 100644 --- a/usr.bin/oasm/include/oasm/lex.h +++ b/usr.bin/oasm/include/oasm/lex.h @@ -95,6 +95,7 @@ typedef enum { TT_SUB, /* 'sub' */ TT_MUL, /* 'mul' */ TT_DIV, /* 'div' */ + TT_HLT, /* 'hlt' */ /* Register ops */ TT_MOV, /* 'mov' */ diff --git a/usr.bin/oasm/lex.c b/usr.bin/oasm/lex.c index f8427e0..7b78d54 100644 --- a/usr.bin/oasm/lex.c +++ b/usr.bin/oasm/lex.c @@ -42,9 +42,11 @@ static char putback = '\0'; #define S_IMN_MOV "mov" #define S_IMN_ADD "add" #define S_IMN_SUB "sub" +#define S_IMN_MUL "mul" #define S_IMN_DIV "div" #define S_IMN_INC "inc" #define S_IMN_DEC "dec" +#define S_IMN_HLT "hlt" /* * Returns 0 if a char is counted as a @@ -179,6 +181,10 @@ token_arith(char *p) return TT_SUB; } else if (strcmp(p, S_IMN_DIV) == 0) { return TT_DIV; + } else if (strcmp(p, S_IMN_HLT) == 0) { + return TT_HLT; + } else if (strcmp(p, S_IMN_MUL) == 0) { + return TT_MUL; } return TT_UNKNOWN; diff --git a/usr.bin/oasm/parse.c b/usr.bin/oasm/parse.c index 7a855ca..9a4dd0e 100644 --- a/usr.bin/oasm/parse.c +++ b/usr.bin/oasm/parse.c @@ -42,6 +42,7 @@ static const char *tokstr[] = { [ TT_SUB ] = "sub", [ TT_MUL ] = "mul", [ TT_DIV ] = "div", + [ TT_HLT ] = "hlt", [ TT_COMMA ] = ",", [ TT_INC ] = "inc", [ TT_DEC ] = "dec", @@ -107,6 +108,10 @@ parse_reg(struct oasm_state *state, struct oasm_token *tok) 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: @@ -122,7 +127,7 @@ parse_reg(struct oasm_state *state, struct oasm_token *tok) } state->last = tok->type; - emit_osxm64(&emit_state, tok); + emit_osmx64(&emit_state, tok); return 0; } @@ -139,14 +144,34 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok) 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_osxm64(&emit_state, tok); + 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_osxm64(&emit_state, tok); + emit_osmx64(&emit_state, tok); break; case TT_IMM: p = tokstr[state->last]; @@ -154,7 +179,7 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok) printf("expected X<n> but got %s\n", p); return -1; } - emit_osxm64(&emit_state, tok); + emit_osmx64(&emit_state, tok); break; default: if (!tok->is_reg) { |