Add RISC-V encodings for lui.

This instruction can materialize constants with the low 12 bits clear.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-03 12:27:22 -07:00
parent c13c318ec4
commit 175b269760
4 changed files with 59 additions and 2 deletions

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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))

View File

@@ -160,3 +160,35 @@ fn recipe_iicmp<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut C
fn recipe_iret<CS: CodeSink + ?Sized>(_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<CS: CodeSink + ?Sized>(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<CS: CodeSink + ?Sized>(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]);
}
}