github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go (about) 1 package arm64 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 "testing" 8 9 "github.com/bananabytelabs/wazero/internal/engine/wazevo/backend/regalloc" 10 "github.com/bananabytelabs/wazero/internal/testing/require" 11 ) 12 13 func TestMachine_lowerConstant(t *testing.T) { 14 t.Run("zero i32", func(t *testing.T) { 15 ssaB, m := newSetup() 16 ssaConstInstr := ssaB.AllocateInstruction() 17 ssaConstInstr.AsIconst32(0) 18 ssaB.InsertInstruction(ssaConstInstr) 19 20 vr := m.lowerConstant(ssaConstInstr) 21 machInstr := getPendingInstr(m) 22 require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID()) 23 require.Equal(t, regalloc.RegTypeInt, vr.RegType()) 24 require.Equal(t, mov64, machInstr.kind) 25 require.Equal(t, "mov x128?, xzr", formatEmittedInstructionsInCurrentBlock(m)) 26 }) 27 28 t.Run("zero i64", func(t *testing.T) { 29 ssaB, m := newSetup() 30 ssaConstInstr := ssaB.AllocateInstruction() 31 ssaConstInstr.AsIconst64(0) 32 ssaB.InsertInstruction(ssaConstInstr) 33 34 vr := m.lowerConstant(ssaConstInstr) 35 machInstr := getPendingInstr(m) 36 require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID()) 37 require.Equal(t, regalloc.RegTypeInt, vr.RegType()) 38 require.Equal(t, mov64, machInstr.kind) 39 require.Equal(t, "mov x128?, xzr", formatEmittedInstructionsInCurrentBlock(m)) 40 }) 41 42 t.Run("TypeF32", func(t *testing.T) { 43 ssaB, m := newSetup() 44 ssaConstInstr := ssaB.AllocateInstruction() 45 ssaConstInstr.AsF32const(1.1234) 46 ssaB.InsertInstruction(ssaConstInstr) 47 48 vr := m.lowerConstant(ssaConstInstr) 49 machInstr := getPendingInstr(m) 50 require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID()) 51 require.Equal(t, regalloc.RegTypeFloat, vr.RegType()) 52 require.Equal(t, loadFpuConst32, machInstr.kind) 53 require.Equal(t, uint64(math.Float32bits(1.1234)), machInstr.u1) 54 55 require.Equal(t, "ldr s128?, #8; b 8; data.f32 1.123400", formatEmittedInstructionsInCurrentBlock(m)) 56 }) 57 58 t.Run("TypeF64", func(t *testing.T) { 59 ssaB, m := newSetup() 60 ssaConstInstr := ssaB.AllocateInstruction() 61 ssaConstInstr.AsF64const(-9471.2) 62 ssaB.InsertInstruction(ssaConstInstr) 63 64 vr := m.lowerConstant(ssaConstInstr) 65 machInstr := getPendingInstr(m) 66 require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID()) 67 require.Equal(t, regalloc.RegTypeFloat, vr.RegType()) 68 require.Equal(t, loadFpuConst64, machInstr.kind) 69 require.Equal(t, math.Float64bits(-9471.2), machInstr.u1) 70 71 require.Equal(t, "ldr d128?, #8; b 16; data.f64 -9471.200000", formatEmittedInstructionsInCurrentBlock(m)) 72 }) 73 } 74 75 func TestMachine_lowerConstantI32(t *testing.T) { 76 for _, tc := range []struct { 77 val uint32 78 exp []string 79 }{ 80 {val: 0, exp: []string{"movz w0, #0x0, lsl 0"}}, 81 {val: 0xffff, exp: []string{"movz w0, #0xffff, lsl 0"}}, 82 {val: 0xffff_0000, exp: []string{"movz w0, #0xffff, lsl 16"}}, 83 {val: 0xffff_fffe, exp: []string{"movn w0, #0x1, lsl 0"}}, 84 {val: 0x2, exp: []string{"orr w0, wzr, #0x2"}}, 85 {val: 0x80000001, exp: []string{ 86 "movz w0, #0x1, lsl 0", 87 "movk w0, #0x8000, lsl 16", 88 }}, 89 {val: 0xf00000f, exp: []string{ 90 "movz w0, #0xf, lsl 0", 91 "movk w0, #0xf00, lsl 16", 92 }}, 93 } { 94 tc := tc 95 t.Run(fmt.Sprintf("%#x", tc.val), func(t *testing.T) { 96 _, m := newSetup() 97 m.lowerConstantI32(regToVReg(x0), int32(tc.val)) 98 exp := strings.Join(tc.exp, "\n") 99 require.Equal(t, exp, formatEmittedInstructionsInCurrentBlock(m)) 100 }) 101 } 102 } 103 104 func TestMachine_lowerConstantI64(t *testing.T) { 105 invert := func(v uint64) uint64 { return ^v } 106 for _, tc := range []struct { 107 val uint64 108 exp []string 109 }{ 110 {val: 0x0, exp: []string{"movz x0, #0x0, lsl 0"}}, 111 {val: 0x1, exp: []string{"orr x0, xzr, #0x1"}}, 112 {val: 0x3, exp: []string{"orr x0, xzr, #0x3"}}, 113 {val: 0xfff000, exp: []string{"orr x0, xzr, #0xfff000"}}, 114 {val: 0x8001 << 16, exp: []string{"movz x0, #0x8001, lsl 16"}}, 115 {val: 0x8001 << 32, exp: []string{"movz x0, #0x8001, lsl 32"}}, 116 {val: 0x8001 << 48, exp: []string{"movz x0, #0x8001, lsl 48"}}, 117 {val: invert(0x8001 << 16), exp: []string{"movn x0, #0x8001, lsl 16"}}, 118 {val: invert(0x8001 << 32), exp: []string{"movn x0, #0x8001, lsl 32"}}, 119 {val: invert(0x8001 << 48), exp: []string{"movn x0, #0x8001, lsl 48"}}, 120 {val: 0x80000001 << 16, exp: []string{ 121 "movz x0, #0x1, lsl 16", 122 "movk x0, #0x8000, lsl 32", 123 }}, 124 {val: 0x40000001, exp: []string{ 125 "movz x0, #0x1, lsl 0", 126 "movk x0, #0x4000, lsl 16", 127 }}, 128 {val: 0xffffffffff001000, exp: []string{ 129 "movn x0, #0xefff, lsl 0", 130 "movk x0, #0xff00, lsl 16", 131 }}, 132 {val: 0xffff0000c466361f, exp: []string{ 133 "movz x0, #0x361f, lsl 0", 134 "movk x0, #0xc466, lsl 16", 135 "movk x0, #0xffff, lsl 48", 136 }}, 137 {val: 0x89705f4136b4a598, exp: []string{ 138 "movz x0, #0xa598, lsl 0", 139 "movk x0, #0x36b4, lsl 16", 140 "movk x0, #0x5f41, lsl 32", 141 "movk x0, #0x8970, lsl 48", 142 }}, 143 {val: 0xffff_0001_0001_0001, exp: []string{ 144 "movn x0, #0xfffe, lsl 0", 145 "movk x0, #0x1, lsl 16", 146 "movk x0, #0x1, lsl 32", 147 }}, 148 } { 149 tc := tc 150 t.Run(fmt.Sprintf("%#x", tc.val), func(t *testing.T) { 151 _, m := newSetup() 152 m.lowerConstantI64(regToVReg(x0), int64(tc.val)) 153 exp := strings.Join(tc.exp, "\n") 154 require.Equal(t, exp, formatEmittedInstructionsInCurrentBlock(m)) 155 }) 156 } 157 }