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
//! Assembly instructions
//!
//! This module allows you to use XuanTie instructions without using specialized assembler or compiler.
//!
//! Not all these instructions are supported on your XuanTie platform.
//! You may use `mcpuid` register to get your implementation model, or read the manual
//! before using any of following assembly instructions.
use core::arch::asm;

// T-Head extended instructions are mostly encoded under custom-0 opcode space (opcode 0x0B).

/// DCACHE.CALL, D-cache clean all dirty items instruction
///
/// Clears all L1 D-cache table items, write all dirty items to next level storage.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn dcache_call() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x001")
}

/// DCACHE.IALL, D-cache invalid all items instruction
///
/// Invalidates all L1 D-cache table items. This instruction only operates on the current hart.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn dcache_iall() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x002")
}

/// DCACHE.CIALL, D-cache clean all dirty and invalid item instruction
///
/// Writes all L1 D-cache dirty items to next level storage, and invalidate all L1 D-cache table items.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn dcache_ciall() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x003")
}

/// IPUSH, fast interrupt stack push instruction
///
/// Push interrupt switch registers into current stack.
/// It pushes `mcause`, `mepc`, `x1`, `x5` to `x7`, `x10` to `x17` and `x28` to `x31` into stack.
/// Another word, the pushed `xi` integer registers are `ra`, `t0` to `t6`, and `a0` to `a7` (not in order)
/// other than CSR registers `mcause` and `mepc`.
///
/// In pseudocode, it performs like:
///
/// ```no_run
/// *sp.sub(1) = mcause;
/// *sp.sub(2) = mepc;
/// *sp.sub(3) = ra;
/// /* ... Mem[sp - 4] ..= Mem[sp - 72] ← mcause, mepc, {xi} */
/// *sp.sub(18) = t6;
/// sp = sp.sub(18);
/// ```
///
/// # Permissions
///
/// Must run on M mode.
///
/// # Exceptions
///
/// Raises store unaligned exception, store access exception, or illegal instruction exception.
#[inline]
pub unsafe fn ipush() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x004")
}

/// IPOP, fast interrupt stack pop instruction
///
/// Pop interrupt switch registers from current stack, and return from interrupt environment.
/// It pops `mcause`, `mepc`, `x1`, `x5` to `x7`, `x10` to `x17` and `x28` to `x31` from stack.
/// Another word, the popped `xi` integer registers are `ra`, `t0` to `t6`, and `a0` to `a7` (not in order)
/// other than CSR registers `mcause` and `mepc`.
///
/// In pseudocode, it performs like:
///
/// ```no_run
/// mcause = *sp.add(17);
/// mepc = *sp.add(16);
/// ra = *sp.add(15);
/// /* ... mcause, mepc, {xi} ← Mem[sp + 68] ..= Mem[sp] */
/// t6 = *sp.add(0);
/// sp = sp.add(18);
/// riscv::asm::mret();
/// ```
///
/// # Permissions
///
/// Must run on M mode.
///
/// # Exceptions
///
/// Raises store unaligned exception, store access exception, or illegal instruction exception.
#[inline]
pub unsafe fn ipop() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x005")
}

/// ICACHE.IALL, I-cache invalid all items instruction
///
/// Invalidates all I-cache table items. This instruction only operates on the current hart.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907, E906 and E902 cores.
#[inline]
pub unsafe fn icache_iall() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x010")
}

/// ICACHE.IALLS, I-cache broadcast all harts to invalid all items instruction
///
/// Invalidates all I-cache table items, and broadcast other harts to invalid all I-cache items.
/// This operation operates on I-cache on all harts.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
#[inline]
pub unsafe fn icache_ialls() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x011")
}

/// L2CACHE.CALL, L2-cache clean all dirty items instruction
///
/// Clears all L2-cache table items, write all dirty items to next level storage.
///
/// # Permissions
///
/// Must run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
#[inline]
pub unsafe fn l2cache_call() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x015")
}

/// L2CACHE.IALL, L2-cache invalid all items instruction
///
/// Invalidates all L2-cache table items.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
#[inline]
pub unsafe fn l2cache_iall() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x016")
}

/// L2CACHE.CIALL, L2-cache clean all dirty and invalid item instruction
///
/// Writes all L2-cache dirty items to next level storage, and invalidate all L2-cache table items.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
#[inline]
pub unsafe fn l2cache_ciall() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x017")
}

/// SYNC, Synchronize instruction
///
/// Ensures that all instructions before retire earlier than this instruction,
/// and all instructions after retire later than this instruction.
///
/// # Permissions
///
/// Can run on M, U mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn sync() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x018")
}

