summaryrefslogtreecommitdiff
path: root/instruction.h
blob: 4ee68ed6ec5b78b2a0f5f121c101c5697fb3c454 (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
#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)

#define INST_TYPE_RTYPE  0
#define INST_TYPE_NITYPE 1
#define INST_TYPE_WITYPE 2
#define INST_TYPE_JTYPE  3
#define INST_TYPE_SHAMT (14)
#define MASK_INST_TYPE(x) ((x) << INST_TYPE_SHAMT)
#define GET_INST_TYPE(x) (0x3 & ((x) >> INST_TYPE_SHAMT))

#define RTYPE_SIZE_BYTES  2 /* instruction fits in 16 bits */
#define NITYPE_SIZE_BYTES 2 /* instruction fits in 16 bits */
#define BTYPE_SIZE_BYTES  2 /* instruction fits in 16 bits */
#define JRTYPE_SIZE_BYTES 2 /* instruction fits in 16 bits */
#define WITYPE_SIZE_BYTES 4 /* 16-bit instruction + 16-bit immediate */
#define JITYPE_SIZE_BYTES 4 /* 16-bit instruction + 16-bit immediate */

/**
 * 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)
#define GET_OPER(x) (0x7 & ((x) >> OPER_SHAMT))

/**
 * 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 GET_JB_COND(x) (0x7 & ((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)
#define GET_JUMP_REG(x) (0x07 & ((x) >> 5))


/**
 * 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
};

/**
 * 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)
#define GET_REG_DEST(x) (0x7 & ((x) >> REG_DEST_OFFSET))

/* left reg: xxxxxxxx ___xxxxx */
#define REG_LEFT_OFFSET (5)
#define MASK_REG_LEFT(x) ((x) << REG_LEFT_OFFSET)
#define GET_REG_LEFT(x) (0x7 & ((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)
#define GET_REG_RIGHT(x) (0x7 & ((x) >> REG_RIGHT_OFFSET))

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

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

#endif /* INSTRUCTION_H */