-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Better splitting for Op::Add, Op::Sub, and Op::Cmp * Split stores if the displacement is too large * Use a shifted immediate argument * Split all places where shifted immediates are used * Add more tests to the cirrus workflow
- Loading branch information
Showing
6 changed files
with
200 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/// How much to shift the immediate by. | ||
pub enum Shift { | ||
LSL0 = 0b0, // no shift | ||
LSL12 = 0b1 // logical shift left by 12 bits | ||
} | ||
|
||
/// Some instructions accept a 12-bit immediate that has an optional shift | ||
/// attached to it. This allows encoding larger values than just fit into 12 | ||
/// bits. We attempt to encode those here. If the values are too large we have | ||
/// to bail out. | ||
pub struct ShiftedImmediate { | ||
shift: Shift, | ||
value: u16 | ||
} | ||
|
||
impl TryFrom<u64> for ShiftedImmediate { | ||
type Error = (); | ||
|
||
/// Attempt to convert a u64 into a BitmaskImm. | ||
fn try_from(value: u64) -> Result<Self, Self::Error> { | ||
let mut current = value; | ||
if current < 2_u64.pow(12) { | ||
return Ok(ShiftedImmediate { shift: Shift::LSL0, value: current as u16 }); | ||
} | ||
|
||
if (current & (2_u64.pow(12) - 1) == 0) && ((current >> 12) < 2_u64.pow(12)) { | ||
return Ok(ShiftedImmediate { shift: Shift::LSL12, value: (current >> 12) as u16 }); | ||
} | ||
|
||
Err(()) | ||
} | ||
} | ||
|
||
impl From<ShiftedImmediate> for u32 { | ||
/// Encode a bitmask immediate into a 32-bit value. | ||
fn from(imm: ShiftedImmediate) -> Self { | ||
0 | ||
| (((imm.shift as u32) & 1) << 12) | ||
| (imm.value as u32) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_no_shift() { | ||
let value = 256; | ||
let result = ShiftedImmediate::try_from(value); | ||
|
||
assert!(matches!(result, Ok(ShiftedImmediate { shift: Shift::LSL0, value }))); | ||
} | ||
|
||
#[test] | ||
fn test_maximum_no_shift() { | ||
let value = (1 << 12) - 1; | ||
let result = ShiftedImmediate::try_from(value); | ||
|
||
assert!(matches!(result, Ok(ShiftedImmediate { shift: Shift::LSL0, value }))); | ||
} | ||
|
||
#[test] | ||
fn test_with_shift() { | ||
let result = ShiftedImmediate::try_from(256 << 12); | ||
|
||
assert!(matches!(result, Ok(ShiftedImmediate { shift: Shift::LSL12, value: 256 }))); | ||
} | ||
|
||
#[test] | ||
fn test_unencodable() { | ||
let result = ShiftedImmediate::try_from((256 << 12) + 1); | ||
assert!(matches!(result, Err(()))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.