Source file src/cmd/compile/internal/mips/ssa.go
1
2
3
4
5 package mips
6
7 import (
8 "math"
9
10 "cmd/compile/internal/gc"
11 "cmd/compile/internal/ssa"
12 "cmd/compile/internal/types"
13 "cmd/internal/obj"
14 "cmd/internal/obj/mips"
15 )
16
17
18 func isFPreg(r int16) bool {
19 return mips.REG_F0 <= r && r <= mips.REG_F31
20 }
21
22
23 func isHILO(r int16) bool {
24 return r == mips.REG_HI || r == mips.REG_LO
25 }
26
27
28 func loadByType(t *types.Type, r int16) obj.As {
29 if isFPreg(r) {
30 if t.Size() == 4 {
31 return mips.AMOVF
32 } else {
33 return mips.AMOVD
34 }
35 } else {
36 switch t.Size() {
37 case 1:
38 if t.IsSigned() {
39 return mips.AMOVB
40 } else {
41 return mips.AMOVBU
42 }
43 case 2:
44 if t.IsSigned() {
45 return mips.AMOVH
46 } else {
47 return mips.AMOVHU
48 }
49 case 4:
50 return mips.AMOVW
51 }
52 }
53 panic("bad load type")
54 }
55
56
57 func storeByType(t *types.Type, r int16) obj.As {
58 if isFPreg(r) {
59 if t.Size() == 4 {
60 return mips.AMOVF
61 } else {
62 return mips.AMOVD
63 }
64 } else {
65 switch t.Size() {
66 case 1:
67 return mips.AMOVB
68 case 2:
69 return mips.AMOVH
70 case 4:
71 return mips.AMOVW
72 }
73 }
74 panic("bad store type")
75 }
76
77 func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
78 switch v.Op {
79 case ssa.OpCopy, ssa.OpMIPSMOVWreg:
80 t := v.Type
81 if t.IsMemory() {
82 return
83 }
84 x := v.Args[0].Reg()
85 y := v.Reg()
86 if x == y {
87 return
88 }
89 as := mips.AMOVW
90 if isFPreg(x) && isFPreg(y) {
91 as = mips.AMOVF
92 if t.Size() == 8 {
93 as = mips.AMOVD
94 }
95 }
96
97 p := s.Prog(as)
98 p.From.Type = obj.TYPE_REG
99 p.From.Reg = x
100 p.To.Type = obj.TYPE_REG
101 p.To.Reg = y
102 if isHILO(x) && isHILO(y) || isHILO(x) && isFPreg(y) || isFPreg(x) && isHILO(y) {
103
104 p.To.Reg = mips.REGTMP
105 p = s.Prog(mips.AMOVW)
106 p.From.Type = obj.TYPE_REG
107 p.From.Reg = mips.REGTMP
108 p.To.Type = obj.TYPE_REG
109 p.To.Reg = y
110 }
111 case ssa.OpMIPSMOVWnop:
112 if v.Reg() != v.Args[0].Reg() {
113 v.Fatalf("input[0] and output not in same register %s", v.LongString())
114 }
115
116 case ssa.OpLoadReg:
117 if v.Type.IsFlags() {
118 v.Fatalf("load flags not implemented: %v", v.LongString())
119 return
120 }
121 r := v.Reg()
122 p := s.Prog(loadByType(v.Type, r))
123 gc.AddrAuto(&p.From, v.Args[0])
124 p.To.Type = obj.TYPE_REG
125 p.To.Reg = r
126 if isHILO(r) {
127
128 p.To.Reg = mips.REGTMP
129 p = s.Prog(mips.AMOVW)
130 p.From.Type = obj.TYPE_REG
131 p.From.Reg = mips.REGTMP
132 p.To.Type = obj.TYPE_REG
133 p.To.Reg = r
134 }
135 case ssa.OpStoreReg:
136 if v.Type.IsFlags() {
137 v.Fatalf("store flags not implemented: %v", v.LongString())
138 return
139 }
140 r := v.Args[0].Reg()
141 if isHILO(r) {
142
143 p := s.Prog(mips.AMOVW)
144 p.From.Type = obj.TYPE_REG
145 p.From.Reg = r
146 p.To.Type = obj.TYPE_REG
147 p.To.Reg = mips.REGTMP
148 r = mips.REGTMP
149 }
150 p := s.Prog(storeByType(v.Type, r))
151 p.From.Type = obj.TYPE_REG
152 p.From.Reg = r
153 gc.AddrAuto(&p.To, v)
154 case ssa.OpMIPSADD,
155 ssa.OpMIPSSUB,
156 ssa.OpMIPSAND,
157 ssa.OpMIPSOR,
158 ssa.OpMIPSXOR,
159 ssa.OpMIPSNOR,
160 ssa.OpMIPSSLL,
161 ssa.OpMIPSSRL,
162 ssa.OpMIPSSRA,
163 ssa.OpMIPSADDF,
164 ssa.OpMIPSADDD,
165 ssa.OpMIPSSUBF,
166 ssa.OpMIPSSUBD,
167 ssa.OpMIPSMULF,
168 ssa.OpMIPSMULD,
169 ssa.OpMIPSDIVF,
170 ssa.OpMIPSDIVD,
171 ssa.OpMIPSMUL:
172 p := s.Prog(v.Op.Asm())
173 p.From.Type = obj.TYPE_REG
174 p.From.Reg = v.Args[1].Reg()
175 p.Reg = v.Args[0].Reg()
176 p.To.Type = obj.TYPE_REG
177 p.To.Reg = v.Reg()
178 case ssa.OpMIPSSGT,
179 ssa.OpMIPSSGTU:
180 p := s.Prog(v.Op.Asm())
181 p.From.Type = obj.TYPE_REG
182 p.From.Reg = v.Args[0].Reg()
183 p.Reg = v.Args[1].Reg()
184 p.To.Type = obj.TYPE_REG
185 p.To.Reg = v.Reg()
186 case ssa.OpMIPSSGTzero,
187 ssa.OpMIPSSGTUzero:
188 p := s.Prog(v.Op.Asm())
189 p.From.Type = obj.TYPE_REG
190 p.From.Reg = v.Args[0].Reg()
191 p.Reg = mips.REGZERO
192 p.To.Type = obj.TYPE_REG
193 p.To.Reg = v.Reg()
194 case ssa.OpMIPSADDconst,
195 ssa.OpMIPSSUBconst,
196 ssa.OpMIPSANDconst,
197 ssa.OpMIPSORconst,
198 ssa.OpMIPSXORconst,
199 ssa.OpMIPSNORconst,
200 ssa.OpMIPSSLLconst,
201 ssa.OpMIPSSRLconst,
202 ssa.OpMIPSSRAconst,
203 ssa.OpMIPSSGTconst,
204 ssa.OpMIPSSGTUconst:
205 p := s.Prog(v.Op.Asm())
206 p.From.Type = obj.TYPE_CONST
207 p.From.Offset = v.AuxInt
208 p.Reg = v.Args[0].Reg()
209 p.To.Type = obj.TYPE_REG
210 p.To.Reg = v.Reg()
211 case ssa.OpMIPSMULT,
212 ssa.OpMIPSMULTU,
213 ssa.OpMIPSDIV,
214 ssa.OpMIPSDIVU:
215
216 p := s.Prog(v.Op.Asm())
217 p.From.Type = obj.TYPE_REG
218 p.From.Reg = v.Args[1].Reg()
219 p.Reg = v.Args[0].Reg()
220 case ssa.OpMIPSMOVWconst:
221 r := v.Reg()
222 p := s.Prog(v.Op.Asm())
223 p.From.Type = obj.TYPE_CONST
224 p.From.Offset = v.AuxInt
225 p.To.Type = obj.TYPE_REG
226 p.To.Reg = r
227 if isFPreg(r) || isHILO(r) {
228
229 p.To.Reg = mips.REGTMP
230 p = s.Prog(mips.AMOVW)
231 p.From.Type = obj.TYPE_REG
232 p.From.Reg = mips.REGTMP
233 p.To.Type = obj.TYPE_REG
234 p.To.Reg = r
235 }
236 case ssa.OpMIPSMOVFconst,
237 ssa.OpMIPSMOVDconst:
238 p := s.Prog(v.Op.Asm())
239 p.From.Type = obj.TYPE_FCONST
240 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
241 p.To.Type = obj.TYPE_REG
242 p.To.Reg = v.Reg()
243 case ssa.OpMIPSCMOVZ:
244 if v.Reg() != v.Args[0].Reg() {
245 v.Fatalf("input[0] and output not in same register %s", v.LongString())
246 }
247 p := s.Prog(v.Op.Asm())
248 p.From.Type = obj.TYPE_REG
249 p.From.Reg = v.Args[2].Reg()
250 p.Reg = v.Args[1].Reg()
251 p.To.Type = obj.TYPE_REG
252 p.To.Reg = v.Reg()
253 case ssa.OpMIPSCMOVZzero:
254 if v.Reg() != v.Args[0].Reg() {
255 v.Fatalf("input[0] and output not in same register %s", v.LongString())
256 }
257 p := s.Prog(v.Op.Asm())
258 p.From.Type = obj.TYPE_REG
259 p.From.Reg = v.Args[1].Reg()
260 p.Reg = mips.REGZERO
261 p.To.Type = obj.TYPE_REG
262 p.To.Reg = v.Reg()
263 case ssa.OpMIPSCMPEQF,
264 ssa.OpMIPSCMPEQD,
265 ssa.OpMIPSCMPGEF,
266 ssa.OpMIPSCMPGED,
267 ssa.OpMIPSCMPGTF,
268 ssa.OpMIPSCMPGTD:
269 p := s.Prog(v.Op.Asm())
270 p.From.Type = obj.TYPE_REG
271 p.From.Reg = v.Args[0].Reg()
272 p.Reg = v.Args[1].Reg()
273 case ssa.OpMIPSMOVWaddr:
274 p := s.Prog(mips.AMOVW)
275 p.From.Type = obj.TYPE_ADDR
276 p.From.Reg = v.Args[0].Reg()
277 var wantreg string
278
279
280
281
282
283 switch v.Aux.(type) {
284 default:
285 v.Fatalf("aux is of unknown type %T", v.Aux)
286 case *obj.LSym:
287 wantreg = "SB"
288 gc.AddAux(&p.From, v)
289 case *gc.Node:
290 wantreg = "SP"
291 gc.AddAux(&p.From, v)
292 case nil:
293
294 wantreg = "SP"
295 p.From.Offset = v.AuxInt
296 }
297 if reg := v.Args[0].RegName(); reg != wantreg {
298 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
299 }
300 p.To.Type = obj.TYPE_REG
301 p.To.Reg = v.Reg()
302 case ssa.OpMIPSMOVBload,
303 ssa.OpMIPSMOVBUload,
304 ssa.OpMIPSMOVHload,
305 ssa.OpMIPSMOVHUload,
306 ssa.OpMIPSMOVWload,
307 ssa.OpMIPSMOVFload,
308 ssa.OpMIPSMOVDload:
309 p := s.Prog(v.Op.Asm())
310 p.From.Type = obj.TYPE_MEM
311 p.From.Reg = v.Args[0].Reg()
312 gc.AddAux(&p.From, v)
313 p.To.Type = obj.TYPE_REG
314 p.To.Reg = v.Reg()
315 case ssa.OpMIPSMOVBstore,
316 ssa.OpMIPSMOVHstore,
317 ssa.OpMIPSMOVWstore,
318 ssa.OpMIPSMOVFstore,
319 ssa.OpMIPSMOVDstore:
320 p := s.Prog(v.Op.Asm())
321 p.From.Type = obj.TYPE_REG
322 p.From.Reg = v.Args[1].Reg()
323 p.To.Type = obj.TYPE_MEM
324 p.To.Reg = v.Args[0].Reg()
325 gc.AddAux(&p.To, v)
326 case ssa.OpMIPSMOVBstorezero,
327 ssa.OpMIPSMOVHstorezero,
328 ssa.OpMIPSMOVWstorezero:
329 p := s.Prog(v.Op.Asm())
330 p.From.Type = obj.TYPE_REG
331 p.From.Reg = mips.REGZERO
332 p.To.Type = obj.TYPE_MEM
333 p.To.Reg = v.Args[0].Reg()
334 gc.AddAux(&p.To, v)
335 case ssa.OpMIPSMOVBreg,
336 ssa.OpMIPSMOVBUreg,
337 ssa.OpMIPSMOVHreg,
338 ssa.OpMIPSMOVHUreg:
339 a := v.Args[0]
340 for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPSMOVWreg || a.Op == ssa.OpMIPSMOVWnop {
341 a = a.Args[0]
342 }
343 if a.Op == ssa.OpLoadReg {
344 t := a.Type
345 switch {
346 case v.Op == ssa.OpMIPSMOVBreg && t.Size() == 1 && t.IsSigned(),
347 v.Op == ssa.OpMIPSMOVBUreg && t.Size() == 1 && !t.IsSigned(),
348 v.Op == ssa.OpMIPSMOVHreg && t.Size() == 2 && t.IsSigned(),
349 v.Op == ssa.OpMIPSMOVHUreg && t.Size() == 2 && !t.IsSigned():
350
351 if v.Reg() == v.Args[0].Reg() {
352 return
353 }
354 p := s.Prog(mips.AMOVW)
355 p.From.Type = obj.TYPE_REG
356 p.From.Reg = v.Args[0].Reg()
357 p.To.Type = obj.TYPE_REG
358 p.To.Reg = v.Reg()
359 return
360 default:
361 }
362 }
363 fallthrough
364 case ssa.OpMIPSMOVWF,
365 ssa.OpMIPSMOVWD,
366 ssa.OpMIPSTRUNCFW,
367 ssa.OpMIPSTRUNCDW,
368 ssa.OpMIPSMOVFD,
369 ssa.OpMIPSMOVDF,
370 ssa.OpMIPSNEGF,
371 ssa.OpMIPSNEGD,
372 ssa.OpMIPSSQRTD,
373 ssa.OpMIPSCLZ:
374 p := s.Prog(v.Op.Asm())
375 p.From.Type = obj.TYPE_REG
376 p.From.Reg = v.Args[0].Reg()
377 p.To.Type = obj.TYPE_REG
378 p.To.Reg = v.Reg()
379 case ssa.OpMIPSNEG:
380
381 p := s.Prog(mips.ASUBU)
382 p.From.Type = obj.TYPE_REG
383 p.From.Reg = v.Args[0].Reg()
384 p.Reg = mips.REGZERO
385 p.To.Type = obj.TYPE_REG
386 p.To.Reg = v.Reg()
387 case ssa.OpMIPSLoweredZero:
388
389
390
391
392
393 var sz int64
394 var mov obj.As
395 switch {
396 case v.AuxInt%4 == 0:
397 sz = 4
398 mov = mips.AMOVW
399 case v.AuxInt%2 == 0:
400 sz = 2
401 mov = mips.AMOVH
402 default:
403 sz = 1
404 mov = mips.AMOVB
405 }
406 p := s.Prog(mips.ASUBU)
407 p.From.Type = obj.TYPE_CONST
408 p.From.Offset = sz
409 p.To.Type = obj.TYPE_REG
410 p.To.Reg = mips.REG_R1
411 p2 := s.Prog(mov)
412 p2.From.Type = obj.TYPE_REG
413 p2.From.Reg = mips.REGZERO
414 p2.To.Type = obj.TYPE_MEM
415 p2.To.Reg = mips.REG_R1
416 p2.To.Offset = sz
417 p3 := s.Prog(mips.AADDU)
418 p3.From.Type = obj.TYPE_CONST
419 p3.From.Offset = sz
420 p3.To.Type = obj.TYPE_REG
421 p3.To.Reg = mips.REG_R1
422 p4 := s.Prog(mips.ABNE)
423 p4.From.Type = obj.TYPE_REG
424 p4.From.Reg = v.Args[1].Reg()
425 p4.Reg = mips.REG_R1
426 p4.To.Type = obj.TYPE_BRANCH
427 gc.Patch(p4, p2)
428 case ssa.OpMIPSLoweredMove:
429
430
431
432
433
434
435
436 var sz int64
437 var mov obj.As
438 switch {
439 case v.AuxInt%4 == 0:
440 sz = 4
441 mov = mips.AMOVW
442 case v.AuxInt%2 == 0:
443 sz = 2
444 mov = mips.AMOVH
445 default:
446 sz = 1
447 mov = mips.AMOVB
448 }
449 p := s.Prog(mips.ASUBU)
450 p.From.Type = obj.TYPE_CONST
451 p.From.Offset = sz
452 p.To.Type = obj.TYPE_REG
453 p.To.Reg = mips.REG_R1
454 p2 := s.Prog(mov)
455 p2.From.Type = obj.TYPE_MEM
456 p2.From.Reg = mips.REG_R1
457 p2.From.Offset = sz
458 p2.To.Type = obj.TYPE_REG
459 p2.To.Reg = mips.REGTMP
460 p3 := s.Prog(mov)
461 p3.From.Type = obj.TYPE_REG
462 p3.From.Reg = mips.REGTMP
463 p3.To.Type = obj.TYPE_MEM
464 p3.To.Reg = mips.REG_R2
465 p4 := s.Prog(mips.AADDU)
466 p4.From.Type = obj.TYPE_CONST
467 p4.From.Offset = sz
468 p4.To.Type = obj.TYPE_REG
469 p4.To.Reg = mips.REG_R1
470 p5 := s.Prog(mips.AADDU)
471 p5.From.Type = obj.TYPE_CONST
472 p5.From.Offset = sz
473 p5.To.Type = obj.TYPE_REG
474 p5.To.Reg = mips.REG_R2
475 p6 := s.Prog(mips.ABNE)
476 p6.From.Type = obj.TYPE_REG
477 p6.From.Reg = v.Args[2].Reg()
478 p6.Reg = mips.REG_R1
479 p6.To.Type = obj.TYPE_BRANCH
480 gc.Patch(p6, p2)
481 case ssa.OpMIPSCALLstatic, ssa.OpMIPSCALLclosure, ssa.OpMIPSCALLinter:
482 s.Call(v)
483 case ssa.OpMIPSLoweredWB:
484 p := s.Prog(obj.ACALL)
485 p.To.Type = obj.TYPE_MEM
486 p.To.Name = obj.NAME_EXTERN
487 p.To.Sym = v.Aux.(*obj.LSym)
488 case ssa.OpMIPSLoweredPanicBoundsA, ssa.OpMIPSLoweredPanicBoundsB, ssa.OpMIPSLoweredPanicBoundsC:
489 p := s.Prog(obj.ACALL)
490 p.To.Type = obj.TYPE_MEM
491 p.To.Name = obj.NAME_EXTERN
492 p.To.Sym = gc.BoundsCheckFunc[v.AuxInt]
493 s.UseArgs(8)
494 case ssa.OpMIPSLoweredPanicExtendA, ssa.OpMIPSLoweredPanicExtendB, ssa.OpMIPSLoweredPanicExtendC:
495 p := s.Prog(obj.ACALL)
496 p.To.Type = obj.TYPE_MEM
497 p.To.Name = obj.NAME_EXTERN
498 p.To.Sym = gc.ExtendCheckFunc[v.AuxInt]
499 s.UseArgs(12)
500 case ssa.OpMIPSLoweredAtomicLoad:
501 s.Prog(mips.ASYNC)
502
503 p := s.Prog(mips.AMOVW)
504 p.From.Type = obj.TYPE_MEM
505 p.From.Reg = v.Args[0].Reg()
506 p.To.Type = obj.TYPE_REG
507 p.To.Reg = v.Reg0()
508
509 s.Prog(mips.ASYNC)
510 case ssa.OpMIPSLoweredAtomicStore:
511 s.Prog(mips.ASYNC)
512
513 p := s.Prog(mips.AMOVW)
514 p.From.Type = obj.TYPE_REG
515 p.From.Reg = v.Args[1].Reg()
516 p.To.Type = obj.TYPE_MEM
517 p.To.Reg = v.Args[0].Reg()
518
519 s.Prog(mips.ASYNC)
520 case ssa.OpMIPSLoweredAtomicStorezero:
521 s.Prog(mips.ASYNC)
522
523 p := s.Prog(mips.AMOVW)
524 p.From.Type = obj.TYPE_REG
525 p.From.Reg = mips.REGZERO
526 p.To.Type = obj.TYPE_MEM
527 p.To.Reg = v.Args[0].Reg()
528
529 s.Prog(mips.ASYNC)
530 case ssa.OpMIPSLoweredAtomicExchange:
531
532
533
534
535
536
537 s.Prog(mips.ASYNC)
538
539 p := s.Prog(mips.AMOVW)
540 p.From.Type = obj.TYPE_REG
541 p.From.Reg = v.Args[1].Reg()
542 p.To.Type = obj.TYPE_REG
543 p.To.Reg = mips.REGTMP
544
545 p1 := s.Prog(mips.ALL)
546 p1.From.Type = obj.TYPE_MEM
547 p1.From.Reg = v.Args[0].Reg()
548 p1.To.Type = obj.TYPE_REG
549 p1.To.Reg = v.Reg0()
550
551 p2 := s.Prog(mips.ASC)
552 p2.From.Type = obj.TYPE_REG
553 p2.From.Reg = mips.REGTMP
554 p2.To.Type = obj.TYPE_MEM
555 p2.To.Reg = v.Args[0].Reg()
556
557 p3 := s.Prog(mips.ABEQ)
558 p3.From.Type = obj.TYPE_REG
559 p3.From.Reg = mips.REGTMP
560 p3.To.Type = obj.TYPE_BRANCH
561 gc.Patch(p3, p)
562
563 s.Prog(mips.ASYNC)
564 case ssa.OpMIPSLoweredAtomicAdd:
565
566
567
568
569
570
571
572 s.Prog(mips.ASYNC)
573
574 p := s.Prog(mips.ALL)
575 p.From.Type = obj.TYPE_MEM
576 p.From.Reg = v.Args[0].Reg()
577 p.To.Type = obj.TYPE_REG
578 p.To.Reg = v.Reg0()
579
580 p1 := s.Prog(mips.AADDU)
581 p1.From.Type = obj.TYPE_REG
582 p1.From.Reg = v.Args[1].Reg()
583 p1.Reg = v.Reg0()
584 p1.To.Type = obj.TYPE_REG
585 p1.To.Reg = mips.REGTMP
586
587 p2 := s.Prog(mips.ASC)
588 p2.From.Type = obj.TYPE_REG
589 p2.From.Reg = mips.REGTMP
590 p2.To.Type = obj.TYPE_MEM
591 p2.To.Reg = v.Args[0].Reg()
592
593 p3 := s.Prog(mips.ABEQ)
594 p3.From.Type = obj.TYPE_REG
595 p3.From.Reg = mips.REGTMP
596 p3.To.Type = obj.TYPE_BRANCH
597 gc.Patch(p3, p)
598
599 s.Prog(mips.ASYNC)
600
601 p4 := s.Prog(mips.AADDU)
602 p4.From.Type = obj.TYPE_REG
603 p4.From.Reg = v.Args[1].Reg()
604 p4.Reg = v.Reg0()
605 p4.To.Type = obj.TYPE_REG
606 p4.To.Reg = v.Reg0()
607
608 case ssa.OpMIPSLoweredAtomicAddconst:
609
610
611
612
613
614
615
616 s.Prog(mips.ASYNC)
617
618 p := s.Prog(mips.ALL)
619 p.From.Type = obj.TYPE_MEM
620 p.From.Reg = v.Args[0].Reg()
621 p.To.Type = obj.TYPE_REG
622 p.To.Reg = v.Reg0()
623
624 p1 := s.Prog(mips.AADDU)
625 p1.From.Type = obj.TYPE_CONST
626 p1.From.Offset = v.AuxInt
627 p1.Reg = v.Reg0()
628 p1.To.Type = obj.TYPE_REG
629 p1.To.Reg = mips.REGTMP
630
631 p2 := s.Prog(mips.ASC)
632 p2.From.Type = obj.TYPE_REG
633 p2.From.Reg = mips.REGTMP
634 p2.To.Type = obj.TYPE_MEM
635 p2.To.Reg = v.Args[0].Reg()
636
637 p3 := s.Prog(mips.ABEQ)
638 p3.From.Type = obj.TYPE_REG
639 p3.From.Reg = mips.REGTMP
640 p3.To.Type = obj.TYPE_BRANCH
641 gc.Patch(p3, p)
642
643 s.Prog(mips.ASYNC)
644
645 p4 := s.Prog(mips.AADDU)
646 p4.From.Type = obj.TYPE_CONST
647 p4.From.Offset = v.AuxInt
648 p4.Reg = v.Reg0()
649 p4.To.Type = obj.TYPE_REG
650 p4.To.Reg = v.Reg0()
651
652 case ssa.OpMIPSLoweredAtomicAnd,
653 ssa.OpMIPSLoweredAtomicOr:
654
655
656
657
658
659
660 s.Prog(mips.ASYNC)
661
662 p := s.Prog(mips.ALL)
663 p.From.Type = obj.TYPE_MEM
664 p.From.Reg = v.Args[0].Reg()
665 p.To.Type = obj.TYPE_REG
666 p.To.Reg = mips.REGTMP
667
668 p1 := s.Prog(v.Op.Asm())
669 p1.From.Type = obj.TYPE_REG
670 p1.From.Reg = v.Args[1].Reg()
671 p1.Reg = mips.REGTMP
672 p1.To.Type = obj.TYPE_REG
673 p1.To.Reg = mips.REGTMP
674
675 p2 := s.Prog(mips.ASC)
676 p2.From.Type = obj.TYPE_REG
677 p2.From.Reg = mips.REGTMP
678 p2.To.Type = obj.TYPE_MEM
679 p2.To.Reg = v.Args[0].Reg()
680
681 p3 := s.Prog(mips.ABEQ)
682 p3.From.Type = obj.TYPE_REG
683 p3.From.Reg = mips.REGTMP
684 p3.To.Type = obj.TYPE_BRANCH
685 gc.Patch(p3, p)
686
687 s.Prog(mips.ASYNC)
688
689 case ssa.OpMIPSLoweredAtomicCas:
690
691
692
693
694
695
696
697
698 p := s.Prog(mips.AMOVW)
699 p.From.Type = obj.TYPE_REG
700 p.From.Reg = mips.REGZERO
701 p.To.Type = obj.TYPE_REG
702 p.To.Reg = v.Reg0()
703
704 s.Prog(mips.ASYNC)
705
706 p1 := s.Prog(mips.ALL)
707 p1.From.Type = obj.TYPE_MEM
708 p1.From.Reg = v.Args[0].Reg()
709 p1.To.Type = obj.TYPE_REG
710 p1.To.Reg = mips.REGTMP
711
712 p2 := s.Prog(mips.ABNE)
713 p2.From.Type = obj.TYPE_REG
714 p2.From.Reg = v.Args[1].Reg()
715 p2.Reg = mips.REGTMP
716 p2.To.Type = obj.TYPE_BRANCH
717
718 p3 := s.Prog(mips.AMOVW)
719 p3.From.Type = obj.TYPE_REG
720 p3.From.Reg = v.Args[2].Reg()
721 p3.To.Type = obj.TYPE_REG
722 p3.To.Reg = v.Reg0()
723
724 p4 := s.Prog(mips.ASC)
725 p4.From.Type = obj.TYPE_REG
726 p4.From.Reg = v.Reg0()
727 p4.To.Type = obj.TYPE_MEM
728 p4.To.Reg = v.Args[0].Reg()
729
730 p5 := s.Prog(mips.ABEQ)
731 p5.From.Type = obj.TYPE_REG
732 p5.From.Reg = v.Reg0()
733 p5.To.Type = obj.TYPE_BRANCH
734 gc.Patch(p5, p1)
735
736 s.Prog(mips.ASYNC)
737
738 p6 := s.Prog(obj.ANOP)
739 gc.Patch(p2, p6)
740
741 case ssa.OpMIPSLoweredNilCheck:
742
743 p := s.Prog(mips.AMOVB)
744 p.From.Type = obj.TYPE_MEM
745 p.From.Reg = v.Args[0].Reg()
746 gc.AddAux(&p.From, v)
747 p.To.Type = obj.TYPE_REG
748 p.To.Reg = mips.REGTMP
749 if gc.Debug_checknil != 0 && v.Pos.Line() > 1 {
750 gc.Warnl(v.Pos, "generated nil check")
751 }
752 case ssa.OpMIPSFPFlagTrue,
753 ssa.OpMIPSFPFlagFalse:
754
755
756
757 cmov := mips.ACMOVF
758 if v.Op == ssa.OpMIPSFPFlagFalse {
759 cmov = mips.ACMOVT
760 }
761 p := s.Prog(mips.AMOVW)
762 p.From.Type = obj.TYPE_CONST
763 p.From.Offset = 1
764 p.To.Type = obj.TYPE_REG
765 p.To.Reg = v.Reg()
766 p1 := s.Prog(cmov)
767 p1.From.Type = obj.TYPE_REG
768 p1.From.Reg = mips.REGZERO
769 p1.To.Type = obj.TYPE_REG
770 p1.To.Reg = v.Reg()
771
772 case ssa.OpMIPSLoweredGetClosurePtr:
773
774 gc.CheckLoweredGetClosurePtr(v)
775 case ssa.OpMIPSLoweredGetCallerSP:
776
777 p := s.Prog(mips.AMOVW)
778 p.From.Type = obj.TYPE_ADDR
779 p.From.Offset = -gc.Ctxt.FixedFrameSize()
780 p.From.Name = obj.NAME_PARAM
781 p.To.Type = obj.TYPE_REG
782 p.To.Reg = v.Reg()
783 case ssa.OpMIPSLoweredGetCallerPC:
784 p := s.Prog(obj.AGETCALLERPC)
785 p.To.Type = obj.TYPE_REG
786 p.To.Reg = v.Reg()
787 case ssa.OpClobber:
788
789 default:
790 v.Fatalf("genValue not implemented: %s", v.LongString())
791 }
792 }
793
794 var blockJump = map[ssa.BlockKind]struct {
795 asm, invasm obj.As
796 }{
797 ssa.BlockMIPSEQ: {mips.ABEQ, mips.ABNE},
798 ssa.BlockMIPSNE: {mips.ABNE, mips.ABEQ},
799 ssa.BlockMIPSLTZ: {mips.ABLTZ, mips.ABGEZ},
800 ssa.BlockMIPSGEZ: {mips.ABGEZ, mips.ABLTZ},
801 ssa.BlockMIPSLEZ: {mips.ABLEZ, mips.ABGTZ},
802 ssa.BlockMIPSGTZ: {mips.ABGTZ, mips.ABLEZ},
803 ssa.BlockMIPSFPT: {mips.ABFPT, mips.ABFPF},
804 ssa.BlockMIPSFPF: {mips.ABFPF, mips.ABFPT},
805 }
806
807 func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
808 switch b.Kind {
809 case ssa.BlockPlain:
810 if b.Succs[0].Block() != next {
811 p := s.Prog(obj.AJMP)
812 p.To.Type = obj.TYPE_BRANCH
813 s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
814 }
815 case ssa.BlockDefer:
816
817
818
819 p := s.Prog(mips.ABNE)
820 p.From.Type = obj.TYPE_REG
821 p.From.Reg = mips.REGZERO
822 p.Reg = mips.REG_R1
823 p.To.Type = obj.TYPE_BRANCH
824 s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()})
825 if b.Succs[0].Block() != next {
826 p := s.Prog(obj.AJMP)
827 p.To.Type = obj.TYPE_BRANCH
828 s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
829 }
830 case ssa.BlockExit:
831 case ssa.BlockRet:
832 s.Prog(obj.ARET)
833 case ssa.BlockRetJmp:
834 p := s.Prog(obj.ARET)
835 p.To.Type = obj.TYPE_MEM
836 p.To.Name = obj.NAME_EXTERN
837 p.To.Sym = b.Aux.(*obj.LSym)
838 case ssa.BlockMIPSEQ, ssa.BlockMIPSNE,
839 ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ,
840 ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ,
841 ssa.BlockMIPSFPT, ssa.BlockMIPSFPF:
842 jmp := blockJump[b.Kind]
843 var p *obj.Prog
844 switch next {
845 case b.Succs[0].Block():
846 p = s.Br(jmp.invasm, b.Succs[1].Block())
847 case b.Succs[1].Block():
848 p = s.Br(jmp.asm, b.Succs[0].Block())
849 default:
850 if b.Likely != ssa.BranchUnlikely {
851 p = s.Br(jmp.asm, b.Succs[0].Block())
852 s.Br(obj.AJMP, b.Succs[1].Block())
853 } else {
854 p = s.Br(jmp.invasm, b.Succs[1].Block())
855 s.Br(obj.AJMP, b.Succs[0].Block())
856 }
857 }
858 if !b.Control.Type.IsFlags() {
859 p.From.Type = obj.TYPE_REG
860 p.From.Reg = b.Control.Reg()
861 }
862 default:
863 b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
864 }
865 }
866
View as plain text