code wiki / _hdl_build / nx_rvc_expand.nx

nx_rvc_expand.nx source

↩ module page · 144 lines · 8287 B

1// nx_rvc_expand.nx -- RV64 C (compressed) extension expander: takes a 16-bit compressed instruction and returns the 2// equivalent 32-bit base instruction word (so the existing 32-bit decoder/execute path runs it unchanged). Covers the 3// common INTEGER RVC encodings gcc emits (quadrants 0/1/2; float c.f* skipped). Returns 0 for unsupported/illegal. 4// A 16-bit halfword is compressed iff (h & 3) != 3. Validated by differential test vs qemu-system-riscv64. 5import "nx_syscalls.nx" 6 7// ---- 32-bit base-instruction encoders (match the RV64 formats) ---- 8func rvc_i(op: i64, f3: i64, rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | ((rs1 & 0x1F) << 15) | ((f3 & 7) << 12) | ((rd & 0x1F) << 7) | op } 9func rvc_r(op: i64, f3: i64, f7: i64, rd: i64, rs1: i64, rs2: i64) -> i64 { return ((f7 & 0x7F) << 25) | ((rs2 & 0x1F) << 20) | ((rs1 & 0x1F) << 15) | ((f3 & 7) << 12) | ((rd & 0x1F) << 7) | op } 10func rvc_s(op: i64, f3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 { return (((imm >> 5) & 0x7F) << 25) | ((rs2 & 0x1F) << 20) | ((rs1 & 0x1F) << 15) | ((f3 & 7) << 12) | ((imm & 0x1F) << 7) | op } 11func rvc_b(f3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 { return (((imm>>12)&1)<<31) | (((imm>>5)&0x3F)<<25) | ((rs2&0x1F)<<20) | ((rs1&0x1F)<<15) | ((f3&7)<<12) | (((imm>>1)&0xF)<<8) | (((imm>>11)&1)<<7) | 0x63 } 12func rvc_u(op: i64, rd: i64, imm: i64) -> i64 { return (imm & 0xFFFFF000) | ((rd & 0x1F) << 7) | op } 13func rvc_j(rd: i64, imm: i64) -> i64 { return (((imm>>20)&1)<<31) | (((imm>>1)&0x3FF)<<21) | (((imm>>11)&1)<<20) | (((imm>>12)&0xFF)<<12) | ((rd&0x1F)<<7) | 0x6F } 14func rvc_sext(v: i64, bits: i64) -> i64 { let m: i64 = 1 << (bits-1); if (v & m) != 0 { return v - (1 << bits) } return v } 15func rvc_bit(h: i64, b: i64) -> i64 { return (h >> b) & 1 } 16 17// is this 16-bit halfword a compressed instruction? (low 2 bits != 11) 18func nx_rvc_is_compressed(h: i64) -> i64 { if (h & 3) == 3 { return 0 } return 1 } 19 20// expand a 16-bit compressed instruction h -> 32-bit equivalent (or 0 if unsupported/illegal). 21func nx_rvc_expand(h: i64) -> i64 { 22 let op: i64 = h & 3 23 let f3: i64 = (h >> 13) & 7 24 let rdp: i64 = 8 + ((h >> 2) & 7) // rd'/rs2' (bits 4:2) 25 let rs1p: i64 = 8 + ((h >> 7) & 7) // rs1'/rd' (bits 9:7) 26 let rd: i64 = (h >> 7) & 0x1F // full 5-bit rd/rs1 27 let rs2: i64 = (h >> 2) & 0x1F // full 5-bit rs2 28 29 if op == 0 { // ---- Quadrant 0 ---- 30 if f3 == 0 { // c.addi4spn -> addi rd', x2, nzuimm 31 let nz: i64 = (((h>>7)&0xF)<<6) | (((h>>11)&3)<<4) | (rvc_bit(h,5)<<3) | (rvc_bit(h,6)<<2) 32 if nz == 0 { return 0 } // reserved 33 return rvc_i(0x13, 0, rdp, 2, nz) 34 } 35 if f3 == 2 { // c.lw -> lw rd', uimm(rs1') 36 let u: i64 = (((h>>10)&7)<<3) | (rvc_bit(h,6)<<2) | (rvc_bit(h,5)<<6) 37 return rvc_i(0x03, 2, rdp, rs1p, u) 38 } 39 if f3 == 3 { // c.ld -> ld rd', uimm(rs1') 40 let u: i64 = (((h>>10)&7)<<3) | (((h>>5)&3)<<6) 41 return rvc_i(0x03, 3, rdp, rs1p, u) 42 } 43 if f3 == 6 { // c.sw -> sw rs2', uimm(rs1') 44 let u: i64 = (((h>>10)&7)<<3) | (rvc_bit(h,6)<<2) | (rvc_bit(h,5)<<6) 45 return rvc_s(0x23, 2, rs1p, rdp, u) 46 } 47 if f3 == 7 { // c.sd -> sd rs2', uimm(rs1') 48 let u: i64 = (((h>>10)&7)<<3) | (((h>>5)&3)<<6) 49 return rvc_s(0x23, 3, rs1p, rdp, u) 50 } 51 return 0 52 } 53 if op == 1 { // ---- Quadrant 1 ---- 54 if f3 == 0 { // c.addi -> addi rd, rd, nzimm (rd may be 0 => c.nop) 55 let im: i64 = rvc_sext((rvc_bit(h,12)<<5) | ((h>>2)&0x1F), 6) 56 return rvc_i(0x13, 0, rd, rd, im) 57 } 58 if f3 == 1 { // c.addiw -> addiw rd, rd, imm (rd != 0) 59 let im: i64 = rvc_sext((rvc_bit(h,12)<<5) | ((h>>2)&0x1F), 6) 60 return rvc_i(0x1B, 0, rd, rd, im) 61 } 62 if f3 == 2 { // c.li -> addi rd, x0, imm 63 let im: i64 = rvc_sext((rvc_bit(h,12)<<5) | ((h>>2)&0x1F), 6) 64 return rvc_i(0x13, 0, rd, 0, im) 65 } 66 if f3 == 3 { 67 if rd == 2 { // c.addi16sp -> addi x2, x2, nzimm 68 let im: i64 = rvc_sext((rvc_bit(h,12)<<9) | (((h>>3)&3)<<7) | (rvc_bit(h,5)<<6) | (rvc_bit(h,2)<<5) | (rvc_bit(h,6)<<4), 10) 69 if im == 0 { return 0 } 70 return rvc_i(0x13, 0, 2, 2, im) 71 } 72 // c.lui -> lui rd, nzimm (imm in [31:12], sign-extended from bit 17) 73 let im20: i64 = rvc_sext((rvc_bit(h,12)<<17) | (((h>>2)&0x1F)<<12), 18) 74 if im20 == 0 { return 0 } 75 return rvc_u(0x37, rd, im20 & 0xFFFFF000) 76 } 77 if f3 == 4 { // misc-ALU 78 let sub: i64 = (h >> 10) & 3 79 let shamt: i64 = (rvc_bit(h,12)<<5) | ((h>>2)&0x1F) 80 if sub == 0 { return rvc_i(0x13, 5, rs1p, rs1p, shamt) } // c.srli (SRLI: f7=0) 81 if sub == 1 { return rvc_i(0x13, 5, rs1p, rs1p, 0x400 | shamt) } // c.srai (SRAI: bit30 set) 82 if sub == 2 { let im: i64 = rvc_sext((rvc_bit(h,12)<<5)|((h>>2)&0x1F),6); return rvc_i(0x13, 7, rs1p, rs1p, im) } // c.andi 83 // sub == 3: register ops 84 let b12: i64 = rvc_bit(h,12); let hi: i64 = (h >> 5) & 3 85 if b12 == 0 { 86 if hi == 0 { return rvc_r(0x33, 0, 0x20, rs1p, rs1p, rdp) } // c.sub 87 if hi == 1 { return rvc_r(0x33, 4, 0, rs1p, rs1p, rdp) } // c.xor 88 if hi == 2 { return rvc_r(0x33, 6, 0, rs1p, rs1p, rdp) } // c.or 89 return rvc_r(0x33, 7, 0, rs1p, rs1p, rdp) // c.and 90 } 91 if hi == 0 { return rvc_r(0x3B, 0, 0x20, rs1p, rs1p, rdp) } // c.subw 92 if hi == 1 { return rvc_r(0x3B, 0, 0, rs1p, rs1p, rdp) } // c.addw 93 return 0 94 } 95 if f3 == 5 { // c.j -> jal x0, offset 96 let off: i64 = rvc_sext((rvc_bit(h,12)<<11)|(rvc_bit(h,8)<<10)|(((h>>9)&3)<<8)|(rvc_bit(h,6)<<7)|(rvc_bit(h,7)<<6)|(rvc_bit(h,2)<<5)|(rvc_bit(h,11)<<4)|(((h>>3)&7)<<1), 12) 97 return rvc_j(0, off) 98 } 99 if f3 == 6 { // c.beqz -> beq rs1', x0, offset 100 let off: i64 = rvc_sext((rvc_bit(h,12)<<8)|(((h>>10)&3)<<3)|(((h>>5)&3)<<6)|(((h>>3)&3)<<1)|(rvc_bit(h,2)<<5), 9) 101 return rvc_b(0, rs1p, 0, off) 102 } 103 if f3 == 7 { // c.bnez -> bne rs1', x0, offset 104 let off: i64 = rvc_sext((rvc_bit(h,12)<<8)|(((h>>10)&3)<<3)|(((h>>5)&3)<<6)|(((h>>3)&3)<<1)|(rvc_bit(h,2)<<5), 9) 105 return rvc_b(1, rs1p, 0, off) 106 } 107 return 0 108 } 109 if op == 2 { // ---- Quadrant 2 ---- 110 if f3 == 0 { // c.slli -> slli rd, rd, shamt 111 let shamt: i64 = (rvc_bit(h,12)<<5) | ((h>>2)&0x1F) 112 return rvc_i(0x13, 1, rd, rd, shamt) 113 } 114 if f3 == 2 { // c.lwsp -> lw rd, uimm(x2) 115 let u: i64 = (rvc_bit(h,12)<<5) | (((h>>4)&7)<<2) | (((h>>2)&3)<<6) 116 return rvc_i(0x03, 2, rd, 2, u) 117 } 118 if f3 == 3 { // c.ldsp -> ld rd, uimm(x2) 119 let u: i64 = (rvc_bit(h,12)<<5) | (((h>>5)&3)<<3) | (((h>>2)&7)<<6) 120 return rvc_i(0x03, 3, rd, 2, u) 121 } 122 if f3 == 4 { // c.jr / c.mv / c.ebreak / c.jalr / c.add 123 let b12: i64 = rvc_bit(h,12) 124 if b12 == 0 { 125 if rs2 == 0 { return rvc_i(0x67, 0, 0, rd, 0) } // c.jr -> jalr x0, 0(rs1) 126 return rvc_r(0x33, 0, 0, rd, 0, rs2) // c.mv -> add rd, x0, rs2 127 } 128 if rd == 0 { if rs2 == 0 { return 0x00100073 } } // c.ebreak 129 if rs2 == 0 { return rvc_i(0x67, 0, 1, rd, 0) } // c.jalr -> jalr x1, 0(rs1) 130 return rvc_r(0x33, 0, 0, rd, rd, rs2) // c.add -> add rd, rd, rs2 131 } 132 if f3 == 6 { // c.swsp -> sw rs2, uimm(x2) 133 let u: i64 = (((h>>9)&0xF)<<2) | (((h>>7)&3)<<6) 134 return rvc_s(0x23, 2, 2, rs2, u) 135 } 136 if f3 == 7 { // c.sdsp -> sd rs2, uimm(x2) 137 let u: i64 = (((h>>10)&7)<<3) | (((h>>7)&7)<<6) 138 return rvc_s(0x23, 3, 2, rs2, u) 139 } 140 return 0 141 } 142 return 0 143} 144func nx_rvc_main_ignore() -> i64 { return 0 }