1
2
3
4
5 package amd64
6
7 import (
8 "fmt"
9 "internal/buildcfg"
10 "math"
11
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/logopt"
15 "cmd/compile/internal/objw"
16 "cmd/compile/internal/ssa"
17 "cmd/compile/internal/ssagen"
18 "cmd/compile/internal/types"
19 "cmd/internal/obj"
20 "cmd/internal/obj/x86"
21 )
22
23
24 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {
25 flive := b.FlagsLiveAtEnd
26 for _, c := range b.ControlValues() {
27 flive = c.Type.IsFlags() || flive
28 }
29 for i := len(b.Values) - 1; i >= 0; i-- {
30 v := b.Values[i]
31 if flive && (v.Op == ssa.OpAMD64MOVLconst || v.Op == ssa.OpAMD64MOVQconst) {
32
33 v.Aux = ssa.AuxMark
34 }
35 if v.Type.IsFlags() {
36 flive = false
37 }
38 for _, a := range v.Args {
39 if a.Type.IsFlags() {
40 flive = true
41 }
42 }
43 }
44 }
45
46
47 func loadByType(t *types.Type) obj.As {
48
49 if !t.IsFloat() {
50 switch t.Size() {
51 case 1:
52 return x86.AMOVBLZX
53 case 2:
54 return x86.AMOVWLZX
55 }
56 }
57
58 return storeByType(t)
59 }
60
61
62 func storeByType(t *types.Type) obj.As {
63 width := t.Size()
64 if t.IsFloat() {
65 switch width {
66 case 4:
67 return x86.AMOVSS
68 case 8:
69 return x86.AMOVSD
70 }
71 } else {
72 switch width {
73 case 1:
74 return x86.AMOVB
75 case 2:
76 return x86.AMOVW
77 case 4:
78 return x86.AMOVL
79 case 8:
80 return x86.AMOVQ
81 case 16:
82 return x86.AMOVUPS
83 }
84 }
85 panic(fmt.Sprintf("bad store type %v", t))
86 }
87
88
89 func moveByType(t *types.Type) obj.As {
90 if t.IsFloat() {
91
92
93
94
95 return x86.AMOVUPS
96 } else {
97 switch t.Size() {
98 case 1:
99
100 return x86.AMOVL
101 case 2:
102 return x86.AMOVL
103 case 4:
104 return x86.AMOVL
105 case 8:
106 return x86.AMOVQ
107 case 16:
108 return x86.AMOVUPS
109 default:
110 panic(fmt.Sprintf("bad int register width %d:%v", t.Size(), t))
111 }
112 }
113 }
114
115
116
117
118
119
120
121 func opregreg(s *ssagen.State, op obj.As, dest, src int16) *obj.Prog {
122 p := s.Prog(op)
123 p.From.Type = obj.TYPE_REG
124 p.To.Type = obj.TYPE_REG
125 p.To.Reg = dest
126 p.From.Reg = src
127 return p
128 }
129
130
131
132
133
134 func memIdx(a *obj.Addr, v *ssa.Value) {
135 r, i := v.Args[0].Reg(), v.Args[1].Reg()
136 a.Type = obj.TYPE_MEM
137 a.Scale = v.Op.Scale()
138 if a.Scale == 1 && i == x86.REG_SP {
139 r, i = i, r
140 }
141 a.Reg = r
142 a.Index = i
143 }
144
145
146
147 func duffStart(size int64) int64 {
148 x, _ := duff(size)
149 return x
150 }
151 func duffAdj(size int64) int64 {
152 _, x := duff(size)
153 return x
154 }
155
156
157
158 func duff(size int64) (int64, int64) {
159 if size < 32 || size > 1024 || size%dzClearStep != 0 {
160 panic("bad duffzero size")
161 }
162 steps := size / dzClearStep
163 blocks := steps / dzBlockLen
164 steps %= dzBlockLen
165 off := dzBlockSize * (dzBlocks - blocks)
166 var adj int64
167 if steps != 0 {
168 off -= dzLeaqSize
169 off -= dzMovSize * steps
170 adj -= dzClearStep * (dzBlockLen - steps)
171 }
172 return off, adj
173 }
174
175 func getgFromTLS(s *ssagen.State, r int16) {
176
177
178 if x86.CanUse1InsnTLS(base.Ctxt) {
179
180 p := s.Prog(x86.AMOVQ)
181 p.From.Type = obj.TYPE_MEM
182 p.From.Reg = x86.REG_TLS
183 p.To.Type = obj.TYPE_REG
184 p.To.Reg = r
185 } else {
186
187
188 p := s.Prog(x86.AMOVQ)
189 p.From.Type = obj.TYPE_REG
190 p.From.Reg = x86.REG_TLS
191 p.To.Type = obj.TYPE_REG
192 p.To.Reg = r
193 q := s.Prog(x86.AMOVQ)
194 q.From.Type = obj.TYPE_MEM
195 q.From.Reg = r
196 q.From.Index = x86.REG_TLS
197 q.From.Scale = 1
198 q.To.Type = obj.TYPE_REG
199 q.To.Reg = r
200 }
201 }
202
203 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
204 switch v.Op {
205 case ssa.OpAMD64VFMADD231SD:
206 p := s.Prog(v.Op.Asm())
207 p.From = obj.Addr{Type: obj.TYPE_REG, Reg: v.Args[2].Reg()}
208 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
209 p.AddRestSourceReg(v.Args[1].Reg())
210 case ssa.OpAMD64ADDQ, ssa.OpAMD64ADDL:
211 r := v.Reg()
212 r1 := v.Args[0].Reg()
213 r2 := v.Args[1].Reg()
214 switch {
215 case r == r1:
216 p := s.Prog(v.Op.Asm())
217 p.From.Type = obj.TYPE_REG
218 p.From.Reg = r2
219 p.To.Type = obj.TYPE_REG
220 p.To.Reg = r
221 case r == r2:
222 p := s.Prog(v.Op.Asm())
223 p.From.Type = obj.TYPE_REG
224 p.From.Reg = r1
225 p.To.Type = obj.TYPE_REG
226 p.To.Reg = r
227 default:
228 var asm obj.As
229 if v.Op == ssa.OpAMD64ADDQ {
230 asm = x86.ALEAQ
231 } else {
232 asm = x86.ALEAL
233 }
234 p := s.Prog(asm)
235 p.From.Type = obj.TYPE_MEM
236 p.From.Reg = r1
237 p.From.Scale = 1
238 p.From.Index = r2
239 p.To.Type = obj.TYPE_REG
240 p.To.Reg = r
241 }
242
243 case ssa.OpAMD64SUBQ, ssa.OpAMD64SUBL,
244 ssa.OpAMD64MULQ, ssa.OpAMD64MULL,
245 ssa.OpAMD64ANDQ, ssa.OpAMD64ANDL,
246 ssa.OpAMD64ORQ, ssa.OpAMD64ORL,
247 ssa.OpAMD64XORQ, ssa.OpAMD64XORL,
248 ssa.OpAMD64SHLQ, ssa.OpAMD64SHLL,
249 ssa.OpAMD64SHRQ, ssa.OpAMD64SHRL, ssa.OpAMD64SHRW, ssa.OpAMD64SHRB,
250 ssa.OpAMD64SARQ, ssa.OpAMD64SARL, ssa.OpAMD64SARW, ssa.OpAMD64SARB,
251 ssa.OpAMD64ROLQ, ssa.OpAMD64ROLL, ssa.OpAMD64ROLW, ssa.OpAMD64ROLB,
252 ssa.OpAMD64RORQ, ssa.OpAMD64RORL, ssa.OpAMD64RORW, ssa.OpAMD64RORB,
253 ssa.OpAMD64ADDSS, ssa.OpAMD64ADDSD, ssa.OpAMD64SUBSS, ssa.OpAMD64SUBSD,
254 ssa.OpAMD64MULSS, ssa.OpAMD64MULSD, ssa.OpAMD64DIVSS, ssa.OpAMD64DIVSD,
255 ssa.OpAMD64MINSS, ssa.OpAMD64MINSD,
256 ssa.OpAMD64POR, ssa.OpAMD64PXOR,
257 ssa.OpAMD64BTSL, ssa.OpAMD64BTSQ,
258 ssa.OpAMD64BTCL, ssa.OpAMD64BTCQ,
259 ssa.OpAMD64BTRL, ssa.OpAMD64BTRQ:
260 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
261
262 case ssa.OpAMD64SHRDQ, ssa.OpAMD64SHLDQ:
263 p := s.Prog(v.Op.Asm())
264 lo, hi, bits := v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg()
265 p.From.Type = obj.TYPE_REG
266 p.From.Reg = bits
267 p.To.Type = obj.TYPE_REG
268 p.To.Reg = lo
269 p.AddRestSourceReg(hi)
270
271 case ssa.OpAMD64BLSIQ, ssa.OpAMD64BLSIL,
272 ssa.OpAMD64BLSMSKQ, ssa.OpAMD64BLSMSKL,
273 ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL:
274 p := s.Prog(v.Op.Asm())
275 p.From.Type = obj.TYPE_REG
276 p.From.Reg = v.Args[0].Reg()
277 p.To.Type = obj.TYPE_REG
278 switch v.Op {
279 case ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL:
280 p.To.Reg = v.Reg0()
281 default:
282 p.To.Reg = v.Reg()
283 }
284
285 case ssa.OpAMD64ANDNQ, ssa.OpAMD64ANDNL:
286 p := s.Prog(v.Op.Asm())
287 p.From.Type = obj.TYPE_REG
288 p.From.Reg = v.Args[0].Reg()
289 p.To.Type = obj.TYPE_REG
290 p.To.Reg = v.Reg()
291 p.AddRestSourceReg(v.Args[1].Reg())
292
293 case ssa.OpAMD64SARXL, ssa.OpAMD64SARXQ,
294 ssa.OpAMD64SHLXL, ssa.OpAMD64SHLXQ,
295 ssa.OpAMD64SHRXL, ssa.OpAMD64SHRXQ:
296 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
297 p.AddRestSourceReg(v.Args[0].Reg())
298
299 case ssa.OpAMD64SHLXLload, ssa.OpAMD64SHLXQload,
300 ssa.OpAMD64SHRXLload, ssa.OpAMD64SHRXQload,
301 ssa.OpAMD64SARXLload, ssa.OpAMD64SARXQload:
302 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
303 m := obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[0].Reg()}
304 ssagen.AddAux(&m, v)
305 p.AddRestSource(m)
306
307 case ssa.OpAMD64SHLXLloadidx1, ssa.OpAMD64SHLXLloadidx4, ssa.OpAMD64SHLXLloadidx8,
308 ssa.OpAMD64SHRXLloadidx1, ssa.OpAMD64SHRXLloadidx4, ssa.OpAMD64SHRXLloadidx8,
309 ssa.OpAMD64SARXLloadidx1, ssa.OpAMD64SARXLloadidx4, ssa.OpAMD64SARXLloadidx8,
310 ssa.OpAMD64SHLXQloadidx1, ssa.OpAMD64SHLXQloadidx8,
311 ssa.OpAMD64SHRXQloadidx1, ssa.OpAMD64SHRXQloadidx8,
312 ssa.OpAMD64SARXQloadidx1, ssa.OpAMD64SARXQloadidx8:
313 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[2].Reg())
314 m := obj.Addr{Type: obj.TYPE_MEM}
315 memIdx(&m, v)
316 ssagen.AddAux(&m, v)
317 p.AddRestSource(m)
318
319 case ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU:
320
321
322
323
324 r := v.Args[1].Reg()
325
326
327 opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
328
329
330 p := s.Prog(v.Op.Asm())
331 p.From.Type = obj.TYPE_REG
332 p.From.Reg = r
333
334 case ssa.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW:
335
336
337
338
339 r := v.Args[1].Reg()
340
341 var opCMP, opNEG, opSXD obj.As
342 switch v.Op {
343 case ssa.OpAMD64DIVQ:
344 opCMP, opNEG, opSXD = x86.ACMPQ, x86.ANEGQ, x86.ACQO
345 case ssa.OpAMD64DIVL:
346 opCMP, opNEG, opSXD = x86.ACMPL, x86.ANEGL, x86.ACDQ
347 case ssa.OpAMD64DIVW:
348 opCMP, opNEG, opSXD = x86.ACMPW, x86.ANEGW, x86.ACWD
349 }
350
351
352
353 var j1, j2 *obj.Prog
354 if ssa.DivisionNeedsFixUp(v) {
355 c := s.Prog(opCMP)
356 c.From.Type = obj.TYPE_REG
357 c.From.Reg = r
358 c.To.Type = obj.TYPE_CONST
359 c.To.Offset = -1
360
361
362 j1 = s.Prog(x86.AJNE)
363 j1.To.Type = obj.TYPE_BRANCH
364
365
366
367 n1 := s.Prog(opNEG)
368 n1.To.Type = obj.TYPE_REG
369 n1.To.Reg = x86.REG_AX
370
371
372 opregreg(s, x86.AXORL, x86.REG_DX, x86.REG_DX)
373
374
375
376
377
378 j2 = s.Prog(obj.AJMP)
379 j2.To.Type = obj.TYPE_BRANCH
380 }
381
382
383 p := s.Prog(opSXD)
384 if j1 != nil {
385 j1.To.SetTarget(p)
386 }
387 p = s.Prog(v.Op.Asm())
388 p.From.Type = obj.TYPE_REG
389 p.From.Reg = r
390
391 if j2 != nil {
392 j2.To.SetTarget(s.Pc())
393 }
394
395 case ssa.OpAMD64HMULQ, ssa.OpAMD64HMULL, ssa.OpAMD64HMULQU, ssa.OpAMD64HMULLU:
396
397
398
399
400
401
402 p := s.Prog(v.Op.Asm())
403 p.From.Type = obj.TYPE_REG
404 p.From.Reg = v.Args[1].Reg()
405
406
407
408 if v.Type.Size() == 1 {
409 m := s.Prog(x86.AMOVB)
410 m.From.Type = obj.TYPE_REG
411 m.From.Reg = x86.REG_AH
412 m.To.Type = obj.TYPE_REG
413 m.To.Reg = x86.REG_DX
414 }
415
416 case ssa.OpAMD64MULQU, ssa.OpAMD64MULLU:
417
418
419 p := s.Prog(v.Op.Asm())
420 p.From.Type = obj.TYPE_REG
421 p.From.Reg = v.Args[1].Reg()
422
423 case ssa.OpAMD64MULQU2:
424
425
426 p := s.Prog(v.Op.Asm())
427 p.From.Type = obj.TYPE_REG
428 p.From.Reg = v.Args[1].Reg()
429
430 case ssa.OpAMD64DIVQU2:
431
432
433 p := s.Prog(v.Op.Asm())
434 p.From.Type = obj.TYPE_REG
435 p.From.Reg = v.Args[2].Reg()
436
437 case ssa.OpAMD64AVGQU:
438
439
440
441 p := s.Prog(x86.AADDQ)
442 p.From.Type = obj.TYPE_REG
443 p.To.Type = obj.TYPE_REG
444 p.To.Reg = v.Reg()
445 p.From.Reg = v.Args[1].Reg()
446 p = s.Prog(x86.ARCRQ)
447 p.From.Type = obj.TYPE_CONST
448 p.From.Offset = 1
449 p.To.Type = obj.TYPE_REG
450 p.To.Reg = v.Reg()
451
452 case ssa.OpAMD64ADDQcarry, ssa.OpAMD64ADCQ:
453 r := v.Reg0()
454 r0 := v.Args[0].Reg()
455 r1 := v.Args[1].Reg()
456 switch r {
457 case r0:
458 p := s.Prog(v.Op.Asm())
459 p.From.Type = obj.TYPE_REG
460 p.From.Reg = r1
461 p.To.Type = obj.TYPE_REG
462 p.To.Reg = r
463 case r1:
464 p := s.Prog(v.Op.Asm())
465 p.From.Type = obj.TYPE_REG
466 p.From.Reg = r0
467 p.To.Type = obj.TYPE_REG
468 p.To.Reg = r
469 default:
470 v.Fatalf("output not in same register as an input %s", v.LongString())
471 }
472
473 case ssa.OpAMD64SUBQborrow, ssa.OpAMD64SBBQ:
474 p := s.Prog(v.Op.Asm())
475 p.From.Type = obj.TYPE_REG
476 p.From.Reg = v.Args[1].Reg()
477 p.To.Type = obj.TYPE_REG
478 p.To.Reg = v.Reg0()
479
480 case ssa.OpAMD64ADDQconstcarry, ssa.OpAMD64ADCQconst, ssa.OpAMD64SUBQconstborrow, ssa.OpAMD64SBBQconst:
481 p := s.Prog(v.Op.Asm())
482 p.From.Type = obj.TYPE_CONST
483 p.From.Offset = v.AuxInt
484 p.To.Type = obj.TYPE_REG
485 p.To.Reg = v.Reg0()
486
487 case ssa.OpAMD64ADDQconst, ssa.OpAMD64ADDLconst:
488 r := v.Reg()
489 a := v.Args[0].Reg()
490 if r == a {
491 switch v.AuxInt {
492 case 1:
493 var asm obj.As
494
495
496
497
498
499 if v.Op == ssa.OpAMD64ADDQconst {
500 asm = x86.AINCQ
501 } else {
502 asm = x86.AINCL
503 }
504 p := s.Prog(asm)
505 p.To.Type = obj.TYPE_REG
506 p.To.Reg = r
507 return
508 case -1:
509 var asm obj.As
510 if v.Op == ssa.OpAMD64ADDQconst {
511 asm = x86.ADECQ
512 } else {
513 asm = x86.ADECL
514 }
515 p := s.Prog(asm)
516 p.To.Type = obj.TYPE_REG
517 p.To.Reg = r
518 return
519 case 0x80:
520
521
522 asm := x86.ASUBL
523 if v.Op == ssa.OpAMD64ADDQconst {
524 asm = x86.ASUBQ
525 }
526 p := s.Prog(asm)
527 p.From.Type = obj.TYPE_CONST
528 p.From.Offset = -0x80
529 p.To.Type = obj.TYPE_REG
530 p.To.Reg = r
531 return
532
533 }
534 p := s.Prog(v.Op.Asm())
535 p.From.Type = obj.TYPE_CONST
536 p.From.Offset = v.AuxInt
537 p.To.Type = obj.TYPE_REG
538 p.To.Reg = r
539 return
540 }
541 var asm obj.As
542 if v.Op == ssa.OpAMD64ADDQconst {
543 asm = x86.ALEAQ
544 } else {
545 asm = x86.ALEAL
546 }
547 p := s.Prog(asm)
548 p.From.Type = obj.TYPE_MEM
549 p.From.Reg = a
550 p.From.Offset = v.AuxInt
551 p.To.Type = obj.TYPE_REG
552 p.To.Reg = r
553
554 case ssa.OpAMD64CMOVQEQ, ssa.OpAMD64CMOVLEQ, ssa.OpAMD64CMOVWEQ,
555 ssa.OpAMD64CMOVQLT, ssa.OpAMD64CMOVLLT, ssa.OpAMD64CMOVWLT,
556 ssa.OpAMD64CMOVQNE, ssa.OpAMD64CMOVLNE, ssa.OpAMD64CMOVWNE,
557 ssa.OpAMD64CMOVQGT, ssa.OpAMD64CMOVLGT, ssa.OpAMD64CMOVWGT,
558 ssa.OpAMD64CMOVQLE, ssa.OpAMD64CMOVLLE, ssa.OpAMD64CMOVWLE,
559 ssa.OpAMD64CMOVQGE, ssa.OpAMD64CMOVLGE, ssa.OpAMD64CMOVWGE,
560 ssa.OpAMD64CMOVQHI, ssa.OpAMD64CMOVLHI, ssa.OpAMD64CMOVWHI,
561 ssa.OpAMD64CMOVQLS, ssa.OpAMD64CMOVLLS, ssa.OpAMD64CMOVWLS,
562 ssa.OpAMD64CMOVQCC, ssa.OpAMD64CMOVLCC, ssa.OpAMD64CMOVWCC,
563 ssa.OpAMD64CMOVQCS, ssa.OpAMD64CMOVLCS, ssa.OpAMD64CMOVWCS,
564 ssa.OpAMD64CMOVQGTF, ssa.OpAMD64CMOVLGTF, ssa.OpAMD64CMOVWGTF,
565 ssa.OpAMD64CMOVQGEF, ssa.OpAMD64CMOVLGEF, ssa.OpAMD64CMOVWGEF:
566 p := s.Prog(v.Op.Asm())
567 p.From.Type = obj.TYPE_REG
568 p.From.Reg = v.Args[1].Reg()
569 p.To.Type = obj.TYPE_REG
570 p.To.Reg = v.Reg()
571
572 case ssa.OpAMD64CMOVQNEF, ssa.OpAMD64CMOVLNEF, ssa.OpAMD64CMOVWNEF:
573
574
575
576
577 p := s.Prog(v.Op.Asm())
578 p.From.Type = obj.TYPE_REG
579 p.From.Reg = v.Args[1].Reg()
580 p.To.Type = obj.TYPE_REG
581 p.To.Reg = v.Reg()
582 var q *obj.Prog
583 if v.Op == ssa.OpAMD64CMOVQNEF {
584 q = s.Prog(x86.ACMOVQPS)
585 } else if v.Op == ssa.OpAMD64CMOVLNEF {
586 q = s.Prog(x86.ACMOVLPS)
587 } else {
588 q = s.Prog(x86.ACMOVWPS)
589 }
590 q.From.Type = obj.TYPE_REG
591 q.From.Reg = v.Args[1].Reg()
592 q.To.Type = obj.TYPE_REG
593 q.To.Reg = v.Reg()
594
595 case ssa.OpAMD64CMOVQEQF, ssa.OpAMD64CMOVLEQF, ssa.OpAMD64CMOVWEQF:
596
597
598
599
600
601
602
603
604
605
606
607 t := v.RegTmp()
608 opregreg(s, moveByType(v.Type), t, v.Args[1].Reg())
609
610 p := s.Prog(v.Op.Asm())
611 p.From.Type = obj.TYPE_REG
612 p.From.Reg = v.Reg()
613 p.To.Type = obj.TYPE_REG
614 p.To.Reg = t
615 var q *obj.Prog
616 if v.Op == ssa.OpAMD64CMOVQEQF {
617 q = s.Prog(x86.ACMOVQPC)
618 } else if v.Op == ssa.OpAMD64CMOVLEQF {
619 q = s.Prog(x86.ACMOVLPC)
620 } else {
621 q = s.Prog(x86.ACMOVWPC)
622 }
623 q.From.Type = obj.TYPE_REG
624 q.From.Reg = t
625 q.To.Type = obj.TYPE_REG
626 q.To.Reg = v.Reg()
627
628 case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst:
629 r := v.Reg()
630 p := s.Prog(v.Op.Asm())
631 p.From.Type = obj.TYPE_CONST
632 p.From.Offset = v.AuxInt
633 p.To.Type = obj.TYPE_REG
634 p.To.Reg = r
635 p.AddRestSourceReg(v.Args[0].Reg())
636
637 case ssa.OpAMD64ANDQconst:
638 asm := v.Op.Asm()
639
640
641 if 0 <= v.AuxInt && v.AuxInt <= (1<<32-1) {
642 asm = x86.AANDL
643 }
644 p := s.Prog(asm)
645 p.From.Type = obj.TYPE_CONST
646 p.From.Offset = v.AuxInt
647 p.To.Type = obj.TYPE_REG
648 p.To.Reg = v.Reg()
649
650 case ssa.OpAMD64SUBQconst, ssa.OpAMD64SUBLconst,
651 ssa.OpAMD64ANDLconst,
652 ssa.OpAMD64ORQconst, ssa.OpAMD64ORLconst,
653 ssa.OpAMD64XORQconst, ssa.OpAMD64XORLconst,
654 ssa.OpAMD64SHLQconst, ssa.OpAMD64SHLLconst,
655 ssa.OpAMD64SHRQconst, ssa.OpAMD64SHRLconst, ssa.OpAMD64SHRWconst, ssa.OpAMD64SHRBconst,
656 ssa.OpAMD64SARQconst, ssa.OpAMD64SARLconst, ssa.OpAMD64SARWconst, ssa.OpAMD64SARBconst,
657 ssa.OpAMD64ROLQconst, ssa.OpAMD64ROLLconst, ssa.OpAMD64ROLWconst, ssa.OpAMD64ROLBconst:
658 p := s.Prog(v.Op.Asm())
659 p.From.Type = obj.TYPE_CONST
660 p.From.Offset = v.AuxInt
661 p.To.Type = obj.TYPE_REG
662 p.To.Reg = v.Reg()
663 case ssa.OpAMD64SBBQcarrymask, ssa.OpAMD64SBBLcarrymask:
664 r := v.Reg()
665 p := s.Prog(v.Op.Asm())
666 p.From.Type = obj.TYPE_REG
667 p.From.Reg = r
668 p.To.Type = obj.TYPE_REG
669 p.To.Reg = r
670 case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8,
671 ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8,
672 ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
673 p := s.Prog(v.Op.Asm())
674 memIdx(&p.From, v)
675 o := v.Reg()
676 p.To.Type = obj.TYPE_REG
677 p.To.Reg = o
678 if v.AuxInt != 0 && v.Aux == nil {
679
680 switch v.Op {
681 case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8:
682 p = s.Prog(x86.ALEAQ)
683 case ssa.OpAMD64LEAL1, ssa.OpAMD64LEAL2, ssa.OpAMD64LEAL4, ssa.OpAMD64LEAL8:
684 p = s.Prog(x86.ALEAL)
685 case ssa.OpAMD64LEAW1, ssa.OpAMD64LEAW2, ssa.OpAMD64LEAW4, ssa.OpAMD64LEAW8:
686 p = s.Prog(x86.ALEAW)
687 }
688 p.From.Type = obj.TYPE_MEM
689 p.From.Reg = o
690 p.To.Type = obj.TYPE_REG
691 p.To.Reg = o
692 }
693 ssagen.AddAux(&p.From, v)
694 case ssa.OpAMD64LEAQ, ssa.OpAMD64LEAL, ssa.OpAMD64LEAW:
695 p := s.Prog(v.Op.Asm())
696 p.From.Type = obj.TYPE_MEM
697 p.From.Reg = v.Args[0].Reg()
698 ssagen.AddAux(&p.From, v)
699 p.To.Type = obj.TYPE_REG
700 p.To.Reg = v.Reg()
701 case ssa.OpAMD64CMPQ, ssa.OpAMD64CMPL, ssa.OpAMD64CMPW, ssa.OpAMD64CMPB,
702 ssa.OpAMD64TESTQ, ssa.OpAMD64TESTL, ssa.OpAMD64TESTW, ssa.OpAMD64TESTB,
703 ssa.OpAMD64BTL, ssa.OpAMD64BTQ:
704 opregreg(s, v.Op.Asm(), v.Args[1].Reg(), v.Args[0].Reg())
705 case ssa.OpAMD64UCOMISS, ssa.OpAMD64UCOMISD:
706
707
708 opregreg(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg())
709 case ssa.OpAMD64CMPQconst, ssa.OpAMD64CMPLconst, ssa.OpAMD64CMPWconst, ssa.OpAMD64CMPBconst:
710 p := s.Prog(v.Op.Asm())
711 p.From.Type = obj.TYPE_REG
712 p.From.Reg = v.Args[0].Reg()
713 p.To.Type = obj.TYPE_CONST
714 p.To.Offset = v.AuxInt
715 case ssa.OpAMD64BTLconst, ssa.OpAMD64BTQconst,
716 ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst,
717 ssa.OpAMD64BTSQconst,
718 ssa.OpAMD64BTCQconst,
719 ssa.OpAMD64BTRQconst:
720 op := v.Op
721 if op == ssa.OpAMD64BTQconst && v.AuxInt < 32 {
722
723 op = ssa.OpAMD64BTLconst
724 }
725 p := s.Prog(op.Asm())
726 p.From.Type = obj.TYPE_CONST
727 p.From.Offset = v.AuxInt
728 p.To.Type = obj.TYPE_REG
729 p.To.Reg = v.Args[0].Reg()
730 case ssa.OpAMD64CMPQload, ssa.OpAMD64CMPLload, ssa.OpAMD64CMPWload, ssa.OpAMD64CMPBload:
731 p := s.Prog(v.Op.Asm())
732 p.From.Type = obj.TYPE_MEM
733 p.From.Reg = v.Args[0].Reg()
734 ssagen.AddAux(&p.From, v)
735 p.To.Type = obj.TYPE_REG
736 p.To.Reg = v.Args[1].Reg()
737 case ssa.OpAMD64CMPQconstload, ssa.OpAMD64CMPLconstload, ssa.OpAMD64CMPWconstload, ssa.OpAMD64CMPBconstload:
738 sc := v.AuxValAndOff()
739 p := s.Prog(v.Op.Asm())
740 p.From.Type = obj.TYPE_MEM
741 p.From.Reg = v.Args[0].Reg()
742 ssagen.AddAux2(&p.From, v, sc.Off64())
743 p.To.Type = obj.TYPE_CONST
744 p.To.Offset = sc.Val64()
745 case ssa.OpAMD64CMPQloadidx8, ssa.OpAMD64CMPQloadidx1, ssa.OpAMD64CMPLloadidx4, ssa.OpAMD64CMPLloadidx1, ssa.OpAMD64CMPWloadidx2, ssa.OpAMD64CMPWloadidx1, ssa.OpAMD64CMPBloadidx1:
746 p := s.Prog(v.Op.Asm())
747 memIdx(&p.From, v)
748 ssagen.AddAux(&p.From, v)
749 p.To.Type = obj.TYPE_REG
750 p.To.Reg = v.Args[2].Reg()
751 case ssa.OpAMD64CMPQconstloadidx8, ssa.OpAMD64CMPQconstloadidx1, ssa.OpAMD64CMPLconstloadidx4, ssa.OpAMD64CMPLconstloadidx1, ssa.OpAMD64CMPWconstloadidx2, ssa.OpAMD64CMPWconstloadidx1, ssa.OpAMD64CMPBconstloadidx1:
752 sc := v.AuxValAndOff()
753 p := s.Prog(v.Op.Asm())
754 memIdx(&p.From, v)
755 ssagen.AddAux2(&p.From, v, sc.Off64())
756 p.To.Type = obj.TYPE_CONST
757 p.To.Offset = sc.Val64()
758 case ssa.OpAMD64MOVLconst, ssa.OpAMD64MOVQconst:
759 x := v.Reg()
760
761
762
763 if v.AuxInt == 0 && v.Aux == nil {
764 opregreg(s, x86.AXORL, x, x)
765 break
766 }
767
768 asm := v.Op.Asm()
769
770
771 if 0 <= v.AuxInt && v.AuxInt <= (1<<32-1) {
772
773 asm = x86.AMOVL
774 }
775 p := s.Prog(asm)
776 p.From.Type = obj.TYPE_CONST
777 p.From.Offset = v.AuxInt
778 p.To.Type = obj.TYPE_REG
779 p.To.Reg = x
780 case ssa.OpAMD64MOVSSconst, ssa.OpAMD64MOVSDconst:
781 x := v.Reg()
782 p := s.Prog(v.Op.Asm())
783 p.From.Type = obj.TYPE_FCONST
784 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
785 p.To.Type = obj.TYPE_REG
786 p.To.Reg = x
787 case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVOload,
788 ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload,
789 ssa.OpAMD64MOVBEQload, ssa.OpAMD64MOVBELload:
790 p := s.Prog(v.Op.Asm())
791 p.From.Type = obj.TYPE_MEM
792 p.From.Reg = v.Args[0].Reg()
793 ssagen.AddAux(&p.From, v)
794 p.To.Type = obj.TYPE_REG
795 p.To.Reg = v.Reg()
796 case ssa.OpAMD64MOVBloadidx1, ssa.OpAMD64MOVWloadidx1, ssa.OpAMD64MOVLloadidx1, ssa.OpAMD64MOVQloadidx1, ssa.OpAMD64MOVSSloadidx1, ssa.OpAMD64MOVSDloadidx1,
797 ssa.OpAMD64MOVQloadidx8, ssa.OpAMD64MOVSDloadidx8, ssa.OpAMD64MOVLloadidx8, ssa.OpAMD64MOVLloadidx4, ssa.OpAMD64MOVSSloadidx4, ssa.OpAMD64MOVWloadidx2,
798 ssa.OpAMD64MOVBELloadidx1, ssa.OpAMD64MOVBELloadidx4, ssa.OpAMD64MOVBELloadidx8, ssa.OpAMD64MOVBEQloadidx1, ssa.OpAMD64MOVBEQloadidx8:
799 p := s.Prog(v.Op.Asm())
800 memIdx(&p.From, v)
801 ssagen.AddAux(&p.From, v)
802 p.To.Type = obj.TYPE_REG
803 p.To.Reg = v.Reg()
804 case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore,
805 ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify,
806 ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify,
807 ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore, ssa.OpAMD64MOVBEWstore:
808 p := s.Prog(v.Op.Asm())
809 p.From.Type = obj.TYPE_REG
810 p.From.Reg = v.Args[1].Reg()
811 p.To.Type = obj.TYPE_MEM
812 p.To.Reg = v.Args[0].Reg()
813 ssagen.AddAux(&p.To, v)
814 case ssa.OpAMD64MOVBstoreidx1, ssa.OpAMD64MOVWstoreidx1, ssa.OpAMD64MOVLstoreidx1, ssa.OpAMD64MOVQstoreidx1, ssa.OpAMD64MOVSSstoreidx1, ssa.OpAMD64MOVSDstoreidx1,
815 ssa.OpAMD64MOVQstoreidx8, ssa.OpAMD64MOVSDstoreidx8, ssa.OpAMD64MOVLstoreidx8, ssa.OpAMD64MOVSSstoreidx4, ssa.OpAMD64MOVLstoreidx4, ssa.OpAMD64MOVWstoreidx2,
816 ssa.OpAMD64ADDLmodifyidx1, ssa.OpAMD64ADDLmodifyidx4, ssa.OpAMD64ADDLmodifyidx8, ssa.OpAMD64ADDQmodifyidx1, ssa.OpAMD64ADDQmodifyidx8,
817 ssa.OpAMD64SUBLmodifyidx1, ssa.OpAMD64SUBLmodifyidx4, ssa.OpAMD64SUBLmodifyidx8, ssa.OpAMD64SUBQmodifyidx1, ssa.OpAMD64SUBQmodifyidx8,
818 ssa.OpAMD64ANDLmodifyidx1, ssa.OpAMD64ANDLmodifyidx4, ssa.OpAMD64ANDLmodifyidx8, ssa.OpAMD64ANDQmodifyidx1, ssa.OpAMD64ANDQmodifyidx8,
819 ssa.OpAMD64ORLmodifyidx1, ssa.OpAMD64ORLmodifyidx4, ssa.OpAMD64ORLmodifyidx8, ssa.OpAMD64ORQmodifyidx1, ssa.OpAMD64ORQmodifyidx8,
820 ssa.OpAMD64XORLmodifyidx1, ssa.OpAMD64XORLmodifyidx4, ssa.OpAMD64XORLmodifyidx8, ssa.OpAMD64XORQmodifyidx1, ssa.OpAMD64XORQmodifyidx8,
821 ssa.OpAMD64MOVBEWstoreidx1, ssa.OpAMD64MOVBEWstoreidx2, ssa.OpAMD64MOVBELstoreidx1, ssa.OpAMD64MOVBELstoreidx4, ssa.OpAMD64MOVBELstoreidx8, ssa.OpAMD64MOVBEQstoreidx1, ssa.OpAMD64MOVBEQstoreidx8:
822 p := s.Prog(v.Op.Asm())
823 p.From.Type = obj.TYPE_REG
824 p.From.Reg = v.Args[2].Reg()
825 memIdx(&p.To, v)
826 ssagen.AddAux(&p.To, v)
827 case ssa.OpAMD64ADDQconstmodify, ssa.OpAMD64ADDLconstmodify:
828 sc := v.AuxValAndOff()
829 off := sc.Off64()
830 val := sc.Val()
831 if val == 1 || val == -1 {
832 var asm obj.As
833 if v.Op == ssa.OpAMD64ADDQconstmodify {
834 if val == 1 {
835 asm = x86.AINCQ
836 } else {
837 asm = x86.ADECQ
838 }
839 } else {
840 if val == 1 {
841 asm = x86.AINCL
842 } else {
843 asm = x86.ADECL
844 }
845 }
846 p := s.Prog(asm)
847 p.To.Type = obj.TYPE_MEM
848 p.To.Reg = v.Args[0].Reg()
849 ssagen.AddAux2(&p.To, v, off)
850 break
851 }
852 fallthrough
853 case ssa.OpAMD64ANDQconstmodify, ssa.OpAMD64ANDLconstmodify, ssa.OpAMD64ORQconstmodify, ssa.OpAMD64ORLconstmodify,
854 ssa.OpAMD64XORQconstmodify, ssa.OpAMD64XORLconstmodify,
855 ssa.OpAMD64BTSQconstmodify, ssa.OpAMD64BTRQconstmodify, ssa.OpAMD64BTCQconstmodify:
856 sc := v.AuxValAndOff()
857 off := sc.Off64()
858 val := sc.Val64()
859 p := s.Prog(v.Op.Asm())
860 p.From.Type = obj.TYPE_CONST
861 p.From.Offset = val
862 p.To.Type = obj.TYPE_MEM
863 p.To.Reg = v.Args[0].Reg()
864 ssagen.AddAux2(&p.To, v, off)
865
866 case ssa.OpAMD64MOVQstoreconst, ssa.OpAMD64MOVLstoreconst, ssa.OpAMD64MOVWstoreconst, ssa.OpAMD64MOVBstoreconst:
867 p := s.Prog(v.Op.Asm())
868 p.From.Type = obj.TYPE_CONST
869 sc := v.AuxValAndOff()
870 p.From.Offset = sc.Val64()
871 p.To.Type = obj.TYPE_MEM
872 p.To.Reg = v.Args[0].Reg()
873 ssagen.AddAux2(&p.To, v, sc.Off64())
874 case ssa.OpAMD64MOVOstoreconst:
875 sc := v.AuxValAndOff()
876 if sc.Val() != 0 {
877 v.Fatalf("MOVO for non zero constants not implemented: %s", v.LongString())
878 }
879
880 if s.ABI != obj.ABIInternal {
881
882 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
883 }
884 p := s.Prog(v.Op.Asm())
885 p.From.Type = obj.TYPE_REG
886 p.From.Reg = x86.REG_X15
887 p.To.Type = obj.TYPE_MEM
888 p.To.Reg = v.Args[0].Reg()
889 ssagen.AddAux2(&p.To, v, sc.Off64())
890
891 case ssa.OpAMD64MOVQstoreconstidx1, ssa.OpAMD64MOVQstoreconstidx8, ssa.OpAMD64MOVLstoreconstidx1, ssa.OpAMD64MOVLstoreconstidx4, ssa.OpAMD64MOVWstoreconstidx1, ssa.OpAMD64MOVWstoreconstidx2, ssa.OpAMD64MOVBstoreconstidx1,
892 ssa.OpAMD64ADDLconstmodifyidx1, ssa.OpAMD64ADDLconstmodifyidx4, ssa.OpAMD64ADDLconstmodifyidx8, ssa.OpAMD64ADDQconstmodifyidx1, ssa.OpAMD64ADDQconstmodifyidx8,
893 ssa.OpAMD64ANDLconstmodifyidx1, ssa.OpAMD64ANDLconstmodifyidx4, ssa.OpAMD64ANDLconstmodifyidx8, ssa.OpAMD64ANDQconstmodifyidx1, ssa.OpAMD64ANDQconstmodifyidx8,
894 ssa.OpAMD64ORLconstmodifyidx1, ssa.OpAMD64ORLconstmodifyidx4, ssa.OpAMD64ORLconstmodifyidx8, ssa.OpAMD64ORQconstmodifyidx1, ssa.OpAMD64ORQconstmodifyidx8,
895 ssa.OpAMD64XORLconstmodifyidx1, ssa.OpAMD64XORLconstmodifyidx4, ssa.OpAMD64XORLconstmodifyidx8, ssa.OpAMD64XORQconstmodifyidx1, ssa.OpAMD64XORQconstmodifyidx8:
896 p := s.Prog(v.Op.Asm())
897 p.From.Type = obj.TYPE_CONST
898 sc := v.AuxValAndOff()
899 p.From.Offset = sc.Val64()
900 switch {
901 case p.As == x86.AADDQ && p.From.Offset == 1:
902 p.As = x86.AINCQ
903 p.From.Type = obj.TYPE_NONE
904 case p.As == x86.AADDQ && p.From.Offset == -1:
905 p.As = x86.ADECQ
906 p.From.Type = obj.TYPE_NONE
907 case p.As == x86.AADDL && p.From.Offset == 1:
908 p.As = x86.AINCL
909 p.From.Type = obj.TYPE_NONE
910 case p.As == x86.AADDL && p.From.Offset == -1:
911 p.As = x86.ADECL
912 p.From.Type = obj.TYPE_NONE
913 }
914 memIdx(&p.To, v)
915 ssagen.AddAux2(&p.To, v, sc.Off64())
916 case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX,
917 ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ,
918 ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS:
919 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg())
920 case ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSL2SS:
921 r := v.Reg()
922
923 opregreg(s, x86.AXORPS, r, r)
924 opregreg(s, v.Op.Asm(), r, v.Args[0].Reg())
925 case ssa.OpAMD64MOVQi2f, ssa.OpAMD64MOVQf2i, ssa.OpAMD64MOVLi2f, ssa.OpAMD64MOVLf2i:
926 var p *obj.Prog
927 switch v.Op {
928 case ssa.OpAMD64MOVQi2f, ssa.OpAMD64MOVQf2i:
929 p = s.Prog(x86.AMOVQ)
930 case ssa.OpAMD64MOVLi2f, ssa.OpAMD64MOVLf2i:
931 p = s.Prog(x86.AMOVL)
932 }
933 p.From.Type = obj.TYPE_REG
934 p.From.Reg = v.Args[0].Reg()
935 p.To.Type = obj.TYPE_REG
936 p.To.Reg = v.Reg()
937 case ssa.OpAMD64ADDQload, ssa.OpAMD64ADDLload, ssa.OpAMD64SUBQload, ssa.OpAMD64SUBLload,
938 ssa.OpAMD64ANDQload, ssa.OpAMD64ANDLload, ssa.OpAMD64ORQload, ssa.OpAMD64ORLload,
939 ssa.OpAMD64XORQload, ssa.OpAMD64XORLload, ssa.OpAMD64ADDSDload, ssa.OpAMD64ADDSSload,
940 ssa.OpAMD64SUBSDload, ssa.OpAMD64SUBSSload, ssa.OpAMD64MULSDload, ssa.OpAMD64MULSSload,
941 ssa.OpAMD64DIVSDload, ssa.OpAMD64DIVSSload:
942 p := s.Prog(v.Op.Asm())
943 p.From.Type = obj.TYPE_MEM
944 p.From.Reg = v.Args[1].Reg()
945 ssagen.AddAux(&p.From, v)
946 p.To.Type = obj.TYPE_REG
947 p.To.Reg = v.Reg()
948 case ssa.OpAMD64ADDLloadidx1, ssa.OpAMD64ADDLloadidx4, ssa.OpAMD64ADDLloadidx8, ssa.OpAMD64ADDQloadidx1, ssa.OpAMD64ADDQloadidx8,
949 ssa.OpAMD64SUBLloadidx1, ssa.OpAMD64SUBLloadidx4, ssa.OpAMD64SUBLloadidx8, ssa.OpAMD64SUBQloadidx1, ssa.OpAMD64SUBQloadidx8,
950 ssa.OpAMD64ANDLloadidx1, ssa.OpAMD64ANDLloadidx4, ssa.OpAMD64ANDLloadidx8, ssa.OpAMD64ANDQloadidx1, ssa.OpAMD64ANDQloadidx8,
951 ssa.OpAMD64ORLloadidx1, ssa.OpAMD64ORLloadidx4, ssa.OpAMD64ORLloadidx8, ssa.OpAMD64ORQloadidx1, ssa.OpAMD64ORQloadidx8,
952 ssa.OpAMD64XORLloadidx1, ssa.OpAMD64XORLloadidx4, ssa.OpAMD64XORLloadidx8, ssa.OpAMD64XORQloadidx1, ssa.OpAMD64XORQloadidx8,
953 ssa.OpAMD64ADDSSloadidx1, ssa.OpAMD64ADDSSloadidx4, ssa.OpAMD64ADDSDloadidx1, ssa.OpAMD64ADDSDloadidx8,
954 ssa.OpAMD64SUBSSloadidx1, ssa.OpAMD64SUBSSloadidx4, ssa.OpAMD64SUBSDloadidx1, ssa.OpAMD64SUBSDloadidx8,
955 ssa.OpAMD64MULSSloadidx1, ssa.OpAMD64MULSSloadidx4, ssa.OpAMD64MULSDloadidx1, ssa.OpAMD64MULSDloadidx8,
956 ssa.OpAMD64DIVSSloadidx1, ssa.OpAMD64DIVSSloadidx4, ssa.OpAMD64DIVSDloadidx1, ssa.OpAMD64DIVSDloadidx8:
957 p := s.Prog(v.Op.Asm())
958
959 r, i := v.Args[1].Reg(), v.Args[2].Reg()
960 p.From.Type = obj.TYPE_MEM
961 p.From.Scale = v.Op.Scale()
962 if p.From.Scale == 1 && i == x86.REG_SP {
963 r, i = i, r
964 }
965 p.From.Reg = r
966 p.From.Index = i
967
968 ssagen.AddAux(&p.From, v)
969 p.To.Type = obj.TYPE_REG
970 p.To.Reg = v.Reg()
971 case ssa.OpAMD64DUFFZERO:
972 if s.ABI != obj.ABIInternal {
973
974 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
975 }
976 off := duffStart(v.AuxInt)
977 adj := duffAdj(v.AuxInt)
978 var p *obj.Prog
979 if adj != 0 {
980 p = s.Prog(x86.ALEAQ)
981 p.From.Type = obj.TYPE_MEM
982 p.From.Offset = adj
983 p.From.Reg = x86.REG_DI
984 p.To.Type = obj.TYPE_REG
985 p.To.Reg = x86.REG_DI
986 }
987 p = s.Prog(obj.ADUFFZERO)
988 p.To.Type = obj.TYPE_ADDR
989 p.To.Sym = ir.Syms.Duffzero
990 p.To.Offset = off
991 case ssa.OpAMD64DUFFCOPY:
992 p := s.Prog(obj.ADUFFCOPY)
993 p.To.Type = obj.TYPE_ADDR
994 p.To.Sym = ir.Syms.Duffcopy
995 if v.AuxInt%16 != 0 {
996 v.Fatalf("bad DUFFCOPY AuxInt %v", v.AuxInt)
997 }
998 p.To.Offset = 14 * (64 - v.AuxInt/16)
999
1000
1001
1002
1003
1004
1005
1006 case ssa.OpCopy:
1007 if v.Type.IsMemory() {
1008 return
1009 }
1010 x := v.Args[0].Reg()
1011 y := v.Reg()
1012 if x != y {
1013 opregreg(s, moveByType(v.Type), y, x)
1014 }
1015 case ssa.OpLoadReg:
1016 if v.Type.IsFlags() {
1017 v.Fatalf("load flags not implemented: %v", v.LongString())
1018 return
1019 }
1020 p := s.Prog(loadByType(v.Type))
1021 ssagen.AddrAuto(&p.From, v.Args[0])
1022 p.To.Type = obj.TYPE_REG
1023 p.To.Reg = v.Reg()
1024
1025 case ssa.OpStoreReg:
1026 if v.Type.IsFlags() {
1027 v.Fatalf("store flags not implemented: %v", v.LongString())
1028 return
1029 }
1030 p := s.Prog(storeByType(v.Type))
1031 p.From.Type = obj.TYPE_REG
1032 p.From.Reg = v.Args[0].Reg()
1033 ssagen.AddrAuto(&p.To, v)
1034 case ssa.OpAMD64LoweredHasCPUFeature:
1035 p := s.Prog(x86.AMOVBLZX)
1036 p.From.Type = obj.TYPE_MEM
1037 ssagen.AddAux(&p.From, v)
1038 p.To.Type = obj.TYPE_REG
1039 p.To.Reg = v.Reg()
1040 case ssa.OpArgIntReg, ssa.OpArgFloatReg:
1041
1042
1043 for _, ap := range v.Block.Func.RegArgs {
1044
1045 addr := ssagen.SpillSlotAddr(ap, x86.REG_SP, v.Block.Func.Config.PtrSize)
1046 s.FuncInfo().AddSpill(
1047 obj.RegSpill{Reg: ap.Reg, Addr: addr, Unspill: loadByType(ap.Type), Spill: storeByType(ap.Type)})
1048 }
1049 v.Block.Func.RegArgs = nil
1050 ssagen.CheckArgReg(v)
1051 case ssa.OpAMD64LoweredGetClosurePtr:
1052
1053 ssagen.CheckLoweredGetClosurePtr(v)
1054 case ssa.OpAMD64LoweredGetG:
1055 if s.ABI == obj.ABIInternal {
1056 v.Fatalf("LoweredGetG should not appear in ABIInternal")
1057 }
1058 r := v.Reg()
1059 getgFromTLS(s, r)
1060 case ssa.OpAMD64CALLstatic, ssa.OpAMD64CALLtail:
1061 if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
1062
1063 if buildcfg.GOOS != "plan9" {
1064 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1065 }
1066
1067 getgFromTLS(s, x86.REG_R14)
1068 }
1069 if v.Op == ssa.OpAMD64CALLtail {
1070 s.TailCall(v)
1071 break
1072 }
1073 s.Call(v)
1074 if s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 {
1075
1076 if buildcfg.GOOS != "plan9" {
1077 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
1078 }
1079
1080 getgFromTLS(s, x86.REG_R14)
1081 }
1082 case ssa.OpAMD64CALLclosure, ssa.OpAMD64CALLinter:
1083 s.Call(v)
1084
1085 case ssa.OpAMD64LoweredGetCallerPC:
1086 p := s.Prog(x86.AMOVQ)
1087 p.From.Type = obj.TYPE_MEM
1088 p.From.Offset = -8
1089 p.From.Name = obj.NAME_PARAM
1090 p.To.Type = obj.TYPE_REG
1091 p.To.Reg = v.Reg()
1092
1093 case ssa.OpAMD64LoweredGetCallerSP:
1094
1095 mov := x86.AMOVQ
1096 if types.PtrSize == 4 {
1097 mov = x86.AMOVL
1098 }
1099 p := s.Prog(mov)
1100 p.From.Type = obj.TYPE_ADDR
1101 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
1102 p.From.Name = obj.NAME_PARAM
1103 p.To.Type = obj.TYPE_REG
1104 p.To.Reg = v.Reg()
1105
1106 case ssa.OpAMD64LoweredWB:
1107 p := s.Prog(obj.ACALL)
1108 p.To.Type = obj.TYPE_MEM
1109 p.To.Name = obj.NAME_EXTERN
1110
1111 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
1112
1113 case ssa.OpAMD64LoweredPanicBoundsA, ssa.OpAMD64LoweredPanicBoundsB, ssa.OpAMD64LoweredPanicBoundsC:
1114 p := s.Prog(obj.ACALL)
1115 p.To.Type = obj.TYPE_MEM
1116 p.To.Name = obj.NAME_EXTERN
1117 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
1118 s.UseArgs(int64(2 * types.PtrSize))
1119
1120 case ssa.OpAMD64NEGQ, ssa.OpAMD64NEGL,
1121 ssa.OpAMD64BSWAPQ, ssa.OpAMD64BSWAPL,
1122 ssa.OpAMD64NOTQ, ssa.OpAMD64NOTL:
1123 p := s.Prog(v.Op.Asm())
1124 p.To.Type = obj.TYPE_REG
1125 p.To.Reg = v.Reg()
1126
1127 case ssa.OpAMD64NEGLflags:
1128 p := s.Prog(v.Op.Asm())
1129 p.To.Type = obj.TYPE_REG
1130 p.To.Reg = v.Reg0()
1131
1132 case ssa.OpAMD64BSFQ, ssa.OpAMD64BSRQ, ssa.OpAMD64BSFL, ssa.OpAMD64BSRL, ssa.OpAMD64SQRTSD, ssa.OpAMD64SQRTSS:
1133 p := s.Prog(v.Op.Asm())
1134 p.From.Type = obj.TYPE_REG
1135 p.From.Reg = v.Args[0].Reg()
1136 p.To.Type = obj.TYPE_REG
1137 switch v.Op {
1138 case ssa.OpAMD64BSFQ, ssa.OpAMD64BSRQ:
1139 p.To.Reg = v.Reg0()
1140 case ssa.OpAMD64BSFL, ssa.OpAMD64BSRL, ssa.OpAMD64SQRTSD, ssa.OpAMD64SQRTSS:
1141 p.To.Reg = v.Reg()
1142 }
1143 case ssa.OpAMD64ROUNDSD:
1144 p := s.Prog(v.Op.Asm())
1145 val := v.AuxInt
1146
1147 if val < 0 || val > 3 {
1148 v.Fatalf("Invalid rounding mode")
1149 }
1150 p.From.Offset = val
1151 p.From.Type = obj.TYPE_CONST
1152 p.AddRestSourceReg(v.Args[0].Reg())
1153 p.To.Type = obj.TYPE_REG
1154 p.To.Reg = v.Reg()
1155 case ssa.OpAMD64POPCNTQ, ssa.OpAMD64POPCNTL,
1156 ssa.OpAMD64TZCNTQ, ssa.OpAMD64TZCNTL,
1157 ssa.OpAMD64LZCNTQ, ssa.OpAMD64LZCNTL:
1158 if v.Args[0].Reg() != v.Reg() {
1159
1160
1161
1162 opregreg(s, x86.AXORL, v.Reg(), v.Reg())
1163 }
1164 p := s.Prog(v.Op.Asm())
1165 p.From.Type = obj.TYPE_REG
1166 p.From.Reg = v.Args[0].Reg()
1167 p.To.Type = obj.TYPE_REG
1168 p.To.Reg = v.Reg()
1169
1170 case ssa.OpAMD64SETEQ, ssa.OpAMD64SETNE,
1171 ssa.OpAMD64SETL, ssa.OpAMD64SETLE,
1172 ssa.OpAMD64SETG, ssa.OpAMD64SETGE,
1173 ssa.OpAMD64SETGF, ssa.OpAMD64SETGEF,
1174 ssa.OpAMD64SETB, ssa.OpAMD64SETBE,
1175 ssa.OpAMD64SETORD, ssa.OpAMD64SETNAN,
1176 ssa.OpAMD64SETA, ssa.OpAMD64SETAE,
1177 ssa.OpAMD64SETO:
1178 p := s.Prog(v.Op.Asm())
1179 p.To.Type = obj.TYPE_REG
1180 p.To.Reg = v.Reg()
1181
1182 case ssa.OpAMD64SETEQstore, ssa.OpAMD64SETNEstore,
1183 ssa.OpAMD64SETLstore, ssa.OpAMD64SETLEstore,
1184 ssa.OpAMD64SETGstore, ssa.OpAMD64SETGEstore,
1185 ssa.OpAMD64SETBstore, ssa.OpAMD64SETBEstore,
1186 ssa.OpAMD64SETAstore, ssa.OpAMD64SETAEstore:
1187 p := s.Prog(v.Op.Asm())
1188 p.To.Type = obj.TYPE_MEM
1189 p.To.Reg = v.Args[0].Reg()
1190 ssagen.AddAux(&p.To, v)
1191
1192 case ssa.OpAMD64SETEQstoreidx1, ssa.OpAMD64SETNEstoreidx1,
1193 ssa.OpAMD64SETLstoreidx1, ssa.OpAMD64SETLEstoreidx1,
1194 ssa.OpAMD64SETGstoreidx1, ssa.OpAMD64SETGEstoreidx1,
1195 ssa.OpAMD64SETBstoreidx1, ssa.OpAMD64SETBEstoreidx1,
1196 ssa.OpAMD64SETAstoreidx1, ssa.OpAMD64SETAEstoreidx1:
1197 p := s.Prog(v.Op.Asm())
1198 memIdx(&p.To, v)
1199 ssagen.AddAux(&p.To, v)
1200
1201 case ssa.OpAMD64SETNEF:
1202 t := v.RegTmp()
1203 p := s.Prog(v.Op.Asm())
1204 p.To.Type = obj.TYPE_REG
1205 p.To.Reg = v.Reg()
1206 q := s.Prog(x86.ASETPS)
1207 q.To.Type = obj.TYPE_REG
1208 q.To.Reg = t
1209
1210 opregreg(s, x86.AORL, v.Reg(), t)
1211
1212 case ssa.OpAMD64SETEQF:
1213 t := v.RegTmp()
1214 p := s.Prog(v.Op.Asm())
1215 p.To.Type = obj.TYPE_REG
1216 p.To.Reg = v.Reg()
1217 q := s.Prog(x86.ASETPC)
1218 q.To.Type = obj.TYPE_REG
1219 q.To.Reg = t
1220
1221 opregreg(s, x86.AANDL, v.Reg(), t)
1222
1223 case ssa.OpAMD64InvertFlags:
1224 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
1225 case ssa.OpAMD64FlagEQ, ssa.OpAMD64FlagLT_ULT, ssa.OpAMD64FlagLT_UGT, ssa.OpAMD64FlagGT_ULT, ssa.OpAMD64FlagGT_UGT:
1226 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
1227 case ssa.OpAMD64AddTupleFirst32, ssa.OpAMD64AddTupleFirst64:
1228 v.Fatalf("AddTupleFirst* should never make it to codegen %v", v.LongString())
1229 case ssa.OpAMD64REPSTOSQ:
1230 s.Prog(x86.AREP)
1231 s.Prog(x86.ASTOSQ)
1232 case ssa.OpAMD64REPMOVSQ:
1233 s.Prog(x86.AREP)
1234 s.Prog(x86.AMOVSQ)
1235 case ssa.OpAMD64LoweredNilCheck:
1236
1237
1238
1239
1240
1241
1242 p := s.Prog(x86.ATESTB)
1243 p.From.Type = obj.TYPE_REG
1244 p.From.Reg = x86.REG_AX
1245 p.To.Type = obj.TYPE_MEM
1246 p.To.Reg = v.Args[0].Reg()
1247 if logopt.Enabled() {
1248 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
1249 }
1250 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
1251 base.WarnfAt(v.Pos, "generated nil check")
1252 }
1253 case ssa.OpAMD64MOVBatomicload, ssa.OpAMD64MOVLatomicload, ssa.OpAMD64MOVQatomicload:
1254 p := s.Prog(v.Op.Asm())
1255 p.From.Type = obj.TYPE_MEM
1256 p.From.Reg = v.Args[0].Reg()
1257 ssagen.AddAux(&p.From, v)
1258 p.To.Type = obj.TYPE_REG
1259 p.To.Reg = v.Reg0()
1260 case ssa.OpAMD64XCHGB, ssa.OpAMD64XCHGL, ssa.OpAMD64XCHGQ:
1261 p := s.Prog(v.Op.Asm())
1262 p.From.Type = obj.TYPE_REG
1263 p.From.Reg = v.Reg0()
1264 p.To.Type = obj.TYPE_MEM
1265 p.To.Reg = v.Args[1].Reg()
1266 ssagen.AddAux(&p.To, v)
1267 case ssa.OpAMD64XADDLlock, ssa.OpAMD64XADDQlock:
1268 s.Prog(x86.ALOCK)
1269 p := s.Prog(v.Op.Asm())
1270 p.From.Type = obj.TYPE_REG
1271 p.From.Reg = v.Reg0()
1272 p.To.Type = obj.TYPE_MEM
1273 p.To.Reg = v.Args[1].Reg()
1274 ssagen.AddAux(&p.To, v)
1275 case ssa.OpAMD64CMPXCHGLlock, ssa.OpAMD64CMPXCHGQlock:
1276 if v.Args[1].Reg() != x86.REG_AX {
1277 v.Fatalf("input[1] not in AX %s", v.LongString())
1278 }
1279 s.Prog(x86.ALOCK)
1280 p := s.Prog(v.Op.Asm())
1281 p.From.Type = obj.TYPE_REG
1282 p.From.Reg = v.Args[2].Reg()
1283 p.To.Type = obj.TYPE_MEM
1284 p.To.Reg = v.Args[0].Reg()
1285 ssagen.AddAux(&p.To, v)
1286 p = s.Prog(x86.ASETEQ)
1287 p.To.Type = obj.TYPE_REG
1288 p.To.Reg = v.Reg0()
1289 case ssa.OpAMD64ANDBlock, ssa.OpAMD64ANDLlock, ssa.OpAMD64ORBlock, ssa.OpAMD64ORLlock:
1290 s.Prog(x86.ALOCK)
1291 p := s.Prog(v.Op.Asm())
1292 p.From.Type = obj.TYPE_REG
1293 p.From.Reg = v.Args[1].Reg()
1294 p.To.Type = obj.TYPE_MEM
1295 p.To.Reg = v.Args[0].Reg()
1296 ssagen.AddAux(&p.To, v)
1297 case ssa.OpAMD64PrefetchT0, ssa.OpAMD64PrefetchNTA:
1298 p := s.Prog(v.Op.Asm())
1299 p.From.Type = obj.TYPE_MEM
1300 p.From.Reg = v.Args[0].Reg()
1301 case ssa.OpClobber:
1302 p := s.Prog(x86.AMOVL)
1303 p.From.Type = obj.TYPE_CONST
1304 p.From.Offset = 0xdeaddead
1305 p.To.Type = obj.TYPE_MEM
1306 p.To.Reg = x86.REG_SP
1307 ssagen.AddAux(&p.To, v)
1308 p = s.Prog(x86.AMOVL)
1309 p.From.Type = obj.TYPE_CONST
1310 p.From.Offset = 0xdeaddead
1311 p.To.Type = obj.TYPE_MEM
1312 p.To.Reg = x86.REG_SP
1313 ssagen.AddAux(&p.To, v)
1314 p.To.Offset += 4
1315 case ssa.OpClobberReg:
1316 x := uint64(0xdeaddeaddeaddead)
1317 p := s.Prog(x86.AMOVQ)
1318 p.From.Type = obj.TYPE_CONST
1319 p.From.Offset = int64(x)
1320 p.To.Type = obj.TYPE_REG
1321 p.To.Reg = v.Reg()
1322 default:
1323 v.Fatalf("genValue not implemented: %s", v.LongString())
1324 }
1325 }
1326
1327 var blockJump = [...]struct {
1328 asm, invasm obj.As
1329 }{
1330 ssa.BlockAMD64EQ: {x86.AJEQ, x86.AJNE},
1331 ssa.BlockAMD64NE: {x86.AJNE, x86.AJEQ},
1332 ssa.BlockAMD64LT: {x86.AJLT, x86.AJGE},
1333 ssa.BlockAMD64GE: {x86.AJGE, x86.AJLT},
1334 ssa.BlockAMD64LE: {x86.AJLE, x86.AJGT},
1335 ssa.BlockAMD64GT: {x86.AJGT, x86.AJLE},
1336 ssa.BlockAMD64OS: {x86.AJOS, x86.AJOC},
1337 ssa.BlockAMD64OC: {x86.AJOC, x86.AJOS},
1338 ssa.BlockAMD64ULT: {x86.AJCS, x86.AJCC},
1339 ssa.BlockAMD64UGE: {x86.AJCC, x86.AJCS},
1340 ssa.BlockAMD64UGT: {x86.AJHI, x86.AJLS},
1341 ssa.BlockAMD64ULE: {x86.AJLS, x86.AJHI},
1342 ssa.BlockAMD64ORD: {x86.AJPC, x86.AJPS},
1343 ssa.BlockAMD64NAN: {x86.AJPS, x86.AJPC},
1344 }
1345
1346 var eqfJumps = [2][2]ssagen.IndexJump{
1347 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPS, Index: 1}},
1348 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPC, Index: 0}},
1349 }
1350 var nefJumps = [2][2]ssagen.IndexJump{
1351 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPC, Index: 1}},
1352 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPS, Index: 0}},
1353 }
1354
1355 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
1356 switch b.Kind {
1357 case ssa.BlockPlain:
1358 if b.Succs[0].Block() != next {
1359 p := s.Prog(obj.AJMP)
1360 p.To.Type = obj.TYPE_BRANCH
1361 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
1362 }
1363 case ssa.BlockDefer:
1364
1365
1366
1367 p := s.Prog(x86.ATESTL)
1368 p.From.Type = obj.TYPE_REG
1369 p.From.Reg = x86.REG_AX
1370 p.To.Type = obj.TYPE_REG
1371 p.To.Reg = x86.REG_AX
1372 p = s.Prog(x86.AJNE)
1373 p.To.Type = obj.TYPE_BRANCH
1374 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
1375 if b.Succs[0].Block() != next {
1376 p := s.Prog(obj.AJMP)
1377 p.To.Type = obj.TYPE_BRANCH
1378 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
1379 }
1380 case ssa.BlockExit, ssa.BlockRetJmp:
1381 case ssa.BlockRet:
1382 s.Prog(obj.ARET)
1383
1384 case ssa.BlockAMD64EQF:
1385 s.CombJump(b, next, &eqfJumps)
1386
1387 case ssa.BlockAMD64NEF:
1388 s.CombJump(b, next, &nefJumps)
1389
1390 case ssa.BlockAMD64EQ, ssa.BlockAMD64NE,
1391 ssa.BlockAMD64LT, ssa.BlockAMD64GE,
1392 ssa.BlockAMD64LE, ssa.BlockAMD64GT,
1393 ssa.BlockAMD64OS, ssa.BlockAMD64OC,
1394 ssa.BlockAMD64ULT, ssa.BlockAMD64UGT,
1395 ssa.BlockAMD64ULE, ssa.BlockAMD64UGE:
1396 jmp := blockJump[b.Kind]
1397 switch next {
1398 case b.Succs[0].Block():
1399 s.Br(jmp.invasm, b.Succs[1].Block())
1400 case b.Succs[1].Block():
1401 s.Br(jmp.asm, b.Succs[0].Block())
1402 default:
1403 if b.Likely != ssa.BranchUnlikely {
1404 s.Br(jmp.asm, b.Succs[0].Block())
1405 s.Br(obj.AJMP, b.Succs[1].Block())
1406 } else {
1407 s.Br(jmp.invasm, b.Succs[1].Block())
1408 s.Br(obj.AJMP, b.Succs[0].Block())
1409 }
1410 }
1411
1412 case ssa.BlockAMD64JUMPTABLE:
1413
1414 p := s.Prog(obj.AJMP)
1415 p.To.Type = obj.TYPE_MEM
1416 p.To.Reg = b.Controls[1].Reg()
1417 p.To.Index = b.Controls[0].Reg()
1418 p.To.Scale = 8
1419
1420 s.JumpTables = append(s.JumpTables, b)
1421
1422 default:
1423 b.Fatalf("branch not implemented: %s", b.LongString())
1424 }
1425 }
1426
1427 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1428 p := s.Prog(loadByType(t))
1429 p.From.Type = obj.TYPE_MEM
1430 p.From.Name = obj.NAME_AUTO
1431 p.From.Sym = n.Linksym()
1432 p.From.Offset = n.FrameOffset() + off
1433 p.To.Type = obj.TYPE_REG
1434 p.To.Reg = reg
1435 return p
1436 }
1437
1438 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1439 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
1440 p.To.Name = obj.NAME_PARAM
1441 p.To.Sym = n.Linksym()
1442 p.Pos = p.Pos.WithNotStmt()
1443 return p
1444 }
1445
View as plain text