/* Copyright (c) 2024 Freya Murphy */ #ifndef __MIPS32_H__ #define __MIPS32_H__ #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, }; /* mips instruction format */ enum mips32_instruction_format { MIPS32_FORMAT_R, MIPS32_FORMAT_I, MIPS32_FORMAT_J, MIPS32_FORMAT_B, }; /* mips instructions */ enum mips32_instruction_type { MIPS32_INS_ADD, MIPS32_INS_ADDI, MIPS32_INS_ADDIU, MIPS32_INS_ADDU, MIPS32_INS_AND, MIPS32_INS_ANDI, MIPS32_INS_BAL, MIPS32_INS_BALC, MIPS32_INS_BC, MIPS32_INS_BEQ, MIPS32_INS_BEQL, MIPS32_INS_BGEZ, MIPS32_INS_BGEZAL, MIPS32_INS_BGEZALL, MIPS32_INS_BGEZL, MIPS32_INS_BGTZ, MIPS32_INS_BGTZL, MIPS32_INS_BLEZ, MIPS32_INS_BLEZL, MIPS32_INS_BLTZ, MIPS32_INS_BLTZAL, MIPS32_INS_BLTZALL, MIPS32_INS_BLTZL, MIPS32_INS_BNE, MIPS32_INS_BNEL, MIPS32_INS_DDIV, MIPS32_INS_DDIVU, MIPS32_INS_DIV, MIPS32_INS_DIVU, MIPS32_INS_J, MIPS32_INS_JAL, MIPS32_INS_JALR, MIPS32_INS_JALX, MIPS32_INS_JR, MIPS32_INS_LB, MIPS32_INS_LBU, MIPS32_INS_LH, MIPS32_INS_LHU, MIPS32_INS_LUI, MIPS32_INS_LW, MIPS32_INS_LWL, MIPS32_INS_LWR, MIPS32_INS_MFHI, MIPS32_INS_MFLO, MIPS32_INS_MTHI, MIPS32_INS_MTLO, MIPS32_INS_MULT, MIPS32_INS_MULTU, MIPS32_INS_SB, MIPS32_INS_SH, MIPS32_INS_SW, MIPS32_INS_SWL, MIPS32_INS_SWR, MIPS32_INS_SLL, MIPS32_INS_SLLV, MIPS32_INS_SLT, MIPS32_INS_SLTI, MIPS32_INS_SLTIU, MIPS32_INS_SLTU, MIPS32_INS_SRA, MIPS32_INS_SRAV, MIPS32_INS_SRL, MIPS32_INS_SRLV, MIPS32_INS_SUB, MIPS32_INS_SUBU, MIPS32_INS_SYSCALL, MIPS32_INS_OR, MIPS32_INS_ORI, MIPS32_INS_NOR, MIPS32_INS_XOR, MIPS32_INS_XORI, // gets the size of the enum __MIPS32_INS_LEN, }; /* mips instruction R TYPE */ struct mips32_instruction_r_data { uint32_t funct : 6; uint32_t shamt : 5; uint32_t rd : 5; uint32_t rt : 5; uint32_t rs : 5; uint32_t op : 6; } __attribute__((packed)); /* mips instruction I TYPE */ struct mips32_instruction_i_data { uint32_t immd : 16; uint32_t rt : 5; uint32_t rs : 5; uint32_t op : 6; } __attribute__((packed)); /* mips instruction J TYPE */ struct mips32_instruction_j_data { uint32_t target : 26; uint32_t op : 6; } __attribute__((packed)); /* mips instruction BRANCH TYPE */ struct mips32_instruction_branch_data { int32_t offset : 16; uint32_t funct : 5; uint32_t rs : 5; uint32_t op : 6; } __attribute__((packed)); /* mips instruction information */ struct mips32_instruction { // metadata enum mips32_instruction_type type; enum mips32_instruction_format format; const char *name; // data union { uint32_t data; struct mips32_instruction_r_data R_data; struct mips32_instruction_i_data I_data; struct mips32_instruction_j_data J_data; struct mips32_instruction_branch_data B_data; } __attribute__((packed)); }; #define MIPS32_INS(ins, format, ...) \ [MIPS32_INS_ ##ins] = { \ MIPS32_INS_ ##ins, \ MIPS32_FORMAT_ ##format, \ #ins, \ .format##_data = { __VA_ARGS__ } \ }, \ static const struct mips32_instruction mips32_instructions[] = { /* ADD - add */ #define MIPS32_OP_SPECIAL 0b000000 #define MIPS32_FUNCT_ADD 0b100000 MIPS32_INS(ADD, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_ADD) /* ADDI - add immediate */ #define MIPS32_OP_ADDI 0b001000 MIPS32_INS(ADDI, I, .op = MIPS32_OP_ADDI) /* ADDIU - add immediate unsigned */ #define MIPS32_OP_ADDIU 0b001001 MIPS32_INS(ADDIU, I, .op = MIPS32_OP_ADDIU) /* ADDU - add unsigned */ #define MIPS32_FUNCT_ADDU 0b100001 MIPS32_INS(ADDU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_ADDU) /* AND - and */ #define MIPS32_FUNCT_AND 0b100100 MIPS32_INS(AND, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_AND) /* ANDI - and immediate */ #define MIPS32_OP_ANDI 0b001100 MIPS32_INS(ANDI, I, .op = MIPS32_OP_ANDI) /* BAL - branch and link */ #define MIPS32_OP_REGIMM 0b000001 #define MIPS32_FUNCT_BAL 0b10001 MIPS32_INS(BAL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BAL) /* BALC - branch and link, compact */ #define MIPS32_OP_BALC 0b111010 MIPS32_INS(BALC, J, .op = MIPS32_OP_BALC) /* BC - branch, compact */ #define MIPS32_OP_BC 0b110010 MIPS32_INS(BC, J, .op = MIPS32_OP_BC) /* BEQ - branch on equal */ #define MIPS32_OP_BEQ 0b000100 MIPS32_INS(BEQ, I, .op = MIPS32_OP_BEQ) /* BEQL - branch on equal likely */ #define MIPS32_OP_BEQL 0b010100 MIPS32_INS(BEQL, I, .op = MIPS32_OP_BEQL) /* BGEZ - branch on greater than or equal to zero */ #define MIPS32_FUNCT_BGEZ 0b00001 MIPS32_INS(BGEZ, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BGEZ) /* BGEZAL - branch on greater than or equal to zero and link */ #define MIPS32_FUNCT_BGEZAL 0b10001 MIPS32_INS(BGEZAL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BGEZAL) /* BGEZAL - branch on greater than or equal to zero and link likely */ #define MIPS32_FUNCT_BGEZALL 0b10011 MIPS32_INS(BGEZALL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BGEZALL) /* BGEZL - branch on greater than or equal to zero likely */ #define MIPS32_FUNCT_BGEZL 0b00011 MIPS32_INS(BGEZL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BGEZL) /* BGTZ - branch on greater than zero */ #define MIPS32_OP_BGTZ 0b000111 MIPS32_INS(BGTZ, I, .op = MIPS32_OP_BGTZ) /* BGTZL - branch on greater than zero likely */ #define MIPS32_OP_BGTZL 0b010111 MIPS32_INS(BGTZL, I, .op = MIPS32_OP_BGTZL) /* BLEZ - branch on less than or equal to zero */ #define MIPS32_OP_BLEZ 0b000110 MIPS32_INS(BLEZ, I, .op = MIPS32_OP_BLEZ) /* BLEZL - branch on less than or equal to zero likely */ #define MIPS32_OP_BLEZL 0b010110 MIPS32_INS(BLEZL, I, .op = MIPS32_OP_BLEZL) /* BLTZ - branch on less than zero */ #define MIPS32_FUNCT_BLTZ 0b00000 MIPS32_INS(BLTZ, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BLTZ) /* BLTZAL - branch on less than zero and link */ #define MIPS32_FUNCT_BLTZAL 0b10000 MIPS32_INS(BLTZAL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BLTZAL) /* BLTZALL - branch on less than zero and link likely */ #define MIPS32_FUNCT_BLTZALL 0b10010 MIPS32_INS(BLTZALL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BLTZALL) /* BLTZL - branch on less than zero likely */ #define MIPS32_FUNCT_BLTZL 0b00010 MIPS32_INS(BLTZL, B, .op = MIPS32_OP_REGIMM, .funct = MIPS32_FUNCT_BLTZL) /* BNE - branch on not equal */ #define MIPS32_OP_BNE 0b000101 MIPS32_INS(BNE, I, .op = MIPS32_OP_BNE) /* BNEL - branch on not equal likely */ #define MIPS32_OP_BNEL 0b010101 MIPS32_INS(BNEL, I, .op = MIPS32_OP_BNEL) /* DDIV - doubleword divide */ #define MIPS32_FUNCT_DDIV 0b011110 MIPS32_INS(DDIV, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_DDIV) /* DDIVU - doubleword divide unsigned */ #define MIPS32_FUNCT_DDIVU 0b011111 MIPS32_INS(DDIVU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_DDIVU) /* DIV - divide */ #define MIPS32_FUNCT_DIV 0b011010 MIPS32_INS(DIV, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_DIV) /* DIVU - divide unsigned */ #define MIPS32_FUNCT_DIVU 0b011011 MIPS32_INS(DIVU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_DIVU) /* J - jump */ #define MIPS32_OP_J 0b000010 MIPS32_INS(J, J, .op = MIPS32_OP_J) /* JAL - jump and link */ #define MIPS32_OP_JAL 0b000011 MIPS32_INS(JAL, J, .op = MIPS32_OP_JAL) /* JALR - jump and link register */ #define MIPS32_FUNCT_JALR 0b001001 MIPS32_INS(JALR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_JALR) /* JALX - jump and link exchange */ #define MIPS32_OP_JALX 0b011101 MIPS32_INS(JALX, J, .op = MIPS32_OP_JALX) /* JR - jump register */ #define MIPS32_FUNCT_JR 0b001000 MIPS32_INS(JR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_JR) /* LB - load byte */ #define MIPS32_OP_LB 0b100000 MIPS32_INS(LB, I, .op = MIPS32_OP_LB) /* LBU - load byte unsigned */ #define MIPS32_OP_LBU 0b100100 MIPS32_INS(LBU, I, .op = MIPS32_OP_LBU) /* LH - load half */ #define MIPS32_OP_LH 0b100001 MIPS32_INS(LH, I, .op = MIPS32_OP_LH) /* LHU - load half unsigned */ #define MIPS32_OP_LHU 0b100101 MIPS32_INS(LHU, I, .op = MIPS32_OP_LHU) /* LUI - load upper immediate */ #define MIPS32_OP_LUI 0b001111 MIPS32_INS(LUI, I, .op = MIPS32_OP_LUI) /* LW - load word */ #define MIPS32_OP_LW 0b100011 MIPS32_INS(LW, I, .op = MIPS32_OP_LW) /* LWL - load word left */ #define MIPS32_OP_LWL 0b100010 MIPS32_INS(LWL, I, .op = MIPS32_OP_LWL) /* LWR - load word right */ #define MIPS32_OP_LWR 0b100110 MIPS32_INS(LWR, I, .op = MIPS32_OP_LWR) /* MFHI - move from hi */ #define MIPS32_FUNCT_MFHI 0b010000 MIPS32_INS(MFHI, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MFHI) /* MFLO - move from hi */ #define MIPS32_FUNCT_MFLO 0b010010 MIPS32_INS(MFLO, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MFLO) /* MTHI - move from hi */ #define MIPS32_FUNCT_MTHI 0b010001 MIPS32_INS(MTHI, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MTHI) /* MTLO - move from hi */ #define MIPS32_FUNCT_MTLO 0b010011 MIPS32_INS(MTLO, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MTLO) /* MULT - multiply */ #define MIPS32_FUNCT_MULT 0b011000 MIPS32_INS(MULT, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MULT) /* MULTU - multiply unsigned */ #define MIPS32_FUNCT_MULTU 0b011001 MIPS32_INS(MULTU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_MULTU) /* SB - store byte */ #define MIPS32_OP_SB 0b101000 MIPS32_INS(SB, I, .op = MIPS32_OP_SB) /* SH - store half */ #define MIPS32_OP_SH 0b101001 MIPS32_INS(SH, I, .op = MIPS32_OP_SH) /* SW - store word */ #define MIPS32_OP_SW 0b101011 MIPS32_INS(SW, I, .op = MIPS32_OP_SW) /* SWL - store word left */ #define MIPS32_OP_SWL 0b101010 MIPS32_INS(SWL, I, .op = MIPS32_OP_SWL) /* SWR - store word right */ #define MIPS32_OP_SWR 0b101110 MIPS32_INS(SWR, I, .op = MIPS32_OP_SWR) /* SLL - shift left logical */ #define MIPS32_FUNCT_SLL 0b000000 MIPS32_INS(SLL, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SLL) /* SLLV - shift left logical variable */ #define MIPS32_FUNCT_SLLV 0b000100 MIPS32_INS(SLLV, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SLLV) /* SLT - set less then */ #define MIPS32_FUNCT_SLT 0b101010 MIPS32_INS(SLT, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SLT) /* SLTI - set less then immediate */ #define MIPS32_OP_SLTI 0b001010 MIPS32_INS(SLTI, I, .op = MIPS32_OP_SLTI) /* SLTIU - set less then imemdiate unsigned */ #define MIPS32_OP_SLTIU 0b001011 MIPS32_INS(SLTIU, I, .op = MIPS32_OP_SLTIU) /* SLTU - set less than unsigned */ #define MIPS32_FUNCT_SLTU 0b101011 MIPS32_INS(SLTU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SLTU) /* SRA - shift right arithmetic */ #define MIPS32_FUNCT_SRA 0b000011 MIPS32_INS(SRA, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SRA) /* SRAV - shift right arithmetic variable */ #define MIPS32_FUNCT_SRAV 0b000111 MIPS32_INS(SRAV, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SRAV) /* SRL - shift right logical */ #define MIPS32_FUNCT_SRL 0b000010 MIPS32_INS(SRL, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SRL) /* SRLV - shift right logical variable */ #define MIPS32_FUNCT_SRLV 0b000110 MIPS32_INS(SRLV, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SRLV) /* SUB - subtract */ #define MIPS32_FUNCT_SUB 0b100010 MIPS32_INS(SUB, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SUB) /* SUBU - subtract unsigned */ #define MIPS32_FUNCT_SUBU 0b100011 MIPS32_INS(SUBU, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SUBU) /* SYSCALL - syscall */ #define MIPS32_FUNCT_SYSCALL 0b001100 MIPS32_INS(SYSCALL, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_SYSCALL) /* OR - or */ #define MIPS32_FUNCT_OR 0b100101 MIPS32_INS(OR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_OR) /* ORI - or imemdiate */ #define MIPS32_OP_ORI 0b001101 MIPS32_INS(ORI, I, .op = MIPS32_OP_ORI) /* NOR - not or */ #define MIPS32_FUNCT_NOR 0b100111 MIPS32_INS(NOR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_NOR) /* XOR - exclusive or */ #define MIPS32_FUNCT_XOR 0b100110 MIPS32_INS(XOR, R, .op = MIPS32_OP_SPECIAL, .funct = MIPS32_FUNCT_XOR) /* XORI - exclusive or immediate */ #define MIPS32_OP_XORI 0b001110 MIPS32_INS(XORI, I, .op = MIPS32_OP_XORI) }; #undef MIPS32_INS /* mips32 directive types */ enum mips32_directive_type { MIPS32_DIRECTIVE_ALIGN, MIPS32_DIRECTIVE_SPACE, MIPS32_DIRECTIVE_WORD, MIPS32_DIRECTIVE_HALF, MIPS32_DIRECTIVE_BYTE, MIPS32_DIRECTIVE_SECTION, MIPS32_DIRECTIVE_EXTERN, MIPS32_DIRECTIVE_GLOBL, }; /* mip32 directive */ struct mips32_directive { enum mips32_directive_type type; uint32_t len; // used for words, halfs, bytes union { uint16_t align; uint16_t space; uint32_t words[MAX_ARG_LENGTH]; uint16_t halfs[MAX_ARG_LENGTH]; uint8_t bytes[MAX_ARG_LENGTH]; char name[MAX_ARG_LENGTH]; }; }; #endif /* __MIPS32_H__ */