Supporting extra instructions not included in the Opcodes database is currently a challenge. Short of migrating to an entirely different source (such as #23), the options are either to patch the XML data file or to append additional instructions at the loading phase. An example of patching the XML was shown in the as-yet unlanded PR #234. This shows the XML patching approach is unwieldy and requires more information than we actually need (for example instruction form encodings). In #335 we discussed the alternative of adding extra instructions during loading. This has the advantage of using avo's simpler internal data structure. This PR prepares for using that approach by adding an `internal/opcodesextra` package, intended to contain manually curated lists of extra instructions to add to the instruction database during loading. At the moment, the only instruction added here is the `MOVLQZX` instruction that's already handled this way. Updates #335 #234 #23
143 lines
5.5 KiB
Go
143 lines
5.5 KiB
Go
package load
|
|
|
|
// alias defines an opcode alias.
|
|
type alias struct {
|
|
From string
|
|
To string
|
|
}
|
|
|
|
// aliases defines a list of opcode aliases. Where possible these are extracted
|
|
// from the code (see note below).
|
|
var aliases = []alias{
|
|
// The PSHUFD/PSHUFL alias is not recorded in the list of "Annoying aliases" below. However the instructions are identical.
|
|
//
|
|
// Reference: https://github.com/golang/go/blob/048c9164a0c5572df18325e377473e7893dbfb07/src/cmd/internal/obj/x86/asm6.go#L1365
|
|
//
|
|
// {APSHUFL, yxshuf, Pq, opBytes{0x70, 00}},
|
|
//
|
|
// Reference: https://github.com/golang/go/blob/048c9164a0c5572df18325e377473e7893dbfb07/src/cmd/internal/obj/x86/asm6.go#L1688
|
|
//
|
|
// {APSHUFD, yxshuf, Pq, opBytes{0x70, 0}},
|
|
//
|
|
{"PSHUFD", "PSHUFL"},
|
|
}
|
|
|
|
// Go contains a list of self-proclaimed "Annoying aliases", as follows. We use
|
|
// a script to automatically extract this list from the source code (see the
|
|
// following go:generate line). Then we merge this with the manual list above.
|
|
//
|
|
// Reference: https://github.com/golang/go/blob/048c9164a0c5572df18325e377473e7893dbfb07/src/cmd/asm/internal/arch/arch.go#L126-L182
|
|
//
|
|
// }
|
|
// // Annoying aliases.
|
|
// 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 */
|
|
// instructions["MASKMOVDQU"] = x86.AMASKMOVOU
|
|
// instructions["MOVD"] = x86.AMOVQ
|
|
// instructions["MOVDQ2Q"] = x86.AMOVQ
|
|
// instructions["MOVNTDQ"] = x86.AMOVNTO
|
|
// instructions["MOVOA"] = x86.AMOVO
|
|
// instructions["PSLLDQ"] = x86.APSLLO
|
|
// instructions["PSRLDQ"] = x86.APSRLO
|
|
// instructions["PADDD"] = x86.APADDL
|
|
//
|
|
// return &Arch{
|
|
//
|
|
|
|
//go:generate ./annoyingaliases.sh zannoyingaliases.go
|
|
|
|
func init() {
|
|
aliases = append(aliases, annoyingaliases...)
|
|
}
|
|
|
|
// maskrequired is a set of AVX-512 opcodes where the mask register is required.
|
|
// Usually the mask register can be omitted, in which case K0 is implied.
|
|
var maskrequired = map[string]bool{
|
|
// Reference: https://github.com/golang/go/blob/4fd94558820100129b98f284e21b19fc27a99926/src/cmd/internal/obj/x86/asm6.go#L4219-L4240
|
|
//
|
|
// // Checks to warn about instruction/arguments combinations that
|
|
// // will unconditionally trigger illegal instruction trap (#UD).
|
|
// switch p.As {
|
|
// case AVGATHERDPD,
|
|
// AVGATHERQPD,
|
|
// AVGATHERDPS,
|
|
// AVGATHERQPS,
|
|
// AVPGATHERDD,
|
|
// AVPGATHERQD,
|
|
// AVPGATHERDQ,
|
|
// AVPGATHERQQ:
|
|
// // AVX512 gather requires explicit K mask.
|
|
// if p.GetFrom3().Reg >= REG_K0 && p.GetFrom3().Reg <= REG_K7 {
|
|
// if !avx512gatherValid(ctxt, p) {
|
|
// return
|
|
// }
|
|
// } else {
|
|
// if !avx2gatherValid(ctxt, p) {
|
|
// return
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
"VGATHERDPD": true,
|
|
"VGATHERQPD": true,
|
|
"VGATHERDPS": true,
|
|
"VGATHERQPS": true,
|
|
"VPGATHERDD": true,
|
|
"VPGATHERQD": true,
|
|
"VPGATHERDQ": true,
|
|
"VPGATHERQQ": true,
|
|
|
|
// Restriction applies to SCATTER instructions too.
|
|
"VPSCATTERDD": true,
|
|
"VPSCATTERDQ": true,
|
|
"VPSCATTERQD": true,
|
|
"VPSCATTERQQ": true,
|
|
"VSCATTERDPD": true,
|
|
"VSCATTERDPS": true,
|
|
"VSCATTERQPD": true,
|
|
"VSCATTERQPS": true,
|
|
}
|