1
2
3
4
5 package mips64
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 if t.IsSigned() {
55 return mips.AMOVW
56 } else {
57 return mips.AMOVWU
58 }
59 case 8:
60 return mips.AMOVV
61 }
62 }
63 panic("bad load type")
64 }
65
66
67 func storeByType(t *types.Type, r int16) obj.As {
68 if isFPreg(r) {
69 if t.Size() == 4 {
70 return mips.AMOVF
71 } else {
72 return mips.AMOVD
73 }
74 } else {
75 switch t.Size() {
76 case 1:
77 return mips.AMOVB
78 case 2:
79 return mips.AMOVH
80 case 4:
81 return mips.AMOVW
82 case 8:
83 return mips.AMOVV
84 }
85 }
86 panic("bad store type")
87 }
88
89 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
90 switch v.Op {
91 case ssa.OpCopy, ssa.OpMIPS64MOVVreg:
92 if v.Type.IsMemory() {
93 return
94 }
95 x := v.Args[0].Reg()
96 y := v.Reg()
97 if x == y {
98 return
99 }
100 as := mips.AMOVV
101 if isFPreg(x) && isFPreg(y) {
102 as = mips.AMOVD
103 }
104 p := s.Prog(as)
105 p.From.Type = obj.TYPE_REG
106 p.From.Reg = x
107 p.To.Type = obj.TYPE_REG
108 p.To.Reg = y
109 if isHILO(x) && isHILO(y) || isHILO(x) && isFPreg(y) || isFPreg(x) && isHILO(y) {
110
111 p.To.Reg = mips.REGTMP
112 p = s.Prog(mips.AMOVV)
113 p.From.Type = obj.TYPE_REG
114 p.From.Reg = mips.REGTMP
115 p.To.Type = obj.TYPE_REG
116 p.To.Reg = y
117 }
118 case ssa.OpMIPS64MOVVnop, ssa.OpMIPS64ZERO:
119
120 case ssa.OpLoadReg:
121 if v.Type.IsFlags() {
122 v.Fatalf("load flags not implemented: %v", v.LongString())
123 return
124 }
125 r := v.Reg()
126 p := s.Prog(loadByType(v.Type, r))
127 ssagen.AddrAuto(&p.From, v.Args[0])
128 p.To.Type = obj.TYPE_REG
129 p.To.Reg = r
130 if isHILO(r) {
131
132 p.To.Reg = mips.REGTMP
133 p = s.Prog(mips.AMOVV)
134 p.From.Type = obj.TYPE_REG
135 p.From.Reg = mips.REGTMP
136 p.To.Type = obj.TYPE_REG
137 p.To.Reg = r
138 }
139 case ssa.OpStoreReg:
140 if v.Type.IsFlags() {
141 v.Fatalf("store flags not implemented: %v", v.LongString())
142 return
143 }
144 r := v.Args[0].Reg()
145 if isHILO(r) {
146
147 p := s.Prog(mips.AMOVV)
148 p.From.Type = obj.TYPE_REG
149 p.From.Reg = r
150 p.To.Type = obj.TYPE_REG
151 p.To.Reg = mips.REGTMP
152 r = mips.REGTMP
153 }
154 p := s.Prog(storeByType(v.Type, r))
155 p.From.Type = obj.TYPE_REG
156 p.From.Reg = r
157 ssagen.AddrAuto(&p.To, v)
158 case ssa.OpMIPS64ADDV,
159 ssa.OpMIPS64SUBV,
160 ssa.OpMIPS64AND,
161 ssa.OpMIPS64OR,
162 ssa.OpMIPS64XOR,
163 ssa.OpMIPS64NOR,
164 ssa.OpMIPS64SLLV,
165 ssa.OpMIPS64SRLV,
166 ssa.OpMIPS64SRAV,
167 ssa.OpMIPS64ADDF,
168 ssa.OpMIPS64ADDD,
169 ssa.OpMIPS64SUBF,
170 ssa.OpMIPS64SUBD,
171 ssa.OpMIPS64MULF,
172 ssa.OpMIPS64MULD,
173 ssa.OpMIPS64DIVF,
174 ssa.OpMIPS64DIVD:
175 p := s.Prog(v.Op.Asm())
176 p.From.Type = obj.TYPE_REG
177 p.From.Reg = v.Args[1].Reg()
178 p.Reg = v.Args[0].Reg()
179 p.To.Type = obj.TYPE_REG
180 p.To.Reg = v.Reg()
181 case ssa.OpMIPS64SGT,
182 ssa.OpMIPS64SGTU:
183 p := s.Prog(v.Op.Asm())
184 p.From.Type = obj.TYPE_REG
185 p.From.Reg = v.Args[0].Reg()
186 p.Reg = v.Args[1].Reg()
187 p.To.Type = obj.TYPE_REG
188 p.To.Reg = v.Reg()
189 case ssa.OpMIPS64ADDVconst,
190 ssa.OpMIPS64SUBVconst,
191 ssa.OpMIPS64ANDconst,
192 ssa.OpMIPS64ORconst,
193 ssa.OpMIPS64XORconst,
194 ssa.OpMIPS64NORconst,
195 ssa.OpMIPS64SLLVconst,
196 ssa.OpMIPS64SRLVconst,
197 ssa.OpMIPS64SRAVconst,
198 ssa.OpMIPS64SGTconst,
199 ssa.OpMIPS64SGTUconst:
200 p := s.Prog(v.Op.Asm())
201 p.From.Type = obj.TYPE_CONST
202 p.From.Offset = v.AuxInt
203 p.Reg = v.Args[0].Reg()
204 p.To.Type = obj.TYPE_REG
205 p.To.Reg = v.Reg()
206 case ssa.OpMIPS64MULV,
207 ssa.OpMIPS64MULVU,
208 ssa.OpMIPS64DIVV,
209 ssa.OpMIPS64DIVVU:
210
211
212
213
214
215 p := s.Prog(v.Op.Asm())
216 p.From.Type = obj.TYPE_REG
217 p.From.Reg = v.Args[1].Reg()
218 p.Reg = v.Args[0].Reg()
219 p1 := s.Prog(mips.AMOVV)
220 p1.From.Type = obj.TYPE_REG
221 p1.From.Reg = mips.REG_HI
222 p1.To.Type = obj.TYPE_REG
223 p1.To.Reg = v.Reg0()
224 p2 := s.Prog(mips.AMOVV)
225 p2.From.Type = obj.TYPE_REG
226 p2.From.Reg = mips.REG_LO
227 p2.To.Type = obj.TYPE_REG
228 p2.To.Reg = v.Reg1()
229 case ssa.OpMIPS64MOVVconst:
230 r := v.Reg()
231 p := s.Prog(v.Op.Asm())
232 p.From.Type = obj.TYPE_CONST
233 p.From.Offset = v.AuxInt
234 p.To.Type = obj.TYPE_REG
235 p.To.Reg = r
236 if isFPreg(r) || isHILO(r) {
237
238 p.To.Reg = mips.REGTMP
239 p = s.Prog(mips.AMOVV)
240 p.From.Type = obj.TYPE_REG
241 p.From.Reg = mips.REGTMP
242 p.To.Type = obj.TYPE_REG
243 p.To.Reg = r
244 }
245 case ssa.OpMIPS64MOVFconst,
246 ssa.OpMIPS64MOVDconst:
247 p := s.Prog(v.Op.Asm())
248 p.From.Type = obj.TYPE_FCONST
249 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
250 p.To.Type = obj.TYPE_REG
251 p.To.Reg = v.Reg()
252 case ssa.OpMIPS64CMPEQF,
253 ssa.OpMIPS64CMPEQD,
254 ssa.OpMIPS64CMPGEF,
255 ssa.OpMIPS64CMPGED,
256 ssa.OpMIPS64CMPGTF,
257 ssa.OpMIPS64CMPGTD:
258 p := s.Prog(v.Op.Asm())
259 p.From.Type = obj.TYPE_REG
260 p.From.Reg = v.Args[0].Reg()
261 p.Reg = v.Args[1].Reg()
262 case ssa.OpMIPS64MOVVaddr:
263 p := s.Prog(mips.AMOVV)
264 p.From.Type = obj.TYPE_ADDR
265 p.From.Reg = v.Args[0].Reg()
266 var wantreg string
267
268
269
270
271
272 switch v.Aux.(type) {
273 default:
274 v.Fatalf("aux is of unknown type %T", v.Aux)
275 case *obj.LSym:
276 wantreg = "SB"
277 ssagen.AddAux(&p.From, v)
278 case *ir.Name:
279 wantreg = "SP"
280 ssagen.AddAux(&p.From, v)
281 case nil:
282
283 wantreg = "SP"
284 p.From.Offset = v.AuxInt
285 }
286 if reg := v.Args[0].RegName(); reg != wantreg {
287 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
288 }
289 p.To.Type = obj.TYPE_REG
290 p.To.Reg = v.Reg()
291 case ssa.OpMIPS64MOVBload,
292 ssa.OpMIPS64MOVBUload,
293 ssa.OpMIPS64MOVHload,
294 ssa.OpMIPS64MOVHUload,
295 ssa.OpMIPS64MOVWload,
296 ssa.OpMIPS64MOVWUload,
297 ssa.OpMIPS64MOVVload,
298 ssa.OpMIPS64MOVFload,
299 ssa.OpMIPS64MOVDload:
300 p := s.Prog(v.Op.Asm())
301 p.From.Type = obj.TYPE_MEM
302 p.From.Reg = v.Args[0].Reg()
303 ssagen.AddAux(&p.From, v)
304 p.To.Type = obj.TYPE_REG
305 p.To.Reg = v.Reg()
306 case ssa.OpMIPS64MOVBstore,
307 ssa.OpMIPS64MOVHstore,
308 ssa.OpMIPS64MOVWstore,
309 ssa.OpMIPS64MOVVstore,
310 ssa.OpMIPS64MOVFstore,
311 ssa.OpMIPS64MOVDstore:
312 p := s.Prog(v.Op.Asm())
313 p.From.Type = obj.TYPE_REG
314 p.From.Reg = v.Args[1].Reg()
315 p.To.Type = obj.TYPE_MEM
316 p.To.Reg = v.Args[0].Reg()
317 ssagen.AddAux(&p.To, v)
318 case ssa.OpMIPS64MOVBreg,
319 ssa.OpMIPS64MOVBUreg,
320 ssa.OpMIPS64MOVHreg,
321 ssa.OpMIPS64MOVHUreg,
322 ssa.OpMIPS64MOVWreg,
323 ssa.OpMIPS64MOVWUreg:
324 a := v.Args[0]
325 for a.Op == ssa.OpCopy || a.Op == ssa.OpMIPS64MOVVreg {
326 a = a.Args[0]
327 }
328 if a.Op == ssa.OpLoadReg && mips.REG_R0 <= a.Reg() && a.Reg() <= mips.REG_R31 {
329
330
331
332 t := a.Type
333 switch {
334 case v.Op == ssa.OpMIPS64MOVBreg && t.Size() == 1 && t.IsSigned(),
335 v.Op == ssa.OpMIPS64MOVBUreg && t.Size() == 1 && !t.IsSigned(),
336 v.Op == ssa.OpMIPS64MOVHreg && t.Size() == 2 && t.IsSigned(),
337 v.Op == ssa.OpMIPS64MOVHUreg && t.Size() == 2 && !t.IsSigned(),
338 v.Op == ssa.OpMIPS64MOVWreg && t.Size() == 4 && t.IsSigned(),
339 v.Op == ssa.OpMIPS64MOVWUreg && t.Size() == 4 && !t.IsSigned():
340
341 if v.Reg() == v.Args[0].Reg() {
342 return
343 }
344 p := s.Prog(mips.AMOVV)
345 p.From.Type = obj.TYPE_REG
346 p.From.Reg = v.Args[0].Reg()
347 p.To.Type = obj.TYPE_REG
348 p.To.Reg = v.Reg()
349 return
350 default:
351 }
352 }
353 fallthrough
354 case ssa.OpMIPS64MOVWF,
355 ssa.OpMIPS64MOVWD,
356 ssa.OpMIPS64TRUNCFW,
357 ssa.OpMIPS64TRUNCDW,
358 ssa.OpMIPS64MOVVF,
359 ssa.OpMIPS64MOVVD,
360 ssa.OpMIPS64TRUNCFV,
361 ssa.OpMIPS64TRUNCDV,
362 ssa.OpMIPS64MOVFD,
363 ssa.OpMIPS64MOVDF,
364 ssa.OpMIPS64MOVWfpgp,
365 ssa.OpMIPS64MOVWgpfp,
366 ssa.OpMIPS64MOVVfpgp,
367 ssa.OpMIPS64MOVVgpfp,
368 ssa.OpMIPS64NEGF,
369 ssa.OpMIPS64NEGD,
370 ssa.OpMIPS64ABSD,
371 ssa.OpMIPS64SQRTF,
372 ssa.OpMIPS64SQRTD:
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.OpMIPS64NEGV:
379
380 p := s.Prog(mips.ASUBVU)
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.OpMIPS64DUFFZERO:
387
388 p := s.Prog(mips.ASUBVU)
389 p.From.Type = obj.TYPE_CONST
390 p.From.Offset = 8
391 p.Reg = v.Args[0].Reg()
392 p.To.Type = obj.TYPE_REG
393 p.To.Reg = mips.REG_R1
394 p = s.Prog(obj.ADUFFZERO)
395 p.To.Type = obj.TYPE_MEM
396 p.To.Name = obj.NAME_EXTERN
397 p.To.Sym = ir.Syms.Duffzero
398 p.To.Offset = v.AuxInt
399 case ssa.OpMIPS64LoweredZero:
400
401
402
403
404
405 var sz int64
406 var mov obj.As
407 switch {
408 case v.AuxInt%8 == 0:
409 sz = 8
410 mov = mips.AMOVV
411 case v.AuxInt%4 == 0:
412 sz = 4
413 mov = mips.AMOVW
414 case v.AuxInt%2 == 0:
415 sz = 2
416 mov = mips.AMOVH
417 default:
418 sz = 1
419 mov = mips.AMOVB
420 }
421 p := s.Prog(mips.ASUBVU)
422 p.From.Type = obj.TYPE_CONST
423 p.From.Offset = sz
424 p.To.Type = obj.TYPE_REG
425 p.To.Reg = mips.REG_R1
426 p2 := s.Prog(mov)
427 p2.From.Type = obj.TYPE_REG
428 p2.From.Reg = mips.REGZERO
429 p2.To.Type = obj.TYPE_MEM
430 p2.To.Reg = mips.REG_R1
431 p2.To.Offset = sz
432 p3 := s.Prog(mips.AADDVU)
433 p3.From.Type = obj.TYPE_CONST
434 p3.From.Offset = sz
435 p3.To.Type = obj.TYPE_REG
436 p3.To.Reg = mips.REG_R1
437 p4 := s.Prog(mips.ABNE)
438 p4.From.Type = obj.TYPE_REG
439 p4.From.Reg = v.Args[1].Reg()
440 p4.Reg = mips.REG_R1
441 p4.To.Type = obj.TYPE_BRANCH
442 p4.To.SetTarget(p2)
443 case ssa.OpMIPS64DUFFCOPY:
444 p := s.Prog(obj.ADUFFCOPY)
445 p.To.Type = obj.TYPE_MEM
446 p.To.Name = obj.NAME_EXTERN
447 p.To.Sym = ir.Syms.Duffcopy
448 p.To.Offset = v.AuxInt
449 case ssa.OpMIPS64LoweredMove:
450
451
452
453
454
455
456
457 var sz int64
458 var mov obj.As
459 switch {
460 case v.AuxInt%8 == 0:
461 sz = 8
462 mov = mips.AMOVV
463 case v.AuxInt%4 == 0:
464 sz = 4
465 mov = mips.AMOVW
466 case v.AuxInt%2 == 0:
467 sz = 2
468 mov = mips.AMOVH
469 default:
470 sz = 1
471 mov = mips.AMOVB
472 }
473 p := s.Prog(mips.ASUBVU)
474 p.From.Type = obj.TYPE_CONST
475 p.From.Offset = sz
476 p.To.Type = obj.TYPE_REG
477 p.To.Reg = mips.REG_R1
478 p2 := s.Prog(mov)
479 p2.From.Type = obj.TYPE_MEM
480 p2.From.Reg = mips.REG_R1
481 p2.From.Offset = sz
482 p2.To.Type = obj.TYPE_REG
483 p2.To.Reg = mips.REGTMP
484 p3 := s.Prog(mov)
485 p3.From.Type = obj.TYPE_REG
486 p3.From.Reg = mips.REGTMP
487 p3.To.Type = obj.TYPE_MEM
488 p3.To.Reg = mips.REG_R2
489 p4 := s.Prog(mips.AADDVU)
490 p4.From.Type = obj.TYPE_CONST
491 p4.From.Offset = sz
492 p4.To.Type = obj.TYPE_REG
493 p4.To.Reg = mips.REG_R1
494 p5 := s.Prog(mips.AADDVU)
495 p5.From.Type = obj.TYPE_CONST
496 p5.From.Offset = sz
497 p5.To.Type = obj.TYPE_REG
498 p5.To.Reg = mips.REG_R2
499 p6 := s.Prog(mips.ABNE)
500 p6.From.Type = obj.TYPE_REG
501 p6.From.Reg = v.Args[2].Reg()
502 p6.Reg = mips.REG_R1
503 p6.To.Type = obj.TYPE_BRANCH
504 p6.To.SetTarget(p2)
505 case ssa.OpMIPS64CALLstatic, ssa.OpMIPS64CALLclosure, ssa.OpMIPS64CALLinter:
506 s.Call(v)
507 case ssa.OpMIPS64CALLtail:
508 s.TailCall(v)
509 case ssa.OpMIPS64LoweredWB:
510 p := s.Prog(obj.ACALL)
511 p.To.Type = obj.TYPE_MEM
512 p.To.Name = obj.NAME_EXTERN
513
514 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
515
516 case ssa.OpMIPS64LoweredPanicBoundsRR, ssa.OpMIPS64LoweredPanicBoundsRC, ssa.OpMIPS64LoweredPanicBoundsCR, ssa.OpMIPS64LoweredPanicBoundsCC:
517
518 code, signed := ssa.BoundsKind(v.AuxInt).Code()
519 xIsReg := false
520 yIsReg := false
521 xVal := 0
522 yVal := 0
523 switch v.Op {
524 case ssa.OpMIPS64LoweredPanicBoundsRR:
525 xIsReg = true
526 xVal = int(v.Args[0].Reg() - mips.REG_R1)
527 yIsReg = true
528 yVal = int(v.Args[1].Reg() - mips.REG_R1)
529 case ssa.OpMIPS64LoweredPanicBoundsRC:
530 xIsReg = true
531 xVal = int(v.Args[0].Reg() - mips.REG_R1)
532 c := v.Aux.(ssa.PanicBoundsC).C
533 if c >= 0 && c <= abi.BoundsMaxConst {
534 yVal = int(c)
535 } else {
536
537 yIsReg = true
538 if yVal == xVal {
539 yVal = 1
540 }
541 p := s.Prog(mips.AMOVV)
542 p.From.Type = obj.TYPE_CONST
543 p.From.Offset = c
544 p.To.Type = obj.TYPE_REG
545 p.To.Reg = mips.REG_R1 + int16(yVal)
546 }
547 case ssa.OpMIPS64LoweredPanicBoundsCR:
548 yIsReg = true
549 yVal = int(v.Args[0].Reg() - mips.REG_R1)
550 c := v.Aux.(ssa.PanicBoundsC).C
551 if c >= 0 && c <= abi.BoundsMaxConst {
552 xVal = int(c)
553 } else {
554
555 xIsReg = true
556 if xVal == yVal {
557 xVal = 1
558 }
559 p := s.Prog(mips.AMOVV)
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(xVal)
564 }
565 case ssa.OpMIPS64LoweredPanicBoundsCC:
566 c := v.Aux.(ssa.PanicBoundsCC).Cx
567 if c >= 0 && c <= abi.BoundsMaxConst {
568 xVal = int(c)
569 } else {
570
571 xIsReg = true
572 p := s.Prog(mips.AMOVV)
573 p.From.Type = obj.TYPE_CONST
574 p.From.Offset = c
575 p.To.Type = obj.TYPE_REG
576 p.To.Reg = mips.REG_R1 + int16(xVal)
577 }
578 c = v.Aux.(ssa.PanicBoundsCC).Cy
579 if c >= 0 && c <= abi.BoundsMaxConst {
580 yVal = int(c)
581 } else {
582
583 yIsReg = true
584 yVal = 1
585 p := s.Prog(mips.AMOVV)
586 p.From.Type = obj.TYPE_CONST
587 p.From.Offset = c
588 p.To.Type = obj.TYPE_REG
589 p.To.Reg = mips.REG_R1 + int16(yVal)
590 }
591 }
592 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
593
594 p := s.Prog(obj.APCDATA)
595 p.From.SetConst(abi.PCDATA_PanicBounds)
596 p.To.SetConst(int64(c))
597 p = s.Prog(obj.ACALL)
598 p.To.Type = obj.TYPE_MEM
599 p.To.Name = obj.NAME_EXTERN
600 p.To.Sym = ir.Syms.PanicBounds
601
602 case ssa.OpMIPS64LoweredAtomicLoad8, ssa.OpMIPS64LoweredAtomicLoad32, ssa.OpMIPS64LoweredAtomicLoad64:
603 as := mips.AMOVV
604 switch v.Op {
605 case ssa.OpMIPS64LoweredAtomicLoad8:
606 as = mips.AMOVB
607 case ssa.OpMIPS64LoweredAtomicLoad32:
608 as = mips.AMOVW
609 }
610 s.Prog(mips.ASYNC)
611 p := s.Prog(as)
612 p.From.Type = obj.TYPE_MEM
613 p.From.Reg = v.Args[0].Reg()
614 p.To.Type = obj.TYPE_REG
615 p.To.Reg = v.Reg0()
616 s.Prog(mips.ASYNC)
617 case ssa.OpMIPS64LoweredAtomicStore8, ssa.OpMIPS64LoweredAtomicStore32, ssa.OpMIPS64LoweredAtomicStore64:
618 as := mips.AMOVV
619 switch v.Op {
620 case ssa.OpMIPS64LoweredAtomicStore8:
621 as = mips.AMOVB
622 case ssa.OpMIPS64LoweredAtomicStore32:
623 as = mips.AMOVW
624 }
625 s.Prog(mips.ASYNC)
626 p := s.Prog(as)
627 p.From.Type = obj.TYPE_REG
628 p.From.Reg = v.Args[1].Reg()
629 p.To.Type = obj.TYPE_MEM
630 p.To.Reg = v.Args[0].Reg()
631 s.Prog(mips.ASYNC)
632 case ssa.OpMIPS64LoweredAtomicStorezero32, ssa.OpMIPS64LoweredAtomicStorezero64:
633 as := mips.AMOVV
634 if v.Op == ssa.OpMIPS64LoweredAtomicStorezero32 {
635 as = mips.AMOVW
636 }
637 s.Prog(mips.ASYNC)
638 p := s.Prog(as)
639 p.From.Type = obj.TYPE_REG
640 p.From.Reg = mips.REGZERO
641 p.To.Type = obj.TYPE_MEM
642 p.To.Reg = v.Args[0].Reg()
643 s.Prog(mips.ASYNC)
644 case ssa.OpMIPS64LoweredAtomicExchange32, ssa.OpMIPS64LoweredAtomicExchange64:
645
646
647
648
649
650
651 ll := mips.ALLV
652 sc := mips.ASCV
653 if v.Op == ssa.OpMIPS64LoweredAtomicExchange32 {
654 ll = mips.ALL
655 sc = mips.ASC
656 }
657 s.Prog(mips.ASYNC)
658 p := s.Prog(mips.AMOVV)
659 p.From.Type = obj.TYPE_REG
660 p.From.Reg = v.Args[1].Reg()
661 p.To.Type = obj.TYPE_REG
662 p.To.Reg = mips.REGTMP
663 p1 := s.Prog(ll)
664 p1.From.Type = obj.TYPE_MEM
665 p1.From.Reg = v.Args[0].Reg()
666 p1.To.Type = obj.TYPE_REG
667 p1.To.Reg = v.Reg0()
668 p2 := s.Prog(sc)
669 p2.From.Type = obj.TYPE_REG
670 p2.From.Reg = mips.REGTMP
671 p2.To.Type = obj.TYPE_MEM
672 p2.To.Reg = v.Args[0].Reg()
673 p3 := s.Prog(mips.ABEQ)
674 p3.From.Type = obj.TYPE_REG
675 p3.From.Reg = mips.REGTMP
676 p3.To.Type = obj.TYPE_BRANCH
677 p3.To.SetTarget(p)
678 s.Prog(mips.ASYNC)
679 case ssa.OpMIPS64LoweredAtomicAdd32, ssa.OpMIPS64LoweredAtomicAdd64:
680
681
682
683
684
685
686
687 ll := mips.ALLV
688 sc := mips.ASCV
689 if v.Op == ssa.OpMIPS64LoweredAtomicAdd32 {
690 ll = mips.ALL
691 sc = mips.ASC
692 }
693 s.Prog(mips.ASYNC)
694 p := s.Prog(ll)
695 p.From.Type = obj.TYPE_MEM
696 p.From.Reg = v.Args[0].Reg()
697 p.To.Type = obj.TYPE_REG
698 p.To.Reg = v.Reg0()
699 p1 := s.Prog(mips.AADDVU)
700 p1.From.Type = obj.TYPE_REG
701 p1.From.Reg = v.Args[1].Reg()
702 p1.Reg = v.Reg0()
703 p1.To.Type = obj.TYPE_REG
704 p1.To.Reg = mips.REGTMP
705 p2 := s.Prog(sc)
706 p2.From.Type = obj.TYPE_REG
707 p2.From.Reg = mips.REGTMP
708 p2.To.Type = obj.TYPE_MEM
709 p2.To.Reg = v.Args[0].Reg()
710 p3 := s.Prog(mips.ABEQ)
711 p3.From.Type = obj.TYPE_REG
712 p3.From.Reg = mips.REGTMP
713 p3.To.Type = obj.TYPE_BRANCH
714 p3.To.SetTarget(p)
715 s.Prog(mips.ASYNC)
716 p4 := s.Prog(mips.AADDVU)
717 p4.From.Type = obj.TYPE_REG
718 p4.From.Reg = v.Args[1].Reg()
719 p4.Reg = v.Reg0()
720 p4.To.Type = obj.TYPE_REG
721 p4.To.Reg = v.Reg0()
722 case ssa.OpMIPS64LoweredAtomicAddconst32, ssa.OpMIPS64LoweredAtomicAddconst64:
723
724
725
726
727
728
729
730 ll := mips.ALLV
731 sc := mips.ASCV
732 if v.Op == ssa.OpMIPS64LoweredAtomicAddconst32 {
733 ll = mips.ALL
734 sc = mips.ASC
735 }
736 s.Prog(mips.ASYNC)
737 p := s.Prog(ll)
738 p.From.Type = obj.TYPE_MEM
739 p.From.Reg = v.Args[0].Reg()
740 p.To.Type = obj.TYPE_REG
741 p.To.Reg = v.Reg0()
742 p1 := s.Prog(mips.AADDVU)
743 p1.From.Type = obj.TYPE_CONST
744 p1.From.Offset = v.AuxInt
745 p1.Reg = v.Reg0()
746 p1.To.Type = obj.TYPE_REG
747 p1.To.Reg = mips.REGTMP
748 p2 := s.Prog(sc)
749 p2.From.Type = obj.TYPE_REG
750 p2.From.Reg = mips.REGTMP
751 p2.To.Type = obj.TYPE_MEM
752 p2.To.Reg = v.Args[0].Reg()
753 p3 := s.Prog(mips.ABEQ)
754 p3.From.Type = obj.TYPE_REG
755 p3.From.Reg = mips.REGTMP
756 p3.To.Type = obj.TYPE_BRANCH
757 p3.To.SetTarget(p)
758 s.Prog(mips.ASYNC)
759 p4 := s.Prog(mips.AADDVU)
760 p4.From.Type = obj.TYPE_CONST
761 p4.From.Offset = v.AuxInt
762 p4.Reg = v.Reg0()
763 p4.To.Type = obj.TYPE_REG
764 p4.To.Reg = v.Reg0()
765 case ssa.OpMIPS64LoweredAtomicAnd32,
766 ssa.OpMIPS64LoweredAtomicOr32:
767
768
769
770
771
772
773 s.Prog(mips.ASYNC)
774
775 p := s.Prog(mips.ALL)
776 p.From.Type = obj.TYPE_MEM
777 p.From.Reg = v.Args[0].Reg()
778 p.To.Type = obj.TYPE_REG
779 p.To.Reg = mips.REGTMP
780
781 p1 := s.Prog(v.Op.Asm())
782 p1.From.Type = obj.TYPE_REG
783 p1.From.Reg = v.Args[1].Reg()
784 p1.Reg = mips.REGTMP
785 p1.To.Type = obj.TYPE_REG
786 p1.To.Reg = mips.REGTMP
787
788 p2 := s.Prog(mips.ASC)
789 p2.From.Type = obj.TYPE_REG
790 p2.From.Reg = mips.REGTMP
791 p2.To.Type = obj.TYPE_MEM
792 p2.To.Reg = v.Args[0].Reg()
793
794 p3 := s.Prog(mips.ABEQ)
795 p3.From.Type = obj.TYPE_REG
796 p3.From.Reg = mips.REGTMP
797 p3.To.Type = obj.TYPE_BRANCH
798 p3.To.SetTarget(p)
799
800 s.Prog(mips.ASYNC)
801
802 case ssa.OpMIPS64LoweredAtomicCas32, ssa.OpMIPS64LoweredAtomicCas64:
803
804
805
806
807
808
809
810
811 ll := mips.ALLV
812 sc := mips.ASCV
813 if v.Op == ssa.OpMIPS64LoweredAtomicCas32 {
814 ll = mips.ALL
815 sc = mips.ASC
816 }
817 p := s.Prog(mips.AMOVV)
818 p.From.Type = obj.TYPE_REG
819 p.From.Reg = mips.REGZERO
820 p.To.Type = obj.TYPE_REG
821 p.To.Reg = v.Reg0()
822 s.Prog(mips.ASYNC)
823 p1 := s.Prog(ll)
824 p1.From.Type = obj.TYPE_MEM
825 p1.From.Reg = v.Args[0].Reg()
826 p1.To.Type = obj.TYPE_REG
827 p1.To.Reg = mips.REGTMP
828 p2 := s.Prog(mips.ABNE)
829 p2.From.Type = obj.TYPE_REG
830 p2.From.Reg = v.Args[1].Reg()
831 p2.Reg = mips.REGTMP
832 p2.To.Type = obj.TYPE_BRANCH
833 p3 := s.Prog(mips.AMOVV)
834 p3.From.Type = obj.TYPE_REG
835 p3.From.Reg = v.Args[2].Reg()
836 p3.To.Type = obj.TYPE_REG
837 p3.To.Reg = v.Reg0()
838 p4 := s.Prog(sc)
839 p4.From.Type = obj.TYPE_REG
840 p4.From.Reg = v.Reg0()
841 p4.To.Type = obj.TYPE_MEM
842 p4.To.Reg = v.Args[0].Reg()
843 p5 := s.Prog(mips.ABEQ)
844 p5.From.Type = obj.TYPE_REG
845 p5.From.Reg = v.Reg0()
846 p5.To.Type = obj.TYPE_BRANCH
847 p5.To.SetTarget(p1)
848 p6 := s.Prog(mips.ASYNC)
849 p2.To.SetTarget(p6)
850 case ssa.OpMIPS64LoweredNilCheck:
851
852 p := s.Prog(mips.AMOVB)
853 p.From.Type = obj.TYPE_MEM
854 p.From.Reg = v.Args[0].Reg()
855 ssagen.AddAux(&p.From, v)
856 p.To.Type = obj.TYPE_REG
857 p.To.Reg = mips.REGTMP
858 if logopt.Enabled() {
859 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
860 }
861 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
862 base.WarnfAt(v.Pos, "generated nil check")
863 }
864 case ssa.OpMIPS64FPFlagTrue,
865 ssa.OpMIPS64FPFlagFalse:
866
867
868
869 branch := mips.ABFPF
870 if v.Op == ssa.OpMIPS64FPFlagFalse {
871 branch = mips.ABFPT
872 }
873 p := s.Prog(mips.AMOVV)
874 p.From.Type = obj.TYPE_REG
875 p.From.Reg = mips.REGZERO
876 p.To.Type = obj.TYPE_REG
877 p.To.Reg = v.Reg()
878 p2 := s.Prog(branch)
879 p2.To.Type = obj.TYPE_BRANCH
880 p3 := s.Prog(mips.AMOVV)
881 p3.From.Type = obj.TYPE_CONST
882 p3.From.Offset = 1
883 p3.To.Type = obj.TYPE_REG
884 p3.To.Reg = v.Reg()
885 p4 := s.Prog(obj.ANOP)
886 p2.To.SetTarget(p4)
887 case ssa.OpMIPS64LoweredGetClosurePtr:
888
889 ssagen.CheckLoweredGetClosurePtr(v)
890 case ssa.OpMIPS64LoweredGetCallerSP:
891
892 p := s.Prog(mips.AMOVV)
893 p.From.Type = obj.TYPE_ADDR
894 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
895 p.From.Name = obj.NAME_PARAM
896 p.To.Type = obj.TYPE_REG
897 p.To.Reg = v.Reg()
898 case ssa.OpMIPS64LoweredGetCallerPC:
899 p := s.Prog(obj.AGETCALLERPC)
900 p.To.Type = obj.TYPE_REG
901 p.To.Reg = v.Reg()
902 case ssa.OpMIPS64LoweredPubBarrier:
903
904 s.Prog(v.Op.Asm())
905 case ssa.OpClobber, ssa.OpClobberReg:
906
907 default:
908 v.Fatalf("genValue not implemented: %s", v.LongString())
909 }
910 }
911
912 var blockJump = map[ssa.BlockKind]struct {
913 asm, invasm obj.As
914 }{
915 ssa.BlockMIPS64EQ: {mips.ABEQ, mips.ABNE},
916 ssa.BlockMIPS64NE: {mips.ABNE, mips.ABEQ},
917 ssa.BlockMIPS64LTZ: {mips.ABLTZ, mips.ABGEZ},
918 ssa.BlockMIPS64GEZ: {mips.ABGEZ, mips.ABLTZ},
919 ssa.BlockMIPS64LEZ: {mips.ABLEZ, mips.ABGTZ},
920 ssa.BlockMIPS64GTZ: {mips.ABGTZ, mips.ABLEZ},
921 ssa.BlockMIPS64FPT: {mips.ABFPT, mips.ABFPF},
922 ssa.BlockMIPS64FPF: {mips.ABFPF, mips.ABFPT},
923 }
924
925 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
926 switch b.Kind {
927 case ssa.BlockPlain, ssa.BlockDefer:
928 if b.Succs[0].Block() != next {
929 p := s.Prog(obj.AJMP)
930 p.To.Type = obj.TYPE_BRANCH
931 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
932 }
933 case ssa.BlockExit, ssa.BlockRetJmp:
934 case ssa.BlockRet:
935 s.Prog(obj.ARET)
936 case ssa.BlockMIPS64EQ, ssa.BlockMIPS64NE,
937 ssa.BlockMIPS64LTZ, ssa.BlockMIPS64GEZ,
938 ssa.BlockMIPS64LEZ, ssa.BlockMIPS64GTZ,
939 ssa.BlockMIPS64FPT, ssa.BlockMIPS64FPF:
940 jmp := blockJump[b.Kind]
941 var p *obj.Prog
942 switch next {
943 case b.Succs[0].Block():
944 p = s.Br(jmp.invasm, b.Succs[1].Block())
945 case b.Succs[1].Block():
946 p = s.Br(jmp.asm, b.Succs[0].Block())
947 default:
948 if b.Likely != ssa.BranchUnlikely {
949 p = s.Br(jmp.asm, b.Succs[0].Block())
950 s.Br(obj.AJMP, b.Succs[1].Block())
951 } else {
952 p = s.Br(jmp.invasm, b.Succs[1].Block())
953 s.Br(obj.AJMP, b.Succs[0].Block())
954 }
955 }
956 if !b.Controls[0].Type.IsFlags() {
957 p.From.Type = obj.TYPE_REG
958 p.From.Reg = b.Controls[0].Reg()
959 }
960 default:
961 b.Fatalf("branch not implemented: %s", b.LongString())
962 }
963 }
964
View as plain text