1
2
3
4
5 package amd64
6
7 import (
8 "fmt"
9 "math"
10
11 "cmd/compile/internal/base"
12 "cmd/compile/internal/ir"
13 "cmd/compile/internal/logopt"
14 "cmd/compile/internal/objw"
15 "cmd/compile/internal/ssa"
16 "cmd/compile/internal/ssa/block"
17 "cmd/compile/internal/ssa/ssaop"
18 "cmd/compile/internal/ssagen"
19 "cmd/compile/internal/types"
20 "cmd/internal/obj"
21 "cmd/internal/obj/x86"
22 "internal/abi"
23 "internal/buildcfg"
24 )
25
26
27 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {
28 flive := b.FlagsLiveAtEnd
29 for _, c := range b.ControlValues() {
30 flive = c.Type.IsFlags() || flive
31 }
32 for i := len(b.Values) - 1; i >= 0; i-- {
33 v := b.Values[i]
34 if flive && (v.Op == ssaop.OpAMD64MOVLconst || v.Op == ssaop.OpAMD64MOVQconst) {
35
36 v.Aux = ssa.AuxMark
37 }
38 if v.Type.IsFlags() {
39 flive = false
40 }
41 for _, a := range v.Args {
42 if a.Type.IsFlags() {
43 flive = true
44 }
45 }
46 }
47 }
48
49 func isGPReg(r int16) bool {
50 return x86.REG_AL <= r && r <= x86.REG_R15
51 }
52
53 func isFPReg(r int16) bool {
54 return x86.REG_X0 <= r && r <= x86.REG_Z31
55 }
56
57 func isKReg(r int16) bool {
58 return x86.REG_K0 <= r && r <= x86.REG_K7
59 }
60
61 func isLowFPReg(r int16) bool {
62 return x86.REG_X0 <= r && r <= x86.REG_X15
63 }
64
65 func isHighFPReg(r int16) bool {
66 return x86.REG_X16 <= r && r <= x86.REG_X31 || x86.REG_Y16 <= r && r <= x86.REG_Y31 || x86.REG_Z16 <= r && r <= x86.REG_Z31
67 }
68
69
70
71
72
73 func loadByRegWidth(r int16, width int64, avx bool) obj.As {
74
75 if !isFPReg(r) && !isKReg(r) {
76 switch width {
77 case 1:
78 return x86.AMOVBLZX
79 case 2:
80 return x86.AMOVWLZX
81 }
82 }
83
84 return storeByRegWidth(r, width, avx)
85 }
86
87
88
89
90 func storeByRegWidth(r int16, width int64, avx bool) obj.As {
91 if isHighFPReg(r) {
92
93 return x86.AVMOVDQU64
94 }
95 if isFPReg(r) {
96 if avx {
97 switch width {
98 case 4:
99 return x86.AVMOVSS
100 case 8:
101 return x86.AVMOVSD
102 case 16:
103 return x86.AVMOVUPS
104 }
105 }
106 switch width {
107 case 4:
108 return x86.AMOVSS
109 case 8:
110 return x86.AMOVSD
111 case 16:
112
113 return x86.AMOVUPS
114 case 32:
115 return x86.AVMOVDQU
116 case 64:
117 return x86.AVMOVDQU64
118 }
119 }
120 if isKReg(r) {
121 return x86.AKMOVQ
122 }
123
124 switch width {
125 case 1:
126 return x86.AMOVB
127 case 2:
128 return x86.AMOVW
129 case 4:
130 return x86.AMOVL
131 case 8:
132 return x86.AMOVQ
133 }
134 panic(fmt.Sprintf("bad store reg=%v, width=%d", r, width))
135 }
136
137
138
139 func moveByRegsWidth(dest, src int16, width int64, avx bool) obj.As {
140
141 if isFPReg(dest) && isFPReg(src) {
142 if isHighFPReg(src) || isHighFPReg(dest) {
143
144 return x86.AVMOVDQU64
145 }
146
147
148
149
150 if width <= 16 {
151 if avx {
152 return x86.AVMOVUPS
153 }
154 return x86.AMOVUPS
155 }
156 if width <= 32 {
157 return x86.AVMOVDQU
158 }
159 return x86.AVMOVDQU64
160 }
161
162 if isKReg(dest) || isKReg(src) {
163 if isFPReg(dest) || isFPReg(src) {
164 panic(fmt.Sprintf("bad move, src=%v, dest=%v, width=%d", src, dest, width))
165 }
166 return x86.AKMOVQ
167 }
168
169 if avx && (isFPReg(dest) || isFPReg(src)) {
170 switch width {
171 case 1, 2, 4:
172 return x86.AVMOVD
173 case 8:
174 return x86.AVMOVQ
175 }
176 }
177
178 switch width {
179 case 1:
180
181 return x86.AMOVL
182 case 2:
183 return x86.AMOVL
184 case 4:
185 return x86.AMOVL
186 case 8:
187 return x86.AMOVQ
188 case 16:
189
190 return x86.AMOVUPS
191 case 32:
192 return x86.AVMOVDQU
193 case 64:
194 return x86.AVMOVDQU64
195 }
196 panic(fmt.Sprintf("bad move, src=%v, dest=%v, width=%d", src, dest, width))
197 }
198
199
200
201
202
203
204
205 func opregreg(s *ssagen.State, op obj.As, dest, src int16) *obj.Prog {
206 p := s.Prog(op)
207 p.From.Type = obj.TYPE_REG
208 p.To.Type = obj.TYPE_REG
209 p.To.Reg = dest
210 p.From.Reg = src
211 return p
212 }
213
214
215
216
217
218 func memIdx(a *obj.Addr, v *ssa.Value) {
219 r, i := v.Args[0].Reg(), v.Args[1].Reg()
220 a.Type = obj.TYPE_MEM
221 a.Scale = v.Op.Scale()
222 if a.Scale == 1 && i == x86.REG_SP {
223 r, i = i, r
224 }
225 a.Reg = r
226 a.Index = i
227 }
228
229 func getgFromTLS(s *ssagen.State, r int16) {
230
231
232 if x86.CanUse1InsnTLS(base.Ctxt) {
233
234 p := s.Prog(x86.AMOVQ)
235 p.From.Type = obj.TYPE_MEM
236 p.From.Reg = x86.REG_TLS
237 p.To.Type = obj.TYPE_REG
238 p.To.Reg = r
239 } else {
240
241
242 p := s.Prog(x86.AMOVQ)
243 p.From.Type = obj.TYPE_REG
244 p.From.Reg = x86.REG_TLS
245 p.To.Type = obj.TYPE_REG
246 p.To.Reg = r
247 q := s.Prog(x86.AMOVQ)
248 q.From.Type = obj.TYPE_MEM
249 q.From.Reg = r
250 q.From.Index = x86.REG_TLS
251 q.From.Scale = 1
252 q.To.Type = obj.TYPE_REG
253 q.To.Reg = r
254 }
255 }
256
257 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
258 switch v.Op {
259 case ssaop.OpAMD64VFMADD231SD, ssaop.OpAMD64VFMADD231SS, ssaop.OpAMD64VFMSUB231SD, ssaop.OpAMD64VFMSUB231SS, ssaop.OpAMD64VFNMADD231SD, ssaop.OpAMD64VFNMADD231SS:
260 p := s.Prog(v.Op.Asm())
261 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: v.Args[2].Reg()}
262 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
263 p.AddRestSourceReg(v.Args[1].Reg())
264 case ssaop.OpAMD64ADDQ, ssaop.OpAMD64ADDL:
265 r := v.Reg()
266 r1 := v.Args[0].Reg()
267 r2 := v.Args[1].Reg()
268 switch {
269 case r == r1:
270 p := s.Prog(v.Op.Asm())
271 p.From.Type = obj.TYPE_REG
272 p.From.Reg = r2
273 p.To.Type = obj.TYPE_REG
274 p.To.Reg = r
275 case r == r2:
276 p := s.Prog(v.Op.Asm())
277 p.From.Type = obj.TYPE_REG
278 p.From.Reg = r1
279 p.To.Type = obj.TYPE_REG
280 p.To.Reg = r
281 default:
282 var asm obj.As
283 if v.Op == ssaop.OpAMD64ADDQ {
284 asm = x86.ALEAQ
285 } else {
286 asm = x86.ALEAL
287 }
288 p := s.Prog(asm)
289 p.From.Type = obj.TYPE_MEM
290 p.From.Reg = r1
291 p.From.Scale = 1
292 p.From.Index = r2
293 p.To.Type = obj.TYPE_REG
294 p.To.Reg = r
295 }
296
297 case ssaop.OpAMD64SUBQ, ssaop.OpAMD64SUBL,
298 ssaop.OpAMD64MULQ, ssaop.OpAMD64MULL,
299 ssaop.OpAMD64ANDQ, ssaop.OpAMD64ANDL,
300 ssaop.OpAMD64ORQ, ssaop.OpAMD64ORL,
301 ssaop.OpAMD64XORQ, ssaop.OpAMD64XORL,
302 ssaop.OpAMD64SHLQ, ssaop.OpAMD64SHLL,
303 ssaop.OpAMD64SHRQ, ssaop.OpAMD64SHRL, ssaop.OpAMD64SHRW, ssaop.OpAMD64SHRB,
304 ssaop.OpAMD64SARQ, ssaop.OpAMD64SARL, ssaop.OpAMD64SARW, ssaop.OpAMD64SARB,
305 ssaop.OpAMD64ROLQ, ssaop.OpAMD64ROLL, ssaop.OpAMD64ROLW, ssaop.OpAMD64ROLB,
306 ssaop.OpAMD64RORQ, ssaop.OpAMD64RORL, ssaop.OpAMD64RORW, ssaop.OpAMD64RORB,
307 ssaop.OpAMD64ADDSS, ssaop.OpAMD64ADDSD, ssaop.OpAMD64SUBSS, ssaop.OpAMD64SUBSD,
308 ssaop.OpAMD64MULSS, ssaop.OpAMD64MULSD, ssaop.OpAMD64DIVSS, ssaop.OpAMD64DIVSD,
309 ssaop.OpAMD64MINSS, ssaop.OpAMD64MINSD,
310 ssaop.OpAMD64MAXSS, ssaop.OpAMD64MAXSD,
311 ssaop.OpAMD64POR, ssaop.OpAMD64PXOR,
312 ssaop.OpAMD64BTSL, ssaop.OpAMD64BTSQ,
313 ssaop.OpAMD64BTCL, ssaop.OpAMD64BTCQ,
314 ssaop.OpAMD64BTRL, ssaop.OpAMD64BTRQ,
315 ssaop.OpAMD64PCMPEQB, ssaop.OpAMD64PSIGNB,
316 ssaop.OpAMD64PUNPCKLBW:
317 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
318
319 case ssaop.OpAMD64PSHUFLW:
320 p := s.Prog(v.Op.Asm())
321 imm := v.AuxInt
322 if imm < 0 || imm > 255 {
323 v.Fatalf("Invalid source selection immediate")
324 }
325 p.From.Offset = imm
326 p.From.Type = obj.TYPE_CONST
327 p.AddRestSourceReg(v.Args[0].Reg())
328 p.To.Type = obj.TYPE_REG
329 p.To.Reg = v.Reg()
330
331 case ssaop.OpAMD64PSHUFBbroadcast:
332
333
334
335
336 if s.ABI != obj.ABIInternal {
337
338 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
339 }
340
341 p := s.Prog(v.Op.Asm())
342 p.From.Type = obj.TYPE_REG
343 p.To.Type = obj.TYPE_REG
344 p.To.Reg = v.Reg()
345 p.From.Reg = x86.REG_X15
346
347 case ssaop.OpAMD64BLSIQ, ssaop.OpAMD64BLSIL,
348 ssaop.OpAMD64BLSMSKQ, ssaop.OpAMD64BLSMSKL,
349 ssaop.OpAMD64BLSRQ, ssaop.OpAMD64BLSRL:
350 p := s.Prog(v.Op.Asm())
351 p.From.Type = obj.TYPE_REG
352 p.From.Reg = v.Args[0].Reg()
353 p.To.Type = obj.TYPE_REG
354 switch v.Op {
355 case ssaop.OpAMD64BLSRQ, ssaop.OpAMD64BLSRL:
356 p.To.Reg = v.Reg0()
357 default:
358 p.To.Reg = v.Reg()
359 }
360
361 case ssaop.OpAMD64ANDNQ, ssaop.OpAMD64ANDNL:
362 p := s.Prog(v.Op.Asm())
363 p.From.Type = obj.TYPE_REG
364 p.From.Reg = v.Args[0].Reg()
365 p.To.Type = obj.TYPE_REG
366 p.To.Reg = v.Reg()
367 p.AddRestSourceReg(v.Args[1].Reg())
368
369 case ssaop.OpAMD64SARXL, ssaop.OpAMD64SARXQ,
370 ssaop.OpAMD64SHLXL, ssaop.OpAMD64SHLXQ,
371 ssaop.OpAMD64SHRXL, ssaop.OpAMD64SHRXQ:
372 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
373 p.AddRestSourceReg(v.Args[0].Reg())
374
375 case ssaop.OpAMD64SHLXLload, ssaop.OpAMD64SHLXQload,
376 ssaop.OpAMD64SHRXLload, ssaop.OpAMD64SHRXQload,
377 ssaop.OpAMD64SARXLload, ssaop.OpAMD64SARXQload:
378 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
379 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
380 ssagen.AddAux(&m, v)
381 p.AddRestSource(m)
382
383 case ssaop.OpAMD64SHLXLloadidx1, ssaop.OpAMD64SHLXLloadidx4, ssaop.OpAMD64SHLXLloadidx8,
384 ssaop.OpAMD64SHRXLloadidx1, ssaop.OpAMD64SHRXLloadidx4, ssaop.OpAMD64SHRXLloadidx8,
385 ssaop.OpAMD64SARXLloadidx1, ssaop.OpAMD64SARXLloadidx4, ssaop.OpAMD64SARXLloadidx8,
386 ssaop.OpAMD64SHLXQloadidx1, ssaop.OpAMD64SHLXQloadidx8,
387 ssaop.OpAMD64SHRXQloadidx1, ssaop.OpAMD64SHRXQloadidx8,
388 ssaop.OpAMD64SARXQloadidx1, ssaop.OpAMD64SARXQloadidx8:
389 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[2].Reg())
390 m := obj.Addr{Type: obj.TYPE_MEM}
391 memIdx(&m, v)
392 ssagen.AddAux(&m, v)
393 p.AddRestSource(m)
394
395 case ssaop.OpAMD64DIVQU, ssaop.OpAMD64DIVLU, ssaop.OpAMD64DIVWU:
396
397
398
399
400 r := v.Args[1].Reg()
401
402
403 opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
404
405
406 p := s.Prog(v.Op.Asm())
407 p.From.Type = obj.TYPE_REG
408 p.From.Reg = r
409
410 case ssaop.OpAMD64DIVQ, ssaop.OpAMD64DIVL, ssaop.OpAMD64DIVW:
411
412
413
414
415 r := v.Args[1].Reg()
416
417 var opCMP, opNEG, opSXD obj.As
418 switch v.Op {
419 case ssaop.OpAMD64DIVQ:
420 opCMP, opNEG, opSXD = x86.ACMPQ, x86.ANEGQ, x86.ACQO
421 case ssaop.OpAMD64DIVL:
422 opCMP, opNEG, opSXD = x86.ACMPL, x86.ANEGL, x86.ACDQ
423 case ssaop.OpAMD64DIVW:
424 opCMP, opNEG, opSXD = x86.ACMPW, x86.ANEGW, x86.ACWD
425 }
426
427
428
429 var j1, j2 *obj.Prog
430 if ssa.DivisionNeedsFixUp(v) {
431 c := s.Prog(opCMP)
432 c.From.Type = obj.TYPE_REG
433 c.From.Reg = r
434 c.To.Type = obj.TYPE_CONST
435 c.To.Offset = -1
436
437
438 j1 = s.Prog(x86.AJNE)
439 j1.To.Type = obj.TYPE_BRANCH
440
441
442
443 n1 := s.Prog(opNEG)
444 n1.To.Type = obj.TYPE_REG
445 n1.To.Reg = x86.REG_AX
446
447
448 opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
449
450
451
452
453
454 j2 = s.Prog(obj.AJMP)
455 j2.To.Type = obj.TYPE_BRANCH
456 }
457
458
459 p := s.Prog(opSXD)
460 if j1 != nil {
461 j1.To.SetTarget(p)
462 }
463 p = s.Prog(v.Op.Asm())
464 p.From.Type = obj.TYPE_REG
465 p.From.Reg = r
466
467 if j2 != nil {
468 j2.To.SetTarget(s.Pc())
469 }
470
471 case ssaop.OpAMD64HMULQ, ssaop.OpAMD64HMULL, ssaop.OpAMD64HMULQU, ssaop.OpAMD64HMULLU:
472
473
474
475
476
477
478 p := s.Prog(v.Op.Asm())
479 p.From.Type = obj.TYPE_REG
480 p.From.Reg = v.Args[1].Reg()
481
482
483
484 if v.Type.Size() == 1 {
485 m := s.Prog(x86.AMOVB)
486 m.From.Type = obj.TYPE_REG
487 m.From.Reg = x86.REG_AH
488 m.To.Type = obj.TYPE_REG
489 m.To.Reg = x86.REG_DX
490 }
491
492 case ssaop.OpAMD64MULQU, ssaop.OpAMD64MULLU:
493
494
495 p := s.Prog(v.Op.Asm())
496 p.From.Type = obj.TYPE_REG
497 p.From.Reg = v.Args[1].Reg()
498
499 case ssaop.OpAMD64MULQU2:
500
501
502 p := s.Prog(v.Op.Asm())
503 p.From.Type = obj.TYPE_REG
504 p.From.Reg = v.Args[1].Reg()
505
506 case ssaop.OpAMD64MULXQ:
507
508
509
510 p := s.Prog(v.Op.Asm())
511 p.From.Type = obj.TYPE_REG
512 p.From.Reg = v.Args[1].Reg()
513 p.AddRestSourceReg(v.Reg1())
514 p.To.Type = obj.TYPE_REG
515 p.To.Reg = v.Reg0()
516
517 case ssaop.OpAMD64DIVQU2:
518
519
520 p := s.Prog(v.Op.Asm())
521 p.From.Type = obj.TYPE_REG
522 p.From.Reg = v.Args[2].Reg()
523
524 case ssaop.OpAMD64AVGQU:
525
526
527
528 p := s.Prog(x86.AADDQ)
529 p.From.Type = obj.TYPE_REG
530 p.To.Type = obj.TYPE_REG
531 p.To.Reg = v.Reg()
532 p.From.Reg = v.Args[1].Reg()
533 p = s.Prog(x86.ARCRQ)
534 p.From.Type = obj.TYPE_CONST
535 p.From.Offset = 1
536 p.To.Type = obj.TYPE_REG
537 p.To.Reg = v.Reg()
538
539 case ssaop.OpAMD64ADDQcarry, ssaop.OpAMD64ADCQ:
540 r := v.Reg0()
541 r0 := v.Args[0].Reg()
542 r1 := v.Args[1].Reg()
543 switch r {
544 case r0:
545 p := s.Prog(v.Op.Asm())
546 p.From.Type = obj.TYPE_REG
547 p.From.Reg = r1
548 p.To.Type = obj.TYPE_REG
549 p.To.Reg = r
550 case r1:
551 p := s.Prog(v.Op.Asm())
552 p.From.Type = obj.TYPE_REG
553 p.From.Reg = r0
554 p.To.Type = obj.TYPE_REG
555 p.To.Reg = r
556 default:
557 v.Fatalf("output not in same register as an input %s", v.LongString())
558 }
559
560 case ssaop.OpAMD64SUBQborrow, ssaop.OpAMD64SBBQ:
561 p := s.Prog(v.Op.Asm())
562 p.From.Type = obj.TYPE_REG
563 p.From.Reg = v.Args[1].Reg()
564 p.To.Type = obj.TYPE_REG
565 p.To.Reg = v.Reg0()
566
567 case ssaop.OpAMD64ADDQconstcarry, ssaop.OpAMD64ADCQconst, ssaop.OpAMD64SUBQconstborrow, ssaop.OpAMD64SBBQconst:
568 p := s.Prog(v.Op.Asm())
569 p.From.Type = obj.TYPE_CONST
570 p.From.Offset = v.AuxInt
571 p.To.Type = obj.TYPE_REG
572 p.To.Reg = v.Reg0()
573
574 case ssaop.OpAMD64ADDQconst, ssaop.OpAMD64ADDLconst:
575 r := v.Reg()
576 a := v.Args[0].Reg()
577 if r == a {
578 switch v.AuxInt {
579 case 1:
580 var asm obj.As
581
582
583
584
585
586 if v.Op == ssaop.OpAMD64ADDQconst {
587 asm = x86.AINCQ
588 } else {
589 asm = x86.AINCL
590 }
591 p := s.Prog(asm)
592 p.To.Type = obj.TYPE_REG
593 p.To.Reg = r
594 return
595 case -1:
596 var asm obj.As
597 if v.Op == ssaop.OpAMD64ADDQconst {
598 asm = x86.ADECQ
599 } else {
600 asm = x86.ADECL
601 }
602 p := s.Prog(asm)
603 p.To.Type = obj.TYPE_REG
604 p.To.Reg = r
605 return
606 case 0x80:
607
608
609 asm := x86.ASUBL
610 if v.Op == ssaop.OpAMD64ADDQconst {
611 asm = x86.ASUBQ
612 }
613 p := s.Prog(asm)
614 p.From.Type = obj.TYPE_CONST
615 p.From.Offset = -0x80
616 p.To.Type = obj.TYPE_REG
617 p.To.Reg = r
618 return
619
620 }
621 p := s.Prog(v.Op.Asm())
622 p.From.Type = obj.TYPE_CONST
623 p.From.Offset = v.AuxInt
624 p.To.Type = obj.TYPE_REG
625 p.To.Reg = r
626 return
627 }
628 var asm obj.As
629 if v.Op == ssaop.OpAMD64ADDQconst {
630 asm = x86.ALEAQ
631 } else {
632 asm = x86.ALEAL
633 }
634 p := s.Prog(asm)
635 p.From.Type = obj.TYPE_MEM
636 p.From.Reg = a
637 p.From.Offset = v.AuxInt
638 p.To.Type = obj.TYPE_REG
639 p.To.Reg = r
640
641 case ssaop.OpAMD64CMOVQEQ, ssaop.OpAMD64CMOVLEQ, ssaop.OpAMD64CMOVWEQ,
642 ssaop.OpAMD64CMOVQLT, ssaop.OpAMD64CMOVLLT, ssaop.OpAMD64CMOVWLT,
643 ssaop.OpAMD64CMOVQNE, ssaop.OpAMD64CMOVLNE, ssaop.OpAMD64CMOVWNE,
644 ssaop.OpAMD64CMOVQGT, ssaop.OpAMD64CMOVLGT, ssaop.OpAMD64CMOVWGT,
645 ssaop.OpAMD64CMOVQLE, ssaop.OpAMD64CMOVLLE, ssaop.OpAMD64CMOVWLE,
646 ssaop.OpAMD64CMOVQGE, ssaop.OpAMD64CMOVLGE, ssaop.OpAMD64CMOVWGE,
647 ssaop.OpAMD64CMOVQHI, ssaop.OpAMD64CMOVLHI, ssaop.OpAMD64CMOVWHI,
648 ssaop.OpAMD64CMOVQLS, ssaop.OpAMD64CMOVLLS, ssaop.OpAMD64CMOVWLS,
649 ssaop.OpAMD64CMOVQCC, ssaop.OpAMD64CMOVLCC, ssaop.OpAMD64CMOVWCC,
650 ssaop.OpAMD64CMOVQCS, ssaop.OpAMD64CMOVLCS, ssaop.OpAMD64CMOVWCS,
651 ssaop.OpAMD64CMOVQGTF, ssaop.OpAMD64CMOVLGTF, ssaop.OpAMD64CMOVWGTF,
652 ssaop.OpAMD64CMOVQGEF, ssaop.OpAMD64CMOVLGEF, ssaop.OpAMD64CMOVWGEF:
653 p := s.Prog(v.Op.Asm())
654 p.From.Type = obj.TYPE_REG
655 p.From.Reg = v.Args[1].Reg()
656 p.To.Type = obj.TYPE_REG
657 p.To.Reg = v.Reg()
658
659 case ssaop.OpAMD64CMOVQNEF, ssaop.OpAMD64CMOVLNEF, ssaop.OpAMD64CMOVWNEF:
660
661
662
663
664 p := s.Prog(v.Op.Asm())
665 p.From.Type = obj.TYPE_REG
666 p.From.Reg = v.Args[1].Reg()
667 p.To.Type = obj.TYPE_REG
668 p.To.Reg = v.Reg()
669 var q *obj.Prog
670 if v.Op == ssaop.OpAMD64CMOVQNEF {
671 q = s.Prog(x86.ACMOVQPS)
672 } else if v.Op == ssaop.OpAMD64CMOVLNEF {
673 q = s.Prog(x86.ACMOVLPS)
674 } else {
675 q = s.Prog(x86.ACMOVWPS)
676 }
677 q.From.Type = obj.TYPE_REG
678 q.From.Reg = v.Args[1].Reg()
679 q.To.Type = obj.TYPE_REG
680 q.To.Reg = v.Reg()
681
682 case ssaop.OpAMD64CMOVQEQF, ssaop.OpAMD64CMOVLEQF, ssaop.OpAMD64CMOVWEQF:
683
684
685
686
687
688
689
690
691
692
693
694 t := v.RegTmp()
695 opregreg(s, moveByRegsWidth(t, v.Args[1].Reg(), v.Type.Size(), hasAVX(v)), t, v.Args[1].Reg())
696
697 p := s.Prog(v.Op.Asm())
698 p.From.Type = obj.TYPE_REG
699 p.From.Reg = v.Reg()
700 p.To.Type = obj.TYPE_REG
701 p.To.Reg = t
702 var q *obj.Prog
703 if v.Op == ssaop.OpAMD64CMOVQEQF {
704 q = s.Prog(x86.ACMOVQPC)
705 } else if v.Op == ssaop.OpAMD64CMOVLEQF {
706 q = s.Prog(x86.ACMOVLPC)
707 } else {
708 q = s.Prog(x86.ACMOVWPC)
709 }
710 q.From.Type = obj.TYPE_REG
711 q.From.Reg = t
712 q.To.Type = obj.TYPE_REG
713 q.To.Reg = v.Reg()
714
715 case ssaop.OpAMD64MULQconst, ssaop.OpAMD64MULLconst:
716 r := v.Reg()
717 p := s.Prog(v.Op.Asm())
718 p.From.Type = obj.TYPE_CONST
719 p.From.Offset = v.AuxInt
720 p.To.Type = obj.TYPE_REG
721 p.To.Reg = r
722 p.AddRestSourceReg(v.Args[0].Reg())
723
724 case ssaop.OpAMD64ANDQconst:
725 asm := v.Op.Asm()
726
727
728 if 0 <= v.AuxInt && v.AuxInt <= (1<<32-1) {
729 asm = x86.AANDL
730 }
731 p := s.Prog(asm)
732 p.From.Type = obj.TYPE_CONST
733 p.From.Offset = v.AuxInt
734 p.To.Type = obj.TYPE_REG
735 p.To.Reg = v.Reg()
736
737 case ssaop.OpAMD64SUBQconst, ssaop.OpAMD64SUBLconst,
738 ssaop.OpAMD64ANDLconst,
739 ssaop.OpAMD64ORQconst, ssaop.OpAMD64ORLconst,
740 ssaop.OpAMD64XORQconst, ssaop.OpAMD64XORLconst:
741 p := s.Prog(v.Op.Asm())
742 p.From.Type = obj.TYPE_CONST
743 p.From.Offset = v.AuxInt
744 p.To.Type = obj.TYPE_REG
745 p.To.Reg = v.Reg()
746
747 case ssaop.OpAMD64SHLQconst, ssaop.OpAMD64SHLLconst,
748 ssaop.OpAMD64SHRQconst, ssaop.OpAMD64SHRLconst, ssaop.OpAMD64SHRWconst, ssaop.OpAMD64SHRBconst,
749 ssaop.OpAMD64SARQconst, ssaop.OpAMD64SARLconst, ssaop.OpAMD64SARWconst, ssaop.OpAMD64SARBconst,
750 ssaop.OpAMD64ROLQconst, ssaop.OpAMD64ROLLconst, ssaop.OpAMD64ROLWconst, ssaop.OpAMD64ROLBconst:
751 var maxShift int64
752 switch v.Op {
753 case ssaop.OpAMD64SHLQconst, ssaop.OpAMD64SHRQconst, ssaop.OpAMD64SARQconst, ssaop.OpAMD64ROLQconst:
754 maxShift = 63
755 case ssaop.OpAMD64SHLLconst, ssaop.OpAMD64SHRLconst, ssaop.OpAMD64SARLconst, ssaop.OpAMD64ROLLconst:
756 maxShift = 31
757 case ssaop.OpAMD64SHRWconst, ssaop.OpAMD64SARWconst, ssaop.OpAMD64ROLWconst:
758 maxShift = 15
759 case ssaop.OpAMD64SHRBconst, ssaop.OpAMD64SARBconst, ssaop.OpAMD64ROLBconst:
760 maxShift = 7
761 default:
762 panic("unreachable")
763 }
764 if v.AuxInt < 0 || v.AuxInt > maxShift {
765 v.Fatalf("shift amount out of range [0,%d]: %d", maxShift, v.AuxInt)
766 }
767 p := s.Prog(v.Op.Asm())
768 p.From.Type = obj.TYPE_CONST
769 p.From.Offset = v.AuxInt
770 p.To.Type = obj.TYPE_REG
771 p.To.Reg = v.Reg()
772 case ssaop.OpAMD64SBBQcarrymask, ssaop.OpAMD64SBBLcarrymask:
773 r := v.Reg()
774 p := s.Prog(v.Op.Asm())
775 p.From.Type = obj.TYPE_REG
776 p.From.Reg = r
777 p.To.Type = obj.TYPE_REG
778 p.To.Reg = r
779 case ssaop.OpAMD64LEAQ1, ssaop.OpAMD64LEAQ2, ssaop.OpAMD64LEAQ4, ssaop.OpAMD64LEAQ8,
780 ssaop.OpAMD64LEAL1, ssaop.OpAMD64LEAL2, ssaop.OpAMD64LEAL4, ssaop.OpAMD64LEAL8,
781 ssaop.OpAMD64LEAW1, ssaop.OpAMD64LEAW2, ssaop.OpAMD64LEAW4, ssaop.OpAMD64LEAW8:
782 p := s.Prog(v.Op.Asm())
783 memIdx(&p.From, v)
784 ssagen.AddAux(&p.From, v)
785 p.To.Type = obj.TYPE_REG
786 p.To.Reg = v.Reg()
787 case ssaop.OpAMD64LEAQ, ssaop.OpAMD64LEAL, ssaop.OpAMD64LEAW:
788 p := s.Prog(v.Op.Asm())
789 p.From.Type = obj.TYPE_MEM
790 p.From.Reg = v.Args[0].Reg()
791 ssagen.AddAux(&p.From, v)
792 p.To.Type = obj.TYPE_REG
793 p.To.Reg = v.Reg()
794 case ssaop.OpAMD64CMPQ, ssaop.OpAMD64CMPL, ssaop.OpAMD64CMPW, ssaop.OpAMD64CMPB,
795 ssaop.OpAMD64TESTQ, ssaop.OpAMD64TESTL, ssaop.OpAMD64TESTW, ssaop.OpAMD64TESTB,
796 ssaop.OpAMD64BTL, ssaop.OpAMD64BTQ:
797 opregreg(s, v.Op.Asm(), v.Args[1].Reg(), v.Args[0].Reg())
798 case ssaop.OpAMD64UCOMISS, ssaop.OpAMD64UCOMISD:
799
800
801 opregreg(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg())
802 case ssaop.OpAMD64CMPQconst, ssaop.OpAMD64CMPLconst, ssaop.OpAMD64CMPWconst, ssaop.OpAMD64CMPBconst:
803 p := s.Prog(v.Op.Asm())
804 p.From.Type = obj.TYPE_REG
805 p.From.Reg = v.Args[0].Reg()
806 p.To.Type = obj.TYPE_CONST
807 p.To.Offset = v.AuxInt
808 case ssaop.OpAMD64BTLconst, ssaop.OpAMD64BTQconst,
809 ssaop.OpAMD64TESTQconst, ssaop.OpAMD64TESTLconst, ssaop.OpAMD64TESTWconst, ssaop.OpAMD64TESTBconst,
810 ssaop.OpAMD64BTSQconst,
811 ssaop.OpAMD64BTCQconst,
812 ssaop.OpAMD64BTRQconst:
813 op := v.Op
814 if op == ssaop.OpAMD64BTQconst && v.AuxInt < 32 {
815
816 op = ssaop.OpAMD64BTLconst
817 }
818 p := s.Prog(op.Asm())
819 p.From.Type = obj.TYPE_CONST
820 p.From.Offset = v.AuxInt
821 p.To.Type = obj.TYPE_REG
822 p.To.Reg = v.Args[0].Reg()
823 case ssaop.OpAMD64CMPQload, ssaop.OpAMD64CMPLload, ssaop.OpAMD64CMPWload, ssaop.OpAMD64CMPBload:
824 p := s.Prog(v.Op.Asm())
825 p.From.Type = obj.TYPE_MEM
826 p.From.Reg = v.Args[0].Reg()
827 ssagen.AddAux(&p.From, v)
828 p.To.Type = obj.TYPE_REG
829 p.To.Reg = v.Args[1].Reg()
830 case ssaop.OpAMD64CMPQconstload, ssaop.OpAMD64CMPLconstload, ssaop.OpAMD64CMPWconstload, ssaop.OpAMD64CMPBconstload:
831 sc := v.AuxValAndOff()
832 p := s.Prog(v.Op.Asm())
833 p.From.Type = obj.TYPE_MEM
834 p.From.Reg = v.Args[0].Reg()
835 ssagen.AddAux2(&p.From, v, sc.Off64())
836 p.To.Type = obj.TYPE_CONST
837 p.To.Offset = sc.Val64()
838 case ssaop.OpAMD64CMPQloadidx8, ssaop.OpAMD64CMPQloadidx1, ssaop.OpAMD64CMPLloadidx4, ssaop.OpAMD64CMPLloadidx1, ssaop.OpAMD64CMPWloadidx2, ssaop.OpAMD64CMPWloadidx1, ssaop.OpAMD64CMPBloadidx1:
839 p := s.Prog(v.Op.Asm())
840 memIdx(&p.From, v)
841 ssagen.AddAux(&p.From, v)
842 p.To.Type = obj.TYPE_REG
843 p.To.Reg = v.Args[2].Reg()
844 case ssaop.OpAMD64CMPQconstloadidx8, ssaop.OpAMD64CMPQconstloadidx1, ssaop.OpAMD64CMPLconstloadidx4, ssaop.OpAMD64CMPLconstloadidx1, ssaop.OpAMD64CMPWconstloadidx2, ssaop.OpAMD64CMPWconstloadidx1, ssaop.OpAMD64CMPBconstloadidx1:
845 sc := v.AuxValAndOff()
846 p := s.Prog(v.Op.Asm())
847 memIdx(&p.From, v)
848 ssagen.AddAux2(&p.From, v, sc.Off64())
849 p.To.Type = obj.TYPE_CONST
850 p.To.Offset = sc.Val64()
851 case ssaop.OpAMD64MOVLconst, ssaop.OpAMD64MOVQconst:
852 x := v.Reg()
853
854
855
856 if v.AuxInt == 0 && v.Aux == nil {
857 opregreg(s, x86.AXORL, x, x)
858 break
859 }
860
861 asm := v.Op.Asm()
862
863
864 if 0 <= v.AuxInt && v.AuxInt <= (1<<32-1) {
865
866 asm = x86.AMOVL
867 }
868 p := s.Prog(asm)
869 p.From.Type = obj.TYPE_CONST
870 p.From.Offset = v.AuxInt
871 p.To.Type = obj.TYPE_REG
872 p.To.Reg = x
873
874 case ssaop.OpAMD64MOVSSconst, ssaop.OpAMD64MOVSDconst:
875 x := v.Reg()
876 if !isFPReg(x) && v.AuxInt == 0 && v.Aux == nil {
877 opregreg(s, x86.AXORL, x, x)
878 break
879 }
880 p := s.Prog(storeByRegWidth(x, v.Type.Size(), hasAVX(v)))
881 p.From.Type = obj.TYPE_FCONST
882 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
883 p.To.Type = obj.TYPE_REG
884 p.To.Reg = x
885 case ssaop.OpAMD64MOVOload:
886 asm := v.Op.Asm()
887 if hasAVX(v) {
888 asm = x86.AVMOVUPS
889 }
890 p := s.Prog(asm)
891 p.From.Type = obj.TYPE_MEM
892 p.From.Reg = v.Args[0].Reg()
893 ssagen.AddAux(&p.From, v)
894 p.To.Type = obj.TYPE_REG
895 p.To.Reg = v.Reg()
896 case ssaop.OpAMD64MOVQload, ssaop.OpAMD64MOVLload, ssaop.OpAMD64MOVWload, ssaop.OpAMD64MOVBload,
897 ssaop.OpAMD64MOVSSload, ssaop.OpAMD64MOVSDload, ssaop.OpAMD64MOVBQSXload, ssaop.OpAMD64MOVWQSXload, ssaop.OpAMD64MOVLQSXload,
898 ssaop.OpAMD64MOVBEQload, ssaop.OpAMD64MOVBELload:
899 p := s.Prog(v.Op.Asm())
900 p.From.Type = obj.TYPE_MEM
901 p.From.Reg = v.Args[0].Reg()
902 ssagen.AddAux(&p.From, v)
903 p.To.Type = obj.TYPE_REG
904 p.To.Reg = v.Reg()
905 case ssaop.OpAMD64MOVBloadidx1, ssaop.OpAMD64MOVWloadidx1, ssaop.OpAMD64MOVLloadidx1, ssaop.OpAMD64MOVQloadidx1, ssaop.OpAMD64MOVSSloadidx1, ssaop.OpAMD64MOVSDloadidx1,
906 ssaop.OpAMD64MOVQloadidx8, ssaop.OpAMD64MOVSDloadidx8, ssaop.OpAMD64MOVLloadidx8, ssaop.OpAMD64MOVLloadidx4, ssaop.OpAMD64MOVSSloadidx4, ssaop.OpAMD64MOVWloadidx2,
907 ssaop.OpAMD64MOVBELloadidx1, ssaop.OpAMD64MOVBELloadidx4, ssaop.OpAMD64MOVBELloadidx8, ssaop.OpAMD64MOVBEQloadidx1, ssaop.OpAMD64MOVBEQloadidx8:
908 p := s.Prog(v.Op.Asm())
909 memIdx(&p.From, v)
910 ssagen.AddAux(&p.From, v)
911 p.To.Type = obj.TYPE_REG
912 p.To.Reg = v.Reg()
913 case ssaop.OpAMD64MOVOstore:
914 asm := v.Op.Asm()
915 if hasAVX(v) {
916 asm = x86.AVMOVUPS
917 }
918 p := s.Prog(asm)
919 p.From.Type = obj.TYPE_REG
920 p.From.Reg = v.Args[1].Reg()
921 p.To.Type = obj.TYPE_MEM
922 p.To.Reg = v.Args[0].Reg()
923 ssagen.AddAux(&p.To, v)
924 case ssaop.OpAMD64MOVQstore, ssaop.OpAMD64MOVSSstore, ssaop.OpAMD64MOVSDstore, ssaop.OpAMD64MOVLstore, ssaop.OpAMD64MOVWstore, ssaop.OpAMD64MOVBstore,
925 ssaop.OpAMD64ADDQmodify, ssaop.OpAMD64SUBQmodify, ssaop.OpAMD64ANDQmodify, ssaop.OpAMD64ORQmodify, ssaop.OpAMD64XORQmodify,
926 ssaop.OpAMD64ADDLmodify, ssaop.OpAMD64SUBLmodify, ssaop.OpAMD64ANDLmodify, ssaop.OpAMD64ORLmodify, ssaop.OpAMD64XORLmodify,
927 ssaop.OpAMD64MOVBEQstore, ssaop.OpAMD64MOVBELstore, ssaop.OpAMD64MOVBEWstore:
928 p := s.Prog(v.Op.Asm())
929 p.From.Type = obj.TYPE_REG
930 p.From.Reg = v.Args[1].Reg()
931 p.To.Type = obj.TYPE_MEM
932 p.To.Reg = v.Args[0].Reg()
933 ssagen.AddAux(&p.To, v)
934 case ssaop.OpAMD64MOVBstoreidx1, ssaop.OpAMD64MOVWstoreidx1, ssaop.OpAMD64MOVLstoreidx1, ssaop.OpAMD64MOVQstoreidx1, ssaop.OpAMD64MOVSSstoreidx1, ssaop.OpAMD64MOVSDstoreidx1,
935 ssaop.OpAMD64MOVQstoreidx8, ssaop.OpAMD64MOVSDstoreidx8, ssaop.OpAMD64MOVLstoreidx8, ssaop.OpAMD64MOVSSstoreidx4, ssaop.OpAMD64MOVLstoreidx4, ssaop.OpAMD64MOVWstoreidx2,
936 ssaop.OpAMD64ADDLmodifyidx1, ssaop.OpAMD64ADDLmodifyidx4, ssaop.OpAMD64ADDLmodifyidx8, ssaop.OpAMD64ADDQmodifyidx1, ssaop.OpAMD64ADDQmodifyidx8,
937 ssaop.OpAMD64SUBLmodifyidx1, ssaop.OpAMD64SUBLmodifyidx4, ssaop.OpAMD64SUBLmodifyidx8, ssaop.OpAMD64SUBQmodifyidx1, ssaop.OpAMD64SUBQmodifyidx8,
938 ssaop.OpAMD64ANDLmodifyidx1, ssaop.OpAMD64ANDLmodifyidx4, ssaop.OpAMD64ANDLmodifyidx8, ssaop.OpAMD64ANDQmodifyidx1, ssaop.OpAMD64ANDQmodifyidx8,
939 ssaop.OpAMD64ORLmodifyidx1, ssaop.OpAMD64ORLmodifyidx4, ssaop.OpAMD64ORLmodifyidx8, ssaop.OpAMD64ORQmodifyidx1, ssaop.OpAMD64ORQmodifyidx8,
940 ssaop.OpAMD64XORLmodifyidx1, ssaop.OpAMD64XORLmodifyidx4, ssaop.OpAMD64XORLmodifyidx8, ssaop.OpAMD64XORQmodifyidx1, ssaop.OpAMD64XORQmodifyidx8,
941 ssaop.OpAMD64MOVBEWstoreidx1, ssaop.OpAMD64MOVBEWstoreidx2, ssaop.OpAMD64MOVBELstoreidx1, ssaop.OpAMD64MOVBELstoreidx4, ssaop.OpAMD64MOVBELstoreidx8, ssaop.OpAMD64MOVBEQstoreidx1, ssaop.OpAMD64MOVBEQstoreidx8:
942 p := s.Prog(v.Op.Asm())
943 p.From.Type = obj.TYPE_REG
944 p.From.Reg = v.Args[2].Reg()
945 memIdx(&p.To, v)
946 ssagen.AddAux(&p.To, v)
947 case ssaop.OpAMD64ADDQconstmodify, ssaop.OpAMD64ADDLconstmodify,
948 ssaop.OpAMD64ADDWconstmodify, ssaop.OpAMD64ADDBconstmodify:
949 sc := v.AuxValAndOff()
950 off := sc.Off64()
951 val := sc.Val()
952 if val == 1 || val == -1 {
953 var asm obj.As
954 switch v.Op {
955 case ssaop.OpAMD64ADDQconstmodify:
956 asm = x86.AINCQ
957 if val == -1 {
958 asm = x86.ADECQ
959 }
960 case ssaop.OpAMD64ADDLconstmodify:
961 asm = x86.AINCL
962 if val == -1 {
963 asm = x86.ADECL
964 }
965 case ssaop.OpAMD64ADDWconstmodify:
966 asm = x86.AINCW
967 if val == -1 {
968 asm = x86.ADECW
969 }
970 default:
971 asm = x86.AINCB
972 if val == -1 {
973 asm = x86.ADECB
974 }
975 }
976 p := s.Prog(asm)
977 p.To.Type = obj.TYPE_MEM
978 p.To.Reg = v.Args[0].Reg()
979 ssagen.AddAux2(&p.To, v, off)
980 break
981 }
982 fallthrough
983 case ssaop.OpAMD64ANDQconstmodify, ssaop.OpAMD64ANDLconstmodify, ssaop.OpAMD64ORQconstmodify, ssaop.OpAMD64ORLconstmodify,
984 ssaop.OpAMD64XORQconstmodify, ssaop.OpAMD64XORLconstmodify,
985 ssaop.OpAMD64ANDWconstmodify, ssaop.OpAMD64ANDBconstmodify, ssaop.OpAMD64ORWconstmodify, ssaop.OpAMD64ORBconstmodify,
986 ssaop.OpAMD64XORWconstmodify, ssaop.OpAMD64XORBconstmodify,
987 ssaop.OpAMD64BTSQconstmodify, ssaop.OpAMD64BTRQconstmodify, ssaop.OpAMD64BTCQconstmodify:
988 sc := v.AuxValAndOff()
989 off := sc.Off64()
990 val := sc.Val64()
991 p := s.Prog(v.Op.Asm())
992 p.From.Type = obj.TYPE_CONST
993 p.From.Offset = val
994 p.To.Type = obj.TYPE_MEM
995 p.To.Reg = v.Args[0].Reg()
996 ssagen.AddAux2(&p.To, v, off)
997
998 case ssaop.OpAMD64MOVQstoreconst, ssaop.OpAMD64MOVLstoreconst, ssaop.OpAMD64MOVWstoreconst, ssaop.OpAMD64MOVBstoreconst:
999 sc := v.AuxValAndOff()
1000 p := s.Prog(v.Op.Asm())
1001 if sc.Val() == 0 && s.ABI == obj.ABIInternal && buildcfg.GOOS != "plan9" && (v.Op == ssaop.OpAMD64MOVQstoreconst || v.Op == ssaop.OpAMD64MOVLstoreconst) {
1002 p.From.Type = obj.TYPE_REG
1003 p.From.Reg = x86.REG_X15
1004 } else {
1005 p.From.Type = obj.TYPE_CONST
1006 p.From.Offset = sc.Val64()
1007 }
1008 p.To.Type = obj.TYPE_MEM
1009 p.To.Reg = v.Args[0].Reg()
1010 ssagen.AddAux2(&p.To, v, sc.Off64())
1011 case ssaop.OpAMD64MOVOstoreconst:
1012 sc := v.AuxValAndOff()
1013 if sc.Val() != 0 {
1014 v.Fatalf("MOVO for non zero constants not implemented: %s", v.LongString())
1015 }
1016
1017 avx := hasAVX(v)
1018 if s.ABI != obj.ABIInternal {
1019
1020 zeroX15Low(s, avx)
1021 }
1022 asm := v.Op.Asm()
1023 if avx {
1024 asm = x86.AVMOVUPS
1025 }
1026 p := s.Prog(asm)
1027 p.From.Type = obj.TYPE_REG
1028 p.From.Reg = x86.REG_X15
1029 p.To.Type = obj.TYPE_MEM
1030 p.To.Reg = v.Args[0].Reg()
1031 ssagen.AddAux2(&p.To, v, sc.Off64())
1032
1033 case ssaop.OpAMD64MOVQstoreconstidx1, ssaop.OpAMD64MOVQstoreconstidx8, ssaop.OpAMD64MOVLstoreconstidx1, ssaop.OpAMD64MOVLstoreconstidx4, ssaop.OpAMD64MOVWstoreconstidx1, ssaop.OpAMD64MOVWstoreconstidx2, ssaop.OpAMD64MOVBstoreconstidx1,
1034 ssaop.OpAMD64ADDLconstmodifyidx1, ssaop.OpAMD64ADDLconstmodifyidx4, ssaop.OpAMD64ADDLconstmodifyidx8, ssaop.OpAMD64ADDQconstmodifyidx1, ssaop.OpAMD64ADDQconstmodifyidx8,
1035 ssaop.OpAMD64ANDLconstmodifyidx1, ssaop.OpAMD64ANDLconstmodifyidx4, ssaop.OpAMD64ANDLconstmodifyidx8, ssaop.OpAMD64ANDQconstmodifyidx1, ssaop.OpAMD64ANDQconstmodifyidx8,
1036 ssaop.OpAMD64ORLconstmodifyidx1, ssaop.OpAMD64ORLconstmodifyidx4, ssaop.OpAMD64ORLconstmodifyidx8, ssaop.OpAMD64ORQconstmodifyidx1, ssaop.OpAMD64ORQconstmodifyidx8,
1037 ssaop.OpAMD64XORLconstmodifyidx1, ssaop.OpAMD64XORLconstmodifyidx4, ssaop.OpAMD64XORLconstmodifyidx8, ssaop.OpAMD64XORQconstmodifyidx1, ssaop.OpAMD64XORQconstmodifyidx8,
1038 ssaop.OpAMD64ADDWconstmodifyidx1, ssaop.OpAMD64ADDWconstmodifyidx2, ssaop.OpAMD64ADDBconstmodifyidx1,
1039 ssaop.OpAMD64ANDWconstmodifyidx1, ssaop.OpAMD64ANDWconstmodifyidx2, ssaop.OpAMD64ANDBconstmodifyidx1,
1040 ssaop.OpAMD64ORWconstmodifyidx1, ssaop.OpAMD64ORWconstmodifyidx2, ssaop.OpAMD64ORBconstmodifyidx1,
1041 ssaop.OpAMD64XORWconstmodifyidx1, ssaop.OpAMD64XORWconstmodifyidx2, ssaop.OpAMD64XORBconstmodifyidx1:
1042 p := s.Prog(v.Op.Asm())
1043 p.From.Type = obj.TYPE_CONST
1044 sc := v.AuxValAndOff()
1045 p.From.Offset = sc.Val64()
1046 if sc.Val() == 0 && s.ABI == obj.ABIInternal && buildcfg.GOOS != "plan9" {
1047 switch v.Op {
1048 case ssaop.OpAMD64MOVQstoreconstidx1, ssaop.OpAMD64MOVQstoreconstidx8,
1049 ssaop.OpAMD64MOVLstoreconstidx1, ssaop.OpAMD64MOVLstoreconstidx4:
1050 p.From.Type = obj.TYPE_REG
1051 p.From.Reg = x86.REG_X15
1052 }
1053 }
1054 switch {
1055 case p.As == x86.AADDQ && p.From.Offset == 1:
1056 p.As = x86.AINCQ
1057 p.From.Type = obj.TYPE_NONE
1058 case p.As == x86.AADDQ && p.From.Offset == -1:
1059 p.As = x86.ADECQ
1060 p.From.Type = obj.TYPE_NONE
1061 case p.As == x86.AADDL && p.From.Offset == 1:
1062 p.As = x86.AINCL
1063 p.From.Type = obj.TYPE_NONE
1064 case p.As == x86.AADDL && p.From.Offset == -1:
1065 p.As = x86.ADECL
1066 p.From.Type = obj.TYPE_NONE
1067 case p.As == x86.AADDW && p.From.Offset == 1:
1068 p.As = x86.AINCW
1069 p.From.Type = obj.TYPE_NONE
1070 case p.As == x86.AADDW && p.From.Offset == -1:
1071 p.As = x86.ADECW
1072 p.From.Type = obj.TYPE_NONE
1073 case p.As == x86.AADDB && p.From.Offset == 1:
1074 p.As = x86.AINCB
1075 p.From.Type = obj.TYPE_NONE
1076 case p.As == x86.AADDB && p.From.Offset == -1:
1077 p.As = x86.ADECB
1078 p.From.Type = obj.TYPE_NONE
1079 }
1080 memIdx(&p.To, v)
1081 ssagen.AddAux2(&p.To, v, sc.Off64())
1082 case ssaop.OpAMD64MOVLQSX, ssaop.OpAMD64MOVWQSX, ssaop.OpAMD64MOVBQSX, ssaop.OpAMD64MOVLQZX, ssaop.OpAMD64MOVWQZX, ssaop.OpAMD64MOVBQZX,
1083 ssaop.OpAMD64CVTTSS2SL, ssaop.OpAMD64CVTTSD2SL, ssaop.OpAMD64CVTTSS2SQ, ssaop.OpAMD64CVTTSD2SQ,
1084 ssaop.OpAMD64CVTSS2SD, ssaop.OpAMD64CVTSD2SS, ssaop.OpAMD64VPBROADCASTB, ssaop.OpAMD64PMOVMSKB:
1085 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg())
1086 case ssaop.OpAMD64CVTSL2SD, ssaop.OpAMD64CVTSQ2SD, ssaop.OpAMD64CVTSQ2SS, ssaop.OpAMD64CVTSL2SS:
1087 r := v.Reg()
1088
1089 opregreg(s, x86.AXORPS, r, r)
1090 opregreg(s, v.Op.Asm(), r, v.Args[0].Reg())
1091 case ssaop.OpAMD64MOVQi2f, ssaop.OpAMD64MOVQf2i, ssaop.OpAMD64MOVLi2f, ssaop.OpAMD64MOVLf2i:
1092 avx := hasAVX(v)
1093 var p *obj.Prog
1094 switch v.Op {
1095 case ssaop.OpAMD64MOVQi2f, ssaop.OpAMD64MOVQf2i:
1096 if avx {
1097 p = s.Prog(x86.AVMOVQ)
1098 } else {
1099 p = s.Prog(x86.AMOVQ)
1100 }
1101 case ssaop.OpAMD64MOVLi2f, ssaop.OpAMD64MOVLf2i:
1102 if avx {
1103 p = s.Prog(x86.AVMOVD)
1104 } else {
1105 p = s.Prog(x86.AMOVL)
1106 }
1107 }
1108 p.From.Type = obj.TYPE_REG
1109 p.From.Reg = v.Args[0].Reg()
1110 p.To.Type = obj.TYPE_REG
1111 p.To.Reg = v.Reg()
1112 case ssaop.OpAMD64ADDQload, ssaop.OpAMD64ADDLload, ssaop.OpAMD64SUBQload, ssaop.OpAMD64SUBLload,
1113 ssaop.OpAMD64ANDQload, ssaop.OpAMD64ANDLload, ssaop.OpAMD64ORQload, ssaop.OpAMD64ORLload,
1114 ssaop.OpAMD64XORQload, ssaop.OpAMD64XORLload, ssaop.OpAMD64ADDSDload, ssaop.OpAMD64ADDSSload,
1115 ssaop.OpAMD64SUBSDload, ssaop.OpAMD64SUBSSload, ssaop.OpAMD64MULSDload, ssaop.OpAMD64MULSSload,
1116 ssaop.OpAMD64DIVSDload, ssaop.OpAMD64DIVSSload:
1117 p := s.Prog(v.Op.Asm())
1118 p.From.Type = obj.TYPE_MEM
1119 p.From.Reg = v.Args[1].Reg()
1120 ssagen.AddAux(&p.From, v)
1121 p.To.Type = obj.TYPE_REG
1122 p.To.Reg = v.Reg()
1123 case ssaop.OpAMD64ADDLloadidx1, ssaop.OpAMD64ADDLloadidx4, ssaop.OpAMD64ADDLloadidx8, ssaop.OpAMD64ADDQloadidx1, ssaop.OpAMD64ADDQloadidx8,
1124 ssaop.OpAMD64SUBLloadidx1, ssaop.OpAMD64SUBLloadidx4, ssaop.OpAMD64SUBLloadidx8, ssaop.OpAMD64SUBQloadidx1, ssaop.OpAMD64SUBQloadidx8,
1125 ssaop.OpAMD64ANDLloadidx1, ssaop.OpAMD64ANDLloadidx4, ssaop.OpAMD64ANDLloadidx8, ssaop.OpAMD64ANDQloadidx1, ssaop.OpAMD64ANDQloadidx8,
1126 ssaop.OpAMD64ORLloadidx1, ssaop.OpAMD64ORLloadidx4, ssaop.OpAMD64ORLloadidx8, ssaop.OpAMD64ORQloadidx1, ssaop.OpAMD64ORQloadidx8,
1127 ssaop.OpAMD64XORLloadidx1, ssaop.OpAMD64XORLloadidx4, ssaop.OpAMD64XORLloadidx8, ssaop.OpAMD64XORQloadidx1, ssaop.OpAMD64XORQloadidx8,
1128 ssaop.OpAMD64ADDSSloadidx1, ssaop.OpAMD64ADDSSloadidx4, ssaop.OpAMD64ADDSDloadidx1, ssaop.OpAMD64ADDSDloadidx8,
1129 ssaop.OpAMD64SUBSSloadidx1, ssaop.OpAMD64SUBSSloadidx4, ssaop.OpAMD64SUBSDloadidx1, ssaop.OpAMD64SUBSDloadidx8,
1130 ssaop.OpAMD64MULSSloadidx1, ssaop.OpAMD64MULSSloadidx4, ssaop.OpAMD64MULSDloadidx1, ssaop.OpAMD64MULSDloadidx8,
1131 ssaop.OpAMD64DIVSSloadidx1, ssaop.OpAMD64DIVSSloadidx4, ssaop.OpAMD64DIVSDloadidx1, ssaop.OpAMD64DIVSDloadidx8:
1132 p := s.Prog(v.Op.Asm())
1133
1134 r, i := v.Args[1].Reg(), v.Args[2].Reg()
1135 p.From.Type = obj.TYPE_MEM
1136 p.From.Scale = v.Op.Scale()
1137 if p.From.Scale == 1 && i == x86.REG_SP {
1138 r, i = i, r
1139 }
1140 p.From.Reg = r
1141 p.From.Index = i
1142
1143 ssagen.AddAux(&p.From, v)
1144 p.To.Type = obj.TYPE_REG
1145 p.To.Reg = v.Reg()
1146
1147 case ssaop.OpAMD64LoweredZero:
1148 avx := hasAVX(v)
1149 if s.ABI != obj.ABIInternal {
1150
1151 zeroX15Low(s, avx)
1152 }
1153 ptrReg := v.Args[0].Reg()
1154 n := v.AuxInt
1155 if n < 16 {
1156 v.Fatalf("Zero too small %d", n)
1157 }
1158 zero16 := func(off int64) {
1159 zero16(s, ptrReg, off, avx)
1160 }
1161
1162
1163 var off int64
1164 for n >= 16 {
1165 zero16(off)
1166 off += 16
1167 n -= 16
1168 }
1169 if n != 0 {
1170
1171
1172 zero16(off + n - 16)
1173 }
1174
1175 case ssaop.OpAMD64LoweredZeroLoop:
1176 avx := hasAVX(v)
1177 if s.ABI != obj.ABIInternal {
1178
1179 zeroX15Low(s, avx)
1180 }
1181 ptrReg := v.Args[0].Reg()
1182 countReg := v.RegTmp()
1183 n := v.AuxInt
1184 loopSize := int64(64)
1185 if n < 3*loopSize {
1186
1187
1188
1189
1190
1191
1192
1193
1194 v.Fatalf("ZeroLoop size too small %d", n)
1195 }
1196 zero16 := func(off int64) {
1197 zero16(s, ptrReg, off, avx)
1198 }
1199
1200
1201
1202 p := s.Prog(x86.AMOVL)
1203 p.From.Type = obj.TYPE_CONST
1204 p.From.Offset = n / loopSize
1205 p.To.Type = obj.TYPE_REG
1206 p.To.Reg = countReg
1207 cntInit := p
1208
1209
1210 for i := range loopSize / 16 {
1211 zero16(i * 16)
1212 }
1213
1214 p = s.Prog(x86.AADDQ)
1215 p.From.Type = obj.TYPE_CONST
1216 p.From.Offset = loopSize
1217 p.To.Type = obj.TYPE_REG
1218 p.To.Reg = ptrReg
1219
1220 p = s.Prog(x86.ADECL)
1221 p.To.Type = obj.TYPE_REG
1222 p.To.Reg = countReg
1223
1224
1225 p = s.Prog(x86.AJNE)
1226 p.To.Type = obj.TYPE_BRANCH
1227 p.To.SetTarget(cntInit.Link)
1228
1229
1230 n %= loopSize
1231
1232
1233 var off int64
1234 for n >= 16 {
1235 zero16(off)
1236 off += 16
1237 n -= 16
1238 }
1239 if n != 0 {
1240
1241
1242 zero16(off + n - 16)
1243 }
1244
1245 case ssaop.OpAMD64LoweredMove:
1246 dstReg := v.Args[0].Reg()
1247 srcReg := v.Args[1].Reg()
1248 if dstReg == srcReg {
1249 break
1250 }
1251 tmpReg := int16(x86.REG_X14)
1252 n := v.AuxInt
1253 if n < 16 {
1254 v.Fatalf("Move too small %d", n)
1255 }
1256 avx := hasAVX(v)
1257
1258 move16 := func(off int64) {
1259 move16(s, srcReg, dstReg, tmpReg, off, avx)
1260 }
1261
1262
1263 var off int64
1264 for n >= 16 {
1265 move16(off)
1266 off += 16
1267 n -= 16
1268 }
1269 if n != 0 {
1270
1271
1272 move16(off + n - 16)
1273 }
1274
1275 case ssaop.OpAMD64LoweredMoveLoop:
1276 dstReg := v.Args[0].Reg()
1277 srcReg := v.Args[1].Reg()
1278 if dstReg == srcReg {
1279 break
1280 }
1281 countReg := v.RegTmp()
1282 tmpReg := int16(x86.REG_X14)
1283 n := v.AuxInt
1284 loopSize := int64(64)
1285 if n < 3*loopSize {
1286
1287
1288
1289
1290
1291
1292
1293
1294 v.Fatalf("ZeroLoop size too small %d", n)
1295 }
1296 avx := hasAVX(v)
1297
1298 move16 := func(off int64) {
1299 move16(s, srcReg, dstReg, tmpReg, off, avx)
1300 }
1301
1302
1303
1304 p := s.Prog(x86.AMOVL)
1305 p.From.Type = obj.TYPE_CONST
1306 p.From.Offset = n / loopSize
1307 p.To.Type = obj.TYPE_REG
1308 p.To.Reg = countReg
1309 cntInit := p
1310
1311
1312 for i := range loopSize / 16 {
1313 move16(i * 16)
1314 }
1315
1316 p = s.Prog(x86.AADDQ)
1317 p.From.Type = obj.TYPE_CONST
1318 p.From.Offset = loopSize
1319 p.To.Type = obj.TYPE_REG
1320 p.To.Reg = srcReg
1321
1322 p = s.Prog(x86.AADDQ)
1323 p.From.Type = obj.TYPE_CONST
1324 p.From.Offset = loopSize
1325 p.To.Type = obj.TYPE_REG
1326 p.To.Reg = dstReg
1327
1328 p = s.Prog(x86.ADECL)
1329 p.To.Type = obj.TYPE_REG
1330 p.To.Reg = countReg
1331
1332
1333 p = s.Prog(x86.AJNE)
1334 p.To.Type = obj.TYPE_BRANCH
1335 p.To.SetTarget(cntInit.Link)
1336
1337
1338 n %= loopSize
1339
1340
1341 var off int64
1342 for n >= 16 {
1343 move16(off)
1344 off += 16
1345 n -= 16
1346 }
1347 if n != 0 {
1348
1349 move16(off + n - 16)
1350 }
1351
1352 case ssaop.OpCopy:
1353 if v.Type.IsMemory() {
1354 return
1355 }
1356 arg := v.Args[0]
1357 x := arg.Reg()
1358 y := v.Reg()
1359 if v.Type.IsSIMD() {
1360 x = simdOrMaskReg(arg)
1361 y = simdOrMaskReg(v)
1362 }
1363 if x != y {
1364 width := v.Type.Size()
1365 if width == 8 && isGPReg(y) && ssa.ZeroUpper32Bits(arg) {
1366
1367
1368
1369
1370 width = 4
1371 }
1372 opregreg(s, moveByRegsWidth(y, x, width, hasAVX(v)), y, x)
1373 }
1374 case ssaop.OpLoadReg:
1375 if v.Type.IsFlags() {
1376 v.Fatalf("load flags not implemented: %v", v.LongString())
1377 return
1378 }
1379 r := v.Reg()
1380 p := s.Prog(loadByRegWidth(r, v.Type.Size(), hasAVX(v)))
1381 ssagen.AddrAuto(&p.From, v.Args[0])
1382 p.To.Type = obj.TYPE_REG
1383 if v.Type.IsSIMD() {
1384 r = simdOrMaskReg(v)
1385 }
1386 p.To.Reg = r
1387
1388 case ssaop.OpStoreReg:
1389 if v.Type.IsFlags() {
1390 v.Fatalf("store flags not implemented: %v", v.LongString())
1391 return
1392 }
1393 r := v.Args[0].Reg()
1394 if v.Type.IsSIMD() {
1395 r = simdOrMaskReg(v.Args[0])
1396 }
1397 p := s.Prog(storeByRegWidth(r, v.Type.Size(), hasAVX(v)))
1398 p.From.Type = obj.TYPE_REG
1399 p.From.Reg = r
1400 ssagen.AddrAuto(&p.To, v)
1401 case ssaop.OpAMD64LoweredHasCPUFeature:
1402
1403 p := s.Prog(x86.AMOVBLZX)
1404 p.From.Type = obj.TYPE_MEM
1405 ssagen.AddAux(&p.From, v)
1406 p.To.Type = obj.TYPE_REG
1407 p.To.Reg = v.Reg()
1408 case ssaop.OpArgIntReg, ssaop.OpArgFloatReg:
1409
1410
1411 for _, ap := range v.Block.Func.RegArgs {
1412
1413 addr := ssagen.SpillSlotAddr(ap, x86.REG_SP, v.Block.Func.Config.PtrSize)
1414 reg := ap.Reg
1415 t := ap.Type
1416 sz := t.Size()
1417 if t.IsSIMD() {
1418 reg = simdRegBySize(reg, sz)
1419 }
1420
1421
1422 avx := v.Block.Func.Entry.CPUfeatures.HasFeature(ssa.CPUavx)
1423 s.FuncInfo().AddSpill(
1424 obj.RegSpill{Reg: reg, Addr: addr, Unspill: loadByRegWidth(reg, sz, avx), Spill: storeByRegWidth(reg, sz, avx)})
1425 }
1426 v.Block.Func.RegArgs = nil
1427 ssagen.CheckArgReg(v)
1428 case ssaop.OpAMD64LoweredGetClosurePtr:
1429
1430 ssagen.CheckLoweredGetClosurePtr(v)
1431 case ssaop.OpAMD64LoweredGetG:
1432 if s.ABI == obj.ABIInternal {
1433 v.Fatalf("LoweredGetG should not appear in ABIInternal")
1434 }
1435 r := v.Reg()
1436 getgFromTLS(s, r)
1437 case ssaop.OpAMD64CALLstatic, ssaop.OpAMD64CALLtail, ssaop.OpAMD64CALLtailinter:
1438 if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
1439
1440 zeroX15(s)
1441
1442 getgFromTLS(s, x86.REG_R14)
1443 }
1444 if v.Op == ssaop.OpAMD64CALLtail || v.Op == ssaop.OpAMD64CALLtailinter {
1445 s.TailCall(v)
1446 break
1447 }
1448 s.Call(v)
1449 if s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 {
1450
1451 zeroX15(s)
1452
1453 getgFromTLS(s, x86.REG_R14)
1454 }
1455 case ssaop.OpAMD64CALLclosure, ssaop.OpAMD64CALLinter:
1456 s.Call(v)
1457
1458 case ssaop.OpAMD64LoweredGetCallerPC:
1459 p := s.Prog(x86.AMOVQ)
1460 p.From.Type = obj.TYPE_MEM
1461 p.From.Offset = -8
1462 p.From.Name = obj.NAME_PARAM
1463 p.To.Type = obj.TYPE_REG
1464 p.To.Reg = v.Reg()
1465
1466 case ssaop.OpAMD64LoweredGetCallerSP:
1467
1468 mov := x86.AMOVQ
1469 if types.PtrSize == 4 {
1470 mov = x86.AMOVL
1471 }
1472 p := s.Prog(mov)
1473 p.From.Type = obj.TYPE_ADDR
1474 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
1475 p.From.Name = obj.NAME_PARAM
1476 p.To.Type = obj.TYPE_REG
1477 p.To.Reg = v.Reg()
1478
1479 case ssaop.OpAMD64LoweredWB:
1480 p := s.Prog(obj.ACALL)
1481 p.To.Type = obj.TYPE_MEM
1482 p.To.Name = obj.NAME_EXTERN
1483
1484 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
1485
1486 case ssaop.OpAMD64LoweredPanicBoundsRR, ssaop.OpAMD64LoweredPanicBoundsRC, ssaop.OpAMD64LoweredPanicBoundsCR, ssaop.OpAMD64LoweredPanicBoundsCC:
1487
1488 code, signed := ssa.BoundsKind(v.AuxInt).Code()
1489 xIsReg := false
1490 yIsReg := false
1491 xVal := 0
1492 yVal := 0
1493 switch v.Op {
1494 case ssaop.OpAMD64LoweredPanicBoundsRR:
1495 xIsReg = true
1496 xVal = int(v.Args[0].Reg() - x86.REG_AX)
1497 yIsReg = true
1498 yVal = int(v.Args[1].Reg() - x86.REG_AX)
1499 case ssaop.OpAMD64LoweredPanicBoundsRC:
1500 xIsReg = true
1501 xVal = int(v.Args[0].Reg() - x86.REG_AX)
1502 c := v.Aux.(ssa.PanicBoundsC).C
1503 if c >= 0 && c <= abi.BoundsMaxConst {
1504 yVal = int(c)
1505 } else {
1506
1507 yIsReg = true
1508 if yVal == xVal {
1509 yVal = 1
1510 }
1511 p := s.Prog(x86.AMOVQ)
1512 p.From.Type = obj.TYPE_CONST
1513 p.From.Offset = c
1514 p.To.Type = obj.TYPE_REG
1515 p.To.Reg = x86.REG_AX + int16(yVal)
1516 }
1517 case ssaop.OpAMD64LoweredPanicBoundsCR:
1518 yIsReg = true
1519 yVal = int(v.Args[0].Reg() - x86.REG_AX)
1520 c := v.Aux.(ssa.PanicBoundsC).C
1521 if c >= 0 && c <= abi.BoundsMaxConst {
1522 xVal = int(c)
1523 } else {
1524
1525 xIsReg = true
1526 if xVal == yVal {
1527 xVal = 1
1528 }
1529 p := s.Prog(x86.AMOVQ)
1530 p.From.Type = obj.TYPE_CONST
1531 p.From.Offset = c
1532 p.To.Type = obj.TYPE_REG
1533 p.To.Reg = x86.REG_AX + int16(xVal)
1534 }
1535 case ssaop.OpAMD64LoweredPanicBoundsCC:
1536 c := v.Aux.(ssa.PanicBoundsCC).Cx
1537 if c >= 0 && c <= abi.BoundsMaxConst {
1538 xVal = int(c)
1539 } else {
1540
1541 xIsReg = true
1542 p := s.Prog(x86.AMOVQ)
1543 p.From.Type = obj.TYPE_CONST
1544 p.From.Offset = c
1545 p.To.Type = obj.TYPE_REG
1546 p.To.Reg = x86.REG_AX + int16(xVal)
1547 }
1548 c = v.Aux.(ssa.PanicBoundsCC).Cy
1549 if c >= 0 && c <= abi.BoundsMaxConst {
1550 yVal = int(c)
1551 } else {
1552
1553 yIsReg = true
1554 yVal = 1
1555 p := s.Prog(x86.AMOVQ)
1556 p.From.Type = obj.TYPE_CONST
1557 p.From.Offset = c
1558 p.To.Type = obj.TYPE_REG
1559 p.To.Reg = x86.REG_AX + int16(yVal)
1560 }
1561 }
1562 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
1563
1564 p := s.Prog(obj.APCDATA)
1565 p.From.SetConst(abi.PCDATA_PanicBounds)
1566 p.To.SetConst(int64(c))
1567 p = s.Prog(obj.ACALL)
1568 p.To.Type = obj.TYPE_MEM
1569 p.To.Name = obj.NAME_EXTERN
1570 p.To.Sym = ir.Syms.PanicBounds
1571
1572 case ssaop.OpAMD64NEGQ, ssaop.OpAMD64NEGL,
1573 ssaop.OpAMD64BSWAPQ, ssaop.OpAMD64BSWAPL,
1574 ssaop.OpAMD64NOTQ, ssaop.OpAMD64NOTL:
1575 p := s.Prog(v.Op.Asm())
1576 p.To.Type = obj.TYPE_REG
1577 p.To.Reg = v.Reg()
1578
1579 case ssaop.OpAMD64NEGLflags:
1580 p := s.Prog(v.Op.Asm())
1581 p.To.Type = obj.TYPE_REG
1582 p.To.Reg = v.Reg0()
1583
1584 case ssaop.OpAMD64ADDQconstflags, ssaop.OpAMD64ADDLconstflags:
1585 p := s.Prog(v.Op.Asm())
1586 p.From.Type = obj.TYPE_CONST
1587 p.From.Offset = v.AuxInt
1588
1589
1590
1591
1592 switch {
1593 case p.As == x86.AADDQ && p.From.Offset == 1:
1594 p.As = x86.AINCQ
1595 p.From.Type = obj.TYPE_NONE
1596 case p.As == x86.AADDQ && p.From.Offset == -1:
1597 p.As = x86.ADECQ
1598 p.From.Type = obj.TYPE_NONE
1599 case p.As == x86.AADDL && p.From.Offset == 1:
1600 p.As = x86.AINCL
1601 p.From.Type = obj.TYPE_NONE
1602 case p.As == x86.AADDL && p.From.Offset == -1:
1603 p.As = x86.ADECL
1604 p.From.Type = obj.TYPE_NONE
1605 }
1606 p.To.Type = obj.TYPE_REG
1607 p.To.Reg = v.Reg0()
1608
1609 case ssaop.OpAMD64BSFQinit, ssaop.OpAMD64BSRQinit:
1610 p := s.Prog(v.Op.Asm())
1611 p.From.Type = obj.TYPE_REG
1612 p.From.Reg = v.Args[1].Reg()
1613 p.To.Type = obj.TYPE_REG
1614 p.To.Reg = v.Reg()
1615 case ssaop.OpAMD64BSFQ, ssaop.OpAMD64BSRQ, ssaop.OpAMD64BSFL, ssaop.OpAMD64BSRL:
1616 if v.Args[0].Reg() != v.Reg() {
1617
1618
1619 opregreg(s, x86.AXORL, v.Reg(), v.Reg())
1620 }
1621 p := s.Prog(v.Op.Asm())
1622 p.From.Type = obj.TYPE_REG
1623 p.From.Reg = v.Args[0].Reg()
1624 p.To.Type = obj.TYPE_REG
1625 p.To.Reg = v.Reg()
1626 case ssaop.OpAMD64SQRTSD, ssaop.OpAMD64SQRTSS:
1627 p := s.Prog(v.Op.Asm())
1628 p.From.Type = obj.TYPE_REG
1629 p.From.Reg = v.Args[0].Reg()
1630 p.To.Type = obj.TYPE_REG
1631 p.To.Reg = v.Reg()
1632 case ssaop.OpAMD64LoweredRound32F, ssaop.OpAMD64LoweredRound64F:
1633
1634 case ssaop.OpAMD64ROUNDSD, ssaop.OpAMD64ROUNDSS:
1635 p := s.Prog(v.Op.Asm())
1636 val := v.AuxInt
1637
1638 if val < 0 || val > 3 {
1639 v.Fatalf("Invalid rounding mode")
1640 }
1641 p.From.Offset = val
1642 p.From.Type = obj.TYPE_CONST
1643 p.AddRestSourceReg(v.Args[0].Reg())
1644 p.To.Type = obj.TYPE_REG
1645 p.To.Reg = v.Reg()
1646 case ssaop.OpAMD64POPCNTQ, ssaop.OpAMD64POPCNTL,
1647 ssaop.OpAMD64TZCNTQ, ssaop.OpAMD64TZCNTL,
1648 ssaop.OpAMD64LZCNTQ, ssaop.OpAMD64LZCNTL:
1649 if v.Args[0].Reg() != v.Reg() {
1650
1651
1652
1653 opregreg(s, x86.AXORL, v.Reg(), v.Reg())
1654 }
1655 p := s.Prog(v.Op.Asm())
1656 p.From.Type = obj.TYPE_REG
1657 p.From.Reg = v.Args[0].Reg()
1658 p.To.Type = obj.TYPE_REG
1659 p.To.Reg = v.Reg()
1660
1661 case ssaop.OpAMD64SETEQ, ssaop.OpAMD64SETNE,
1662 ssaop.OpAMD64SETL, ssaop.OpAMD64SETLE,
1663 ssaop.OpAMD64SETG, ssaop.OpAMD64SETGE,
1664 ssaop.OpAMD64SETGF, ssaop.OpAMD64SETGEF,
1665 ssaop.OpAMD64SETB, ssaop.OpAMD64SETBE,
1666 ssaop.OpAMD64SETORD, ssaop.OpAMD64SETNAN,
1667 ssaop.OpAMD64SETA, ssaop.OpAMD64SETAE,
1668 ssaop.OpAMD64SETO:
1669 p := s.Prog(v.Op.Asm())
1670 p.To.Type = obj.TYPE_REG
1671 p.To.Reg = v.Reg()
1672
1673 case ssaop.OpAMD64SETEQstore, ssaop.OpAMD64SETNEstore,
1674 ssaop.OpAMD64SETLstore, ssaop.OpAMD64SETLEstore,
1675 ssaop.OpAMD64SETGstore, ssaop.OpAMD64SETGEstore,
1676 ssaop.OpAMD64SETBstore, ssaop.OpAMD64SETBEstore,
1677 ssaop.OpAMD64SETAstore, ssaop.OpAMD64SETAEstore:
1678 p := s.Prog(v.Op.Asm())
1679 p.To.Type = obj.TYPE_MEM
1680 p.To.Reg = v.Args[0].Reg()
1681 ssagen.AddAux(&p.To, v)
1682
1683 case ssaop.OpAMD64SETEQstoreidx1, ssaop.OpAMD64SETNEstoreidx1,
1684 ssaop.OpAMD64SETLstoreidx1, ssaop.OpAMD64SETLEstoreidx1,
1685 ssaop.OpAMD64SETGstoreidx1, ssaop.OpAMD64SETGEstoreidx1,
1686 ssaop.OpAMD64SETBstoreidx1, ssaop.OpAMD64SETBEstoreidx1,
1687 ssaop.OpAMD64SETAstoreidx1, ssaop.OpAMD64SETAEstoreidx1:
1688 p := s.Prog(v.Op.Asm())
1689 memIdx(&p.To, v)
1690 ssagen.AddAux(&p.To, v)
1691
1692 case ssaop.OpAMD64SETNEF:
1693 t := v.RegTmp()
1694 p := s.Prog(v.Op.Asm())
1695 p.To.Type = obj.TYPE_REG
1696 p.To.Reg = v.Reg()
1697 q := s.Prog(x86.ASETPS)
1698 q.To.Type = obj.TYPE_REG
1699 q.To.Reg = t
1700
1701 opregreg(s, x86.AORL, v.Reg(), t)
1702
1703 case ssaop.OpAMD64SETEQF:
1704 t := v.RegTmp()
1705 p := s.Prog(v.Op.Asm())
1706 p.To.Type = obj.TYPE_REG
1707 p.To.Reg = v.Reg()
1708 q := s.Prog(x86.ASETPC)
1709 q.To.Type = obj.TYPE_REG
1710 q.To.Reg = t
1711
1712 opregreg(s, x86.AANDL, v.Reg(), t)
1713
1714 case ssaop.OpAMD64InvertFlags:
1715 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
1716 case ssaop.OpAMD64FlagEQ, ssaop.OpAMD64FlagLT_ULT, ssaop.OpAMD64FlagLT_UGT, ssaop.OpAMD64FlagGT_ULT, ssaop.OpAMD64FlagGT_UGT:
1717 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
1718 case ssaop.OpAMD64AddTupleFirst32, ssaop.OpAMD64AddTupleFirst64:
1719 v.Fatalf("AddTupleFirst* should never make it to codegen %v", v.LongString())
1720 case ssaop.OpAMD64REPSTOSQ:
1721 s.Prog(x86.AREP)
1722 s.Prog(x86.ASTOSQ)
1723 case ssaop.OpAMD64REPMOVSQ:
1724 s.Prog(x86.AREP)
1725 s.Prog(x86.AMOVSQ)
1726 case ssaop.OpAMD64LoweredNilCheck:
1727
1728
1729
1730
1731
1732
1733 p := s.Prog(x86.ATESTB)
1734 p.From.Type = obj.TYPE_REG
1735 p.From.Reg = x86.REG_AX
1736 p.To.Type = obj.TYPE_MEM
1737 p.To.Reg = v.Args[0].Reg()
1738 if logopt.Enabled() {
1739 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
1740 }
1741 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
1742 base.WarnfAt(v.Pos, "generated nil check")
1743 }
1744 case ssaop.OpAMD64MOVBatomicload, ssaop.OpAMD64MOVLatomicload, ssaop.OpAMD64MOVQatomicload:
1745 p := s.Prog(v.Op.Asm())
1746 p.From.Type = obj.TYPE_MEM
1747 p.From.Reg = v.Args[0].Reg()
1748 ssagen.AddAux(&p.From, v)
1749 p.To.Type = obj.TYPE_REG
1750 p.To.Reg = v.Reg0()
1751 case ssaop.OpAMD64XCHGB, ssaop.OpAMD64XCHGL, ssaop.OpAMD64XCHGQ:
1752 p := s.Prog(v.Op.Asm())
1753 p.From.Type = obj.TYPE_REG
1754 p.From.Reg = v.Reg0()
1755 p.To.Type = obj.TYPE_MEM
1756 p.To.Reg = v.Args[1].Reg()
1757 ssagen.AddAux(&p.To, v)
1758 case ssaop.OpAMD64XADDLlock, ssaop.OpAMD64XADDQlock:
1759 s.Prog(x86.ALOCK)
1760 p := s.Prog(v.Op.Asm())
1761 p.From.Type = obj.TYPE_REG
1762 p.From.Reg = v.Reg0()
1763 p.To.Type = obj.TYPE_MEM
1764 p.To.Reg = v.Args[1].Reg()
1765 ssagen.AddAux(&p.To, v)
1766 case ssaop.OpAMD64CMPXCHGLlock, ssaop.OpAMD64CMPXCHGQlock:
1767 if v.Args[1].Reg() != x86.REG_AX {
1768 v.Fatalf("input[1] not in AX %s", v.LongString())
1769 }
1770 s.Prog(x86.ALOCK)
1771 p := s.Prog(v.Op.Asm())
1772 p.From.Type = obj.TYPE_REG
1773 p.From.Reg = v.Args[2].Reg()
1774 p.To.Type = obj.TYPE_MEM
1775 p.To.Reg = v.Args[0].Reg()
1776 ssagen.AddAux(&p.To, v)
1777 p = s.Prog(x86.ASETEQ)
1778 p.To.Type = obj.TYPE_REG
1779 p.To.Reg = v.Reg0()
1780 case ssaop.OpAMD64ANDBlock, ssaop.OpAMD64ANDLlock, ssaop.OpAMD64ANDQlock,
1781 ssaop.OpAMD64ORBlock, ssaop.OpAMD64ORLlock, ssaop.OpAMD64ORQlock,
1782 ssaop.OpAMD64ADDLlock, ssaop.OpAMD64ADDQlock,
1783 ssaop.OpAMD64SUBLlock, ssaop.OpAMD64SUBQlock:
1784
1785 s.Prog(x86.ALOCK)
1786 p := s.Prog(v.Op.Asm())
1787 p.From.Type = obj.TYPE_REG
1788 p.From.Reg = v.Args[1].Reg()
1789 p.To.Type = obj.TYPE_MEM
1790 p.To.Reg = v.Args[0].Reg()
1791 ssagen.AddAux(&p.To, v)
1792 case ssaop.OpAMD64INCLlock, ssaop.OpAMD64INCQlock,
1793 ssaop.OpAMD64DECLlock, ssaop.OpAMD64DECQlock:
1794
1795 s.Prog(x86.ALOCK)
1796 p := s.Prog(v.Op.Asm())
1797 p.To.Type = obj.TYPE_MEM
1798 p.To.Reg = v.Args[0].Reg()
1799 ssagen.AddAux(&p.To, v)
1800 case ssaop.OpAMD64LoweredAtomicAnd64, ssaop.OpAMD64LoweredAtomicOr64, ssaop.OpAMD64LoweredAtomicAnd32, ssaop.OpAMD64LoweredAtomicOr32:
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812 mov := x86.AMOVQ
1813 op := x86.AANDQ
1814 cmpxchg := x86.ACMPXCHGQ
1815 switch v.Op {
1816 case ssaop.OpAMD64LoweredAtomicOr64:
1817 op = x86.AORQ
1818 case ssaop.OpAMD64LoweredAtomicAnd32:
1819 mov = x86.AMOVL
1820 op = x86.AANDL
1821 cmpxchg = x86.ACMPXCHGL
1822 case ssaop.OpAMD64LoweredAtomicOr32:
1823 mov = x86.AMOVL
1824 op = x86.AORL
1825 cmpxchg = x86.ACMPXCHGL
1826 }
1827 addr := v.Args[0].Reg()
1828 mask := v.Args[1].Reg()
1829 tmp := v.RegTmp()
1830 p1 := s.Prog(mov)
1831 p1.From.Type = obj.TYPE_REG
1832 p1.From.Reg = mask
1833 p1.To.Type = obj.TYPE_REG
1834 p1.To.Reg = tmp
1835 p2 := s.Prog(mov)
1836 p2.From.Type = obj.TYPE_MEM
1837 p2.From.Reg = addr
1838 ssagen.AddAux(&p2.From, v)
1839 p2.To.Type = obj.TYPE_REG
1840 p2.To.Reg = x86.REG_AX
1841 p3 := s.Prog(op)
1842 p3.From.Type = obj.TYPE_REG
1843 p3.From.Reg = x86.REG_AX
1844 p3.To.Type = obj.TYPE_REG
1845 p3.To.Reg = tmp
1846 s.Prog(x86.ALOCK)
1847 p5 := s.Prog(cmpxchg)
1848 p5.From.Type = obj.TYPE_REG
1849 p5.From.Reg = tmp
1850 p5.To.Type = obj.TYPE_MEM
1851 p5.To.Reg = addr
1852 ssagen.AddAux(&p5.To, v)
1853 p6 := s.Prog(x86.AJNE)
1854 p6.To.Type = obj.TYPE_BRANCH
1855 p6.To.SetTarget(p1)
1856 case ssaop.OpAMD64PrefetchT0, ssaop.OpAMD64PrefetchNTA:
1857 p := s.Prog(v.Op.Asm())
1858 p.From.Type = obj.TYPE_MEM
1859 p.From.Reg = v.Args[0].Reg()
1860 case ssaop.OpClobber:
1861 p := s.Prog(x86.AMOVL)
1862 p.From.Type = obj.TYPE_CONST
1863 p.From.Offset = 0xdeaddead
1864 p.To.Type = obj.TYPE_MEM
1865 p.To.Reg = x86.REG_SP
1866 ssagen.AddAux(&p.To, v)
1867 p = s.Prog(x86.AMOVL)
1868 p.From.Type = obj.TYPE_CONST
1869 p.From.Offset = 0xdeaddead
1870 p.To.Type = obj.TYPE_MEM
1871 p.To.Reg = x86.REG_SP
1872 ssagen.AddAux(&p.To, v)
1873 p.To.Offset += 4
1874 case ssaop.OpClobberReg:
1875 x := uint64(0xdeaddeaddeaddead)
1876 p := s.Prog(x86.AMOVQ)
1877 p.From.Type = obj.TYPE_CONST
1878 p.From.Offset = int64(x)
1879 p.To.Type = obj.TYPE_REG
1880 p.To.Reg = v.Reg()
1881
1882
1883 case ssaop.OpAMD64VZEROUPPER, ssaop.OpAMD64VZEROALL:
1884 s.Prog(v.Op.Asm())
1885
1886 case ssaop.OpAMD64Zero128, ssaop.OpAMD64Zero256, ssaop.OpAMD64Zero512:
1887
1888 case ssaop.OpAMD64VMOVSSf2v, ssaop.OpAMD64VMOVSDf2v:
1889
1890 p := s.Prog(v.Op.Asm())
1891 p.From.Type = obj.TYPE_REG
1892 p.From.Reg = v.Args[0].Reg()
1893 p.AddRestSourceReg(x86.REG_X15)
1894 p.To.Type = obj.TYPE_REG
1895 p.To.Reg = simdReg(v)
1896
1897 case ssaop.OpAMD64VMOVQload, ssaop.OpAMD64VMOVDload,
1898 ssaop.OpAMD64VMOVSSload, ssaop.OpAMD64VMOVSDload:
1899 p := s.Prog(v.Op.Asm())
1900 p.From.Type = obj.TYPE_MEM
1901 p.From.Reg = v.Args[0].Reg()
1902 ssagen.AddAux(&p.From, v)
1903 p.To.Type = obj.TYPE_REG
1904 p.To.Reg = simdReg(v)
1905
1906 case ssaop.OpAMD64VMOVSSconst, ssaop.OpAMD64VMOVSDconst:
1907
1908 x := simdReg(v)
1909 p := s.Prog(v.Op.Asm())
1910 p.From.Type = obj.TYPE_FCONST
1911 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
1912 p.To.Type = obj.TYPE_REG
1913 p.To.Reg = x
1914
1915 case ssaop.OpAMD64VMOVD, ssaop.OpAMD64VMOVQ:
1916
1917 p := s.Prog(v.Op.Asm())
1918 p.From.Type = obj.TYPE_REG
1919 p.From.Reg = v.Args[0].Reg()
1920 p.To.Type = obj.TYPE_REG
1921 p.To.Reg = simdReg(v)
1922
1923 case ssaop.OpAMD64VMOVDQUload128, ssaop.OpAMD64VMOVDQUload256, ssaop.OpAMD64VMOVDQUload512,
1924 ssaop.OpAMD64KMOVBload, ssaop.OpAMD64KMOVWload, ssaop.OpAMD64KMOVDload, ssaop.OpAMD64KMOVQload:
1925 p := s.Prog(v.Op.Asm())
1926 p.From.Type = obj.TYPE_MEM
1927 p.From.Reg = v.Args[0].Reg()
1928 ssagen.AddAux(&p.From, v)
1929 p.To.Type = obj.TYPE_REG
1930 p.To.Reg = simdOrMaskReg(v)
1931 case ssaop.OpAMD64VMOVDQUstore128, ssaop.OpAMD64VMOVDQUstore256, ssaop.OpAMD64VMOVDQUstore512,
1932 ssaop.OpAMD64KMOVBstore, ssaop.OpAMD64KMOVWstore, ssaop.OpAMD64KMOVDstore, ssaop.OpAMD64KMOVQstore:
1933 p := s.Prog(v.Op.Asm())
1934 p.From.Type = obj.TYPE_REG
1935 p.From.Reg = simdOrMaskReg(v.Args[1])
1936 p.To.Type = obj.TYPE_MEM
1937 p.To.Reg = v.Args[0].Reg()
1938 ssagen.AddAux(&p.To, v)
1939
1940 case ssaop.OpAMD64VPMASK32load128, ssaop.OpAMD64VPMASK64load128, ssaop.OpAMD64VPMASK32load256, ssaop.OpAMD64VPMASK64load256:
1941 p := s.Prog(v.Op.Asm())
1942 p.From.Type = obj.TYPE_MEM
1943 p.From.Reg = v.Args[0].Reg()
1944 ssagen.AddAux(&p.From, v)
1945 p.To.Type = obj.TYPE_REG
1946 p.To.Reg = simdReg(v)
1947 p.AddRestSourceReg(simdReg(v.Args[1]))
1948
1949 case ssaop.OpAMD64VPMASK32store128, ssaop.OpAMD64VPMASK64store128, ssaop.OpAMD64VPMASK32store256, ssaop.OpAMD64VPMASK64store256:
1950 p := s.Prog(v.Op.Asm())
1951 p.From.Type = obj.TYPE_REG
1952 p.From.Reg = simdReg(v.Args[2])
1953 p.To.Type = obj.TYPE_MEM
1954 p.To.Reg = v.Args[0].Reg()
1955 ssagen.AddAux(&p.To, v)
1956 p.AddRestSourceReg(simdReg(v.Args[1]))
1957
1958 case ssaop.OpAMD64VPMASK64load512, ssaop.OpAMD64VPMASK32load512, ssaop.OpAMD64VPMASK16load512, ssaop.OpAMD64VPMASK8load512:
1959 p := s.Prog(v.Op.Asm())
1960 p.From.Type = obj.TYPE_MEM
1961 p.From.Reg = v.Args[0].Reg()
1962 ssagen.AddAux(&p.From, v)
1963 p.To.Type = obj.TYPE_REG
1964 p.To.Reg = simdReg(v)
1965 p.AddRestSourceReg(v.Args[1].Reg())
1966 x86.ParseSuffix(p, "Z")
1967
1968 case ssaop.OpAMD64KANDB, ssaop.OpAMD64KANDW, ssaop.OpAMD64KANDD, ssaop.OpAMD64KANDQ,
1969 ssaop.OpAMD64KANDNB, ssaop.OpAMD64KANDNW, ssaop.OpAMD64KANDND, ssaop.OpAMD64KANDNQ,
1970 ssaop.OpAMD64KORB, ssaop.OpAMD64KORW, ssaop.OpAMD64KORD, ssaop.OpAMD64KORQ,
1971 ssaop.OpAMD64KXORB, ssaop.OpAMD64KXORW, ssaop.OpAMD64KXORD, ssaop.OpAMD64KXORQ,
1972 ssaop.OpAMD64KXNORB, ssaop.OpAMD64KXNORW, ssaop.OpAMD64KXNORD, ssaop.OpAMD64KXNORQ:
1973 p := s.Prog(v.Op.Asm())
1974 p.From.Type = obj.TYPE_REG
1975 p.From.Reg = v.Args[0].Reg()
1976 p.To.Type = obj.TYPE_REG
1977 p.To.Reg = v.Reg()
1978 p.AddRestSourceReg(v.Args[1].Reg())
1979
1980 case ssaop.OpAMD64VPMASK64store512, ssaop.OpAMD64VPMASK32store512, ssaop.OpAMD64VPMASK16store512, ssaop.OpAMD64VPMASK8store512:
1981 p := s.Prog(v.Op.Asm())
1982 p.From.Type = obj.TYPE_REG
1983 p.From.Reg = simdReg(v.Args[2])
1984 p.To.Type = obj.TYPE_MEM
1985 p.To.Reg = v.Args[0].Reg()
1986 ssagen.AddAux(&p.To, v)
1987 p.AddRestSourceReg(v.Args[1].Reg())
1988
1989 case ssaop.OpAMD64VPMOVMToVec8x16,
1990 ssaop.OpAMD64VPMOVMToVec8x32,
1991 ssaop.OpAMD64VPMOVMToVec8x64,
1992 ssaop.OpAMD64VPMOVMToVec16x8,
1993 ssaop.OpAMD64VPMOVMToVec16x16,
1994 ssaop.OpAMD64VPMOVMToVec16x32,
1995 ssaop.OpAMD64VPMOVMToVec32x4,
1996 ssaop.OpAMD64VPMOVMToVec32x8,
1997 ssaop.OpAMD64VPMOVMToVec32x16,
1998 ssaop.OpAMD64VPMOVMToVec64x2,
1999 ssaop.OpAMD64VPMOVMToVec64x4,
2000 ssaop.OpAMD64VPMOVMToVec64x8:
2001 p := s.Prog(v.Op.Asm())
2002 p.From.Type = obj.TYPE_REG
2003 p.From.Reg = v.Args[0].Reg()
2004 p.To.Type = obj.TYPE_REG
2005 p.To.Reg = simdReg(v)
2006
2007 case ssaop.OpAMD64VPMOVVec8x16ToM,
2008 ssaop.OpAMD64VPMOVVec8x32ToM,
2009 ssaop.OpAMD64VPMOVVec8x64ToM,
2010 ssaop.OpAMD64VPMOVVec16x8ToM,
2011 ssaop.OpAMD64VPMOVVec16x16ToM,
2012 ssaop.OpAMD64VPMOVVec16x32ToM,
2013 ssaop.OpAMD64VPMOVVec32x4ToM,
2014 ssaop.OpAMD64VPMOVVec32x8ToM,
2015 ssaop.OpAMD64VPMOVVec32x16ToM,
2016 ssaop.OpAMD64VPMOVVec64x2ToM,
2017 ssaop.OpAMD64VPMOVVec64x4ToM,
2018 ssaop.OpAMD64VPMOVVec64x8ToM,
2019 ssaop.OpAMD64VPMOVMSKB128,
2020 ssaop.OpAMD64VPMOVMSKB256,
2021 ssaop.OpAMD64VMOVMSKPS128,
2022 ssaop.OpAMD64VMOVMSKPS256,
2023 ssaop.OpAMD64VMOVMSKPD128,
2024 ssaop.OpAMD64VMOVMSKPD256:
2025 p := s.Prog(v.Op.Asm())
2026 p.From.Type = obj.TYPE_REG
2027 p.From.Reg = simdReg(v.Args[0])
2028 p.To.Type = obj.TYPE_REG
2029 p.To.Reg = v.Reg()
2030
2031 case ssaop.OpAMD64KMOVQk, ssaop.OpAMD64KMOVDk, ssaop.OpAMD64KMOVWk, ssaop.OpAMD64KMOVBk,
2032 ssaop.OpAMD64KMOVQi, ssaop.OpAMD64KMOVDi, ssaop.OpAMD64KMOVWi, ssaop.OpAMD64KMOVBi,
2033 ssaop.OpAMD64KNOTB, ssaop.OpAMD64KNOTW, ssaop.OpAMD64KNOTD, ssaop.OpAMD64KNOTQ:
2034
2035 p := s.Prog(v.Op.Asm())
2036 p.From.Type = obj.TYPE_REG
2037 p.From.Reg = v.Args[0].Reg()
2038 p.To.Type = obj.TYPE_REG
2039 p.To.Reg = v.Reg()
2040 case ssaop.OpAMD64VPTEST:
2041
2042
2043 p := s.Prog(v.Op.Asm())
2044 p.From.Type = obj.TYPE_REG
2045 p.From.Reg = simdReg(v.Args[0])
2046 p.To.Type = obj.TYPE_REG
2047 p.To.Reg = simdReg(v.Args[1])
2048
2049 default:
2050 if !ssaGenSIMDValue(s, v) {
2051 v.Fatalf("genValue not implemented: %s", v.LongString())
2052 }
2053 }
2054 }
2055
2056
2057
2058 func vxorpsX15(s *ssagen.State) {
2059 p := s.Prog(x86.AVXORPS)
2060 p.From.Type = obj.TYPE_REG
2061 p.From.Reg = x86.REG_X15
2062 p.AddRestSourceReg(x86.REG_X15)
2063 p.To.Type = obj.TYPE_REG
2064 p.To.Reg = x86.REG_X15
2065 }
2066
2067
2068
2069 func zeroX15Low(s *ssagen.State, avx bool) {
2070 if avx {
2071 vxorpsX15(s)
2072 return
2073 }
2074 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
2075 }
2076
2077
2078 func zeroX15(s *ssagen.State) {
2079 if buildcfg.GOAMD64 >= 3 {
2080 vxorpsX15(s)
2081 return
2082 }
2083 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
2084
2085 p := s.Prog(x86.ACMPB)
2086 p.From.Type = obj.TYPE_MEM
2087 p.From.Name = obj.NAME_EXTERN
2088 p.From.Sym = ir.Syms.X86HasAVX
2089 p.To.Type = obj.TYPE_CONST
2090 p.To.Offset = 1
2091 jmp := s.Prog(x86.AJNE)
2092 jmp.To.Type = obj.TYPE_BRANCH
2093 vxorpsX15(s)
2094 end := s.Prog(obj.ANOP)
2095 jmp.To.SetTarget(end)
2096 }
2097
2098
2099 func simdV11(s *ssagen.State, v *ssa.Value) *obj.Prog {
2100 p := s.Prog(v.Op.Asm())
2101 p.From.Type = obj.TYPE_REG
2102 p.From.Reg = simdReg(v.Args[0])
2103 p.To.Type = obj.TYPE_REG
2104 p.To.Reg = simdReg(v)
2105 return p
2106 }
2107
2108
2109 func simdV21(s *ssagen.State, v *ssa.Value) *obj.Prog {
2110 p := s.Prog(v.Op.Asm())
2111 p.From.Type = obj.TYPE_REG
2112
2113
2114 p.From.Reg = simdReg(v.Args[1])
2115 p.AddRestSourceReg(simdReg(v.Args[0]))
2116 p.To.Type = obj.TYPE_REG
2117 p.To.Reg = simdReg(v)
2118 return p
2119 }
2120
2121
2122
2123
2124 func simdVfpv(s *ssagen.State, v *ssa.Value) *obj.Prog {
2125 p := s.Prog(v.Op.Asm())
2126 p.From.Type = obj.TYPE_REG
2127
2128
2129 p.From.Reg = v.Args[1].Reg()
2130 p.AddRestSourceReg(simdReg(v.Args[0]))
2131 p.To.Type = obj.TYPE_REG
2132 p.To.Reg = simdReg(v)
2133 return p
2134 }
2135
2136
2137 func simdV2k(s *ssagen.State, v *ssa.Value) *obj.Prog {
2138 p := s.Prog(v.Op.Asm())
2139 p.From.Type = obj.TYPE_REG
2140 p.From.Reg = simdReg(v.Args[1])
2141 p.AddRestSourceReg(simdReg(v.Args[0]))
2142 p.To.Type = obj.TYPE_REG
2143 p.To.Reg = maskReg(v)
2144 return p
2145 }
2146
2147
2148 func simdV2kv(s *ssagen.State, v *ssa.Value) *obj.Prog {
2149 p := s.Prog(v.Op.Asm())
2150 p.From.Type = obj.TYPE_REG
2151 p.From.Reg = simdReg(v.Args[1])
2152 p.AddRestSourceReg(simdReg(v.Args[0]))
2153
2154
2155
2156
2157
2158 p.AddRestSourceReg(maskReg(v.Args[2]))
2159 p.To.Type = obj.TYPE_REG
2160 p.To.Reg = simdReg(v)
2161 return p
2162 }
2163
2164
2165 func simdV2kvResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2166 p := s.Prog(v.Op.Asm())
2167 p.From.Type = obj.TYPE_REG
2168 p.From.Reg = simdReg(v.Args[1])
2169
2170
2171
2172
2173
2174 p.AddRestSourceReg(maskReg(v.Args[2]))
2175 p.To.Type = obj.TYPE_REG
2176 p.To.Reg = simdReg(v)
2177 return p
2178 }
2179
2180
2181
2182
2183 func simdVfpkv(s *ssagen.State, v *ssa.Value) *obj.Prog {
2184 p := s.Prog(v.Op.Asm())
2185 p.From.Type = obj.TYPE_REG
2186 p.From.Reg = v.Args[1].Reg()
2187 p.AddRestSourceReg(simdReg(v.Args[0]))
2188 p.AddRestSourceReg(maskReg(v.Args[2]))
2189 p.To.Type = obj.TYPE_REG
2190 p.To.Reg = simdReg(v)
2191 return p
2192 }
2193
2194
2195 func simdV2kk(s *ssagen.State, v *ssa.Value) *obj.Prog {
2196 p := s.Prog(v.Op.Asm())
2197 p.From.Type = obj.TYPE_REG
2198 p.From.Reg = simdReg(v.Args[1])
2199 p.AddRestSourceReg(simdReg(v.Args[0]))
2200 p.AddRestSourceReg(maskReg(v.Args[2]))
2201 p.To.Type = obj.TYPE_REG
2202 p.To.Reg = maskReg(v)
2203 return p
2204 }
2205
2206
2207 func simdVkv(s *ssagen.State, v *ssa.Value) *obj.Prog {
2208 p := s.Prog(v.Op.Asm())
2209 p.From.Type = obj.TYPE_REG
2210 p.From.Reg = simdReg(v.Args[0])
2211 p.AddRestSourceReg(maskReg(v.Args[1]))
2212 p.To.Type = obj.TYPE_REG
2213 p.To.Reg = simdReg(v)
2214 return p
2215 }
2216
2217
2218 func simdV11Imm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2219 p := s.Prog(v.Op.Asm())
2220 p.From.Offset = int64(v.AuxUInt8())
2221 p.From.Type = obj.TYPE_CONST
2222 p.AddRestSourceReg(simdReg(v.Args[0]))
2223 p.To.Type = obj.TYPE_REG
2224 p.To.Reg = simdReg(v)
2225 return p
2226 }
2227
2228
2229 func simdVkvImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2230 p := s.Prog(v.Op.Asm())
2231 p.From.Offset = int64(v.AuxUInt8())
2232 p.From.Type = obj.TYPE_CONST
2233 p.AddRestSourceReg(simdReg(v.Args[0]))
2234 p.AddRestSourceReg(maskReg(v.Args[1]))
2235 p.To.Type = obj.TYPE_REG
2236 p.To.Reg = simdReg(v)
2237 return p
2238 }
2239
2240
2241 func simdV21Imm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2242 p := s.Prog(v.Op.Asm())
2243 p.From.Offset = int64(v.AuxUInt8())
2244 p.From.Type = obj.TYPE_CONST
2245 p.AddRestSourceReg(simdReg(v.Args[1]))
2246 p.AddRestSourceReg(simdReg(v.Args[0]))
2247 p.To.Type = obj.TYPE_REG
2248 p.To.Reg = simdReg(v)
2249 return p
2250 }
2251
2252
2253 func simdVgpvImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2254 p := s.Prog(v.Op.Asm())
2255 p.From.Offset = int64(v.AuxUInt8())
2256 p.From.Type = obj.TYPE_CONST
2257 p.AddRestSourceReg(v.Args[1].Reg())
2258 p.AddRestSourceReg(simdReg(v.Args[0]))
2259 p.To.Type = obj.TYPE_REG
2260 p.To.Reg = simdReg(v)
2261 return p
2262 }
2263 func simdVgpvImm(s *ssagen.State, v *ssa.Value) *obj.Prog {
2264
2265
2266
2267
2268
2269
2270 return simdVgpvImm8(s, v)
2271 }
2272
2273
2274 func simdV2kImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2275 p := s.Prog(v.Op.Asm())
2276 p.From.Offset = int64(v.AuxUInt8())
2277 p.From.Type = obj.TYPE_CONST
2278 p.AddRestSourceReg(simdReg(v.Args[1]))
2279 p.AddRestSourceReg(simdReg(v.Args[0]))
2280 p.To.Type = obj.TYPE_REG
2281 p.To.Reg = maskReg(v)
2282 return p
2283 }
2284
2285
2286 func simdV2kkImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2287 p := s.Prog(v.Op.Asm())
2288 p.From.Offset = int64(v.AuxUInt8())
2289 p.From.Type = obj.TYPE_CONST
2290 p.AddRestSourceReg(simdReg(v.Args[1]))
2291 p.AddRestSourceReg(simdReg(v.Args[0]))
2292 p.AddRestSourceReg(maskReg(v.Args[2]))
2293 p.To.Type = obj.TYPE_REG
2294 p.To.Reg = maskReg(v)
2295 return p
2296 }
2297
2298 func simdV2kvImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2299 p := s.Prog(v.Op.Asm())
2300 p.From.Offset = int64(v.AuxUInt8())
2301 p.From.Type = obj.TYPE_CONST
2302 p.AddRestSourceReg(simdReg(v.Args[1]))
2303 p.AddRestSourceReg(simdReg(v.Args[0]))
2304 p.AddRestSourceReg(maskReg(v.Args[2]))
2305 p.To.Type = obj.TYPE_REG
2306 p.To.Reg = simdReg(v)
2307 return p
2308 }
2309
2310
2311 func simdV31ResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2312 p := s.Prog(v.Op.Asm())
2313 p.From.Type = obj.TYPE_REG
2314 p.From.Reg = simdReg(v.Args[2])
2315 p.AddRestSourceReg(simdReg(v.Args[1]))
2316 p.To.Type = obj.TYPE_REG
2317 p.To.Reg = simdReg(v)
2318 return p
2319 }
2320
2321 func simdV31ResultInArg0Imm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2322 p := s.Prog(v.Op.Asm())
2323 p.From.Offset = int64(v.AuxUInt8())
2324 p.From.Type = obj.TYPE_CONST
2325
2326 p.AddRestSourceReg(simdReg(v.Args[2]))
2327 p.AddRestSourceReg(simdReg(v.Args[1]))
2328
2329 p.To.Type = obj.TYPE_REG
2330 p.To.Reg = simdReg(v)
2331 return p
2332 }
2333
2334
2335
2336
2337 func simdV31loadResultInArg0Imm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2338 sc := v.AuxValAndOff()
2339 p := s.Prog(v.Op.Asm())
2340
2341 p.From.Type = obj.TYPE_CONST
2342 p.From.Offset = sc.Val64()
2343
2344 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[2].Reg()}
2345 ssagen.AddAux2(&m, v, sc.Off64())
2346 p.AddRestSource(m)
2347
2348 p.AddRestSourceReg(simdReg(v.Args[1]))
2349 return p
2350 }
2351
2352
2353 func simdV3kvResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2354 p := s.Prog(v.Op.Asm())
2355 p.From.Type = obj.TYPE_REG
2356 p.From.Reg = simdReg(v.Args[2])
2357 p.AddRestSourceReg(simdReg(v.Args[1]))
2358 p.AddRestSourceReg(maskReg(v.Args[3]))
2359 p.To.Type = obj.TYPE_REG
2360 p.To.Reg = simdReg(v)
2361 return p
2362 }
2363
2364 func simdVgpImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2365 p := s.Prog(v.Op.Asm())
2366 p.From.Offset = int64(v.AuxUInt8())
2367 p.From.Type = obj.TYPE_CONST
2368 p.AddRestSourceReg(simdReg(v.Args[0]))
2369 p.To.Type = obj.TYPE_REG
2370 p.To.Reg = v.Reg()
2371 return p
2372 }
2373
2374 func simdVgpImm(s *ssagen.State, v *ssa.Value) *obj.Prog {
2375
2376
2377
2378
2379 return simdVgpImm8(s, v)
2380 }
2381
2382
2383 func simdV31(s *ssagen.State, v *ssa.Value) *obj.Prog {
2384 p := s.Prog(v.Op.Asm())
2385 p.From.Type = obj.TYPE_REG
2386 p.From.Reg = simdReg(v.Args[2])
2387 p.AddRestSourceReg(simdReg(v.Args[1]))
2388 p.AddRestSourceReg(simdReg(v.Args[0]))
2389 p.To.Type = obj.TYPE_REG
2390 p.To.Reg = simdReg(v)
2391 return p
2392 }
2393
2394
2395 func simdV3kv(s *ssagen.State, v *ssa.Value) *obj.Prog {
2396 p := s.Prog(v.Op.Asm())
2397 p.From.Type = obj.TYPE_REG
2398 p.From.Reg = simdReg(v.Args[2])
2399 p.AddRestSourceReg(simdReg(v.Args[1]))
2400 p.AddRestSourceReg(simdReg(v.Args[0]))
2401 p.AddRestSourceReg(maskReg(v.Args[3]))
2402 p.To.Type = obj.TYPE_REG
2403 p.To.Reg = simdReg(v)
2404 return p
2405 }
2406
2407
2408 func simdVkvload(s *ssagen.State, v *ssa.Value) *obj.Prog {
2409 p := s.Prog(v.Op.Asm())
2410 p.From.Type = obj.TYPE_MEM
2411 p.From.Reg = v.Args[0].Reg()
2412 ssagen.AddAux(&p.From, v)
2413 p.AddRestSourceReg(maskReg(v.Args[1]))
2414 p.To.Type = obj.TYPE_REG
2415 p.To.Reg = simdReg(v)
2416 return p
2417 }
2418
2419
2420 func simdV21load(s *ssagen.State, v *ssa.Value) *obj.Prog {
2421 p := s.Prog(v.Op.Asm())
2422 p.From.Type = obj.TYPE_MEM
2423 p.From.Reg = v.Args[1].Reg()
2424 ssagen.AddAux(&p.From, v)
2425 p.AddRestSourceReg(simdReg(v.Args[0]))
2426 p.To.Type = obj.TYPE_REG
2427 p.To.Reg = simdReg(v)
2428 return p
2429 }
2430
2431
2432 func simdV31loadResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2433 p := s.Prog(v.Op.Asm())
2434 p.From.Type = obj.TYPE_MEM
2435 p.From.Reg = v.Args[2].Reg()
2436 ssagen.AddAux(&p.From, v)
2437 p.AddRestSourceReg(simdReg(v.Args[1]))
2438 p.To.Type = obj.TYPE_REG
2439 p.To.Reg = simdReg(v)
2440 return p
2441 }
2442
2443
2444 func simdV3kvloadResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2445 p := s.Prog(v.Op.Asm())
2446 p.From.Type = obj.TYPE_MEM
2447 p.From.Reg = v.Args[2].Reg()
2448 ssagen.AddAux(&p.From, v)
2449 p.AddRestSourceReg(simdReg(v.Args[1]))
2450 p.AddRestSourceReg(maskReg(v.Args[3]))
2451 p.To.Type = obj.TYPE_REG
2452 p.To.Reg = simdReg(v)
2453 return p
2454 }
2455
2456
2457 func simdV2kvload(s *ssagen.State, v *ssa.Value) *obj.Prog {
2458 p := s.Prog(v.Op.Asm())
2459 p.From.Type = obj.TYPE_MEM
2460 p.From.Reg = v.Args[1].Reg()
2461 ssagen.AddAux(&p.From, v)
2462 p.AddRestSourceReg(simdReg(v.Args[0]))
2463 p.AddRestSourceReg(maskReg(v.Args[2]))
2464 p.To.Type = obj.TYPE_REG
2465 p.To.Reg = simdReg(v)
2466 return p
2467 }
2468
2469
2470 func simdV2kload(s *ssagen.State, v *ssa.Value) *obj.Prog {
2471 p := s.Prog(v.Op.Asm())
2472 p.From.Type = obj.TYPE_MEM
2473 p.From.Reg = v.Args[1].Reg()
2474 ssagen.AddAux(&p.From, v)
2475 p.AddRestSourceReg(simdReg(v.Args[0]))
2476 p.To.Type = obj.TYPE_REG
2477 p.To.Reg = maskReg(v)
2478 return p
2479 }
2480
2481
2482 func simdV11load(s *ssagen.State, v *ssa.Value) *obj.Prog {
2483 p := s.Prog(v.Op.Asm())
2484 p.From.Type = obj.TYPE_MEM
2485 p.From.Reg = v.Args[0].Reg()
2486 ssagen.AddAux(&p.From, v)
2487 p.To.Type = obj.TYPE_REG
2488 p.To.Reg = simdReg(v)
2489 return p
2490 }
2491
2492
2493 func simdV11loadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2494 sc := v.AuxValAndOff()
2495 p := s.Prog(v.Op.Asm())
2496 p.From.Type = obj.TYPE_CONST
2497 p.From.Offset = sc.Val64()
2498 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
2499 ssagen.AddAux2(&m, v, sc.Off64())
2500 p.AddRestSource(m)
2501 p.To.Type = obj.TYPE_REG
2502 p.To.Reg = simdReg(v)
2503 return p
2504 }
2505
2506
2507 func simdVkvloadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2508 sc := v.AuxValAndOff()
2509 p := s.Prog(v.Op.Asm())
2510 p.From.Type = obj.TYPE_CONST
2511 p.From.Offset = sc.Val64()
2512 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
2513 ssagen.AddAux2(&m, v, sc.Off64())
2514 p.AddRestSource(m)
2515 p.AddRestSourceReg(maskReg(v.Args[1]))
2516 p.To.Type = obj.TYPE_REG
2517 p.To.Reg = simdReg(v)
2518 return p
2519 }
2520
2521
2522 func simdV21loadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2523 sc := v.AuxValAndOff()
2524 p := s.Prog(v.Op.Asm())
2525 p.From.Type = obj.TYPE_CONST
2526 p.From.Offset = sc.Val64()
2527 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()}
2528 ssagen.AddAux2(&m, v, sc.Off64())
2529 p.AddRestSource(m)
2530 p.AddRestSourceReg(simdReg(v.Args[0]))
2531 p.To.Type = obj.TYPE_REG
2532 p.To.Reg = simdReg(v)
2533 return p
2534 }
2535
2536
2537 func simdV2kloadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2538 sc := v.AuxValAndOff()
2539 p := s.Prog(v.Op.Asm())
2540 p.From.Type = obj.TYPE_CONST
2541 p.From.Offset = sc.Val64()
2542 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()}
2543 ssagen.AddAux2(&m, v, sc.Off64())
2544 p.AddRestSource(m)
2545 p.AddRestSourceReg(simdReg(v.Args[0]))
2546 p.To.Type = obj.TYPE_REG
2547 p.To.Reg = maskReg(v)
2548 return p
2549 }
2550
2551
2552 func simdV2kkloadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2553 sc := v.AuxValAndOff()
2554 p := s.Prog(v.Op.Asm())
2555 p.From.Type = obj.TYPE_CONST
2556 p.From.Offset = sc.Val64()
2557 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()}
2558 ssagen.AddAux2(&m, v, sc.Off64())
2559 p.AddRestSource(m)
2560 p.AddRestSourceReg(simdReg(v.Args[0]))
2561 p.AddRestSourceReg(maskReg(v.Args[2]))
2562 p.To.Type = obj.TYPE_REG
2563 p.To.Reg = maskReg(v)
2564 return p
2565 }
2566
2567
2568 func simdV2kvloadImm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2569 sc := v.AuxValAndOff()
2570 p := s.Prog(v.Op.Asm())
2571 p.From.Type = obj.TYPE_CONST
2572 p.From.Offset = sc.Val64()
2573 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()}
2574 ssagen.AddAux2(&m, v, sc.Off64())
2575 p.AddRestSource(m)
2576 p.AddRestSourceReg(simdReg(v.Args[0]))
2577 p.AddRestSourceReg(maskReg(v.Args[2]))
2578 p.To.Type = obj.TYPE_REG
2579 p.To.Reg = simdReg(v)
2580 return p
2581 }
2582
2583
2584 func simdV21ResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2585 p := s.Prog(v.Op.Asm())
2586 p.From.Type = obj.TYPE_REG
2587 p.From.Reg = simdReg(v.Args[1])
2588 p.To.Type = obj.TYPE_REG
2589 p.To.Reg = simdReg(v)
2590 return p
2591 }
2592
2593
2594 func simdV21ResultInArg0Imm8(s *ssagen.State, v *ssa.Value) *obj.Prog {
2595 p := s.Prog(v.Op.Asm())
2596 p.From.Offset = int64(v.AuxUInt8())
2597 p.From.Type = obj.TYPE_CONST
2598 p.AddRestSourceReg(simdReg(v.Args[1]))
2599 p.To.Type = obj.TYPE_REG
2600 p.To.Reg = simdReg(v)
2601 return p
2602 }
2603
2604
2605 func simdV31x0AtIn2ResultInArg0(s *ssagen.State, v *ssa.Value) *obj.Prog {
2606 return simdV31ResultInArg0(s, v)
2607 }
2608
2609 var blockJump = [...]struct {
2610 asm, invasm obj.As
2611 }{
2612 block.BlockAMD64EQ: {x86.AJEQ, x86.AJNE},
2613 block.BlockAMD64NE: {x86.AJNE, x86.AJEQ},
2614 block.BlockAMD64LT: {x86.AJLT, x86.AJGE},
2615 block.BlockAMD64GE: {x86.AJGE, x86.AJLT},
2616 block.BlockAMD64LE: {x86.AJLE, x86.AJGT},
2617 block.BlockAMD64GT: {x86.AJGT, x86.AJLE},
2618 block.BlockAMD64OS: {x86.AJOS, x86.AJOC},
2619 block.BlockAMD64OC: {x86.AJOC, x86.AJOS},
2620 block.BlockAMD64ULT: {x86.AJCS, x86.AJCC},
2621 block.BlockAMD64UGE: {x86.AJCC, x86.AJCS},
2622 block.BlockAMD64UGT: {x86.AJHI, x86.AJLS},
2623 block.BlockAMD64ULE: {x86.AJLS, x86.AJHI},
2624 block.BlockAMD64ORD: {x86.AJPC, x86.AJPS},
2625 block.BlockAMD64NAN: {x86.AJPS, x86.AJPC},
2626 }
2627
2628 var eqfJumps = [2][2]ssagen.IndexJump{
2629 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPS, Index: 1}},
2630 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPC, Index: 0}},
2631 }
2632 var nefJumps = [2][2]ssagen.IndexJump{
2633 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPC, Index: 1}},
2634 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPS, Index: 0}},
2635 }
2636
2637 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
2638 switch b.Kind {
2639 case block.BlockPlain, block.BlockDefer:
2640 if b.Succs[0].Block() != next {
2641 p := s.Prog(obj.AJMP)
2642 p.To.Type = obj.TYPE_BRANCH
2643 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
2644 }
2645 case block.BlockExit, block.BlockRetJmp:
2646 case block.BlockRet:
2647 s.Prog(obj.ARET)
2648
2649 case block.BlockAMD64EQF:
2650 s.CombJump(b, next, &eqfJumps)
2651
2652 case block.BlockAMD64NEF:
2653 s.CombJump(b, next, &nefJumps)
2654
2655 case block.BlockAMD64EQ, block.BlockAMD64NE,
2656 block.BlockAMD64LT, block.BlockAMD64GE,
2657 block.BlockAMD64LE, block.BlockAMD64GT,
2658 block.BlockAMD64OS, block.BlockAMD64OC,
2659 block.BlockAMD64ULT, block.BlockAMD64UGT,
2660 block.BlockAMD64ULE, block.BlockAMD64UGE:
2661 jmp := blockJump[b.Kind]
2662 switch next {
2663 case b.Succs[0].Block():
2664 s.Br(jmp.invasm, b.Succs[1].Block())
2665 case b.Succs[1].Block():
2666 s.Br(jmp.asm, b.Succs[0].Block())
2667 default:
2668 if b.Likely != ssa.BranchUnlikely {
2669 s.Br(jmp.asm, b.Succs[0].Block())
2670 s.Br(obj.AJMP, b.Succs[1].Block())
2671 } else {
2672 s.Br(jmp.invasm, b.Succs[1].Block())
2673 s.Br(obj.AJMP, b.Succs[0].Block())
2674 }
2675 }
2676
2677 case block.BlockAMD64JUMPTABLE:
2678
2679 p := s.Prog(obj.AJMP)
2680 p.To.Type = obj.TYPE_MEM
2681 p.To.Reg = b.Controls[1].Reg()
2682 p.To.Index = b.Controls[0].Reg()
2683 p.To.Scale = 8
2684
2685 s.JumpTables = append(s.JumpTables, b)
2686
2687 default:
2688 b.Fatalf("branch not implemented: %s", b.LongString())
2689 }
2690 }
2691
2692 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
2693
2694
2695
2696 p := s.Prog(loadByRegWidth(reg, t.Size(), f.Entry.CPUfeatures.HasFeature(ssa.CPUavx)))
2697 p.From.Type = obj.TYPE_MEM
2698 p.From.Name = obj.NAME_AUTO
2699 p.From.Sym = n.Linksym()
2700 p.From.Offset = n.FrameOffset() + off
2701 p.To.Type = obj.TYPE_REG
2702 p.To.Reg = reg
2703 return p
2704 }
2705
2706 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
2707
2708 p = pp.Append(p, storeByRegWidth(reg, t.Size(), f.Entry.CPUfeatures.HasFeature(ssa.CPUavx)), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
2709 p.To.Name = obj.NAME_PARAM
2710 p.To.Sym = n.Linksym()
2711 p.Pos = p.Pos.WithNotStmt()
2712 return p
2713 }
2714
2715
2716
2717
2718
2719 func hasAVX(v *ssa.Value) bool {
2720 return v.Block.CPUfeatures.HasFeature(ssa.CPUavx)
2721 }
2722
2723
2724 func zero16(s *ssagen.State, reg int16, off int64, avx bool) {
2725
2726 op := x86.AMOVUPS
2727 if avx {
2728 op = x86.AVMOVUPS
2729 }
2730 p := s.Prog(op)
2731 p.From.Type = obj.TYPE_REG
2732 p.From.Reg = x86.REG_X15
2733 p.To.Type = obj.TYPE_MEM
2734 p.To.Reg = reg
2735 p.To.Offset = off
2736 }
2737
2738
2739 func move16(s *ssagen.State, src, dst, tmp int16, off int64, avx bool) {
2740
2741
2742 op := x86.AMOVUPS
2743 if avx {
2744 op = x86.AVMOVUPS
2745 }
2746 p := s.Prog(op)
2747 p.From.Type = obj.TYPE_MEM
2748 p.From.Reg = src
2749 p.From.Offset = off
2750 p.To.Type = obj.TYPE_REG
2751 p.To.Reg = tmp
2752 p = s.Prog(op)
2753 p.From.Type = obj.TYPE_REG
2754 p.From.Reg = tmp
2755 p.To.Type = obj.TYPE_MEM
2756 p.To.Reg = dst
2757 p.To.Offset = off
2758 }
2759
2760
2761
2762 func simdReg(v *ssa.Value) int16 {
2763 t := v.Type
2764 if !t.IsSIMD() {
2765 base.Fatalf("simdReg: not a simd type; v=%s, b=b%d, f=%s", v.LongString(), v.Block.ID, v.Block.Func.Name)
2766 }
2767 return simdRegBySize(v.Reg(), t.Size())
2768 }
2769
2770 func simdRegBySize(reg int16, size int64) int16 {
2771 switch size {
2772 case 16:
2773 return reg
2774 case 32:
2775 return reg + (x86.REG_Y0 - x86.REG_X0)
2776 case 64:
2777 return reg + (x86.REG_Z0 - x86.REG_X0)
2778 }
2779 panic("simdRegBySize: bad size")
2780 }
2781
2782
2783 func maskReg(v *ssa.Value) int16 {
2784 t := v.Type
2785 if !t.IsSIMD() {
2786 base.Fatalf("maskReg: not a simd type; v=%s, b=b%d, f=%s", v.LongString(), v.Block.ID, v.Block.Func.Name)
2787 }
2788 switch t.Size() {
2789 case 8:
2790 return v.Reg()
2791 }
2792 panic("unreachable")
2793 }
2794
2795
2796 func simdOrMaskReg(v *ssa.Value) int16 {
2797 t := v.Type
2798 if t.Size() <= 8 {
2799 return maskReg(v)
2800 }
2801 return simdReg(v)
2802 }
2803
2804
2805
2806
2807
2808 func simdCheckRegOnly(v *ssa.Value, regStart, regEnd int16) int16 {
2809 if v.Reg() > regEnd || v.Reg() < regStart {
2810 panic("simdCheckRegOnly: not the desired register")
2811 }
2812 return v.Reg()
2813 }
2814
View as plain text