diff --git a/cranelift/filetests/isa/riscv/binary32.cton b/cranelift/filetests/isa/riscv/binary32.cton index 68bc718ea7..fd3d910a18 100644 --- a/cranelift/filetests/isa/riscv/binary32.cton +++ b/cranelift/filetests/isa/riscv/binary32.cton @@ -55,9 +55,15 @@ ebb0: [-,%x7] v114 = bxor_imm v1, 1000 ; bin: 3e854393 [-,%x16] v115 = bxor_imm v2, -905 ; bin: c77ac813 - ; TBD: slli - ; TBD: srli - ; TBD: srai + ; slli + [-,%x7] v120 = ishl_imm v1, 31 ; bin: 01f51393 + [-,%x16] v121 = ishl_imm v2, 8 ; bin: 008a9813 + ; srli + [-,%x7] v122 = ushr_imm v1, 31 ; bin: 01f55393 + [-,%x16] v123 = ushr_imm v2, 8 ; bin: 008ad813 + ; srai + [-,%x7] v124 = sshr_imm v1, 31 ; bin: 41f55393 + [-,%x16] v125 = sshr_imm v2, 8 ; bin: 408ad813 return } diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 480d377c6b..a3941af526 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -38,6 +38,40 @@ fn put_r(bits: u16, sink.put4(i); } +/// R-type instructions with a shift amount instead of rs2. +/// +/// 31 25 19 14 11 6 +/// funct7 shamt rs1 funct3 rd opcode +/// 25 20 15 12 7 0 +/// +/// Both funct7 and shamt contribute to bit 25. In RV64, shamt uses it for shifts > 31. +/// +/// Encoding bits: `opcode[6:2] | (funct3 << 5) | (funct7 << 8)`. +fn put_rshamt(bits: u16, + rs1: RegUnit, + shamt: i64, + rd: RegUnit, + sink: &mut CS) { + let bits = bits as u32; + let opcode5 = bits & 0x1f; + let funct3 = (bits >> 5) & 0x7; + let funct7 = (bits >> 8) & 0x7f; + let rs1 = rs1 as u32 & 0x1f; + let shamt = shamt as u32 & 0x3f; + let rd = rd as u32 & 0x1f; + + // 0-6: opcode + let mut i = 0x3; + i |= opcode5 << 2; + i |= rd << 7; + i |= funct3 << 12; + i |= rs1 << 15; + i |= shamt << 20; + i |= funct7 << 25; + + sink.put4(i); +} + fn recipe_r(func: &Function, inst: Inst, sink: &mut CS) { if let InstructionData::Binary { args, .. } = func.dfg[inst] { put_r(func.encodings[inst].bits(), @@ -62,8 +96,16 @@ fn recipe_ricmp(func: &Function, inst: Inst, sink: &mut C } } -fn recipe_rshamt(_func: &Function, _inst: Inst, _sink: &mut CS) { - unimplemented!() +fn recipe_rshamt(func: &Function, inst: Inst, sink: &mut CS) { + if let InstructionData::BinaryImm { arg, imm, .. } = func.dfg[inst] { + put_rshamt(func.encodings[inst].bits(), + func.locations[arg].unwrap_reg(), + imm.into(), + func.locations[func.dfg.first_result(inst)].unwrap_reg(), + sink); + } else { + panic!("Expected BinaryImm format: {:?}", func.dfg[inst]); + } } /// I-type instructions. @@ -99,7 +141,7 @@ fn recipe_i(func: &Function, inst: Inst, sink: &mut CS) { func.locations[func.dfg.first_result(inst)].unwrap_reg(), sink); } else { - panic!("Expected Binary format: {:?}", func.dfg[inst]); + panic!("Expected BinaryImm format: {:?}", func.dfg[inst]); } }