1
2
3
4
5 package loong64
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/objw"
14 "cmd/compile/internal/ssa"
15 "cmd/compile/internal/ssagen"
16 "cmd/compile/internal/types"
17 "cmd/internal/obj"
18 "cmd/internal/obj/loong64"
19 )
20
21
22 func isFPreg(r int16) bool {
23 return loong64.REG_F0 <= r && r <= loong64.REG_F31
24 }
25
26
27 func loadByType(t *types.Type, r int16) obj.As {
28 if isFPreg(r) {
29 if t.Size() == 4 {
30 return loong64.AMOVF
31 } else {
32 return loong64.AMOVD
33 }
34 } else {
35 switch t.Size() {
36 case 1:
37 if t.IsSigned() {
38 return loong64.AMOVB
39 } else {
40 return loong64.AMOVBU
41 }
42 case 2:
43 if t.IsSigned() {
44 return loong64.AMOVH
45 } else {
46 return loong64.AMOVHU
47 }
48 case 4:
49 if t.IsSigned() {
50 return loong64.AMOVW
51 } else {
52 return loong64.AMOVWU
53 }
54 case 8:
55 return loong64.AMOVV
56 }
57 }
58 panic("bad load type")
59 }
60
61
62 func storeByType(t *types.Type, r int16) obj.As {
63 if isFPreg(r) {
64 if t.Size() == 4 {
65 return loong64.AMOVF
66 } else {
67 return loong64.AMOVD
68 }
69 } else {
70 switch t.Size() {
71 case 1:
72 return loong64.AMOVB
73 case 2:
74 return loong64.AMOVH
75 case 4:
76 return loong64.AMOVW
77 case 8:
78 return loong64.AMOVV
79 }
80 }
81 panic("bad store type")
82 }
83
84
85
86
87
88
89
90
91
92
93 func largestMove(alignment int64) (obj.As, int64) {
94 switch {
95 case alignment%8 == 0:
96 return loong64.AMOVV, 8
97 case alignment%4 == 0:
98 return loong64.AMOVW, 4
99 case alignment%2 == 0:
100 return loong64.AMOVH, 2
101 default:
102 return loong64.AMOVB, 1
103 }
104 }
105
106 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
107 switch v.Op {
108 case ssa.OpCopy, ssa.OpLOONG64MOVVreg:
109 if v.Type.IsMemory() {
110 return
111 }
112 x := v.Args[0].Reg()
113 y := v.Reg()
114 if x == y {
115 return
116 }
117 as := loong64.AMOVV
118 if isFPreg(x) && isFPreg(y) {
119 as = loong64.AMOVD
120 }
121 p := s.Prog(as)
122 p.From.Type = obj.TYPE_REG
123 p.From.Reg = x
124 p.To.Type = obj.TYPE_REG
125 p.To.Reg = y
126 case ssa.OpLOONG64MOVVnop:
127
128 case ssa.OpLoadReg:
129 if v.Type.IsFlags() {
130 v.Fatalf("load flags not implemented: %v", v.LongString())
131 return
132 }
133 r := v.Reg()
134 p := s.Prog(loadByType(v.Type, r))
135 ssagen.AddrAuto(&p.From, v.Args[0])
136 p.To.Type = obj.TYPE_REG
137 p.To.Reg = r
138 case ssa.OpStoreReg:
139 if v.Type.IsFlags() {
140 v.Fatalf("store flags not implemented: %v", v.LongString())
141 return
142 }
143 r := v.Args[0].Reg()
144 p := s.Prog(storeByType(v.Type, r))
145 p.From.Type = obj.TYPE_REG
146 p.From.Reg = r
147 ssagen.AddrAuto(&p.To, v)
148 case ssa.OpArgIntReg, ssa.OpArgFloatReg:
149
150
151 for _, a := range v.Block.Func.RegArgs {
152
153
154 addr := ssagen.SpillSlotAddr(a, loong64.REGSP, base.Ctxt.Arch.FixedFrameSize)
155 s.FuncInfo().AddSpill(
156 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type, a.Reg), Spill: storeByType(a.Type, a.Reg)})
157 }
158 v.Block.Func.RegArgs = nil
159 ssagen.CheckArgReg(v)
160 case ssa.OpLOONG64ADDV,
161 ssa.OpLOONG64SUBV,
162 ssa.OpLOONG64AND,
163 ssa.OpLOONG64OR,
164 ssa.OpLOONG64XOR,
165 ssa.OpLOONG64NOR,
166 ssa.OpLOONG64SLLV,
167 ssa.OpLOONG64SRLV,
168 ssa.OpLOONG64SRAV,
169 ssa.OpLOONG64ROTR,
170 ssa.OpLOONG64ROTRV,
171 ssa.OpLOONG64ADDF,
172 ssa.OpLOONG64ADDD,
173 ssa.OpLOONG64SUBF,
174 ssa.OpLOONG64SUBD,
175 ssa.OpLOONG64MULF,
176 ssa.OpLOONG64MULD,
177 ssa.OpLOONG64DIVF,
178 ssa.OpLOONG64DIVD,
179 ssa.OpLOONG64MULV, ssa.OpLOONG64MULHV, ssa.OpLOONG64MULHVU,
180 ssa.OpLOONG64DIVV, ssa.OpLOONG64REMV, ssa.OpLOONG64DIVVU, ssa.OpLOONG64REMVU:
181 p := s.Prog(v.Op.Asm())
182 p.From.Type = obj.TYPE_REG
183 p.From.Reg = v.Args[1].Reg()
184 p.Reg = v.Args[0].Reg()
185 p.To.Type = obj.TYPE_REG
186 p.To.Reg = v.Reg()
187 case ssa.OpLOONG64SGT,
188 ssa.OpLOONG64SGTU:
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 = v.Args[1].Reg()
193 p.To.Type = obj.TYPE_REG
194 p.To.Reg = v.Reg()
195 case ssa.OpLOONG64ADDVconst,
196 ssa.OpLOONG64SUBVconst,
197 ssa.OpLOONG64ANDconst,
198 ssa.OpLOONG64ORconst,
199 ssa.OpLOONG64XORconst,
200 ssa.OpLOONG64NORconst,
201 ssa.OpLOONG64SLLVconst,
202 ssa.OpLOONG64SRLVconst,
203 ssa.OpLOONG64SRAVconst,
204 ssa.OpLOONG64ROTRconst,
205 ssa.OpLOONG64ROTRVconst,
206 ssa.OpLOONG64SGTconst,
207 ssa.OpLOONG64SGTUconst:
208 p := s.Prog(v.Op.Asm())
209 p.From.Type = obj.TYPE_CONST
210 p.From.Offset = v.AuxInt
211 p.Reg = v.Args[0].Reg()
212 p.To.Type = obj.TYPE_REG
213 p.To.Reg = v.Reg()
214 case ssa.OpLOONG64MOVVconst:
215 r := v.Reg()
216 p := s.Prog(v.Op.Asm())
217 p.From.Type = obj.TYPE_CONST
218 p.From.Offset = v.AuxInt
219 p.To.Type = obj.TYPE_REG
220 p.To.Reg = r
221 if isFPreg(r) {
222
223 p.To.Reg = loong64.REGTMP
224 p = s.Prog(loong64.AMOVV)
225 p.From.Type = obj.TYPE_REG
226 p.From.Reg = loong64.REGTMP
227 p.To.Type = obj.TYPE_REG
228 p.To.Reg = r
229 }
230 case ssa.OpLOONG64MOVFconst,
231 ssa.OpLOONG64MOVDconst:
232 p := s.Prog(v.Op.Asm())
233 p.From.Type = obj.TYPE_FCONST
234 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
235 p.To.Type = obj.TYPE_REG
236 p.To.Reg = v.Reg()
237 case ssa.OpLOONG64CMPEQF,
238 ssa.OpLOONG64CMPEQD,
239 ssa.OpLOONG64CMPGEF,
240 ssa.OpLOONG64CMPGED,
241 ssa.OpLOONG64CMPGTF,
242 ssa.OpLOONG64CMPGTD:
243 p := s.Prog(v.Op.Asm())
244 p.From.Type = obj.TYPE_REG
245 p.From.Reg = v.Args[0].Reg()
246 p.Reg = v.Args[1].Reg()
247 case ssa.OpLOONG64MOVVaddr:
248 p := s.Prog(loong64.AMOVV)
249 p.From.Type = obj.TYPE_ADDR
250 p.From.Reg = v.Args[0].Reg()
251 var wantreg string
252
253
254
255
256
257 switch v.Aux.(type) {
258 default:
259 v.Fatalf("aux is of unknown type %T", v.Aux)
260 case *obj.LSym:
261 wantreg = "SB"
262 ssagen.AddAux(&p.From, v)
263 case *ir.Name:
264 wantreg = "SP"
265 ssagen.AddAux(&p.From, v)
266 case nil:
267
268 wantreg = "SP"
269 p.From.Offset = v.AuxInt
270 }
271 if reg := v.Args[0].RegName(); reg != wantreg {
272 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
273 }
274 p.To.Type = obj.TYPE_REG
275 p.To.Reg = v.Reg()
276 case ssa.OpLOONG64MOVBload,
277 ssa.OpLOONG64MOVBUload,
278 ssa.OpLOONG64MOVHload,
279 ssa.OpLOONG64MOVHUload,
280 ssa.OpLOONG64MOVWload,
281 ssa.OpLOONG64MOVWUload,
282 ssa.OpLOONG64MOVVload,
283 ssa.OpLOONG64MOVFload,
284 ssa.OpLOONG64MOVDload:
285 p := s.Prog(v.Op.Asm())
286 p.From.Type = obj.TYPE_MEM
287 p.From.Reg = v.Args[0].Reg()
288 ssagen.AddAux(&p.From, v)
289 p.To.Type = obj.TYPE_REG
290 p.To.Reg = v.Reg()
291 case ssa.OpLOONG64MOVBstore,
292 ssa.OpLOONG64MOVHstore,
293 ssa.OpLOONG64MOVWstore,
294 ssa.OpLOONG64MOVVstore,
295 ssa.OpLOONG64MOVFstore,
296 ssa.OpLOONG64MOVDstore:
297 p := s.Prog(v.Op.Asm())
298 p.From.Type = obj.TYPE_REG
299 p.From.Reg = v.Args[1].Reg()
300 p.To.Type = obj.TYPE_MEM
301 p.To.Reg = v.Args[0].Reg()
302 ssagen.AddAux(&p.To, v)
303 case ssa.OpLOONG64MOVBstorezero,
304 ssa.OpLOONG64MOVHstorezero,
305 ssa.OpLOONG64MOVWstorezero,
306 ssa.OpLOONG64MOVVstorezero:
307 p := s.Prog(v.Op.Asm())
308 p.From.Type = obj.TYPE_REG
309 p.From.Reg = loong64.REGZERO
310 p.To.Type = obj.TYPE_MEM
311 p.To.Reg = v.Args[0].Reg()
312 ssagen.AddAux(&p.To, v)
313 case ssa.OpLOONG64MOVBreg,
314 ssa.OpLOONG64MOVBUreg,
315 ssa.OpLOONG64MOVHreg,
316 ssa.OpLOONG64MOVHUreg,
317 ssa.OpLOONG64MOVWreg,
318 ssa.OpLOONG64MOVWUreg:
319 a := v.Args[0]
320 for a.Op == ssa.OpCopy || a.Op == ssa.OpLOONG64MOVVreg {
321 a = a.Args[0]
322 }
323 if a.Op == ssa.OpLoadReg && loong64.REG_R0 <= a.Reg() && a.Reg() <= loong64.REG_R31 {
324
325
326
327
328 t := a.Type
329 switch {
330 case v.Op == ssa.OpLOONG64MOVBreg && t.Size() == 1 && t.IsSigned(),
331 v.Op == ssa.OpLOONG64MOVBUreg && t.Size() == 1 && !t.IsSigned(),
332 v.Op == ssa.OpLOONG64MOVHreg && t.Size() == 2 && t.IsSigned(),
333 v.Op == ssa.OpLOONG64MOVHUreg && t.Size() == 2 && !t.IsSigned(),
334 v.Op == ssa.OpLOONG64MOVWreg && t.Size() == 4 && t.IsSigned(),
335 v.Op == ssa.OpLOONG64MOVWUreg && t.Size() == 4 && !t.IsSigned():
336
337 if v.Reg() == v.Args[0].Reg() {
338 return
339 }
340 p := s.Prog(loong64.AMOVV)
341 p.From.Type = obj.TYPE_REG
342 p.From.Reg = v.Args[0].Reg()
343 p.To.Type = obj.TYPE_REG
344 p.To.Reg = v.Reg()
345 return
346 default:
347 }
348 }
349 fallthrough
350 case ssa.OpLOONG64MOVWF,
351 ssa.OpLOONG64MOVWD,
352 ssa.OpLOONG64TRUNCFW,
353 ssa.OpLOONG64TRUNCDW,
354 ssa.OpLOONG64MOVVF,
355 ssa.OpLOONG64MOVVD,
356 ssa.OpLOONG64TRUNCFV,
357 ssa.OpLOONG64TRUNCDV,
358 ssa.OpLOONG64MOVFD,
359 ssa.OpLOONG64MOVDF,
360 ssa.OpLOONG64NEGF,
361 ssa.OpLOONG64NEGD,
362 ssa.OpLOONG64SQRTD,
363 ssa.OpLOONG64SQRTF:
364 p := s.Prog(v.Op.Asm())
365 p.From.Type = obj.TYPE_REG
366 p.From.Reg = v.Args[0].Reg()
367 p.To.Type = obj.TYPE_REG
368 p.To.Reg = v.Reg()
369 case ssa.OpLOONG64NEGV:
370
371 p := s.Prog(loong64.ASUBVU)
372 p.From.Type = obj.TYPE_REG
373 p.From.Reg = v.Args[0].Reg()
374 p.Reg = loong64.REGZERO
375 p.To.Type = obj.TYPE_REG
376 p.To.Reg = v.Reg()
377 case ssa.OpLOONG64DUFFZERO:
378
379 p := s.Prog(obj.ADUFFZERO)
380 p.To.Type = obj.TYPE_MEM
381 p.To.Name = obj.NAME_EXTERN
382 p.To.Sym = ir.Syms.Duffzero
383 p.To.Offset = v.AuxInt
384 case ssa.OpLOONG64LoweredZero:
385
386
387
388 mov, sz := largestMove(v.AuxInt)
389 p := s.Prog(mov)
390 p.From.Type = obj.TYPE_REG
391 p.From.Reg = loong64.REGZERO
392 p.To.Type = obj.TYPE_MEM
393 p.To.Reg = v.Args[0].Reg()
394
395 p2 := s.Prog(loong64.AADDVU)
396 p2.From.Type = obj.TYPE_CONST
397 p2.From.Offset = sz
398 p2.To.Type = obj.TYPE_REG
399 p2.To.Reg = v.Args[0].Reg()
400
401 p3 := s.Prog(loong64.ABGEU)
402 p3.From.Type = obj.TYPE_REG
403 p3.From.Reg = v.Args[1].Reg()
404 p3.Reg = v.Args[0].Reg()
405 p3.To.Type = obj.TYPE_BRANCH
406 p3.To.SetTarget(p)
407
408 case ssa.OpLOONG64DUFFCOPY:
409 p := s.Prog(obj.ADUFFCOPY)
410 p.To.Type = obj.TYPE_MEM
411 p.To.Name = obj.NAME_EXTERN
412 p.To.Sym = ir.Syms.Duffcopy
413 p.To.Offset = v.AuxInt
414 case ssa.OpLOONG64LoweredMove:
415
416
417
418
419
420 mov, sz := largestMove(v.AuxInt)
421 p := s.Prog(mov)
422 p.From.Type = obj.TYPE_MEM
423 p.From.Reg = v.Args[1].Reg()
424 p.To.Type = obj.TYPE_REG
425 p.To.Reg = loong64.REGTMP
426
427 p2 := s.Prog(mov)
428 p2.From.Type = obj.TYPE_REG
429 p2.From.Reg = loong64.REGTMP
430 p2.To.Type = obj.TYPE_MEM
431 p2.To.Reg = v.Args[0].Reg()
432
433 p3 := s.Prog(loong64.AADDVU)
434 p3.From.Type = obj.TYPE_CONST
435 p3.From.Offset = sz
436 p3.To.Type = obj.TYPE_REG
437 p3.To.Reg = v.Args[1].Reg()
438
439 p4 := s.Prog(loong64.AADDVU)
440 p4.From.Type = obj.TYPE_CONST
441 p4.From.Offset = sz
442 p4.To.Type = obj.TYPE_REG
443 p4.To.Reg = v.Args[0].Reg()
444
445 p5 := s.Prog(loong64.ABGEU)
446 p5.From.Type = obj.TYPE_REG
447 p5.From.Reg = v.Args[2].Reg()
448 p5.Reg = v.Args[1].Reg()
449 p5.To.Type = obj.TYPE_BRANCH
450 p5.To.SetTarget(p)
451
452 case ssa.OpLOONG64CALLstatic, ssa.OpLOONG64CALLclosure, ssa.OpLOONG64CALLinter:
453 s.Call(v)
454 case ssa.OpLOONG64CALLtail:
455 s.TailCall(v)
456 case ssa.OpLOONG64LoweredWB:
457 p := s.Prog(obj.ACALL)
458 p.To.Type = obj.TYPE_MEM
459 p.To.Name = obj.NAME_EXTERN
460
461 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
462 case ssa.OpLOONG64LoweredPanicBoundsA, ssa.OpLOONG64LoweredPanicBoundsB, ssa.OpLOONG64LoweredPanicBoundsC:
463 p := s.Prog(obj.ACALL)
464 p.To.Type = obj.TYPE_MEM
465 p.To.Name = obj.NAME_EXTERN
466 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
467 s.UseArgs(16)
468 case ssa.OpLOONG64LoweredAtomicLoad8, ssa.OpLOONG64LoweredAtomicLoad32, ssa.OpLOONG64LoweredAtomicLoad64:
469 as := loong64.AMOVV
470 switch v.Op {
471 case ssa.OpLOONG64LoweredAtomicLoad8:
472 as = loong64.AMOVB
473 case ssa.OpLOONG64LoweredAtomicLoad32:
474 as = loong64.AMOVW
475 }
476 s.Prog(loong64.ADBAR)
477 p := s.Prog(as)
478 p.From.Type = obj.TYPE_MEM
479 p.From.Reg = v.Args[0].Reg()
480 p.To.Type = obj.TYPE_REG
481 p.To.Reg = v.Reg0()
482 s.Prog(loong64.ADBAR)
483 case ssa.OpLOONG64LoweredAtomicStore8, ssa.OpLOONG64LoweredAtomicStore32, ssa.OpLOONG64LoweredAtomicStore64:
484 as := loong64.AMOVV
485 switch v.Op {
486 case ssa.OpLOONG64LoweredAtomicStore8:
487 as = loong64.AMOVB
488 case ssa.OpLOONG64LoweredAtomicStore32:
489 as = loong64.AMOVW
490 }
491 s.Prog(loong64.ADBAR)
492 p := s.Prog(as)
493 p.From.Type = obj.TYPE_REG
494 p.From.Reg = v.Args[1].Reg()
495 p.To.Type = obj.TYPE_MEM
496 p.To.Reg = v.Args[0].Reg()
497 s.Prog(loong64.ADBAR)
498 case ssa.OpLOONG64LoweredAtomicStorezero32, ssa.OpLOONG64LoweredAtomicStorezero64:
499 as := loong64.AMOVV
500 if v.Op == ssa.OpLOONG64LoweredAtomicStorezero32 {
501 as = loong64.AMOVW
502 }
503 s.Prog(loong64.ADBAR)
504 p := s.Prog(as)
505 p.From.Type = obj.TYPE_REG
506 p.From.Reg = loong64.REGZERO
507 p.To.Type = obj.TYPE_MEM
508 p.To.Reg = v.Args[0].Reg()
509 s.Prog(loong64.ADBAR)
510 case ssa.OpLOONG64LoweredAtomicExchange32, ssa.OpLOONG64LoweredAtomicExchange64:
511
512
513
514
515
516
517 ll := loong64.ALLV
518 sc := loong64.ASCV
519 if v.Op == ssa.OpLOONG64LoweredAtomicExchange32 {
520 ll = loong64.ALL
521 sc = loong64.ASC
522 }
523 s.Prog(loong64.ADBAR)
524 p := s.Prog(loong64.AMOVV)
525 p.From.Type = obj.TYPE_REG
526 p.From.Reg = v.Args[1].Reg()
527 p.To.Type = obj.TYPE_REG
528 p.To.Reg = loong64.REGTMP
529 p1 := s.Prog(ll)
530 p1.From.Type = obj.TYPE_MEM
531 p1.From.Reg = v.Args[0].Reg()
532 p1.To.Type = obj.TYPE_REG
533 p1.To.Reg = v.Reg0()
534 p2 := s.Prog(sc)
535 p2.From.Type = obj.TYPE_REG
536 p2.From.Reg = loong64.REGTMP
537 p2.To.Type = obj.TYPE_MEM
538 p2.To.Reg = v.Args[0].Reg()
539 p3 := s.Prog(loong64.ABEQ)
540 p3.From.Type = obj.TYPE_REG
541 p3.From.Reg = loong64.REGTMP
542 p3.To.Type = obj.TYPE_BRANCH
543 p3.To.SetTarget(p)
544 s.Prog(loong64.ADBAR)
545 case ssa.OpLOONG64LoweredAtomicAdd32, ssa.OpLOONG64LoweredAtomicAdd64:
546
547
548
549
550
551
552
553 ll := loong64.ALLV
554 sc := loong64.ASCV
555 if v.Op == ssa.OpLOONG64LoweredAtomicAdd32 {
556 ll = loong64.ALL
557 sc = loong64.ASC
558 }
559 s.Prog(loong64.ADBAR)
560 p := s.Prog(ll)
561 p.From.Type = obj.TYPE_MEM
562 p.From.Reg = v.Args[0].Reg()
563 p.To.Type = obj.TYPE_REG
564 p.To.Reg = v.Reg0()
565 p1 := s.Prog(loong64.AADDVU)
566 p1.From.Type = obj.TYPE_REG
567 p1.From.Reg = v.Args[1].Reg()
568 p1.Reg = v.Reg0()
569 p1.To.Type = obj.TYPE_REG
570 p1.To.Reg = loong64.REGTMP
571 p2 := s.Prog(sc)
572 p2.From.Type = obj.TYPE_REG
573 p2.From.Reg = loong64.REGTMP
574 p2.To.Type = obj.TYPE_MEM
575 p2.To.Reg = v.Args[0].Reg()
576 p3 := s.Prog(loong64.ABEQ)
577 p3.From.Type = obj.TYPE_REG
578 p3.From.Reg = loong64.REGTMP
579 p3.To.Type = obj.TYPE_BRANCH
580 p3.To.SetTarget(p)
581 s.Prog(loong64.ADBAR)
582 p4 := s.Prog(loong64.AADDVU)
583 p4.From.Type = obj.TYPE_REG
584 p4.From.Reg = v.Args[1].Reg()
585 p4.Reg = v.Reg0()
586 p4.To.Type = obj.TYPE_REG
587 p4.To.Reg = v.Reg0()
588 case ssa.OpLOONG64LoweredAtomicAddconst32, ssa.OpLOONG64LoweredAtomicAddconst64:
589
590
591
592
593
594
595
596 ll := loong64.ALLV
597 sc := loong64.ASCV
598 if v.Op == ssa.OpLOONG64LoweredAtomicAddconst32 {
599 ll = loong64.ALL
600 sc = loong64.ASC
601 }
602 s.Prog(loong64.ADBAR)
603 p := s.Prog(ll)
604 p.From.Type = obj.TYPE_MEM
605 p.From.Reg = v.Args[0].Reg()
606 p.To.Type = obj.TYPE_REG
607 p.To.Reg = v.Reg0()
608 p1 := s.Prog(loong64.AADDVU)
609 p1.From.Type = obj.TYPE_CONST
610 p1.From.Offset = v.AuxInt
611 p1.Reg = v.Reg0()
612 p1.To.Type = obj.TYPE_REG
613 p1.To.Reg = loong64.REGTMP
614 p2 := s.Prog(sc)
615 p2.From.Type = obj.TYPE_REG
616 p2.From.Reg = loong64.REGTMP
617 p2.To.Type = obj.TYPE_MEM
618 p2.To.Reg = v.Args[0].Reg()
619 p3 := s.Prog(loong64.ABEQ)
620 p3.From.Type = obj.TYPE_REG
621 p3.From.Reg = loong64.REGTMP
622 p3.To.Type = obj.TYPE_BRANCH
623 p3.To.SetTarget(p)
624 s.Prog(loong64.ADBAR)
625 p4 := s.Prog(loong64.AADDVU)
626 p4.From.Type = obj.TYPE_CONST
627 p4.From.Offset = v.AuxInt
628 p4.Reg = v.Reg0()
629 p4.To.Type = obj.TYPE_REG
630 p4.To.Reg = v.Reg0()
631 case ssa.OpLOONG64LoweredAtomicCas32, ssa.OpLOONG64LoweredAtomicCas64:
632
633
634
635
636
637
638
639
640 ll := loong64.ALLV
641 sc := loong64.ASCV
642 if v.Op == ssa.OpLOONG64LoweredAtomicCas32 {
643 ll = loong64.ALL
644 sc = loong64.ASC
645 }
646 p := s.Prog(loong64.AMOVV)
647 p.From.Type = obj.TYPE_REG
648 p.From.Reg = loong64.REGZERO
649 p.To.Type = obj.TYPE_REG
650 p.To.Reg = v.Reg0()
651 s.Prog(loong64.ADBAR)
652 p1 := s.Prog(ll)
653 p1.From.Type = obj.TYPE_MEM
654 p1.From.Reg = v.Args[0].Reg()
655 p1.To.Type = obj.TYPE_REG
656 p1.To.Reg = loong64.REGTMP
657 p2 := s.Prog(loong64.ABNE)
658 p2.From.Type = obj.TYPE_REG
659 p2.From.Reg = v.Args[1].Reg()
660 p2.Reg = loong64.REGTMP
661 p2.To.Type = obj.TYPE_BRANCH
662 p3 := s.Prog(loong64.AMOVV)
663 p3.From.Type = obj.TYPE_REG
664 p3.From.Reg = v.Args[2].Reg()
665 p3.To.Type = obj.TYPE_REG
666 p3.To.Reg = v.Reg0()
667 p4 := s.Prog(sc)
668 p4.From.Type = obj.TYPE_REG
669 p4.From.Reg = v.Reg0()
670 p4.To.Type = obj.TYPE_MEM
671 p4.To.Reg = v.Args[0].Reg()
672 p5 := s.Prog(loong64.ABEQ)
673 p5.From.Type = obj.TYPE_REG
674 p5.From.Reg = v.Reg0()
675 p5.To.Type = obj.TYPE_BRANCH
676 p5.To.SetTarget(p1)
677 p6 := s.Prog(loong64.ADBAR)
678 p2.To.SetTarget(p6)
679 case ssa.OpLOONG64LoweredNilCheck:
680
681 p := s.Prog(loong64.AMOVB)
682 p.From.Type = obj.TYPE_MEM
683 p.From.Reg = v.Args[0].Reg()
684 ssagen.AddAux(&p.From, v)
685 p.To.Type = obj.TYPE_REG
686 p.To.Reg = loong64.REGTMP
687 if logopt.Enabled() {
688 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
689 }
690 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
691 base.WarnfAt(v.Pos, "generated nil check")
692 }
693 case ssa.OpLOONG64FPFlagTrue,
694 ssa.OpLOONG64FPFlagFalse:
695
696
697
698 branch := loong64.ABFPF
699 if v.Op == ssa.OpLOONG64FPFlagFalse {
700 branch = loong64.ABFPT
701 }
702 p := s.Prog(loong64.AMOVV)
703 p.From.Type = obj.TYPE_REG
704 p.From.Reg = loong64.REGZERO
705 p.To.Type = obj.TYPE_REG
706 p.To.Reg = v.Reg()
707 p2 := s.Prog(branch)
708 p2.To.Type = obj.TYPE_BRANCH
709 p3 := s.Prog(loong64.AMOVV)
710 p3.From.Type = obj.TYPE_CONST
711 p3.From.Offset = 1
712 p3.To.Type = obj.TYPE_REG
713 p3.To.Reg = v.Reg()
714 p4 := s.Prog(obj.ANOP)
715 p2.To.SetTarget(p4)
716 case ssa.OpLOONG64LoweredGetClosurePtr:
717
718 ssagen.CheckLoweredGetClosurePtr(v)
719 case ssa.OpLOONG64LoweredGetCallerSP:
720
721 p := s.Prog(loong64.AMOVV)
722 p.From.Type = obj.TYPE_ADDR
723 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
724 p.From.Name = obj.NAME_PARAM
725 p.To.Type = obj.TYPE_REG
726 p.To.Reg = v.Reg()
727 case ssa.OpLOONG64LoweredGetCallerPC:
728 p := s.Prog(obj.AGETCALLERPC)
729 p.To.Type = obj.TYPE_REG
730 p.To.Reg = v.Reg()
731 case ssa.OpLOONG64MASKEQZ, ssa.OpLOONG64MASKNEZ:
732 p := s.Prog(v.Op.Asm())
733 p.From.Type = obj.TYPE_REG
734 p.From.Reg = v.Args[1].Reg()
735 p.Reg = v.Args[0].Reg()
736 p.To.Type = obj.TYPE_REG
737 p.To.Reg = v.Reg()
738 case ssa.OpClobber, ssa.OpClobberReg:
739
740 default:
741 v.Fatalf("genValue not implemented: %s", v.LongString())
742 }
743 }
744
745 var blockJump = map[ssa.BlockKind]struct {
746 asm, invasm obj.As
747 }{
748 ssa.BlockLOONG64EQ: {loong64.ABEQ, loong64.ABNE},
749 ssa.BlockLOONG64NE: {loong64.ABNE, loong64.ABEQ},
750 ssa.BlockLOONG64LTZ: {loong64.ABLTZ, loong64.ABGEZ},
751 ssa.BlockLOONG64GEZ: {loong64.ABGEZ, loong64.ABLTZ},
752 ssa.BlockLOONG64LEZ: {loong64.ABLEZ, loong64.ABGTZ},
753 ssa.BlockLOONG64GTZ: {loong64.ABGTZ, loong64.ABLEZ},
754 ssa.BlockLOONG64FPT: {loong64.ABFPT, loong64.ABFPF},
755 ssa.BlockLOONG64FPF: {loong64.ABFPF, loong64.ABFPT},
756 }
757
758 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
759 switch b.Kind {
760 case ssa.BlockPlain:
761 if b.Succs[0].Block() != next {
762 p := s.Prog(obj.AJMP)
763 p.To.Type = obj.TYPE_BRANCH
764 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
765 }
766 case ssa.BlockDefer:
767
768
769
770 p := s.Prog(loong64.ABNE)
771 p.From.Type = obj.TYPE_REG
772 p.From.Reg = loong64.REGZERO
773 p.Reg = loong64.REG_R19
774 p.To.Type = obj.TYPE_BRANCH
775 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
776 if b.Succs[0].Block() != next {
777 p := s.Prog(obj.AJMP)
778 p.To.Type = obj.TYPE_BRANCH
779 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
780 }
781 case ssa.BlockExit, ssa.BlockRetJmp:
782 case ssa.BlockRet:
783 s.Prog(obj.ARET)
784 case ssa.BlockLOONG64EQ, ssa.BlockLOONG64NE,
785 ssa.BlockLOONG64LTZ, ssa.BlockLOONG64GEZ,
786 ssa.BlockLOONG64LEZ, ssa.BlockLOONG64GTZ,
787 ssa.BlockLOONG64FPT, ssa.BlockLOONG64FPF:
788 jmp := blockJump[b.Kind]
789 var p *obj.Prog
790 switch next {
791 case b.Succs[0].Block():
792 p = s.Br(jmp.invasm, b.Succs[1].Block())
793 case b.Succs[1].Block():
794 p = s.Br(jmp.asm, b.Succs[0].Block())
795 default:
796 if b.Likely != ssa.BranchUnlikely {
797 p = s.Br(jmp.asm, b.Succs[0].Block())
798 s.Br(obj.AJMP, b.Succs[1].Block())
799 } else {
800 p = s.Br(jmp.invasm, b.Succs[1].Block())
801 s.Br(obj.AJMP, b.Succs[0].Block())
802 }
803 }
804 if !b.Controls[0].Type.IsFlags() {
805 p.From.Type = obj.TYPE_REG
806 p.From.Reg = b.Controls[0].Reg()
807 }
808 default:
809 b.Fatalf("branch not implemented: %s", b.LongString())
810 }
811 }
812
813 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
814 p := s.Prog(loadByType(t, reg))
815 p.From.Type = obj.TYPE_MEM
816 p.From.Name = obj.NAME_AUTO
817 p.From.Sym = n.Linksym()
818 p.From.Offset = n.FrameOffset() + off
819 p.To.Type = obj.TYPE_REG
820 p.To.Reg = reg
821 return p
822 }
823
824 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
825 p = pp.Append(p, storeByType(t, reg), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
826 p.To.Name = obj.NAME_PARAM
827 p.To.Sym = n.Linksym()
828 p.Pos = p.Pos.WithNotStmt()
829 return p
830 }
831
View as plain text