Skip to content

Commit 0077817

Browse files
authored
pulley: sign-extend xconst immediates (bytecodealliance#9075)
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]>
1 parent 28ea648 commit 0077817

File tree

6 files changed

+52
-54
lines changed

6 files changed

+52
-54
lines changed

pulley/README.md

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,24 @@ to change, instructions to appear and disappear, and APIs to be overhauled.
4747
Here is the disassembly of `f(a, b) = a + b` in Pulley today:
4848

4949
```
50-
0: 11 1f f0 ff ff ff ff ff ff ff xconst64 x31, 18446744073709551600
51-
a: 12 20 20 1f xadd32 sp, sp, x31
52-
e: 32 20 08 21 store64_offset8 sp, 8, lr
53-
12: 30 20 22 store64 sp, fp
54-
15: 0b 22 20 xmov fp, sp
55-
18: 12 00 00 01 xadd32 x0, x0, x1
56-
1c: 0b 20 22 xmov sp, fp
57-
1f: 25 21 20 08 load64_offset8 lr, sp, 8
58-
23: 22 22 20 load64 fp, sp
59-
26: 0e 1f 10 xconst8 x31, 16
60-
29: 12 20 20 1f xadd32 sp, sp, x31
61-
2d: 00 ret
50+
0: 0e 1f f0 xconst8 x31, -16
51+
3: 12 20 20 1f xadd32 sp, sp, x31
52+
7: 29 20 08 21 store64_offset8 sp, 8, lr
53+
b: 27 20 22 store64 sp, fp
54+
e: 0b 22 20 xmov fp, sp
55+
11: 12 00 00 01 xadd32 x0, x0, x1
56+
15: 0b 20 22 xmov sp, fp
57+
18: 25 21 20 08 load64_offset8 lr, sp, 8
58+
1c: 22 22 20 load64 fp, sp
59+
1f: 0e 1f 10 xconst8 x31, 16
60+
22: 12 20 20 1f xadd32 sp, sp, x31
61+
26: 00 ret
6262
```
6363

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

66-
* We could avoid allocating a deallocating a stack frame because this function's
66+
* We could avoid allocating and deallocating a stack frame because this function's
6767
body doesn't use any stack slots.
68-
* We could sign-extend, rather than zero-extend, constants so that `-16` has a
69-
single-byte encoding instead of an eight-byte encoding.
7068
* We could collapse the whole prologue and epilogue instruction sequences into
7169
super-instructions, since they are identical (modulo the frame size immediate)
7270
for all functions.

pulley/src/interp.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -788,23 +788,23 @@ impl OpVisitor for InterpreterVisitor<'_> {
788788
Continuation::Continue
789789
}
790790

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

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

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

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

