Implement ireduce, sextend, and uextend between i8/i16 and i32/i64.
This commit is contained in:
@@ -552,3 +552,35 @@ ebb1:
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
; Tests for i32/i8 conversion instructions.
|
||||
function %I32_I8() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i32 1
|
||||
|
||||
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
|
||||
|
||||
; asm: movsbl %cl, %esi
|
||||
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f be f1
|
||||
|
||||
; asm: movzbl %cl, %esi
|
||||
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b6 f1
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
; Tests for i32/i16 conversion instructions.
|
||||
function %I32_I16() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i32 1
|
||||
|
||||
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
|
||||
|
||||
; asm: movswl %cx, %esi
|
||||
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f bf f1
|
||||
|
||||
; asm: movzwl %cx, %esi
|
||||
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b7 f1
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
@@ -1084,6 +1084,118 @@ ebb2:
|
||||
jump ebb1 ; bin: eb fd
|
||||
}
|
||||
|
||||
; Tests for i32/i8 conversion instructions.
|
||||
function %I32_I8() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i32 1
|
||||
[-,%rsi] v2 = iconst.i32 2
|
||||
[-,%r10] v3 = iconst.i32 3
|
||||
|
||||
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
|
||||
[-,%rsi] v12 = ireduce.i8 v2 ; bin:
|
||||
[-,%r10] v13 = ireduce.i8 v3 ; bin:
|
||||
|
||||
; asm: movsbl %cl, %esi
|
||||
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f be f1
|
||||
; asm: movsbl %sil, %r10d
|
||||
[-,%r10] v21 = sextend.i32 v12 ; bin: 44 0f be d6
|
||||
; asm: movsbl %r10b, %ecx
|
||||
[-,%rcx] v22 = sextend.i32 v13 ; bin: 41 0f be ca
|
||||
|
||||
; asm: movzbl %cl, %esi
|
||||
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b6 f1
|
||||
; asm: movzbl %sil, %r10d
|
||||
[-,%r10] v31 = uextend.i32 v12 ; bin: 44 0f b6 d6
|
||||
; asm: movzbl %r10b, %ecx
|
||||
[-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b6 ca
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
; Tests for i32/i16 conversion instructions.
|
||||
function %I32_I16() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i32 1
|
||||
[-,%rsi] v2 = iconst.i32 2
|
||||
[-,%r10] v3 = iconst.i32 3
|
||||
|
||||
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
|
||||
[-,%rsi] v12 = ireduce.i16 v2 ; bin:
|
||||
[-,%r10] v13 = ireduce.i16 v3 ; bin:
|
||||
|
||||
; asm: movswl %cx, %esi
|
||||
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f bf f1
|
||||
; asm: movswl %si, %r10d
|
||||
[-,%r10] v21 = sextend.i32 v12 ; bin: 44 0f bf d6
|
||||
; asm: movswl %r10w, %ecx
|
||||
[-,%rcx] v22 = sextend.i32 v13 ; bin: 41 0f bf ca
|
||||
|
||||
; asm: movzwl %cx, %esi
|
||||
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b7 f1
|
||||
; asm: movzwl %si, %r10d
|
||||
[-,%r10] v31 = uextend.i32 v12 ; bin: 44 0f b7 d6
|
||||
; asm: movzwl %r10w, %ecx
|
||||
[-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b7 ca
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
; Tests for i64/i8 conversion instructions.
|
||||
function %I64_I8() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i64 1
|
||||
[-,%rsi] v2 = iconst.i64 2
|
||||
[-,%r10] v3 = iconst.i64 3
|
||||
|
||||
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
|
||||
[-,%rsi] v12 = ireduce.i8 v2 ; bin:
|
||||
[-,%r10] v13 = ireduce.i8 v3 ; bin:
|
||||
|
||||
; asm: movsbq %cl, %rsi
|
||||
[-,%rsi] v20 = sextend.i64 v11 ; bin: 48 0f be f1
|
||||
; asm: movsbq %sil, %r10
|
||||
[-,%r10] v21 = sextend.i64 v12 ; bin: 4c 0f be d6
|
||||
; asm: movsbq %r10b, %rcx
|
||||
[-,%rcx] v22 = sextend.i64 v13 ; bin: 49 0f be ca
|
||||
|
||||
; asm: movzbl %cl, %esi
|
||||
[-,%rsi] v30 = uextend.i64 v11 ; bin: 0f b6 f1
|
||||
; asm: movzbl %sil, %r10d
|
||||
[-,%r10] v31 = uextend.i64 v12 ; bin: 44 0f b6 d6
|
||||
; asm: movzbl %r10b, %ecx
|
||||
[-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b6 ca
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
; Tests for i64/i16 conversion instructions.
|
||||
function %I64_I16() {
|
||||
ebb0:
|
||||
[-,%rcx] v1 = iconst.i64 1
|
||||
[-,%rsi] v2 = iconst.i64 2
|
||||
[-,%r10] v3 = iconst.i64 3
|
||||
|
||||
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
|
||||
[-,%rsi] v12 = ireduce.i16 v2 ; bin:
|
||||
[-,%r10] v13 = ireduce.i16 v3 ; bin:
|
||||
|
||||
; asm: movswq %cx, %rsi
|
||||
[-,%rsi] v20 = sextend.i64 v11 ; bin: 48 0f bf f1
|
||||
; asm: movswq %si, %r10
|
||||
[-,%r10] v21 = sextend.i64 v12 ; bin: 4c 0f bf d6
|
||||
; asm: movswq %r10w, %rcx
|
||||
[-,%rcx] v22 = sextend.i64 v13 ; bin: 49 0f bf ca
|
||||
|
||||
; asm: movzwl %cx, %esi
|
||||
[-,%rsi] v30 = uextend.i64 v11 ; bin: 0f b7 f1
|
||||
; asm: movzwl %si, %r10d
|
||||
[-,%r10] v31 = uextend.i64 v12 ; bin: 44 0f b7 d6
|
||||
; asm: movzwl %r10w, %ecx
|
||||
[-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b7 ca
|
||||
|
||||
trap user0 ; bin: 0f 0b
|
||||
}
|
||||
|
||||
; Tests for i64/i32 conversion instructions.
|
||||
function %I64_I32() {
|
||||
ebb0:
|
||||
|
||||
@@ -406,9 +406,55 @@ I64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6))
|
||||
|
||||
# Numerical conversions.
|
||||
|
||||
# Converting i64 to i32 is a no-op in 64-bit mode.
|
||||
# Reducing an integer is a no-op.
|
||||
I32.enc(base.ireduce.i8.i32, r.null, 0)
|
||||
I32.enc(base.ireduce.i16.i32, r.null, 0)
|
||||
I64.enc(base.ireduce.i8.i32, r.null, 0)
|
||||
I64.enc(base.ireduce.i16.i32, r.null, 0)
|
||||
I64.enc(base.ireduce.i8.i64, r.null, 0)
|
||||
I64.enc(base.ireduce.i16.i64, r.null, 0)
|
||||
I64.enc(base.ireduce.i32.i64, r.null, 0)
|
||||
|
||||
# TODO: Add encodings for cbw, cwde, cdqe, which are sign-extending
|
||||
# instructions for %al/%ax/%eax to %ax/%eax/%rax.
|
||||
|
||||
# movsbl
|
||||
I32.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe))
|
||||
I64.enc(base.sextend.i32.i8, *r.urm.rex(0x0f, 0xbe))
|
||||
I64.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe))
|
||||
|
||||
# movswl
|
||||
I32.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf))
|
||||
I64.enc(base.sextend.i32.i16, *r.urm.rex(0x0f, 0xbf))
|
||||
I64.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf))
|
||||
|
||||
# movsbq
|
||||
I64.enc(base.sextend.i64.i8, *r.urm.rex(0x0f, 0xbe, w=1))
|
||||
|
||||
# movswq
|
||||
I64.enc(base.sextend.i64.i16, *r.urm.rex(0x0f, 0xbf, w=1))
|
||||
|
||||
# movslq
|
||||
I64.enc(base.sextend.i64.i32, *r.urm.rex(0x63, w=1))
|
||||
|
||||
# movzbl
|
||||
I32.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6))
|
||||
I64.enc(base.uextend.i32.i8, *r.urm.rex(0x0f, 0xb6))
|
||||
I64.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6))
|
||||
|
||||
# movzwl
|
||||
I32.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7))
|
||||
I64.enc(base.uextend.i32.i16, *r.urm.rex(0x0f, 0xb7))
|
||||
I64.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7))
|
||||
|
||||
# movzbq, encoded as movzbl because it's equivalent and shorter
|
||||
I64.enc(base.uextend.i64.i8, *r.urm.rex(0x0f, 0xb6))
|
||||
I64.enc(base.uextend.i64.i8, *r.urm(0x0f, 0xb6))
|
||||
|
||||
# movzwq, encoded as movzwl because it's equivalent and shorter
|
||||
I64.enc(base.uextend.i64.i16, *r.urm.rex(0x0f, 0xb7))
|
||||
I64.enc(base.uextend.i64.i16, *r.urm(0x0f, 0xb7))
|
||||
|
||||
# A 32-bit register copy clears the high 32 bits.
|
||||
I64.enc(base.uextend.i64.i32, *r.umr.rex(0x89))
|
||||
I64.enc(base.uextend.i64.i32, *r.umr(0x89))
|
||||
|
||||
Reference in New Issue
Block a user