Fill in boilerplate for Intel and ARM targets.

The intel, arm32, and arm32 targets were only defined in the meta
language previously. Add Rust implementations too.

This is mostly boilerplate, except for the unit tests in the
registers.rs files.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-23 10:42:07 -08:00
parent 353caf23cd
commit fb4db38dd6
24 changed files with 456 additions and 18 deletions

View File

@@ -0,0 +1,8 @@
//! Encoding tables for ARM32 ISA.
use ir::InstructionData;
use ir::instructions::InstructionFormat;
use ir::types;
use isa::enc_tables::{Level1Entry, Level2Entry};
include!(concat!(env!("OUT_DIR"), "/encoding-arm32.rs"));

View File

@@ -0,0 +1,73 @@
//! ARM 32-bit Instruction Set Architecture.
pub mod settings;
mod enc_tables;
mod registers;
use super::super::settings as shared_settings;
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
use isa::Builder as IsaBuilder;
use isa::{TargetIsa, RegInfo, Encoding, Legalize};
use ir::{InstructionData, DataFlowGraph};
#[allow(dead_code)]
struct Isa {
shared_flags: shared_settings::Flags,
isa_flags: settings::Flags,
cpumode: &'static [shared_enc_tables::Level1Entry<u16>],
}
/// Get an ISA builder for creating ARM32 targets.
pub fn isa_builder() -> IsaBuilder {
IsaBuilder {
setup: settings::builder(),
constructor: isa_constructor,
}
}
fn isa_constructor(shared_flags: shared_settings::Flags,
builder: &shared_settings::Builder)
-> Box<TargetIsa> {
let level1 = if shared_flags.is_compressed() {
&enc_tables::LEVEL1_T32[..]
} else {
&enc_tables::LEVEL1_A32[..]
};
Box::new(Isa {
isa_flags: settings::Flags::new(&shared_flags, builder),
shared_flags: shared_flags,
cpumode: level1,
})
}
impl TargetIsa for Isa {
fn name(&self) -> &'static str {
"arm32"
}
fn flags(&self) -> &shared_settings::Flags {
&self.shared_flags
}
fn register_info(&self) -> &RegInfo {
&registers::INFO
}
fn encode(&self, _: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize> {
lookup_enclist(inst.first_type(),
inst.opcode(),
self.cpumode,
&enc_tables::LEVEL2[..])
.and_then(|enclist_offset| {
general_encoding(enclist_offset,
&enc_tables::ENCLISTS[..],
|instp| enc_tables::check_instp(inst, instp),
|isap| self.isa_flags.numbered_predicate(isap as usize))
.ok_or(Legalize::Expand)
})
}
fn recipe_names(&self) -> &'static [&'static str] {
&enc_tables::RECIPE_NAMES[..]
}
}

View File

@@ -0,0 +1,32 @@
//! ARM32 register descriptions.
use isa::registers::{RegBank, RegInfo};
include!(concat!(env!("OUT_DIR"), "/registers-arm32.rs"));
#[cfg(test)]
mod tests {
use super::INFO;
use isa::RegUnit;
#[test]
fn unit_encodings() {
assert_eq!(INFO.parse_regunit("s0"), Some(0));
assert_eq!(INFO.parse_regunit("s31"), Some(31));
assert_eq!(INFO.parse_regunit("s32"), Some(32));
assert_eq!(INFO.parse_regunit("r0"), Some(64));
assert_eq!(INFO.parse_regunit("r15"), Some(79));
}
#[test]
fn unit_names() {
fn uname(ru: RegUnit) -> String {
INFO.display_regunit(ru).to_string()
}
assert_eq!(uname(0), "%s0");
assert_eq!(uname(1), "%s1");
assert_eq!(uname(31), "%s31");
assert_eq!(uname(64), "%r0");
}
}

View File

@@ -0,0 +1,9 @@
//! ARM32 Settings.
use settings::{self, detail, Builder};
use std::fmt;
// Include code generated by `lib/cretonne/meta/gen_settings.py`. This file contains a public
// `Flags` struct with an impl for all of the settings defined in
// `lib/cretonne/meta/cretonne/settings.py`.
include!(concat!(env!("OUT_DIR"), "/settings-arm32.rs"));

View File

@@ -0,0 +1,8 @@
//! Encoding tables for ARM64 ISA.
use ir::InstructionData;
use ir::instructions::InstructionFormat;
use ir::types;
use isa::enc_tables::{Level1Entry, Level2Entry};
include!(concat!(env!("OUT_DIR"), "/encoding-arm64.rs"));

View File

