Add RISC-V encodings for supported icmp variants.

Only slt and ult variants are in the instruction set. Other condition
codes must be synthesized.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-31 12:12:09 -07:00
parent 75b156e1c7
commit e9907fbdd6
5 changed files with 69 additions and 23 deletions

View File

@@ -14,7 +14,6 @@ ebb0:
; sub ; sub
[-,%x7] v12 = isub v1, v2 ; bin: 415503b3 [-,%x7] v12 = isub v1, v2 ; bin: 415503b3
[-,%x16] v13 = isub v2, v1 ; bin: 40aa8833 [-,%x16] v13 = isub v2, v1 ; bin: 40aa8833
; TBD: slt/sltu
; and ; and
[-,%x7] v20 = band v1, v2 ; bin: 015573b3 [-,%x7] v20 = band v1, v2 ; bin: 015573b3
[-,%x16] v21 = band v2, v1 ; bin: 00aaf833 [-,%x16] v21 = band v2, v1 ; bin: 00aaf833
@@ -33,5 +32,12 @@ ebb0:
; sra ; sra
[-,%x7] v34 = sshr v1, v2 ; bin: 415553b3 [-,%x7] v34 = sshr v1, v2 ; bin: 415553b3
[-,%x16] v35 = sshr v2, v1 ; bin: 40aad833 [-,%x16] v35 = sshr v2, v1 ; bin: 40aad833
; slt
[-,%x7] v42 = icmp slt, v1, v2 ; bin: 015523b3
[-,%x16] v43 = icmp slt, v2, v1 ; bin: 00aaa833
; sltu
[-,%x7] v44 = icmp ult, v1, v2 ; bin: 015533b3
[-,%x16] v45 = icmp ult, v2, v1 ; bin: 00aab833
return return
} }

View File

