Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  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
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
/* $NetBSD: insn.h,v 1.4 2021/04/19 07:55:59 dholland Exp $ */

/*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Matt Thomas of 3am Software Foundry.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _RISCV_INSN_H_
#define _RISCV_INSN_H_

/*
 * I have corrected and updated this, but it's the wrong way to do it.
 * It's still used by ddb_machdep.c but that code should be fixed to
 * use the newer stuff below. - dholland
 */
union riscv_insn {
	uint32_t val;
	/* register ops */
	struct {
		unsigned int r_opcode : 7;
		unsigned int r_rd : 5;
		unsigned int r_funct3 : 3;
		unsigned int r_rs1 : 5;
		unsigned int r_rs2 : 5;
		unsigned int r_funct7 : 7;
	} type_r;
	/* 32-bit shifts */
	struct {
		unsigned int rs32_opcode : 7;
		unsigned int rs32_rd : 5;
		unsigned int rs32_funct3 : 3;
		unsigned int rs32_rs1 : 5;
		unsigned int rs32_shamt : 5;
		unsigned int rs32_funct7 : 7;
	} type_rs32;
	/* 64-bit shifts */
	struct {
		unsigned int rs64_opcode : 7;
		unsigned int rs64_rd : 5;
		unsigned int rs64_funct3 : 3;
		unsigned int rs64_rs1 : 5;
		unsigned int rs64_shamt : 6;
		unsigned int rs64_zero : 1;
		unsigned int rs64_funct5 : 5;
	} type_rs64;
	/* atomics */
	struct {
		unsigned int ra_opcode : 7;
		unsigned int ra_rd : 5;
		unsigned int ra_funct3 : 3;
		unsigned int ra_rs1 : 5;
		unsigned int ra_rs2 : 5;
		unsigned int ra_rl : 1;
		unsigned int ra_aq : 1;
		unsigned int ra_funct5 : 5;
	} type_ra;
	/* certain fpu ops */
	struct {
		unsigned int rf_opcode : 7;
		unsigned int rf_rd : 5;
		unsigned int rf_rm : 3;
		unsigned int rf_rs1 : 5;
		unsigned int rf_rs2 : 5;
		unsigned int rf_size : 2;
		unsigned int rf_funct5 : 5;
	} type_rf;
	/* other fpu ops */
	struct {
		unsigned int rf4_opcode : 7;
		unsigned int rf4_rd : 5;
		unsigned int rf4_rm : 3;
		unsigned int rf4_rs1 : 5;
		unsigned int rf4_rs2 : 5;
		unsigned int rf4_size : 2;
		unsigned int rf4_rs3 : 5;
	} type_rf4;
	/* immediates */
	struct {
		unsigned int i_opcode : 7;
		unsigned int i_rd : 5;
		unsigned int i_funct3 : 3;
		unsigned int i_rs1 : 5;
		signed int i_imm11to0 : 12;
	} type_i;
	/* stores */
	struct {
		unsigned int s_opcode : 7;
		unsigned int s_imm4_to_0 : 5;
		unsigned int s_funct3 : 3;
		unsigned int s_rs1 : 5;
		unsigned int s_rs2 : 5;
		signed int s_imm11_to_5 : 7;
	} type_s;
	/* branches */
	struct {
		unsigned int b_opcode : 7;
		unsigned int b_imm11 : 1;
		unsigned int b_imm4to1 : 4;
		unsigned int b_funct3 : 3;
		unsigned int b_rs1 : 5;
		unsigned int b_rs2 : 5;
		unsigned int b_imm10to5 : 6;
		signed int b_imm12 : 1;
	} type_b;
	/* large immediate constants */
	struct {
		unsigned int u_opcode : 7;
		unsigned int u_rd : 5;
		signed int u_imm31to12 : 20;
	} type_u;
	/* large immediate jumps */
	struct {
		unsigned int j_opcode : 7;
		unsigned int j_rd : 5;
		unsigned int j_imm19to12 : 9;
		unsigned int j_imm11 : 1;
		unsigned int j_imm10to1 : 9;
		signed int j_imm20 : 1;
	} type_j;
};

