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