1
2
3
4
5 package x86
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/ssa"
15 "cmd/compile/internal/ssagen"
16 "cmd/compile/internal/types"
17 "cmd/internal/obj"
18 "cmd/internal/obj/x86"
19 )
20
21
22 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {
23 flive := b.FlagsLiveAtEnd
24 for _, c := range b.ControlValues() {
25 flive = c.Type.IsFlags() || flive
26 }
27 for i := len(b.Values) - 1; i >= 0; i-- {
28 v := b.Values[i]
29 if flive && v.Op == ssa.Op386MOVLconst {
30
31 v.Aux = v
32 }
33 if v.Type.IsFlags() {
34 flive = false
35 }
36 for _, a := range v.Args {
37 if a.Type.IsFlags() {
38 flive = true
39 }
40 }
41 }
42 }
43
44
45 func loadByType(t *types.Type) obj.As {
46
47 if !t.IsFloat() {
48 switch t.Size() {
49 case 1:
50 return x86.AMOVBLZX
51 case 2:
52 return x86.AMOVWLZX
53 }
54 }
55
56 return storeByType(t)
57 }
58
59
60 func storeByType(t *types.Type) obj.As {
61 width := t.Size()
62 if t.IsFloat() {
63 switch width {
64 case 4:
65 return x86.AMOVSS
66 case 8:
67 return x86.AMOVSD
68 }
69 } else {
70 switch width {
71 case 1:
72 return x86.AMOVB
73 case 2:
74 return x86.AMOVW
75 case 4:
76 return x86.AMOVL
77 }
78 }
79 panic("bad store type")
80 }
81
82
83 func moveByType(t *types.Type) obj.As {
84 if t.IsFloat() {
85 switch t.Size() {
86 case 4:
87 return x86.AMOVSS
88 case 8:
89 return x86.AMOVSD
90 default:
91 panic(fmt.Sprintf("bad float register width %d:%s", t.Size(), t))
92 }
93 } else {
94 switch t.Size() {
95 case 1:
96
97 return x86.AMOVL
98 case 2:
99 return x86.AMOVL
100 case 4:
101 return x86.AMOVL
102 default:
103 panic(fmt.Sprintf("bad int register width %d:%s", t.Size(), t))
104 }
105 }
106 }
107
108
109
110
111
112 func opregreg(s *ssagen.State, op obj.As, dest, src int16) *obj.Prog {
113 p := s.Prog(op)
114 p.From.Type = obj.TYPE_REG
115 p.To.Type = obj.TYPE_REG
116 p.To.Reg = dest
117 p.From.Reg = src
118 return p
119 }
120
121 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
122 switch v.Op {
123 case ssa.Op386ADDL:
124 r := v.Reg()
125 r1 := v.Args[0].Reg()
126 r2 := v.Args[1].Reg()
127 switch {
128 case r == r1:
129 p := s.Prog(v.Op.Asm())
130 p.From.Type = obj.TYPE_REG
131 p.From.Reg = r2
132 p.To.Type = obj.TYPE_REG
133 p.To.Reg = r
134 case r == r2:
135 p := s.Prog(v.Op.Asm())
136 p.From.Type = obj.TYPE_REG
137 p.From.Reg = r1
138 p.To.Type = obj.TYPE_REG
139 p.To.Reg = r
140 default:
141 p := s.Prog(x86.ALEAL)
142 p.From.Type = obj.TYPE_MEM
143 p.From.Reg = r1
144 p.From.Scale = 1
145 p.From.Index = r2
146 p.To.Type = obj.TYPE_REG
147 p.To.Reg = r
148 }
149
150
151 case ssa.Op386SUBL,
152 ssa.Op386MULL,
153 ssa.Op386ANDL,
154 ssa.Op386ORL,
155 ssa.Op386XORL,
156 ssa.Op386SHLL,
157 ssa.Op386SHRL, ssa.Op386SHRW, ssa.Op386SHRB,
158 ssa.Op386SARL, ssa.Op386SARW, ssa.Op386SARB,
159 ssa.Op386ADDSS, ssa.Op386ADDSD, ssa.Op386SUBSS, ssa.Op386SUBSD,
160 ssa.Op386MULSS, ssa.Op386MULSD, ssa.Op386DIVSS, ssa.Op386DIVSD,
161 ssa.Op386PXOR,
162 ssa.Op386ADCL,
163 ssa.Op386SBBL:
164 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
165
166 case ssa.Op386ADDLcarry, ssa.Op386SUBLcarry:
167
168 opregreg(s, v.Op.Asm(), v.Reg0(), v.Args[1].Reg())
169
170 case ssa.Op386ADDLconstcarry, ssa.Op386SUBLconstcarry:
171
172 p := s.Prog(v.Op.Asm())
173 p.From.Type = obj.TYPE_CONST
174 p.From.Offset = v.AuxInt
175 p.To.Type = obj.TYPE_REG
176 p.To.Reg = v.Reg0()
177
178 case ssa.Op386DIVL, ssa.Op386DIVW,
179 ssa.Op386DIVLU, ssa.Op386DIVWU,
180 ssa.Op386MODL, ssa.Op386MODW,
181 ssa.Op386MODLU, ssa.Op386MODWU:
182
183
184
185 x := v.Args[1].Reg()
186
187
188
189 var j *obj.Prog
190 if v.Op == ssa.Op386DIVL || v.Op == ssa.Op386DIVW ||
191 v.Op == ssa.Op386MODL || v.Op == ssa.Op386MODW {
192
193 if ssa.DivisionNeedsFixUp(v) {
194 var c *obj.Prog
195 switch v.Op {
196 case ssa.Op386DIVL, ssa.Op386MODL:
197 c = s.Prog(x86.ACMPL)
198 j = s.Prog(x86.AJEQ)
199
200 case ssa.Op386DIVW, ssa.Op386MODW:
201 c = s.Prog(x86.ACMPW)
202 j = s.Prog(x86.AJEQ)
203 }
204 c.From.Type = obj.TYPE_REG
205 c.From.Reg = x
206 c.To.Type = obj.TYPE_CONST
207 c.To.Offset = -1
208
209 j.To.Type = obj.TYPE_BRANCH
210 }
211
212 switch v.Op {
213 case ssa.Op386DIVL, ssa.Op386MODL:
214 s.Prog(x86.ACDQ)
215 case ssa.Op386DIVW, ssa.Op386MODW:
216 s.Prog(x86.ACWD)
217 }
218 }
219
220
221
222 if v.Op == ssa.Op386DIVLU || v.Op == ssa.Op386MODLU ||
223 v.Op == ssa.Op386DIVWU || v.Op == ssa.Op386MODWU {
224 c := s.Prog(x86.AXORL)
225 c.From.Type = obj.TYPE_REG
226 c.From.Reg = x86.REG_DX
227 c.To.Type = obj.TYPE_REG
228 c.To.Reg = x86.REG_DX
229 }
230
231 p := s.Prog(v.Op.Asm())
232 p.From.Type = obj.TYPE_REG
233 p.From.Reg = x
234
235
236 if j != nil {
237 j2 := s.Prog(obj.AJMP)
238 j2.To.Type = obj.TYPE_BRANCH
239
240 var n *obj.Prog
241 if v.Op == ssa.Op386DIVL || v.Op == ssa.Op386DIVW {
242
243 n = s.Prog(x86.ANEGL)
244 n.To.Type = obj.TYPE_REG
245 n.To.Reg = x86.REG_AX
246 } else {
247
248 n = s.Prog(x86.AXORL)
249 n.From.Type = obj.TYPE_REG
250 n.From.Reg = x86.REG_DX
251 n.To.Type = obj.TYPE_REG
252 n.To.Reg = x86.REG_DX
253 }
254
255 j.To.SetTarget(n)
256 j2.To.SetTarget(s.Pc())
257 }
258
259 case ssa.Op386HMULL, ssa.Op386HMULLU:
260
261
262
263
264
265
266 p := s.Prog(v.Op.Asm())
267 p.From.Type = obj.TYPE_REG
268 p.From.Reg = v.Args[1].Reg()
269
270
271
272 if v.Type.Size() == 1 {
273 m := s.Prog(x86.AMOVB)
274 m.From.Type = obj.TYPE_REG
275 m.From.Reg = x86.REG_AH
276 m.To.Type = obj.TYPE_REG
277 m.To.Reg = x86.REG_DX
278 }
279
280 case ssa.Op386MULLU:
281
282
283 p := s.Prog(v.Op.Asm())
284 p.From.Type = obj.TYPE_REG
285 p.From.Reg = v.Args[1].Reg()
286
287 case ssa.Op386MULLQU:
288
289 p := s.Prog(v.Op.Asm())
290 p.From.Type = obj.TYPE_REG
291 p.From.Reg = v.Args[1].Reg()
292
293 case ssa.Op386AVGLU:
294
295
296
297 p := s.Prog(x86.AADDL)
298 p.From.Type = obj.TYPE_REG
299 p.To.Type = obj.TYPE_REG
300 p.To.Reg = v.Reg()
301 p.From.Reg = v.Args[1].Reg()
302 p = s.Prog(x86.ARCRL)
303 p.From.Type = obj.TYPE_CONST
304 p.From.Offset = 1
305 p.To.Type = obj.TYPE_REG
306 p.To.Reg = v.Reg()
307
308 case ssa.Op386ADDLconst:
309 r := v.Reg()
310 a := v.Args[0].Reg()
311 if r == a {
312 if v.AuxInt == 1 {
313 p := s.Prog(x86.AINCL)
314 p.To.Type = obj.TYPE_REG
315 p.To.Reg = r
316 return
317 }
318 if v.AuxInt == -1 {
319 p := s.Prog(x86.ADECL)
320 p.To.Type = obj.TYPE_REG
321 p.To.Reg = r
322 return
323 }
324 p := s.Prog(v.Op.Asm())
325 p.From.Type = obj.TYPE_CONST
326 p.From.Offset = v.AuxInt
327 p.To.Type = obj.TYPE_REG
328 p.To.Reg = r
329 return
330 }
331 p := s.Prog(x86.ALEAL)
332 p.From.Type = obj.TYPE_MEM
333 p.From.Reg = a
334 p.From.Offset = v.AuxInt
335 p.To.Type = obj.TYPE_REG
336 p.To.Reg = r
337
338 case ssa.Op386MULLconst:
339 r := v.Reg()
340 p := s.Prog(v.Op.Asm())
341 p.From.Type = obj.TYPE_CONST
342 p.From.Offset = v.AuxInt
343 p.To.Type = obj.TYPE_REG
344 p.To.Reg = r
345 p.SetFrom3Reg(v.Args[0].Reg())
346
347 case ssa.Op386SUBLconst,
348 ssa.Op386ADCLconst,
349 ssa.Op386SBBLconst,
350 ssa.Op386ANDLconst,
351 ssa.Op386ORLconst,
352 ssa.Op386XORLconst,
353 ssa.Op386SHLLconst,
354 ssa.Op386SHRLconst, ssa.Op386SHRWconst, ssa.Op386SHRBconst,
355 ssa.Op386SARLconst, ssa.Op386SARWconst, ssa.Op386SARBconst,
356 ssa.Op386ROLLconst, ssa.Op386ROLWconst, ssa.Op386ROLBconst:
357 p := s.Prog(v.Op.Asm())
358 p.From.Type = obj.TYPE_CONST
359 p.From.Offset = v.AuxInt
360 p.To.Type = obj.TYPE_REG
361 p.To.Reg = v.Reg()
362 case ssa.Op386SBBLcarrymask:
363 r := v.Reg()
364 p := s.Prog(v.Op.Asm())
365 p.From.Type = obj.TYPE_REG
366 p.From.Reg = r
367 p.To.Type = obj.TYPE_REG
368 p.To.Reg = r
369 case ssa.Op386LEAL1, ssa.Op386LEAL2, ssa.Op386LEAL4, ssa.Op386LEAL8:
370 r := v.Args[0].Reg()
371 i := v.Args[1].Reg()
372 p := s.Prog(x86.ALEAL)
373 switch v.Op {
374 case ssa.Op386LEAL1:
375 p.From.Scale = 1
376 if i == x86.REG_SP {
377 r, i = i, r
378 }
379 case ssa.Op386LEAL2:
380 p.From.Scale = 2
381 case ssa.Op386LEAL4:
382 p.From.Scale = 4
383 case ssa.Op386LEAL8:
384 p.From.Scale = 8
385 }
386 p.From.Type = obj.TYPE_MEM
387 p.From.Reg = r
388 p.From.Index = i
389 ssagen.AddAux(&p.From, v)
390 p.To.Type = obj.TYPE_REG
391 p.To.Reg = v.Reg()
392 case ssa.Op386LEAL:
393 p := s.Prog(x86.ALEAL)
394 p.From.Type = obj.TYPE_MEM
395 p.From.Reg = v.Args[0].Reg()
396 ssagen.AddAux(&p.From, v)
397 p.To.Type = obj.TYPE_REG
398 p.To.Reg = v.Reg()
399 case ssa.Op386CMPL, ssa.Op386CMPW, ssa.Op386CMPB,
400 ssa.Op386TESTL, ssa.Op386TESTW, ssa.Op386TESTB:
401 opregreg(s, v.Op.Asm(), v.Args[1].Reg(), v.Args[0].Reg())
402 case ssa.Op386UCOMISS, ssa.Op386UCOMISD:
403
404
405 opregreg(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg())
406 case ssa.Op386CMPLconst, ssa.Op386CMPWconst, ssa.Op386CMPBconst:
407 p := s.Prog(v.Op.Asm())
408 p.From.Type = obj.TYPE_REG
409 p.From.Reg = v.Args[0].Reg()
410 p.To.Type = obj.TYPE_CONST
411 p.To.Offset = v.AuxInt
412 case ssa.Op386TESTLconst, ssa.Op386TESTWconst, ssa.Op386TESTBconst:
413 p := s.Prog(v.Op.Asm())
414 p.From.Type = obj.TYPE_CONST
415 p.From.Offset = v.AuxInt
416 p.To.Type = obj.TYPE_REG
417 p.To.Reg = v.Args[0].Reg()
418 case ssa.Op386CMPLload, ssa.Op386CMPWload, ssa.Op386CMPBload:
419 p := s.Prog(v.Op.Asm())
420 p.From.Type = obj.TYPE_MEM
421 p.From.Reg = v.Args[0].Reg()
422 ssagen.AddAux(&p.From, v)
423 p.To.Type = obj.TYPE_REG
424 p.To.Reg = v.Args[1].Reg()
425 case ssa.Op386CMPLconstload, ssa.Op386CMPWconstload, ssa.Op386CMPBconstload:
426 sc := v.AuxValAndOff()
427 p := s.Prog(v.Op.Asm())
428 p.From.Type = obj.TYPE_MEM
429 p.From.Reg = v.Args[0].Reg()
430 ssagen.AddAux2(&p.From, v, sc.Off64())
431 p.To.Type = obj.TYPE_CONST
432 p.To.Offset = sc.Val64()
433 case ssa.Op386MOVLconst:
434 x := v.Reg()
435
436
437
438 if v.AuxInt == 0 && v.Aux == nil {
439 p := s.Prog(x86.AXORL)
440 p.From.Type = obj.TYPE_REG
441 p.From.Reg = x
442 p.To.Type = obj.TYPE_REG
443 p.To.Reg = x
444 break
445 }
446
447 p := s.Prog(v.Op.Asm())
448 p.From.Type = obj.TYPE_CONST
449 p.From.Offset = v.AuxInt
450 p.To.Type = obj.TYPE_REG
451 p.To.Reg = x
452 case ssa.Op386MOVSSconst, ssa.Op386MOVSDconst:
453 x := v.Reg()
454 p := s.Prog(v.Op.Asm())
455 p.From.Type = obj.TYPE_FCONST
456 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
457 p.To.Type = obj.TYPE_REG
458 p.To.Reg = x
459 case ssa.Op386MOVSSconst1, ssa.Op386MOVSDconst1:
460 p := s.Prog(x86.ALEAL)
461 p.From.Type = obj.TYPE_MEM
462 p.From.Name = obj.NAME_EXTERN
463 f := math.Float64frombits(uint64(v.AuxInt))
464 if v.Op == ssa.Op386MOVSDconst1 {
465 p.From.Sym = base.Ctxt.Float64Sym(f)
466 } else {
467 p.From.Sym = base.Ctxt.Float32Sym(float32(f))
468 }
469 p.To.Type = obj.TYPE_REG
470 p.To.Reg = v.Reg()
471 case ssa.Op386MOVSSconst2, ssa.Op386MOVSDconst2:
472 p := s.Prog(v.Op.Asm())
473 p.From.Type = obj.TYPE_MEM
474 p.From.Reg = v.Args[0].Reg()
475 p.To.Type = obj.TYPE_REG
476 p.To.Reg = v.Reg()
477
478 case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVLload, ssa.Op386MOVWload, ssa.Op386MOVBload, ssa.Op386MOVBLSXload, ssa.Op386MOVWLSXload:
479 p := s.Prog(v.Op.Asm())
480 p.From.Type = obj.TYPE_MEM
481 p.From.Reg = v.Args[0].Reg()
482 ssagen.AddAux(&p.From, v)
483 p.To.Type = obj.TYPE_REG
484 p.To.Reg = v.Reg()
485 case ssa.Op386MOVBloadidx1, ssa.Op386MOVWloadidx1, ssa.Op386MOVLloadidx1, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1,
486 ssa.Op386MOVSDloadidx8, ssa.Op386MOVLloadidx4, ssa.Op386MOVSSloadidx4, ssa.Op386MOVWloadidx2:
487 r := v.Args[0].Reg()
488 i := v.Args[1].Reg()
489 p := s.Prog(v.Op.Asm())
490 p.From.Type = obj.TYPE_MEM
491 switch v.Op {
492 case ssa.Op386MOVBloadidx1, ssa.Op386MOVWloadidx1, ssa.Op386MOVLloadidx1, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1:
493 if i == x86.REG_SP {
494 r, i = i, r
495 }
496 p.From.Scale = 1
497 case ssa.Op386MOVSDloadidx8:
498 p.From.Scale = 8
499 case ssa.Op386MOVLloadidx4, ssa.Op386MOVSSloadidx4:
500 p.From.Scale = 4
501 case ssa.Op386MOVWloadidx2:
502 p.From.Scale = 2
503 }
504 p.From.Reg = r
505 p.From.Index = i
506 ssagen.AddAux(&p.From, v)
507 p.To.Type = obj.TYPE_REG
508 p.To.Reg = v.Reg()
509 case ssa.Op386ADDLloadidx4, ssa.Op386SUBLloadidx4, ssa.Op386MULLloadidx4,
510 ssa.Op386ANDLloadidx4, ssa.Op386ORLloadidx4, ssa.Op386XORLloadidx4:
511 p := s.Prog(v.Op.Asm())
512 p.From.Type = obj.TYPE_MEM
513 p.From.Reg = v.Args[1].Reg()
514 p.From.Index = v.Args[2].Reg()
515 p.From.Scale = 4
516 ssagen.AddAux(&p.From, v)
517 p.To.Type = obj.TYPE_REG
518 p.To.Reg = v.Reg()
519 case ssa.Op386ADDLload, ssa.Op386SUBLload, ssa.Op386MULLload,
520 ssa.Op386ANDLload, ssa.Op386ORLload, ssa.Op386XORLload,
521 ssa.Op386ADDSDload, ssa.Op386ADDSSload, ssa.Op386SUBSDload, ssa.Op386SUBSSload,
522 ssa.Op386MULSDload, ssa.Op386MULSSload, ssa.Op386DIVSSload, ssa.Op386DIVSDload:
523 p := s.Prog(v.Op.Asm())
524 p.From.Type = obj.TYPE_MEM
525 p.From.Reg = v.Args[1].Reg()
526 ssagen.AddAux(&p.From, v)
527 p.To.Type = obj.TYPE_REG
528 p.To.Reg = v.Reg()
529 case ssa.Op386MOVSSstore, ssa.Op386MOVSDstore, ssa.Op386MOVLstore, ssa.Op386MOVWstore, ssa.Op386MOVBstore,
530 ssa.Op386ADDLmodify, ssa.Op386SUBLmodify, ssa.Op386ANDLmodify, ssa.Op386ORLmodify, ssa.Op386XORLmodify:
531 p := s.Prog(v.Op.Asm())
532 p.From.Type = obj.TYPE_REG
533 p.From.Reg = v.Args[1].Reg()
534 p.To.Type = obj.TYPE_MEM
535 p.To.Reg = v.Args[0].Reg()
536 ssagen.AddAux(&p.To, v)
537 case ssa.Op386ADDLconstmodify:
538 sc := v.AuxValAndOff()
539 val := sc.Val()
540 if val == 1 || val == -1 {
541 var p *obj.Prog
542 if val == 1 {
543 p = s.Prog(x86.AINCL)
544 } else {
545 p = s.Prog(x86.ADECL)
546 }
547 off := sc.Off64()
548 p.To.Type = obj.TYPE_MEM
549 p.To.Reg = v.Args[0].Reg()
550 ssagen.AddAux2(&p.To, v, off)
551 break
552 }
553 fallthrough
554 case ssa.Op386ANDLconstmodify, ssa.Op386ORLconstmodify, ssa.Op386XORLconstmodify:
555 sc := v.AuxValAndOff()
556 off := sc.Off64()
557 val := sc.Val64()
558 p := s.Prog(v.Op.Asm())
559 p.From.Type = obj.TYPE_CONST
560 p.From.Offset = val
561 p.To.Type = obj.TYPE_MEM
562 p.To.Reg = v.Args[0].Reg()
563 ssagen.AddAux2(&p.To, v, off)
564 case ssa.Op386MOVBstoreidx1, ssa.Op386MOVWstoreidx1, ssa.Op386MOVLstoreidx1, ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1,
565 ssa.Op386MOVSDstoreidx8, ssa.Op386MOVSSstoreidx4, ssa.Op386MOVLstoreidx4, ssa.Op386MOVWstoreidx2,
566 ssa.Op386ADDLmodifyidx4, ssa.Op386SUBLmodifyidx4, ssa.Op386ANDLmodifyidx4, ssa.Op386ORLmodifyidx4, ssa.Op386XORLmodifyidx4:
567 r := v.Args[0].Reg()
568 i := v.Args[1].Reg()
569 p := s.Prog(v.Op.Asm())
570 p.From.Type = obj.TYPE_REG
571 p.From.Reg = v.Args[2].Reg()
572 p.To.Type = obj.TYPE_MEM
573 switch v.Op {
574 case ssa.Op386MOVBstoreidx1, ssa.Op386MOVWstoreidx1, ssa.Op386MOVLstoreidx1, ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1:
575 if i == x86.REG_SP {
576 r, i = i, r
577 }
578 p.To.Scale = 1
579 case ssa.Op386MOVSDstoreidx8:
580 p.To.Scale = 8
581 case ssa.Op386MOVSSstoreidx4, ssa.Op386MOVLstoreidx4,
582 ssa.Op386ADDLmodifyidx4, ssa.Op386SUBLmodifyidx4, ssa.Op386ANDLmodifyidx4, ssa.Op386ORLmodifyidx4, ssa.Op386XORLmodifyidx4:
583 p.To.Scale = 4
584 case ssa.Op386MOVWstoreidx2:
585 p.To.Scale = 2
586 }
587 p.To.Reg = r
588 p.To.Index = i
589 ssagen.AddAux(&p.To, v)
590 case ssa.Op386MOVLstoreconst, ssa.Op386MOVWstoreconst, ssa.Op386MOVBstoreconst:
591 p := s.Prog(v.Op.Asm())
592 p.From.Type = obj.TYPE_CONST
593 sc := v.AuxValAndOff()
594 p.From.Offset = sc.Val64()
595 p.To.Type = obj.TYPE_MEM
596 p.To.Reg = v.Args[0].Reg()
597 ssagen.AddAux2(&p.To, v, sc.Off64())
598 case ssa.Op386ADDLconstmodifyidx4:
599 sc := v.AuxValAndOff()
600 val := sc.Val()
601 if val == 1 || val == -1 {
602 var p *obj.Prog
603 if val == 1 {
604 p = s.Prog(x86.AINCL)
605 } else {
606 p = s.Prog(x86.ADECL)
607 }
608 off := sc.Off64()
609 p.To.Type = obj.TYPE_MEM
610 p.To.Reg = v.Args[0].Reg()
611 p.To.Scale = 4
612 p.To.Index = v.Args[1].Reg()
613 ssagen.AddAux2(&p.To, v, off)
614 break
615 }
616 fallthrough
617 case ssa.Op386MOVLstoreconstidx1, ssa.Op386MOVLstoreconstidx4, ssa.Op386MOVWstoreconstidx1, ssa.Op386MOVWstoreconstidx2, ssa.Op386MOVBstoreconstidx1,
618 ssa.Op386ANDLconstmodifyidx4, ssa.Op386ORLconstmodifyidx4, ssa.Op386XORLconstmodifyidx4:
619 p := s.Prog(v.Op.Asm())
620 p.From.Type = obj.TYPE_CONST
621 sc := v.AuxValAndOff()
622 p.From.Offset = sc.Val64()
623 r := v.Args[0].Reg()
624 i := v.Args[1].Reg()
625 switch v.Op {
626 case ssa.Op386MOVBstoreconstidx1, ssa.Op386MOVWstoreconstidx1, ssa.Op386MOVLstoreconstidx1:
627 p.To.Scale = 1
628 if i == x86.REG_SP {
629 r, i = i, r
630 }
631 case ssa.Op386MOVWstoreconstidx2:
632 p.To.Scale = 2
633 case ssa.Op386MOVLstoreconstidx4,
634 ssa.Op386ADDLconstmodifyidx4, ssa.Op386ANDLconstmodifyidx4, ssa.Op386ORLconstmodifyidx4, ssa.Op386XORLconstmodifyidx4:
635 p.To.Scale = 4
636 }
637 p.To.Type = obj.TYPE_MEM
638 p.To.Reg = r
639 p.To.Index = i
640 ssagen.AddAux2(&p.To, v, sc.Off64())
641 case ssa.Op386MOVWLSX, ssa.Op386MOVBLSX, ssa.Op386MOVWLZX, ssa.Op386MOVBLZX,
642 ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD,
643 ssa.Op386CVTTSS2SL, ssa.Op386CVTTSD2SL,
644 ssa.Op386CVTSS2SD, ssa.Op386CVTSD2SS:
645 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg())
646 case ssa.Op386DUFFZERO:
647 p := s.Prog(obj.ADUFFZERO)
648 p.To.Type = obj.TYPE_ADDR
649 p.To.Sym = ir.Syms.Duffzero
650 p.To.Offset = v.AuxInt
651 case ssa.Op386DUFFCOPY:
652 p := s.Prog(obj.ADUFFCOPY)
653 p.To.Type = obj.TYPE_ADDR
654 p.To.Sym = ir.Syms.Duffcopy
655 p.To.Offset = v.AuxInt
656
657 case ssa.OpCopy:
658 if v.Type.IsMemory() {
659 return
660 }
661 x := v.Args[0].Reg()
662 y := v.Reg()
663 if x != y {
664 opregreg(s, moveByType(v.Type), y, x)
665 }
666 case ssa.OpLoadReg:
667 if v.Type.IsFlags() {
668 v.Fatalf("load flags not implemented: %v", v.LongString())
669 return
670 }
671 p := s.Prog(loadByType(v.Type))
672 ssagen.AddrAuto(&p.From, v.Args[0])
673 p.To.Type = obj.TYPE_REG
674 p.To.Reg = v.Reg()
675
676 case ssa.OpStoreReg:
677 if v.Type.IsFlags() {
678 v.Fatalf("store flags not implemented: %v", v.LongString())
679 return
680 }
681 p := s.Prog(storeByType(v.Type))
682 p.From.Type = obj.TYPE_REG
683 p.From.Reg = v.Args[0].Reg()
684 ssagen.AddrAuto(&p.To, v)
685 case ssa.Op386LoweredGetClosurePtr:
686
687 ssagen.CheckLoweredGetClosurePtr(v)
688 case ssa.Op386LoweredGetG:
689 r := v.Reg()
690
691
692 if x86.CanUse1InsnTLS(base.Ctxt) {
693
694 p := s.Prog(x86.AMOVL)
695 p.From.Type = obj.TYPE_MEM
696 p.From.Reg = x86.REG_TLS
697 p.To.Type = obj.TYPE_REG
698 p.To.Reg = r
699 } else {
700
701
702 p := s.Prog(x86.AMOVL)
703 p.From.Type = obj.TYPE_REG
704 p.From.Reg = x86.REG_TLS
705 p.To.Type = obj.TYPE_REG
706 p.To.Reg = r
707 q := s.Prog(x86.AMOVL)
708 q.From.Type = obj.TYPE_MEM
709 q.From.Reg = r
710 q.From.Index = x86.REG_TLS
711 q.From.Scale = 1
712 q.To.Type = obj.TYPE_REG
713 q.To.Reg = r
714 }
715
716 case ssa.Op386LoweredGetCallerPC:
717 p := s.Prog(x86.AMOVL)
718 p.From.Type = obj.TYPE_MEM
719 p.From.Offset = -4
720 p.From.Name = obj.NAME_PARAM
721 p.To.Type = obj.TYPE_REG
722 p.To.Reg = v.Reg()
723
724 case ssa.Op386LoweredGetCallerSP:
725
726 p := s.Prog(x86.AMOVL)
727 p.From.Type = obj.TYPE_ADDR
728 p.From.Offset = -base.Ctxt.FixedFrameSize()
729 p.From.Name = obj.NAME_PARAM
730 p.To.Type = obj.TYPE_REG
731 p.To.Reg = v.Reg()
732
733 case ssa.Op386LoweredWB:
734 p := s.Prog(obj.ACALL)
735 p.To.Type = obj.TYPE_MEM
736 p.To.Name = obj.NAME_EXTERN
737 p.To.Sym = v.Aux.(*obj.LSym)
738
739 case ssa.Op386LoweredPanicBoundsA, ssa.Op386LoweredPanicBoundsB, ssa.Op386LoweredPanicBoundsC:
740 p := s.Prog(obj.ACALL)
741 p.To.Type = obj.TYPE_MEM
742 p.To.Name = obj.NAME_EXTERN
743 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
744 s.UseArgs(8)
745
746 case ssa.Op386LoweredPanicExtendA, ssa.Op386LoweredPanicExtendB, ssa.Op386LoweredPanicExtendC:
747 p := s.Prog(obj.ACALL)
748 p.To.Type = obj.TYPE_MEM
749 p.To.Name = obj.NAME_EXTERN
750 p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
751 s.UseArgs(12)
752
753 case ssa.Op386CALLstatic, ssa.Op386CALLclosure, ssa.Op386CALLinter:
754 s.Call(v)
755 case ssa.Op386CALLtail:
756 s.TailCall(v)
757 case ssa.Op386NEGL,
758 ssa.Op386BSWAPL,
759 ssa.Op386NOTL:
760 p := s.Prog(v.Op.Asm())
761 p.To.Type = obj.TYPE_REG
762 p.To.Reg = v.Reg()
763 case ssa.Op386BSFL, ssa.Op386BSFW,
764 ssa.Op386BSRL, ssa.Op386BSRW,
765 ssa.Op386SQRTSS, ssa.Op386SQRTSD:
766 p := s.Prog(v.Op.Asm())
767 p.From.Type = obj.TYPE_REG
768 p.From.Reg = v.Args[0].Reg()
769 p.To.Type = obj.TYPE_REG
770 p.To.Reg = v.Reg()
771 case ssa.Op386SETEQ, ssa.Op386SETNE,
772 ssa.Op386SETL, ssa.Op386SETLE,
773 ssa.Op386SETG, ssa.Op386SETGE,
774 ssa.Op386SETGF, ssa.Op386SETGEF,
775 ssa.Op386SETB, ssa.Op386SETBE,
776 ssa.Op386SETORD, ssa.Op386SETNAN,
777 ssa.Op386SETA, ssa.Op386SETAE,
778 ssa.Op386SETO:
779 p := s.Prog(v.Op.Asm())
780 p.To.Type = obj.TYPE_REG
781 p.To.Reg = v.Reg()
782
783 case ssa.Op386SETNEF:
784 p := s.Prog(v.Op.Asm())
785 p.To.Type = obj.TYPE_REG
786 p.To.Reg = v.Reg()
787 q := s.Prog(x86.ASETPS)
788 q.To.Type = obj.TYPE_REG
789 q.To.Reg = x86.REG_AX
790 opregreg(s, x86.AORL, v.Reg(), x86.REG_AX)
791
792 case ssa.Op386SETEQF:
793 p := s.Prog(v.Op.Asm())
794 p.To.Type = obj.TYPE_REG
795 p.To.Reg = v.Reg()
796 q := s.Prog(x86.ASETPC)
797 q.To.Type = obj.TYPE_REG
798 q.To.Reg = x86.REG_AX
799 opregreg(s, x86.AANDL, v.Reg(), x86.REG_AX)
800
801 case ssa.Op386InvertFlags:
802 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
803 case ssa.Op386FlagEQ, ssa.Op386FlagLT_ULT, ssa.Op386FlagLT_UGT, ssa.Op386FlagGT_ULT, ssa.Op386FlagGT_UGT:
804 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
805 case ssa.Op386REPSTOSL:
806 s.Prog(x86.AREP)
807 s.Prog(x86.ASTOSL)
808 case ssa.Op386REPMOVSL:
809 s.Prog(x86.AREP)
810 s.Prog(x86.AMOVSL)
811 case ssa.Op386LoweredNilCheck:
812
813
814
815
816
817
818 p := s.Prog(x86.ATESTB)
819 p.From.Type = obj.TYPE_REG
820 p.From.Reg = x86.REG_AX
821 p.To.Type = obj.TYPE_MEM
822 p.To.Reg = v.Args[0].Reg()
823 ssagen.AddAux(&p.To, v)
824 if logopt.Enabled() {
825 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
826 }
827 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
828 base.WarnfAt(v.Pos, "generated nil check")
829 }
830 case ssa.OpClobber:
831 p := s.Prog(x86.AMOVL)
832 p.From.Type = obj.TYPE_CONST
833 p.From.Offset = 0xdeaddead
834 p.To.Type = obj.TYPE_MEM
835 p.To.Reg = x86.REG_SP
836 ssagen.AddAux(&p.To, v)
837 case ssa.OpClobberReg:
838
839 default:
840 v.Fatalf("genValue not implemented: %s", v.LongString())
841 }
842 }
843
844 var blockJump = [...]struct {
845 asm, invasm obj.As
846 }{
847 ssa.Block386EQ: {x86.AJEQ, x86.AJNE},
848 ssa.Block386NE: {x86.AJNE, x86.AJEQ},
849 ssa.Block386LT: {x86.AJLT, x86.AJGE},
850 ssa.Block386GE: {x86.AJGE, x86.AJLT},
851 ssa.Block386LE: {x86.AJLE, x86.AJGT},
852 ssa.Block386GT: {x86.AJGT, x86.AJLE},
853 ssa.Block386OS: {x86.AJOS, x86.AJOC},
854 ssa.Block386OC: {x86.AJOC, x86.AJOS},
855 ssa.Block386ULT: {x86.AJCS, x86.AJCC},
856 ssa.Block386UGE: {x86.AJCC, x86.AJCS},
857 ssa.Block386UGT: {x86.AJHI, x86.AJLS},
858 ssa.Block386ULE: {x86.AJLS, x86.AJHI},
859 ssa.Block386ORD: {x86.AJPC, x86.AJPS},
860 ssa.Block386NAN: {x86.AJPS, x86.AJPC},
861 }
862
863 var eqfJumps = [2][2]ssagen.IndexJump{
864 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPS, Index: 1}},
865 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPC, Index: 0}},
866 }
867 var nefJumps = [2][2]ssagen.IndexJump{
868 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPC, Index: 1}},
869 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPS, Index: 0}},
870 }
871
872 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
873 switch b.Kind {
874 case ssa.BlockPlain:
875 if b.Succs[0].Block() != next {
876 p := s.Prog(obj.AJMP)
877 p.To.Type = obj.TYPE_BRANCH
878 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
879 }
880 case ssa.BlockDefer:
881
882
883
884 p := s.Prog(x86.ATESTL)
885 p.From.Type = obj.TYPE_REG
886 p.From.Reg = x86.REG_AX
887 p.To.Type = obj.TYPE_REG
888 p.To.Reg = x86.REG_AX
889 p = s.Prog(x86.AJNE)
890 p.To.Type = obj.TYPE_BRANCH
891 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
892 if b.Succs[0].Block() != next {
893 p := s.Prog(obj.AJMP)
894 p.To.Type = obj.TYPE_BRANCH
895 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
896 }
897 case ssa.BlockExit, ssa.BlockRetJmp:
898 case ssa.BlockRet:
899 s.Prog(obj.ARET)
900
901 case ssa.Block386EQF:
902 s.CombJump(b, next, &eqfJumps)
903
904 case ssa.Block386NEF:
905 s.CombJump(b, next, &nefJumps)
906
907 case ssa.Block386EQ, ssa.Block386NE,
908 ssa.Block386LT, ssa.Block386GE,
909 ssa.Block386LE, ssa.Block386GT,
910 ssa.Block386OS, ssa.Block386OC,
911 ssa.Block386ULT, ssa.Block386UGT,
912 ssa.Block386ULE, ssa.Block386UGE:
913 jmp := blockJump[b.Kind]
914 switch next {
915 case b.Succs[0].Block():
916 s.Br(jmp.invasm, b.Succs[1].Block())
917 case b.Succs[1].Block():
918 s.Br(jmp.asm, b.Succs[0].Block())
919 default:
920 if b.Likely != ssa.BranchUnlikely {
921 s.Br(jmp.asm, b.Succs[0].Block())
922 s.Br(obj.AJMP, b.Succs[1].Block())
923 } else {
924 s.Br(jmp.invasm, b.Succs[1].Block())
925 s.Br(obj.AJMP, b.Succs[0].Block())
926 }
927 }
928 default:
929 b.Fatalf("branch not implemented: %s", b.LongString())
930 }
931 }
932
View as plain text