mips/include/mips.h

221 lines
5 KiB
C
Raw Permalink Normal View History

2024-10-04 23:41:10 +00:00
/* 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,
};
2024-10-09 16:08:58 +00:00
/* 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,
};
2024-10-04 23:41:10 +00:00
/* 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;
};
2024-10-09 16:08:58 +00:00
/* 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;
};
2024-10-04 23:41:10 +00:00
} __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__ */