diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/kstat/kstat.c | 7 | ||||
-rw-r--r-- | usr.bin/oasm/emit.c | 88 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/emit.h | 16 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/label.h | 55 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/lex.h | 25 | ||||
-rw-r--r-- | usr.bin/oasm/include/oasm/state.h | 4 | ||||
-rw-r--r-- | usr.bin/oasm/label.c | 166 | ||||
-rw-r--r-- | usr.bin/oasm/lex.c | 85 | ||||
-rw-r--r-- | usr.bin/oasm/parse.c | 37 | ||||
-rw-r--r-- | usr.bin/oemu/cpu.c | 107 | ||||
-rw-r--r-- | usr.bin/oemu/include/oemu/osmx64.h | 16 | ||||
-rw-r--r-- | usr.bin/osh/osh.c | 40 |
12 files changed, 622 insertions, 24 deletions
diff --git a/usr.bin/kstat/kstat.c b/usr.bin/kstat/kstat.c index 853bc8b..e3b7e6a 100644 --- a/usr.bin/kstat/kstat.c +++ b/usr.bin/kstat/kstat.c @@ -37,6 +37,8 @@ get_sched_stat(void) { struct sched_stat stat; struct sched_cpu *cpu; + double nonline, noffline; + uint16_t online_percent; int fd; fd = open("/ctl/sched/stat", O_RDONLY); @@ -50,10 +52,15 @@ get_sched_stat(void) } close(fd); + noffline = stat.nhlt; + nonline = (stat.ncpu - noffline); + online_percent = (uint16_t)(((double)nonline / (nonline + noffline)) * 100); + printf("-------------------------------\n"); printf("Number of tasks: %d\n", stat.nproc); printf("Number of cores online: %d\n", stat.ncpu); printf("Scheduler quantum: %d usec\n", stat.quantum_usec); + printf("CPU is %d%% online\n", online_percent); printf("-------------------------------\n"); /* diff --git a/usr.bin/oasm/emit.c b/usr.bin/oasm/emit.c index eb38779..6b17eab 100644 --- a/usr.bin/oasm/emit.c +++ b/usr.bin/oasm/emit.c @@ -296,6 +296,87 @@ 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); +} + +/* + * Encode a NOP instruction + * + * 'nop' - no operands + * + * Returns the next token on success, + * otherwise NULL. + */ +static struct oasm_token * +emit_encode_nop(struct emit_state *state, struct oasm_token *tok) +{ + inst_t curinst; + + curinst.opcode = OSMX64_NOP; + curinst.rd = 0; + curinst.unused = 0; + emit_bytes(state, &curinst, sizeof(curinst)); + return TAILQ_NEXT(tok, link); +} + int emit_osmx64(struct emit_state *state, struct oasm_token *tp) { @@ -367,6 +448,9 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) curtok = TAILQ_FIRST(&emit->ir); while (curtok != NULL) { switch (curtok->type) { + case TT_NOP: + curtok = emit_encode_nop(emit, curtok); + break; case TT_MOV: curtok = emit_encode_mov(emit, curtok); break; @@ -387,6 +471,10 @@ emit_process(struct oasm_state *oasm, struct emit_state *emit) curtok = emit_encode_hlt(emit, curtok); break; default: + if (tok_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..3fc2674 100644 --- a/usr.bin/oasm/include/oasm/emit.h +++ b/usr.bin/oasm/include/oasm/emit.h @@ -56,12 +56,16 @@ #define OSMX64_OR 0x07 /* Bitwise OR operation */ #define OSMX64_XOR 0x08 /* Bitwise XOR operation */ #define OSMX64_AND 0x09 /* Bitwise AND operation */ -#define OSMX64_NOT 0x10 /* Bitwise NOT operation */ -#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 */ -#define OSMX64_BR 0x15 /* Branch */ +#define OSMX64_NOT 0x0A /* Bitwise NOT operation */ +#define OSMX64_SLL 0x0B /* Shift left logical operation */ +#define OSMX64_SRL 0x0C /* Shift right logical operation */ +#define OSMX64_MOV_IMM 0x0D /* Data move operation from IMM */ +#define OSMX64_HLT 0x0E /* Halt the processor */ +#define OSMX64_BR 0x0F /* Branch */ +#define OSMX64_MROB 0x10 /* Mask register over byte */ +#define OSMX64_MROW 0x11 /* Mask register over word */ +#define OSMX64_MROD 0x12 /* Mask register over dword */ +#define OSMX64_MROQ 0x13 /* Mask register over qword */ /* * OSMX64 register definitions diff --git a/usr.bin/oasm/include/oasm/label.h b/usr.bin/oasm/include/oasm/label.h new file mode 100644 index 0000000..8acb369 --- /dev/null +++ b/usr.bin/oasm/include/oasm/label.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _OASM_LABEL_H_ +#define _OASM_LABEL_H_ + +#include <sys/types.h> +#include <sys/queue.h> + +#define MAX_LABELS 128 + +/* + * Represents a label + * + * @name: Label name (e.g., _start) + * @ip: Address at which label code starts + */ +struct oasm_label { + char *name; + uintptr_t ip; + TAILQ_ENTRY(oasm_label) link; + TAILQ_HEAD(, oasm_label) buckets; +}; + +void labels_destroy(void); +int label_enter(const char *name, uintptr_t ip); +struct oasm_label *label_lookup(const char *name); + +#endif /* !_OASM_LABEL_H_ */ diff --git a/usr.bin/oasm/include/oasm/lex.h b/usr.bin/oasm/include/oasm/lex.h index 62183e0..873f6b9 100644 --- a/usr.bin/oasm/include/oasm/lex.h +++ b/usr.bin/oasm/include/oasm/lex.h @@ -33,6 +33,7 @@ #include <sys/queue.h> #include <sys/cdefs.h> #include <stdint.h> +#include <stdbool.h> struct oasm_state; @@ -89,6 +90,7 @@ struct oasm_state; */ typedef enum { TT_UNKNOWN, /* Unknown token */ + TT_NOP, /* No operation */ /* Arithmetic instructions */ TT_ADD, /* 'add' */ @@ -97,12 +99,17 @@ 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' */ TT_INC, /* 'inc' */ TT_DEC, /* 'dec' */ TT_IMM, /* #<n> */ + TT_LABEL, /* 'label: ...' */ /* Register sets */ __XN_REGS, /* x0-x15 */ @@ -155,4 +162,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 +tok_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/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/label.c b/usr.bin/oasm/label.c new file mode 100644 index 0000000..2647bb9 --- /dev/null +++ b/usr.bin/oasm/label.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/queue.h> +#include <oasm/label.h> +#include <oasm/log.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <stdbool.h> + +static struct oasm_label *labels[MAX_LABELS]; +static size_t label_count = 0; + +static uint32_t +fnv1_hash(const char *s) +{ + uint32_t hash = 2166136261UL; + const uint8_t *p = (uint8_t *)s; + + while (*p != '\0') { + hash ^= *p; + hash = hash * 0x01000193; + ++p; + } + + return hash; +} + +/* + * The label table is a big hashmap containing + * label entries. This function creates and add + * a new label into the table. + * + * @name: Name of the label (e.g., _start) + * @ip: Instruction pointer + */ +int +label_enter(const char *name, uintptr_t ip) +{ + uint32_t hash = fnv1_hash(name); + uint32_t idx = hash % MAX_LABELS; + struct oasm_label *lp, *lp_new; + + if (label_count >= MAX_LABELS) { + oasm_err("[internal error]: too many labels\n"); + return -EIO; + } + + lp_new = malloc(sizeof(*lp_new)); + if (lp_new == NULL) { + oasm_err("[internal error]: out of memory\n"); + return -ENOMEM; + } + + /* Initialize the label */ + lp_new->name = strdup(name); + lp_new->ip = ip; + TAILQ_INIT(&lp_new->buckets); + + /* + * If there is no existing entry here, we + * can take this slot. + */ + lp = labels[idx]; + if (lp == NULL) { + labels[idx] = lp_new; + ++label_count; + return 0; + } + + /* + * To prevent collisions in our table here, + * we must check if the name matches at all. + * If it does not, there is a collision and + * we'll have to add this to a bucket. + */ + if (strcmp(name, lp->name) != 0) { + TAILQ_INSERT_TAIL(&lp->buckets, lp_new, link); + ++label_count; + return 0; + } + + /* Can't put the same entry in twice */ + oasm_err("[internal error]: duplicate labels\n"); + return -EEXIST; +} + +/* + * Find a label entry in the label table. + * + * @name: Name of the label to lookup (e.g., _start) + */ +struct oasm_label * +label_lookup(const char *name) +{ + uint32_t hash = fnv1_hash(name); + uint32_t idx = hash % MAX_LABELS; + struct oasm_label *lp, *lp_tmp; + + lp = labels[idx]; + if (lp == NULL) { + return NULL; + } + + /* Is this the label we are looking up? */ + if (strcmp(name, lp->name) == 0) { + return lp; + } + + /* Maybe there was a collision? */ + TAILQ_FOREACH(lp_tmp, &lp->buckets, link) { + if (strcmp(name, lp_tmp->name) == 0) { + return lp_tmp; + } + } + + return NULL; +} + +/* + * Clean up all allocated labels by + * calling free() on each entry of + * the queue. + */ +void +labels_destroy(void) +{ + struct oasm_label *lp; + + for (size_t i = 0; i < MAX_LABELS; ++i) { + lp = labels[i]; + if (lp != NULL) { + free(lp->name); + free(lp); + } + } +} diff --git a/usr.bin/oasm/lex.c b/usr.bin/oasm/lex.c index a33a570..fea9dc3 100644 --- a/usr.bin/oasm/lex.c +++ b/usr.bin/oasm/lex.c @@ -40,6 +40,7 @@ static char putback = '\0'; /* Instruction mnemonic strings */ +#define S_IMN_NOP "nop" #define S_IMN_MOV "mov" #define S_IMN_ADD "add" #define S_IMN_SUB "sub" @@ -49,6 +50,24 @@ 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 + +/* + * 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 @@ -63,7 +82,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 +173,10 @@ lex_nomstr(struct oasm_state *state, char **res) retval = tmp; break; } + if (tmp == ':') { + retval = tmp; + break; + } if (tmp == '\n') { ++state->line; retval = tmp; @@ -205,6 +228,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) { @@ -295,7 +353,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 +364,21 @@ 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; + } + + /* No operation? */ + if (strcmp(p, S_IMN_NOP) == 0) { + ttp->type = TT_NOP; + ttp->raw = p; + return 0; + } /* Arithmetic operation? */ if ((tok = token_arith(p)) != TT_UNKNOWN) { @@ -330,6 +402,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) { @@ -340,6 +418,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..c81b498 100644 --- a/usr.bin/oasm/parse.c +++ b/usr.bin/oasm/parse.c @@ -34,10 +34,12 @@ #include <oasm/lex.h> #include <oasm/parse.h> #include <oasm/log.h> +#include <oasm/label.h> static struct emit_state emit_state; static const char *tokstr[] = { [ TT_UNKNOWN] = "bad", + [ TT_NOP ] = "nop", [ TT_ADD ] = "add", [ TT_SUB ] = "sub", [ TT_MUL ] = "mul", @@ -49,6 +51,14 @@ static const char *tokstr[] = { [ TT_DEC ] = "dec", [ TT_MOV ] = "mov", [ 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", @@ -117,8 +127,12 @@ parse_reg(struct oasm_state *state, struct oasm_token *tok) state->last = tok->type; break; default: + if (tok_is_mro(state->last)) { + break; + } + p = tokstr[state->last]; - oasm_err("bad instruction '%s' for regop\n", p); + oasm_err("bad token '%s' for regop\n", p); return -1; } @@ -134,22 +148,24 @@ parse_reg(struct oasm_state *state, struct oasm_token *tok) } static int -parse_imm(struct oasm_token *tok, tt_t last) -{ - return 0; -} - -static int parse_tok(struct oasm_state *state, struct oasm_token *tok) { const char *p; int error; switch (tok->type) { + case TT_NOP: + state->last = tok->type; + emit_osmx64(&emit_state, tok); + break; case TT_BR: state->last = tok->type; emit_osmx64(&emit_state, tok); break; + case TT_LABEL: + state->last = tok->type; + label_enter(tok->raw, state->pip); + break; case TT_HLT: state->last = tok->type; emit_osmx64(&emit_state, tok); @@ -188,6 +204,12 @@ parse_tok(struct oasm_state *state, struct oasm_token *tok) emit_osmx64(&emit_state, tok); break; default: + if (tok_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; @@ -230,4 +252,5 @@ parse_enter(struct oasm_state *state) /* Process then destroy the emit state */ emit_process(state, &emit_state); emit_destroy(&emit_state); + labels_destroy(); } diff --git a/usr.bin/oemu/cpu.c b/usr.bin/oemu/cpu.c index 07ddc7b..49d4671 100644 --- a/usr.bin/oemu/cpu.c +++ b/usr.bin/oemu/cpu.c @@ -27,15 +27,35 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> #include <sys/param.h> #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <stdbool.h> #include <oemu/cpu.h> #include <oemu/types.h> #include <oemu/osmx64.h> /* + * Return true if the instruction is an + * MRO type instruction. + */ +static bool +cpu_is_mro(inst_t *inst) +{ + switch (inst->opcode) { + case INST_MROB: + case INST_MROW: + case INST_MROD: + case INST_MROQ: + return true; + } + + return false; +} + +/* * Decode the INST_MOV_IMM instruction * * @cpu: CPU that is executing @@ -225,6 +245,77 @@ cpu_br(struct oemu_cpu *cpu, inst_t *inst) } /* + * Decode MRO type instructions + */ +static void +cpu_mro(struct oemu_cpu *cpu, inst_t *inst) +{ + inst_t *next_inst; + struct cpu_regs *regs = &cpu->regs; + char *inst_str = "bad"; + uint64_t mask = 0; + bool set_mask = false; + imm_t imm; + + switch (inst->imm) { + case 0: break; + case 1: + set_mask = true; + break; + default: + imm = inst->imm & 1; + if (inst->imm == 1) { + set_mask = true; + } + break; + } + + switch (inst->opcode) { + case INST_MROB: + inst_str = "mrob"; + if (!set_mask) { + break; + } + mask |= MASK(8); + break; + case INST_MROW: + inst_str = "mrow"; + if (!set_mask) { + break; + } + mask |= MASK(16); + break; + case INST_MROD: + inst_str = "mrod"; + if (!set_mask) { + break; + } + mask |= MASK(32); + break; + case INST_MROQ: + inst_str = "mroq"; + if (!set_mask) { + break; + } + mask |= __UINT64_MAX; + break; + } + + if (inst->rd > NELEM(regs->xreg)) { + printf("bad register operand for '%s'\n", inst_str); + return; + } + + if (set_mask) { + imm = regs->xreg[inst->rd] |= mask; + printf("set %x->x%d, new=%x\n", mask, inst->rd, imm); + } else { + imm = regs->xreg[inst->rd] &= ~mask; + printf("cleared %x->x%d, new=%x\n", mask, inst->rd, imm); + } +} + +/* * Reset a CPU to a default state */ void @@ -286,6 +377,10 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) inst = (inst_t *)&memp[regs->ip]; switch (inst->opcode) { + case INST_NOP: + /* NOP */ + regs->ip += sizeof(*inst); + continue; case INST_MOV_IMM: cpu_mov_imm(cpu, inst); break; @@ -310,8 +405,20 @@ cpu_kick(struct oemu_cpu *cpu, struct sysmem *mem) case INST_BR: cpu_br(cpu, inst); break; + default: + if (cpu_is_mro(inst)) { + cpu_mro(cpu, inst); + } + break; } + /* + * X0 is readonly and should always be zero, undo + * any writes or side effects from any operations + * upon this register. + */ + regs->xreg[0] = 0; + /* Is this a halt instruction? */ if (inst->opcode == INST_HLT) { printf("HALTED\n"); diff --git a/usr.bin/oemu/include/oemu/osmx64.h b/usr.bin/oemu/include/oemu/osmx64.h index b1df5d3..ffd6156 100644 --- a/usr.bin/oemu/include/oemu/osmx64.h +++ b/usr.bin/oemu/include/oemu/osmx64.h @@ -43,12 +43,16 @@ #define INST_OR 0x07 /* Bitwise OR operation */ #define INST_XOR 0x08 /* Bitwise XOR operation */ #define INST_AND 0x09 /* Bitwise AND operation */ -#define INST_NOT 0x10 /* Bitwise NOT operation */ -#define INST_SLL 0x11 /* Shift left logical operation */ -#define INST_SRL 0x12 /* Shift right logical operation */ -#define INST_MOV_IMM 0x13 /* Data move operation from IMM */ -#define INST_HLT 0x14 /* Halt */ -#define INST_BR 0x15 /* Branch */ +#define INST_NOT 0x0A /* Bitwise NOT operation */ +#define INST_SLL 0x0B /* Shift left logical operation */ +#define INST_SRL 0x0C /* Shift right logical operation */ +#define INST_MOV_IMM 0x0D /* Data move operation from IMM */ +#define INST_HLT 0x0E /* Halt */ +#define INST_BR 0x0F /* Branch */ +#define INST_MROB 0x10 /* Mask register over byte */ +#define INST_MROW 0x11 /* Mask register over word */ +#define INST_MROD 0x12 /* Mask register over dword */ +#define INST_MROQ 0x13 /* Mask register over qword */ /* Registers */ #define REG_X0 0x00 diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index af7f4ab..545f95a 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -43,6 +43,9 @@ #define is_printable(C) ((C) >= 32 && (C) <= 126) #define is_ascii(C) ((C) >= 0 && (C) <= 128) +#define INPUT_SIZE 64 + +#define REPEAT "!!" #define COMMENT '@' #define WELCOME \ ":::::::::::::::::::::::::::::::::::::::\n" \ @@ -66,7 +69,8 @@ #define PROMPT "[%s::osmora]~ " -static char buf[64]; +static char last_command[INPUT_SIZE]; +static char buf[INPUT_SIZE]; static int running; static int bell_fd; static bool bs_bell = true; /* Beep on backspace */ @@ -365,6 +369,18 @@ parse_line(char *input) struct parse_state state = {0}; pid_t child; + /* + * If we are using the REPEAT shorthand, + * repeat the last command. We return -EAGAIN + * to indicate we did not parse a normal command + * so the repeat command isn't pushed into the last + * command buffer and we enter a recursive hell. + */ + if (strcmp(input, REPEAT) == 0) { + parse_line(last_command); + return -EAGAIN; + } + /* Ensure the aux vector is zeored */ memset(argv, 0, sizeof(argv)); @@ -426,6 +442,25 @@ open_script(const char *pathname) return 0; } +static void +dump_file(const char *pathname) +{ + FILE *file; + char buf[64]; + int fd; + + file = fopen(pathname, "r"); + if (file == NULL) { + return; + } + + while (fgets(buf, sizeof(buf), file) != NULL) { + printf("%s", buf); + } + + fclose(file); +} + int main(int argc, char **argv) { @@ -442,7 +477,7 @@ main(int argc, char **argv) running = 1; bell_fd = open("/dev/beep", O_WRONLY); - puts(WELCOME); + dump_file("/etc/motd"); while (running) { printf(PROMPT, getlogin()); @@ -457,6 +492,7 @@ main(int argc, char **argv) continue; } + memcpy(last_command, buf, buf_i + 1); buf[0] = '\0'; } return 0; |