Commit 225ffa5f authored by Pavel Zakopaylo's avatar Pavel Zakopaylo

Fixed misc issues to make tr64 tests pass

-> Made API and tests use `transmute` for f64/u64 instead of `as`
-> Changed relevant logical shifts to (correctly) be arithmetic shifts
-> Fixed small typo in tests
-> (misc) Made STORE correctly handle arbitrary (< 64) sized ints
parent fbf7e93a
......@@ -22,6 +22,8 @@
// TODO: Move architecture independent codes in here, inst_sel and asm_backend to somewhere else...
pub mod inst_sel;
use utils::bit_utils::bits_ones;
mod codegen;
pub use compiler::backend::aarch64::codegen::CodeGenerator;
......@@ -1179,12 +1181,6 @@ fn hfa_length(t : P<MuType>) -> usize
}
}
#[inline(always)]
// Returns the number that has 'n' 1's in a row (i.e. 2^n-1)
pub fn bits_ones(n: usize) -> u64 {
if n == 64 { (-(1 as i64)) as u64 }
else { (1 << n) - 1 }
}
// val is an unsigned multiple of n and val/n fits in 12 bits
#[inline(always)]
pub fn is_valid_immediate_offset(val: i64, n : usize) -> bool {
......@@ -2555,4 +2551,4 @@ fn is_int_ex_reg(val: &P<Value>) -> bool
fn is_fp_reg(val: &P<Value>) -> bool
{
RegGroup::get_from_value(&val) == RegGroup::FPR && (val.is_reg() || val.is_const())
}
\ No newline at end of file
}
......@@ -26,6 +26,20 @@ pub fn lower_bits_u8(value: u8, len: usize) -> u8 {
// u64
#[inline(always)]
// Returns the number that has 'n' 1's in a row (i.e. 2^n-1)
pub fn bits_ones(n: usize) -> u64 {
if n == 64 { (-(1 as i64)) as u64 }
else { (1 << n) - 1 }
}
#[inline(always)]
pub fn u64_asr(val: u64, shift: u32) -> u64 {
let _val: i64 = val as i64;
let res: i64 = _val >> shift;
res as u64
}
#[inline(always)]
pub fn set_nth_bit_u64 (value: u64, index: usize, set_value: u8) -> u64 {
value ^ (((-(set_value as i64) as u64) ^ value) & (1 << index))
......
......@@ -41,6 +41,9 @@ use std::sync::RwLock;
use std::sync::RwLockWriteGuard;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
use std;
use utils::bit_utils::{bits_ones, u64_asr};
// FIXME:
// besides fields in VM, there are some 'globals' we need to persist
// such as STRUCT_TAG_MAP
......@@ -1410,14 +1413,12 @@ impl <'a> VM {
unsafe {
match val.v {
APIHandleValue::Int(ival, bits) => {
let trunc: u64 = ival & bits_ones(bits);
match bits {
1 => addr.store::<u8>((ival as u8) & 0b1u8),
6 => addr.store::<u8>((ival as u8) & 0b111111u8),
8 => addr.store::<u8>(ival as u8),
16 => addr.store::<u16>(ival as u16),
32 => addr.store::<u32>(ival as u32),
52 => addr.store::<u64>(ival & ((1 << 51)-1)),
64 => addr.store::<u64>(ival),
1 ... 8 => addr.store::<u8>(trunc as u8),
9 ... 16 => addr.store::<u16>(trunc as u16),
17 ... 32 => addr.store::<u32>(trunc as u32),
33 ... 64 => addr.store::<u64>(trunc as u64),
_ => panic!("unimplemented int length")
}
},
......@@ -1653,7 +1654,7 @@ impl <'a> VM {
self.new_handle(APIHandle {
id: handle_id,
v : APIHandleValue::Double(
value.v.as_tr64() as f64
unsafe { std::mem::transmute(value.v.as_tr64()) }
)
})
}
......@@ -1680,7 +1681,7 @@ impl <'a> VM {
v : APIHandleValue::Ref(types::REF_VOID_TYPE.clone(),
unsafe { Address::from_usize(
((opnd & 0x7ffffffffff8u64) |
((opnd & 0x8000000000000000u64) >> 16)) as usize
u64_asr((opnd & 0x8000000000000000u64), 16)) as usize
) })
})
}
......@@ -1692,7 +1693,7 @@ impl <'a> VM {
self.new_handle(APIHandle {
id: handle_id,
v : APIHandleValue::Int(
(((opnd & 0x000f800000000000u64) >> 46) | ((opnd & 0x4) >> 2)),
(u64_asr((opnd & 0x000f800000000000u64), 46) | (u64_asr((opnd & 0x4), 2))),
6
)
})
......@@ -1701,7 +1702,7 @@ impl <'a> VM {
// See: `fpToTr64`
pub fn handle_tr64_from_fp(&self, value: APIHandleArg) -> APIHandleResult {
let handle_id = self.next_id();
let double_bits = value.v.as_double() as u64;
let double_bits = unsafe { std::mem::transmute(value.v.as_double()) };
let result_bits = if value.v.as_double().is_nan() {
double_bits & 0xfff8000000000000u64 | 0x0000000000000008u64
......
......@@ -18,6 +18,7 @@ use mu::ast::types::*;
use mu::utils::Address;
use std::f64;
use std::mem::transmute;
/**
* Helper functions to test VM:: methods with literal values
......@@ -97,7 +98,7 @@ fn test_other_bit_pattern_is_double() {
assert!(vm.handle_tr64_is_fp(&tr64(0x123456789abcdef0u64)));
assert!(vm.handle_tr64_is_fp(&tr64(0x7ff123456789abccu64)));
assert!(vm.handle_tr64_is_fp(&tr64(0xfffffffffffffffcu64)));
assert!(vm.handle_tr64_is_fp(&tr64(3.1415927f64 as u64)));
unsafe { assert!(vm.handle_tr64_is_fp(&tr64(transmute(3.1415927f64)))); }
}
#[test]
......@@ -114,11 +115,13 @@ fn test_encode_int() {
fn test_encode_double() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_from_fp(&double(3.14_f64)).v.as_tr64(), 3.14_f64 as u64);
assert_eq!(vm.handle_tr64_from_fp(&double(-3.14_f64)).v.as_tr64(), -3.14_f64 as u64);
assert_eq!(vm.handle_tr64_from_fp(&double(f64::INFINITY)).v.as_tr64(), 0x7ff0000000000000u64);
assert_eq!(vm.handle_tr64_from_fp(&double(0x7ff123456789abcdu64 as f64)).v.as_tr64(), 0x7ff0000000000008u64);
assert!((vm.handle_tr64_from_fp(&double(0x7ff123456789abcdu64 as f64)).v.as_tr64() as f64).is_nan());
unsafe {
assert_eq!(vm.handle_tr64_from_fp(&double(3.14_f64)).v.as_tr64(), transmute(3.14_f64));
assert_eq!(vm.handle_tr64_from_fp(&double(-3.14_f64)).v.as_tr64(), transmute(-3.14_f64));
assert_eq!(vm.handle_tr64_from_fp(&double(f64::INFINITY)).v.as_tr64(), 0x7ff0000000000000u64);
assert_eq!(vm.handle_tr64_from_fp(&double(transmute(0x7ff123456789abcdu64))).v.as_tr64(), 0x7ff0000000000008u64);
assert!(transmute::<u64, f64>((vm.handle_tr64_from_fp(&double(transmute(0x7ff123456789abcdu64))).v.as_tr64())).is_nan());
}
}
#[test]
......@@ -156,7 +159,7 @@ fn test_decode_tagref() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_to_ref(&tr64(0x7ff0555555555552u64)).v.as_ref().1.as_usize() as u64, 0x555555555550u64);
assert_eq!(vm.handle_tr64_to_ref(&tr64(0xfff02aaaaaaaaaaau64)).v.as_ref().1.as_usize() as u64, 0x555555555550u64);
assert_eq!(vm.handle_tr64_to_ref(&tr64(0xfff02aaaaaaaaaaau64)).v.as_ref().1.as_usize() as u64, 0xffffaaaaaaaaaaa8u64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7ff0555555555552u64)).v.as_int(), 0u64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7fff800000000006u64)).v.as_int(), 0x3fu64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7ffa800000000002u64)).v.as_int(), 0x2au64);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment