summaryrefslogtreecommitdiff
path: root/include/mips.h
blob: b63d631781daf109dd4b60d1e242fb5c5a6ac8ff (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
/* Copyright (c) 2024 Freya Murphy */

#ifndef __MIPS_H__
#define __MIPS_H__

#include <mlimits.h>
#include <stdint.h>

/* all mips registers $0-$31 */
enum mips_register {
	MIPS_REG_ZERO =  0,
	MIPS_REG_AT   =  1,
	MIPS_REG_V0   =  2,
	MIPS_REG_V1   =  3,
	MIPS_REG_A0   =  4,
	MIPS_REG_A1   =  5,
	MIPS_REG_A2   =  6,
	MIPS_REG_A3   =  7,
	MIPS_REG_T0   =  8,
	MIPS_REG_T1   =  9,
	MIPS_REG_T2   = 10,
	MIPS_REG_T3   = 11,
	MIPS_REG_T4   = 12,
	MIPS_REG_T5   = 13,
	MIPS_REG_T6   = 14,
	MIPS_REG_T7   = 15,
	MIPS_REG_S0   = 16,
	MIPS_REG_S1   = 17,
	MIPS_REG_S2   = 18,
	MIPS_REG_S3   = 19,
	MIPS_REG_S4   = 20,
	MIPS_REG_S5   = 21,
	MIPS_REG_S6   = 22,
	MIPS_REG_S7   = 23,
	MIPS_REG_T8   = 24,
	MIPS_REG_T9   = 25,
	MIPS_REG_K0   = 26,
	MIPS_REG_K1   = 27,
	MIPS_REG_GP   = 28,
	MIPS_REG_SP   = 29,
	MIPS_REG_FP   = 30,
	MIPS_REG_RA   = 31,
};

/* mips instructions */
enum mips_instruction_type {
	MIPS_INS_ADD,
	MIPS_INS_ADDI,
	MIPS_INS_ADDIU,
	MIPS_INS_ADDU,
	MIPS_INS_AND,
	MIPS_INS_ANDI,
	MIPS_INS_BAL,
	MIPS_INS_BALC,
	MIPS_INS_BC,
	MIPS_INS_BEQ,
	MIPS_INS_BEQL,
	MIPS_INS_BGEZ,
	MIPS_INS_BGEZAL,
	MIPS_INS_BGEZALL,
	MIPS_INS_BGEZL,
	MIPS_INS_BGTZ,
	MIPS_INS_BGTZL,
	MIPS_INS_BLEZ,
	MIPS_INS_BLEZL,
	MIPS_INS_BLTZ,
	MIPS_INS_BLTZAL,
	MIPS_INS_BLTZALL,
	MIPS_INS_BLTZL,
	MIPS_INS_BNE,
	MIPS_INS_BNEL,
	MIPS_INS_DIV,
	MIPS_INS_MOD,
	MIPS_INS_DIVU,
	MIPS_INS_MODU,
	MIPS_INS_J,
	MIPS_INS_JAL,
	MIPS_INS_JALR,
	MIPS_INS_JALX,
	MIPS_INS_JR,
	MIPS_INS_LB,
	MIPS_INS_LBU,
	MIPS_INS_LH,
	MIPS_INS_LHU,
	MIPS_INS_LUI,
	MIPS_INS_LW,
	MIPS_INS_LWL,
	MIPS_INS_LWR,
	MIPS_INS_MFHI,
	MIPS_INS_MFLO,
	MIPS_INS_MTHI,
	MIPS_INS_MTLO,
	MIPS_INS_MUL,
	MIPS_INS_MUH,
	MIPS_INS_MULU,
	MIPS_INS_MUHU,
	MIPS_INS_MULT,
	MIPS_INS_SB,
	MIPS_INS_SH,
	MIPS_INS_SW,
	MIPS_INS_SWL,
	MIPS_INS_SWR,
	MIPS_INS_SLL,
	MIPS_INS_SLLV,
	MIPS_INS_SLT,
	MIPS_INS_SLTI,
	MIPS_INS_SLTIU,
	MIPS_INS_SLTU,
	MIPS_INS_SRA,
	MIPS_INS_SRAV,
	MIPS_INS_SRL,
	MIPS_INS_SRLV,
	MIPS_INS_SUB,
	MIPS_INS_SUBU,
	MIPS_INS_SYSCALL,
	MIPS_INS_OR,
	MIPS_INS_ORI,
	MIPS_INS_NOR,
	MIPS_INS_XOR,
	MIPS_INS_XORI,
	// gets the size of the enum
	__MIPS_INS_LEN,
};

union mips_instruction_data {
	/* 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));

/* mips instruction information */
struct mips_instruction {
	// metadata
	enum mips_instruction_type type;
	const char *name;

	// data
	union mips_instruction_data data;
};

#define MIPS_INS(ins, ...) \
	[MIPS_INS_ ##ins] = { \
		MIPS_INS_ ##ins, \
		#ins, \
		.data = { __VA_ARGS__ } \
	}, \

static const struct mips_instruction mips_instructions[] = {
/* ADD - add */
#define MIPS_OP_SPECIAL    0b000000
#define MIPS_FUNCT_ADD     0b100000
MIPS_INS(ADD, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_ADD)

/* ADDI - add immediate */
#define MIPS_OP_ADDI       0b001000
MIPS_INS(ADDI, .op = MIPS_OP_ADDI)

/* ADDIU - add immediate unsigned */
#define MIPS_OP_ADDIU      0b001001
MIPS_INS(ADDIU, .op = MIPS_OP_ADDIU)

/* ADDU - add unsigned */
#define MIPS_FUNCT_ADDU    0b100001
MIPS_INS(ADDU, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_ADDU)

/* AND - and */
#define MIPS_FUNCT_AND     0b100100
MIPS_INS(AND, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_AND)

/* ANDI - and immediate */
#define MIPS_OP_ANDI       0b001100
MIPS_INS(ANDI, .op = MIPS_OP_ANDI)

/* BAL - branch and link */
#define MIPS_OP_REGIMM     0b000001
#define MIPS_FUNCT_BAL     0b10001
MIPS_INS(BAL, .op = MIPS_OP_REGIMM, .funct = MIPS_FUNCT_BAL)

/* BALC - branch and link, compact */
#define MIPS_OP_BALC       0b111010
MIPS_INS(BALC, .op = MIPS_OP_BALC)

/* BC - branch, compact */
#define MIPS_OP_BC         0b110010
MIPS_INS(BC, .op = MIPS_OP_BC)

/* BEQ - branch on equal */
#define MIPS_OP_BEQ        0b000100
MIPS_INS(BEQ, .op = MIPS_OP_BEQ)

/* BEQL - branch on equal likely */
#define MIPS_OP_BEQL       0b010100
MIPS_INS(BEQL, .op = MIPS_OP_BEQL)

/* BGEZ - branch on greater than or equal to zero */
#define MIPS_FUNCT_BGEZ    0b00001
MIPS_INS(BGEZ, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BGEZ)

/* BGEZAL - branch on greater than or equal to zero and link */
#define MIPS_FUNCT_BGEZAL  0b10001
MIPS_INS(BGEZAL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BGEZAL)

/* BGEZAL - branch on greater than or equal to zero and link likely */
#define MIPS_FUNCT_BGEZALL 0b10011
MIPS_INS(BGEZALL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BGEZALL)

/* BGEZL - branch on greater than or equal to zero likely */
#define MIPS_FUNCT_BGEZL   0b00011
MIPS_INS(BGEZL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BGEZL)

/* BGTZ - branch on greater than zero */
#define MIPS_OP_BGTZ       0b000111
MIPS_INS(BGTZ, .op = MIPS_OP_BGTZ)

/* BGTZL - branch on greater than zero likely */
#define MIPS_OP_BGTZL      0b010111
MIPS_INS(BGTZL, .op = MIPS_OP_BGTZL)

/* BLEZ - branch on less than or equal to zero */
#define MIPS_OP_BLEZ       0b000110
MIPS_INS(BLEZ, .op = MIPS_OP_BLEZ)

/* BLEZL - branch on less than or equal to zero likely */
#define MIPS_OP_BLEZL      0b010110
MIPS_INS(BLEZL, .op = MIPS_OP_BLEZL)

/* BLTZ - branch on less than zero */
#define MIPS_FUNCT_BLTZ    0b00000
MIPS_INS(BLTZ, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BLTZ)

/* BLTZAL - branch on less than zero and link */
#define MIPS_FUNCT_BLTZAL  0b10000
MIPS_INS(BLTZAL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BLTZAL)

/* BLTZALL - branch on less than zero and link likely */
#define MIPS_FUNCT_BLTZALL 0b10010
MIPS_INS(BLTZALL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BLTZALL)

/* BLTZL - branch on less than zero likely */
#define MIPS_FUNCT_BLTZL   0b00010
MIPS_INS(BLTZL, .op = MIPS_OP_REGIMM, .bfunct = MIPS_FUNCT_BLTZL)

/* BNE - branch on not equal */
#define MIPS_OP_BNE        0b000101
MIPS_INS(BNE, .op = MIPS_OP_BNE)

/* BNEL - branch on not equal likely */
#define MIPS_OP_BNEL       0b010101
MIPS_INS(BNEL, .op = MIPS_OP_BNEL)

/* DIV - divide */
#define MIPS_FUNCT_SOP32   0b011010
#define MIPS_SOP32_DIV     0b00010
MIPS_INS(DIV, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP32_DIV,
	 .funct = MIPS_FUNCT_SOP32)

/* MOD - modulo */
#define MIPS_SOP32_MOD     0b00011
MIPS_INS(MOD, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP32_MOD,
	 .funct = MIPS_FUNCT_SOP32)

/* DIVU - divide unsigned */
#define MIPS_FUNCT_SOP33   0b011011
#define MIPS_SOP33_DIVU    0b00010
MIPS_INS(DIVU, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP33_DIVU,
	 .funct = MIPS_FUNCT_SOP33)

/* MODU - modulo unsigned */
#define MIPS_SOP33_MODU    0b00011
MIPS_INS(MODU, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP33_MODU,
	 .funct = MIPS_FUNCT_SOP33)

/* J - jump */
#define MIPS_OP_J          0b000010
MIPS_INS(J, .op = MIPS_OP_J)

/* JAL - jump and link */
#define MIPS_OP_JAL        0b000011
MIPS_INS(JAL, .op = MIPS_OP_JAL)

/* JALR - jump and link register */
#define MIPS_FUNCT_JALR    0b001001
MIPS_INS(JALR, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_JALR)

/* JALX - jump and link exchange */
#define MIPS_OP_JALX       0b011101
MIPS_INS(JALX, .op = MIPS_OP_JALX)

/* JR - jump register */
#define MIPS_FUNCT_JR      0b001000
MIPS_INS(JR, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_JR)

/* LB - load byte */
#define MIPS_OP_LB         0b100000
MIPS_INS(LB, .op = MIPS_OP_LB)

/* LBU - load byte unsigned */
#define MIPS_OP_LBU        0b100100
MIPS_INS(LBU, .op = MIPS_OP_LBU)

/* LH - load half */
#define MIPS_OP_LH         0b100001
MIPS_INS(LH, .op = MIPS_OP_LH)

/* LHU - load half unsigned */
#define MIPS_OP_LHU        0b100101
MIPS_INS(LHU, .op = MIPS_OP_LHU)

/* LUI - load upper immediate */
#define MIPS_OP_LUI        0b001111
MIPS_INS(LUI, .op = MIPS_OP_LUI)

/* LW - load word */
#define MIPS_OP_LW         0b100011
MIPS_INS(LW, .op = MIPS_OP_LW)

/* LWL - load word left */
#define MIPS_OP_LWL        0b100010
MIPS_INS(LWL, .op = MIPS_OP_LWL)

/* LWR - load word right */
#define MIPS_OP_LWR        0b100110
MIPS_INS(LWR, .op = MIPS_OP_LWR)

/* MFHI - move from hi */
#define MIPS_FUNCT_MFHI    0b010000
MIPS_INS(MFHI, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_MFHI)

/* MFLO - move from hi */
#define MIPS_FUNCT_MFLO    0b010010
MIPS_INS(MFLO, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_MFLO)

/* MTHI - move from hi */
#define MIPS_FUNCT_MTHI    0b010001
MIPS_INS(MTHI, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_MTHI)

/* MTLO - move from hi */
#define MIPS_FUNCT_MTLO    0b010011
MIPS_INS(MTLO, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_MTLO)

/* MUL - multiply low word */
#define MIPS_FUNCT_SOP30   0b011000
#define MIPS_SOP30_MUL     0b00010
MIPS_INS(MUL, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP30_MUL,
	 .funct = MIPS_FUNCT_SOP30)

/* MUH - multiply high word */
#define MIPS_SOP30_MUH     0b00011
MIPS_INS(MUH, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP30_MUH,
	 .funct = MIPS_FUNCT_SOP30)

/* MULU - multiply low word unsigned */
#define MIPS_FUNCT_SOP31   0b011001
#define MIPS_SOP31_MULU    0b00010
MIPS_INS(MULU, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP31_MULU,
	 .funct = MIPS_FUNCT_SOP31)

/* MUHU - multiply high word unsgined */
#define MIPS_SOP31_MUHU    0b00011
MIPS_INS(MUHU, .op = MIPS_OP_SPECIAL, .shamt = MIPS_SOP31_MUHU,
	 .funct = MIPS_FUNCT_SOP31)

/* MULT - multiply (OLD) */
#define MIPS_FUNCT_MULT    0b011000
MIPS_INS(MULT, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_MULT)

/* SB - store byte */
#define MIPS_OP_SB         0b101000
MIPS_INS(SB, .op = MIPS_OP_SB)

/* SH - store half */
#define MIPS_OP_SH         0b101001
MIPS_INS(SH, .op = MIPS_OP_SH)

/* SW - store word */
#define MIPS_OP_SW         0b101011
MIPS_INS(SW, .op = MIPS_OP_SW)

/* SWL - store word left */
#define MIPS_OP_SWL        0b101010
MIPS_INS(SWL, .op = MIPS_OP_SWL)

/* SWR - store word right */
#define MIPS_OP_SWR        0b101110
MIPS_INS(SWR, .op = MIPS_OP_SWR)

/* SLL - shift left logical */
#define MIPS_FUNCT_SLL     0b000000
MIPS_INS(SLL, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SLL)

/* SLLV - shift left logical variable */
#define MIPS_FUNCT_SLLV    0b000100
MIPS_INS(SLLV, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SLLV)

/* SLT - set less then */
#define MIPS_FUNCT_SLT     0b101010
MIPS_INS(SLT, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SLT)

/* SLTI - set less then immediate */
#define MIPS_OP_SLTI       0b001010
MIPS_INS(SLTI, .op = MIPS_OP_SLTI)

/* SLTIU - set less then imemdiate unsigned */
#define MIPS_OP_SLTIU      0b001011
MIPS_INS(SLTIU, .op = MIPS_OP_SLTIU)

/* SLTU - set less than unsigned */
#define MIPS_FUNCT_SLTU    0b101011
MIPS_INS(SLTU, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SLTU)

/* SRA - shift right arithmetic */
#define MIPS_FUNCT_SRA     0b000011
MIPS_INS(SRA, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SRA)

/* SRAV - shift right arithmetic variable */
#define MIPS_FUNCT_SRAV    0b000111
MIPS_INS(SRAV, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SRAV)

/* SRL - shift right logical */
#define MIPS_FUNCT_SRL     0b000010
MIPS_INS(SRL, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SRL)

/* SRLV - shift right logical variable */
#define MIPS_FUNCT_SRLV    0b000110
MIPS_INS(SRLV, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SRLV)

/* SUB - subtract */
#define MIPS_FUNCT_SUB     0b100010
MIPS_INS(SUB, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SUB)

/* SUBU - subtract unsigned */
#define MIPS_FUNCT_SUBU    0b100011
MIPS_INS(SUBU, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SUBU)

/* SYSCALL - syscall */
#define MIPS_FUNCT_SYSCALL 0b001100
MIPS_INS(SYSCALL, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_SYSCALL)

/* OR - or */
#define MIPS_FUNCT_OR      0b100101
MIPS_INS(OR, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_OR)

/* ORI - or imemdiate */
#define MIPS_OP_ORI        0b001101
MIPS_INS(ORI, .op = MIPS_OP_ORI)

/* NOR - not or */
#define MIPS_FUNCT_NOR     0b100111
MIPS_INS(NOR, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_NOR)

/* XOR - exclusive or */
#define MIPS_FUNCT_XOR     0b100110
MIPS_INS(XOR, .op = MIPS_OP_SPECIAL, .funct = MIPS_FUNCT_XOR)

/* XORI - exclusive or immediate */
#define MIPS_OP_XORI       0b001110
MIPS_INS(XORI, .op = MIPS_OP_XORI)
};

#undef MIPS_INS

#endif /* __MIPS_H__ */