summaryrefslogtreecommitdiff
path: root/instruction.h
blob: 3ee18d99dba66db0545b77480fe49f0f285d8374 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef INSTRUCTION_H
#define INSTRUCTION_H

/**
 * Values used for software-only identification instruction types. Values not
 * tied to machine language. Guaranteed unique.
 */
enum INST_TYPE {
	INST_TYPE_R,
	INST_TYPE_NI,
	INST_TYPE_WI,
	INST_TYPE_JR,
	INST_TYPE_JI,
	INST_TYPE_B
};

/**
 * Masks for all four instruction types. Not guaranteed unique
 */
#define MASK_INST_RTYPE  (0x0000)
#define MASK_INST_NITYPE (0x4000)
#define MASK_INST_WITYPE (0x8000)
#define MASK_INST_JTYPE  (0xC000)

/**
 * ALU operation types
 * R-type and I-type take 3-bit ALU oper as bits:
 * xx___xxx xxxxxxxx
 */
enum OPER {
	OPER_ADD = 0,
	OPER_SUB = 1,
	OPER_SHL = 2,
	OPER_SHR = 3,
	OPER_AND = 4,
	OPER_OR  = 5,
	OPER_XOR = 6,
	OPER_MUL = 7,
};
#define OPER_SHAMT (11)
#define MASK_OPER(x) ((x) << OPER_SHAMT)

static const char *oper_to_human[] = {
	[OPER_ADD] = "add",
	[OPER_SUB] = "sub",
	[OPER_SHL] = "shl",
	[OPER_SHR] = "shr",
	[OPER_AND] = "and",
	[OPER_OR ] = "or",
	[OPER_XOR] = "xor",
	[OPER_MUL] = "mul"
};

/**
 * Masks for jump and branch conditions
 * J-type instructions (jump, branch) take these as follows:
 * xxx___xx xxxxxxxx
 */
enum JCOND {
	JB_UNCOND  = 0x0,
	JB_NEVER   = 0x1,
	JB_ZERO    = 0x2,
	JB_NZERO   = 0x3,
	JB_CARRY   = 0x4,
	JB_NCARRY  = 0x5,
	JB_CARRYZ  = 0x6,
	JB_NCARRYZ = 0x7
};
#define JB_SHAMT   (10)
#define MASK_JB_COND(x) ((x) << JB_SHAMT)
#define MASK_IS_JUMP   (0 << 13)
#define MASK_IS_BRANCH (1 << 13)
#define MASK_JI (0x0 << 8)
#define MASK_JR (0x1 << 8)
#define MASK_JUMP_REGISTER(x) ((x) << 5)

static const char *j_to_human[] = {
	[JB_UNCOND]  = "jmp",
	[JB_NEVER]   = "jn",
	[JB_ZERO]    = "jz",
	[JB_NZERO]   = "jnz",
	[JB_CARRY]   = "jc",
	[JB_NCARRY]  = "jnc",
	[JB_CARRYZ]  = "jcz",
	[JB_NCARRYZ] = "jncz"
};
static const char *b_to_human[] = {
	[JB_UNCOND]  = "bra",
	[JB_NEVER]   = "bn",
	[JB_ZERO]    = "bz",
	[JB_NZERO]   = "bnz",
	[JB_CARRY]   = "bc",
	[JB_NCARRY]  = "bnc",
	[JB_CARRYZ]  = "bcz",
	[JB_NCARRYZ] = "bncz"
};

/**
 * Register numbers used in all manner of instructions in varying positions
 */
enum REG {
	REG_0 = 0,
	REG_1 = 1,
	REG_2 = 2,
	REG_3 = 3,
	REG_4 = 4,
	REG_5 = 5,
	REG_6 = 6,
	REG_H = 7
};

static const char *reg_to_human[] = {
	[REG_0] = "$0",
	[REG_1] = "$1",
	[REG_2] = "$2",
	[REG_3] = "$3",
	[REG_4] = "$4",
	[REG_5] = "$5",
	[REG_6] = "$6",
	[REG_H] = "$H",
};

/**
 * Offset macro to turn REG_* into mask for register operands of R-type and
 * I-type instructions
 */
/* destination reg: xxxxx___ xxxxxxxx */
#define REG_DEST_OFFSET (8)
#define MASK_REG_DEST(x) ((x) << REG_DEST_OFFSET)

/* left reg: xxxxxxxx ___xxxxx */
#define REG_LEFT_OFFSET (5)
#define MASK_REG_LEFT(x) ((x) << REG_LEFT_OFFSET)

/* right reg (R-type only): xxxxxxxx xxx___xx */
#define REG_RIGHT_OFFSET (2)
#define MASK_REG_RIGHT(x) ((x) << REG_RIGHT_OFFSET)

/* five LSb are narrow immediate value */
#define MASK_NI_IMM(x) ((x) & 0x1F)

/* 10 LSb is branch offset */
#define MASK_B_OFFSET(x) ((x) & 0x3FF)

#endif /* INSTRUCTION_H */