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