/*
 * old macro still in use with the above
 * (XXX, doesn't handle 16-bit instructions)
 */

#define OPCODE_P(i, x)		(((i) & 0b1111111) == ((OPCODE_##x<<2)|0b11))

////////////////////////////////////////////////////////////

/*
 * Instruction size
 */

/* cumulative size tests */
#define INSN_SIZE_IS_16(insn) (((insn) & 0b11) != 0b11)
#define INSN_SIZE_IS_32(insn) (((insn) & 0b11100) != 0b11100)
#define INSN_SIZE_IS_48(insn) (((insn) & 0b100000) != 0b100000)
#define INSN_SIZE_IS_64(insn) (((insn) & 0b1000000) != 0b1000000)

/* returns 1-5 for the number of uint16s */
#define INSN_HALFWORDS(insn) \
	(INSN_SIZE_IS_16(insn) ? 1 : \
	 INSN_SIZE_IS_32(insn) ? 2 : \
	 INSN_SIZE_IS_48(insn) ? 3 : \
	 INSN_SIZE_IS_64(insn) ? 4 : \
	 5)

#define INSN_SIZE(insn) (INSN_HALFWORDS(insn) * sizeof(uint16_t))

/*
 * sign-extend x from the bottom k bits
 */
#define SIGNEXT32(x, k) ( \
		( ((x) & (1U << ((k)-1))) ? (0xffffffffU << (k)) : 0U) | \
		((x) & (0xffffffffU >> (32 - (k))))			 \
	)

/*
 * Field extractors for 32-bit instructions
 */

#define INSN_OPCODE32(insn)	(((insn) & 0x0000007f) >> 2)
#define INSN_RD(insn)		(((insn) & 0x00000f80) >> 7)
#define INSN_FUNCT3(insn)	(((insn) & 0x00007000) >> 12)
#define INSN_RS1(insn)		(((insn) & 0x000f8000) >> 15)
#define INSN_RS2(insn)		(((insn) & 0x01f00000) >> 20)
#define INSN_FUNCT7(insn)	(((insn) & 0xfe000000) >> 25)

/* U-type immediate, just the top bits of the instruction */
#define INSN_IMM_U(insn)	 ((insn) & 0xfffff000)

/* I-type immediate, upper 12 bits sign-extended */
#define INSN_IMM_I(insn)	SIGNEXT32(((insn) & 0xfff00000) >> 20, 12)

/* S-type immediate (stores), pasted from funct7 field and rd field */
#define INSN_IMM_S_raw(insn)	((INSN_FUNCT7(insn) << 5) | INSN_RD(insn))
#define INSN_IMM_S(insn)	SIGNEXT32(INSN_IMM_S_raw(insn), 12)

/* B-type immediate (branches), pasted messily from funct7 and rd fields */
#define INSN_IMM_B_raw(insn)			\
	(((insn & 0x80000000) >> (31-12)) |	\
	 ((insn & 0x00000080) << (11-7))  |	\
	 ((insn & 0x7e000000) >> (25-5))  |	\
	 ((insn & 0x00000f00) >> (8-1)))
#define INSN_IMM_B(insn)	SIGNEXT32(INSN_IMM_B_raw(insn), 13)

/* J-type immediate (jumps), rehash of the U immediate field */
#define INSN_IMM_J_raw(insn)			\
	(((insn & 0x80000000) >> (31-20)) |	\
	 ((insn & 0x000ff000) >> (12-12)) |	\
	 ((insn & 0x00100000) >> (20-11)) |	\
	 ((insn & 0x7fe00000) >> (21-1)))
#define INSN_IMM_J(insn)	SIGNEXT32(INSN_IMM_J_raw(insn), 21)

/*
 * Field extractors for 16-bit instructions
 */

#define INSN16_QUADRANT(insn)	((insn) & 0b11)

