@@ -7,6 +7,14 @@ macro_rules! bitcat {
77 ( bitcat! { acc( $a) $b( $e) } | bitcat! { acc( $a - $b) $( $rest) + } )
88 } ;
99
10+ ( acc( $a: expr) signed $b: literal( $e: expr) , $( $rest: tt) + ) => {
11+ ( bitcat! { acc( $a) signed $b( $e) } | bitcat! { acc( $a - $b) $( $rest) + } )
12+ } ;
13+
14+ ( acc( $a: expr) signed $b: literal( $e: expr) ) => {
15+ ( i32_to_iN:: <$b>( $e) ) << const { $a - $b }
16+ } ;
17+
1018 ( acc( $a: expr) $b: literal( $e: expr) ) => {
1119 ( $e as u32 & const { ( 1 << $b) - 1 } ) << const { $a - $b }
1220 } ;
@@ -16,126 +24,193 @@ macro_rules! bitcat {
1624 } ;
1725}
1826
27+ macro_rules! bits {
28+ ( $start: literal .. $end: literal, $num: expr) => {
29+ ( $num >> $start) & ( ( 1 << ( $end - $start) ) - 1 )
30+ } ;
31+
32+ ( $start: literal ..= $end: literal, $num: expr) => {
33+ ( $num >> $start) & ( ( 1 << ( $end - $start + 1 ) ) - 1 )
34+ } ;
35+
36+ ( $bit: literal, $num: expr) => {
37+ ( $num >> $bit) & 1
38+ } ;
39+ }
40+
41+ #[ allow( non_snake_case) ]
42+ fn i32_to_iN < const N : u32 > ( from : i32 ) -> u32 {
43+ let lower_bits = ( 1 << ( N - 1 ) ) - 1 ;
44+
45+ if from. is_negative ( ) {
46+ ( from as u32 ) & lower_bits | ( 1 << ( N - 1 ) )
47+ } else {
48+ ( from as u32 ) & lower_bits
49+ }
50+ }
51+
52+ #[ test]
53+ fn test_i32_reinterpret ( ) {
54+ assert_eq ! ( i32_to_iN:: <4 >( -1 ) , 0b1111 ) ;
55+ assert_eq ! ( i32_to_iN:: <5 >( -1 ) , 0b11111 ) ;
56+ assert_eq ! ( i32_to_iN:: <4 >( -2 ) , 0b1110 ) ;
57+ assert_eq ! ( i32_to_iN:: <4 >( 1 ) , 0b0001 ) ;
58+ assert_eq ! ( i32_to_iN:: <4 >( 0 ) , 0b0000 ) ;
59+ assert_eq ! ( i32_to_iN:: <4 >( -3 ) , 0b1101 ) ;
60+ assert_eq ! ( i32_to_iN:: <4 >( -4 ) , 0b1100 ) ;
61+ assert_eq ! ( i32_to_iN:: <4 >( 2 ) , 0b0010 ) ;
62+ assert_eq ! ( i32_to_iN:: <4 >( 3 ) , 0b0011 ) ;
63+ assert_eq ! ( i32_to_iN:: <5 >( -16 ) , 0b10000 ) ;
64+ assert_eq ! ( i32_to_iN:: <5 >( -15 ) , 0b10001 ) ;
65+ assert_eq ! ( i32_to_iN:: <5 >( 15 ) , 0b01111 ) ;
66+ assert_eq ! ( i32_to_iN:: <6 >( -32 ) , 0b100000 ) ;
67+ assert_eq ! ( i32_to_iN:: <6 >( 31 ) , 0b011111 ) ;
68+ }
69+
70+ #[ test]
71+ #[ rustfmt:: skip]
72+ fn test_bitcat_signed ( ) {
73+ assert_eq ! ( bitcat! { acc( 8 ) signed 4 ( 0 ) , 4 ( 0 ) } , 0b0000_0000 ) ;
74+ assert_eq ! ( bitcat! { acc( 8 ) signed 4 ( -1 ) , 4 ( 0 ) } , 0b1111_0000 ) ;
75+ assert_eq ! ( bitcat! { acc( 8 ) signed 4 ( -2 ) , 4 ( 1 ) } , 0b1110_0001 ) ;
76+ assert_eq ! ( bitcat! { acc( 8 ) signed 4 ( 2 ) , 4 ( 3 ) } , 0b0010_0011 ) ;
77+ assert_eq ! ( bitcat! { acc( 8 ) signed 5 ( -16 ) , 3 ( 7 ) } , 0b10000_111 ) ;
78+ assert_eq ! ( bitcat! { acc( 8 ) signed 6 ( -32 ) , 2 ( 3 ) } , 0b100000_11 ) ;
79+ assert_eq ! ( bitcat! { acc( 16 ) signed 8 ( -128 ) , 8 ( 255 ) } , 0b10000000_11111111 ) ;
80+ assert_eq ! ( bitcat! { acc( 16 ) signed 12 ( -2048 ) , 4 ( 15 ) } , 0b100000000000_1111 ) ;
81+ assert_eq ! ( bitcat! { acc( 32 ) signed 20 ( -524288 ) , 12 ( 0xFFF ) } , 0b10000000000000000000_111111111111 ) ;
82+ }
83+
1984pub ( crate ) use bitcat;
2085
2186#[ inline]
22- pub fn lui ( rd : u8 , imm : u32 ) -> u32 {
23- bitcat ! { 20 ( imm) , 5 ( rd) , 7 ( 0b0110111 ) }
87+ pub fn lui ( rd : u8 , imm : i32 ) -> u32 {
88+ bitcat ! { signed 20 ( imm) , 5 ( rd) , 7 ( 0b0110111 ) }
2489}
2590
2691#[ inline]
27- pub fn auipc ( rd : u8 , imm : u32 ) -> u32 {
28- bitcat ! { 20 ( imm) , 5 ( rd) , 7 ( 0b0010111 ) }
92+ pub fn auipc ( rd : u8 , imm : i32 ) -> u32 {
93+ bitcat ! { signed 20 ( imm) , 5 ( rd) , 7 ( 0b0010111 ) }
2994}
3095
3196#[ inline]
32- pub fn jal ( rd : u8 , imm : u32 ) -> u32 {
97+ pub fn jal ( rd : u8 , imm : i32 ) -> u32 {
98+ let imm = i32_to_iN :: < 20 > ( imm) ;
3399 bitcat ! { 1 ( imm >> 20 ) , 10 ( imm >> 1 ) , 1 ( imm >> 11 ) , 8 ( imm >> 12 ) , 5 ( rd) , 7 ( 0b1101111 ) }
34100}
35101
36102#[ inline]
37- pub fn jalr ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
38- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b1100111 ) }
103+ pub fn jalr ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
104+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b1100111 ) }
39105}
40106
41107#[ inline]
42- pub fn beq ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
108+ pub fn beq ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
109+ let imm = i32_to_iN :: < 12 > ( imm) ;
43110 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b000 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
44111}
45112
46113#[ inline]
47- pub fn bne ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
114+ pub fn bne ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
115+ let imm = i32_to_iN :: < 12 > ( imm) ;
48116 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b001 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
49117}
50118
51119#[ inline]
52- pub fn blt ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
120+ pub fn blt ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
121+ let imm = i32_to_iN :: < 12 > ( imm) ;
53122 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b100 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
54123}
55124
56125#[ inline]
57- pub fn bge ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
126+ pub fn bge ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
127+ let imm = i32_to_iN :: < 12 > ( imm) ;
58128 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b101 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
59129}
60130
61131#[ inline]
62- pub fn bltu ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
132+ pub fn bltu ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
133+ let imm = i32_to_iN :: < 12 > ( imm) ;
63134 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b110 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
64135}
65136
66137#[ inline]
67- pub fn bgeu ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
138+ pub fn bgeu ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
139+ let imm = i32_to_iN :: < 12 > ( imm) ;
68140 bitcat ! { 1 ( imm >> 12 ) , 6 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b111 ) , 4 ( imm >> 1 ) , 1 ( imm >> 11 ) , 7 ( 0b1100011 ) }
69141}
70142
71143#[ inline]
72- pub fn lb ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
73- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b0000011 ) }
144+ pub fn lb ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
145+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b0000011 ) }
74146}
75147
76148#[ inline]
77- pub fn lh ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
78- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b001 ) , 5 ( rd) , 7 ( 0b0000011 ) }
149+ pub fn lh ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
150+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b001 ) , 5 ( rd) , 7 ( 0b0000011 ) }
79151}
80152
81153#[ inline]
82- pub fn lw ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
83- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b010 ) , 5 ( rd) , 7 ( 0b0000011 ) }
154+ pub fn lw ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
155+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b010 ) , 5 ( rd) , 7 ( 0b0000011 ) }
84156}
85157
86158#[ inline]
87- pub fn lbu ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
88- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b100 ) , 5 ( rd) , 7 ( 0b0000011 ) }
159+ pub fn lbu ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
160+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b100 ) , 5 ( rd) , 7 ( 0b0000011 ) }
89161}
90162
91163#[ inline]
92- pub fn lhu ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
164+ pub fn lhu ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
93165 bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b101 ) , 5 ( rd) , 7 ( 0b0000011 ) }
94166}
95167
96168#[ inline]
97- pub fn sb ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
169+ pub fn sb ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
170+ let imm = i32_to_iN :: < 12 > ( imm) ;
98171 bitcat ! { 7 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( imm) , 7 ( 0b0100011 ) }
99172}
100173
101174#[ inline]
102- pub fn sh ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
175+ pub fn sh ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
176+ let imm = i32_to_iN :: < 12 > ( imm) ;
103177 bitcat ! { 7 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b001 ) , 5 ( imm) , 7 ( 0b0100011 ) }
104178}
105179
106180#[ inline]
107- pub fn sw ( rs1 : u8 , rs2 : u8 , imm : u16 ) -> u32 {
181+ pub fn sw ( rs1 : u8 , rs2 : u8 , imm : i32 ) -> u32 {
182+ let imm = i32_to_iN :: < 12 > ( imm) ;
108183 bitcat ! { 7 ( imm >> 5 ) , 5 ( rs2) , 5 ( rs1) , 3 ( 0b010 ) , 5 ( imm) , 7 ( 0b0100011 ) }
109184}
110185
111186#[ inline]
112- pub fn addi ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
113- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b0010011 ) }
187+ pub fn addi ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
188+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b000 ) , 5 ( rd) , 7 ( 0b0010011 ) }
114189}
115190
116191#[ inline]
117- pub fn slti ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
118- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b010 ) , 5 ( rd) , 7 ( 0b0010011 ) }
192+ pub fn slti ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
193+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b010 ) , 5 ( rd) , 7 ( 0b0010011 ) }
119194}
120195
121196#[ inline]
122- pub fn sltiu ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
123- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b011 ) , 5 ( rd) , 7 ( 0b0010011 ) }
197+ pub fn sltiu ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
198+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b011 ) , 5 ( rd) , 7 ( 0b0010011 ) }
124199}
125200
126201#[ inline]
127- pub fn xori ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
128- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b100 ) , 5 ( rd) , 7 ( 0b0010011 ) }
202+ pub fn xori ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
203+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b100 ) , 5 ( rd) , 7 ( 0b0010011 ) }
129204}
130205
131206#[ inline]
132- pub fn ori ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
133- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b110 ) , 5 ( rd) , 7 ( 0b0010011 ) }
207+ pub fn ori ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
208+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b110 ) , 5 ( rd) , 7 ( 0b0010011 ) }
134209}
135210
136211#[ inline]
137- pub fn andi ( rd : u8 , rs1 : u8 , imm : u16 ) -> u32 {
138- bitcat ! { 12 ( imm) , 5 ( rs1) , 3 ( 0b111 ) , 5 ( rd) , 7 ( 0b0010011 ) }
212+ pub fn andi ( rd : u8 , rs1 : u8 , imm : i32 ) -> u32 {
213+ bitcat ! { signed 12 ( imm) , 5 ( rs1) , 3 ( 0b111 ) , 5 ( rd) , 7 ( 0b0010011 ) }
139214}
140215
141216#[ inline]
@@ -229,7 +304,7 @@ pub fn mv(rd: u8, rs: u8) -> u32 {
229304}
230305
231306#[ inline]
232- pub fn j ( imm : u32 ) -> u32 {
307+ pub fn j ( imm : i32 ) -> u32 {
233308 jal ( 0 , imm)
234309}
235310
@@ -244,6 +319,6 @@ pub fn jal_r(rd: u8, rs1: u8) -> u32 {
244319}
245320
246321#[ inline]
247- pub fn call ( imm : u32 ) -> u32 {
322+ pub fn call ( imm : i32 ) -> u32 {
248323 jal ( 1 , imm)
249324}
0 commit comments