/// SYNC.S, Synchronize and broadcast instruction
///
/// Ensures that all instructions before retire earlier than this instruction,
/// and all instructions after retire later than this instruction.
/// This request will be broadcast to all other harts.
///
/// # Permissions
///
/// Can run on M, S or U mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
#[inline]
pub unsafe fn sync_s() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x019")
}

/// SYNC.I, Synchronize and clean instruction
///
/// Ensures that all instructions before retire earlier than this instruction,
/// and all instructions after retire later than this instruction.
/// The pipeline is emptied when this instruction retires.
///
/// # Permissions
///
/// Can run on M, U mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn sync_i() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x01A")
}

/// SYNC.IS, Synchronize, clean and broadcast instruction
///
/// Ensures that all instructions before retire earlier than this instruction,
/// and all instructions after retire later than this instruction.
/// The pipeline is emptied when this instruction retires.
/// This request will be broadcast to all other harts.
///
/// # Permissions
///
/// Can run on M, S or U mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
#[inline]
pub unsafe fn sync_is() {
    asm!(".insn i 0x0B, 0, x0, x0, 0x01B")
}

/// DCACHE.CSW, D-cache clean dirty item on way and set instruction
///
/// Writes D-cache dirty table item corresponding to given way and set to next level storage.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
///
/// The C910 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The C906 core has a 4-way set-associative D-cache. Input variable `rs1[31:30]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The E907 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
///
/// The E906 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
#[inline]
pub unsafe fn dcache_csw(way_and_set: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x021", in(reg) way_and_set)
}

/// DCACHE.ISW, D-cache invalid item for way and set instruction
///
/// Invalidate D-cache dirty table item corresponding to given way and set.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
///
/// The C910 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The C906 core has a 4-way set-associative D-cache. Input variable `rs1[31:30]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The E907 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
///
/// The E906 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
#[inline]
pub unsafe fn dcache_isw(way_and_set: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x022", in(reg) way_and_set)
}

/// DCACHE.CISW, D-cache clean dirty and invalid for way and set instruction
///
/// Writes L1 D-cache dirty item corresponding to given way and set to next level storage,
/// and invalidate this table item.
/// This instruction only operates on the current hart.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
///
/// The C910 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The C906 core has a 4-way set-associative D-cache. Input variable `rs1[31:30]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 64 Kibibytes, `w` equals 14.
///
/// The E907 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
///
/// The E906 core has a 2-way set-associative D-cache. Input variable `rs1[31]` represents number of way,
/// while `rs1[w:6]` represents number of set. When D-cache is configured 32 Kibibytes, `w` equals 13;
/// when configured 16 Kibibytes, `w` equals 12, and so on.
#[inline]
pub unsafe fn dcache_cisw(way_and_set: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x023", in(reg) way_and_set)
}

/// DCACHE.CVAL1, L1 D-cache clean dirty item for virtual address instruction
///
/// Writes D-cache table item corresponding to virtual address `va` to next level storage.
/// This operation effects on L1-cache on all harts.
///
/// # Permissions
///
/// Can run on M, S or U mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception, or load page fault exception.
///
/// - When `mxstatus.theadisaee = 0`, this instruction always raise illegal instruction exception.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 1`, this instruction can be run on U mode.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 0`,
///   this instruction will raise illegal instruction when being run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
/// On Xuantie C906 User Manual, this instruction is named `DCACHE.CVA`.
#[inline]
pub unsafe fn dcache_cval1(va: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x024", in(reg) va)
}

/// DCACHE.CVA, D-cache clean dirty item for virtual address instruction
///
/// Writes D-cache and L2-cache table item corresponding to virtual address `va` to next level storage.
/// This operation effects on all harts and the L2-cache.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception, or load page fault exception.
///
/// - When `mxstatus.theadisaee = 0`, this instruction always raise illegal instruction exception.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 1`, this instruction can be run on U mode.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 0`,
///   this instruction will raise illegal instruction when being run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
///
/// The Xuantie C906 User Manual names `DCACHE.CVAL1` as `DCACHE.CVA`; to clean dirty item on
/// C906 you may need to use function [`dcache_cval1`] on this library.
#[inline]
pub unsafe fn dcache_cva(va: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x025", in(reg) va)
}

