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.Op386NEGL,
756 ssa.Op386BSWAPL,
757 ssa.Op386NOTL:
758 p := s.Prog(v.Op.Asm())
759 p.To.Type = obj.TYPE_REG
760 p.To.Reg = v.Reg()
761 case ssa.Op386BSFL, ssa.Op386BSFW,
762 ssa.Op386BSRL, ssa.Op386BSRW,
763 ssa.Op386SQRTSS, ssa.Op386SQRTSD:
764 p := s.Prog(v.Op.Asm())
765 p.From.Type = obj.TYPE_REG
766 p.From.Reg = v.Args[0].Reg()
767 p.To.Type = obj.TYPE_REG
768 p.To.Reg = v.Reg()
769 case ssa.Op386SETEQ, ssa.Op386SETNE,
770 ssa.Op386SETL, ssa.Op386SETLE,
771 ssa.Op386SETG, ssa.Op386SETGE,
772 ssa.Op386SETGF, ssa.Op386SETGEF,
773 ssa.Op386SETB, ssa.Op386SETBE,
774 ssa.Op386SETORD, ssa.Op386SETNAN,
775 ssa.Op386SETA, ssa.Op386SETAE,
776 ssa.Op386SETO:
777 p := s.Prog(v.Op.Asm())
778 p.To.Type = obj.TYPE_REG
779 p.To.Reg = v.Reg()
780
781 case ssa.Op386SETNEF:
782 p := s.Prog(v.Op.Asm())
783 p.To.Type = obj.TYPE_REG
784 p.To.Reg = v.Reg()
785 q := s.Prog(x86.ASETPS)
786 q.To.Type = obj.TYPE_REG
787 q.To.Reg = x86.REG_AX
788 opregreg(s, x86.AORL, v.Reg(), x86.REG_AX)
789
790 case ssa.Op386SETEQF:
791 p := s.Prog(v.Op.Asm())
792 p.To.Type = obj.TYPE_REG
793 p.To.Reg = v.Reg()
794 q := s.Prog(x86.ASETPC)
795 q.To.Type = obj.TYPE_REG
796 q.To.Reg = x86.REG_AX
797 opregreg(s, x86.AANDL, v.Reg(), x86.REG_AX)
798
799 case ssa.Op386InvertFlags:
800 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
801 case ssa.Op386FlagEQ, ssa.Op386FlagLT_ULT, ssa.Op386FlagLT_UGT, ssa.Op386FlagGT_ULT, ssa.Op386FlagGT_UGT:
802 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
803 case ssa.Op386REPSTOSL:
804 s.Prog(x86.AREP)
805 s.Prog(x86.ASTOSL)
806 case ssa.Op386REPMOVSL:
807 s.Prog(x86.AREP)
808 s.Prog(x86.AMOVSL)
809 case ssa.Op386LoweredNilCheck:
810
811
812
813
814
815
816 p := s.Prog(x86.ATESTB)
817 p.From.Type = obj.TYPE_REG
818 p.From.Reg = x86.REG_AX
819 p.To.Type = obj.TYPE_MEM
820 p.To.Reg = v.Args[0].Reg()
821 ssagen.AddAux(&p.To, v)
822 if logopt.Enabled() {
823 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
824 }
825 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
826 base.WarnfAt(v.Pos, "generated nil check")
827 }
828 case ssa.OpClobber:
829 p := s.Prog(x86.AMOVL)
830 p.From.Type = obj.TYPE_CONST
831 p.From.Offset = 0xdeaddead
832 p.To.Type = obj.TYPE_MEM
833 p.To.Reg = x86.REG_SP
834 ssagen.AddAux(&p.To, v)
835 case ssa.OpClobberReg:
836
837 default:
838 v.Fatalf("genValue not implemented: %s", v.LongString())
839 }
840 }
841
842 var blockJump = [...]struct {
843 asm, invasm obj.As
844 }{
845 ssa.Block386EQ: {x86.AJEQ, x86.AJNE},
846 ssa.Block386NE: {x86.AJNE, x86.AJEQ},
847 ssa.Block386LT: {x86.AJLT, x86.AJGE},
848 ssa.Block386GE: {x86.AJGE, x86.AJLT},
849 ssa.Block386LE: {x86.AJLE, x86.AJGT},
850 ssa.Block386GT: {x86.AJGT, x86.AJLE},
851 ssa.Block386OS: {x86.AJOS, x86.AJOC},
852 ssa.Block386OC: {x86.AJOC, x86.AJOS},
853 ssa.Block386ULT: {x86.AJCS, x86.AJCC},
854 ssa.Block386UGE: {x86.AJCC, x86.AJCS},
855 ssa.Block386UGT: {x86.AJHI, x86.AJLS},
856 ssa.Block386ULE: {x86.AJLS, x86.AJHI},
857 ssa.Block386ORD: {x86.AJPC, x86.AJPS},
858 ssa.Block386NAN: {x86.AJPS, x86.AJPC},
859 }
860
861 var eqfJumps = [2][2]ssagen.IndexJump{
862 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPS, Index: 1}},
863 {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPC, Index: 0}},
864 }
865 var nefJumps = [2][2]ssagen.IndexJump{
866 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPC, Index: 1}},
867 {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPS, Index: 0}},
868 }
869
870 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
871 switch b.Kind {
872 case ssa.BlockPlain:
873 if b.Succs[0].Block() != next {
874 p := s.Prog(obj.AJMP)
875 p.To.Type = obj.TYPE_BRANCH
876 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
877 }
878 case ssa.BlockDefer:
879
880
881
882 p := s.Prog(x86.ATESTL)
883 p.From.Type = obj.TYPE_REG
884 p.From.Reg = x86.REG_AX
885 p.To.Type = obj.TYPE_REG
886 p.To.Reg = x86.REG_AX
887 p = s.Prog(x86.AJNE)
888 p.To.Type = obj.TYPE_BRANCH
889 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
890 if b.Succs[0].Block() != next {
891 p := s.Prog(obj.AJMP)
892 p.To.Type = obj.TYPE_BRANCH
893 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
894 }
895 case ssa.BlockExit:
896 case ssa.BlockRet:
897 s.Prog(obj.ARET)
898 case ssa.BlockRetJmp:
899 p := s.Prog(obj.AJMP)
900 p.To.Type = obj.TYPE_MEM
901 p.To.Name = obj.NAME_EXTERN
902 p.To.Sym = b.Aux.(*obj.LSym)
903
904 case ssa.Block386EQF:
905 s.CombJump(b, next, &eqfJumps)
906
907 case ssa.Block386NEF:
908 s.CombJump(b, next, &nefJumps)
909
910 case ssa.Block386EQ, ssa.Block386NE,
911 ssa.Block386LT, ssa.Block386GE,
912 ssa.Block386LE, ssa.Block386GT,
913 ssa.Block386OS, ssa.Block386OC,
914 ssa.Block386ULT, ssa.Block386UGT,
915 ssa.Block386ULE, ssa.Block386UGE:
916 jmp := blockJump[b.Kind]
917 switch next {
918 case b.Succs[0].Block():
919 s.Br(jmp.invasm, b.Succs[1].Block())
920 case b.Succs[1].Block():
921 s.Br(jmp.asm, b.Succs[0].Block())
922 default:
923 if b.Likely != ssa.BranchUnlikely {
924 s.Br(jmp.asm, b.Succs[0].Block())
925 s.Br(obj.AJMP, b.Succs[1].Block())
926 } else {
927 s.Br(jmp.invasm, b.Succs[1].Block())
928 s.Br(obj.AJMP, b.Succs[0].Block())
929 }
930 }
931 default:
932 b.Fatalf("branch not implemented: %s", b.LongString())
933 }
934 }
935
View as plain text