pulley/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ macro_rules! for_each_op {
5757
/// Move between `v` registers.
5858
vmov = Vmov { dst: VReg, src: VReg };
5959

60-
/// Set `dst = zero_extend(imm8)`.
61-
xconst8 = Xconst8 { dst: XReg, imm: u8 };
62-
/// Set `dst = zero_extend(imm16)`.
63-
xconst16 = Xconst16 { dst: XReg, imm: u16 };
64-
/// Set `dst = zero_extend(imm32)`.
65-
xconst32 = Xconst32 { dst: XReg, imm: u32 };
60+
/// Set `dst = sign_extend(imm8)`.
61+
xconst8 = Xconst8 { dst: XReg, imm: i8 };
62+
/// Set `dst = sign_extend(imm16)`.
63+
xconst16 = Xconst16 { dst: XReg, imm: i16 };
64+
/// Set `dst = sign_extend(imm32)`.
65+
xconst32 = Xconst32 { dst: XReg, imm: i32 };
6666
/// Set `dst = imm64`.
67-
xconst64 = Xconst64 { dst: XReg, imm: u64 };
67+
xconst64 = Xconst64 { dst: XReg, imm: i64 };
6868

6969
/// 32-bit wrapping addition: `low32(dst) = low32(src1) + low32(src2)`.
7070
///

pulley/src/regs.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,12 @@ impl XReg {
156156

157157
impl fmt::Display for XReg {
158158
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159-
match self {
160-
x if *x == Self::SP => write!(f, "sp"),
161-
x if *x == Self::LR => write!(f, "lr"),
162-
x if *x == Self::FP => write!(f, "fp"),
163-
x if *x == Self::SPILL_TMP_0 => write!(f, "spilltmp0"),
164-
x if *x == Self::SPILL_TMP_1 => write!(f, "spilltmp1"),
159+
match *self {
160+
Self::SP => write!(f, "sp"),
161+
Self::LR => write!(f, "lr"),
162+
Self::FP => write!(f, "fp"),
163+
Self::SPILL_TMP_0 => write!(f, "spilltmp0"),
164+
Self::SPILL_TMP_1 => write!(f, "spilltmp1"),
165165
Self(x) => write!(f, "x{x}"),
166166
}
167167
}

pulley/tests/all/disas.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ fn simple() {
3333
assert_disas(
3434
&[
3535
// Prologue.
36-
Op::Xconst64(Xconst64 {
36+
Op::Xconst8(Xconst8 {
3737
dst: x31,
38-
imm: -16i64 as u64,
38+
imm: -16i8,
3939
}),
4040
Op::Xadd32(Xadd32 {
4141
dst: XReg::SP,
@@ -84,18 +84,18 @@ fn simple() {
8484
Op::Ret(Ret {}),
8585
],
8686
r#"
87-
0: 11 1f f0 ff ff ff ff ff ff ff xconst64 x31, 18446744073709551600
88-
a: 12 20 20 1f xadd32 sp, sp, x31
89-
e: 29 20 08 21 store64_offset8 sp, 8, lr
90-
12: 27 20 22 store64 sp, fp
91-
15: 0b 22 20 xmov fp, sp
92-
18: 12 00 00 01 xadd32 x0, x0, x1
93-
1c: 0b 20 22 xmov sp, fp
94-
1f: 25 21 20 08 load64_offset8 lr, sp, 8
95-
23: 22 22 20 load64 fp, sp
96-
26: 0e 1f 10 xconst8 x31, 16
97-
29: 12 20 20 1f xadd32 sp, sp, x31
98-
2d: 00 ret
87+
0: 0e 1f f0 xconst8 x31, -16
88+
3: 12 20 20 1f xadd32 sp, sp, x31
89+
7: 29 20 08 21 store64_offset8 sp, 8, lr
90+
b: 27 20 22 store64 sp, fp
91+
e: 0b 22 20 xmov fp, sp
92+
11: 12 00 00 01 xadd32 x0, x0, x1
93+
15: 0b 20 22 xmov sp, fp
94+
18: 25 21 20 08 load64_offset8 lr, sp, 8
95+
1c: 22 22 20 load64 fp, sp
96+
1f: 0e 1f 10 xconst8 x31, 16
97+
22: 12 20 20 1f xadd32 sp, sp, x31
98+
26: 00 ret
9999
"#,
100100
);
101101
}

pulley/tests/all/interp.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn f(f: u8) -> FReg {
7272

7373
#[test]
7474
fn xconst8() {
75-
for (expected, imm) in [(42u64, 42u8), (u64::from(u8::MAX), u8::MAX)] {
75+
for (expected, imm) in [(42u64, 42i8), (u64::MAX, -1i8)] {
7676
unsafe {
7777
assert_one(
7878
[(x(0), 0x1234567812345678u64)],
@@ -86,7 +86,7 @@ fn xconst8() {
8686

8787
#[test]
8888
fn xconst16() {
89-
for (expected, imm) in [(42u64, 42u16), (u64::from(u16::MAX), u16::MAX)] {
89+
for (expected, imm) in [(42u64, 42i16), (u64::MAX, -1i16)] {
9090
unsafe {
9191
assert_one(
9292
[(x(0), 0x1234567812345678u64)],
@@ -100,7 +100,7 @@ fn xconst16() {
100100

101101
#[test]
102102
fn xconst32() {
103-
for (expected, imm) in [(42u64, 42u32), (u64::from(u32::MAX), u32::MAX)] {
103+
for (expected, imm) in [(42u64, 42i32), (u64::MAX, -1i32)] {
104104
unsafe {
105105
assert_one(
106106
[(x(0), 0x1234567812345678u64)],
@@ -114,7 +114,7 @@ fn xconst32() {
114114

115115
#[test]
116116
fn xconst64() {
117-
for (expected, imm) in [(42u64, 42u64), (u64::MAX, u64::MAX)] {
117+
for (expected, imm) in [(42u64, 42i64), (u64::MAX, -1i64)] {
118118
unsafe {
119119
assert_one(
120120
[(x(0), 0x1234567812345678u64)],

0 commit comments

Comments
 (0)