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.OpMIPSMOVWfpgp,
365 ssa.OpMIPSMOVWgpfp,
366 ssa.OpMIPSNEGF,
367 ssa.OpMIPSNEGD,
368 ssa.OpMIPSABSD,
369 ssa.OpMIPSSQRTF,
370 ssa.OpMIPSSQRTD,
371 ssa.OpMIPSCLZ:
372 p := s.Prog(v.Op.Asm())
373 p.From.Type = obj.TYPE_REG
374 p.From.Reg = v.Args[0].Reg()
375 p.To.Type = obj.TYPE_REG
376 p.To.Reg = v.Reg()
377 case ssa.OpMIPSNEG:
378
379 p := s.Prog(mips.ASUBU)
380 p.From.Type = obj.TYPE_REG
381 p.From.Reg = v.Args[0].Reg()
382 p.Reg = mips.REGZERO
383 p.To.Type = obj.TYPE_REG
384 p.To.Reg = v.Reg()
385 case ssa.OpMIPSLoweredZero:
386
387
388
389
390
391 var sz int64
392 var mov obj.As
393 switch {
394 case v.AuxInt%4 == 0:
395 sz = 4
396 mov = mips.AMOVW
397 case v.AuxInt%2 == 0:
398 sz = 2
399 mov = mips.AMOVH
400 default:
401 sz = 1
402 mov = mips.AMOVB
403 }
404 p := s.Prog(mips.ASUBU)
405 p.From.Type = obj.TYPE_CONST
406 p.From.Offset = sz
407 p.To.Type = obj.TYPE_REG
408 p.To.Reg = mips.REG_R1
409 p2 := s.Prog(mov)
410 p2.From.Type = obj.TYPE_REG
411 p2.From.Reg = mips.REGZERO
412 p2.To.Type = obj.TYPE_MEM
413 p2.To.Reg = mips.REG_R1
414 p2.To.Offset = sz
415 p3 := s.Prog(mips.AADDU)
416 p3.From.Type = obj.TYPE_CONST
417 p3.From.Offset = sz
418 p3.To.Type = obj.TYPE_REG
419 p3.To.Reg = mips.REG_R1
420 p4 := s.Prog(mips.ABNE)
421 p4.From.Type = obj.TYPE_REG
422 p4.From.Reg = v.Args[1].Reg()
423 p4.Reg = mips.REG_R1
424 p4.To.Type = obj.TYPE_BRANCH
425 p4.To.SetTarget(p2)
426 case ssa.OpMIPSLoweredMove:
427
428
429
430
431
432
433
434 var sz int64
435 var mov obj.As
436 switch {
437 case v.AuxInt%4 == 0:
438 sz = 4
439 mov = mips.AMOVW
440 case v.AuxInt%2 == 0:
441 sz = 2
442 mov = mips.AMOVH
443 default:
444 sz = 1
445 mov = mips.AMOVB
446 }
447 p := s.Prog(mips.ASUBU)
448 p.From.Type = obj.TYPE_CONST
449 p.From.Offset = sz
450 p.To.Type = obj.TYPE_REG
451 p.To.Reg = mips.REG_R1
452 p2 := s.Prog(mov)
453 p2.From.Type = obj.TYPE_MEM
454 p2.From.Reg = mips.REG_R1
455 p2.From.Offset = sz
456 p2.To.Type = obj.TYPE_REG
457 p2.To.Reg = mips.REGTMP
458 p3 := s.Prog(mov)
459 p3.From.Type = obj.TYPE_REG
460 p3.From.Reg = mips.REGTMP
461 p3.To.Type = obj.TYPE_MEM
462 p3.To.Reg = mips.REG_R2
463 p4 := s.Prog(mips.AADDU)
464 p4.From.Type = obj.TYPE_CONST
465 p4.From.Offset = sz
466 p4.To.Type = obj.TYPE_REG
467 p4.To.Reg = mips.REG_R1
468 p5 := s.Prog(mips.AADDU)
469 p5.From.Type = obj.TYPE_CONST
470 p5.From.Offset = sz
471 p5.To.Type = obj.TYPE_REG
472 p5.To.Reg = mips.REG_R2
473 p6 := s.Prog(mips.ABNE)
474 p6.From.Type = obj.TYPE_REG
475 p6.From.Reg = v.Args[2].Reg()
476 p6.Reg = mips.REG_R1
477 p6.To.Type = obj.TYPE_BRANCH
478 p6.To.SetTarget(p2)
479 case ssa.OpMIPSCALLstatic, ssa.OpMIPSCALLclosure, ssa.OpMIPSCALLinter:
480 s.Call(v)
481 case ssa.OpMIPSCALLtail:
482 s.TailCall(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
488 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
489 case ssa.OpMIPSLoweredPanicBoundsA, ssa.OpMIPSLoweredPanicBoundsB, ssa.OpMIPSLoweredPanicBoundsC:
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.BoundsCheckFunc[v.AuxInt]
494 s.UseArgs(8)
495 case ssa.OpMIPSLoweredPanicExtendA, ssa.OpMIPSLoweredPanicExtendB, ssa.OpMIPSLoweredPanicExtendC:
496 p := s.Prog(obj.ACALL)
497 p.To.Type = obj.TYPE_MEM
498 p.To.Name = obj.NAME_EXTERN
499 p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
500 s.UseArgs(12)
501 case ssa.OpMIPSLoweredAtomicLoad8,
502 ssa.OpMIPSLoweredAtomicLoad32:
503 s.Prog(mips.ASYNC)
504
505 var op obj.As
506 switch v.Op {
507 case ssa.OpMIPSLoweredAtomicLoad8:
508 op = mips.AMOVB
509 case ssa.OpMIPSLoweredAtomicLoad32:
510 op = mips.AMOVW
511 }
512 p := s.Prog(op)
513 p.From.Type = obj.TYPE_MEM
514 p.From.Reg = v.Args[0].Reg()
515 p.To.Type = obj.TYPE_REG
516 p.To.Reg = v.Reg0()
517
518 s.Prog(mips.ASYNC)
519 case ssa.OpMIPSLoweredAtomicStore8,
520 ssa.OpMIPSLoweredAtomicStore32:
521 s.Prog(mips.ASYNC)
522
523 var op obj.As
524 switch v.Op {
525 case ssa.OpMIPSLoweredAtomicStore8:
526 op = mips.AMOVB
527 case ssa.OpMIPSLoweredAtomicStore32:
528 op = mips.AMOVW
529 }
530 p := s.Prog(op)
531 p.From.Type = obj.TYPE_REG
532 p.From.Reg = v.Args[1].Reg()
533 p.To.Type = obj.TYPE_MEM
534 p.To.Reg = v.Args[0].Reg()
535
536 s.Prog(mips.ASYNC)
537 case ssa.OpMIPSLoweredAtomicStorezero:
538 s.Prog(mips.ASYNC)
539
540 p := s.Prog(mips.AMOVW)
541 p.From.Type = obj.TYPE_REG
542 p.From.Reg = mips.REGZERO
543 p.To.Type = obj.TYPE_MEM
544 p.To.Reg = v.Args[0].Reg()
545
546 s.Prog(mips.ASYNC)
547 case ssa.OpMIPSLoweredAtomicExchange:
548
549
550
551
552
553
554 s.Prog(mips.ASYNC)
555
556 p := s.Prog(mips.AMOVW)
557 p.From.Type = obj.TYPE_REG
558 p.From.Reg = v.Args[1].Reg()
559 p.To.Type = obj.TYPE_REG
560 p.To.Reg = mips.REGTMP
561
562 p1 := s.Prog(mips.ALL)
563 p1.From.Type = obj.TYPE_MEM
564 p1.From.Reg = v.Args[0].Reg()
565 p1.To.Type = obj.TYPE_REG
566 p1.To.Reg = v.Reg0()
567
568 p2 := s.Prog(mips.ASC)
569 p2.From.Type = obj.TYPE_REG
570 p2.From.Reg = mips.REGTMP
571 p2.To.Type = obj.TYPE_MEM
572 p2.To.Reg = v.Args[0].Reg()
573
574 p3 := s.Prog(mips.ABEQ)
575 p3.From.Type = obj.TYPE_REG
576 p3.From.Reg = mips.REGTMP
577 p3.To.Type = obj.TYPE_BRANCH
578 p3.To.SetTarget(p)
579
580 s.Prog(mips.ASYNC)
581 case ssa.OpMIPSLoweredAtomicAdd:
582
583
584
585
586
587
588
589 s.Prog(mips.ASYNC)
590
591 p := s.Prog(mips.ALL)
592 p.From.Type = obj.TYPE_MEM
593 p.From.Reg = v.Args[0].Reg()
594 p.To.Type = obj.TYPE_REG
595 p.To.Reg = v.Reg0()
596
597 p1 := s.Prog(mips.AADDU)
598 p1.From.Type = obj.TYPE_REG
599 p1.From.Reg = v.Args[1].Reg()
600 p1.Reg = v.Reg0()
601 p1.To.Type = obj.TYPE_REG
602 p1.To.Reg = mips.REGTMP
603
604 p2 := s.Prog(mips.ASC)
605 p2.From.Type = obj.TYPE_REG
606 p2.From.Reg = mips.REGTMP
607 p2.To.Type = obj.TYPE_MEM
608 p2.To.Reg = v.Args[0].Reg()
609
610 p3 := s.Prog(mips.ABEQ)
611 p3.From.Type = obj.TYPE_REG
612 p3.From.Reg = mips.REGTMP
613 p3.To.Type = obj.TYPE_BRANCH
614 p3.To.SetTarget(p)
615
616 s.Prog(mips.ASYNC)
617
618 p4 := s.Prog(mips.AADDU)
619 p4.From.Type = obj.TYPE_REG
620 p4.From.Reg = v.Args[1].Reg()
621 p4.Reg = v.Reg0()
622 p4.To.Type = obj.TYPE_REG
623 p4.To.Reg = v.Reg0()
624
625 case ssa.OpMIPSLoweredAtomicAddconst:
626
627
628
629
630
631
632
633 s.Prog(mips.ASYNC)
634
635 p := s.Prog(mips.ALL)
636 p.From.Type = obj.TYPE_MEM
637 p.From.Reg = v.Args[0].Reg()
638 p.To.Type = obj.TYPE_REG
639 p.To.Reg = v.Reg0()
640
641 p1 := s.Prog(mips.AADDU)
642 p1.From.Type = obj.TYPE_CONST
643 p1.From.Offset = v.AuxInt
644 p1.Reg = v.Reg0()
645 p1.To.Type = obj.TYPE_REG
646 p1.To.Reg = mips.REGTMP
647
648 p2 := s.Prog(mips.ASC)
649 p2.From.Type = obj.TYPE_REG
650 p2.From.Reg = mips.REGTMP
651 p2.To.Type = obj.TYPE_MEM
652 p2.To.Reg = v.Args[0].Reg()
653
654 p3 := s.Prog(mips.ABEQ)
655 p3.From.Type = obj.TYPE_REG
656 p3.From.Reg = mips.REGTMP
657 p3.To.Type = obj.TYPE_BRANCH
658 p3.To.SetTarget(p)
659
660 s.Prog(mips.ASYNC)
661
662 p4 := s.Prog(mips.AADDU)
663 p4.From.Type = obj.TYPE_CONST
664 p4.From.Offset = v.AuxInt
665 p4.Reg = v.Reg0()
666 p4.To.Type = obj.TYPE_REG
667 p4.To.Reg = v.Reg0()
668
669 case ssa.OpMIPSLoweredAtomicAnd,
670 ssa.OpMIPSLoweredAtomicOr:
671
672
673
674
675
676
677 s.Prog(mips.ASYNC)
678
679 p := s.Prog(mips.ALL)
680 p.From.Type = obj.TYPE_MEM
681 p.From.Reg = v.Args[0].Reg()
682 p.To.Type = obj.TYPE_REG
683 p.To.Reg = mips.REGTMP
684
685 p1 := s.Prog(v.Op.Asm())
686 p1.From.Type = obj.TYPE_REG
687 p1.From.Reg = v.Args[1].Reg()
688 p1.Reg = mips.REGTMP
689 p1.To.Type = obj.TYPE_REG
690 p1.To.Reg = mips.REGTMP
691
692 p2 := s.Prog(mips.ASC)
693 p2.From.Type = obj.TYPE_REG
694 p2.From.Reg = mips.REGTMP
695 p2.To.Type = obj.TYPE_MEM
696 p2.To.Reg = v.Args[0].Reg()
697
698 p3 := s.Prog(mips.ABEQ)
699 p3.From.Type = obj.TYPE_REG
700 p3.From.Reg = mips.REGTMP
701 p3.To.Type = obj.TYPE_BRANCH
702 p3.To.SetTarget(p)
703
704 s.Prog(mips.ASYNC)
705
706 case ssa.OpMIPSLoweredAtomicCas:
707
708
709
710
711
712
713
714
715 p := s.Prog(mips.AMOVW)
716 p.From.Type = obj.TYPE_REG
717 p.From.Reg = mips.REGZERO
718 p.To.Type = obj.TYPE_REG
719 p.To.Reg = v.Reg0()
720
721 s.Prog(mips.ASYNC)
722
723 p1 := s.Prog(mips.ALL)
724 p1.From.Type = obj.TYPE_MEM
725 p1.From.Reg = v.Args[0].Reg()
726 p1.To.Type = obj.TYPE_REG
727 p1.To.Reg = mips.REGTMP
728
729 p2 := s.Prog(mips.ABNE)
730 p2.From.Type = obj.TYPE_REG
731 p2.From.Reg = v.Args[1].Reg()
732 p2.Reg = mips.REGTMP
733 p2.To.Type = obj.TYPE_BRANCH
734
735 p3 := s.Prog(mips.AMOVW)
736 p3.From.Type = obj.TYPE_REG
737 p3.From.Reg = v.Args[2].Reg()
738 p3.To.Type = obj.TYPE_REG
739 p3.To.Reg = v.Reg0()
740
741 p4 := s.Prog(mips.ASC)
742 p4.From.Type = obj.TYPE_REG
743 p4.From.Reg = v.Reg0()
744 p4.To.Type = obj.TYPE_MEM
745 p4.To.Reg = v.Args[0].Reg()
746
747 p5 := s.Prog(mips.ABEQ)
748 p5.From.Type = obj.TYPE_REG
749 p5.From.Reg = v.Reg0()
750 p5.To.Type = obj.TYPE_BRANCH
751 p5.To.SetTarget(p1)
752
753 s.Prog(mips.ASYNC)
754
755 p6 := s.Prog(obj.ANOP)
756 p2.To.SetTarget(p6)
757
758 case ssa.OpMIPSLoweredNilCheck:
759
760 p := s.Prog(mips.AMOVB)
761 p.From.Type = obj.TYPE_MEM
762 p.From.Reg = v.Args[0].Reg()
763 ssagen.AddAux(&p.From, v)
764 p.To.Type = obj.TYPE_REG
765 p.To.Reg = mips.REGTMP
766 if logopt.Enabled() {
767 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
768 }
769 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
770 base.WarnfAt(v.Pos, "generated nil check")
771 }
772 case ssa.OpMIPSFPFlagTrue,
773 ssa.OpMIPSFPFlagFalse:
774
775
776
777 cmov := mips.ACMOVF
778 if v.Op == ssa.OpMIPSFPFlagFalse {
779 cmov = mips.ACMOVT
780 }
781 p := s.Prog(mips.AMOVW)
782 p.From.Type = obj.TYPE_CONST
783 p.From.Offset = 1
784 p.To.Type = obj.TYPE_REG
785 p.To.Reg = v.Reg()
786 p1 := s.Prog(cmov)
787 p1.From.Type = obj.TYPE_REG
788 p1.From.Reg = mips.REGZERO
789 p1.To.Type = obj.TYPE_REG
790 p1.To.Reg = v.Reg()
791
792 case ssa.OpMIPSLoweredGetClosurePtr:
793
794 ssagen.CheckLoweredGetClosurePtr(v)
795 case ssa.OpMIPSLoweredGetCallerSP:
796
797 p := s.Prog(mips.AMOVW)
798 p.From.Type = obj.TYPE_ADDR
799 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
800 p.From.Name = obj.NAME_PARAM
801 p.To.Type = obj.TYPE_REG
802 p.To.Reg = v.Reg()
803 case ssa.OpMIPSLoweredGetCallerPC:
804 p := s.Prog(obj.AGETCALLERPC)
805 p.To.Type = obj.TYPE_REG
806 p.To.Reg = v.Reg()
807 case ssa.OpClobber, ssa.OpClobberReg:
808
809 default:
810 v.Fatalf("genValue not implemented: %s", v.LongString())
811 }
812 }
813
814 var blockJump = map[ssa.BlockKind]struct {
815 asm, invasm obj.As
816 }{
817 ssa.BlockMIPSEQ: {mips.ABEQ, mips.ABNE},
818 ssa.BlockMIPSNE: {mips.ABNE, mips.ABEQ},
819 ssa.BlockMIPSLTZ: {mips.ABLTZ, mips.ABGEZ},
820 ssa.BlockMIPSGEZ: {mips.ABGEZ, mips.ABLTZ},
821 ssa.BlockMIPSLEZ: {mips.ABLEZ, mips.ABGTZ},
822 ssa.BlockMIPSGTZ: {mips.ABGTZ, mips.ABLEZ},
823 ssa.BlockMIPSFPT: {mips.ABFPT, mips.ABFPF},
824 ssa.BlockMIPSFPF: {mips.ABFPF, mips.ABFPT},
825 }
826
827 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
828 switch b.Kind {
829 case ssa.BlockPlain:
830 if b.Succs[0].Block() != next {
831 p := s.Prog(obj.AJMP)
832 p.To.Type = obj.TYPE_BRANCH
833 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
834 }
835 case ssa.BlockDefer:
836
837
838
839 p := s.Prog(mips.ABNE)
840 p.From.Type = obj.TYPE_REG
841 p.From.Reg = mips.REGZERO
842 p.Reg = mips.REG_R1
843 p.To.Type = obj.TYPE_BRANCH
844 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
845 if b.Succs[0].Block() != next {
846 p := s.Prog(obj.AJMP)
847 p.To.Type = obj.TYPE_BRANCH
848 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
849 }
850 case ssa.BlockExit, ssa.BlockRetJmp:
851 case ssa.BlockRet:
852 s.Prog(obj.ARET)
853 case ssa.BlockMIPSEQ, ssa.BlockMIPSNE,
854 ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ,
855 ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ,
856 ssa.BlockMIPSFPT, ssa.BlockMIPSFPF:
857 jmp := blockJump[b.Kind]
858 var p *obj.Prog
859 switch next {
860 case b.Succs[0].Block():
861 p = s.Br(jmp.invasm, b.Succs[1].Block())
862 case b.Succs[1].Block():
863 p = s.Br(jmp.asm, b.Succs[0].Block())
864 default:
865 if b.Likely != ssa.BranchUnlikely {
866 p = s.Br(jmp.asm, b.Succs[0].Block())
867 s.Br(obj.AJMP, b.Succs[1].Block())
868 } else {
869 p = s.Br(jmp.invasm, b.Succs[1].Block())
870 s.Br(obj.AJMP, b.Succs[0].Block())
871 }
872 }
873 if !b.Controls[0].Type.IsFlags() {
874 p.From.Type = obj.TYPE_REG
875 p.From.Reg = b.Controls[0].Reg()
876 }
877 default:
878 b.Fatalf("branch not implemented: %s", b.LongString())
879 }
880 }
881
View as plain text