diff --git a/generation/src/Shift.hs b/generation/src/Shift.hs index 84e9f57..e606bbc 100644 --- a/generation/src/Shift.hs +++ b/generation/src/Shift.hs @@ -32,7 +32,8 @@ declareShiftOperators bitsize = entries = bitsize `div` 64 unsignedShifts = generateUnsigneds struct_name shlUsizeImpls = generateBaseUsizes struct_name - shlActualImpl = concatMap actualImplLines [1..entries-1] + shlActualImpl = concatMap actualShlImplLines [1..entries-1] + shrActualImpl = concatMap (actualShrImplLines entries) (reverse [0..entries-1]) testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty in [sourceFile| #[cfg(test)] @@ -50,7 +51,6 @@ declareShiftOperators bitsize = let copy = self.clone(); let digits = rhs / 64; let bits = rhs % 64; - let mask = !(0xFFFF_FFFF_FFFF_FFFFu64 << bits); let shift = (64 - bits) as u32; let base0 = if digits == 0 { copy.value[0] } else { 0 }; @@ -60,8 +60,14 @@ declareShiftOperators bitsize = } impl ShrAssign for $$struct_name { - fn shr_assign(&mut self, _rhs: usize) { - panic!("base shl_assign"); + fn shr_assign(&mut self, rhs: usize) { + let copy = self.clone(); + let digits = rhs / 64; + let bits = rhs % 64; + let mask = !(0xFFFFFFFFFFFFFFFFu64 << bits); + let shift = (64 - bits) as u32; + + $@{shrActualImpl} } } @@ -90,8 +96,8 @@ declareShiftOperators bitsize = } |] -actualImplLines :: Word -> [Stmt Span] -actualImplLines i = +actualShlImplLines :: Word -> [Stmt Span] +actualShlImplLines i = let basei = mkIdent ("base" ++ show i) basei1 = mkIdent ("base" ++ show (i - 1)) carryi = mkIdent ("carry" ++ show i) @@ -106,6 +112,25 @@ actualImplLines i = , [stmt|self.value[$$(liti)] = ($$basei << bits) | $$carryi; |] ] +actualShrImplLines :: Word -> Word -> [Stmt Span] +actualShrImplLines entries i = + let basei = mkIdent ("base" ++ show i) + carryi = mkIdent ("carry" ++ show i) + carryi1 = mkIdent ("carry" ++ show (i + 1)) + targeti = mkIdent ("target" ++ show i) + liti = toLit i + litentries = toLit entries + in [ + [stmt|let $$targeti = $$(liti) + digits; |] + , [stmt|let $$basei = if $$targeti >= $$(litentries) { 0 } else { copy.value[$$targeti] }; |] + , if i == 0 + then [stmt| {} |]; + else [stmt|let ($$carryi,_) = ($$basei & mask).overflowing_shl(shift); |] + , if (i + 1) == entries + then [stmt|self.value[$$(liti)] = $$basei >> bits ; |] + else [stmt|self.value[$$(liti)] = ($$basei >> bits) | $$carryi1; |] + ] + generateBaseUsizes :: Ident -> [Item Span] generateBaseUsizes sname = generateBaseUsize sname (mkIdent "Shl") (mkIdent "shl") (mkIdent "shl_assign") ++