summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/kstat/kstat.c7
-rw-r--r--usr.bin/oasm/emit.c88
-rw-r--r--usr.bin/oasm/include/oasm/emit.h16
-rw-r--r--usr.bin/oasm/include/oasm/label.h55
-rw-r--r--usr.bin/oasm/include/oasm/lex.h25
-rw-r--r--usr.bin/oasm/include/oasm/state.h4
-rw-r--r--usr.bin/oasm/label.c166
-rw-r--r--usr.bin/oasm/lex.c85
-rw-r--r--usr.bin/oasm/parse.c37
-rw-r--r--usr.bin/oemu/cpu.c107
-rw-r--r--usr.bin/oemu/include/oemu/osmx64.h16
-rw-r--r--usr.bin/osh/osh.c40
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;