@@ -3,9 +3,15 @@ RISC-V Encodings.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from base import instructions as base from base import instructions as base
from base.immediates import intcc
from .defs import RV32, RV64 from .defs import RV32, RV64
from .recipes import OPIMM, OPIMM32, OP, OP32, JALR, R, Rshamt, I, Iret from .recipes import OPIMM, OPIMM32, OP, OP32, JALR, R, Rshamt, Ricmp, I, Iret
from .settings import use_m from .settings import use_m
from cdsl.ast import Var
# Dummies for instruction predicates.
x = Var('x')
y = Var('y')
# Basic arithmetic binary instructions are encoded in an R-type instruction. # Basic arithmetic binary instructions are encoded in an R-type instruction.
for inst, inst_imm, f3, f7 in [ for inst, inst_imm, f3, f7 in [
@@ -47,6 +53,13 @@ for inst, inst_imm, f3, f7 in [
RV64.enc(inst_imm.i64, Rshamt, OPIMM(f3, f7)) RV64.enc(inst_imm.i64, Rshamt, OPIMM(f3, f7))
RV64.enc(inst_imm.i32, Rshamt, OPIMM32(f3, f7)) RV64.enc(inst_imm.i32, Rshamt, OPIMM32(f3, f7))
# Signed and unsigned integer 'less than'. There are no 'w' variants for
# comparing 32-bit numbers in RV64.
RV32.enc(base.icmp.i32(intcc.slt, x, y), Ricmp, OP(0b010, 0b0000000))
RV64.enc(base.icmp.i64(intcc.slt, x, y), Ricmp, OP(0b010, 0b0000000))
RV32.enc(base.icmp.i32(intcc.ult, x, y), Ricmp, OP(0b011, 0b0000000))
RV64.enc(base.icmp.i64(intcc.ult, x, y), Ricmp, OP(0b011, 0b0000000))
# "M" Standard Extension for Integer Multiplication and Division. # "M" Standard Extension for Integer Multiplication and Division.
# Gated by the `use_m` flag. # Gated by the `use_m` flag.
RV32.enc(base.imul.i32, R, OP(0b000, 0b0000001), isap=use_m) RV32.enc(base.imul.i32, R, OP(0b000, 0b0000001), isap=use_m)

View File

@@ -11,7 +11,7 @@ instruction formats described in the reference:
from __future__ import absolute_import from __future__ import absolute_import
from cdsl.isa import EncRecipe from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt from cdsl.predicates import IsSignedInt
from base.formats import Binary, BinaryImm, MultiAry from base.formats import Binary, BinaryImm, MultiAry, IntCompare
from .registers import GPR from .registers import GPR
# The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit # The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit
@@ -79,6 +79,9 @@ R = EncRecipe('R', Binary, ins=(GPR, GPR), outs=GPR)
# R-type with an immediate shift amount instead of rs2. # R-type with an immediate shift amount instead of rs2.
Rshamt = EncRecipe('Rshamt', BinaryImm, ins=GPR, outs=GPR) Rshamt = EncRecipe('Rshamt', BinaryImm, ins=GPR, outs=GPR)
# R-type encoding of an integer comparison.
Ricmp = EncRecipe('Ricmp', IntCompare, ins=(GPR, GPR), outs=GPR)
I = EncRecipe( I = EncRecipe(
'I', BinaryImm, ins=GPR, outs=GPR, 'I', BinaryImm, ins=GPR, outs=GPR,
instp=IsSignedInt(BinaryImm.imm, 12)) instp=IsSignedInt(BinaryImm.imm, 12))

View File

@@ -2,6 +2,7 @@
use binemit::{CodeSink, bad_encoding}; use binemit::{CodeSink, bad_encoding};
use ir::{Function, Inst, InstructionData}; use ir::{Function, Inst, InstructionData};
use isa::RegUnit;
include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs")); include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs"));
@@ -12,33 +13,55 @@ include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs"));
/// 25 20 15 12 7 0 /// 25 20 15 12 7 0
/// ///
/// Encoding bits: `opcode[6:2] | (funct3 << 5) | (funct7 << 8)`. /// Encoding bits: `opcode[6:2] | (funct3 << 5) | (funct7 << 8)`.
fn put_r<CS: CodeSink + ?Sized>(bits: u16,
rs1: RegUnit,
rs2: RegUnit,
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 rs2 = rs2 as u32 & 0x1f;
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 |= rs2 << 20;
i |= funct7 << 25;
sink.put4(i);
}
fn recipe_r<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) { fn recipe_r<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::Binary { args, .. } = func.dfg[inst] { if let InstructionData::Binary { args, .. } = func.dfg[inst] {
let bits = func.encodings[inst].bits(); put_r(func.encodings[inst].bits(),
let rs1 = func.locations[args[0]].unwrap_reg(); func.locations[args[0]].unwrap_reg(),
let rs2 = func.locations[args[1]].unwrap_reg(); func.locations[args[1]].unwrap_reg(),
let rd = func.locations[func.dfg.first_result(inst)].unwrap_reg(); func.locations[func.dfg.first_result(inst)].unwrap_reg(),
sink);
// 0-6: opcode
let mut i = 0x3;
i |= (bits as u32 & 0x1f) << 2;
// 7-11: rd
i |= (rd as u32 & 0x1f) << 7;
// 12-14: funct3
i |= ((bits as u32 >> 5) & 0x7) << 12;
// 15-19: rs1
i |= (rs1 as u32 & 0x1f) << 15;
// 20-24: rs1
i |= (rs2 as u32 & 0x1f) << 20;
// 25-31: funct7
i |= ((bits as u32 >> 8) & 0x7f) << 25;
sink.put4(i);
} else { } else {
panic!("Expected Binary format: {:?}", func.dfg[inst]); panic!("Expected Binary format: {:?}", func.dfg[inst]);
} }
} }
fn recipe_ricmp<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::IntCompare { args, .. } = func.dfg[inst] {
put_r(func.encodings[inst].bits(),
func.locations[args[0]].unwrap_reg(),
func.locations[args[1]].unwrap_reg(),
func.locations[func.dfg.first_result(inst)].unwrap_reg(),
sink);
} else {
panic!("Expected IntCompare format: {:?}", func.dfg[inst]);
}
}
fn recipe_rshamt<CS: CodeSink + ?Sized>(_func: &Function, _inst: Inst, _sink: &mut CS) { fn recipe_rshamt<CS: CodeSink + ?Sized>(_func: &Function, _inst: Inst, _sink: &mut CS) {
unimplemented!() unimplemented!()
} }

View File

@@ -1,5 +1,6 @@
//! Encoding tables for RISC-V. //! Encoding tables for RISC-V.
use ir::condcodes::IntCC;
use ir::{Opcode, InstructionData}; use ir::{Opcode, InstructionData};
use ir::types; use ir::types;
use predicates; use predicates;