riscv-utils

Scheme utility procedures for the RISC-V instruction set architecture

git clone https://git.8pit.net/riscv-utils.git

 1(import srfi-151)
 2
 3;; Size of instruction in bits.
 4;; XXX: Compressed instructions currently not supported.
 5(define INSTR_SIZE 32)
 6
 7;; Wrapper around bit-field to support the imm[end:start]
 8;; syntax used in the RISC-V specification.
 9(define (imm-field instr end start)
10  (bit-field instr start (+ end 1)))
11(define (imm-field-single instr pos)
12  (imm-field instr pos pos))
13
14(define (to-twocomp numbits input)
15  (let ((max (/ (expt 2 numbits) 2)))
16    (if (or (>= input max)
17            (< input (* -1 max)))
18      (error "given signed value too large for field")
19      (if (negative? input)
20        (+ (expt 2 numbits) input)
21        input))))
22
23(define (new-field value size position)
24  (if (> value (- (expt 2 size) 1))
25    (error "given value too large for field")
26    (arithmetic-shift value position)))
27
28(define-syntax new-instr
29  (syntax-rules (field)
30    ((new-instr N (field val siz))
31     (new-field val siz (- N siz)))
32    ((new-instr N (field val siz) fields ...)
33     (bitwise-ior
34       (new-instr N (field val siz))
35       (new-instr (- N siz) fields ...)))))
36
37(define (r-type opcode funct3 funct7
38          rs1 rs2 rd)
39  (new-instr INSTR_SIZE
40    (field funct7 7)
41    (field rs2 5)
42    (field rs1 5)
43    (field funct3 3)
44    (field rd 5)
45    (field opcode 7)))
46
47(define (i-type opcode funct3 rs1 rd imm)
48  (let ((imm-signed (to-twocomp 12 imm)))
49    (new-instr INSTR_SIZE
50      (field imm-signed 12)
51      (field rs1 5)
52      (field funct3 3)
53      (field rd 5)
54      (field opcode 7))))
55
56(define (s-type opcode funct3 rs1 rs2 imm)
57  (let ((imm-signed (to-twocomp 12 imm)))
58    (new-instr INSTR_SIZE
59      (field (imm-field imm-signed 11 5) 7)
60      (field rs2 5)
61      (field rs1 5)
62      (field funct3 3)
63      (field (imm-field imm-signed 4 0) 5)
64      (field opcode 7))))
65
66(define (b-type opcode funct3 rs1 rs2 imm)
67  (let ((imm-signed (to-twocomp 12 imm)))
68    (new-instr INSTR_SIZE
69      (field (imm-field-single imm-signed 12) 1)
70      (field (imm-field imm-signed 10 5) 6)
71      (field rs2 5)
72      (field rs1 5)
73      (field funct3 3)
74      (field (imm-field imm-signed 4 1) 4)
75      (field (imm-field-single imm-signed 11) 1)
76      (field opcode 7))))
77
78(define (u-type opcode rd imm)
79  (new-instr INSTR_SIZE
80    (field imm 20)
81    (field rd 5)
82    (field opcode 7)))
83
84(define (j-type opcode rd imm)
85  (new-instr INSTR_SIZE
86    (field (imm-field-single imm 20) 1)
87    (field (imm-field imm 10 1) 10)
88    (field (imm-field-single imm 11) 1)
89    (field (imm-field imm 19 12) 8)
90    (field rd 5)
91    (field opcode 7)))