/*
 * In the manual there's
 *    FUNCT3 (bits 13-15)
 *    FUNCT4 (bits 12-15)
 *    FUNCT6 (bits 10-15)
 *    FUNCT2 (bits 5-6)
 *
 * but this does not reflect the actual usage correctly. So I've got
 *    FUNCT3 (bits 13-15)
 *    FUNCT2a (bits 10-11)
 *    FUNCT1b (bit 12)
 *    FUNCT2b (bits 5-6)
 *    FUNCT3b (FUNCT1b pasted to FUNCT3b)
 *
 * Quadrant 0 just uses FUNCT3;
 * Quadrant 1 goes FUNCT3 -> FUNCT2a -> FUNCT3b,
 * Quadrant 2 goes FUNCT3 -> FUNCT1b.
 */
#define INSN16_FUNCT3(insn)	(((insn) & 0xe000) >> 13)
#define INSN16_FUNCT2a(insn)	(((insn) & 0x0c00) >> 10)
#define INSN16_FUNCT1b(insn)	(((insn) & 0x1000) >> 12)
#define INSN16_FUNCT2b(insn)	(((insn) & 0x0060) >> 5)
#define INSN16_FUNCT3c(insn)	\
	((INSN16_FUNCT1b(insn) << 2) | INSN16_FUNCT2b(insn))

/* full-size register fields */
#define INSN16_RS1(insn)	(((insn) & 0x0f80) >> 7)  /* bits 7-11 */
#define INSN16_RS2(insn)	(((insn) & 0x007c) >> 2)  /* bits 2-6 */

/* small register fields, for registers 8-15 */
#define INSN16_RS1x(insn)	((((insn) & 0x0380) >> 7) + 8)	/* bits 7-9 */
#define INSN16_RS2x(insn)	((((insn) & 0x001c) >> 2) + 8)	/* bits 2-4 */

/* CI format immediates, for word/double/quad offsets, zero-extended */
#define INSN16_IMM_CI_W(insn) \
	((((insn) & 0b0001000000000000) >> (12-5)) |	\
	 (((insn) & 0b0000000001110000) >> (4-2)) |	\
	 (((insn) & 0b0000000000001100) << (6-2)))
#define INSN16_IMM_CI_D(insn) \
	((((insn) & 0b0001000000000000) >> (12-5)) |	\
	 (((insn) & 0b0000000001100000) >> (4-2)) |	\
	 (((insn) & 0b0000000000011100) << (6-2)))
#define INSN16_IMM_CI_Q(insn) \
	((((insn) & 0b0001000000000000) >> (12-5)) |	\
	 (((insn) & 0b0000000001000000) >> (4-2)) |	\
	 (((insn) & 0b0000000000111100) << (6-2)))

/* additional CI format immediates for constants, sign-extended */
#define INSN16_IMM_CI_K_raw(insn) \
	((((insn) & 0b0001000000000000) >> (12-5)) |	\
	 (((insn) & 0b0000000001111100) >> (2-0)))
#define INSN16_IMM_CI_K(insn) SIGNEXT32(INSN16_IMM_CI_K_raw(insn), 6)
#define INSN16_IMM_CI_K12(insn) SIGNEXT32(INSN16_IMM_CI_K_raw(insn) << 12, 18)

