Skip to content

Commit

Permalink
pulley: sign-extend xconst immediates (bytecodealliance#9075)
Browse files Browse the repository at this point in the history
Change `xconst8`, `xconst16`, `xconst32` and `xconst64` instructions to
sign-extend rather than zero-extend their immediates.

Copyright (c) 2024, Arm Limited.

Signed-off-by: Karl Meakin <[email protected]>
  • Loading branch information
Kmeakin authored Aug 6, 2024
1 parent 28ea648 commit 0077817
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 54 deletions.
28 changes: 13 additions & 15 deletions pulley/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,24 @@ to change, instructions to appear and disappear, and APIs to be overhauled.
Here is the disassembly of `f(a, b) = a + b` in Pulley today:

```
0: 11 1f f0 ff ff ff ff ff ff ff xconst64 x31, 18446744073709551600
a: 12 20 20 1f xadd32 sp, sp, x31
e: 32 20 08 21 store64_offset8 sp, 8, lr
12: 30 20 22 store64 sp, fp
15: 0b 22 20 xmov fp, sp
18: 12 00 00 01 xadd32 x0, x0, x1
1c: 0b 20 22 xmov sp, fp
1f: 25 21 20 08 load64_offset8 lr, sp, 8
23: 22 22 20 load64 fp, sp
26: 0e 1f 10 xconst8 x31, 16
29: 12 20 20 1f xadd32 sp, sp, x31
2d: 00 ret
0: 0e 1f f0 xconst8 x31, -16
3: 12 20 20 1f xadd32 sp, sp, x31
7: 29 20 08 21 store64_offset8 sp, 8, lr
b: 27 20 22 store64 sp, fp
e: 0b 22 20 xmov fp, sp
11: 12 00 00 01 xadd32 x0, x0, x1
15: 0b 20 22 xmov sp, fp
18: 25 21 20 08 load64_offset8 lr, sp, 8
1c: 22 22 20 load64 fp, sp
1f: 0e 1f 10 xconst8 x31, 16
22: 12 20 20 1f xadd32 sp, sp, x31
26: 00 ret
```

Note that there are a number of things that could be improved here:

* We could avoid allocating a deallocating a stack frame because this function's
* We could avoid allocating and deallocating a stack frame because this function's
body doesn't use any stack slots.
* We could sign-extend, rather than zero-extend, constants so that `-16` has a
single-byte encoding instead of an eight-byte encoding.
* We could collapse the whole prologue and epilogue instruction sequences into
super-instructions, since they are identical (modulo the frame size immediate)
for all functions.
Expand Down
16 changes: 8 additions & 8 deletions pulley/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,23 +788,23 @@ impl OpVisitor for InterpreterVisitor<'_> {
Continuation::Continue
}

fn xconst8(&mut self, dst: XReg, imm: u8) -> Self::Return {
self.state.x_mut(dst).set_u64(u64::from(imm));
fn xconst8(&mut self, dst: XReg, imm: i8) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
Continuation::Continue
}

fn xconst16(&mut self, dst: XReg, imm: u16) -> Self::Return {
self.state.x_mut(dst).set_u64(u64::from(imm));
fn xconst16(&mut self, dst: XReg, imm: i16) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
Continuation::Continue
}

fn xconst32(&mut self, dst: XReg, imm: u32) -> Self::Return {
self.state.x_mut(dst).set_u64(u64::from(imm));
fn xconst32(&mut self, dst: XReg, imm: i32) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
Continuation::Continue
}