/// DCACHE.IVA, D-cache invalid item for virtual address instruction
///
/// Invalidates D-cache or L2-cache (if applicable) table item corresponding to virtual address `va`.
///
/// This instruction operates on the current hart. If applicable, this instruction will
/// operates on L2-cache, and decide whether to broadcast to other harts according to
/// the share attribute of the virtual address.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception, or load page fault exception.
///
/// - When `mxstatus.theadisaee = 0`, this instruction always raise illegal instruction exception.
/// - When `mxstatus.theadisaee = 1`, this instruction will raise illegal instruction when being run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
#[inline]
pub unsafe fn dcache_iva(va: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x026", in(reg) va)
}

/// DCACHE.CIVA, D-cache clean dirty and invalid for virtual address instruction
///
/// Write D-cache or L2-cache (if applicable) table item corresponding to virtual address `va`
/// to next level storage, and invalidate this table item.
///
/// This instruction operates on the current hart. If applicable, this instruction will
/// operates on L2-cache, and decide whether to broadcast to other harts according to
/// the share attribute of the virtual address.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception, or load page fault exception.
///
/// - When `mxstatus.theadisaee = 0`, this instruction always raise illegal instruction exception.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 1`, this instruction can be run on U mode.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 0`,
///   this instruction will raise illegal instruction when being run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
#[inline]
pub unsafe fn dcache_civa(va: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x027", in(reg) va)
}

/// DCACHE.CPAL1, L1 D-cache clean dirty item for physical address instruction
///
/// Writes D-cache table item corresponding to physical address `pa` to next level storage.
/// This operation effects on L1-cache for all harts.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
/// On Xuantie C906 User Manual, Xuantie E907 User Manual and Xuantie E906 User Manual,
/// this instruction is named `DCACHE.CPA`.
#[inline]
pub unsafe fn dcache_cpal1(pa: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x028", in(reg) pa)
}

/// DCACHE.CPA, D-cache clean dirty item for physical address instruction
///
/// Writes D-cache and L2-cache table item corresponding to physical address `pa` to next level storage.
/// This operation effects on all harts and the L2-cache.
///
/// # Permissions
///
/// Can run on M or S mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 core.
///
/// The Xuantie C906 User Manual, Xuantie E907 User Manual and Xuantie E906 User Manual
/// names `DCACHE.CPAL1` as `DCACHE.CPA`; to clean dirty item on
/// these cores you may need to use function [`dcache_cpal1`] on this library.
#[inline]
pub unsafe fn dcache_cpa(pa: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x029", in(reg) pa)
}

#[inline]
/// DCACHE.IPA, D-cache invalid item for physical address instruction
///
/// Invalidates D-cache table item corresponding to physical address `pa`.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
pub unsafe fn dcache_ipa(pa: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x02A", in(reg) pa)
}

/// DCACHE.CIPA, D-cache clean dirty and invalid for physical address instruction
///
/// Writes D-cache or L2-cache (if applicable) table item corresponding to physical address `pa`
/// to next level storage, and invalidate this table item.
/// If applicable, this instruction operates on all harts and the L2-cache.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907 and E906 cores.
#[inline]
pub unsafe fn dcache_cipa(pa: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x02B", in(reg) pa)
}

/// ICACHE.IVA, I-cache invalid item for virtual address instruction
///
/// Invalidates the I-cache table item corresponding to virtual address `va`.
///
/// This instruction operates on the current hart. If applicable, this instruction will
/// operates on L2-cache, and decide whether to broadcast to other harts according to
/// the share attribute of the virtual address.
///
/// # Permissions
///
/// Can run on M, S or U mode.
///
/// # Exceptions
///
/// Raises illegal instruction exception, or load page fault exception.
///
/// - When `mxstatus.theadisaee = 0`, this instruction always raise illegal instruction exception.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 1`, this instruction can be run on U mode.
/// - When `mxstatus.theadisaee = 1`, and `mxstatus.ucme = 0`,
///   this instruction will raise illegal instruction when being run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910 and C906 cores.
#[inline]
pub unsafe fn icache_iva(va: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x030", in(reg) va)
}

/// ICACHE.IPA, I-cache invalid item for physical address instruction
///
/// Invalidates I-cache table item corresponding to physical address `pa`.
/// If applicable, this instruction operates on all harts.
///
/// # Permissions
///
/// Can run on M mode, or S mode if applicable.
///
/// # Exceptions
///
/// Raises illegal instruction exception when `mxstatus.theadisaee = 0`, or
/// when `mxstatus.theadisaee = 1` but run on U mode.
///
/// # Platform support
///
/// This instruction is supported on Xuantie C910, C906, E907, E906 and E902 cores.
#[inline]
pub unsafe fn icache_ipa(pa: usize) {
    asm!(".insn i 0x0B, 0, x0, {}, 0x038", in(reg) pa)
}