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
217
218
219
220 p := s.Prog(v.Op.Asm())
221 p.From.Type = obj.TYPE_REG
222 p.From.Reg = v.Args[1].Reg()
223 p.Reg = v.Args[0].Reg()
224 p1 := s.Prog(mips.AMOVW)
225 p1.From.Type = obj.TYPE_REG
226 p1.From.Reg = mips.REG_HI
227 p1.To.Type = obj.TYPE_REG
228 p1.To.Reg = v.Reg0()
229 p2 := s.Prog(mips.AMOVW)
230 p2.From.Type = obj.TYPE_REG
231 p2.From.Reg = mips.REG_LO
232 p2.To.Type = obj.TYPE_REG
233 p2.To.Reg = v.Reg1()
234 case ssa.OpMIPSMOVWconst:
235 r := v.Reg()
236 p := s.Prog(v.Op.Asm())
237 p.From.Type = obj.TYPE_CONST
238 p.From.Offset = v.AuxInt
239 p.To.Type = obj.TYPE_REG
240 p.To.Reg = r
241 if isFPreg(r) || isHILO(r) {
242
243 p.To.Reg = mips.REGTMP
244 p = s.Prog(mips.AMOVW)
245 p.From.Type = obj.TYPE_REG
246 p.From.Reg = mips.REGTMP
247 p.To.Type = obj.TYPE_REG
248 p.To.Reg = r
249 }
250 case ssa.OpMIPSMOVFconst,
251 ssa.OpMIPSMOVDconst:
252 p := s.Prog(v.Op.Asm())
253 p.From.Type = obj.TYPE_FCONST
254 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
255 p.To.Type = obj.TYPE_REG
256 p.To.Reg = v.Reg()
257 case ssa.OpMIPSCMOVZ:
258 p := s.Prog(v.Op.Asm())
259 p.From.Type = obj.TYPE_REG
260 p.From.Reg = v.Args[2].Reg()
261 p.Reg = v.Args[1].Reg()
262 p.To.Type = obj.TYPE_REG
263 p.To.Reg = v.Reg()
264 case ssa.OpMIPSCMOVZzero:
265 p := s.Prog(v.Op.Asm())
266 p.From.Type = obj.TYPE_REG
267 p.From.Reg = v.Args[1].Reg()
268 p.Reg = mips.REGZERO
269 p.To.Type = obj.TYPE_REG
270 p.To.Reg = v.Reg()
271 case ssa.OpMIPSCMPEQF,
272 ssa.OpMIPSCMPEQD,
273 ssa.OpMIPSCMPGEF,
274 ssa.OpMIPSCMPGED,
275 ssa.OpMIPSCMPGTF,
276 ssa.OpMIPSCMPGTD:
277 p := s.Prog(v.Op.Asm())
278 p.From.Type = obj.TYPE_REG
279 p.From.Reg = v.Args[0].Reg()
280 p.Reg = v.Args[1].Reg()
281 case ssa.OpMIPSMOVWaddr:
282 p := s.Prog(mips.AMOVW)
283 p.From.Type = obj.TYPE_ADDR
284 p.From.Reg = v.Args[0].Reg()
285 var wantreg string
286
287
288
289
290
291 switch v.Aux.(type) {
292 default:
293 v.Fatalf("aux is of unknown type %T", v.Aux)
294 case *obj.LSym:
295 wantreg = "SB"
296 ssagen.AddAux(&p.From, v)
297 case *ir.Name:
298 wantreg = "SP"
299 ssagen.AddAux(&p.From, v)
300 case nil:
301
302 wantreg = "SP"
303 p.From.Offset = v.AuxInt
304 }
305 if reg := v.Args[0].RegName(); reg != wantreg {
306 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
307 }
308 p.To.Type = obj.TYPE_REG
309 p.To.Reg = v.Reg()
310 case ssa.OpMIPSMOVBload,
311 ssa.OpMIPSMOVBUload,
312 ssa.OpMIPSMOVHload,
313 ssa.OpMIPSMOVHUload,
314 ssa.OpMIPSMOVWload,
315 ssa.OpMIPSMOVFload,
316 ssa.OpMIPSMOVDload:
317 p := s.Prog(v.Op.Asm())
318 p.From.Type = obj.TYPE_MEM
319 p.From.Reg = v.Args[0].Reg()
320 ssagen.AddAux(&p.From, v)
321 p.To.Type = obj.TYPE_REG
322 p.To.Reg = v.Reg()
323 case ssa.OpMIPSMOVBstore,
324 ssa.OpMIPSMOVHstore,
325 ssa.OpMIPSMOVWstore,
326 ssa.OpMIPSMOVFstore,
327 ssa.OpMIPSMOVDstore:
328 p := s.Prog(v.Op.Asm())
329 p.From.Type = obj.TYPE_REG
330 p.From.Reg = v.Args[1].Reg()
331 p.To.Type = obj.TYPE_MEM
332 p.To.Reg = v.Args[0].Reg()
333 ssagen.AddAux(&p.To, v)
334 case ssa.OpMIPSMOVBstorezero,
335 ssa.OpMIPSMOVHstorezero,
336 ssa.OpMIPSMOVWstorezero:
337 p := s.Prog(v.Op.Asm())
338 p.From.Type = obj.TYPE_REG
339 p.From.Reg = mips.REGZERO
340 p.To.Type = obj.TYPE_MEM
341 p.To.Reg = v.Args[0].Reg()
342 ssagen.AddAux(&p.To, v)
343 case ssa.OpMIPSMOVBreg,
344 ssa.OpMIPSMOVBUreg,
345 ssa.OpMIPSMOVHreg,
346 ssa.OpMIPSMOVHUreg:
347 a := v.Args[0]
348 for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPSMOVWreg || a.Op == ssa.OpMIPSMOVWnop {
349 a = a.Args[0]
350 }
351 if a.Op == ssa.OpLoadReg {
352 t := a.Type
353 switch {
354 case v.Op == ssa.OpMIPSMOVBreg && t.Size() == 1 && t.IsSigned(),
355 v.Op == ssa.OpMIPSMOVBUreg && t.Size() == 1 && !t.IsSigned(),
356 v.Op == ssa.OpMIPSMOVHreg && t.Size() == 2 && t.IsSigned(),
357 v.Op == ssa.OpMIPSMOVHUreg && t.Size() == 2 && !t.IsSigned():
358
359 if v.Reg() == v.Args[0].Reg() {
360 return
361 }
362 p := s.Prog(mips.AMOVW)
363 p.From.Type = obj.TYPE_REG
364 p.From.Reg = v.Args[0].Reg()
365 p.To.Type = obj.TYPE_REG
366 p.To.Reg = v.Reg()
367 return
368 default:
369 }
370 }
371 fallthrough
372 case ssa.OpMIPSMOVWF,
373 ssa.OpMIPSMOVWD,
374 ssa.OpMIPSTRUNCFW,
375 ssa.OpMIPSTRUNCDW,
376 ssa.OpMIPSMOVFD,
377 ssa.OpMIPSMOVDF,
378 ssa.OpMIPSMOVWfpgp,
379 ssa.OpMIPSMOVWgpfp,
380 ssa.OpMIPSNEGF,
381 ssa.OpMIPSNEGD,
382 ssa.OpMIPSABSD,
383 ssa.OpMIPSSQRTF,
384 ssa.OpMIPSSQRTD,
385 ssa.OpMIPSCLZ:
386 p := s.Prog(v.Op.Asm())
387 p.From.Type = obj.TYPE_REG
388 p.From.Reg = v.Args[0].Reg()
389 p.To.Type = obj.TYPE_REG
390 p.To.Reg = v.Reg()
391 case ssa.OpMIPSNEG:
392
393 p := s.Prog(mips.ASUBU)
394 p.From.Type = obj.TYPE_REG
395 p.From.Reg = v.Args[0].Reg()
396 p.Reg = mips.REGZERO
397 p.To.Type = obj.TYPE_REG
398 p.To.Reg = v.Reg()
399 case ssa.OpMIPSLoweredZero:
400
401
402
403
404
405 var sz int64
406 var mov obj.As
407 switch {
408 case v.AuxInt%4 == 0:
409 sz = 4
410 mov = mips.AMOVW
411 case v.AuxInt%2 == 0:
412 sz = 2
413 mov = mips.AMOVH
414 default:
415 sz = 1
416 mov = mips.AMOVB
417 }
418 p := s.Prog(mips.ASUBU)
419 p.From.Type = obj.TYPE_CONST
420 p.From.Offset = sz
421 p.To.Type = obj.TYPE_REG
422 p.To.Reg = mips.REG_R1
423 p2 := s.Prog(mov)
424 p2.From.Type = obj.TYPE_REG
425 p2.From.Reg = mips.REGZERO
426 p2.To.Type = obj.TYPE_MEM
427 p2.To.Reg = mips.REG_R1
428 p2.To.Offset = sz
429 p3 := s.Prog(mips.AADDU)
430 p3.From.Type = obj.TYPE_CONST
431 p3.From.Offset = sz
432 p3.To.Type = obj.TYPE_REG
433 p3.To.Reg = mips.REG_R1
434 p4 := s.Prog(mips.ABNE)
435 p4.From.Type = obj.TYPE_REG
436 p4.From.Reg = v.Args[1].Reg()
437 p4.Reg = mips.REG_R1
438 p4.To.Type = obj.TYPE_BRANCH
439 p4.To.SetTarget(p2)
440 case ssa.OpMIPSLoweredMove:
441
442
443
444
445
446
447
448 var sz int64
449 var mov obj.As
450 switch {
451 case v.AuxInt%4 == 0:
452 sz = 4
453 mov = mips.AMOVW
454 case v.AuxInt%2 == 0:
455 sz = 2
456 mov = mips.AMOVH
457 default:
458 sz = 1
459 mov = mips.AMOVB
460 }
461 p := s.Prog(mips.ASUBU)
462 p.From.Type = obj.TYPE_CONST
463 p.From.Offset = sz
464 p.To.Type = obj.TYPE_REG
465 p.To.Reg = mips.REG_R1
466 p2 := s.Prog(mov)
467 p2.From.Type = obj.TYPE_MEM
468 p2.From.Reg = mips.REG_R1
469 p2.From.Offset = sz
470 p2.To.Type = obj.TYPE_REG
471 p2.To.Reg = mips.REGTMP
472 p3 := s.Prog(mov)
473 p3.From.Type = obj.TYPE_REG
474 p3.From.Reg = mips.REGTMP
475 p3.To.Type = obj.TYPE_MEM
476 p3.To.Reg = mips.REG_R2
477 p4 := s.Prog(mips.AADDU)
478 p4.From.Type = obj.TYPE_CONST
479 p4.From.Offset = sz
480 p4.To.Type = obj.TYPE_REG
481 p4.To.Reg = mips.REG_R1
482 p5 := s.Prog(mips.AADDU)
483 p5.From.Type = obj.TYPE_CONST
484 p5.From.Offset = sz
485 p5.To.Type = obj.TYPE_REG
486 p5.To.Reg = mips.REG_R2
487 p6 := s.Prog(mips.ABNE)
488 p6.From.Type = obj.TYPE_REG
489 p6.From.Reg = v.Args[2].Reg()
490 p6.Reg = mips.REG_R1
491 p6.To.Type = obj.TYPE_BRANCH
492 p6.To.SetTarget(p2)
493 case ssa.OpMIPSCALLstatic, ssa.OpMIPSCALLclosure, ssa.OpMIPSCALLinter:
494 s.Call(v)
495 case ssa.OpMIPSCALLtail, ssa.OpMIPSCALLtailinter:
496 s.TailCall(v)
497 case ssa.OpMIPSLoweredWB:
498 p := s.Prog(obj.ACALL)
499 p.To.Type = obj.TYPE_MEM
500 p.To.Name = obj.NAME_EXTERN
501
502 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
503
504 case ssa.OpMIPSLoweredPanicBoundsRR, ssa.OpMIPSLoweredPanicBoundsRC, ssa.OpMIPSLoweredPanicBoundsCR, ssa.OpMIPSLoweredPanicBoundsCC,
505 ssa.OpMIPSLoweredPanicExtendRR, ssa.OpMIPSLoweredPanicExtendRC:
506
507 code, signed := ssa.BoundsKind(v.AuxInt).Code()
508 xIsReg := false
509 yIsReg := false
510 xVal := 0
511 yVal := 0
512 extend := false
513 switch v.Op {
514 case ssa.OpMIPSLoweredPanicBoundsRR:
515 xIsReg = true
516 xVal = int(v.Args[0].Reg() - mips.REG_R1)
517 yIsReg = true
518 yVal = int(v.Args[1].Reg() - mips.REG_R1)
519 case ssa.OpMIPSLoweredPanicExtendRR:
520 extend = true
521 xIsReg = true
522 hi := int(v.Args[0].Reg() - mips.REG_R1)
523 lo := int(v.Args[1].Reg() - mips.REG_R1)
524 xVal = hi<<2 + lo
525 yIsReg = true
526 yVal = int(v.Args[2].Reg() - mips.REG_R1)
527 case ssa.OpMIPSLoweredPanicBoundsRC:
528 xIsReg = true
529 xVal = int(v.Args[0].Reg() - mips.REG_R1)
530 c := v.Aux.(ssa.PanicBoundsC).C
531 if c >= 0 && c <= abi.BoundsMaxConst {
532 yVal = int(c)
533 } else {
534
535 yIsReg = true
536 if yVal == xVal {
537 yVal = 1
538 }
539 p := s.Prog(mips.AMOVW)
540 p.From.Type = obj.TYPE_CONST
541 p.From.Offset = c
542 p.To.Type = obj.TYPE_REG
543 p.To.Reg = mips.REG_R1 + int16(yVal)
544 }
545 case ssa.OpMIPSLoweredPanicExtendRC:
546 extend = true
547 xIsReg = true
548 hi := int(v.Args[0].Reg() - mips.REG_R1)
549 lo := int(v.Args[1].Reg() - mips.REG_R1)
550 xVal = hi<<2 + lo
551 c := v.Aux.(ssa.PanicBoundsC).C
552 if c >= 0 && c <= abi.BoundsMaxConst {
553 yVal = int(c)
554 } else {
555
556 for yVal == hi || yVal == lo {
557 yVal++
558 }
559 p := s.Prog(mips.AMOVW)
560 p.From.Type = obj.TYPE_CONST
561 p.From.Offset = c
562 p.To.Type = obj.TYPE_REG
563 p.To.Reg = mips.REG_R1 + int16(yVal)
564 }
565 case ssa.OpMIPSLoweredPanicBoundsCR:
566 yIsReg = true
567 yVal = int(v.Args[0].Reg() - mips.REG_R1)
568 c := v.Aux.(ssa.PanicBoundsC).C
569 if c >= 0 && c <= abi.BoundsMaxConst {
570 xVal = int(c)
571 } else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
572
573 xIsReg = true
574 if xVal == yVal {
575 xVal = 1
576 }
577 p := s.Prog(mips.AMOVW)
578 p.From.Type = obj.TYPE_CONST
579 p.From.Offset = c
580 p.To.Type = obj.TYPE_REG
581 p.To.Reg = mips.REG_R1 + int16(xVal)
582 } else {
583
584 extend = true
585 xIsReg = true
586 hi := 0
587 lo := 1
588 if hi == yVal {
589 hi = 2
590 }
591 if lo == yVal {
592 lo = 2
593 }
594 xVal = hi<<2 + lo
595 p := s.Prog(mips.AMOVW)
596 p.From.Type = obj.TYPE_CONST
597 p.From.Offset = c >> 32
598 p.To.Type = obj.TYPE_REG
599 p.To.Reg = mips.REG_R1 + int16(hi)
600 p = s.Prog(mips.AMOVW)
601 p.From.Type = obj.TYPE_CONST
602 p.From.Offset = int64(int32(c))
603 p.To.Type = obj.TYPE_REG
604 p.To.Reg = mips.REG_R1 + int16(lo)
605 }
606 case ssa.OpMIPSLoweredPanicBoundsCC:
607 c := v.Aux.(ssa.PanicBoundsCC).Cx
608 if c >= 0 && c <= abi.BoundsMaxConst {
609 xVal = int(c)
610 } else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
611
612 xIsReg = true
613 p := s.Prog(mips.AMOVW)
614 p.From.Type = obj.TYPE_CONST
615 p.From.Offset = c
616 p.To.Type = obj.TYPE_REG
617 p.To.Reg = mips.REG_R1 + int16(xVal)
618 } else {
619
620 extend = true
621 xIsReg = true
622 hi := 0
623 lo := 1
624 xVal = hi<<2 + lo
625 p := s.Prog(mips.AMOVW)
626 p.From.Type = obj.TYPE_CONST
627 p.From.Offset = c >> 32
628 p.To.Type = obj.TYPE_REG
629 p.To.Reg = mips.REG_R1 + int16(hi)
630 p = s.Prog(mips.AMOVW)
631 p.From.Type = obj.TYPE_CONST
632 p.From.Offset = int64(int32(c))
633 p.To.Type = obj.TYPE_REG
634 p.To.Reg = mips.REG_R1 + int16(lo)
635 }
636 c = v.Aux.(ssa.PanicBoundsCC).Cy
637 if c >= 0 && c <= abi.BoundsMaxConst {
638 yVal = int(c)
639 } else {
640
641 yIsReg = true
642 yVal = 2
643 p := s.Prog(mips.AMOVW)
644 p.From.Type = obj.TYPE_CONST
645 p.From.Offset = c
646 p.To.Type = obj.TYPE_REG
647 p.To.Reg = mips.REG_R1 + int16(yVal)
648 }
649 }
650 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
651
652 p := s.Prog(obj.APCDATA)
653 p.From.SetConst(abi.PCDATA_PanicBounds)
654 p.To.SetConst(int64(c))
655 p = s.Prog(obj.ACALL)
656 p.To.Type = obj.TYPE_MEM
657 p.To.Name = obj.NAME_EXTERN
658 if extend {
659 p.To.Sym = ir.Syms.PanicExtend
660 } else {
661 p.To.Sym = ir.Syms.PanicBounds
662 }
663
664 case ssa.OpMIPSLoweredAtomicLoad8,
665 ssa.OpMIPSLoweredAtomicLoad32:
666 s.Prog(mips.ASYNC)
667
668 var op obj.As
669 switch v.Op {
670 case ssa.OpMIPSLoweredAtomicLoad8:
671 op = mips.AMOVB
672 case ssa.OpMIPSLoweredAtomicLoad32:
673 op = mips.AMOVW
674 }
675 p := s.Prog(op)
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 = v.Reg0()
680
681 s.Prog(mips.ASYNC)
682 case ssa.OpMIPSLoweredAtomicStore8,
683 ssa.OpMIPSLoweredAtomicStore32:
684 s.Prog(mips.ASYNC)
685
686 var op obj.As
687 switch v.Op {
688 case ssa.OpMIPSLoweredAtomicStore8:
689 op = mips.AMOVB
690 case ssa.OpMIPSLoweredAtomicStore32:
691 op = mips.AMOVW
692 }
693 p := s.Prog(op)
694 p.From.Type = obj.TYPE_REG
695 p.From.Reg = v.Args[1].Reg()
696 p.To.Type = obj.TYPE_MEM
697 p.To.Reg = v.Args[0].Reg()
698
699 s.Prog(mips.ASYNC)
700 case ssa.OpMIPSLoweredAtomicStorezero:
701 s.Prog(mips.ASYNC)
702
703 p := s.Prog(mips.AMOVW)
704 p.From.Type = obj.TYPE_REG
705 p.From.Reg = mips.REGZERO
706 p.To.Type = obj.TYPE_MEM
707 p.To.Reg = v.Args[0].Reg()
708
709 s.Prog(mips.ASYNC)
710 case ssa.OpMIPSLoweredAtomicExchange:
711
712
713
714
715
716
717 s.Prog(mips.ASYNC)
718
719 p := s.Prog(mips.AMOVW)
720 p.From.Type = obj.TYPE_REG
721 p.From.Reg = v.Args[1].Reg()
722 p.To.Type = obj.TYPE_REG
723 p.To.Reg = mips.REGTMP
724
725 p1 := s.Prog(mips.ALL)
726 p1.From.Type = obj.TYPE_MEM
727 p1.From.Reg = v.Args[0].Reg()
728 p1.To.Type = obj.TYPE_REG
729 p1.To.Reg = v.Reg0()
730
731 p2 := s.Prog(mips.ASC)
732 p2.From.Type = obj.TYPE_REG
733 p2.From.Reg = mips.REGTMP
734 p2.To.Type = obj.TYPE_MEM
735 p2.To.Reg = v.Args[0].Reg()
736
737 p3 := s.Prog(mips.ABEQ)
738 p3.From.Type = obj.TYPE_REG
739 p3.From.Reg = mips.REGTMP
740 p3.To.Type = obj.TYPE_BRANCH
741 p3.To.SetTarget(p)
742
743 s.Prog(mips.ASYNC)
744 case ssa.OpMIPSLoweredAtomicAdd:
745
746
747
748
749
750
751
752 s.Prog(mips.ASYNC)
753
754 p := s.Prog(mips.ALL)
755 p.From.Type = obj.TYPE_MEM
756 p.From.Reg = v.Args[0].Reg()
757 p.To.Type = obj.TYPE_REG
758 p.To.Reg = v.Reg0()
759
760 p1 := s.Prog(mips.AADDU)
761 p1.From.Type = obj.TYPE_REG
762 p1.From.Reg = v.Args[1].Reg()
763 p1.Reg = v.Reg0()
764 p1.To.Type = obj.TYPE_REG
765 p1.To.Reg = mips.REGTMP
766
767 p2 := s.Prog(mips.ASC)
768 p2.From.Type = obj.TYPE_REG
769 p2.From.Reg = mips.REGTMP
770 p2.To.Type = obj.TYPE_MEM
771 p2.To.Reg = v.Args[0].Reg()
772
773 p3 := s.Prog(mips.ABEQ)
774 p3.From.Type = obj.TYPE_REG
775 p3.From.Reg = mips.REGTMP
776 p3.To.Type = obj.TYPE_BRANCH
777 p3.To.SetTarget(p)
778
779 s.Prog(mips.ASYNC)
780
781 p4 := s.Prog(mips.AADDU)
782 p4.From.Type = obj.TYPE_REG
783 p4.From.Reg = v.Args[1].Reg()
784 p4.Reg = v.Reg0()
785 p4.To.Type = obj.TYPE_REG
786 p4.To.Reg = v.Reg0()
787
788 case ssa.OpMIPSLoweredAtomicAddconst:
789
790
791
792
793
794
795
796 s.Prog(mips.ASYNC)
797
798 p := s.Prog(mips.ALL)
799 p.From.Type = obj.TYPE_MEM
800 p.From.Reg = v.Args[0].Reg()
801 p.To.Type = obj.TYPE_REG
802 p.To.Reg = v.Reg0()
803
804 p1 := s.Prog(mips.AADDU)
805 p1.From.Type = obj.TYPE_CONST
806 p1.From.Offset = v.AuxInt
807 p1.Reg = v.Reg0()
808 p1.To.Type = obj.TYPE_REG
809 p1.To.Reg = mips.REGTMP
810
811 p2 := s.Prog(mips.ASC)
812 p2.From.Type = obj.TYPE_REG
813 p2.From.Reg = mips.REGTMP
814 p2.To.Type = obj.TYPE_MEM
815 p2.To.Reg = v.Args[0].Reg()
816
817 p3 := s.Prog(mips.ABEQ)
818 p3.From.Type = obj.TYPE_REG
819 p3.From.Reg = mips.REGTMP
820 p3.To.Type = obj.TYPE_BRANCH
821 p3.To.SetTarget(p)
822
823 s.Prog(mips.ASYNC)
824
825 p4 := s.Prog(mips.AADDU)
826 p4.From.Type = obj.TYPE_CONST
827 p4.From.Offset = v.AuxInt
828 p4.Reg = v.Reg0()
829 p4.To.Type = obj.TYPE_REG
830 p4.To.Reg = v.Reg0()
831
832 case ssa.OpMIPSLoweredAtomicAnd,
833 ssa.OpMIPSLoweredAtomicOr:
834
835
836
837
838
839
840 s.Prog(mips.ASYNC)
841
842 p := s.Prog(mips.ALL)
843 p.From.Type = obj.TYPE_MEM
844 p.From.Reg = v.Args[0].Reg()
845 p.To.Type = obj.TYPE_REG
846 p.To.Reg = mips.REGTMP
847
848 p1 := s.Prog(v.Op.Asm())
849 p1.From.Type = obj.TYPE_REG
850 p1.From.Reg = v.Args[1].Reg()
851 p1.Reg = mips.REGTMP
852 p1.To.Type = obj.TYPE_REG
853 p1.To.Reg = mips.REGTMP
854
855 p2 := s.Prog(mips.ASC)
856 p2.From.Type = obj.TYPE_REG
857 p2.From.Reg = mips.REGTMP
858 p2.To.Type = obj.TYPE_MEM
859 p2.To.Reg = v.Args[0].Reg()
860
861 p3 := s.Prog(mips.ABEQ)
862 p3.From.Type = obj.TYPE_REG
863 p3.From.Reg = mips.REGTMP
864 p3.To.Type = obj.TYPE_BRANCH
865 p3.To.SetTarget(p)
866
867 s.Prog(mips.ASYNC)
868
869 case ssa.OpMIPSLoweredAtomicCas:
870
871
872
873
874
875
876
877
878 p := s.Prog(mips.AMOVW)
879 p.From.Type = obj.TYPE_REG
880 p.From.Reg = mips.REGZERO
881 p.To.Type = obj.TYPE_REG
882 p.To.Reg = v.Reg0()
883
884 s.Prog(mips.ASYNC)
885
886 p1 := s.Prog(mips.ALL)
887 p1.From.Type = obj.TYPE_MEM
888 p1.From.Reg = v.Args[0].Reg()
889 p1.To.Type = obj.TYPE_REG
890 p1.To.Reg = mips.REGTMP
891
892 p2 := s.Prog(mips.ABNE)
893 p2.From.Type = obj.TYPE_REG
894 p2.From.Reg = v.Args[1].Reg()
895 p2.Reg = mips.REGTMP
896 p2.To.Type = obj.TYPE_BRANCH
897
898 p3 := s.Prog(mips.AMOVW)
899 p3.From.Type = obj.TYPE_REG
900 p3.From.Reg = v.Args[2].Reg()
901 p3.To.Type = obj.TYPE_REG
902 p3.To.Reg = v.Reg0()
903
904 p4 := s.Prog(mips.ASC)
905 p4.From.Type = obj.TYPE_REG
906 p4.From.Reg = v.Reg0()
907 p4.To.Type = obj.TYPE_MEM
908 p4.To.Reg = v.Args[0].Reg()
909
910 p5 := s.Prog(mips.ABEQ)
911 p5.From.Type = obj.TYPE_REG
912 p5.From.Reg = v.Reg0()
913 p5.To.Type = obj.TYPE_BRANCH
914 p5.To.SetTarget(p1)
915
916 s.Prog(mips.ASYNC)
917
918 p6 := s.Prog(obj.ANOP)
919 p2.To.SetTarget(p6)
920
921 case ssa.OpMIPSLoweredNilCheck:
922
923 p := s.Prog(mips.AMOVB)
924 p.From.Type = obj.TYPE_MEM
925 p.From.Reg = v.Args[0].Reg()
926 ssagen.AddAux(&p.From, v)
927 p.To.Type = obj.TYPE_REG
928 p.To.Reg = mips.REGTMP
929 if logopt.Enabled() {
930 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
931 }
932 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
933 base.WarnfAt(v.Pos, "generated nil check")
934 }
935 case ssa.OpMIPSFPFlagTrue,
936 ssa.OpMIPSFPFlagFalse:
937
938
939
940 cmov := mips.ACMOVF
941 if v.Op == ssa.OpMIPSFPFlagFalse {
942 cmov = mips.ACMOVT
943 }
944 p := s.Prog(mips.AMOVW)
945 p.From.Type = obj.TYPE_CONST
946 p.From.Offset = 1
947 p.To.Type = obj.TYPE_REG
948 p.To.Reg = v.Reg()
949 p1 := s.Prog(cmov)
950 p1.From.Type = obj.TYPE_REG
951 p1.From.Reg = mips.REGZERO
952 p1.To.Type = obj.TYPE_REG
953 p1.To.Reg = v.Reg()
954
955 case ssa.OpMIPSLoweredGetClosurePtr:
956
957 ssagen.CheckLoweredGetClosurePtr(v)
958 case ssa.OpMIPSLoweredGetCallerSP:
959
960 p := s.Prog(mips.AMOVW)
961 p.From.Type = obj.TYPE_ADDR
962 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
963 p.From.Name = obj.NAME_PARAM
964 p.To.Type = obj.TYPE_REG
965 p.To.Reg = v.Reg()
966 case ssa.OpMIPSLoweredGetCallerPC:
967 p := s.Prog(obj.AGETCALLERPC)
968 p.To.Type = obj.TYPE_REG
969 p.To.Reg = v.Reg()
970 case ssa.OpMIPSLoweredPubBarrier:
971
972 s.Prog(v.Op.Asm())
973 case ssa.OpClobber, ssa.OpClobberReg:
974
975 default:
976 v.Fatalf("genValue not implemented: %s", v.LongString())
977 }
978 }
979
980 var blockJump = map[ssa.BlockKind]struct {
981 asm, invasm obj.As
982 }{
983 ssa.BlockMIPSEQ: {mips.ABEQ, mips.ABNE},
984 ssa.BlockMIPSNE: {mips.ABNE, mips.ABEQ},
985 ssa.BlockMIPSLTZ: {mips.ABLTZ, mips.ABGEZ},
986 ssa.BlockMIPSGEZ: {mips.ABGEZ, mips.ABLTZ},
987 ssa.BlockMIPSLEZ: {mips.ABLEZ, mips.ABGTZ},
988 ssa.BlockMIPSGTZ: {mips.ABGTZ, mips.ABLEZ},
989 ssa.BlockMIPSFPT: {mips.ABFPT, mips.ABFPF},
990 ssa.BlockMIPSFPF: {mips.ABFPF, mips.ABFPT},
991 }
992
993 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
994 switch b.Kind {
995 case ssa.BlockPlain, ssa.BlockDefer:
996 if b.Succs[0].Block() != next {
997 p := s.Prog(obj.AJMP)
998 p.To.Type = obj.TYPE_BRANCH
999 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
1000 }
1001 case ssa.BlockExit, ssa.BlockRetJmp:
1002 case ssa.BlockRet:
1003 s.Prog(obj.ARET)
1004 case ssa.BlockMIPSEQ, ssa.BlockMIPSNE,
1005 ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ,
1006 ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ,
1007 ssa.BlockMIPSFPT, ssa.BlockMIPSFPF:
1008 jmp := blockJump[b.Kind]
1009 var p *obj.Prog
1010 switch next {
1011 case b.Succs[0].Block():
1012 p = s.Br(jmp.invasm, b.Succs[1].Block())
1013 case b.Succs[1].Block():
1014 p = s.Br(jmp.asm, b.Succs[0].Block())
1015 default:
1016 if b.Likely != ssa.BranchUnlikely {
1017 p = s.Br(jmp.asm, b.Succs[0].Block())
1018 s.Br(obj.AJMP, b.Succs[1].Block())
1019 } else {
1020 p = s.Br(jmp.invasm, b.Succs[1].Block())
1021 s.Br(obj.AJMP, b.Succs[0].Block())
1022 }
1023 }
1024 if !b.Controls[0].Type.IsFlags() {
1025 p.From.Type = obj.TYPE_REG
1026 p.From.Reg = b.Controls[0].Reg()
1027 }
1028 default:
1029 b.Fatalf("branch not implemented: %s", b.LongString())
1030 }
1031 }
1032
View as plain text