diff --git a/cranelift/filetests/isa/intel/binary32.cton b/cranelift/filetests/isa/intel/binary32.cton index 7d3e3a683b..df98a86515 100644 --- a/cranelift/filetests/isa/intel/binary32.cton +++ b/cranelift/filetests/isa/intel/binary32.cton @@ -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 +} diff --git a/cranelift/filetests/isa/intel/binary64.cton b/cranelift/filetests/isa/intel/binary64.cton index b579b4d58d..9eca950ee6 100644 --- a/cranelift/filetests/isa/intel/binary64.cton +++ b/cranelift/filetests/isa/intel/binary64.cton @@ -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: diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index f9b77a04bd..162caccf65 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -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))