Sort out signed shifts.
This commit is contained in:
@@ -42,8 +42,8 @@ declareShiftOperators bitsize _ =
|
|||||||
unsignedShifts = generateUnsigneds struct_name
|
unsignedShifts = generateUnsigneds struct_name
|
||||||
shlUsizeImpls = generateBaseUsizes struct_name
|
shlUsizeImpls = generateBaseUsizes struct_name
|
||||||
shlActualImpl = concatMap actualShlImplLines [1..entries-1]
|
shlActualImpl = concatMap actualShlImplLines [1..entries-1]
|
||||||
shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1])
|
shrActualImpl = concatMap (actualShrImplLines False entries) (reverse [0..entries-1])
|
||||||
resAssign = map reassignSelf [0..entries-1]
|
resAssign = map (reassignSelf False) [0..entries-1]
|
||||||
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
|
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -71,10 +71,11 @@ declareShiftOperators bitsize _ =
|
|||||||
|
|
||||||
impl ShrAssign<usize> for $$struct_name {
|
impl ShrAssign<usize> for $$struct_name {
|
||||||
fn shr_assign(&mut self, rhs: usize) {
|
fn shr_assign(&mut self, rhs: usize) {
|
||||||
let digits = rhs / 64;
|
let digits = rhs / 64;
|
||||||
let bits = rhs % 64;
|
let bits = rhs % 64;
|
||||||
let mask = !(0xFFFFFFFFFFFFFFFFu64 << bits);
|
let mask = !(0xFFFFFFFFFFFFFFFFu64 << bits);
|
||||||
let shift = (64 - bits) as u32;
|
let shift = (64 - bits) as u32;
|
||||||
|
let arith_base = 0;
|
||||||
|
|
||||||
$@{shrActualImpl}
|
$@{shrActualImpl}
|
||||||
$@{resAssign}
|
$@{resAssign}
|
||||||
@@ -112,10 +113,9 @@ declareSignedShiftOperators bitsize _ =
|
|||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
unsignedShifts = generateUnsigneds struct_name
|
unsignedShifts = generateUnsigneds struct_name
|
||||||
shlUsizeImpls = generateBaseUsizes struct_name
|
shlUsizeImpls = generateBaseUsizes struct_name
|
||||||
shlActualImpl = concatMap actualShlImplLines [1..entries-1]
|
shrActualImpl = concatMap (actualShrImplLines True entries) (reverse [0..entries-1])
|
||||||
shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1])
|
resAssign = map (reassignSelf True) [0..entries-1]
|
||||||
resAssign = map reassignSelf [0..entries-1]
|
testFileLit = Lit [] (Str (testFile False bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
|
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
@@ -129,13 +129,24 @@ declareSignedShiftOperators bitsize _ =
|
|||||||
|
|
||||||
impl ShlAssign<usize> for $$struct_name {
|
impl ShlAssign<usize> for $$struct_name {
|
||||||
fn shl_assign(&mut self, rhs: usize) {
|
fn shl_assign(&mut self, rhs: usize) {
|
||||||
panic!("shl_assign")
|
self.contents <<= rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShrAssign<usize> for $$struct_name {
|
impl ShrAssign<usize> for $$struct_name {
|
||||||
fn shr_assign(&mut self, rhs: usize) {
|
fn shr_assign(&mut self, rhs: usize) {
|
||||||
panic!("shr_assign")
|
let digits = rhs / 64;
|
||||||
|
let bits = rhs % 64;
|
||||||
|
let mask = !(0xFFFFFFFFFFFFFFFFu64 << bits);
|
||||||
|
let shift = (64 - bits) as u32;
|
||||||
|
let arith_base = if self.is_negative() {
|
||||||
|
0xFFFF_FFFF_FFFF_FFFFu64
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
$@{shrActualImpl}
|
||||||
|
$@{resAssign}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +157,7 @@ declareSignedShiftOperators bitsize _ =
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[test]
|
#[test]
|
||||||
fn KATs() {
|
fn KATs() {
|
||||||
run_test(build_test_path("shift", $$(testFileLit)), 4, |case| {
|
run_test(build_test_path("sshift", $$(testFileLit)), 4, |case| {
|
||||||
let (neg0, xbytes) = case.get("x").unwrap();
|
let (neg0, xbytes) = case.get("x").unwrap();
|
||||||
let (neg1, sbytes) = case.get("s").unwrap();
|
let (neg1, sbytes) = case.get("s").unwrap();
|
||||||
let (neg2, lbytes) = case.get("l").unwrap();
|
let (neg2, lbytes) = case.get("l").unwrap();
|
||||||
@@ -185,8 +196,8 @@ actualShlImplLines i =
|
|||||||
, [stmt|let $$resi = ($$basei << bits) | $$carryi; |]
|
, [stmt|let $$resi = ($$basei << bits) | $$carryi; |]
|
||||||
]
|
]
|
||||||
|
|
||||||
actualShrImplLines :: Word -> Word -> [Stmt Span]
|
actualShrImplLines :: Bool -> Word -> Word -> [Stmt Span]
|
||||||
actualShrImplLines entries i =
|
actualShrImplLines prefix_field entries i =
|
||||||
let basei = mkIdent ("base" ++ show i)
|
let basei = mkIdent ("base" ++ show i)
|
||||||
carryi = mkIdent ("carry" ++ show i)
|
carryi = mkIdent ("carry" ++ show i)
|
||||||
carryi1 = mkIdent ("carry" ++ show (i + 1))
|
carryi1 = mkIdent ("carry" ++ show (i + 1))
|
||||||
@@ -194,22 +205,27 @@ actualShrImplLines entries i =
|
|||||||
resi = mkIdent ("res" ++ show i)
|
resi = mkIdent ("res" ++ show i)
|
||||||
liti = toLit i
|
liti = toLit i
|
||||||
litentries = toLit entries
|
litentries = toLit entries
|
||||||
in [
|
sourceI | prefix_field = [expr| self.contents.value[$$targeti] |]
|
||||||
[stmt|let $$targeti = $$(liti) + digits; |]
|
| otherwise = [expr| self.value[$$targeti] |]
|
||||||
, [stmt|let $$basei = if $$targeti >= $$(litentries) { 0 } else { self.value[$$targeti] }; |]
|
in concat [
|
||||||
|
[[stmt|let $$targeti = $$(liti) + digits; |]]
|
||||||
|
, [[stmt|let $$basei = if $$targeti >= $$(litentries) { arith_base } else { $$(sourceI) }; |]]
|
||||||
|
, if i == (entries - 1)
|
||||||
|
then [[stmt| let ($$carryi1,_) = (arith_base & mask).overflowing_shl(shift); |]]
|
||||||
|
else []
|
||||||
, if i == 0
|
, if i == 0
|
||||||
then [stmt| {} |];
|
then []
|
||||||
else [stmt|let ($$carryi,_) = ($$basei & mask).overflowing_shl(shift); |]
|
else [[stmt|let ($$carryi,_) = ($$basei & mask).overflowing_shl(shift); |]]
|
||||||
, if (i + 1) == entries
|
, [[stmt|let $$resi = ($$basei >> bits) | $$carryi1; |]]
|
||||||
then [stmt|let $$resi = $$basei >> bits ; |]
|
|
||||||
else [stmt|let $$resi = ($$basei >> bits) | $$carryi1; |]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
reassignSelf :: Word -> Stmt Span
|
reassignSelf :: Bool -> Word -> Stmt Span
|
||||||
reassignSelf i =
|
reassignSelf prefix_field i =
|
||||||
let liti = toLit i
|
let liti = toLit i
|
||||||
resi = mkIdent ("res" ++ show i)
|
resi = mkIdent ("res" ++ show i)
|
||||||
in [stmt| self.value[$$(liti)] = $$resi; |]
|
in if prefix_field
|
||||||
|
then [stmt| self.contents.value[$$(liti)] = $$resi; |]
|
||||||
|
else [stmt| self.value[$$(liti)] = $$resi; |]
|
||||||
|
|
||||||
generateBaseUsizes :: Ident -> [Item Span]
|
generateBaseUsizes :: Ident -> [Item Span]
|
||||||
generateBaseUsizes sname =
|
generateBaseUsizes sname =
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ declareUnsafeSubtractOperators bitsize _ =
|
|||||||
declareUnsafeSignedSubtractOperators :: Word -> [Word] -> SourceFile Span
|
declareUnsafeSignedSubtractOperators :: Word -> [Word] -> SourceFile Span
|
||||||
declareUnsafeSignedSubtractOperators bitsize _ =
|
declareUnsafeSignedSubtractOperators bitsize _ =
|
||||||
let sname = mkIdent ("I" ++ show bitsize)
|
let sname = mkIdent ("I" ++ show bitsize)
|
||||||
testFileLit = Lit [] (Str (testFile True bitsize) Cooked Unsuffixed mempty) mempty
|
testFileLit = Lit [] (Str (testFile False bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::ops::SubAssign;
|
use core::ops::SubAssign;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user