]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/ssa/gen/AMD64Ops.go
Merge "[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch" into...
[gostls13.git] / src / cmd / compile / internal / ssa / gen / AMD64Ops.go
1 // Copyright 2015 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 package main
6
7 import "strings"
8
9 // copied from ../../amd64/reg.go
10 var regNamesAMD64 = []string{
11         ".AX",
12         ".CX",
13         ".DX",
14         ".BX",
15         ".SP",
16         ".BP",
17         ".SI",
18         ".DI",
19         ".R8",
20         ".R9",
21         ".R10",
22         ".R11",
23         ".R12",
24         ".R13",
25         ".R14",
26         ".R15",
27         ".X0",
28         ".X1",
29         ".X2",
30         ".X3",
31         ".X4",
32         ".X5",
33         ".X6",
34         ".X7",
35         ".X8",
36         ".X9",
37         ".X10",
38         ".X11",
39         ".X12",
40         ".X13",
41         ".X14",
42         ".X15",
43
44         // pseudo-registers
45         ".SB",
46         ".FLAGS",
47 }
48
49 func init() {
50         // Make map from reg names to reg integers.
51         if len(regNamesAMD64) > 64 {
52                 panic("too many registers")
53         }
54         num := map[string]int{}
55         for i, name := range regNamesAMD64 {
56                 if name[0] != '.' {
57                         panic("register name " + name + " does not start with '.'")
58                 }
59                 num[name[1:]] = i
60         }
61         buildReg := func(s string) regMask {
62                 m := regMask(0)
63                 for _, r := range strings.Split(s, " ") {
64                         if n, ok := num[r]; ok {
65                                 m |= regMask(1) << uint(n)
66                                 continue
67                         }
68                         panic("register " + r + " not found")
69                 }
70                 return m
71         }
72
73         // Common individual register masks
74         var (
75                 ax         = buildReg("AX")
76                 cx         = buildReg("CX")
77                 dx         = buildReg("DX")
78                 x15        = buildReg("X15")
79                 gp         = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15")
80                 fp         = buildReg("X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15")
81                 gpsp       = gp | buildReg("SP")
82                 gpspsb     = gpsp | buildReg("SB")
83                 flags      = buildReg("FLAGS")
84                 callerSave = gp | fp | flags
85         )
86         // Common slices of register masks
87         var (
88                 gponly    = []regMask{gp}
89                 fponly    = []regMask{fp}
90                 flagsonly = []regMask{flags}
91         )
92
93         // Common regInfo
94         var (
95                 gp01      = regInfo{inputs: []regMask{}, outputs: gponly}
96                 gp01flags = regInfo{inputs: []regMask{}, outputs: gponly, clobbers: flags}
97                 gp11      = regInfo{inputs: []regMask{gpsp}, outputs: gponly, clobbers: flags}
98                 gp11nf    = regInfo{inputs: []regMask{gpsp}, outputs: gponly} // nf: no flags clobbered
99                 gp11sb    = regInfo{inputs: []regMask{gpspsb}, outputs: gponly}
100                 gp21      = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly, clobbers: flags}
101                 gp21sb    = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly}
102                 gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}, clobbers: flags}
103                 gp11div   = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax},
104                         clobbers: dx | flags}
105                 gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx},
106                         clobbers: ax | flags}
107                 gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx},
108                         clobbers: ax | flags}
109                 gp10 = regInfo{inputs: []regMask{gp}}
110
111                 gp2flags  = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly}
112                 gp1flags  = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly}
113                 flagsgp   = regInfo{inputs: flagsonly, outputs: gponly}
114                 readflags = regInfo{inputs: flagsonly, outputs: gponly}
115                 flagsgpax = regInfo{inputs: flagsonly, clobbers: ax | flags, outputs: []regMask{gp &^ ax}}
116
117                 gpload    = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly}
118                 gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly}
119
120                 gpstore    = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
121                 gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}}
122
123                 fp01    = regInfo{inputs: []regMask{}, outputs: fponly}
124                 fp21    = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
125                 fp21x15 = regInfo{inputs: []regMask{fp &^ x15, fp &^ x15},
126                         clobbers: x15, outputs: []regMask{fp &^ x15}}
127                 fpgp     = regInfo{inputs: fponly, outputs: gponly}
128                 gpfp     = regInfo{inputs: gponly, outputs: fponly}
129                 fp11     = regInfo{inputs: fponly, outputs: fponly}
130                 fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly}
131                 // fp1flags = regInfo{inputs: fponly, outputs: flagsonly}
132
133                 fpload    = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly}
134                 fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly}
135
136                 fpstore    = regInfo{inputs: []regMask{gpspsb, fp, 0}}
137                 fpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, fp, 0}}
138         )
139         // TODO: most ops clobber flags
140
141         // Suffixes encode the bit width of various instructions.
142         // Q = 64 bit, L = 32 bit, W = 16 bit, B = 8 bit
143
144         // TODO: 2-address instructions.  Mark ops as needing matching input/output regs.
145         var AMD64ops = []opData{
146                 // fp ops
147                 {name: "ADDSS", reg: fp21, asm: "ADDSS"},    // fp32 add
148                 {name: "ADDSD", reg: fp21, asm: "ADDSD"},    // fp64 add
149                 {name: "SUBSS", reg: fp21x15, asm: "SUBSS"}, // fp32 sub
150                 {name: "SUBSD", reg: fp21x15, asm: "SUBSD"}, // fp64 sub
151                 {name: "MULSS", reg: fp21, asm: "MULSS"},    // fp32 mul
152                 {name: "MULSD", reg: fp21, asm: "MULSD"},    // fp64 mul
153                 {name: "DIVSS", reg: fp21x15, asm: "DIVSS"}, // fp32 div
154                 {name: "DIVSD", reg: fp21x15, asm: "DIVSD"}, // fp64 div
155
156                 {name: "MOVSSload", reg: fpload, asm: "MOVSS"},        // fp32 load
157                 {name: "MOVSDload", reg: fpload, asm: "MOVSD"},        // fp64 load
158                 {name: "MOVSSconst", reg: fp01, asm: "MOVSS"},         // fp32 constant
159                 {name: "MOVSDconst", reg: fp01, asm: "MOVSD"},         // fp64 constant
160                 {name: "MOVSSloadidx4", reg: fploadidx, asm: "MOVSS"}, // fp32 load
161                 {name: "MOVSDloadidx8", reg: fploadidx, asm: "MOVSD"}, // fp64 load
162
163                 {name: "MOVSSstore", reg: fpstore, asm: "MOVSS"},        // fp32 store
164                 {name: "MOVSDstore", reg: fpstore, asm: "MOVSD"},        // fp64 store
165                 {name: "MOVSSstoreidx4", reg: fpstoreidx, asm: "MOVSS"}, // fp32 indexed by 4i store
166                 {name: "MOVSDstoreidx8", reg: fpstoreidx, asm: "MOVSD"}, // fp64 indexed by 8i store
167
168                 // binary ops
169                 {name: "ADDQ", reg: gp21, asm: "ADDQ"},                     // arg0 + arg1
170                 {name: "ADDL", reg: gp21, asm: "ADDL"},                     // arg0 + arg1
171                 {name: "ADDW", reg: gp21, asm: "ADDW"},                     // arg0 + arg1
172                 {name: "ADDB", reg: gp21, asm: "ADDB"},                     // arg0 + arg1
173                 {name: "ADDQconst", reg: gp11, asm: "ADDQ", typ: "UInt64"}, // arg0 + auxint
174                 {name: "ADDLconst", reg: gp11, asm: "ADDL"},                // arg0 + auxint
175                 {name: "ADDWconst", reg: gp11, asm: "ADDW"},                // arg0 + auxint
176                 {name: "ADDBconst", reg: gp11, asm: "ADDB"},                // arg0 + auxint
177
178                 {name: "SUBQ", reg: gp21, asm: "SUBQ"},      // arg0 - arg1
179                 {name: "SUBL", reg: gp21, asm: "SUBL"},      // arg0 - arg1
180                 {name: "SUBW", reg: gp21, asm: "SUBW"},      // arg0 - arg1
181                 {name: "SUBB", reg: gp21, asm: "SUBB"},      // arg0 - arg1
182                 {name: "SUBQconst", reg: gp11, asm: "SUBQ"}, // arg0 - auxint
183                 {name: "SUBLconst", reg: gp11, asm: "SUBL"}, // arg0 - auxint
184                 {name: "SUBWconst", reg: gp11, asm: "SUBW"}, // arg0 - auxint
185                 {name: "SUBBconst", reg: gp11, asm: "SUBB"}, // arg0 - auxint
186
187                 {name: "MULQ", reg: gp21, asm: "IMULQ"},      // arg0 * arg1
188                 {name: "MULL", reg: gp21, asm: "IMULL"},      // arg0 * arg1
189                 {name: "MULW", reg: gp21, asm: "IMULW"},      // arg0 * arg1
190                 {name: "MULB", reg: gp21, asm: "IMULW"},      // arg0 * arg1
191                 {name: "MULQconst", reg: gp11, asm: "IMULQ"}, // arg0 * auxint
192                 {name: "MULLconst", reg: gp11, asm: "IMULL"}, // arg0 * auxint
193                 {name: "MULWconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint
194                 {name: "MULBconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint
195
196                 {name: "HMULL", reg: gp11hmul, asm: "IMULL"}, // (arg0 * arg1) >> width
197                 {name: "HMULW", reg: gp11hmul, asm: "IMULW"}, // (arg0 * arg1) >> width
198                 {name: "HMULB", reg: gp11hmul, asm: "IMULB"}, // (arg0 * arg1) >> width
199                 {name: "HMULLU", reg: gp11hmul, asm: "MULL"}, // (arg0 * arg1) >> width
200                 {name: "HMULWU", reg: gp11hmul, asm: "MULW"}, // (arg0 * arg1) >> width
201                 {name: "HMULBU", reg: gp11hmul, asm: "MULB"}, // (arg0 * arg1) >> width
202
203                 {name: "DIVQ", reg: gp11div, asm: "IDIVQ"}, // arg0 / arg1
204                 {name: "DIVL", reg: gp11div, asm: "IDIVL"}, // arg0 / arg1
205                 {name: "DIVW", reg: gp11div, asm: "IDIVW"}, // arg0 / arg1
206                 {name: "DIVQU", reg: gp11div, asm: "DIVQ"}, // arg0 / arg1
207                 {name: "DIVLU", reg: gp11div, asm: "DIVL"}, // arg0 / arg1
208                 {name: "DIVWU", reg: gp11div, asm: "DIVW"}, // arg0 / arg1
209
210                 {name: "MODQ", reg: gp11mod, asm: "IDIVQ"}, // arg0 % arg1
211                 {name: "MODL", reg: gp11mod, asm: "IDIVL"}, // arg0 % arg1
212                 {name: "MODW", reg: gp11mod, asm: "IDIVW"}, // arg0 % arg1
213                 {name: "MODQU", reg: gp11mod, asm: "DIVQ"}, // arg0 % arg1
214                 {name: "MODLU", reg: gp11mod, asm: "DIVL"}, // arg0 % arg1
215                 {name: "MODWU", reg: gp11mod, asm: "DIVW"}, // arg0 % arg1
216
217                 {name: "ANDQ", reg: gp21, asm: "ANDQ"},      // arg0 & arg1
218                 {name: "ANDL", reg: gp21, asm: "ANDL"},      // arg0 & arg1
219                 {name: "ANDW", reg: gp21, asm: "ANDW"},      // arg0 & arg1
220                 {name: "ANDB", reg: gp21, asm: "ANDB"},      // arg0 & arg1
221                 {name: "ANDQconst", reg: gp11, asm: "ANDQ"}, // arg0 & auxint
222                 {name: "ANDLconst", reg: gp11, asm: "ANDL"}, // arg0 & auxint
223                 {name: "ANDWconst", reg: gp11, asm: "ANDW"}, // arg0 & auxint
224                 {name: "ANDBconst", reg: gp11, asm: "ANDB"}, // arg0 & auxint
225
226                 {name: "ORQ", reg: gp21, asm: "ORQ"},      // arg0 | arg1
227                 {name: "ORL", reg: gp21, asm: "ORL"},      // arg0 | arg1
228                 {name: "ORW", reg: gp21, asm: "ORW"},      // arg0 | arg1
229                 {name: "ORB", reg: gp21, asm: "ORB"},      // arg0 | arg1
230                 {name: "ORQconst", reg: gp11, asm: "ORQ"}, // arg0 | auxint
231                 {name: "ORLconst", reg: gp11, asm: "ORL"}, // arg0 | auxint
232                 {name: "ORWconst", reg: gp11, asm: "ORW"}, // arg0 | auxint
233                 {name: "ORBconst", reg: gp11, asm: "ORB"}, // arg0 | auxint
234
235                 {name: "XORQ", reg: gp21, asm: "XORQ"},      // arg0 ^ arg1
236                 {name: "XORL", reg: gp21, asm: "XORL"},      // arg0 ^ arg1
237                 {name: "XORW", reg: gp21, asm: "XORW"},      // arg0 ^ arg1
238                 {name: "XORB", reg: gp21, asm: "XORB"},      // arg0 ^ arg1
239                 {name: "XORQconst", reg: gp11, asm: "XORQ"}, // arg0 ^ auxint
240                 {name: "XORLconst", reg: gp11, asm: "XORL"}, // arg0 ^ auxint
241                 {name: "XORWconst", reg: gp11, asm: "XORW"}, // arg0 ^ auxint
242                 {name: "XORBconst", reg: gp11, asm: "XORB"}, // arg0 ^ auxint
243
244                 {name: "CMPQ", reg: gp2flags, asm: "CMPQ", typ: "Flags"},      // arg0 compare to arg1
245                 {name: "CMPL", reg: gp2flags, asm: "CMPL", typ: "Flags"},      // arg0 compare to arg1
246                 {name: "CMPW", reg: gp2flags, asm: "CMPW", typ: "Flags"},      // arg0 compare to arg1
247                 {name: "CMPB", reg: gp2flags, asm: "CMPB", typ: "Flags"},      // arg0 compare to arg1
248                 {name: "CMPQconst", reg: gp1flags, asm: "CMPQ", typ: "Flags"}, // arg0 compare to auxint
249                 {name: "CMPLconst", reg: gp1flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to auxint
250                 {name: "CMPWconst", reg: gp1flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to auxint
251                 {name: "CMPBconst", reg: gp1flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to auxint
252
253                 {name: "UCOMISS", reg: fp2flags, asm: "UCOMISS", typ: "Flags"}, // arg0 compare to arg1, f32
254                 {name: "UCOMISD", reg: fp2flags, asm: "UCOMISD", typ: "Flags"}, // arg0 compare to arg1, f64
255
256                 {name: "TESTQ", reg: gp2flags, asm: "TESTQ", typ: "Flags"},      // (arg0 & arg1) compare to 0
257                 {name: "TESTL", reg: gp2flags, asm: "TESTL", typ: "Flags"},      // (arg0 & arg1) compare to 0
258                 {name: "TESTW", reg: gp2flags, asm: "TESTW", typ: "Flags"},      // (arg0 & arg1) compare to 0
259                 {name: "TESTB", reg: gp2flags, asm: "TESTB", typ: "Flags"},      // (arg0 & arg1) compare to 0
260                 {name: "TESTQconst", reg: gp1flags, asm: "TESTQ", typ: "Flags"}, // (arg0 & auxint) compare to 0
261                 {name: "TESTLconst", reg: gp1flags, asm: "TESTL", typ: "Flags"}, // (arg0 & auxint) compare to 0
262                 {name: "TESTWconst", reg: gp1flags, asm: "TESTW", typ: "Flags"}, // (arg0 & auxint) compare to 0
263                 {name: "TESTBconst", reg: gp1flags, asm: "TESTB", typ: "Flags"}, // (arg0 & auxint) compare to 0
264
265                 {name: "SHLQ", reg: gp21shift, asm: "SHLQ"}, // arg0 << arg1, shift amount is mod 64
266                 {name: "SHLL", reg: gp21shift, asm: "SHLL"}, // arg0 << arg1, shift amount is mod 32
267                 {name: "SHLW", reg: gp21shift, asm: "SHLW"}, // arg0 << arg1, shift amount is mod 32
268                 {name: "SHLB", reg: gp21shift, asm: "SHLB"}, // arg0 << arg1, shift amount is mod 32
269                 {name: "SHLQconst", reg: gp11, asm: "SHLQ"}, // arg0 << auxint, shift amount 0-63
270                 {name: "SHLLconst", reg: gp11, asm: "SHLL"}, // arg0 << auxint, shift amount 0-31
271                 {name: "SHLWconst", reg: gp11, asm: "SHLW"}, // arg0 << auxint, shift amount 0-31
272                 {name: "SHLBconst", reg: gp11, asm: "SHLB"}, // arg0 << auxint, shift amount 0-31
273                 // Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount!
274
275                 {name: "SHRQ", reg: gp21shift, asm: "SHRQ"}, // unsigned arg0 >> arg1, shift amount is mod 64
276                 {name: "SHRL", reg: gp21shift, asm: "SHRL"}, // unsigned arg0 >> arg1, shift amount is mod 32
277                 {name: "SHRW", reg: gp21shift, asm: "SHRW"}, // unsigned arg0 >> arg1, shift amount is mod 32
278                 {name: "SHRB", reg: gp21shift, asm: "SHRB"}, // unsigned arg0 >> arg1, shift amount is mod 32
279                 {name: "SHRQconst", reg: gp11, asm: "SHRQ"}, // unsigned arg0 >> auxint, shift amount 0-63
280                 {name: "SHRLconst", reg: gp11, asm: "SHRL"}, // unsigned arg0 >> auxint, shift amount 0-31
281                 {name: "SHRWconst", reg: gp11, asm: "SHRW"}, // unsigned arg0 >> auxint, shift amount 0-31
282                 {name: "SHRBconst", reg: gp11, asm: "SHRB"}, // unsigned arg0 >> auxint, shift amount 0-31
283
284                 {name: "SARQ", reg: gp21shift, asm: "SARQ"}, // signed arg0 >> arg1, shift amount is mod 64
285                 {name: "SARL", reg: gp21shift, asm: "SARL"}, // signed arg0 >> arg1, shift amount is mod 32
286                 {name: "SARW", reg: gp21shift, asm: "SARW"}, // signed arg0 >> arg1, shift amount is mod 32
287                 {name: "SARB", reg: gp21shift, asm: "SARB"}, // signed arg0 >> arg1, shift amount is mod 32
288                 {name: "SARQconst", reg: gp11, asm: "SARQ"}, // signed arg0 >> auxint, shift amount 0-63
289                 {name: "SARLconst", reg: gp11, asm: "SARL"}, // signed arg0 >> auxint, shift amount 0-31
290                 {name: "SARWconst", reg: gp11, asm: "SARW"}, // signed arg0 >> auxint, shift amount 0-31
291                 {name: "SARBconst", reg: gp11, asm: "SARB"}, // signed arg0 >> auxint, shift amount 0-31
292
293                 {name: "ROLQconst", reg: gp11, asm: "ROLQ"}, // arg0 rotate left auxint, rotate amount 0-63
294                 {name: "ROLLconst", reg: gp11, asm: "ROLL"}, // arg0 rotate left auxint, rotate amount 0-31
295                 {name: "ROLWconst", reg: gp11, asm: "ROLW"}, // arg0 rotate left auxint, rotate amount 0-15
296                 {name: "ROLBconst", reg: gp11, asm: "ROLB"}, // arg0 rotate left auxint, rotate amount 0-7
297
298                 // unary ops
299                 {name: "NEGQ", reg: gp11, asm: "NEGQ"}, // -arg0
300                 {name: "NEGL", reg: gp11, asm: "NEGL"}, // -arg0
301                 {name: "NEGW", reg: gp11, asm: "NEGW"}, // -arg0
302                 {name: "NEGB", reg: gp11, asm: "NEGB"}, // -arg0
303
304                 {name: "NOTQ", reg: gp11, asm: "NOTQ"}, // ^arg0
305                 {name: "NOTL", reg: gp11, asm: "NOTL"}, // ^arg0
306                 {name: "NOTW", reg: gp11, asm: "NOTW"}, // ^arg0
307                 {name: "NOTB", reg: gp11, asm: "NOTB"}, // ^arg0
308
309                 {name: "SQRTSD", reg: fp11, asm: "SQRTSD"}, // sqrt(arg0)
310
311                 {name: "SBBQcarrymask", reg: flagsgp, asm: "SBBQ"}, // (int64)(-1) if carry is set, 0 if carry is clear.
312                 {name: "SBBLcarrymask", reg: flagsgp, asm: "SBBL"}, // (int32)(-1) if carry is set, 0 if carry is clear.
313                 // Note: SBBW and SBBB are subsumed by SBBL
314
315                 {name: "SETEQ", reg: readflags, asm: "SETEQ"}, // extract == condition from arg0
316                 {name: "SETNE", reg: readflags, asm: "SETNE"}, // extract != condition from arg0
317                 {name: "SETL", reg: readflags, asm: "SETLT"},  // extract signed < condition from arg0
318                 {name: "SETLE", reg: readflags, asm: "SETLE"}, // extract signed <= condition from arg0
319                 {name: "SETG", reg: readflags, asm: "SETGT"},  // extract signed > condition from arg0
320                 {name: "SETGE", reg: readflags, asm: "SETGE"}, // extract signed >= condition from arg0
321                 {name: "SETB", reg: readflags, asm: "SETCS"},  // extract unsigned < condition from arg0
322                 {name: "SETBE", reg: readflags, asm: "SETLS"}, // extract unsigned <= condition from arg0
323                 {name: "SETA", reg: readflags, asm: "SETHI"},  // extract unsigned > condition from arg0
324                 {name: "SETAE", reg: readflags, asm: "SETCC"}, // extract unsigned >= condition from arg0
325                 // Need different opcodes for floating point conditions because
326                 // any comparison involving a NaN is always FALSE and thus
327                 // the patterns for inverting conditions cannot be used.
328                 {name: "SETEQF", reg: flagsgpax, asm: "SETEQ"}, // extract == condition from arg0
329                 {name: "SETNEF", reg: flagsgpax, asm: "SETNE"}, // extract != condition from arg0
330                 {name: "SETORD", reg: flagsgp, asm: "SETPC"},   // extract "ordered" (No Nan present) condition from arg0
331                 {name: "SETNAN", reg: flagsgp, asm: "SETPS"},   // extract "unordered" (Nan present) condition from arg0
332
333                 {name: "SETGF", reg: flagsgp, asm: "SETHI"},  // extract floating > condition from arg0
334                 {name: "SETGEF", reg: flagsgp, asm: "SETCC"}, // extract floating >= condition from arg0
335
336                 {name: "MOVBQSX", reg: gp11nf, asm: "MOVBQSX"}, // sign extend arg0 from int8 to int64
337                 {name: "MOVBQZX", reg: gp11nf, asm: "MOVBQZX"}, // zero extend arg0 from int8 to int64
338                 {name: "MOVWQSX", reg: gp11nf, asm: "MOVWQSX"}, // sign extend arg0 from int16 to int64
339                 {name: "MOVWQZX", reg: gp11nf, asm: "MOVWQZX"}, // zero extend arg0 from int16 to int64
340                 {name: "MOVLQSX", reg: gp11nf, asm: "MOVLQSX"}, // sign extend arg0 from int32 to int64
341                 {name: "MOVLQZX", reg: gp11nf, asm: "MOVLQZX"}, // zero extend arg0 from int32 to int64
342
343                 // clobbers flags as liblink will rewrite these to XOR reg, reg if the constant is zero
344                 // TODO: revisit when issue 12405 is fixed
345                 {name: "MOVBconst", reg: gp01flags, asm: "MOVB", typ: "UInt8"},  // 8 low bits of auxint
346                 {name: "MOVWconst", reg: gp01flags, asm: "MOVW", typ: "UInt16"}, // 16 low bits of auxint
347                 {name: "MOVLconst", reg: gp01flags, asm: "MOVL", typ: "UInt32"}, // 32 low bits of auxint
348                 {name: "MOVQconst", reg: gp01flags, asm: "MOVQ", typ: "UInt64"}, // auxint
349
350                 {name: "CVTTSD2SL", reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32
351                 {name: "CVTTSD2SQ", reg: fpgp, asm: "CVTTSD2SQ"}, // convert float64 to int64
352                 {name: "CVTTSS2SL", reg: fpgp, asm: "CVTTSS2SL"}, // convert float32 to int32
353                 {name: "CVTTSS2SQ", reg: fpgp, asm: "CVTTSS2SQ"}, // convert float32 to int64
354                 {name: "CVTSL2SS", reg: gpfp, asm: "CVTSL2SS"},   // convert int32 to float32
355                 {name: "CVTSL2SD", reg: gpfp, asm: "CVTSL2SD"},   // convert int32 to float64
356                 {name: "CVTSQ2SS", reg: gpfp, asm: "CVTSQ2SS"},   // convert int64 to float32
357                 {name: "CVTSQ2SD", reg: gpfp, asm: "CVTSQ2SD"},   // convert int64 to float64
358                 {name: "CVTSD2SS", reg: fp11, asm: "CVTSD2SS"},   // convert float64 to float32
359                 {name: "CVTSS2SD", reg: fp11, asm: "CVTSS2SD"},   // convert float32 to float64
360
361                 {name: "PXOR", reg: fp21, asm: "PXOR"}, // exclusive or, applied to X regs for float negation.
362
363                 {name: "LEAQ", reg: gp11sb},  // arg0 + auxint + offset encoded in aux
364                 {name: "LEAQ1", reg: gp21sb}, // arg0 + arg1 + auxint
365                 {name: "LEAQ2", reg: gp21sb}, // arg0 + 2*arg1 + auxint
366                 {name: "LEAQ4", reg: gp21sb}, // arg0 + 4*arg1 + auxint
367                 {name: "LEAQ8", reg: gp21sb}, // arg0 + 8*arg1 + auxint
368
369                 // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
370                 {name: "MOVBload", reg: gpload, asm: "MOVB"},               // load byte from arg0+auxint+aux. arg1=mem
371                 {name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX"},         // ditto, extend to int64
372                 {name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX"},         // ditto, extend to uint64
373                 {name: "MOVWload", reg: gpload, asm: "MOVW"},               // load 2 bytes from arg0+auxint+aux. arg1=mem
374                 {name: "MOVLload", reg: gpload, asm: "MOVL"},               // load 4 bytes from arg0+auxint+aux. arg1=mem
375                 {name: "MOVQload", reg: gpload, asm: "MOVQ"},               // load 8 bytes from arg0+auxint+aux. arg1=mem
376                 {name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ"},        // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem
377                 {name: "MOVBstore", reg: gpstore, asm: "MOVB", typ: "Mem"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
378                 {name: "MOVWstore", reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
379                 {name: "MOVLstore", reg: gpstore, asm: "MOVL", typ: "Mem"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
380                 {name: "MOVQstore", reg: gpstore, asm: "MOVQ", typ: "Mem"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
381                 {name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ"},      // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem
382
383                 // arg0 = (duff-adjusted) pointer to start of memory to zero
384                 // arg1 = value to store (will always be zero)
385                 // arg2 = mem
386                 // auxint = offset into duffzero code to start executing
387                 // returns mem
388                 {
389                         name: "DUFFZERO",
390                         reg: regInfo{
391                                 inputs:   []regMask{buildReg("DI"), buildReg("X0")},
392                                 clobbers: buildReg("DI FLAGS"),
393                         },
394                 },
395                 {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Float64"},
396
397                 // arg0 = address of memory to zero
398                 // arg1 = # of 8-byte words to zero
399                 // arg2 = value to store (will always be zero)
400                 // arg3 = mem
401                 // returns mem
402                 {
403                         name: "REPSTOSQ",
404                         reg: regInfo{
405                                 inputs:   []regMask{buildReg("DI"), buildReg("CX"), buildReg("AX")},
406                                 clobbers: buildReg("DI CX FLAGS"),
407                         },
408                 },
409
410                 {name: "CALLstatic", reg: regInfo{clobbers: callerSave}},                                 // call static function aux.(*gc.Sym).  arg0=mem, auxint=argsize, returns mem
411                 {name: "CALLclosure", reg: regInfo{[]regMask{gpsp, buildReg("DX"), 0}, callerSave, nil}}, // call function via closure.  arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
412                 {name: "CALLdefer", reg: regInfo{clobbers: callerSave}},                                  // call deferproc.  arg0=mem, auxint=argsize, returns mem
413                 {name: "CALLgo", reg: regInfo{clobbers: callerSave}},                                     // call newproc.  arg0=mem, auxint=argsize, returns mem
414                 {name: "CALLinter", reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}},           // call fn by pointer.  arg0=codeptr, arg1=mem, auxint=argsize, returns mem
415
416                 {name: "REPMOVSB", reg: regInfo{[]regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")}, buildReg("DI SI CX"), nil}}, // move arg2 bytes from arg1 to arg0.  arg3=mem, returns memory
417
418                 // (InvertFlags (CMPQ a b)) == (CMPQ b a)
419                 // So if we want (SETL (CMPQ a b)) but we can't do that because a is a constant,
420                 // then we do (SETL (InvertFlags (CMPQ b a))) instead.
421                 // Rewrites will convert this to (SETG (CMPQ b a)).
422                 // InvertFlags is a pseudo-op which can't appear in assembly output.
423                 {name: "InvertFlags"}, // reverse direction of arg0
424
425                 // Pseudo-ops
426                 {name: "LoweredPanicNilCheck", reg: gp10},
427                 {name: "LoweredGetG", reg: gp01}, // arg0=mem
428                 // Scheduler ensures LoweredGetClosurePtr occurs only in entry block,
429                 // and sorts it to the very beginning of the block to prevent other
430                 // use of DX (the closure pointer)
431                 {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
432         }
433
434         var AMD64blocks = []blockData{
435                 {name: "EQ"},
436                 {name: "NE"},
437                 {name: "LT"},
438                 {name: "LE"},
439                 {name: "GT"},
440                 {name: "GE"},
441                 {name: "ULT"},
442                 {name: "ULE"},
443                 {name: "UGT"},
444                 {name: "UGE"},
445                 {name: "EQF"},
446                 {name: "NEF"},
447                 {name: "ORD"}, // FP, ordered comparison (parity zero)
448                 {name: "NAN"}, // FP, unordered comparison (parity one)
449         }
450
451         archs = append(archs, arch{"AMD64", AMD64ops, AMD64blocks, regNamesAMD64})
452 }