1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This file encapsulates some of the odd characteristics of the
6// Loong64 (LoongArch64) instruction set, to minimize its interaction
7// with the core of the assembler.
8
9package arch
10
11import (
12	"cmd/internal/obj"
13	"cmd/internal/obj/loong64"
14)
15
16func jumpLoong64(word string) bool {
17	switch word {
18	case "BEQ", "BFPF", "BFPT", "BLTZ", "BGEZ", "BLEZ", "BGTZ", "BLT", "BLTU", "JIRL", "BNE", "BGE", "BGEU", "JMP", "JAL", "CALL":
19		return true
20	}
21	return false
22}
23
24// IsLoong64CMP reports whether the op (as defined by an loong64.A* constant) is
25// one of the CMP instructions that require special handling.
26func IsLoong64CMP(op obj.As) bool {
27	switch op {
28	case loong64.ACMPEQF, loong64.ACMPEQD, loong64.ACMPGEF, loong64.ACMPGED,
29		loong64.ACMPGTF, loong64.ACMPGTD:
30		return true
31	}
32	return false
33}
34
35// IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
36// one of the MUL/DIV/REM instructions that require special handling.
37func IsLoong64MUL(op obj.As) bool {
38	switch op {
39	case loong64.AMUL, loong64.AMULU, loong64.AMULV, loong64.AMULVU,
40		loong64.ADIV, loong64.ADIVU, loong64.ADIVV, loong64.ADIVVU,
41		loong64.AREM, loong64.AREMU, loong64.AREMV, loong64.AREMVU:
42		return true
43	}
44	return false
45}
46
47// IsLoong64RDTIME reports whether the op (as defined by an loong64.A*
48// constant) is one of the RDTIMELW/RDTIMEHW/RDTIMED instructions that
49// require special handling.
50func IsLoong64RDTIME(op obj.As) bool {
51	switch op {
52	case loong64.ARDTIMELW, loong64.ARDTIMEHW, loong64.ARDTIMED:
53		return true
54	}
55	return false
56}
57
58func IsLoong64AMO(op obj.As) bool {
59	return loong64.IsAtomicInst(op)
60}
61
62func loong64RegisterNumber(name string, n int16) (int16, bool) {
63	switch name {
64	case "F":
65		if 0 <= n && n <= 31 {
66			return loong64.REG_F0 + n, true
67		}
68	case "FCSR":
69		if 0 <= n && n <= 31 {
70			return loong64.REG_FCSR0 + n, true
71		}
72	case "FCC":
73		if 0 <= n && n <= 31 {
74			return loong64.REG_FCC0 + n, true
75		}
76	case "R":
77		if 0 <= n && n <= 31 {
78			return loong64.REG_R0 + n, true
79		}
80	}
81	return 0, false
82}
83