/* Copyright (c) 2024 Freya Murphy */ #ifndef __MIPS32_H__ #define __MIPS32_H__ #include #include #include /* 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, }; /* all mips fp registers $f0-$f31 */ enum mips32_fp_register { MIPS32_REG_F0 = 0, MIPS32_REG_F1 = 1, MIPS32_REG_F2 = 2, MIPS32_REG_F3 = 3, MIPS32_REG_F4 = 4, MIPS32_REG_F5 = 5, MIPS32_REG_F6 = 6, MIPS32_REG_F7 = 7, MIPS32_REG_F8 = 8, MIPS32_REG_F9 = 9, MIPS32_REG_F10 = 10, MIPS32_REG_F11 = 11, MIPS32_REG_F12 = 12, MIPS32_REG_F13 = 13, MIPS32_REG_F14 = 14, MIPS32_REG_F15 = 15, MIPS32_REG_F16 = 16, MIPS32_REG_F17 = 17, MIPS32_REG_F18 = 18, MIPS32_REG_F19 = 19, MIPS32_REG_F20 = 20, MIPS32_REG_F21 = 21, MIPS32_REG_F22 = 22, MIPS32_REG_F23 = 23, MIPS32_REG_F24 = 24, MIPS32_REG_F25 = 25, MIPS32_REG_F26 = 26, MIPS32_REG_F27 = 27, MIPS32_REG_F28 = 28, MIPS32_REG_F29 = 29, MIPS32_REG_F30 = 30, MIPS32_REG_F31 = 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; }; /* coprocessor */ struct { uint32_t : 21; uint32_t cfunct : 5; uint32_t : 6; }; /* flags */ struct { // 6 bit uint32_t : 5; uint32_t sc : 1; // interrupt // 5 bit uint32_t rv : 1; // rotate variable uint32_t : 3; uint32_t hb : 1; // hazard barrier // 5 bit uint32_t : 5; // 5 bit uint32_t tf : 1; // true false uint32_t nd : 1; // uint32_t cc : 3; // code // 5 bit uint32_t r : 1; // rotate uint32_t : 3; uint32_t c0 : 1; // cop0 // 6 bit uint32_t : 6; }; /* break code */ struct { uint32_t : 6; uint32_t code : 20; uint32_t : 6; }; /* floating point */ struct { uint32_t : 6; uint32_t fd : 5; uint32_t fs : 5; uint32_t ft : 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 = /// ENTRY -> // i.e. any valid entry from grammer synax /// ENTRY -> hi // high 16bits of into /// ENTRY -> lo // low 16bits of into /* 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__ */