|
|
@@ -792,6 +792,9 @@ type instructionType int |
|
|
|
const ( |
|
|
|
instrPush instructionType = iota |
|
|
|
instrMove |
|
|
|
// instrTransformingMove is essentially a move, but it performs some |
|
|
|
// transformation of the data during the process. |
|
|
|
instrTransformingMove |
|
|
|
instrJump |
|
|
|
instrConditionalMove |
|
|
|
instrOther |
|
|
@@ -818,6 +821,11 @@ func classifyInstruction(instr string, args []*node32) instructionType { |
|
|
|
if len(args) == 1 { |
|
|
|
return instrJump |
|
|
|
} |
|
|
|
|
|
|
|
case "vpbroadcastq": |
|
|
|
if len(args) == 2 { |
|
|
|
return instrTransformingMove |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return instrOther |
|
|
@@ -870,6 +878,13 @@ func moveTo(w stringWriter, target string, isAVX bool) wrapperFunc { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func finalTransform(w stringWriter, transformInstruction, reg string) wrapperFunc { |
|
|
|
return func(k func()) { |
|
|
|
k() |
|
|
|
w.WriteString("\t" + transformInstruction + " " + reg + ", " + reg + "\n") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func isValidLEATarget(reg string) bool { |
|
|
|
return !strings.HasPrefix(reg, "%xmm") && !strings.HasPrefix(reg, "%ymm") && !strings.HasPrefix(reg, "%zmm") |
|
|
|
} |
|
|
@@ -1018,6 +1033,13 @@ Args: |
|
|
|
case instrMove: |
|
|
|
assertNodeType(argNodes[1], ruleRegisterOrConstant) |
|
|
|
targetReg = d.contents(argNodes[1]) |
|
|
|
case instrTransformingMove: |
|
|
|
assertNodeType(argNodes[1], ruleRegisterOrConstant) |
|
|
|
targetReg = d.contents(argNodes[1]) |
|
|
|
wrappers = append(wrappers, finalTransform(d.output, instructionName, targetReg)) |
|
|
|
if isValidLEATarget(targetReg) { |
|
|
|
return nil, fmt.Errorf("Currently transforming moves are assumed to target XMM registers. Otherwise we'll pop %rax before reading it to do the transform.") |
|
|
|
} |
|
|
|
default: |
|
|
|
return nil, fmt.Errorf("Cannot rewrite GOTPCREL reference for instruction %q", instructionName) |
|
|
|
} |
|
|
|