"cmd/internal/obj"
"cmd/internal/obj/arm"
"cmd/internal/obj/arm64"
+ "cmd/internal/obj/loong64"
"cmd/internal/obj/mips"
"cmd/internal/obj/ppc64"
"cmd/internal/obj/riscv"
return archArm()
case "arm64":
return archArm64()
+ case "loong64":
+ return archLoong64(&loong64.Linkloong64)
case "mips":
return archMips(&mips.Linkmips)
case "mipsle":
}
}
+func archLoong64(linkArch *obj.LinkArch) *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 := loong64.REG_R0; i <= loong64.REG_R31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := loong64.REG_F0; i <= loong64.REG_F31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := loong64.REG_FCSR0; i <= loong64.REG_FCSR31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := loong64.REG_FCC0; i <= loong64.REG_FCC31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ // Pseudo-registers.
+ register["SB"] = RSB
+ register["FP"] = RFP
+ register["PC"] = RPC
+ // Avoid unintentionally clobbering g using R22.
+ delete(register, "R22")
+ register["g"] = loong64.REG_R22
+ register["RSB"] = loong64.REG_R31
+ registerPrefix := map[string]bool{
+ "F": true,
+ "FCSR": true,
+ "FCC": true,
+ "R": true,
+ }
+
+ instructions := make(map[string]obj.As)
+ for i, s := range obj.Anames {
+ instructions[s] = obj.As(i)
+ }
+ for i, s := range loong64.Anames {
+ if obj.As(i) >= obj.A_ARCHSPECIFIC {
+ instructions[s] = obj.As(i) + obj.ABaseLoong64
+ }
+ }
+ // Annoying alias.
+ instructions["JAL"] = loong64.AJAL
+
+ return &Arch{
+ LinkArch: linkArch,
+ Instructions: instructions,
+ Register: register,
+ RegisterPrefix: registerPrefix,
+ RegisterNumber: loong64RegisterNumber,
+ IsJump: jumpLoong64,
+ }
+}
+
func archRISCV64(shared bool) *Arch {
register := make(map[string]int16)
--- /dev/null
+// Copyright 2022 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
+// Loong64 (LoongArch64) instruction set, to minimize its interaction
+// with the core of the assembler.
+
+package arch
+
+import (
+ "cmd/internal/obj"
+ "cmd/internal/obj/loong64"
+)
+
+func jumpLoong64(word string) bool {
+ switch word {
+ case "BEQ", "BFPF", "BFPT", "BLTZ", "BGEZ", "BLEZ", "BGTZ", "BLT", "BLTU", "JIRL", "BNE", "BGE", "BGEU", "JMP", "JAL", "CALL":
+ return true
+ }
+ return false
+}
+
+// IsLoong64CMP reports whether the op (as defined by an loong64.A* constant) is
+// one of the CMP instructions that require special handling.
+func IsLoong64CMP(op obj.As) bool {
+ switch op {
+ case loong64.ACMPEQF, loong64.ACMPEQD, loong64.ACMPGEF, loong64.ACMPGED,
+ loong64.ACMPGTF, loong64.ACMPGTD:
+ return true
+ }
+ return false
+}
+
+// IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
+// one of the MUL/DIV/REM instructions that require special handling.
+func IsLoong64MUL(op obj.As) bool {
+ switch op {
+ case loong64.AMUL, loong64.AMULU, loong64.AMULV, loong64.AMULVU,
+ loong64.ADIV, loong64.ADIVU, loong64.ADIVV, loong64.ADIVVU,
+ loong64.AREM, loong64.AREMU, loong64.AREMV, loong64.AREMVU:
+ return true
+ }
+ return false
+}
+
+func loong64RegisterNumber(name string, n int16) (int16, bool) {
+ switch name {
+ case "F":
+ if 0 <= n && n <= 31 {
+ return loong64.REG_F0 + n, true
+ }
+ case "FCSR":
+ if 0 <= n && n <= 31 {
+ return loong64.REG_FCSR0 + n, true
+ }
+ case "FCC":
+ if 0 <= n && n <= 31 {
+ return loong64.REG_FCC0 + n, true
+ }
+ case "R":
+ if 0 <= n && n <= 31 {
+ return loong64.REG_R0 + n, true
+ }
+ }
+ return 0, false
+}
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
+ if p.arch.Family == sys.Loong64 {
+ // 3-operand jumps.
+ // First two must be registers
+ target = &a[2]
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
if p.arch.Family == sys.S390X {
// 3-operand jumps.
target = &a[2]
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
+ } else if p.arch.Family == sys.Loong64 {
+ if arch.IsLoong64CMP(op) {
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
}
prog.From = a[0]
prog.To = a[1]
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
+ case sys.Loong64:
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ prog.To = a[2]
case sys.ARM:
// Special cases.
if arch.IsARMSTREX(op) {