@@ -0,0 +1,66 @@
//! ARM 64-bit Instruction Set Architecture.
pub mod settings;
mod enc_tables;
mod registers;
use super::super::settings as shared_settings;
use isa::enc_tables::{lookup_enclist, general_encoding};
use isa::Builder as IsaBuilder;
use isa::{TargetIsa, RegInfo, Encoding, Legalize};
use ir::{InstructionData, DataFlowGraph};
#[allow(dead_code)]
struct Isa {
shared_flags: shared_settings::Flags,
isa_flags: settings::Flags,
}
/// Get an ISA builder for creating ARM64 targets.
pub fn isa_builder() -> IsaBuilder {
IsaBuilder {
setup: settings::builder(),
constructor: isa_constructor,
}
}
fn isa_constructor(shared_flags: shared_settings::Flags,
builder: &shared_settings::Builder)
-> Box<TargetIsa> {
Box::new(Isa {
isa_flags: settings::Flags::new(&shared_flags, builder),
shared_flags: shared_flags,
})
}
impl TargetIsa for Isa {
fn name(&self) -> &'static str {
"arm64"
}
fn flags(&self) -> &shared_settings::Flags {
&self.shared_flags
}
fn register_info(&self) -> &RegInfo {
&registers::INFO
}
fn encode(&self, _: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize> {
lookup_enclist(inst.first_type(),
inst.opcode(),
&enc_tables::LEVEL1_A64[..],
&enc_tables::LEVEL2[..])
.and_then(|enclist_offset| {
general_encoding(enclist_offset,
&enc_tables::ENCLISTS[..],
|instp| enc_tables::check_instp(inst, instp),
|isap| self.isa_flags.numbered_predicate(isap as usize))
.ok_or(Legalize::Expand)
})
}
fn recipe_names(&self) -> &'static [&'static str] {
&enc_tables::RECIPE_NAMES[..]
}
}

View File

@@ -0,0 +1,37 @@
//! ARM64 register descriptions.
use isa::registers::{RegBank, RegInfo};
include!(concat!(env!("OUT_DIR"), "/registers-arm64.rs"));
#[cfg(test)]
mod tests {
use super::INFO;
use isa::RegUnit;
#[test]
fn unit_encodings() {
assert_eq!(INFO.parse_regunit("x0"), Some(0));
assert_eq!(INFO.parse_regunit("x31"), Some(31));
assert_eq!(INFO.parse_regunit("v0"), Some(32));
assert_eq!(INFO.parse_regunit("v31"), Some(63));
assert_eq!(INFO.parse_regunit("x32"), None);
assert_eq!(INFO.parse_regunit("v32"), None);
}
#[test]
fn unit_names() {
fn uname(ru: RegUnit) -> String {
INFO.display_regunit(ru).to_string()
}
assert_eq!(uname(0), "%x0");
assert_eq!(uname(1), "%x1");
assert_eq!(uname(31), "%x31");
assert_eq!(uname(32), "%v0");
assert_eq!(uname(33), "%v1");
assert_eq!(uname(63), "%v31");
assert_eq!(uname(64), "%INVALID64");
}
}

View File

@@ -0,0 +1,9 @@
//! ARM64 Settings.
use settings::{self, detail, Builder};
use std::fmt;
// Include code generated by `lib/cretonne/meta/gen_settings.py`. This file contains a public
// `Flags` struct with an impl for all of the settings defined in
// `lib/cretonne/meta/cretonne/settings.py`.
include!(concat!(env!("OUT_DIR"), "/settings-arm64.rs"));

View File

@@ -0,0 +1,8 @@
//! Encoding tables for Intel ISAs.
use ir::InstructionData;
use ir::instructions::InstructionFormat;
use ir::types;
use isa::enc_tables::{Level1Entry, Level2Entry};
include!(concat!(env!("OUT_DIR"), "/encoding-intel.rs"));

View File

