summaryrefslogtreecommitdiff
path: root/include/mips32.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/mips32.h142
1 files changed, 142 insertions, 0 deletions
diff --git a/include/mips32.h b/include/mips32.h
new file mode 100644
index 0000000..e2b86b7
--- /dev/null
+++ b/include/mips32.h
@@ -0,0 +1,142 @@
+/* Copyright (c) 2024 Freya Murphy */
+
+#ifndef __MIPS32_H__
+#define __MIPS32_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <mlimits.h>
+
+/* all mips registers $0-$31 */
+enum mips32_register {
+ MIPS32_REG_ZERO = 0,
+ MIPS32_REG_AT = 1,
+ MIPS32_REG_V0 = 2,
+ MIPS32_REG_V1 = 3,
+ MIPS32_REG_A0 = 4,
+ MIPS32_REG_A1 = 5,
+ MIPS32_REG_A2 = 6,
+ MIPS32_REG_A3 = 7,
+ MIPS32_REG_T0 = 8,
+ MIPS32_REG_T1 = 9,
+ MIPS32_REG_T2 = 10,
+ MIPS32_REG_T3 = 11,
+ MIPS32_REG_T4 = 12,
+ MIPS32_REG_T5 = 13,
+ MIPS32_REG_T6 = 14,
+ MIPS32_REG_T7 = 15,
+ MIPS32_REG_S0 = 16,
+ MIPS32_REG_S1 = 17,
+ MIPS32_REG_S2 = 18,
+ MIPS32_REG_S3 = 19,
+ MIPS32_REG_S4 = 20,
+ MIPS32_REG_S5 = 21,
+ MIPS32_REG_S6 = 22,
+ MIPS32_REG_S7 = 23,
+ MIPS32_REG_T8 = 24,
+ MIPS32_REG_T9 = 25,
+ MIPS32_REG_K0 = 26,
+ MIPS32_REG_K1 = 27,
+ MIPS32_REG_GP = 28,
+ MIPS32_REG_SP = 29,
+ MIPS32_REG_FP = 30,
+ MIPS32_REG_RA = 31,
+};
+
+/* mips instruction */
+union mips32_instruction {
+ /* raw ins */
+ uint32_t raw : 32;
+ /* register type */
+ struct {
+ uint32_t funct : 6;
+ uint32_t shamt : 5;
+ uint32_t rd : 5;
+ uint32_t rt : 5;
+ uint32_t rs : 5;
+ uint32_t op : 6;
+ };
+ /* immediate type */
+ struct {
+ uint32_t immd : 16;
+ uint32_t : 16;
+ };
+ /* jump type */
+ struct {
+ uint32_t target : 26;
+ uint32_t : 6;
+ };
+ /* branch compact */
+ struct {
+ int32_t offs26 : 26;
+ uint32_t : 6;
+ };
+ /* branch */
+ struct {
+ int32_t offset : 16;
+ uint32_t bfunct : 5;
+ uint32_t : 11;
+ };
+} __attribute__((packed));
+
+/// grammer syntax:
+///
+/// ... the grammer takes entries parsed from the instruction,
+/// and updates the instructions with values based on the type
+/// of entry. i.e. immd would require a immd in the next argument,
+/// and update the low 16bits of the instruction.
+///
+/// GRAMMER -> ENTRIES
+/// GRAMMER -> ε
+/// ENTRIES -> ENTRIES, ENTRY
+/// ENTRY -> rd // i.e. $at
+/// ENTRY -> rs
+/// ENTRY -> rt
+/// ENTRY -> immd // i.e. 0x80
+/// ENTRY -> offset // i.e. main (16bits)
+/// ENTRY -> offest(base) // i.e. 4($sp)
+/// ENTRY -> target // i.e. main (28bits shifted)
+///
+/// // grammer entries are always defined onto themselves... meaning the
+/// // name of their type directly corresponds to the mips field in the
+/// // instruction
+///
+/// pseudo grammer syntax:
+///
+/// ... psuedo entries represents what values should be placed where
+/// in each of the pseudo instructions. psuedo grammer is extended such
+/// that hardcoded values can be returned. i.e. setting rt=$at
+///
+/// GRAMMER -> ENTRIES
+/// GRAMMER -> ε
+/// ENTREIS -> ENTRIES, ENTRYSET
+/// ENTRYSET -> ENTRY | SET
+/// SET -> ENTRY = <REGISTER>
+/// ENTRY -> <GRAMMER: ENTRY> // i.e. any valid entry from grammer synax
+/// ENTRY -> hi // high 16bits of <target> into <immd>
+/// ENTRY -> lo // low 16bits of <target> into <immd>
+
+/* mips grammer */
+struct mips32_grammer {
+ // the name of the ins
+ char *name;
+ // the grammer of the ins
+ char *grammer;
+ // the index of the ins (if real)
+ int enum_index;
+
+ // for pseudo instructions only
+ int pseudo_len;
+ struct mips32__pseudo_grammer {
+ // what instruction is this
+ // part in the pseudo instruction
+ int enum_index;
+ // what parts of the instruction
+ // to update with values from
+ // grammer
+ char *update;
+
+ } pseudo_grammer[MAX_ARG_LENGTH];
+};
+
+#endif /* __MIPS32_H__ */