mips/include/mips32.h

143 lines
3.4 KiB
C
Raw 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,
};
/* 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__ */