1
2
3
4
5 package arm64
6
7 import (
8 "fmt"
9 "strings"
10
11 "_gen/unify"
12 )
13
14
15 func asComment(text string, width int) string {
16 text = strings.TrimSpace(text)
17 text = strings.ReplaceAll(text, "&", "&")
18 text = strings.ReplaceAll(text, "\n", " ")
19 words := strings.Fields(text)
20 var lines []string
21 line := ""
22 for _, w := range words {
23 if line != "" {
24 line = line + " "
25 }
26 line = line + w
27 if len(line) >= width {
28 lines = append(lines, "// "+line)
29 line = ""
30 }
31 }
32 if len(line) > 0 {
33 lines = append(lines, "// "+line)
34 }
35 return strings.Join(lines, "\n")
36 }
37
38
39 func (op *Operand) Emit() *unify.Value {
40 var opDb unify.DefBuilder
41 opDb.Add("class", unify.NewValue(unify.NewStringExact(op.Class)))
42
43 if op.BaseType != "" {
44 opDb.Add("base", unify.NewValue(unify.NewStringExact(op.BaseType)))
45 }
46
47 if op.Bits > 0 {
48 opDb.Add("bits", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.Bits))))
49 }
50
51 if op.ElemBits > 0 {
52 opDb.Add("elemBits", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.ElemBits))))
53 }
54
55 if op.Lanes > 0 {
56 opDb.Add("lanes", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.Lanes))))
57 }
58
59 if op.Type == OperandImm {
60 opDb.Add("bits", unify.NewValue(unify.NewStringExact("8")))
61 if op.ImmMax == 0 {
62 opDb.Add("const", unify.NewValue(unify.NewStringExact("0")))
63 } else {
64 opDb.Add("immOffset", unify.NewValue(unify.NewStringExact("0")))
65 }
66 if op.ImmMax > 0 {
67 opDb.Add("immMax", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.ImmMax))))
68 }
69 }
70
71 if op.Role != "" {
72 opDb.Add("role", unify.NewValue(unify.NewStringExact(op.Role)))
73 }
74
75 if op.ListNumber >= 0 {
76 opDb.Add("listNumber", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.ListNumber))))
77 }
78
79 opDb.Add("asmPos", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.AsmPos))))
80
81 return unify.NewValue(opDb.Build())
82 }
83
84
85 func (template *template) Emit(arrangement string) *unify.Value {
86 var db unify.DefBuilder
87
88
89 mnemonic := template.instruction.Mnemonic()
90 switch mnemonic {
91 case "INS", "UMOV":
92 arrangement = arrangement[len(arrangement)-1:]
93 mnemonic = "VMOV"
94 case "DUP":
95 arrangement = arrangement[len(arrangement)-1:]
96 mnemonic = "V" + mnemonic
97 default:
98
99
100 isAESOrSHA := strings.HasPrefix(mnemonic, "AES") ||
101 (len(mnemonic) > 3 && mnemonic[:3] == "SHA" && mnemonic[3] >= '0' && mnemonic[3] <= '9')
102 if !isAESOrSHA {
103 mnemonic = "V" + mnemonic
104 }
105 }
106
107 db.Add("asm", unify.NewValue(unify.NewStringExact(mnemonic)))
108 db.Add("arrangement", unify.NewValue(unify.NewStringExact(arrangement)))
109 db.Add("goarch", unify.NewValue(unify.NewStringExact("arm64")))
110 db.Add("cpuFeature", unify.NewValue(unify.NewStringExact("NEON")))
111 db.Add("inVariant", unify.NewValue(unify.NewTuple()))
112
113 if doc := template.instruction.Documentation(); doc != "" {
114 db.Add("details", unify.NewValue(unify.NewStringExact(asComment(doc, 80))))
115 }
116
117 var inVals, outVals []*unify.Value
118 for _, op := range template.operands {
119 if op.Role == "destination" {
120 outVals = append(outVals, op.Emit())
121 } else {
122 inVals = append(inVals, op.Emit())
123 }
124 }
125
126 db.Add("in", unify.NewValue(unify.NewTuple(inVals...)))
127 db.Add("out", unify.NewValue(unify.NewTuple(outVals...)))
128
129 return unify.NewValue(db.Build())
130 }
131
132
133
134 func (instruction *Instruction) EmitAll() []*unify.Value {
135 var defs []*unify.Value
136
137 mnemonic := instruction.Mnemonic()
138 templates := instruction.templates()
139 arrangements, ashape := instruction.Arrangements()
140 if ashape == UnsupportedArngs {
141 return nil
142 }
143 for _, template := range templates {
144 for _, arr := range arrangements {
145
146 updatedTemplate := template
147 updatedTemplate.operands = make([]Operand, len(template.operands))
148 copy(updatedTemplate.operands, template.operands)
149
150
151
152
153
154 vregPos := 0
155 for i := range updatedTemplate.operands {
156 updatedTemplate.operands[i].instantiate(arr, ashape, vregPos, mnemonic)
157 if updatedTemplate.operands[i].Type == OperandVReg {
158 vregPos++
159 }
160 }
161 defs = append(defs, updatedTemplate.Emit(arr.arrangement))
162 }
163 }
164
165 return defs
166 }
167
View as plain text