/* and another one, sign-extended */
#define INSN16_IMM_CI_K4_raw(insn) \
	((((insn) & 0b0001000000000000) >> (12-9)) |	\
	 (((insn) & 0b0000000001000000) >> (6-4)) |	\
	 (((insn) & 0b0000000000100000) << (6-5)) |	\
	 (((insn) & 0b0000000000011000) << (7-3)) |	\
	 (((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CI_K4(insn) SIGNEXT32(INSN16_IMM_CI_K4_raw(insn), 10)


/* CSS format immediates, for word/double/quad offsets, zero-extended */
#define INSN16_IMM_CSS_W(insn) \
	((((insn) & 0b0001111000000000) >> (9-2)) |	\
	 (((insn) & 0b0000000110000000) >> (7-6)))
#define INSN16_IMM_CSS_D(insn) \
	((((insn) & 0b0001110000000000) >> (9-2)) |	\
	 (((insn) & 0b0000001110000000) >> (7-6)))
#define INSN16_IMM_CSS_Q(insn) \
	((((insn) & 0b0001100000000000) >> (9-2)) |	\
	 (((insn) & 0b0000011110000000) >> (7-6)))

/* CL format immediates, for word/double/quad offsets, zero-extended */
#define INSN16_IMM_CL_W(insn) \
	((((insn) & 0b0001110000000000) >> (10-3)) |	\
	 (((insn) & 0b0000000001000000) >> (6-2)) |	\
	 (((insn) & 0b0000000000100000) << (6-5)))
#define INSN16_IMM_CL_D(insn) \
	((((insn) & 0b0001110000000000) >> (10-3)) |	\
	 (((insn) & 0b0000000001100000) << (6-5)))
#define INSN16_IMM_CL_Q(insn) \
	((((insn) & 0b0001100000000000) >> (11-4)) |	\
	 (((insn) & 0b0000010000000000) >> (10-8)) |	\
	 (((insn) & 0b0000000001100000) << (6-5)))

/* CS format immediates are the same as the CL ones */
#define INSN16_IMM_CS_W(insn) INSN16_IMM_CL_W(insn)
#define INSN16_IMM_CS_D(insn) INSN16_IMM_CL_D(insn)
#define INSN16_IMM_CS_Q(insn) INSN16_IMM_CL_Q(insn)

/* CJ format immedate, sign extended */
#define INSN16_IMM_CJ_raw(insn) \
	((((insn) & 0b0001000000000000) >> (12-11)) |	\
	 (((insn) & 0b0000100000000000) >> (11-4)) |	\
	 (((insn) & 0b0000011000000000) >> (9-8)) |	\
	 (((insn) & 0b0000000100000000) << (10-8)) |	\
	 (((insn) & 0b0000000010000000) >> (7-6)) |	\
	 (((insn) & 0b0000000001000000) << (7-6)) |	\
	 (((insn) & 0b0000000000111000) >> (3-1)) |	\
	 (((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CJ(insn) SIGNEXT32(INSN16_IMM_CJ_raw(insn), 12)

/* CB format immediate, sign extended */
#define INSN16_IMM_CB_raw(insn) \
	((((insn) & 0b0001000000000000) >> (12-8)) |	\
	 (((insn) & 0b0000110000000000) >> (10-3)) |	\
	 (((insn) & 0b0000000001100000) << (6-5)) |	\
	 (((insn) & 0b0000000000011000) >> (3-1)) |	\
	 (((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CB(insn) SIGNEXT32(INSN16_IMM_CB_raw(insn), 9)

/* also some CB instructions use the CI_K immediate */

/* CIW format immediate, zero-extended */
#define INSN16_IMM_CIW(insn) \
	((((insn) & 0b0001100000000000) >> (11-4)) |	\
	 (((insn) & 0b0000011110000000) >> (7-6)) |	\
	 (((insn) & 0b0000000001000000) >> (6-2)) |	\
	 (((insn) & 0b0000000000100000) >> (5-3)))

/*
 * Values for the primary opcode field (bits 2-6) in 32-bit instructions
 */

#define	OPCODE_LOAD		0b00000
#define	OPCODE_LOADFP		0b00001
#define	OPCODE_CUSTOM0		0b00010
#define	OPCODE_MISCMEM		0b00011
#define	OPCODE_OPIMM		0b00100
#define	OPCODE_AUIPC		0b00101
#define	OPCODE_OPIMM32		0b00110
#define	OPCODE_X48a		0b00111

#define	OPCODE_STORE		0b01000
#define	OPCODE_STOREFP		0b01001
#define	OPCODE_CUSTOM1		0b01010
#define	OPCODE_AMO		0b01011
#define	OPCODE_OP		0b01100
#define	OPCODE_LUI		0b01101
#define	OPCODE_OP32		0b01110
#define	OPCODE_X64		0b01111

#define	OPCODE_MADD		0b10000		// FMADD.[S,D]
#define	OPCODE_MSUB		0b10001		// FMSUB.[S,D]
#define	OPCODE_NMSUB		0b10010		// FNMSUB.[S,D]
#define	OPCODE_NMADD		0b10011		// FNMADD.[S,D]
#define	OPCODE_OPFP		0b10100
#define	OPCODE_rsvd21		0b10101
#define	OPCODE_CUSTOM2		0b10110
#define	OPCODE_X48b		0b10111

#define	OPCODE_BRANCH		0b11000
#define	OPCODE_JALR		0b11001
#define	OPCODE_rsvd26		0b11010
#define	OPCODE_JAL		0b11011
#define	OPCODE_SYSTEM		0b11100
#define	OPCODE_rsvd29		0b11101
#define	OPCODE_CUSTOM3		0b11110
#define	OPCODE_X80		0b11111

/*
 * Values for the secondary/tertiary opcode field funct7 in 32-bit instructions
 * for various primary and secondary opcodes.
 *
 * Note: for many of these the opcodes shown are the top 5 bits and the
 * bottom two serve a separate purpose.
 */

// primary is OP (0b01100, 12)
#define OP_ARITH		0b0000000
#define OP_MULDIV		0b0000001
#define OP_NARITH		0b0100000

// primary is OPFP (0b10100, 20), top 5 bits
// bottom 2 bits give the size
#define OPFP_ADD		0b00000
#define OPFP_SUB		0b00001
#define OPFP_MUL		0b00010
#define OPFP_DIV		0b00011
#define OPFP_SGNJ		0b00100
#define OPFP_MINMAX		0b00101
#define OPFP_CVTFF		0b01000
#define OPFP_SQRT		0b01011
#define OPFP_CMP		0b10100
#define OPFP_CVTIF		0b11000
#define OPFP_CVTFI		0b11010
#define OPFP_MVFI_CLASS		0b11100
#define OPFP_MVIF		0b11110

// primary is OPFP (0b10100, 20), bottom two bits (operand size)
// these bits also give the size for FMADD/FMSUB/FNMSUB/FNMADD
// and for FCVTFF they appear at the bottom of the rs2 field as well
#define OPFP_S			0b00
#define OPFP_D			0b01
#define OPFP_Q			0b11

// in some instructions they're an integer operand size instead
#define OPFP_W			0b00
#define OPFP_WU			0b01
#define OPFP_L			0b10
#define OPFP_LU			0b11

// primary is AMO (0b01011, 11), top 5 bits
// (bottom two bits are ACQUIRE and RELEASE flags respectively)
// funct3 gives the operand size
#define AMO_ADD			0b00000
#define AMO_SWAP		0b00001
#define AMO_LR			0b00010
#define AMO_SC			0b00011
#define AMO_XOR			0b00100
#define AMO_OR			0b01000
#define AMO_AND			0b01100
#define AMO_MIN			0b10000
#define AMO_MAX			0b10100
#define AMO_MINU		0b11000
#define AMO_MAXU		0b11100

// primary is SYSTEM (0b11100, 28) and funct3 is PRIV (0)
#define PRIV_USER		0b0000000
#define PRIV_SYSTEM		0b0001000
#define PRIV_SFENCE_VMA		0b0001001
#define PRIV_HFENCE_BVMA	0b0010001
#define PRIV_MACHINE		0b0011000
#define PRIV_HFENCE_GVMA	0b1010001

/*
 * Values for the secondary/tertiary opcode field funct3 in 32-bit instructions
 * for various primary and secondary opcodes.
 */

// primary is LOAD (0x00000)
#define LOAD_LB			0b000
#define LOAD_LH			0b001
#define LOAD_LW			0b010
#define LOAD_LD			0b011		// RV64I
#define LOAD_LBU		0b100
#define LOAD_LHU		0b101
#define LOAD_LWU		0b110		// RV64I

// primary is LOADFP (0x00001)
#define LOADFP_FLW		0b010
#define LOADFP_FLD		0b011
#define LOADFP_FLQ		0b100

// primary is MISCMEM (0x00011, 3)
#define MISCMEM_FENCE		0b000
#define MISCMEM_FENCEI		0b001

// primary is STORE (0b01000, 8)
#define STORE_SB		0b000
#define STORE_SH		0b001
#define STORE_SW		0b010
#define STORE_SD		0b011		// RV64I

// primary is STOREFP (0b01001, 9)
#define STOREFP_FSW		0b010
#define STOREFP_FSD		0b011
#define STOREFP_FSQ		0b100

// primary is AMO (0b01011, 11), funct7 gives the operation
#define AMO_W			0b010
#define AMO_D			0b011		// RV64I

// primary is
//    OPIMM   (0b00100, 4)
//    OPIMM32 (0b00110, 6)
//    OP      (0b01100, 12) when funct7 is ARITH or NARITH
//    OP32    (0b01110, 14)
//                                               OP	OP	OP32	OP32
// given:			   OPIMM OPIMM32 ARITH	NARITH  ARITH	NARITH
#define OP_ADDSUB	0b000	// addi  addiw   add	sub	addw	subw
#define OP_SLL		0b001	// (1)   (2)     sll	-	sllw	-
#define OP_SLT		0b010	// slti  -       slt	-	-	-
#define OP_SLTU		0b011	// sltiu -       sltu	-	-	-
#define OP_XOR		0b100	// xori  -       xor	-	-	-
#define OP_SRX		0b101	// (3)   (4)     srl    sra	srlw	sraw
#define OP_OR		0b110	// ori   -       or	-	-	-
#define OP_AND		0b111	// andi  -       and	-	-	-
//
// (1) slli when funct7 is ARITH
// (2) slliw when funct7 is ARITH
// (3) srli when funct7 is ARITH, srai when funct7 is NARITH
// (4) srliw when funct7 is ARITH, sraiw when funct7 is NARITH
//
// caution: on RV64, the immediate field of slli/srli/srai bleeds into
// funct7, so you have to actually only test the upper 6 bits of funct7.
// (and if RV128 ever actually happens, the upper 5 bits; conveniently
// that aligns with other uses of those 5 bits)
//

// primary is
//    OP      (0b01100, 12) when funct7 is MULDIV
//    OP32    (0b01110, 14) when funct7 is MULDIV
//
// given:				   OP      OP32
#define OP_MUL			0b000	// mul     mulw
#define OP_MULH			0b001	// mulh    -
#define OP_MULHSU		0b010	// mulhsu  -
#define OP_MULHU		0b011   // mulhu   -
#define OP_DIV			0b100	// div     divw
#define OP_DIVU			0b101	// divu    divuw
#define OP_REM			0b110	// rem     remw
#define OP_REMU			0b111	// remu    remuw

// primary is
//    MADD    (0b10000, 16)
//    MSUB    (0b10001, 17)
//    NMADD   (0b10010, 18)
//    NMSUB   (0b10011, 19)
//    OPFP    (0b10100, 20) when funct7 is
//                ADD SUB MULDIV SQRT CVTFF CVTIF CVTFI
#define ROUND_RNE		0b000
#define ROUND_RTZ		0b001
#define ROUND_RDN		0b010
#define ROUND_RUP		0b011
#define ROUND_RMM		0b100
#define ROUND_DYN		0b111

// primary is OPFP (0b10100, 20) and funct7 is FSGNJ (0b00100)
#define SGN_SGNJ		0b000
#define SGN_SGNJN		0b001
#define SGN_SGNJX		0b010

// primary is OPFP (0b10100, 20) and funct7 is MINMAX (0b00101)
#define MINMAX_MIN		0b000
#define MINMAX_MAX		0b001

// primary is OPFP (0b10100, 20) and funct7 is CMP (0b10100)
#define CMP_LE			0b000
#define CMP_LT			0b001
#define CMP_EQ			0b010

// primary is OPFP (0b10100, 20) and funct7 is MVFI_CLASS (0b11110)
#define MVFI_CLASS_MVFI		0b000
#define MVFI_CLASS_CLASS	0b001

// primary is BRANCH (0b11000, 24)
#define BRANCH_BEQ		0b000
#define BRANCH_BNE		0b001
#define BRANCH_BLT		0b100
#define BRANCH_BGE		0b101
#define BRANCH_BLTU		0b110
#define BRANCH_BGEU		0b111

// primary is SYSTEM (0b11100, 28)
#define SYSTEM_PRIV		0b000
#define SYSTEM_CSRRW		0b001
#define SYSTEM_CSRRS		0b010
#define SYSTEM_CSRRC		0b011
#define SYSTEM_CSRRWI		0b101
#define SYSTEM_CSRRSI		0b110
#define SYSTEM_CSRRCI		0b111

// the funct3 field is not used for
//    AUIPC   (0b00101, 5)
//    LUI     (0b01101, 13)
//    JALR    (0b11001, 25) (or rather, it's always 0)
//    JAL     (0b11011, 27)

// and for these there are no standard instructions defined anyhow
//    CUSTOM0 (0b00010, 2)
//    CUSTOM1 (0b01010, 10)
//    CUSTOM2 (0b10110, 22)
//    CUSTOM3 (0b11110, 30)
//    rsvd21  (0b10101, 21)
//    rsvd29  (0b11101, 29)
//    X48a    (0b00111, 7)
//    X64     (0b01111, 15)
//    X48b    (0b10111, 23)
//    X80     (0b11111, 31)

/*
 * quaternary opcodes in rs2 field of 32-bit instructions
 */

// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is USER (0)
#define USER_ECALL		0b00000
#define USER_EBREAK		0b00001
#define USER_URET		0b00010

// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is SYSTEM (0b0001000, 16)
#define SYSTEM_SRET		0b00010
#define SYSTEM_WFI		0b00101

// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is MACHINE (0b0011000, 48)
#define MACHINE_MRET		0b00010

// primary is OPFP (0b10100, 20)
// funct7 is CVTFI or CVTIF
#define CVT_W			0b00000
#define CVT_WU			0b00001
#define CVT_L			0b00010
#define CVT_LU			0b00011

/*
 * code bits for fence instruction
 */

#define FENCE_INPUT	0b1000
#define FENCE_OUTPUT	0b0100
#define FENCE_READ	0b0010
#define FENCE_WRITE	0b0001

#define FENCE_FM_NORMAL	0b0000
#define FENCE_FM_TSO	0b1000

/*
 * AMO aq/rl bits in funct7
 */
#define AMO_AQ		0b0000010
#define AMO_RL		0b0000001

/*
 * Opcode values for 16-bit instructions.
 */

#define OPCODE16_Q0	0b00	/* quadrant 0 */
#define OPCODE16_Q1	0b01	/* quadrant 1 */
#define OPCODE16_Q2	0b10	/* quadrant 2 */

/* quadrant 0 */
#define Q0_ADDI4SPN	0b000
#define Q0_FLD_LQ	0b001	/* RV32/RV64 FLD, RV128 LQ */
#define Q0_LW		0b010
#define Q0_FLW_LD	0b011	/* RV32 FLW, RV64/RV128 LD */
#define Q0_RESERVED	0b100
#define Q0_FSD_SQ	0b101	/* RV32/RV64 FSD, RV128 SQ */
#define Q0_SW		0b110
#define Q0_FSW_SD	0b111	/* RV32 FSW, RV64/RV128 SD */

/* quadrant 1 */
#define Q1_NOP_ADDI	0b000	/* NOP when rs1/rd == 0, ADDI otherwise */
#define Q1_JAL_ADDIW	0b001	/* RV32 JAL, RV64/RV128 ADDIW */
#define Q1_LI		0b010
#define Q1_ADDI16SP_LUI	0b011	/* ADDI16SP when rs1/rd == sp, else LUI */
#define Q1_MISC		0b100
#define Q1_J		0b101
#define Q1_BEQZ		0b110
#define Q1_BNEZ		0b111

/* funct2a values for Q1_MISC */
#define Q1MISC_SRLI	0b00
#define Q1MISC_SRAI	0b01
#define Q1MISC_ANDI	0b10
#define Q1MISC_MORE	0b11

/* funct3b values for Q1MISC_MORE */
#define Q1MORE_SUB	0b000
#define Q1MORE_XOR	0b001
#define Q1MORE_OR	0b010
#define Q1MORE_AND	0b011
#define Q1MORE_SUBW	0b100	/* RV64/RV128 */
#define Q1MORE_ADDW	0b101	/* RV64/RV128 */

/* quadrant 2 */
#define Q2_SLLI		0b000
#define Q2_FLDSP_LQSP	0b001	/* RV32/RV64 FLDSP, RV128 LQSP */
#define Q2_LWSP		0b010
#define Q2_FLWSP_LDSP	0b011	/* RV32 FLWSP, RV64/RV128 LDSP */
#define Q2_MISC		0b100
#define Q2_FSDSP_SQSP	0b101	/* RV32/RV64 FSDSP, RV128 SQSP */
#define Q2_SWSP		0b110
#define Q2_FSWSP_SDSP	0b111	/* RV32/RV64 FSWSP, RV128 SDSP */

/* funct1b values for Q2_MISC */
#define Q2MISC_JR_MV	0b0	/* JR when rs2 == 0, MV otherwise */
#define Q2MISC_EBREAK_JALR_ADD	0b1 /* EBREAK rs1==0; JALR rs2==0; else ADD */

/*
 * CSR numbers
 */

// fpu
#define CSR_FFLAGS		0x001
#define CSR_FRM			0x002
#define CSR_FCSR		0x003

// perfcounters
#define CSR_CYCLE		0xc00
#define CSR_TIME		0xc01
#define CSR_INSTRET		0xc02
#define CSR_HPMCOUNTER(n)	(0xc00+(n))	// n in 3..31
#define CSR_CYCLEH		0xc80	// RV32I
#define CSR_TIMEH		0xc81	// RV32I
#define CSR_INSTRETH		0xc82	// RV32I
#define CSR_HPMCOUNTERH(n)	(0xc80+(n))	// n in 3..31

// system
#define CSR_SSTATUS		0x100
//	CSR_SEDELEG		0x102
//	CSR_SIDELEG		0x103
#define CSR_SIE			0x104
#define CSR_STVEC		0x105
#define CSR_SCOUNTEREN		0x106
#define CSR_SSCRATCH		0x140
#define CSR_SEPC		0x141
#define CSR_SCAUSE		0x142
#define CSR_STVAL		0x143
#define CSR_SIP			0x144
#define CSR_SATP		0x180

// machine
#define CSR_MVENDORID		0xf11
#define CSR_MARCHID		0xf12
#define CSR_MIMPID		0xf13
#define CSR_MHARTID		0xf14
#define CSR_MSTATUS		0x300
#define CSR_MISA		0x301
#define CSR_MEDELEG		0x302
#define CSR_MIDELEG		0x303
#define CSR_MIE			0x304
#define CSR_MTVEC		0x305
#define CSR_MCOUNTEREN		0x306
#define CSR_MSCRATCH		0x340
#define CSR_MEPC		0x341
#define CSR_MCAUSE		0x342
#define CSR_MTVAL		0x343
#define CSR_MIP			0x344
#define CSR_PMPCFG(n)		(0x3a0 + (n))	// n in 0..3
#define CSR_PMPADDR(n)		(0x3b0 + (n))	// n in 0..15
#define CSR_MCYCLE		0xb00
#define CSR_MINSTRET		0xb02
#define CSR_MHPMCOUNTER(n)	(0xb00+(n))	// n in 3..31
#define CSR_MCYCLEH		0xb80	// RV32I
#define CSR_MINSTRETH		0xb82	// RV32I
#define CSR_MHPMCOUNTERH(n)	(0xb80+(n))	// n in 3..31
#define CSR_MCOUNTINHIBIT	0x320
#define CSR_MHPMEVENT(n)	(0x320+(n))	// n in 3..31

// debug
#define CSR_TSELECT		0x7a0
#define CSR_TDATA1		0x7a1
#define CSR_TDATA2		0x7a2
#define CSR_TDATA3		0x7a3
#define CSR_DCSR		0x7b0
#define CSR_DPC			0x7b1
#define CSR_DSCRATCH0		0x7b2
#define CSR_DSCRATCH1		0x7b3


#endif /* _RISCV_INSN_H_ */