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.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, ssa.OpMIPSCALLtailinter:
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
490 case ssa.OpMIPSLoweredPanicBoundsRR, ssa.OpMIPSLoweredPanicBoundsRC, ssa.OpMIPSLoweredPanicBoundsCR, ssa.OpMIPSLoweredPanicBoundsCC,
491 ssa.OpMIPSLoweredPanicExtendRR, ssa.OpMIPSLoweredPanicExtendRC:
492
493 code, signed := ssa.BoundsKind(v.AuxInt).Code()
494 xIsReg := false
495 yIsReg := false
496 xVal := 0
497 yVal := 0
498 extend := false
499 switch v.Op {
500 case ssa.OpMIPSLoweredPanicBoundsRR:
501 xIsReg = true
502 xVal = int(v.Args[0].Reg() - mips.REG_R1)
503 yIsReg = true
504 yVal = int(v.Args[1].Reg() - mips.REG_R1)
505 case ssa.OpMIPSLoweredPanicExtendRR:
506 extend = true
507 xIsReg = true
508 hi := int(v.Args[0].Reg() - mips.REG_R1)
509 lo := int(v.Args[1].Reg() - mips.REG_R1)
510 xVal = hi<<2 + lo
511 yIsReg = true
512 yVal = int(v.Args[2].Reg() - mips.REG_R1)
513 case ssa.OpMIPSLoweredPanicBoundsRC:
514 xIsReg = true
515 xVal = int(v.Args[0].Reg() - mips.REG_R1)
516 c := v.Aux.(ssa.PanicBoundsC).C
517 if c >= 0 && c <= abi.BoundsMaxConst {
518 yVal = int(c)
519 } else {
520
521 yIsReg = true
522 if yVal == xVal {
523 yVal = 1
524 }
525 p := s.Prog(mips.AMOVW)
526 p.From.Type = obj.TYPE_CONST
527 p.From.Offset = c
528 p.To.Type = obj.TYPE_REG
529 p.To.Reg = mips.REG_R1 + int16(yVal)
530 }
531 case ssa.OpMIPSLoweredPanicExtendRC:
532 extend = true
533 xIsReg = true
534 hi := int(v.Args[0].Reg() - mips.REG_R1)
535 lo := int(v.Args[1].Reg() - mips.REG_R1)
536 xVal = hi<<2 + lo
537 c := v.Aux.(ssa.PanicBoundsC).C
538 if c >= 0 && c <= abi.BoundsMaxConst {
539 yVal = int(c)
540 } else {
541
542 for yVal == hi || yVal == lo {
543 yVal++
544 }
545 p := s.Prog(mips.AMOVW)
546 p.From.Type = obj.TYPE_CONST
547 p.From.Offset = c
548 p.To.Type = obj.TYPE_REG
549 p.To.Reg = mips.REG_R1 + int16(yVal)
550 }
551 case ssa.OpMIPSLoweredPanicBoundsCR:
552 yIsReg = true
553 yVal = int(v.Args[0].Reg() - mips.REG_R1)
554 c := v.Aux.(ssa.PanicBoundsC).C
555 if c >= 0 && c <= abi.BoundsMaxConst {
556 xVal = int(c)
557 } else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
558
559 xIsReg = true
560 if xVal == yVal {
561 xVal = 1
562 }
563 p := s.Prog(mips.AMOVW)
564 p.From.Type = obj.TYPE_CONST
565 p.From.Offset = c
566 p.To.Type = obj.TYPE_REG
567 p.To.Reg = mips.REG_R1 + int16(xVal)
568 } else {
569
570 extend = true
571 xIsReg = true
572 hi := 0
573 lo := 1
574 if hi == yVal {
575 hi = 2
576 }
577 if lo == yVal {
578 lo = 2
579 }
580 xVal = hi<<2 + lo
581 p := s.Prog(mips.AMOVW)
582 p.From.Type = obj.TYPE_CONST
583 p.From.Offset = c >> 32
584 p.To.Type = obj.TYPE_REG
585 p.To.Reg = mips.REG_R1 + int16(hi)
586 p = s.Prog(mips.AMOVW)
587 p.From.Type = obj.TYPE_CONST
588 p.From.Offset = int64(int32(c))
589 p.To.Type = obj.TYPE_REG
590 p.To.Reg = mips.REG_R1 + int16(lo)
591 }
592 case ssa.OpMIPSLoweredPanicBoundsCC:
593 c := v.Aux.(ssa.PanicBoundsCC).Cx
594 if c >= 0 && c <= abi.BoundsMaxConst {
595 xVal = int(c)
596 } else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
597
598 xIsReg = true
599 p := s.Prog(mips.AMOVW)
600 p.From.Type = obj.TYPE_CONST
601 p.From.Offset = c
602 p.To.Type = obj.TYPE_REG
603 p.To.Reg = mips.REG_R1 + int16(xVal)
604 } else {
605
606 extend = true
607 xIsReg = true
608 hi := 0
609 lo := 1
610 xVal = hi<<2 + lo
611 p := s.Prog(mips.AMOVW)
612 p.From.Type = obj.TYPE_CONST
613 p.From.Offset = c >> 32
614 p.To.Type = obj.TYPE_REG
615 p.To.Reg = mips.REG_R1 + int16(hi)
616 p = s.Prog(mips.AMOVW)
617 p.From.Type = obj.TYPE_CONST
618 p.From.Offset = int64(int32(c))
619 p.To.Type = obj.TYPE_REG
620 p.To.Reg = mips.REG_R1 + int16(lo)
621 }
622 c = v.Aux.(ssa.PanicBoundsCC).Cy
623 if c >= 0 && c <= abi.BoundsMaxConst {
624 yVal = int(c)
625 } else {
626
627 yIsReg = true
628 yVal = 2
629 p := s.Prog(mips.AMOVW)
630 p.From.Type = obj.TYPE_CONST
631 p.From.Offset = c
632 p.To.Type = obj.TYPE_REG
633 p.To.Reg = mips.REG_R1 + int16(yVal)
634 }
635 }
636 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
637
638 p := s.Prog(obj.APCDATA)
639 p.From.SetConst(abi.PCDATA_PanicBounds)
640 p.To.SetConst(int64(c))
641 p = s.Prog(obj.ACALL)
642 p.To.Type = obj.TYPE_MEM
643 p.To.Name = obj.NAME_EXTERN
644 if extend {
645 p.To.Sym = ir.Syms.PanicExtend
646 } else {
647 p.To.Sym = ir.Syms.PanicBounds
648 }
649
650 case ssa.OpMIPSLoweredAtomicLoad8,
651 ssa.OpMIPSLoweredAtomicLoad32:
652 s.Prog(mips.ASYNC)
653
654 var op obj.As
655 switch v.Op {
656 case ssa.OpMIPSLoweredAtomicLoad8:
657 op = mips.AMOVB
658 case ssa.OpMIPSLoweredAtomicLoad32:
659 op = mips.AMOVW
660 }
661 p := s.Prog(op)
662 p.From.Type = obj.TYPE_MEM
663 p.From.Reg = v.Args[0].Reg()
664 p.To.Type = obj.TYPE_REG
665 p.To.Reg = v.Reg0()
666
667 s.Prog(mips.ASYNC)
668 case ssa.OpMIPSLoweredAtomicStore8,
669 ssa.OpMIPSLoweredAtomicStore32:
670 s.Prog(mips.ASYNC)
671
672 var op obj.As
673 switch v.Op {
674 case ssa.OpMIPSLoweredAtomicStore8:
675 op = mips.AMOVB
676 case ssa.OpMIPSLoweredAtomicStore32:
677 op = mips.AMOVW
678 }
679 p := s.Prog(op)
680 p.From.Type = obj.TYPE_REG
681 p.From.Reg = v.Args[1].Reg()
682 p.To.Type = obj.TYPE_MEM
683 p.To.Reg = v.Args[0].Reg()
684
685 s.Prog(mips.ASYNC)
686 case ssa.OpMIPSLoweredAtomicStorezero:
687 s.Prog(mips.ASYNC)
688
689 p := s.Prog(mips.AMOVW)
690 p.From.Type = obj.TYPE_REG
691 p.From.Reg = mips.REGZERO
692 p.To.Type = obj.TYPE_MEM
693 p.To.Reg = v.Args[0].Reg()
694
695 s.Prog(mips.ASYNC)
696 case ssa.OpMIPSLoweredAtomicExchange:
697
698
699
700
701
702
703 s.Prog(mips.ASYNC)
704
705 p := s.Prog(mips.AMOVW)
706 p.From.Type = obj.TYPE_REG
707 p.From.Reg = v.Args[1].Reg()
708 p.To.Type = obj.TYPE_REG
709 p.To.Reg = mips.REGTMP
710
711 p1 := s.Prog(mips.ALL)
712 p1.From.Type = obj.TYPE_MEM
713 p1.From.Reg = v.Args[0].Reg()
714 p1.To.Type = obj.TYPE_REG
715 p1.To.Reg = v.Reg0()
716
717 p2 := s.Prog(mips.ASC)
718 p2.From.Type = obj.TYPE_REG
719 p2.From.Reg = mips.REGTMP
720 p2.To.Type = obj.TYPE_MEM
721 p2.To.Reg = v.Args[0].Reg()
722
723 p3 := s.Prog(mips.ABEQ)
724 p3.From.Type = obj.TYPE_REG
725 p3.From.Reg = mips.REGTMP
726 p3.To.Type = obj.TYPE_BRANCH
727 p3.To.SetTarget(p)
728
729 s.Prog(mips.ASYNC)
730 case ssa.OpMIPSLoweredAtomicAdd:
731
732
733
734
735
736
737
738 s.Prog(mips.ASYNC)
739
740 p := s.Prog(mips.ALL)
741 p.From.Type = obj.TYPE_MEM
742 p.From.Reg = v.Args[0].Reg()
743 p.To.Type = obj.TYPE_REG
744 p.To.Reg = v.Reg0()
745
746 p1 := s.Prog(mips.AADDU)
747 p1.From.Type = obj.TYPE_REG
748 p1.From.Reg = v.Args[1].Reg()
749 p1.Reg = v.Reg0()
750 p1.To.Type = obj.TYPE_REG
751 p1.To.Reg = mips.REGTMP
752
753 p2 := s.Prog(mips.ASC)
754 p2.From.Type = obj.TYPE_REG
755 p2.From.Reg = mips.REGTMP
756 p2.To.Type = obj.TYPE_MEM
757 p2.To.Reg = v.Args[0].Reg()
758
759 p3 := s.Prog(mips.ABEQ)
760 p3.From.Type = obj.TYPE_REG
761 p3.From.Reg = mips.REGTMP
762 p3.To.Type = obj.TYPE_BRANCH
763 p3.To.SetTarget(p)
764
765 s.Prog(mips.ASYNC)
766
767 p4 := s.Prog(mips.AADDU)
768 p4.From.Type = obj.TYPE_REG
769 p4.From.Reg = v.Args[1].Reg()
770 p4.Reg = v.Reg0()
771 p4.To.Type = obj.TYPE_REG
772 p4.To.Reg = v.Reg0()
773
774 case ssa.OpMIPSLoweredAtomicAddconst:
775
776
777
778
779
780
781
782 s.Prog(mips.ASYNC)
783
784 p := s.Prog(mips.ALL)
785 p.From.Type = obj.TYPE_MEM
786 p.From.Reg = v.Args[0].Reg()
787 p.To.Type = obj.TYPE_REG
788 p.To.Reg = v.Reg0()
789
790 p1 := s.Prog(mips.AADDU)
791 p1.From.Type = obj.TYPE_CONST
792 p1.From.Offset = v.AuxInt
793 p1.Reg = v.Reg0()
794 p1.To.Type = obj.TYPE_REG
795 p1.To.Reg = mips.REGTMP
796
797 p2 := s.Prog(mips.ASC)
798 p2.From.Type = obj.TYPE_REG
799 p2.From.Reg = mips.REGTMP
800 p2.To.Type = obj.TYPE_MEM
801 p2.To.Reg = v.Args[0].Reg()
802
803 p3 := s.Prog(mips.ABEQ)
804 p3.From.Type = obj.TYPE_REG
805 p3.From.Reg = mips.REGTMP
806 p3.To.Type = obj.TYPE_BRANCH
807 p3.To.SetTarget(p)
808
809 s.Prog(mips.ASYNC)
810
811 p4 := s.Prog(mips.AADDU)
812 p4.From.Type = obj.TYPE_CONST
813 p4.From.Offset = v.AuxInt
814 p4.Reg = v.Reg0()
815 p4.To.Type = obj.TYPE_REG
816 p4.To.Reg = v.Reg0()
817
818 case ssa.OpMIPSLoweredAtomicAnd,
819 ssa.OpMIPSLoweredAtomicOr:
820
821
822
823
824
825
826 s.Prog(mips.ASYNC)
827
828 p := s.Prog(mips.ALL)
829 p.From.Type = obj.TYPE_MEM
830 p.From.Reg = v.Args[0].Reg()
831 p.To.Type = obj.TYPE_REG
832 p.To.Reg = mips.REGTMP
833
834 p1 := s.Prog(v.Op.Asm())
835 p1.From.Type = obj.TYPE_REG
836 p1.From.Reg = v.Args[1].Reg()
837 p1.Reg = mips.REGTMP
838 p1.To.Type = obj.TYPE_REG
839 p1.To.Reg = mips.REGTMP
840
841 p2 := s.Prog(mips.ASC)
842 p2.From.Type = obj.TYPE_REG
843 p2.From.Reg = mips.REGTMP
844 p2.To.Type = obj.TYPE_MEM
845 p2.To.Reg = v.Args[0].Reg()
846
847 p3 := s.Prog(mips.ABEQ)
848 p3.From.Type = obj.TYPE_REG
849 p3.From.Reg = mips.REGTMP
850 p3.To.Type = obj.TYPE_BRANCH
851 p3.To.SetTarget(p)
852
853 s.Prog(mips.ASYNC)
854
855 case ssa.OpMIPSLoweredAtomicCas:
856
857
858
859
860
861
862
863
864 p := s.Prog(mips.AMOVW)
865 p.From.Type = obj.TYPE_REG
866 p.From.Reg = mips.REGZERO
867 p.To.Type = obj.TYPE_REG
868 p.To.Reg = v.Reg0()
869
870 s.Prog(mips.ASYNC)
871
872 p1 := s.Prog(mips.ALL)
873 p1.From.Type = obj.TYPE_MEM
874 p1.From.Reg = v.Args[0].Reg()
875 p1.To.Type = obj.TYPE_REG
876 p1.To.Reg = mips.REGTMP
877
878 p2 := s.Prog(mips.ABNE)
879 p2.From.Type = obj.TYPE_REG
880 p2.From.Reg = v.Args[1].Reg()
881 p2.Reg = mips.REGTMP
882 p2.To.Type = obj.TYPE_BRANCH
883
884 p3 := s.Prog(mips.AMOVW)
885 p3.From.Type = obj.TYPE_REG
886 p3.From.Reg = v.Args[2].Reg()
887 p3.To.Type = obj.TYPE_REG
888 p3.To.Reg = v.Reg0()
889
890 p4 := s.Prog(mips.ASC)
891 p4.From.Type = obj.TYPE_REG
892 p4.From.Reg = v.Reg0()
893 p4.To.Type = obj.TYPE_MEM
894 p4.To.Reg = v.Args[0].Reg()
895
896 p5 := s.Prog(mips.ABEQ)
897 p5.From.Type = obj.TYPE_REG
898 p5.From.Reg = v.Reg0()
899 p5.To.Type = obj.TYPE_BRANCH
900 p5.To.SetTarget(p1)
901
902 s.Prog(mips.ASYNC)
903
904 p6 := s.Prog(obj.ANOP)
905 p2.To.SetTarget(p6)
906
907 case ssa.OpMIPSLoweredNilCheck:
908
909 p := s.Prog(mips.AMOVB)
910 p.From.Type = obj.TYPE_MEM
911 p.From.Reg = v.Args[0].Reg()
912 ssagen.AddAux(&p.From, v)
913 p.To.Type = obj.TYPE_REG
914 p.To.Reg = mips.REGTMP
915 if logopt.Enabled() {
916 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
917 }
918 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
919 base.WarnfAt(v.Pos, "generated nil check")
920 }
921 case ssa.OpMIPSFPFlagTrue,
922 ssa.OpMIPSFPFlagFalse:
923
924
925
926 cmov := mips.ACMOVF
927 if v.Op == ssa.OpMIPSFPFlagFalse {
928 cmov = mips.ACMOVT
929 }
930 p := s.Prog(mips.AMOVW)
931 p.From.Type = obj.TYPE_CONST
932 p.From.Offset = 1
933 p.To.Type = obj.TYPE_REG
934 p.To.Reg = v.Reg()
935 p1 := s.Prog(cmov)
936 p1.From.Type = obj.TYPE_REG
937 p1.From.Reg = mips.REGZERO
938 p1.To.Type = obj.TYPE_REG
939 p1.To.Reg = v.Reg()
940
941 case ssa.OpMIPSLoweredGetClosurePtr:
942
943 ssagen.CheckLoweredGetClosurePtr(v)
944 case ssa.OpMIPSLoweredGetCallerSP:
945
946 p := s.Prog(mips.AMOVW)
947 p.From.Type = obj.TYPE_ADDR
948 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
949 p.From.Name = obj.NAME_PARAM
950 p.To.Type = obj.TYPE_REG
951 p.To.Reg = v.Reg()
952 case ssa.OpMIPSLoweredGetCallerPC:
953 p := s.Prog(obj.AGETCALLERPC)
954 p.To.Type = obj.TYPE_REG
955 p.To.Reg = v.Reg()
956 case ssa.OpMIPSLoweredPubBarrier:
957
958 s.Prog(v.Op.Asm())
959 case ssa.OpClobber, ssa.OpClobberReg:
960
961 default:
962 v.Fatalf("genValue not implemented: %s", v.LongString())
963 }
964 }
965
966 var blockJump = map[ssa.BlockKind]struct {
967 asm, invasm obj.As
968 }{
969 ssa.BlockMIPSEQ: {mips.ABEQ, mips.ABNE},
970 ssa.BlockMIPSNE: {mips.ABNE, mips.ABEQ},
971 ssa.BlockMIPSLTZ: {mips.ABLTZ, mips.ABGEZ},
972 ssa.BlockMIPSGEZ: {mips.ABGEZ, mips.ABLTZ},
973 ssa.BlockMIPSLEZ: {mips.ABLEZ, mips.ABGTZ},
974 ssa.BlockMIPSGTZ: {mips.ABGTZ, mips.ABLEZ},
975 ssa.BlockMIPSFPT: {mips.ABFPT, mips.ABFPF},
976 ssa.BlockMIPSFPF: {mips.ABFPF, mips.ABFPT},
977 }
978
979 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
980 switch b.Kind {
981 case ssa.BlockPlain, ssa.BlockDefer:
982 if b.Succs[0].Block() != next {
983 p := s.Prog(obj.AJMP)
984 p.To.Type = obj.TYPE_BRANCH
985 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
986 }
987 case ssa.BlockExit, ssa.BlockRetJmp:
988 case ssa.BlockRet:
989 s.Prog(obj.ARET)
990 case ssa.BlockMIPSEQ, ssa.BlockMIPSNE,
991 ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ,
992 ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ,
993 ssa.BlockMIPSFPT, ssa.BlockMIPSFPF:
994 jmp := blockJump[b.Kind]
995 var p *obj.Prog
996 switch next {
997 case b.Succs[0].Block():
998 p = s.Br(jmp.invasm, b.Succs[1].Block())
999 case b.Succs[1].Block():
1000 p = s.Br(jmp.asm, b.Succs[0].Block())
1001 default:
1002 if b.Likely != ssa.BranchUnlikely {
1003 p = s.Br(jmp.asm, b.Succs[0].Block())
1004 s.Br(obj.AJMP, b.Succs[1].Block())
1005 } else {
1006 p = s.Br(jmp.invasm, b.Succs[1].Block())
1007 s.Br(obj.AJMP, b.Succs[0].Block())
1008 }
1009 }
1010 if !b.Controls[0].Type.IsFlags() {
1011 p.From.Type = obj.TYPE_REG
1012 p.From.Reg = b.Controls[0].Reg()
1013 }
1014 default:
1015 b.Fatalf("branch not implemented: %s", b.LongString())
1016 }
1017 }
1018
View as plain text