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