Support three-argument instructions on x86-64.
Change-Id: I81c855cd4805d4a5016999669a0cb5261838f23a Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/35224 Commit-Queue: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
3390fd88d7
commit
1d1345377a
@ -801,6 +801,8 @@ const (
|
||||
// instrCombine merges the source and destination in some fashion, for example
|
||||
// a 2-operand bitwise operation.
|
||||
instrCombine
|
||||
// instrThreeArg merges two sources into a destination in some fashion.
|
||||
instrThreeArg
|
||||
instrOther
|
||||
)
|
||||
|
||||
@ -831,6 +833,11 @@ func classifyInstruction(instr string, args []*node32) instructionType {
|
||||
return instrCombine
|
||||
}
|
||||
|
||||
case "sarxq", "shlxq", "shrxq":
|
||||
if len(args) == 3 {
|
||||
return instrThreeArg
|
||||
}
|
||||
|
||||
case "vpbroadcastq":
|
||||
if len(args) == 2 {
|
||||
return instrTransformingMove
|
||||
@ -878,10 +885,24 @@ func saveFlags(w stringWriter, redzoneCleared bool) wrapperFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func saveRegister(w stringWriter, avoidReg string) (wrapperFunc, string) {
|
||||
reg := "%rax"
|
||||
if reg == avoidReg {
|
||||
reg = "%rbx"
|
||||
func saveRegister(w stringWriter, avoidRegs []string) (wrapperFunc, string) {
|
||||
candidates := []string{"%rax", "%rbx", "%rcx", "%rdx"}
|
||||
|
||||
var reg string
|
||||
NextCandidate:
|
||||
for _, candidate := range candidates {
|
||||
for _, avoid := range avoidRegs {
|
||||
if candidate == avoid {
|
||||
continue NextCandidate
|
||||
}
|
||||
}
|
||||
|
||||
reg = candidate
|
||||
break
|
||||
}
|
||||
|
||||
if len(reg) == 0 {
|
||||
panic("too many excluded registers")
|
||||
}
|
||||
|
||||
return func(k func()) {
|
||||
@ -918,6 +939,13 @@ func combineOp(w stringWriter, instructionName, source, dest string) wrapperFunc
|
||||
}
|
||||
}
|
||||
|
||||
func threeArgCombineOp(w stringWriter, instructionName, source1, source2, dest string) wrapperFunc {
|
||||
return func(k func()) {
|
||||
k()
|
||||
w.WriteString("\t" + instructionName + " " + source1 + ", " + source2 + ", " + dest + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func isValidLEATarget(reg string) bool {
|
||||
return !strings.HasPrefix(reg, "%xmm") && !strings.HasPrefix(reg, "%ymm") && !strings.HasPrefix(reg, "%zmm")
|
||||
}
|
||||
@ -1033,9 +1061,6 @@ Args:
|
||||
if len(offset) > 0 {
|
||||
return nil, errors.New("loading from GOT with offset is unsupported")
|
||||
}
|
||||
if i != 0 {
|
||||
return nil, errors.New("GOT access must be source operand")
|
||||
}
|
||||
if !d.isRIPRelative(memRef) {
|
||||
return nil, errors.New("GOT access must be IP-relative")
|
||||
}
|
||||
@ -1048,10 +1073,15 @@ Args:
|
||||
useGOT = true
|
||||
}
|
||||
|
||||
classification := classifyInstruction(instructionName, argNodes)
|
||||
if classification != instrThreeArg && i != 0 {
|
||||
return nil, errors.New("GOT access must be source operand")
|
||||
}
|
||||
|
||||
// Reduce the instruction to movq symbol@GOTPCREL, targetReg.
|
||||
var targetReg string
|
||||
var redzoneCleared bool
|
||||
switch classifyInstruction(instructionName, argNodes) {
|
||||
switch classification {
|
||||
case instrPush:
|
||||
wrappers = append(wrappers, push(d.output))
|
||||
targetReg = "%rax"
|
||||
@ -1073,12 +1103,36 @@ Args:
|
||||
if !isValidLEATarget(targetReg) {
|
||||
return nil, fmt.Errorf("cannot handle combining instructions targeting non-general registers")
|
||||
}
|
||||
saveRegWrapper, tempReg := saveRegister(d.output, targetReg)
|
||||
saveRegWrapper, tempReg := saveRegister(d.output, []string{targetReg})
|
||||
redzoneCleared = true
|
||||
wrappers = append(wrappers, saveRegWrapper)
|
||||
|
||||
wrappers = append(wrappers, combineOp(d.output, instructionName, tempReg, targetReg))
|
||||
targetReg = tempReg
|
||||
case instrThreeArg:
|
||||
if n := len(argNodes); n != 3 {
|
||||
return nil, fmt.Errorf("three-argument instruction has %d arguments", n)
|
||||
}
|
||||
if i != 0 && i != 1 {
|
||||
return nil, errors.New("GOT access must be from soure operand")
|
||||
}
|
||||
targetReg = d.contents(argNodes[2])
|
||||
|
||||
otherSource := d.contents(argNodes[1])
|
||||
if i == 1 {
|
||||
otherSource = d.contents(argNodes[0])
|
||||
}
|
||||
|
||||
saveRegWrapper, tempReg := saveRegister(d.output, []string{targetReg, otherSource})
|
||||
redzoneCleared = true
|
||||
wrappers = append(wrappers, saveRegWrapper)
|
||||
|
||||
if i == 0 {
|
||||
wrappers = append(wrappers, threeArgCombineOp(d.output, instructionName, tempReg, otherSource, targetReg))
|
||||
} else {
|
||||
wrappers = append(wrappers, threeArgCombineOp(d.output, instructionName, otherSource, tempReg, targetReg))
|
||||
}
|
||||
targetReg = tempReg
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot rewrite GOTPCREL reference for instruction %q", instructionName)
|
||||
}
|
||||
@ -1087,7 +1141,7 @@ Args:
|
||||
// Sometimes the compiler will load from the GOT to an
|
||||
// XMM register, which is not a valid target of an LEA
|
||||
// instruction.
|
||||
saveRegWrapper, tempReg := saveRegister(d.output, "")
|
||||
saveRegWrapper, tempReg := saveRegister(d.output, nil)
|
||||
wrappers = append(wrappers, saveRegWrapper)
|
||||
isAVX := strings.HasPrefix(instructionName, "v")
|
||||
wrappers = append(wrappers, moveTo(d.output, targetReg, isAVX, tempReg))
|
||||
|
@ -48,6 +48,7 @@ var delocateTests = []delocateTest{
|
||||
{"x86_64-GOTRewrite", []string{"in.s"}, "out.s"},
|
||||
{"x86_64-LabelRewrite", []string{"in1.s", "in2.s"}, "out.s"},
|
||||
{"x86_64-Sections", []string{"in.s"}, "out.s"},
|
||||
{"x86_64-ThreeArg", []string{"in.s"}, "out.s"},
|
||||
}
|
||||
|
||||
func TestDelocate(t *testing.T) {
|
||||
|
14
util/fipstools/delocate/testdata/x86_64-ThreeArg/in.s
vendored
Normal file
14
util/fipstools/delocate/testdata/x86_64-ThreeArg/in.s
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
.type foo, @function
|
||||
.globl foo
|
||||
foo:
|
||||
movq %rax, %rax
|
||||
shrxq %rbx, kBoringSSLRSASqrtTwo@GOTPCREL(%rip), %rax
|
||||
shrxq kBoringSSLRSASqrtTwo@GOTPCREL(%rip), %rbx, %rax
|
||||
|
||||
|
||||
.type kBoringSSLRSASqrtTwo,@object # @kBoringSSLRSASqrtTwo
|
||||
.section .rodata,"a",@progbits,unique,760
|
||||
.globl kBoringSSLRSASqrtTwo
|
||||
.p2align 4
|
||||
kBoringSSLRSASqrtTwo:
|
||||
.quad -2404814165548301886 # 0xdea06241f7aa81c2
|
114
util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s
vendored
Normal file
114
util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
.text
|
||||
.file 1 "inserted_by_delocate.c"
|
||||
.loc 1 1 0
|
||||
BORINGSSL_bcm_text_start:
|
||||
.type foo, @function
|
||||
.globl foo
|
||||
.Lfoo_local_target:
|
||||
foo:
|
||||
movq %rax, %rax
|
||||
# WAS shrxq %rbx, kBoringSSLRSASqrtTwo@GOTPCREL(%rip), %rax
|
||||
leaq -128(%rsp), %rsp
|
||||
pushq %rcx
|
||||
leaq .LkBoringSSLRSASqrtTwo_local_target(%rip), %rcx
|
||||
shrxq %rbx, %rcx, %rax
|
||||
popq %rcx
|
||||
leaq 128(%rsp), %rsp
|
||||
# WAS shrxq kBoringSSLRSASqrtTwo@GOTPCREL(%rip), %rbx, %rax
|
||||
leaq -128(%rsp), %rsp
|
||||
pushq %rcx
|
||||
leaq .LkBoringSSLRSASqrtTwo_local_target(%rip), %rcx
|
||||
shrxq %rcx, %rbx, %rax
|
||||
popq %rcx
|
||||
leaq 128(%rsp), %rsp
|
||||
|
||||
|
||||
.type kBoringSSLRSASqrtTwo,@object # @kBoringSSLRSASqrtTwo
|
||||
# WAS .section .rodata,"a",@progbits,unique,760
|
||||
.text
|
||||
.globl kBoringSSLRSASqrtTwo
|
||||
.p2align 4
|
||||
.LkBoringSSLRSASqrtTwo_local_target:
|
||||
kBoringSSLRSASqrtTwo:
|
||||
.quad -2404814165548301886 # 0xdea06241f7aa81c2
|
||||
.text
|
||||
.loc 1 2 0
|
||||
BORINGSSL_bcm_text_end:
|
||||
.type OPENSSL_ia32cap_get, @function
|
||||
.globl OPENSSL_ia32cap_get
|
||||
.LOPENSSL_ia32cap_get_local_target:
|
||||
OPENSSL_ia32cap_get:
|
||||
leaq OPENSSL_ia32cap_P(%rip), %rax
|
||||
ret
|
||||
.extern OPENSSL_ia32cap_P
|
||||
.type OPENSSL_ia32cap_addr_delta, @object
|
||||
.size OPENSSL_ia32cap_addr_delta, 8
|
||||
OPENSSL_ia32cap_addr_delta:
|
||||
.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
|
||||
.type BORINGSSL_bcm_text_hash, @object
|
||||
.size BORINGSSL_bcm_text_hash, 64
|
||||
BORINGSSL_bcm_text_hash:
|
||||
.byte 0xae
|
||||
.byte 0x2c
|
||||
.byte 0xea
|
||||
.byte 0x2a
|
||||
.byte 0xbd
|
||||
.byte 0xa6
|
||||
.byte 0xf3
|
||||
.byte 0xec
|
||||
.byte 0x97
|
||||
.byte 0x7f
|
||||
.byte 0x9b
|
||||
.byte 0xf6
|
||||
.byte 0x94
|
||||
.byte 0x9a
|
||||
.byte 0xfc
|
||||
.byte 0x83
|
||||
.byte 0x68
|
||||
.byte 0x27
|
||||
.byte 0xcb
|
||||
.byte 0xa0
|
||||
.byte 0xa0
|
||||
.byte 0x9f
|
||||
.byte 0x6b
|
||||
.byte 0x6f
|
||||
.byte 0xde
|
||||
.byte 0x52
|
||||
.byte 0xcd
|
||||
.byte 0xe2
|
||||
.byte 0xcd
|
||||
.byte 0xff
|
||||
.byte 0x31
|
||||
.byte 0x80
|
||||
.byte 0xa2
|
||||
.byte 0xd4
|
||||
.byte 0xc3
|
||||
.byte 0x66
|
||||
.byte 0xf
|
||||
.byte 0xc2
|
||||
.byte 0x6a
|
||||
.byte 0x7b
|
||||
.byte 0xf4
|
||||
.byte 0xbe
|
||||
.byte 0x39
|
||||
.byte 0xa2
|
||||
.byte 0xd7
|
||||
.byte 0x25
|
||||
.byte 0xdb
|
||||
.byte 0x21
|
||||
.byte 0x98
|
||||
.byte 0xe9
|
||||
.byte 0xd5
|
||||
.byte 0x53
|
||||
.byte 0xbf
|
||||
.byte 0x5c
|
||||
.byte 0x32
|
||||
.byte 0x6
|
||||
.byte 0x83
|
||||
.byte 0x34
|
||||
.byte 0xc
|
||||
.byte 0x65
|
||||
.byte 0x89
|
||||
.byte 0x52
|
||||
.byte 0xbd
|
||||
.byte 0x1f
|
Loading…
Reference in New Issue
Block a user