feat(amd64): encode the mixed-width extend family and PMOVMSKB
Assisted-by: GLM 5.3
This commit is contained in:
+40
-13
@@ -838,15 +838,24 @@ func (e *enc) encodeBswap(ops []Operand, size int) error {
|
||||
// width. The source is narrower than the destination, so the plain size-suffix
|
||||
// convention does not apply to these names.
|
||||
var movExtendOp = map[string]struct {
|
||||
op []byte
|
||||
dst64 bool
|
||||
op []byte
|
||||
dstSize int
|
||||
}{
|
||||
"MOVBLZX": {[]byte{0x0F, 0xB6}, false}, // byte → long, zero-extend
|
||||
"MOVBQZX": {[]byte{0x0F, 0xB6}, true}, // byte → quad, zero-extend
|
||||
"MOVWLZX": {[]byte{0x0F, 0xB7}, false}, // word → long, zero-extend
|
||||
"MOVWQZX": {[]byte{0x0F, 0xB7}, true}, // word → quad, zero-extend
|
||||
"MOVWLSX": {[]byte{0x0F, 0xBF}, false}, // word → long, sign-extend
|
||||
"MOVLQSX": {[]byte{0x63}, true}, // long → quad, sign-extend (MOVSXD)
|
||||
"MOVBLZX": {[]byte{0x0F, 0xB6}, 4}, // byte → long, zero-extend
|
||||
"MOVBQZX": {[]byte{0x0F, 0xB6}, 8}, // byte → quad, zero-extend
|
||||
"MOVWLZX": {[]byte{0x0F, 0xB7}, 4}, // word → long, zero-extend
|
||||
"MOVWQZX": {[]byte{0x0F, 0xB7}, 8}, // word → quad, zero-extend
|
||||
"MOVWLSX": {[]byte{0x0F, 0xBF}, 4}, // word → long, sign-extend
|
||||
"MOVLQSX": {[]byte{0x63}, 8}, // long → quad, sign-extend (MOVSXD)
|
||||
"MOVBWZX": {[]byte{0x0F, 0xB6}, 2}, // byte → word, zero-extend
|
||||
"MOVBWSX": {[]byte{0x0F, 0xBE}, 2}, // byte → word, sign-extend
|
||||
"MOVBLSX": {[]byte{0x0F, 0xBE}, 4}, // byte → long, sign-extend
|
||||
"MOVBQSX": {[]byte{0x0F, 0xBE}, 8}, // byte → quad, sign-extend
|
||||
"MOVWQSX": {[]byte{0x0F, 0xBF}, 8}, // word → quad, sign-extend
|
||||
// A long → quad zero-extend is a plain 32-bit move: every 32-bit
|
||||
// operation zero-extends its result into the full register, so the
|
||||
// toolchain lowers MOVLQZX to the plain MOVL encoding.
|
||||
"MOVLQZX": {[]byte{0x8B}, 4},
|
||||
}
|
||||
|
||||
// encodeMovExtend encodes a mixed-width extending move: reg = dst (the wider
|
||||
@@ -860,12 +869,30 @@ func (e *enc) encodeMovExtend(base string, ops []Operand) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("%s destination must be a register", base)
|
||||
}
|
||||
size := 4
|
||||
if spec.dst64 {
|
||||
size = 8
|
||||
i := newInstr(spec.dstSize, spec.op)
|
||||
if err := setRM(i, dstReg, ops[0], spec.dstSize); err != nil {
|
||||
return err
|
||||
}
|
||||
i := newInstr(size, spec.op)
|
||||
if err := setRM(i, dstReg, ops[0], size); err != nil {
|
||||
return e.emit(i)
|
||||
}
|
||||
|
||||
// encodePmovmskb encodes PMOVMSKB, the legacy SSE2 byte mask extract: the
|
||||
// XMM source's sign bytes pack into a GP destination, 66 0F D7 /r.
|
||||
func (e *enc) encodePmovmskb(base string, ops []Operand) error {
|
||||
if len(ops) != 2 {
|
||||
return fmt.Errorf("%s expects 2 operands, got %d", base, len(ops))
|
||||
}
|
||||
srcReg, srcVec := vecReg(ops[0])
|
||||
if !srcVec {
|
||||
return fmt.Errorf("%s source must be an XMM register", base)
|
||||
}
|
||||
dstReg, ok := ops[1].(Reg)
|
||||
if !ok {
|
||||
return fmt.Errorf("%s destination must be a register", base)
|
||||
}
|
||||
i := newInstr(4, []byte{0x0F, 0xD7})
|
||||
i.prefix = 0x66
|
||||
if err := setRM(i, dstReg, srcReg, 4); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.emit(i)
|
||||
|
||||
Reference in New Issue
Block a user