diff options
Diffstat (limited to 'usr.bin/oasm/emit.c')
-rw-r--r-- | usr.bin/oasm/emit.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/usr.bin/oasm/emit.c b/usr.bin/oasm/emit.c index 139cf47..63f716a 100644 --- a/usr.bin/oasm/emit.c +++ b/usr.bin/oasm/emit.c @@ -377,6 +377,71 @@ emit_encode_nop(struct emit_state *state, struct oasm_token *tok) return TAILQ_NEXT(tok, link); } +/* + * Encode a bitwise instruction: + * + * and r, r/imm + * or r, r/imm + * xor r, r/imm + */ +static struct oasm_token * +emit_encode_bitw(struct emit_state *state, struct oasm_token *tok) +{ + inst_t curinst; + imm_t imm; + reg_t rd; + uint8_t opcode = OSMX64_AND; + char *inst_str = "and"; + + switch (tok->type) { + case TT_OR: + opcode = OSMX64_OR; + inst_str = "or"; + break; + case TT_XOR: + opcode = OSMX64_XOR; + inst_str = "xor"; + break; + } + + /* Next token should be a register */ + tok = TAILQ_NEXT(tok, link); + if (tok == NULL) { + oasm_err("[emit error]: expected register for '%s'\n", inst_str); + return NULL; + } + if (!tok_is_xreg(tok->type)) { + oasm_err("[emit error]: bad register for '%s'\n", inst_str); + return NULL; + } + + rd = ir_to_reg(tok->type); + tok = TAILQ_NEXT(tok, link); + if (tok == NULL) { + oasm_err("[emit error]: missing operand in '%s'\n", inst_str); + return NULL; + } + + /* + * Check that the next token is an immediate + * value. + * + * TODO: Allow a register operand to be passed + * to these instructions. + */ + if (tok->type != TT_IMM) { + oasm_err("[emit error]: expected <imm> for '%s'\n", inst_str); + return NULL; + } + + imm = tok->imm; + curinst.opcode = opcode; + curinst.rd = rd; + curinst.imm = imm; + emit_bytes(state, &curinst, sizeof(curinst)); + return TAILQ_NEXT(tok, link); +} + int emit_osmx64(struct emit_state *state, struct oasm_token *tp) { @@ -464,6 +529,11 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) case TT_DIV: curtok = emit_encode_arith(emit, curtok); break; + case TT_AND: + case TT_OR: + case TT_XOR: + curtok = emit_encode_bitw(emit, curtok); + break; case TT_BR: curtok = emit_encode_br(emit, curtok); break; @@ -471,7 +541,7 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) curtok = emit_encode_hlt(emit, curtok); break; default: - if (lex_is_mro(curtok->type)) { + if (tok_is_mro(curtok->type)) { curtok = emit_encode_mro(emit, curtok); break; } |