fn xconst64(&mut self, dst: XReg, imm: u64) -> Self::Return {
self.state.x_mut(dst).set_u64(imm);
fn xconst64(&mut self, dst: XReg, imm: i64) -> Self::Return {
self.state.x_mut(dst).set_i64(imm);
Continuation::Continue
}

Expand Down
14 changes: 7 additions & 7 deletions pulley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ macro_rules! for_each_op {
/// Move between `v` registers.
vmov = Vmov { dst: VReg, src: VReg };

/// Set `dst = zero_extend(imm8)`.
xconst8 = Xconst8 { dst: XReg, imm: u8 };
/// Set `dst = zero_extend(imm16)`.
xconst16 = Xconst16 { dst: XReg, imm: u16 };
/// Set `dst = zero_extend(imm32)`.
xconst32 = Xconst32 { dst: XReg, imm: u32 };
/// Set `dst = sign_extend(imm8)`.
xconst8 = Xconst8 { dst: XReg, imm: i8 };
/// Set `dst = sign_extend(imm16)`.
xconst16 = Xconst16 { dst: XReg, imm: i16 };
/// Set `dst = sign_extend(imm32)`.
xconst32 = Xconst32 { dst: XReg, imm: i32 };
/// Set `dst = imm64`.
xconst64 = Xconst64 { dst: XReg, imm: u64 };
xconst64 = Xconst64 { dst: XReg, imm: i64 };

/// 32-bit wrapping addition: `low32(dst) = low32(src1) + low32(src2)`.
///
Expand Down
12 changes: 6 additions & 6 deletions pulley/src/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ impl XReg {

impl fmt::Display for XReg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
x if *x == Self::SP => write!(f, "sp"),
x if *x == Self::LR => write!(f, "lr"),
x if *x == Self::FP => write!(f, "fp"),
x if *x == Self::SPILL_TMP_0 => write!(f, "spilltmp0"),
x if *x == Self::SPILL_TMP_1 => write!(f, "spilltmp1"),
match *self {
Self::SP => write!(f, "sp"),
Self::LR => write!(f, "lr"),
Self::FP => write!(f, "fp"),
Self::SPILL_TMP_0 => write!(f, "spilltmp0"),
Self::SPILL_TMP_1 => write!(f, "spilltmp1"),
Self(x) => write!(f, "x{x}"),
}
}
Expand Down
28 changes: 14 additions & 14 deletions pulley/tests/all/disas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ fn simple() {
assert_disas(
&[
// Prologue.
Op::Xconst64(Xconst64 {
Op::Xconst8(Xconst8 {
dst: x31,
imm: -16i64 as u64,
imm: -16i8,
}),
Op::Xadd32(Xadd32 {
dst: XReg::SP,
Expand Down Expand Up @@ -84,18 +84,18 @@ fn simple() {
Op::Ret(Ret {}),
],
r#"
0: 11 1f f0 ff ff ff ff ff ff ff xconst64 x31, 18446744073709551600
a: 12 20 20 1f xadd32 sp, sp, x31
e: 29 20 08 21 store64_offset8 sp, 8, lr
12: 27 20 22 store64 sp, fp
15: 0b 22 20 xmov fp, sp
18: 12 00 00 01 xadd32 x0, x0, x1
1c: 0b 20 22 xmov sp, fp
1f: 25 21 20 08 load64_offset8 lr, sp, 8
23: 22 22 20 load64 fp, sp
26: 0e 1f 10 xconst8 x31, 16
29: 12 20 20 1f xadd32 sp, sp, x31
2d: 00 ret
0: 0e 1f f0 xconst8 x31, -16
3: 12 20 20 1f xadd32 sp, sp, x31
7: 29 20 08 21 store64_offset8 sp, 8, lr
b: 27 20 22 store64 sp, fp
e: 0b 22 20 xmov fp, sp
11: 12 00 00 01 xadd32 x0, x0, x1
15: 0b 20 22 xmov sp, fp
18: 25 21 20 08 load64_offset8 lr, sp, 8
1c: 22 22 20 load64 fp, sp
1f: 0e 1f 10 xconst8 x31, 16
22: 12 20 20 1f xadd32 sp, sp, x31
26: 00 ret
"#,
);
}
8 changes: 4 additions & 4 deletions pulley/tests/all/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn f(f: u8) -> FReg {

#[test]
fn xconst8() {
for (expected, imm) in [(42u64, 42u8), (u64::from(u8::MAX), u8::MAX)] {
for (expected, imm) in [(42u64, 42i8), (u64::MAX, -1i8)] {
unsafe {
assert_one(
[(x(0), 0x1234567812345678u64)],
Expand All @@ -86,7 +86,7 @@ fn xconst8() {

#[test]
fn xconst16() {
for (expected, imm) in [(42u64, 42u16), (u64::from(u16::MAX), u16::MAX)] {
for (expected, imm) in [(42u64, 42i16), (u64::MAX, -1i16)] {
unsafe {
assert_one(
[(x(0), 0x1234567812345678u64)],
Expand All @@ -100,7 +100,7 @@ fn xconst16() {

#[test]
fn xconst32() {
for (expected, imm) in [(42u64, 42u32), (u64::from(u32::MAX), u32::MAX)] {
for (expected, imm) in [(42u64, 42i32), (u64::MAX, -1i32)] {
unsafe {
assert_one(
[(x(0), 0x1234567812345678u64)],
Expand All @@ -114,7 +114,7 @@ fn xconst32() {

#[test]
fn xconst64() {
for (expected, imm) in [(42u64, 42u64), (u64::MAX, u64::MAX)] {
for (expected, imm) in [(42u64, 42i64), (u64::MAX, -1i64)] {
unsafe {
assert_one(
[(x(0), 0x1234567812345678u64)],
Expand Down

0 comments on commit 0077817

Please sign in to comment.