diff options
author | Freya Murphy <freya@freyacat.org> | 2024-09-09 12:41:49 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-09-09 12:41:49 -0400 |
commit | 2ed275821676a0d5baea6c7fd843d71c72c2342c (patch) | |
tree | 480297f28e5c42d02a47b3b94027a7abe507d010 /include/mips32.h | |
download | mips-2ed275821676a0d5baea6c7fd843d71c72c2342c.tar.gz mips-2ed275821676a0d5baea6c7fd843d71c72c2342c.tar.bz2 mips-2ed275821676a0d5baea6c7fd843d71c72c2342c.zip |
initial mips32 (r2000ish mips32r6) assembler
Diffstat (limited to 'include/mips32.h')
-rw-r--r-- | include/mips32.h | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/include/mips32.h b/include/mips32.h new file mode 100644 index 0000000..ce0e997 --- /dev/null +++ b/include/mips32.h @@ -0,0 +1,496 @@ +/* Copyright (c) 2024 Freya Murphy */ + +#ifndef __MIPS32_H__ +#define __MIPS32_H__ + +#include <mlimits.h> +#include <stdint.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 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_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) + +/* 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, +}; + +/* mip32 directive */ +struct mips32_directive { + enum mips32_directive_type type; + 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__ */ |