#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1)) #define EXTRACT_RVC_J_IMM(x) \ �� ((RV_X(x, 3, 3) << 1) | \ �� (RV_X(x, 11, 1) << 4) | \ �� (RV_X(x, 2, 1) << 5) | \ �� (RV_X(x, 7, 1) << 6) | \ �� (RV_X(x, 6, 1) << 7) | \ �� (RV_X(x, 9, 2) << 8) | \ �� (RV_X(x, 8, 1) << 10) | \ �� (-RV_X(x, 12, 1) << 11))
template <typename T, unsigned B>
inline T sign_extend(const T x)
{
struct {
T x:B;
} s;
return s.x = x;
}
imm11=
((inst >> 2) & 0b10110100000) |
((inst << 3) & 0b01000000000) |
((inst >> 0) & 0b00001000000) |
((inst << 2) & 0b00000010000) |
((inst >> 8) & 0b00000001000) |
((inst >> 3) & 0b00000000111)
imm11 = sign_extend<signed int,11>(immm11) << 1
mov eax, edi shr eax, 2 and eax, 1440 mov ecx, edi and ecx, 64 lea esi, [8*rcx] lea r8d, [4*rdi] and r8d, 16 mov edx, edi shr edx, 8 and edx, 8 shr edi, 3 and edi, 7 or esi, ecx or esi, eax or esi, r8d or esi, edx or esi, edi shl esi, 21 sar esi, 20
mov eax, edi shr eax, 2 and eax, 14 mov ecx, edi shr ecx, 7 and ecx, 16 or ecx, eax lea eax, [8*rdi] and eax, 32 or eax, ecx mov ecx, edi shr ecx mov edx, ecx and edx, 64 or eax, edx mov edx, edi and edx, 64 shl edx, 1 or eax, edx and ecx, 768 or eax, ecx lea esi, [4*rdi] and esi, 1024 or esi, eax shr edi, 12 and edi, 1 neg edi shl edi, 11 or esi, edi
shl esi, 21 sar esi, 20
Not sure if this helps or is relevant, but here's how I implement sign extension in my emulator.�� If I want to sign extend x from bit 11, then I'd write x | -(x & 2048).�� This should expand to at most three instructions (maybe 4 on RISC-V).
Although i had the imm11 in the lower 11 bits and gcc has folded the <<
1 (for CJ format) into the shl/sar for the sign extension.
C.J, C.JAL imm11 offset[11|4|9:8|10|6|7|3:1|5]
I see where my confusion is now. It's with my reading of the notation. I was expecting a range of 3 bits in the right hand position based on reading the macro. 0b1110
Now I understand the convention. I didn't have this problem with the notation in the ISA Spec. It's a little confusing as I was interpreting the offset in the spec encoding as if it where in the physical bit location. i.e. reading right to left, bit 5 as the LSB.
It does actually say 3:1 only in my read it was in position 4:2 and bit 5 was in the LSB (not the LST at bit offset 5).
The Compressed Spec could do with some text on the immediate offset encoding notation (or I have overlooked it). Feedback: I found it much harder to read than the main ISA spec. If I can come up with some concise text describing the notation I will share it.
I follow now and my decoder is working. Thanks for taking the time.
$ more immj.c
#include <stdio.h>
#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
#define EXTRACT_RVC_J_IMM(x) \
((RV_X(x, 3, 3) << 1) | \
(RV_X(x, 11, 1) << 4) | \
(RV_X(x, 2, 1) << 5) | \
(RV_X(x, 7, 1) << 6) | \
(RV_X(x, 6, 1) << 7) | \
(RV_X(x, 9, 2) << 8) | \
(RV_X(x, 8, 1) << 10) | \
(-RV_X(x, 12, 1) << 11))
int main()
{
printf("%04x\n", (RV_X(0xffff, 3, 3) << 1));
}
$ gcc immj.c -o immj
$ ./immj
000e