From dddcc0b2caae9bdd805e98c002059114d3488a2a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 30 Aug 2016 10:44:33 -0700 Subject: [PATCH] Add an encoding test for RISC-V. Test that the generated encoding tables work as expected. Change isa::Encoding into a struct with named fields so the recipe and bits can be accessed. --- cranelift/src/libcretonne/isa/mod.rs | 21 +++++++- cranelift/src/libcretonne/isa/riscv/mod.rs | 58 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/cranelift/src/libcretonne/isa/mod.rs b/cranelift/src/libcretonne/isa/mod.rs index 18723a16a5..6eaae9fc62 100644 --- a/cranelift/src/libcretonne/isa/mod.rs +++ b/cranelift/src/libcretonne/isa/mod.rs @@ -107,11 +107,28 @@ pub trait TargetIsa { /// encoding *bits*. The recipe determines the native instruction format and the mapping of /// operands to encoded bits. The encoding bits provide additional information to the recipe, /// typically parts of the opcode. -pub struct Encoding(u16, u16); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Encoding { + recipe: u16, + bits: u16, +} impl Encoding { /// Create a new `Encoding` containing `(recipe, bits)`. pub fn new(recipe: u16, bits: u16) -> Encoding { - Encoding(recipe, bits) + Encoding { + recipe: recipe, + bits: bits, + } + } + + /// Get the recipe number in this encoding. + pub fn recipe(self) -> usize { + self.recipe as usize + } + + /// Get the recipe-specific encoding bits. + pub fn bits(self) -> u16 { + self.bits } } diff --git a/cranelift/src/libcretonne/isa/riscv/mod.rs b/cranelift/src/libcretonne/isa/riscv/mod.rs index 5211479f9c..8abb53467b 100644 --- a/cranelift/src/libcretonne/isa/riscv/mod.rs +++ b/cranelift/src/libcretonne/isa/riscv/mod.rs @@ -57,3 +57,61 @@ impl TargetIsa for Isa { &encoding::RECIPE_NAMES[..] } } + +#[cfg(test)] +mod tests { + use settings::{self, Configurable}; + use isa; + use ir::{DataFlowGraph, InstructionData, Opcode}; + use ir::{types, immediates}; + + fn encstr(isa: &isa::TargetIsa, enc: isa::Encoding) -> String { + format!("{}/{:02x}", isa.recipe_names()[enc.recipe()], enc.bits()) + } + + #[test] + fn test_64bitenc() { + let mut shared_builder = settings::builder(); + shared_builder.set_bool("is_64bit", true).unwrap(); + let shared_flags = settings::Flags::new(shared_builder); + let isa = isa::lookup("riscv").unwrap().finish(shared_flags); + + let mut dfg = DataFlowGraph::new(); + let ebb = dfg.make_ebb(); + let arg64 = dfg.append_ebb_arg(ebb, types::I64); + let arg32 = dfg.append_ebb_arg(ebb, types::I32); + + // Try to encode iadd_imm.i64 vx1, -10. + let inst64 = InstructionData::BinaryImm { + opcode: Opcode::IaddImm, + ty: types::I64, + arg: arg64, + imm: immediates::Imm64::new(-10), + }; + + // ADDI is I/0b00100 + assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst64).unwrap()), "I/04"); + + // Try to encode iadd_imm.i64 vx1, -10000. + let inst64_large = InstructionData::BinaryImm { + opcode: Opcode::IaddImm, + ty: types::I64, + arg: arg64, + imm: immediates::Imm64::new(-10000), + }; + + // Immediate is out of range for ADDI. + assert_eq!(isa.encode(&dfg, &inst64_large), None); + + // Create an iadd_imm.i32 which is encodable in RV64. + let inst32 = InstructionData::BinaryImm { + opcode: Opcode::IaddImm, + ty: types::I32, + arg: arg32, + imm: immediates::Imm64::new(10), + }; + + // ADDIW is I/0b00110 + assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst32).unwrap()), "I/06"); + } +}