diff --git a/filetests/isa/riscv/binary32.cton b/filetests/isa/riscv/binary32.cton index aa0a7b7389..f7225c234e 100644 --- a/filetests/isa/riscv/binary32.cton +++ b/filetests/isa/riscv/binary32.cton @@ -71,5 +71,9 @@ ebb0: [-,%x7] v132 = icmp_imm ult, v1, 1000 ; bin: 3e853393 [-,%x16] v133 = icmp_imm ult, v2, -905 ; bin: c77ab813 + ; lui + [-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7 + [-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837 + return } diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index 1966a576c2..e1d186db5d 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -5,8 +5,8 @@ from __future__ import absolute_import from base import instructions as base from base.immediates import intcc from .defs import RV32, RV64 -from .recipes import OPIMM, OPIMM32, OP, OP32 -from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret +from .recipes import OPIMM, OPIMM32, OP, OP32, LUI +from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret, U from .settings import use_m from cdsl.ast import Var @@ -66,6 +66,11 @@ RV64.enc(base.icmp_imm.i64(intcc.slt, x, y), Iicmp, OPIMM(0b010)) RV32.enc(base.icmp_imm.i32(intcc.ult, x, y), Iicmp, OPIMM(0b011)) RV64.enc(base.icmp_imm.i64(intcc.ult, x, y), Iicmp, OPIMM(0b011)) +# Integer constants with the low 12 bits clear are materialized by lui. +RV32.enc(base.iconst.i32, U, LUI()) +RV64.enc(base.iconst.i32, U, LUI()) +RV64.enc(base.iconst.i64, U, LUI()) + # "M" Standard Extension for Integer Multiplication and Division. # Gated by the `use_m` flag. RV32.enc(base.imul.i32, R, OP(0b000, 0b0000001), isap=use_m) diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index fb31b5d60a..ebeb9f9ee1 100644 --- a/lib/cretonne/meta/isa/riscv/recipes.py +++ b/lib/cretonne/meta/isa/riscv/recipes.py @@ -12,6 +12,7 @@ from __future__ import absolute_import from cdsl.isa import EncRecipe from cdsl.predicates import IsSignedInt from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm +from base.formats import UnaryImm from .registers import GPR # The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit @@ -72,6 +73,16 @@ def OP32(funct3, funct7): return 0b01110 | (funct3 << 5) | (funct7 << 8) +def AIUPC(): + # type: () -> int + return 0b00101 + + +def LUI(): + # type: () -> int + return 0b01101 + + # R-type 32-bit instructions: These are mostly binary arithmetic instructions. # The encbits are `opcode[6:2] | (funct3 << 5) | (funct7 << 8) R = EncRecipe('R', Binary, ins=(GPR, GPR), outs=GPR) @@ -95,3 +106,8 @@ Iicmp = EncRecipe( # immediate offset. # The variable return values are not encoded. Iret = EncRecipe('Iret', MultiAry, ins=GPR, outs=()) + +# U-type instructions have a 20-bit immediate that targets bits 12-31. +U = EncRecipe( + 'U', UnaryImm, ins=(), outs=GPR, + instp=IsSignedInt(UnaryImm.imm, 32, 12)) diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 5479a60898..a295a66386 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -160,3 +160,35 @@ fn recipe_iicmp(func: &Function, inst: Inst, sink: &mut C fn recipe_iret(_func: &Function, _inst: Inst, _sink: &mut CS) { unimplemented!() } + +/// U-type instructions. +/// +/// 31 11 6 +/// imm rd opcode +/// 12 7 0 +/// +/// Encoding bits: `opcode[6:2] | (funct3 << 5)` +fn put_u(bits: u16, imm: i64, rd: RegUnit, sink: &mut CS) { + let bits = bits as u32; + let opcode5 = bits & 0x1f; + let rd = rd as u32 & 0x1f; + + // 0-6: opcode + let mut i = 0x3; + i |= opcode5 << 2; + i |= rd << 7; + i |= imm as u32 & 0xfffff000; + + sink.put4(i); +} + +fn recipe_u(func: &Function, inst: Inst, sink: &mut CS) { + if let InstructionData::UnaryImm { imm, .. } = func.dfg[inst] { + put_u(func.encodings[inst].bits(), + imm.into(), + func.locations[func.dfg.first_result(inst)].unwrap_reg(), + sink); + } else { + panic!("Expected UnaryImm format: {:?}", func.dfg[inst]); + } +}