2015-01-22 10:46:50 -08: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.
|
|
|
|
|
|
|
|
|
|
package arch
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmd/internal/obj"
|
2015-02-13 17:01:43 -08:00
|
|
|
"cmd/internal/obj/arm"
|
2015-03-08 14:11:41 +01:00
|
|
|
"cmd/internal/obj/arm64"
|
2015-09-10 11:32:32 -04:00
|
|
|
"cmd/internal/obj/mips"
|
2015-02-18 20:30:55 -08:00
|
|
|
"cmd/internal/obj/ppc64"
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
"cmd/internal/obj/x86"
|
2015-02-13 17:01:43 -08:00
|
|
|
"fmt"
|
2015-03-03 09:30:07 -08:00
|
|
|
"strings"
|
2015-01-22 10:46:50 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Pseudo-registers whose names are the constant name without the leading R.
|
|
|
|
|
const (
|
|
|
|
|
RFP = -(iota + 1)
|
|
|
|
|
RSB
|
|
|
|
|
RSP
|
|
|
|
|
RPC
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Arch wraps the link architecture object with more architecture-specific information.
|
|
|
|
|
type Arch struct {
|
|
|
|
|
*obj.LinkArch
|
|
|
|
|
// Map of instruction names to enumeration.
|
2016-03-07 18:00:08 -08:00
|
|
|
Instructions map[string]obj.As
|
2015-01-22 10:46:50 -08:00
|
|
|
// Map of register names to enumeration.
|
2015-02-18 20:30:55 -08:00
|
|
|
Register map[string]int16
|
|
|
|
|
// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
|
|
|
|
|
RegisterPrefix map[string]bool
|
|
|
|
|
// RegisterNumber converts R(10) into arm.REG_R10.
|
|
|
|
|
RegisterNumber func(string, int16) (int16, bool)
|
2015-02-13 17:01:43 -08:00
|
|
|
// Instruction is a jump.
|
|
|
|
|
IsJump func(word string) bool
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
|
2015-02-18 20:30:55 -08:00
|
|
|
// nilRegisterNumber is the register number function for architectures
|
|
|
|
|
// that do not accept the R(N) notation. It always returns failure.
|
|
|
|
|
func nilRegisterNumber(name string, n int16) (int16, bool) {
|
|
|
|
|
return 0, false
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
var Pseudos = map[string]obj.As{
|
2015-02-06 11:39:23 -08:00
|
|
|
"DATA": obj.ADATA,
|
|
|
|
|
"FUNCDATA": obj.AFUNCDATA,
|
|
|
|
|
"GLOBL": obj.AGLOBL,
|
|
|
|
|
"PCDATA": obj.APCDATA,
|
|
|
|
|
"TEXT": obj.ATEXT,
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-22 10:46:50 -08:00
|
|
|
// Set configures the architecture specified by GOARCH and returns its representation.
|
|
|
|
|
// It returns nil if GOARCH is not recognized.
|
|
|
|
|
func Set(GOARCH string) *Arch {
|
|
|
|
|
switch GOARCH {
|
|
|
|
|
case "386":
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
return archX86(&x86.Link386)
|
2015-01-22 10:46:50 -08:00
|
|
|
case "amd64":
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
return archX86(&x86.Linkamd64)
|
2015-02-13 17:01:43 -08:00
|
|
|
case "amd64p32":
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
return archX86(&x86.Linkamd64p32)
|
2015-02-13 17:01:43 -08:00
|
|
|
case "arm":
|
|
|
|
|
return archArm()
|
2015-03-08 14:11:41 +01:00
|
|
|
case "arm64":
|
|
|
|
|
return archArm64()
|
2015-09-10 11:32:32 -04:00
|
|
|
case "mips64":
|
|
|
|
|
a := archMips64()
|
|
|
|
|
a.LinkArch = &mips.Linkmips64
|
|
|
|
|
return a
|
|
|
|
|
case "mips64le":
|
|
|
|
|
a := archMips64()
|
|
|
|
|
a.LinkArch = &mips.Linkmips64le
|
|
|
|
|
return a
|
2015-02-18 20:30:55 -08:00
|
|
|
case "ppc64":
|
|
|
|
|
a := archPPC64()
|
|
|
|
|
a.LinkArch = &ppc64.Linkppc64
|
|
|
|
|
return a
|
2015-02-20 12:23:27 -05:00
|
|
|
case "ppc64le":
|
|
|
|
|
a := archPPC64()
|
|
|
|
|
a.LinkArch = &ppc64.Linkppc64le
|
|
|
|
|
return a
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
func jumpX86(word string) bool {
|
2015-11-02 14:53:31 +03:00
|
|
|
return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
2015-01-22 10:46:50 -08:00
|
|
|
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
func archX86(linkArch *obj.LinkArch) *Arch {
|
2015-02-18 20:30:55 -08:00
|
|
|
register := make(map[string]int16)
|
2015-01-22 10:46:50 -08:00
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
for i, s := range x86.Register {
|
2015-02-18 20:30:55 -08:00
|
|
|
register[s] = int16(i + x86.REG_AL)
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
// Pseudo-registers.
|
2015-02-18 20:30:55 -08:00
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Register prefix not used on this architecture.
|
2015-01-22 10:46:50 -08:00
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions := make(map[string]obj.As)
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range obj.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions[s] = obj.As(i)
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range x86.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
|
|
|
|
instructions[s] = obj.As(i) + obj.ABaseAMD64
|
2015-03-02 20:17:20 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-22 10:46:50 -08:00
|
|
|
// Annoying aliases.
|
2015-04-28 12:35:06 -07:00
|
|
|
instructions["JA"] = x86.AJHI /* alternate */
|
|
|
|
|
instructions["JAE"] = x86.AJCC /* alternate */
|
|
|
|
|
instructions["JB"] = x86.AJCS /* alternate */
|
|
|
|
|
instructions["JBE"] = x86.AJLS /* alternate */
|
|
|
|
|
instructions["JC"] = x86.AJCS /* alternate */
|
|
|
|
|
instructions["JCC"] = x86.AJCC /* carry clear (CF = 0) */
|
|
|
|
|
instructions["JCS"] = x86.AJCS /* carry set (CF = 1) */
|
|
|
|
|
instructions["JE"] = x86.AJEQ /* alternate */
|
|
|
|
|
instructions["JEQ"] = x86.AJEQ /* equal (ZF = 1) */
|
|
|
|
|
instructions["JG"] = x86.AJGT /* alternate */
|
|
|
|
|
instructions["JGE"] = x86.AJGE /* greater than or equal (signed) (SF = OF) */
|
|
|
|
|
instructions["JGT"] = x86.AJGT /* greater than (signed) (ZF = 0 && SF = OF) */
|
|
|
|
|
instructions["JHI"] = x86.AJHI /* higher (unsigned) (CF = 0 && ZF = 0) */
|
|
|
|
|
instructions["JHS"] = x86.AJCC /* alternate */
|
|
|
|
|
instructions["JL"] = x86.AJLT /* alternate */
|
|
|
|
|
instructions["JLE"] = x86.AJLE /* less than or equal (signed) (ZF = 1 || SF != OF) */
|
|
|
|
|
instructions["JLO"] = x86.AJCS /* alternate */
|
|
|
|
|
instructions["JLS"] = x86.AJLS /* lower or same (unsigned) (CF = 1 || ZF = 1) */
|
|
|
|
|
instructions["JLT"] = x86.AJLT /* less than (signed) (SF != OF) */
|
|
|
|
|
instructions["JMI"] = x86.AJMI /* negative (minus) (SF = 1) */
|
|
|
|
|
instructions["JNA"] = x86.AJLS /* alternate */
|
|
|
|
|
instructions["JNAE"] = x86.AJCS /* alternate */
|
|
|
|
|
instructions["JNB"] = x86.AJCC /* alternate */
|
|
|
|
|
instructions["JNBE"] = x86.AJHI /* alternate */
|
|
|
|
|
instructions["JNC"] = x86.AJCC /* alternate */
|
|
|
|
|
instructions["JNE"] = x86.AJNE /* not equal (ZF = 0) */
|
|
|
|
|
instructions["JNG"] = x86.AJLE /* alternate */
|
|
|
|
|
instructions["JNGE"] = x86.AJLT /* alternate */
|
|
|
|
|
instructions["JNL"] = x86.AJGE /* alternate */
|
|
|
|
|
instructions["JNLE"] = x86.AJGT /* alternate */
|
|
|
|
|
instructions["JNO"] = x86.AJOC /* alternate */
|
|
|
|
|
instructions["JNP"] = x86.AJPC /* alternate */
|
|
|
|
|
instructions["JNS"] = x86.AJPL /* alternate */
|
|
|
|
|
instructions["JNZ"] = x86.AJNE /* alternate */
|
|
|
|
|
instructions["JO"] = x86.AJOS /* alternate */
|
|
|
|
|
instructions["JOC"] = x86.AJOC /* overflow clear (OF = 0) */
|
|
|
|
|
instructions["JOS"] = x86.AJOS /* overflow set (OF = 1) */
|
|
|
|
|
instructions["JP"] = x86.AJPS /* alternate */
|
|
|
|
|
instructions["JPC"] = x86.AJPC /* parity clear (PF = 0) */
|
|
|
|
|
instructions["JPE"] = x86.AJPS /* alternate */
|
|
|
|
|
instructions["JPL"] = x86.AJPL /* non-negative (plus) (SF = 0) */
|
|
|
|
|
instructions["JPO"] = x86.AJPC /* alternate */
|
|
|
|
|
instructions["JPS"] = x86.AJPS /* parity set (PF = 1) */
|
|
|
|
|
instructions["JS"] = x86.AJMI /* alternate */
|
|
|
|
|
instructions["JZ"] = x86.AJEQ /* alternate */
|
2015-01-22 10:46:50 -08:00
|
|
|
instructions["MASKMOVDQU"] = x86.AMASKMOVOU
|
|
|
|
|
instructions["MOVD"] = x86.AMOVQ
|
|
|
|
|
instructions["MOVDQ2Q"] = x86.AMOVQ
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["MOVNTDQ"] = x86.AMOVNTO
|
2015-02-24 11:00:07 -08:00
|
|
|
instructions["MOVOA"] = x86.AMOVO
|
2015-02-24 12:30:39 -08:00
|
|
|
instructions["PSLLDQ"] = x86.APSLLO
|
|
|
|
|
instructions["PSRLDQ"] = x86.APSRLO
|
2016-01-23 22:50:58 -05:00
|
|
|
instructions["PADDD"] = x86.APADDL
|
2015-01-22 10:46:50 -08:00
|
|
|
|
|
|
|
|
return &Arch{
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
LinkArch: linkArch,
|
2015-03-02 11:04:06 -08:00
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: nil,
|
|
|
|
|
RegisterNumber: nilRegisterNumber,
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
IsJump: jumpX86,
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func archArm() *Arch {
|
2015-02-18 20:30:55 -08:00
|
|
|
register := make(map[string]int16)
|
2015-02-13 17:01:43 -08:00
|
|
|
// Create maps for easy lookup of instruction names etc.
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
// Note that there is no list of names as there is for x86.
|
2015-02-13 17:01:43 -08:00
|
|
|
for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
|
|
|
|
// Avoid unintentionally clobbering g using R10.
|
2015-02-18 20:30:55 -08:00
|
|
|
delete(register, "R10")
|
|
|
|
|
register["g"] = arm.REG_R10
|
2015-02-13 17:01:43 -08:00
|
|
|
for i := 0; i < 16; i++ {
|
2015-02-18 20:30:55 -08:00
|
|
|
register[fmt.Sprintf("C%d", i)] = int16(i)
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pseudo-registers.
|
2015-02-18 20:30:55 -08:00
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
register["SP"] = RSP
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"F": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
}
|
2015-02-13 17:01:43 -08:00
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions := make(map[string]obj.As)
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range obj.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions[s] = obj.As(i)
|
2015-02-13 17:01:43 -08:00
|
|
|
}
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range arm.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
|
|
|
|
instructions[s] = obj.As(i) + obj.ABaseARM
|
2015-03-02 20:17:20 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-13 17:01:43 -08:00
|
|
|
// Annoying aliases.
|
|
|
|
|
instructions["B"] = obj.AJMP
|
|
|
|
|
instructions["BL"] = obj.ACALL
|
2015-03-09 12:36:11 -07:00
|
|
|
// MCR differs from MRC by the way fields of the word are encoded.
|
|
|
|
|
// (Details in arm.go). Here we add the instruction so parse will find
|
|
|
|
|
// it, but give it an opcode number known only to us.
|
|
|
|
|
instructions["MCR"] = aMCR
|
2015-02-13 17:01:43 -08:00
|
|
|
|
|
|
|
|
return &Arch{
|
2015-03-02 11:04:06 -08:00
|
|
|
LinkArch: &arm.Linkarm,
|
|
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: armRegisterNumber,
|
|
|
|
|
IsJump: jumpArm,
|
2015-01-22 10:46:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-18 20:30:55 -08:00
|
|
|
|
2015-03-08 14:11:41 +01:00
|
|
|
func archArm64() *Arch {
|
|
|
|
|
register := make(map[string]int16)
|
|
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// Note that there is no list of names as there is for 386 and amd64.
|
|
|
|
|
register[arm64.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
|
|
|
|
|
for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
|
|
|
|
|
register[arm64.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
|
|
|
|
|
register[arm64.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
|
|
|
|
|
register[arm64.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
register["LR"] = arm64.REGLINK
|
|
|
|
|
register["DAIF"] = arm64.REG_DAIF
|
|
|
|
|
register["NZCV"] = arm64.REG_NZCV
|
|
|
|
|
register["FPSR"] = arm64.REG_FPSR
|
|
|
|
|
register["FPCR"] = arm64.REG_FPCR
|
|
|
|
|
register["SPSR_EL1"] = arm64.REG_SPSR_EL1
|
|
|
|
|
register["ELR_EL1"] = arm64.REG_ELR_EL1
|
|
|
|
|
register["SPSR_EL2"] = arm64.REG_SPSR_EL2
|
|
|
|
|
register["ELR_EL2"] = arm64.REG_ELR_EL2
|
|
|
|
|
register["CurrentEL"] = arm64.REG_CurrentEL
|
|
|
|
|
register["SP_EL0"] = arm64.REG_SP_EL0
|
|
|
|
|
register["SPSel"] = arm64.REG_SPSel
|
|
|
|
|
register["DAIFSet"] = arm64.REG_DAIFSet
|
|
|
|
|
register["DAIFClr"] = arm64.REG_DAIFClr
|
|
|
|
|
// Conditional operators, like EQ, NE, etc.
|
|
|
|
|
register["EQ"] = arm64.COND_EQ
|
|
|
|
|
register["NE"] = arm64.COND_NE
|
|
|
|
|
register["HS"] = arm64.COND_HS
|
2015-09-17 11:47:16 +02:00
|
|
|
register["CS"] = arm64.COND_HS
|
2015-03-08 14:11:41 +01:00
|
|
|
register["LO"] = arm64.COND_LO
|
2015-09-17 11:47:16 +02:00
|
|
|
register["CC"] = arm64.COND_LO
|
2015-03-08 14:11:41 +01:00
|
|
|
register["MI"] = arm64.COND_MI
|
|
|
|
|
register["PL"] = arm64.COND_PL
|
|
|
|
|
register["VS"] = arm64.COND_VS
|
|
|
|
|
register["VC"] = arm64.COND_VC
|
|
|
|
|
register["HI"] = arm64.COND_HI
|
|
|
|
|
register["LS"] = arm64.COND_LS
|
|
|
|
|
register["GE"] = arm64.COND_GE
|
|
|
|
|
register["LT"] = arm64.COND_LT
|
|
|
|
|
register["GT"] = arm64.COND_GT
|
|
|
|
|
register["LE"] = arm64.COND_LE
|
|
|
|
|
register["AL"] = arm64.COND_AL
|
|
|
|
|
register["NV"] = arm64.COND_NV
|
|
|
|
|
// Pseudo-registers.
|
|
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
register["SP"] = RSP
|
|
|
|
|
// Avoid unintentionally clobbering g using R28.
|
|
|
|
|
delete(register, "R28")
|
|
|
|
|
register["g"] = arm64.REG_R28
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"F": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
"V": true,
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions := make(map[string]obj.As)
|
2015-03-08 14:11:41 +01:00
|
|
|
for i, s := range obj.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions[s] = obj.As(i)
|
2015-03-08 14:11:41 +01:00
|
|
|
}
|
|
|
|
|
for i, s := range arm64.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
|
|
|
|
instructions[s] = obj.As(i) + obj.ABaseARM64
|
2015-03-08 14:11:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Annoying aliases.
|
|
|
|
|
instructions["B"] = arm64.AB
|
|
|
|
|
instructions["BL"] = arm64.ABL
|
|
|
|
|
|
|
|
|
|
return &Arch{
|
|
|
|
|
LinkArch: &arm64.Linkarm64,
|
|
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: arm64RegisterNumber,
|
|
|
|
|
IsJump: jumpArm64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 20:30:55 -08:00
|
|
|
func archPPC64() *Arch {
|
|
|
|
|
register := make(map[string]int16)
|
|
|
|
|
// Create maps for easy lookup of instruction names etc.
|
cmd/internal/obj/x86: take over i386 duty, clean up PINSRQ, CMPSD
Make cmd/internal/obj/x86 support 32-bit mode and use
instead of cmd/internal/obj/i386. Delete cmd/internal/obj/i386.
Clean up encoding of PINSRQ, CMPSD to use explicit third arg
instead of jamming it into an unused slot of a different arg.
Also fix bug in old6a, which declared the wrong grammar.
The accepted (and encoded) arguments to CMPSD etc are mem,reg not reg,mem.
Code that did try to use mem,reg before would be rejected by liblink,
so only reg,reg ever worked, so existing code is not affected.
After this change, code can use mem,reg successfully.
The real bug here is that the encoding tables inverted the argument
order, making the comparisons all backward from what they say on the page.
It's too late to swap them, though: people have already written code that
expects the inverted comparisons (like in package math, and likely externally).
The best we can do is make the argument that should and can take a
memory operand accept it.
Bit-for-bit compatibility checked against tree without this CL.
Change-Id: Ife5685bc98c95001f64407f35066b34b4dae11c1
Reviewed-on: https://go-review.googlesource.com/6810
Reviewed-by: Rob Pike <r@golang.org>
2015-03-04 15:46:52 -05:00
|
|
|
// Note that there is no list of names as there is for x86.
|
2015-02-18 20:30:55 -08:00
|
|
|
for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
2015-02-27 12:36:15 -08:00
|
|
|
for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
|
|
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
|
2015-02-26 17:09:16 -08:00
|
|
|
register[obj.Rconv(i)] = int16(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
register["CR"] = ppc64.REG_CR
|
|
|
|
|
register["XER"] = ppc64.REG_XER
|
|
|
|
|
register["LR"] = ppc64.REG_LR
|
|
|
|
|
register["CTR"] = ppc64.REG_CTR
|
|
|
|
|
register["FPSCR"] = ppc64.REG_FPSCR
|
|
|
|
|
register["MSR"] = ppc64.REG_MSR
|
|
|
|
|
// Pseudo-registers.
|
|
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Avoid unintentionally clobbering g using R30.
|
|
|
|
|
delete(register, "R30")
|
|
|
|
|
register["g"] = ppc64.REG_R30
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"CR": true,
|
|
|
|
|
"F": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
"SPR": true,
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions := make(map[string]obj.As)
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range obj.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions[s] = obj.As(i)
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
2015-03-02 20:17:20 -08:00
|
|
|
for i, s := range ppc64.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
|
|
|
|
instructions[s] = obj.As(i) + obj.ABasePPC64
|
2015-03-02 20:17:20 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-18 20:30:55 -08:00
|
|
|
// Annoying aliases.
|
|
|
|
|
instructions["BR"] = ppc64.ABR
|
|
|
|
|
instructions["BL"] = ppc64.ABL
|
|
|
|
|
|
|
|
|
|
return &Arch{
|
2015-03-02 11:04:06 -08:00
|
|
|
LinkArch: &ppc64.Linkppc64,
|
|
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: ppc64RegisterNumber,
|
|
|
|
|
IsJump: jumpPPC64,
|
2015-02-18 20:30:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-09-10 11:32:32 -04:00
|
|
|
|
|
|
|
|
func archMips64() *Arch {
|
|
|
|
|
register := make(map[string]int16)
|
|
|
|
|
// Create maps for easy lookup of instruction names etc.
|
|
|
|
|
// Note that there is no list of names as there is for x86.
|
|
|
|
|
for i := mips.REG_R0; i <= mips.REG_R31; i++ {
|
|
|
|
|
register[obj.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := mips.REG_F0; i <= mips.REG_F31; i++ {
|
|
|
|
|
register[obj.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := mips.REG_M0; i <= mips.REG_M31; i++ {
|
|
|
|
|
register[obj.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
|
|
|
|
|
register[obj.Rconv(i)] = int16(i)
|
|
|
|
|
}
|
|
|
|
|
register["HI"] = mips.REG_HI
|
|
|
|
|
register["LO"] = mips.REG_LO
|
|
|
|
|
// Pseudo-registers.
|
|
|
|
|
register["SB"] = RSB
|
|
|
|
|
register["FP"] = RFP
|
|
|
|
|
register["PC"] = RPC
|
|
|
|
|
// Avoid unintentionally clobbering g using R30.
|
|
|
|
|
delete(register, "R30")
|
|
|
|
|
register["g"] = mips.REG_R30
|
|
|
|
|
registerPrefix := map[string]bool{
|
|
|
|
|
"F": true,
|
|
|
|
|
"FCR": true,
|
|
|
|
|
"M": true,
|
|
|
|
|
"R": true,
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions := make(map[string]obj.As)
|
2015-09-10 11:32:32 -04:00
|
|
|
for i, s := range obj.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
instructions[s] = obj.As(i)
|
2015-09-10 11:32:32 -04:00
|
|
|
}
|
|
|
|
|
for i, s := range mips.Anames {
|
2016-03-07 18:00:08 -08:00
|
|
|
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
|
|
|
|
instructions[s] = obj.As(i) + obj.ABaseMIPS64
|
2015-09-10 11:32:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Annoying alias.
|
|
|
|
|
instructions["JAL"] = mips.AJAL
|
|
|
|
|
|
|
|
|
|
return &Arch{
|
|
|
|
|
LinkArch: &mips.Linkmips64,
|
|
|
|
|
Instructions: instructions,
|
|
|
|
|
Register: register,
|
|
|
|
|
RegisterPrefix: registerPrefix,
|
|
|
|
|
RegisterNumber: mipsRegisterNumber,
|
|
|
|
|
IsJump: jumpMIPS64,
|
|
|
|
|
}
|
|
|
|
|
}
|