x64: Refactor and fill out some gpr-vs-xmm bits (#6058)

* x64: Add instruction helpers for `mov{d,q}`

These will soon grow AVX-equivalents so move them to instruction helpers
to have clauses for AVX in the future.

* x64: Don't auto-convert between RegMemImm and XmmMemImm

The previous conversion, `mov_rmi_to_xmm`, would move from GPR registers
to XMM registers which isn't what many of the other `convert` statements
between these newtypes do. This seemed like a possible footgun so I've
removed the auto-conversion and added an explicit helper to go from a
`u32` to an `XmmMemImm`.

* x64: Add AVX encodings of some more GPR-related insns

This commit adds some more support for AVX instructions where GPRs are
in use mixed in with XMM registers. This required a few more variants of
`Inst` to handle the new instructions.

* Fix vpmovmskb encoding

* Fix xmm-to-gpr encoding of vmovd/vmovq

* Fix typo

* Fix rebase conflict

* Fix rebase conflict with tests
This commit is contained in:
Alex Crichton
2023-03-22 09:58:09 -05:00
committed by GitHub
parent a1072007b8
commit 2fde25311e
14 changed files with 695 additions and 83 deletions

View File

@@ -320,6 +320,21 @@
(dst WritableGpr)
(imm u8))
;; XMM (scalar) unary op (from integer to float reg): vmovd, vmovq,
;; vcvtsi2s{s,d}
(GprToXmmVex (op AvxOpcode)
(src GprMem)
(dst WritableXmm)
(src_size OperandSize))
;; XMM (scalar) unary op (from xmm to integer reg): vmovd, vmovq,
;; vcvtts{s,d}2si
(XmmToGprVex (op AvxOpcode)
(src Xmm)
(dst WritableGpr)
(dst_size OperandSize))
;; XMM (scalar or vector) binary op that relies on the EVEX
;; prefix. Takes two inputs.
(XmmRmREvex (op Avx512Opcode)
@@ -1277,6 +1292,13 @@
Vpbroadcastw
Vpbroadcastd
Vbroadcastss
Vmovd
Vmovq
Vmovmskps
Vmovmskpd
Vpmovmskb
Vcvtsi2ss
Vcvtsi2sd
))
(type Avx512Opcode extern
@@ -1539,6 +1561,10 @@
(decl lo_gpr (Value) Gpr)
(rule (lo_gpr regs) (gpr_new (lo_reg regs)))
;; Construct a new `XmmMemImm` from a 32-bit immediate.
(decl xmi_imm (u32) XmmMemImm)
(extern constructor xmi_imm xmi_imm)
;;;; Helpers for Working With Integer Comparison Codes ;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1818,10 +1844,7 @@
(decl mov_rmi_to_xmm (RegMemImm) XmmMemImm)
(rule (mov_rmi_to_xmm rmi @ (RegMemImm.Mem _)) (xmm_mem_imm_new rmi))
(rule (mov_rmi_to_xmm rmi @ (RegMemImm.Imm _)) (xmm_mem_imm_new rmi))
(rule (mov_rmi_to_xmm (RegMemImm.Reg r))
(gpr_to_xmm (SseOpcode.Movd)
r
(OperandSize.Size32)))
(rule (mov_rmi_to_xmm (RegMemImm.Reg r)) (x64_movd_to_xmm r))
;;;; Helpers for Emitting Calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1941,9 +1964,37 @@
(if-let $true (use_avx_simd))
(xmm_movrm_vex (AvxOpcode.Vmovupd) addr data))
(decl x64_movd (Xmm) Gpr)
(rule (x64_movd from)
;; Helper for creating `movd` instructions.
(decl x64_movd_to_gpr (Xmm) Gpr)
(rule (x64_movd_to_gpr from)
(xmm_to_gpr (SseOpcode.Movd) from (OperandSize.Size32)))
(rule 1 (x64_movd_to_gpr from)
(if-let $true (use_avx_simd))
(xmm_to_gpr_vex (AvxOpcode.Vmovd) from (OperandSize.Size32)))
;; Helper for creating `movd` instructions.
(decl x64_movd_to_xmm (GprMem) Xmm)
(rule (x64_movd_to_xmm from)
(gpr_to_xmm (SseOpcode.Movd) from (OperandSize.Size32)))
(rule 1 (x64_movd_to_xmm from)
(if-let $true (use_avx_simd))
(gpr_to_xmm_vex (AvxOpcode.Vmovd) from (OperandSize.Size32)))
;; Helper for creating `movq` instructions.
(decl x64_movq_to_xmm (GprMem) Xmm)
(rule (x64_movq_to_xmm src)
(gpr_to_xmm (SseOpcode.Movq) src (OperandSize.Size64)))
(rule 1 (x64_movq_to_xmm from)
(if-let $true (use_avx_simd))
(gpr_to_xmm_vex (AvxOpcode.Vmovq) from (OperandSize.Size64)))
;; Helper for creating `movq` instructions.
(decl x64_movq_to_gpr (Xmm) Gpr)
(rule (x64_movq_to_gpr src)
(xmm_to_gpr (SseOpcode.Movq) src (OperandSize.Size64)))
(rule 1 (x64_movq_to_gpr from)
(if-let $true (use_avx_simd))
(xmm_to_gpr_vex (AvxOpcode.Vmovq) from (OperandSize.Size64)))
(decl x64_movdqu_load (XmmMem) Xmm)
(rule (x64_movdqu_load from)
@@ -2186,15 +2237,11 @@
;; `f32` immediates.
(rule 2 (imm $F32 (u64_nonzero bits))
(gpr_to_xmm (SseOpcode.Movd)
(imm $I32 bits)
(OperandSize.Size32)))
(x64_movd_to_xmm (imm $I32 bits)))
;; `f64` immediates.
(rule 2 (imm $F64 (u64_nonzero bits))
(gpr_to_xmm (SseOpcode.Movq)
(imm $I64 bits)
(OperandSize.Size64)))
(x64_movq_to_xmm (imm $I64 bits)))
;; Special case for when a 64-bit immediate fits into 32-bits. We can use a
;; 32-bit move that zero-extends the value, which has a smaller encoding.
@@ -3663,20 +3710,44 @@
(_ Unit (emit (MInst.XmmToGprImmVex op src dst imm))))
dst))
;; Helper for creating `MInst.XmmToGprVex` instructions.
(decl xmm_to_gpr_vex (AvxOpcode Xmm OperandSize) Gpr)
(rule (xmm_to_gpr_vex op src size)
(let ((dst WritableGpr (temp_writable_gpr))
(_ Unit (emit (MInst.XmmToGprVex op src dst size))))
dst))
;; Helper for creating `MInst.GprToXmmVex` instructions.
(decl gpr_to_xmm_vex (AvxOpcode GprMem OperandSize) Xmm)
(rule (gpr_to_xmm_vex op src size)
(let ((dst WritableXmm (temp_writable_xmm))
(_ Unit (emit (MInst.GprToXmmVex op src dst size))))
dst))
;; Helper for creating `pmovmskb` instructions.
(decl x64_pmovmskb (OperandSize Xmm) Gpr)
(rule (x64_pmovmskb size src)
(xmm_to_gpr (SseOpcode.Pmovmskb) src size))
(rule 1 (x64_pmovmskb size src)
(if-let $true (use_avx_simd))
(xmm_to_gpr_vex (AvxOpcode.Vpmovmskb) src size))
;; Helper for creating `movmskps` instructions.
(decl x64_movmskps (OperandSize Xmm) Gpr)
(rule (x64_movmskps size src)
(xmm_to_gpr (SseOpcode.Movmskps) src size))
(rule 1 (x64_movmskps size src)
(if-let $true (use_avx_simd))
(xmm_to_gpr_vex (AvxOpcode.Vmovmskps) src size))
;; Helper for creating `movmskpd` instructions.
(decl x64_movmskpd (OperandSize Xmm) Gpr)
(rule (x64_movmskpd size src)
(xmm_to_gpr (SseOpcode.Movmskpd) src size))
(rule 1 (x64_movmskpd size src)
(if-let $true (use_avx_simd))
(xmm_to_gpr_vex (AvxOpcode.Vmovmskpd) src size))
;; Helper for creating `MInst.GprToXmm` instructions.
(decl gpr_to_xmm (SseOpcode GprMem OperandSize) Xmm)
@@ -3973,11 +4044,17 @@
(decl x64_cvtsi2ss (Type GprMem) Xmm)
(rule (x64_cvtsi2ss ty x)
(gpr_to_xmm (SseOpcode.Cvtsi2ss) x (raw_operand_size_of_type ty)))
(rule 1 (x64_cvtsi2ss ty x)
(if-let $true (use_avx_simd))
(gpr_to_xmm_vex (AvxOpcode.Vcvtsi2ss) x (raw_operand_size_of_type ty)))
;; Helper for creating `cvtsi2sd` instructions.
(decl x64_cvtsi2sd (Type GprMem) Xmm)
(rule (x64_cvtsi2sd ty x)
(gpr_to_xmm (SseOpcode.Cvtsi2sd) x (raw_operand_size_of_type ty)))
(rule 1 (x64_cvtsi2sd ty x)
(if-let $true (use_avx_simd))
(gpr_to_xmm_vex (AvxOpcode.Vcvtsi2sd) x (raw_operand_size_of_type ty)))
;; Helper for creating `cvttps2dq` instructions.
(decl x64_cvttps2dq (XmmMem) Xmm)
@@ -4486,15 +4563,15 @@
(decl bitcast_xmm_to_gpr (Type Xmm) Gpr)
(rule (bitcast_xmm_to_gpr $F32 src)
(xmm_to_gpr (SseOpcode.Movd) src (OperandSize.Size32)))
(x64_movd_to_gpr src))
(rule (bitcast_xmm_to_gpr $F64 src)
(xmm_to_gpr (SseOpcode.Movq) src (OperandSize.Size64)))
(x64_movq_to_gpr src))
(decl bitcast_gpr_to_xmm (Type Gpr) Xmm)
(rule (bitcast_gpr_to_xmm $I32 src)
(gpr_to_xmm (SseOpcode.Movd) src (OperandSize.Size32)))
(x64_movd_to_xmm src))
(rule (bitcast_gpr_to_xmm $I64 src)
(gpr_to_xmm (SseOpcode.Movq) src (OperandSize.Size64)))
(x64_movq_to_xmm src))
;;;; Stack Addresses ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -4678,7 +4755,6 @@
(convert Reg XmmMem reg_to_xmm_mem)
(convert Reg RegMemImm reg_to_reg_mem_imm)
(convert RegMem XmmMem reg_mem_to_xmm_mem)
(convert RegMemImm XmmMemImm mov_rmi_to_xmm)
(convert Xmm XmmMem xmm_to_xmm_mem)
(convert Xmm XmmMemImm xmm_to_xmm_mem_imm)
(convert Xmm XmmMemAligned xmm_to_xmm_mem_aligned)