@@ -0,0 +1,73 @@
//! Intel Instruction Set Architectures.
pub mod settings;
mod enc_tables;
mod registers;
use super::super::settings as shared_settings;
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
use isa::Builder as IsaBuilder;
use isa::{TargetIsa, RegInfo, Encoding, Legalize};
use ir::{InstructionData, DataFlowGraph};
#[allow(dead_code)]
struct Isa {
shared_flags: shared_settings::Flags,
isa_flags: settings::Flags,
cpumode: &'static [shared_enc_tables::Level1Entry<u16>],
}
/// Get an ISA builder for creating Intel targets.
pub fn isa_builder() -> IsaBuilder {
IsaBuilder {
setup: settings::builder(),
constructor: isa_constructor,
}
}
fn isa_constructor(shared_flags: shared_settings::Flags,
builder: &shared_settings::Builder)
-> Box<TargetIsa> {
let level1 = if shared_flags.is_64bit() {
&enc_tables::LEVEL1_I64[..]
} else {
&enc_tables::LEVEL1_I32[..]
};
Box::new(Isa {
isa_flags: settings::Flags::new(&shared_flags, builder),
shared_flags: shared_flags,
cpumode: level1,
})
}
impl TargetIsa for Isa {
fn name(&self) -> &'static str {
"intel"
}
fn flags(&self) -> &shared_settings::Flags {
&self.shared_flags
}
fn register_info(&self) -> &RegInfo {
&registers::INFO
}
fn encode(&self, _: &DataFlowGraph, inst: &InstructionData) -> Result<Encoding, Legalize> {
lookup_enclist(inst.first_type(),
inst.opcode(),
self.cpumode,
&enc_tables::LEVEL2[..])
.and_then(|enclist_offset| {
general_encoding(enclist_offset,
&enc_tables::ENCLISTS[..],
|instp| enc_tables::check_instp(inst, instp),
|isap| self.isa_flags.numbered_predicate(isap as usize))
.ok_or(Legalize::Expand)
})
}
fn recipe_names(&self) -> &'static [&'static str] {
&enc_tables::RECIPE_NAMES[..]
}
}

View File

@@ -0,0 +1,49 @@
//! Intel register descriptions.
use isa::registers::{RegBank, RegInfo};
include!(concat!(env!("OUT_DIR"), "/registers-intel.rs"));
#[cfg(test)]
mod tests {
use super::INFO;
use isa::RegUnit;
#[test]
fn unit_encodings() {
// The encoding of integer registers is not alphabetical.
assert_eq!(INFO.parse_regunit("rax"), Some(0));
assert_eq!(INFO.parse_regunit("rbx"), Some(3));
assert_eq!(INFO.parse_regunit("rcx"), Some(1));
assert_eq!(INFO.parse_regunit("rdx"), Some(2));
assert_eq!(INFO.parse_regunit("rsi"), Some(6));
assert_eq!(INFO.parse_regunit("rdi"), Some(7));
assert_eq!(INFO.parse_regunit("rbp"), Some(5));
assert_eq!(INFO.parse_regunit("rsp"), Some(4));
assert_eq!(INFO.parse_regunit("r8"), Some(8));
assert_eq!(INFO.parse_regunit("r15"), Some(15));
assert_eq!(INFO.parse_regunit("xmm0"), Some(16));
assert_eq!(INFO.parse_regunit("xmm15"), Some(31));
}
#[test]
fn unit_names() {
fn uname(ru: RegUnit) -> String {
INFO.display_regunit(ru).to_string()
}
assert_eq!(uname(0), "%rax");
assert_eq!(uname(3), "%rbx");
assert_eq!(uname(1), "%rcx");
assert_eq!(uname(2), "%rdx");
assert_eq!(uname(6), "%rsi");
assert_eq!(uname(7), "%rdi");
assert_eq!(uname(5), "%rbp");
assert_eq!(uname(4), "%rsp");
assert_eq!(uname(8), "%r8");
assert_eq!(uname(15), "%r15");
assert_eq!(uname(16), "%xmm0");
assert_eq!(uname(31), "%xmm15");
}
}

View File

@@ -0,0 +1,9 @@
//! Intel Settings.
use settings::{self, detail, Builder};
use std::fmt;
// Include code generated by `lib/cretonne/meta/gen_settings.py`. This file contains a public
// `Flags` struct with an impl for all of the settings defined in
// `lib/cretonne/meta/cretonne/settings.py`.
include!(concat!(env!("OUT_DIR"), "/settings-intel.rs"));

View File

@@ -46,6 +46,9 @@ use settings;
use ir::{InstructionData, DataFlowGraph};
pub mod riscv;
pub mod intel;
pub mod arm32;
pub mod arm64;
mod encoding;
mod enc_tables;
mod registers;
@@ -55,6 +58,9 @@ mod registers;
pub fn lookup(name: &str) -> Option<Builder> {
match name {
"riscv" => riscv_builder(),
"intel" => intel_builder(),
"arm32" => arm32_builder(),
"arm64" => arm64_builder(),
_ => None,
}
}
@@ -64,6 +70,18 @@ fn riscv_builder() -> Option<Builder> {
Some(riscv::isa_builder())
}
fn intel_builder() -> Option<Builder> {
Some(intel::isa_builder())
}
fn arm32_builder() -> Option<Builder> {
Some(arm32::isa_builder())
}
fn arm64_builder() -> Option<Builder> {
Some(arm64::isa_builder())
}
/// Builder for a `TargetIsa`.
/// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`.
pub struct Builder {