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.OpMIPSCALLtail:
479 s.TailCall(v)
480 case ssa.OpMIPSLoweredWB:
481 p := s.Prog(obj.ACALL)
482 p.To.Type = obj.TYPE_MEM
483 p.To.Name = obj.NAME_EXTERN
484 p.To.Sym = v.Aux.(*obj.LSym)
485 case ssa.OpMIPSLoweredPanicBoundsA, ssa.OpMIPSLoweredPanicBoundsB, ssa.OpMIPSLoweredPanicBoundsC:
486 p := s.Prog(obj.ACALL)
487 p.To.Type = obj.TYPE_MEM
488 p.To.Name = obj.NAME_EXTERN
489 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
490 s.UseArgs(8)
491 case ssa.OpMIPSLoweredPanicExtendA, ssa.OpMIPSLoweredPanicExtendB, ssa.OpMIPSLoweredPanicExtendC:
492 p := s.Prog(obj.ACALL)
493 p.To.Type = obj.TYPE_MEM
494 p.To.Name = obj.NAME_EXTERN
495 p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
496 s.UseArgs(12)
497 case ssa.OpMIPSLoweredAtomicLoad8,
498 ssa.OpMIPSLoweredAtomicLoad32:
499 s.Prog(mips.ASYNC)
500
501 var op obj.As
502 switch v.Op {
503 case ssa.OpMIPSLoweredAtomicLoad8:
504 op = mips.AMOVB
505 case ssa.OpMIPSLoweredAtomicLoad32:
506 op = mips.AMOVW
507 }
508 p := s.Prog(op)
509 p.From.Type = obj.TYPE_MEM
510 p.From.Reg = v.Args[0].Reg()
511 p.To.Type = obj.TYPE_REG
512 p.To.Reg = v.Reg0()
513
514 s.Prog(mips.ASYNC)
515 case ssa.OpMIPSLoweredAtomicStore8,
516 ssa.OpMIPSLoweredAtomicStore32:
517 s.Prog(mips.ASYNC)
518
519 var op obj.As
520 switch v.Op {
521 case ssa.OpMIPSLoweredAtomicStore8:
522 op = mips.AMOVB
523 case ssa.OpMIPSLoweredAtomicStore32:
524 op = mips.AMOVW
525 }
526 p := s.Prog(op)
527 p.From.Type = obj.TYPE_REG
528 p.From.Reg = v.Args[1].Reg()
529 p.To.Type = obj.TYPE_MEM
530 p.To.Reg = v.Args[0].Reg()
531
532 s.Prog(mips.ASYNC)
533 case ssa.OpMIPSLoweredAtomicStorezero:
534 s.Prog(mips.ASYNC)
535
536 p := s.Prog(mips.AMOVW)
537 p.From.Type = obj.TYPE_REG
538 p.From.Reg = mips.REGZERO
539 p.To.Type = obj.TYPE_MEM
540 p.To.Reg = v.Args[0].Reg()
541
542 s.Prog(mips.ASYNC)
543 case ssa.OpMIPSLoweredAtomicExchange:
544
545
546
547
548
549
550 s.Prog(mips.ASYNC)
551
552 p := s.Prog(mips.AMOVW)
553 p.From.Type = obj.TYPE_REG
554 p.From.Reg = v.Args[1].Reg()
555 p.To.Type = obj.TYPE_REG
556 p.To.Reg = mips.REGTMP
557
558 p1 := s.Prog(mips.ALL)
559 p1.From.Type = obj.TYPE_MEM
560 p1.From.Reg = v.Args[0].Reg()
561 p1.To.Type = obj.TYPE_REG
562 p1.To.Reg = v.Reg0()
563
564 p2 := s.Prog(mips.ASC)
565 p2.From.Type = obj.TYPE_REG
566 p2.From.Reg = mips.REGTMP
567 p2.To.Type = obj.TYPE_MEM
568 p2.To.Reg = v.Args[0].Reg()
569
570 p3 := s.Prog(mips.ABEQ)
571 p3.From.Type = obj.TYPE_REG
572 p3.From.Reg = mips.REGTMP
573 p3.To.Type = obj.TYPE_BRANCH
574 p3.To.SetTarget(p)
575
576 s.Prog(mips.ASYNC)
577 case ssa.OpMIPSLoweredAtomicAdd:
578
579
580
581
582
583
584
585 s.Prog(mips.ASYNC)
586
587 p := s.Prog(mips.ALL)
588 p.From.Type = obj.TYPE_MEM
589 p.From.Reg = v.Args[0].Reg()
590 p.To.Type = obj.TYPE_REG
591 p.To.Reg = v.Reg0()
592
593 p1 := s.Prog(mips.AADDU)
594 p1.From.Type = obj.TYPE_REG
595 p1.From.Reg = v.Args[1].Reg()
596 p1.Reg = v.Reg0()
597 p1.To.Type = obj.TYPE_REG
598 p1.To.Reg = mips.REGTMP
599
600 p2 := s.Prog(mips.ASC)
601 p2.From.Type = obj.TYPE_REG
602 p2.From.Reg = mips.REGTMP
603 p2.To.Type = obj.TYPE_MEM
604 p2.To.Reg = v.Args[0].Reg()
605
606 p3 := s.Prog(mips.ABEQ)
607 p3.From.Type = obj.TYPE_REG
608 p3.From.Reg = mips.REGTMP
609 p3.To.Type = obj.TYPE_BRANCH
610 p3.To.SetTarget(p)
611
612 s.Prog(mips.ASYNC)
613
614 p4 := s.Prog(mips.AADDU)
615 p4.From.Type = obj.TYPE_REG
616 p4.From.Reg = v.Args[1].Reg()
617 p4.Reg = v.Reg0()
618 p4.To.Type = obj.TYPE_REG
619 p4.To.Reg = v.Reg0()
620
621 case ssa.OpMIPSLoweredAtomicAddconst:
622
623
624
625
626
627
628
629 s.Prog(mips.ASYNC)
630
631 p := s.Prog(mips.ALL)
632 p.From.Type = obj.TYPE_MEM
633 p.From.Reg = v.Args[0].Reg()
634 p.To.Type = obj.TYPE_REG
635 p.To.Reg = v.Reg0()
636
637 p1 := s.Prog(mips.AADDU)
638 p1.From.Type = obj.TYPE_CONST
639 p1.From.Offset = v.AuxInt
640 p1.Reg = v.Reg0()
641 p1.To.Type = obj.TYPE_REG
642 p1.To.Reg = mips.REGTMP
643
644 p2 := s.Prog(mips.ASC)
645 p2.From.Type = obj.TYPE_REG
646 p2.From.Reg = mips.REGTMP
647 p2.To.Type = obj.TYPE_MEM
648 p2.To.Reg = v.Args[0].Reg()
649
650 p3 := s.Prog(mips.ABEQ)
651 p3.From.Type = obj.TYPE_REG
652 p3.From.Reg = mips.REGTMP
653 p3.To.Type = obj.TYPE_BRANCH
654 p3.To.SetTarget(p)
655
656 s.Prog(mips.ASYNC)
657
658 p4 := s.Prog(mips.AADDU)
659 p4.From.Type = obj.TYPE_CONST
660 p4.From.Offset = v.AuxInt
661 p4.Reg = v.Reg0()
662 p4.To.Type = obj.TYPE_REG
663 p4.To.Reg = v.Reg0()
664
665 case ssa.OpMIPSLoweredAtomicAnd,
666 ssa.OpMIPSLoweredAtomicOr:
667
668
669
670
671
672
673 s.Prog(mips.ASYNC)
674
675 p := s.Prog(mips.ALL)
676 p.From.Type = obj.TYPE_MEM
677 p.From.Reg = v.Args[0].Reg()
678 p.To.Type = obj.TYPE_REG
679 p.To.Reg = mips.REGTMP
680
681 p1 := s.Prog(v.Op.Asm())
682 p1.From.Type = obj.TYPE_REG
683 p1.From.Reg = v.Args[1].Reg()
684 p1.Reg = mips.REGTMP
685 p1.To.Type = obj.TYPE_REG
686 p1.To.Reg = mips.REGTMP
687
688 p2 := s.Prog(mips.ASC)
689 p2.From.Type = obj.TYPE_REG
690 p2.From.Reg = mips.REGTMP
691 p2.To.Type = obj.TYPE_MEM
692 p2.To.Reg = v.Args[0].Reg()
693
694 p3 := s.Prog(mips.ABEQ)
695 p3.From.Type = obj.TYPE_REG
696 p3.From.Reg = mips.REGTMP
697 p3.To.Type = obj.TYPE_BRANCH
698 p3.To.SetTarget(p)
699
700 s.Prog(mips.ASYNC)
701
702 case ssa.OpMIPSLoweredAtomicCas:
703
704
705
706
707
708
709
710
711 p := s.Prog(mips.AMOVW)
712 p.From.Type = obj.TYPE_REG
713 p.From.Reg = mips.REGZERO
714 p.To.Type = obj.TYPE_REG
715 p.To.Reg = v.Reg0()
716
717 s.Prog(mips.ASYNC)
718
719 p1 := s.Prog(mips.ALL)
720 p1.From.Type = obj.TYPE_MEM
721 p1.From.Reg = v.Args[0].Reg()
722 p1.To.Type = obj.TYPE_REG
723 p1.To.Reg = mips.REGTMP
724
725 p2 := s.Prog(mips.ABNE)
726 p2.From.Type = obj.TYPE_REG
727 p2.From.Reg = v.Args[1].Reg()
728 p2.Reg = mips.REGTMP
729 p2.To.Type = obj.TYPE_BRANCH
730
731 p3 := s.Prog(mips.AMOVW)
732 p3.From.Type = obj.TYPE_REG
733 p3.From.Reg = v.Args[2].Reg()
734 p3.To.Type = obj.TYPE_REG
735 p3.To.Reg = v.Reg0()
736
737 p4 := s.Prog(mips.ASC)
738 p4.From.Type = obj.TYPE_REG
739 p4.From.Reg = v.Reg0()
740 p4.To.Type = obj.TYPE_MEM
741 p4.To.Reg = v.Args[0].Reg()
742
743 p5 := s.Prog(mips.ABEQ)
744 p5.From.Type = obj.TYPE_REG
745 p5.From.Reg = v.Reg0()
746 p5.To.Type = obj.TYPE_BRANCH
747 p5.To.SetTarget(p1)
748
749 s.Prog(mips.ASYNC)
750
751 p6 := s.Prog(obj.ANOP)
752 p2.To.SetTarget(p6)
753
754 case ssa.OpMIPSLoweredNilCheck:
755
756 p := s.Prog(mips.AMOVB)
757 p.From.Type = obj.TYPE_MEM
758 p.From.Reg = v.Args[0].Reg()
759 ssagen.AddAux(&p.From, v)
760 p.To.Type = obj.TYPE_REG
761 p.To.Reg = mips.REGTMP
762 if logopt.Enabled() {
763 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
764 }
765 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
766 base.WarnfAt(v.Pos, "generated nil check")
767 }
768 case ssa.OpMIPSFPFlagTrue,
769 ssa.OpMIPSFPFlagFalse:
770
771
772
773 cmov := mips.ACMOVF
774 if v.Op == ssa.OpMIPSFPFlagFalse {
775 cmov = mips.ACMOVT
776 }
777 p := s.Prog(mips.AMOVW)
778 p.From.Type = obj.TYPE_CONST
779 p.From.Offset = 1
780 p.To.Type = obj.TYPE_REG
781 p.To.Reg = v.Reg()
782 p1 := s.Prog(cmov)
783 p1.From.Type = obj.TYPE_REG
784 p1.From.Reg = mips.REGZERO
785 p1.To.Type = obj.TYPE_REG
786 p1.To.Reg = v.Reg()
787
788 case ssa.OpMIPSLoweredGetClosurePtr:
789
790 ssagen.CheckLoweredGetClosurePtr(v)
791 case ssa.OpMIPSLoweredGetCallerSP:
792
793 p := s.Prog(mips.AMOVW)
794 p.From.Type = obj.TYPE_ADDR
795 p.From.Offset = -base.Ctxt.FixedFrameSize()
796 p.From.Name = obj.NAME_PARAM
797 p.To.Type = obj.TYPE_REG
798 p.To.Reg = v.Reg()
799 case ssa.OpMIPSLoweredGetCallerPC:
800 p := s.Prog(obj.AGETCALLERPC)
801 p.To.Type = obj.TYPE_REG
802 p.To.Reg = v.Reg()
803 case ssa.OpClobber, ssa.OpClobberReg:
804
805 default:
806 v.Fatalf("genValue not implemented: %s", v.LongString())
807 }
808 }
809
810 var blockJump = map[ssa.BlockKind]struct {
811 asm, invasm obj.As
812 }{
813 ssa.BlockMIPSEQ: {mips.ABEQ, mips.ABNE},
814 ssa.BlockMIPSNE: {mips.ABNE, mips.ABEQ},
815 ssa.BlockMIPSLTZ: {mips.ABLTZ, mips.ABGEZ},
816 ssa.BlockMIPSGEZ: {mips.ABGEZ, mips.ABLTZ},
817 ssa.BlockMIPSLEZ: {mips.ABLEZ, mips.ABGTZ},
818 ssa.BlockMIPSGTZ: {mips.ABGTZ, mips.ABLEZ},
819 ssa.BlockMIPSFPT: {mips.ABFPT, mips.ABFPF},
820 ssa.BlockMIPSFPF: {mips.ABFPF, mips.ABFPT},
821 }
822
823 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
824 switch b.Kind {
825 case ssa.BlockPlain:
826 if b.Succs[0].Block() != next {
827 p := s.Prog(obj.AJMP)
828 p.To.Type = obj.TYPE_BRANCH
829 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
830 }
831 case ssa.BlockDefer:
832
833
834
835 p := s.Prog(mips.ABNE)
836 p.From.Type = obj.TYPE_REG
837 p.From.Reg = mips.REGZERO
838 p.Reg = mips.REG_R1
839 p.To.Type = obj.TYPE_BRANCH
840 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
841 if b.Succs[0].Block() != next {
842 p := s.Prog(obj.AJMP)
843 p.To.Type = obj.TYPE_BRANCH
844 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
845 }
846 case ssa.BlockExit, ssa.BlockRetJmp:
847 case ssa.BlockRet:
848 s.Prog(obj.ARET)
849 case ssa.BlockMIPSEQ, ssa.BlockMIPSNE,
850 ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ,
851 ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ,
852 ssa.BlockMIPSFPT, ssa.BlockMIPSFPF:
853 jmp := blockJump[b.Kind]
854 var p *obj.Prog
855 switch next {
856 case b.Succs[0].Block():
857 p = s.Br(jmp.invasm, b.Succs[1].Block())
858 case b.Succs[1].Block():
859 p = s.Br(jmp.asm, b.Succs[0].Block())
860 default:
861 if b.Likely != ssa.BranchUnlikely {
862 p = s.Br(jmp.asm, b.Succs[0].Block())
863 s.Br(obj.AJMP, b.Succs[1].Block())
864 } else {
865 p = s.Br(jmp.invasm, b.Succs[1].Block())
866 s.Br(obj.AJMP, b.Succs[0].Block())
867 }
868 }
869 if !b.Controls[0].Type.IsFlags() {
870 p.From.Type = obj.TYPE_REG
871 p.From.Reg = b.Controls[0].Reg()
872 }
873 default:
874 b.Fatalf("branch not implemented: %s", b.LongString())
875 }
876 }
877
View as plain text