2015-03-08 14:11:41 +01:00
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
// This file encapsulates some of the odd characteristics of the ARM64
|
|
|
|
|
// instruction set, to minimize its interaction with the core of the
|
|
|
|
|
// assembler.
|
|
|
|
|
|
|
|
|
|
package arch
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"cmd/internal/obj/arm64"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var arm64LS = map[string]uint8{
|
|
|
|
|
"P": arm64.C_XPOST,
|
|
|
|
|
"W": arm64.C_XPRE,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var arm64Jump = map[string]bool{
|
|
|
|
|
"B": true,
|
|
|
|
|
"BL": true,
|
|
|
|
|
"BEQ": true,
|
|
|
|
|
"BNE": true,
|
|
|
|
|
"BCS": true,
|
|
|
|
|
"BHS": true,
|
|
|
|
|
"BCC": true,
|
|
|
|
|
"BLO": true,
|
|
|
|
|
"BMI": true,
|
|
|
|
|
"BPL": true,
|
|
|
|
|
"BVS": true,
|
|
|
|
|
"BVC": true,
|
|
|
|
|
"BHI": true,
|
|
|
|
|
"BLS": true,
|
|
|
|
|
"BGE": true,
|
|
|
|
|
"BLT": true,
|
|
|
|
|
"BGT": true,
|
|
|
|
|
"BLE": true,
|
|
|
|
|
"CALL": true,
|
|
|
|
|
"CBZ": true,
|
|
|
|
|
"CBZW": true,
|
|
|
|
|
"CBNZ": true,
|
|
|
|
|
"CBNZW": true,
|
2015-07-27 23:26:26 -04:00
|
|
|
"JMP": true,
|
2016-11-28 10:35:12 +08:00
|
|
|
"TBNZ": true,
|
|
|
|
|
"TBZ": true,
|
2015-03-08 14:11:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func jumpArm64(word string) bool {
|
|
|
|
|
return arm64Jump[word]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsARM64CMP reports whether the op (as defined by an arm.A* constant) is
|
|
|
|
|
// one of the comparison instructions that require special handling.
|
2016-03-07 18:00:08 -08:00
|
|
|
func IsARM64CMP(op obj.As) bool {
|
2015-03-08 14:11:41 +01:00
|
|
|
switch op {
|
|
|
|
|
case arm64.ACMN, arm64.ACMP, arm64.ATST,
|
2017-06-13 12:24:19 +00:00
|
|
|
arm64.ACMNW, arm64.ACMPW, arm64.ATSTW,
|
|
|
|
|
arm64.AFCMPS, arm64.AFCMPD,
|
|
|
|
|
arm64.AFCMPES, arm64.AFCMPED:
|
2015-03-08 14:11:41 +01:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsARM64STLXR reports whether the op (as defined by an arm64.A*
|
|
|
|
|
// constant) is one of the STLXR-like instructions that require special
|
|
|
|
|
// handling.
|
2016-03-07 18:00:08 -08:00
|
|
|
func IsARM64STLXR(op obj.As) bool {
|
2015-03-08 14:11:41 +01:00
|
|
|
switch op {
|
2017-06-14 06:24:18 +00:00
|
|
|
case arm64.ASTLXRB, arm64.ASTLXRH, arm64.ASTLXRW, arm64.ASTLXR,
|
|
|
|
|
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR:
|
2015-03-08 14:11:41 +01:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ARM64Suffix handles the special suffix for the ARM64.
|
|
|
|
|
// It returns a boolean to indicate success; failure means
|
|
|
|
|
// cond was unrecognized.
|
|
|
|
|
func ARM64Suffix(prog *obj.Prog, cond string) bool {
|
|
|
|
|
if cond == "" {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
bits, ok := ParseARM64Suffix(cond)
|
|
|
|
|
if !ok {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
prog.Scond = bits
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseARM64Suffix parses the suffix attached to an ARM64 instruction.
|
|
|
|
|
// The input is a single string consisting of period-separated condition
|
|
|
|
|
// codes, such as ".P.W". An initial period is ignored.
|
|
|
|
|
func ParseARM64Suffix(cond string) (uint8, bool) {
|
|
|
|
|
if cond == "" {
|
|
|
|
|
return 0, true
|
|
|
|
|
}
|
|
|
|
|
return parseARMCondition(cond, arm64LS, nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func arm64RegisterNumber(name string, n int16) (int16, bool) {
|
|
|
|
|
switch name {
|
|
|
|
|
case "F":
|
|
|
|
|
if 0 <= n && n <= 31 {
|
|
|
|
|
return arm64.REG_F0 + n, true
|
|
|
|
|
}
|
|
|
|
|
case "R":
|
|
|
|
|
if 0 <= n && n <= 30 { // not 31
|
|
|
|
|
return arm64.REG_R0 + n, true
|
|
|
|
|
}
|
|
|
|
|
case "V":
|
|
|
|
|
if 0 <= n && n <= 31 {
|
|
|
|
|
return arm64.REG_V0 + n, true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0, false
|
|
|
|
|
}
|