aboutsummaryrefslogtreecommitdiff
path: root/cpu/lm32.cpu
blob: ecd8160816efce2ba20896089763c86cdc5a5f5b (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
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
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
; Lattice Mico32 CPU description.  -*- Scheme -*-
; Copyright 2008-2013  Free Software Foundation, Inc.
; Contributed by Jon Beniston <jon@beniston.com>
;
; This file is part of the GNU Binutils.
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
; MA 02110-1301, USA.

(include "simplify.inc")

(define-arch
  (name lm32) ; name of cpu family
  (comment "Lattice Mico32")
  (default-alignment aligned)
  (insn-lsb0? #t)
  (machs lm32)
  (isas lm32)
)


; Instruction sets.

(define-isa
  (name lm32)
  (comment "Lattice Mico32 ISA")
  (default-insn-word-bitsize 32)
  (default-insn-bitsize 32)
  (base-insn-bitsize 32)
  (decode-assist (31 30 29 28 27 26))
)


; Cpu family definitions.

(define-cpu
  ; cpu names must be distinct from the architecture name and machine name
  (name lm32bf)
  (comment "Lattice Mico32 CPU")
  (endian big)
  (word-bitsize 32)
)

(define-mach
  (name lm32)
  (comment "Lattice Mico32 MACH")
  (cpu lm32bf)
)

(define-model
  (name lm32)
  (comment "Lattice Mico32 reference implementation")
  (mach lm32)
  (unit u-exec "Execution unit" ()
    1 1 () () () ())
) 


; Hardware elements.

(dnh h-pc "Program counter" (PC) (pc) () () ())

(dnh h-gr "General purpose registers"
  ()
  (register SI (32))
  (keyword "" ( 
               (gp 26) (fp 27) (sp 28) (ra 29) (ea 30) (ba 31)
               (r0 0) (r1 1) (r2 2) (r3 3)
               (r4 4) (r5 5) (r6 6) (r7 7)
               (r8 8) (r9 9) (r10 10) (r11 11)
               (r12 12) (r13 13) (r14 14) (r15 15)
               (r16 16) (r17 17) (r18 18) (r19 19)
               (r20 20) (r21 21) (r22 22) (r23 23)
               (r24 24) (r25 25) (r26 26) (r27 27)
               (r28 28) (r29 29) (r30 30) (r31 31)                
              )
  )
  () ()
)
  
(dnh h-csr "Control and status registers"
  ()
  (register SI (32))
  (keyword "" (
               (IE 0) (IM 1) (IP 2) 
               (ICC 3) (DCC 4)
               (CC 5)
               (CFG 6)
               (EBA 7)
               (DC 8)
               (DEBA 9)
	       (CFG2 10)
               (JTX 14) (JRX 15)          
               (BP0 16) (BP1 17) (BP2 18) (BP3 19)
               (WP0 24) (WP1 25) (WP2 26) (WP3 27)     
               (PSW 29) (TLBVADDR 30) (TLBPADDR 31) (TLBBADVADDR 31)
              )
  )
  () ()
)              
  

; Instruction fields.

(dnf f-opcode   "opcode field"                () 31  6)
(dnf f-r0       "register index 0 field"      () 25  5)
(dnf f-r1       "register index 1 field"      () 20  5)
(dnf f-r2       "register index 2 field"      () 15  5)
(dnf f-resv0    "reserved"                    (RESERVED) 10 11)
(dnf f-shift    "shift amount field"          ()  4  5)
(df  f-imm      "signed immediate field"      () 15 16 INT #f #f)
(dnf f-uimm     "unsigned immediate field"    () 15 16)
(dnf f-csr      "csr field"                   () 25  5)
(dnf f-user     "user defined field"          () 10 11)
(dnf f-exception "exception field"            () 25 26)

(df f-branch "branch offset field" (PCREL-ADDR) 15 16 INT
        ((value pc) (sra SI (sub SI value pc) 2))
	((value pc) (add SI pc (sub (xor (sll (and value #xffff) 2)
					 #x20000)
				    #x20000)))
)
(df f-call "call offset field" (PCREL-ADDR) 25 26 INT 
        ((value pc) (sra SI (sub SI value pc) 2))
	((value pc) (add SI pc (sub (xor (sll (and value #x3ffffff) 2)
					 #x8000000)
				    #x8000000)))
)


; Operands.

(dnop r0        "register 0"            () h-gr         f-r0)
(dnop r1        "register 1"            () h-gr         f-r1)
(dnop r2        "register 2"            () h-gr         f-r2)
(dnop shift     "shift amout"           () h-uint       f-shift)
(dnop imm       "signed immediate"      () h-sint       f-imm)
(dnop uimm      "unsigned immediate"    () h-uint       f-uimm)
(dnop branch    "branch offset"         () h-iaddr      f-branch)
(dnop call      "call offset"           () h-iaddr      f-call)
(dnop csr       "csr"                   () h-csr        f-csr)
(dnop user      "user"                  () h-uint       f-user)
(dnop exception "exception"             () h-uint       f-exception)
            
(define-operand
  (name hi16)
  (comment "high 16-bit immediate")
  (attrs)
  (type h-uint)
  (index f-uimm)
  (handlers (parse "hi16"))
)

(define-operand
  (name lo16)
  (comment "low 16-bit immediate")
  (attrs)
  (type h-uint)
  (index f-uimm)
  (handlers (parse "lo16"))
)

(define-operand
  (name gp16)
  (comment "gp relative 16-bit immediate")
  (attrs)
  (type h-sint)
  (index f-imm)
  (handlers (parse "gp16"))
)

(define-operand
  (name got16)
  (comment "got 16-bit immediate")
  (attrs)
  (type h-sint)
  (index f-imm)
  (handlers (parse "got16"))
)

(define-operand
  (name gotoffhi16)
  (comment "got offset high 16-bit immediate")
  (attrs)
  (type h-sint)
  (index f-imm)
  (handlers (parse "gotoff_hi16"))
)

(define-operand
  (name gotofflo16)
  (comment "got offset low 16-bit immediate")
  (attrs)
  (type h-sint)
  (index f-imm)
  (handlers (parse "gotoff_lo16"))
)


; Enumerations.

(define-normal-insn-enum
  opcodes "opcodes" () OP_ f-opcode
  (("ADD"       45)      
   ("ADDI"      13)      
   ("AND"       40)
   ("ANDI"      8)
   ("ANDHI"     24)
   ("B"         48)
   ("BI"        56)
   ("BE"        17)
   ("BG"        18)
   ("BGE"       19)
   ("BGEU"      20)
   ("BGU"       21)
   ("BNE"       23)
   ("CALL"      54)
   ("CALLI"     62)
   ("CMPE"      57)
   ("CMPEI"     25)
   ("CMPG"      58)
   ("CMPGI"     26)
   ("CMPGE"     59)
   ("CMPGEI"    27)
   ("CMPGEU"    60)
   ("CMPGEUI"   28)
   ("CMPGU"     61)
   ("CMPGUI"    29)
   ("CMPNE"     63)
   ("CMPNEI"    31)
   ("DIVU"      35)
   ("LB"        4)
   ("LBU"       16)
   ("LH"        7)
   ("LHU"       11)
   ("LW"        10)
   ("MODU"      49)
   ("MUL"       34)
   ("MULI"      2)
   ("NOR"       33)
   ("NORI"      1)
   ("OR"        46)
   ("ORI"       14)
   ("ORHI"      30)
   ("RAISE"     43)
   ("RCSR"      36)
   ("SB"        12)
   ("SEXTB"     44)
   ("SEXTH"     55)
   ("SH"        3)
   ("SL"        47)
   ("SLI"       15)
   ("SR"        37)
   ("SRI"       5)
   ("SRU"       32)
   ("SRUI"      0)
   ("SUB"       50)
   ("SW"        22)
   ("USER"      51)
   ("WCSR"      52)
   ("XNOR"      41)
   ("XNORI"     9)
   ("XOR"       38)
   ("XORI"      6)
  )
)
 

; Instructions. Note: Reg-reg must come before reg-imm.

(dni add "add" ()
        "add $r2,$r0,$r1"
        (+ OP_ADD r0 r1 r2 (f-resv0 0))
        (set r2 (add r0 r1))
        ()
)

(dni addi "add immediate" ()
        "addi $r1,$r0,$imm"  
        (+ OP_ADDI r0 r1 imm)
        (set r1 (add r0 (ext SI (trunc HI imm))))
        ()
)

(dni and "and" ()
        "and $r2,$r0,$r1"
        (+ OP_AND r0 r1 r2 (f-resv0 0))
        (set r2 (and r0 r1))
        ()
)

(dni andi "and immediate" ()
        "andi $r1,$r0,$uimm"  
        (+ OP_ANDI r0 r1 uimm)
        (set r1 (and r0 (zext SI uimm)))
        ()
)

(dni andhii "and high immediate" ()
        "andhi $r1,$r0,$hi16"  
        (+ OP_ANDHI r0 r1 hi16)
        (set r1 (and r0 (sll SI hi16 16)))
        ()
)

(dni b "branch" ()
        "b $r0"
        (+ OP_B r0 (f-r1 0) (f-r2 0) (f-resv0 0))
        (set pc (c-call USI "@cpu@_b_insn" r0 f-r0))
        ()
)

(dni bi "branch immediate" ()
        "bi $call"
        (+ OP_BI call)
        (set pc (ext SI call))
        ()
)

(dni be "branch equal" ()
        "be $r0,$r1,$branch"
        (+ OP_BE r0 r1 branch)
        (if (eq r0 r1)
            (set pc branch)
        )
        ()
)

(dni bg "branch greater" ()
        "bg $r0,$r1,$branch"
        (+ OP_BG r0 r1 branch)
        (if (gt r0 r1)
            (set pc branch)
        )
        ()
)

(dni bge "branch greater or equal" ()
        "bge $r0,$r1,$branch"
        (+ OP_BGE r0 r1 branch)
        (if (ge r0 r1)
            (set pc branch)
        )
        ()
)

(dni bgeu "branch greater or equal unsigned" ()
        "bgeu $r0,$r1,$branch"
        (+ OP_BGEU r0 r1 branch)
        (if (geu r0 r1)
            (set pc branch)
        )
        ()
)

(dni bgu "branch greater unsigned" ()
        "bgu $r0,$r1,$branch"
        (+ OP_BGU r0 r1 branch)
        (if (gtu r0 r1)
            (set pc branch)
        )
        ()
)

(dni bne "branch not equal" ()
        "bne $r0,$r1,$branch"
        (+ OP_BNE r0 r1 branch)
        (if (ne r0 r1)
            (set pc branch)
        )
        ()
)

(dni call "call" ()
        "call $r0"
        (+ OP_CALL r0 (f-r1 0) (f-r2 0) (f-resv0 0))
        (sequence ()
                (set (reg h-gr 29) (add pc 4))
                (set pc r0) 
        )
        ()
)

(dni calli "call immediate" ()
        "calli $call"
        (+ OP_CALLI call)
        (sequence ()
                (set (reg h-gr 29) (add pc 4))
                (set pc (ext SI call)) 
        )
        ()
)

(dni cmpe "compare equal" ()
        "cmpe $r2,$r0,$r1"  
        (+ OP_CMPE r0 r1 r2 (f-resv0 0))
        (set r2 (eq SI r0 r1))
        ()
)

(dni cmpei "compare equal immediate" ()
        "cmpei $r1,$r0,$imm"  
        (+ OP_CMPEI r0 r1 imm)
        (set r1 (eq SI r0 (ext SI (trunc HI imm))))
        ()
)

(dni cmpg "compare greater than" ()
        "cmpg $r2,$r0,$r1"  
        (+ OP_CMPG r0 r1 r2 (f-resv0 0))
        (set r2 (gt SI r0 r1))
        ()
)

(dni cmpgi "compare greater than immediate" ()
        "cmpgi $r1,$r0,$imm"  
        (+ OP_CMPGI r0 r1 imm)
        (set r1 (gt SI r0 (ext SI (trunc HI imm))))
        ()
)

(dni cmpge "compare greater or equal" ()
        "cmpge $r2,$r0,$r1"  
        (+ OP_CMPGE r0 r1 r2 (f-resv0 0))
        (set r2 (ge SI r0 r1))
        ()
)

(dni cmpgei "compare greater or equal immediate" ()
        "cmpgei $r1,$r0,$imm"  
        (+ OP_CMPGEI r0 r1 imm)
        (set r1 (ge SI r0 (ext SI (trunc HI imm))))
        ()
)

(dni cmpgeu "compare greater or equal unsigned" ()
        "cmpgeu $r2,$r0,$r1"  
        (+ OP_CMPGEU r0 r1 r2 (f-resv0 0))
        (set r2 (geu SI r0 r1))
        ()
)

(dni cmpgeui "compare greater or equal unsigned immediate" ()
        "cmpgeui $r1,$r0,$uimm"  
        (+ OP_CMPGEUI r0 r1 uimm)
        (set r1 (geu SI r0 (zext SI uimm)))
        ()
)

(dni cmpgu "compare greater than unsigned" ()
        "cmpgu $r2,$r0,$r1"  
        (+ OP_CMPGU r0 r1 r2 (f-resv0 0))
        (set r2 (gtu SI r0 r1))
        ()
)

(dni cmpgui "compare greater than unsigned immediate" ()
        "cmpgui $r1,$r0,$uimm"  
        (+ OP_CMPGUI r0 r1 uimm)
        (set r1 (gtu SI r0 (zext SI uimm)))
        ()
)

(dni cmpne "compare not equal" ()
        "cmpne $r2,$r0,$r1"  
        (+ OP_CMPNE r0 r1 r2 (f-resv0 0))
        (set r2 (ne SI r0 r1))
        ()
)

(dni cmpnei "compare not equal immediate" ()
        "cmpnei $r1,$r0,$imm"  
        (+ OP_CMPNEI r0 r1 imm)
        (set r1 (ne SI r0 (ext SI (trunc HI imm))))
        ()
)

(dni divu "unsigned divide" ()
        "divu $r2,$r0,$r1"
        (+ OP_DIVU r0 r1 r2 (f-resv0 0))
        (set pc (c-call USI "@cpu@_divu_insn" pc f-r0 f-r1 f-r2))
        ()
)

(dni lb "load byte" ()
        "lb $r1,($r0+$imm)"
        (+ OP_LB r0 r1 imm)
        (set r1 (ext SI (mem QI (add r0 (ext SI (trunc HI imm))))))
        ()
)

(dni lbu "load byte unsigned" ()
        "lbu $r1,($r0+$imm)"
        (+ OP_LBU r0 r1 imm)
        (set r1 (zext SI (mem QI (add r0 (ext SI (trunc HI imm))))))
        ()
)

(dni lh "load halfword" ()
        "lh $r1,($r0+$imm)"
        (+ OP_LH r0 r1 imm)
        (set r1 (ext SI (mem HI (add r0 (ext SI (trunc HI imm))))))
        ()
)

(dni lhu "load halfword unsigned" ()
        "lhu $r1,($r0+$imm)"
        (+ OP_LHU r0 r1 imm)
        (set r1 (zext SI (mem HI (add r0 (ext SI (trunc HI imm))))))
        ()
)

(dni lw "load word" ()
        "lw $r1,($r0+$imm)"
        (+ OP_LW r0 r1 imm)
        (set r1 (mem SI (add r0 (ext SI (trunc HI imm)))))
        ()
)

(dni modu "unsigned modulus" ()
        "modu $r2,$r0,$r1"
        (+ OP_MODU r0 r1 r2 (f-resv0 0))
        (set pc (c-call USI "@cpu@_modu_insn" pc f-r0 f-r1 f-r2))
        ()
)

(dni mul "mulitply" ()
        "mul $r2,$r0,$r1"
        (+ OP_MUL r0 r1 r2 (f-resv0 0))
        (set r2 (mul r0 r1))
        ()
)

(dni muli "multiply immediate" ()
        "muli $r1,$r0,$imm"  
        (+ OP_MULI r0 r1 imm)
        (set r1 (mul r0 (ext SI (trunc HI imm))))
        ()
)

(dni nor "nor" ()
        "nor $r2,$r0,$r1"
        (+ OP_NOR r0 r1 r2 (f-resv0 0))
        (set r2 (inv (or r0 r1)))
        ()
)

(dni nori "nor immediate" ()
        "nori $r1,$r0,$uimm"  
        (+ OP_NORI r0 r1 uimm)
        (set r1 (inv (or r0 (zext SI uimm))))
        ()
)

(dni or "or" ()
        "or $r2,$r0,$r1"
        (+ OP_OR r0 r1 r2 (f-resv0 0))
        (set r2 (or r0 r1))
        ()
)

(dni ori "or immediate" ()
        "ori $r1,$r0,$lo16"  
        (+ OP_ORI r0 r1 lo16)
        (set r1 (or r0 (zext SI lo16)))
        ()
)

(dni orhii "or high immediate" ()
        "orhi $r1,$r0,$hi16"  
        (+ OP_ORHI r0 r1 hi16)
        (set r1 (or r0 (sll SI hi16 16)))
        ()
)

(dni rcsr "read control or status register" ()
        "rcsr $r2,$csr"
        (+ OP_RCSR csr (f-r1 0) r2 (f-resv0 0))
        (set r2 csr) 
        ()
)

(dni sb "store byte" ()
        "sb ($r0+$imm),$r1"
        (+ OP_SB r0 r1 imm)
        (set (mem QI (add r0 (ext SI (trunc HI imm)))) r1)
        ()
)

(dni sextb "sign extend byte" ()
        "sextb $r2,$r0"
        (+ OP_SEXTB r0 (f-r1 0) r2 (f-resv0 0))
        (set r2 (ext SI (trunc QI r0)))
        ()
)

(dni sexth "sign extend half-word" ()
        "sexth $r2,$r0"
        (+ OP_SEXTH r0 (f-r1 0) r2 (f-resv0 0))
        (set r2 (ext SI (trunc HI r0)))
        ()
)

(dni sh "store halfword" ()
        "sh ($r0+$imm),$r1"
        (+ OP_SH r0 r1 imm)
        (set (mem HI (add r0 (ext SI (trunc HI imm)))) r1)
        ()
)

(dni sl "shift left" ()
        "sl $r2,$r0,$r1"
        (+ OP_SL r0 r1 r2 (f-resv0 0))
        (set r2 (sll SI r0 r1))
        ()
)

(dni sli "shift left immediate" ()
        "sli $r1,$r0,$imm"  
        (+ OP_SLI r0 r1 imm)
        (set r1 (sll SI r0 imm))
        ()
)

(dni sr "shift right" ()
        "sr $r2,$r0,$r1"
        (+ OP_SR r0 r1 r2 (f-resv0 0))
        (set r2 (sra SI r0 r1))
        ()
)

(dni sri "shift right immediate" ()
        "sri $r1,$r0,$imm"  
        (+ OP_SRI r0 r1 imm)
        (set r1 (sra SI r0 imm))
        ()
)

(dni sru "shift right unsigned" ()
        "sru $r2,$r0,$r1"
        (+ OP_SRU r0 r1 r2 (f-resv0 0))
        (set r2 (srl SI r0 r1))
        ()
)

(dni srui "shift right unsigned immediate" ()
        "srui $r1,$r0,$imm"  
        (+ OP_SRUI r0 r1 imm)
        (set r1 (srl SI r0 imm))
        ()
)

(dni sub "subtract" ()
        "sub $r2,$r0,$r1"
        (+ OP_SUB r0 r1 r2 (f-resv0 0))
        (set r2 (sub r0 r1))
        ()
)

(dni sw "store word" ()
        "sw ($r0+$imm),$r1"
        (+ OP_SW r0 r1 imm)
        (set (mem SI (add r0 (ext SI (trunc HI imm)))) r1)
        ()
)

(dni user "user defined instruction" ()
        "user $r2,$r0,$r1,$user"
        (+ OP_USER r0 r1 r2 user)
        (set r2 (c-call SI "@cpu@_user_insn" r0 r1 user))
        ()
)

(dni wcsr "write control or status register" ()
        "wcsr $csr,$r1"
        (+ OP_WCSR csr r1 (f-r2 0) (f-resv0 0))
        (c-call VOID "@cpu@_wcsr_insn" f-csr r1) 
        ()
)
    
(dni xor "xor" ()
        "xor $r2,$r0,$r1"
        (+ OP_XOR r0 r1 r2 (f-resv0 0))
        (set r2 (xor r0 r1))
        ()
)

(dni xori "xor immediate" ()
        "xori $r1,$r0,$uimm"  
        (+ OP_XORI r0 r1 uimm)
        (set r1 (xor r0 (zext SI uimm)))
        ()
)

(dni xnor "xnor" ()
        "xnor $r2,$r0,$r1"
        (+ OP_XNOR r0 r1 r2 (f-resv0 0))
        (set r2 (inv (xor r0 r1)))
        ()
)

(dni xnori "xnor immediate" ()
        "xnori $r1,$r0,$uimm"  
        (+ OP_XNORI r0 r1 uimm)
        (set r1 (inv (xor r0 (zext SI uimm))))
        ()
)

; Pseudo instructions

(dni break "breakpoint" ()
        "break"
        (+ OP_RAISE (f-exception 2))
        (set pc (c-call USI "@cpu@_break_insn" pc))
        ()
)

(dni scall "system call" ()
        "scall"
        (+ OP_RAISE (f-exception 7))
        (set pc (c-call USI "@cpu@_scall_insn" pc))
        ()
)

(dni bret "return from breakpoint" (ALIAS)
        "bret"
        (+ OP_B (f-r0 31) (f-r1 0) (f-r2 0) (f-resv0 0))
        (set pc (c-call USI "@cpu@_bret_insn" r0))
        ()
)

(dni eret "return from exception" (ALIAS)
        "eret"
        (+ OP_B (f-r0 30) (f-r1 0) (f-r2 0) (f-resv0 0))
        (set pc (c-call USI "@cpu@_eret_insn" r0))
        ()
)
    
(dni ret "return" (ALIAS)
        "ret"
        (+ OP_B (f-r0 29) (f-r1 0) (f-r2 0) (f-resv0 0))
        (set pc r0)
        ()
)

(dni mv "move" (ALIAS)
        "mv $r2,$r0"
        (+ OP_OR r0 (f-r1 0) r2 (f-resv0 0))
        (set r2 r0)
        ()
)

(dni mvi "move immediate" (ALIAS)
        "mvi $r1,$imm"
        (+ OP_ADDI (f-r0 0) r1 imm)
        (set r1 (add r0 (ext SI (trunc HI imm))))
        ()
)

(dni mvui "move unsigned immediate" (ALIAS)
        "mvu $r1,$lo16"
        (+ OP_ORI (f-r0 0) r1 lo16)
        (set r1 (zext SI lo16))
        ()
)

(dni mvhi "move high immediate" (ALIAS)
        "mvhi $r1,$hi16"
        (+ OP_ORHI (f-r0 0) r1 hi16)
        (set r1 (or r0 (sll SI hi16 16)))
        ()
)

(dni mva "move address" (ALIAS)
        "mva $r1,$gp16"
        (+ OP_ADDI (f-r0 26) r1 gp16)
        (set r1 (add r0 (ext SI (trunc HI gp16))))
        ()
)

(dni not "not" (ALIAS)
        "not $r2,$r0"
        (+ OP_XNOR r0 (f-r1 0) r2 (f-resv0 0))
        (set r2 (inv r0))
        ()
)

(dni nop "nop" (ALIAS)
        "nop"
        (+ OP_ADDI (f-r0 0) (f-r1 0) (f-imm 0))
        (set r0 r0)
        ()
)

(dni lbgprel "load byte gp relative" (ALIAS)
        "lb $r1,$gp16"
        (+ OP_LB (f-r0 26) r1 gp16)
        (set r1 (ext SI (mem QI (add r0 (ext SI (trunc HI gp16))))))
        ()
)

(dni lbugprel "load byte unsigned gp relative" (ALIAS)
        "lbu $r1,$gp16"
        (+ OP_LBU (f-r0 26) r1 gp16)
        (set r1 (zext SI (mem QI (add r0 (ext SI (trunc HI gp16))))))
        ()
)

(dni lhgprel "load halfword gp relative" (ALIAS)
        "lh $r1,$gp16"
        (+ OP_LH (f-r0 26) r1 gp16)
        (set r1 (ext SI (mem HI (add r0 (ext SI (trunc HI gp16))))))
        ()
)

(dni lhugprel "load halfword unsigned gp relative" (ALIAS)
        "lhu $r1,$gp16"
        (+ OP_LHU (f-r0 26) r1 gp16)
        (set r1 (zext SI (mem HI (add r0 (ext SI (trunc HI gp16))))))
        ()
)

(dni lwgprel "load word gp relative" (ALIAS)
        "lw $r1,$gp16"
        (+ OP_LW (f-r0 26) r1 gp16)
        (set r1 (mem SI (add r0 (ext SI (trunc HI gp16)))))
        ()
)

(dni sbgprel "store byte gp relative" (ALIAS)
        "sb $gp16,$r1"
        (+ OP_SB (f-r0 26) r1 gp16)
        (set (mem QI (add r0 (ext SI (trunc HI gp16)))) r1)
        ()
)

(dni shgprel "store halfword gp relative" (ALIAS)
        "sh $gp16,$r1"
        (+ OP_SH (f-r0 26) r1 gp16)
        (set (mem HI (add r0 (ext SI (trunc HI gp16)))) r1)
        ()
)

(dni swgprel "store word gp relative" (ALIAS)
        "sw $gp16,$r1"
        (+ OP_SW (f-r0 26) r1 gp16)
        (set (mem SI (add r0 (ext SI (trunc HI gp16)))) r1)
        ()
)

(dni lwgotrel "load word got relative" (ALIAS)
        "lw $r1,(gp+$got16)"
        (+ OP_LW (f-r0 26) r1 got16)
        (set r1 (mem SI (add r0 (ext SI (trunc HI got16)))))
        ()
)

(dni orhigotoffi "or high got offset immediate" (ALIAS)
        "orhi $r1,$r0,$gotoffhi16"  
        (+ OP_ORHI r0 r1 gotoffhi16)
        (set r1 (or r0 (sll SI gotoffhi16 16)))
        ()
)

(dni addgotoff "add got offset" (ALIAS)
        "addi $r1,$r0,$gotofflo16"  
        (+ OP_ADDI r0 r1 gotofflo16)
        (set r1 (add r0 (ext SI (trunc HI gotofflo16))))
        ()
)

(dni swgotoff "store word got offset" (ALIAS)
        "sw ($r0+$gotofflo16),$r1"
        (+ OP_SW r0 r1 gotofflo16)
        (set (mem SI (add r0 (ext SI (trunc HI gotofflo16)))) r1)
        ()
)

(dni lwgotoff "load word got offset" (ALIAS)
        "lw $r1,($r0+$gotofflo16)"
        (+ OP_LW r0 r1 gotofflo16)
        (set r1 (mem SI (add r0 (ext SI (trunc HI gotofflo16)))))
        ()
)

(dni shgotoff "store half word got offset" (ALIAS)
        "sh ($r0+$gotofflo16),$r1"
        (+ OP_SH r0 r1 gotofflo16)
        (set (mem HI (add r0 (ext SI (trunc HI gotofflo16)))) r1)
        ()
)

(dni lhgotoff "load half word got offset" (ALIAS)
        "lh $r1,($r0+$gotofflo16)"
        (+ OP_LH r0 r1 gotofflo16)
        (set r1 (ext SI (mem HI (add r0 (ext SI (trunc HI gotofflo16))))))
        ()
)

(dni lhugotoff "load half word got offset unsigned" (ALIAS)
        "lhu $r1,($r0+$gotofflo16)"
        (+ OP_LHU r0 r1 gotofflo16)
        (set r1 (zext SI (mem HI (add r0 (ext SI (trunc HI gotofflo16))))))
        ()
)

(dni sbgotoff "store byte got offset" (ALIAS)
        "sb ($r0+$gotofflo16),$r1"
        (+ OP_SB r0 r1 gotofflo16)
        (set (mem QI (add r0 (ext SI (trunc HI gotofflo16)))) r1)
        ()
)

(dni lbgotoff "load byte got offset" (ALIAS)
        "lb $r1,($r0+$gotofflo16)"
        (+ OP_LB r0 r1 gotofflo16)
        (set r1 (ext SI (mem QI (add r0 (ext SI (trunc HI gotofflo16))))))
        ()
)

(dni lbugotoff "load byte got offset unsigned" (ALIAS)
        "lbu $r1,($r0+$gotofflo16)"
        (+ OP_LBU r0 r1 gotofflo16)
        (set r1 (zext SI (mem QI (add r0 (ext SI (trunc HI gotofflo16))))))
        ()
)