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/ssa/block"
16 "cmd/compile/internal/ssa/ssaop"
17 "cmd/compile/internal/ssagen"
18 "cmd/compile/internal/types"
19 "cmd/internal/obj"
20 "cmd/internal/obj/loong64"
21 "internal/abi"
22 )
23
24
25 func isFPreg(r int16) bool {
26 return loong64.REG_F0 <= r && r <= loong64.REG_F31
27 }
28
29
30 func loadByType(t *types.Type, r int16) obj.As {
31 if isFPreg(r) {
32 if t.Size() == 4 {
33 return loong64.AMOVF
34 } else {
35 return loong64.AMOVD
36 }
37 } else {
38 switch t.Size() {
39 case 1:
40 if t.IsSigned() {
41 return loong64.AMOVB
42 } else {
43 return loong64.AMOVBU
44 }
45 case 2:
46 if t.IsSigned() {
47 return loong64.AMOVH
48 } else {
49 return loong64.AMOVHU
50 }
51 case 4:
52 if t.IsSigned() {
53 return loong64.AMOVW
54 } else {
55 return loong64.AMOVWU
56 }
57 case 8:
58 return loong64.AMOVV
59 }
60 }
61 panic("bad load type")
62 }
63
64
65 func storeByType(t *types.Type, r int16) obj.As {
66 if isFPreg(r) {
67 if t.Size() == 4 {
68 return loong64.AMOVF
69 } else {
70 return loong64.AMOVD
71 }
72 } else {
73 switch t.Size() {
74 case 1:
75 return loong64.AMOVB
76 case 2:
77 return loong64.AMOVH
78 case 4:
79 return loong64.AMOVW
80 case 8:
81 return loong64.AMOVV
82 }
83 }
84 panic("bad store type")
85 }
86
87
88
89
90
91
92
93
94
95
96 func largestMove(alignment int64) (obj.As, int64) {
97 switch {
98 case alignment%8 == 0:
99 return loong64.AMOVV, 8
100 case alignment%4 == 0:
101 return loong64.AMOVW, 4
102 case alignment%2 == 0:
103 return loong64.AMOVH, 2
104 default:
105 return loong64.AMOVB, 1
106 }
107 }
108
109 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
110 switch v.Op {
111 case ssaop.OpCopy, ssaop.OpLOONG64MOVVreg:
112 if v.Type.IsMemory() {
113 return
114 }
115 x := v.Args[0].Reg()
116 y := v.Reg()
117 if x == y {
118 return
119 }
120 as := loong64.AMOVV
121 if isFPreg(x) && isFPreg(y) {
122 as = loong64.AMOVD
123 }
124 p := s.Prog(as)
125 p.From.Type = obj.TYPE_REG
126 p.From.Reg = x
127 p.To.Type = obj.TYPE_REG
128 p.To.Reg = y
129 case ssaop.OpLOONG64MOVVnop,
130 ssaop.OpLOONG64ZERO,
131 ssaop.OpLOONG64LoweredRound32F,
132 ssaop.OpLOONG64LoweredRound64F:
133
134 case ssaop.OpLoadReg:
135 if v.Type.IsFlags() {
136 v.Fatalf("load flags not implemented: %v", v.LongString())
137 return
138 }
139 r := v.Reg()
140 p := s.Prog(loadByType(v.Type, r))
141 ssagen.AddrAuto(&p.From, v.Args[0])
142 p.To.Type = obj.TYPE_REG
143 p.To.Reg = r
144 case ssaop.OpStoreReg:
145 if v.Type.IsFlags() {
146 v.Fatalf("store flags not implemented: %v", v.LongString())
147 return
148 }
149 r := v.Args[0].Reg()
150 p := s.Prog(storeByType(v.Type, r))
151 p.From.Type = obj.TYPE_REG
152 p.From.Reg = r
153 ssagen.AddrAuto(&p.To, v)
154 case ssaop.OpArgIntReg, ssaop.OpArgFloatReg:
155
156
157 for _, a := range v.Block.Func.RegArgs {
158
159
160 addr := ssagen.SpillSlotAddr(a, loong64.REGSP, base.Ctxt.Arch.FixedFrameSize)
161 s.FuncInfo().AddSpill(
162 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type, a.Reg), Spill: storeByType(a.Type, a.Reg)})
163 }
164 v.Block.Func.RegArgs = nil
165 ssagen.CheckArgReg(v)
166 case ssaop.OpLOONG64ADDV,
167 ssaop.OpLOONG64SUBV,
168 ssaop.OpLOONG64AND,
169 ssaop.OpLOONG64OR,
170 ssaop.OpLOONG64XOR,
171 ssaop.OpLOONG64NOR,
172 ssaop.OpLOONG64ANDN,
173 ssaop.OpLOONG64ORN,
174 ssaop.OpLOONG64SLL,
175 ssaop.OpLOONG64SLLV,
176 ssaop.OpLOONG64SRL,
177 ssaop.OpLOONG64SRLV,
178 ssaop.OpLOONG64SRA,
179 ssaop.OpLOONG64SRAV,
180 ssaop.OpLOONG64ROTR,
181 ssaop.OpLOONG64ROTRV,
182 ssaop.OpLOONG64ADDF,
183 ssaop.OpLOONG64ADDD,
184 ssaop.OpLOONG64SUBF,
185 ssaop.OpLOONG64SUBD,
186 ssaop.OpLOONG64MULF,
187 ssaop.OpLOONG64MULD,
188 ssaop.OpLOONG64DIVF,
189 ssaop.OpLOONG64DIVD,
190 ssaop.OpLOONG64MULV, ssaop.OpLOONG64MULHV, ssaop.OpLOONG64MULHVU, ssaop.OpLOONG64MULH, ssaop.OpLOONG64MULHU,
191 ssaop.OpLOONG64DIVV, ssaop.OpLOONG64REMV, ssaop.OpLOONG64DIVVU, ssaop.OpLOONG64REMVU,
192 ssaop.OpLOONG64MULWVW, ssaop.OpLOONG64MULWVWU,
193 ssaop.OpLOONG64FCOPYSGD:
194 p := s.Prog(v.Op.Asm())
195 p.From.Type = obj.TYPE_REG
196 p.From.Reg = v.Args[1].Reg()
197 p.Reg = v.Args[0].Reg()
198 p.To.Type = obj.TYPE_REG
199 p.To.Reg = v.Reg()
200
201 case ssaop.OpLOONG64BSTRPICKV,
202 ssaop.OpLOONG64BSTRPICKW:
203 p := s.Prog(v.Op.Asm())
204 p.From.Type = obj.TYPE_CONST
205 if v.Op == ssaop.OpLOONG64BSTRPICKW {
206 p.From.Offset = v.AuxInt >> 5
207 p.AddRestSourceConst(v.AuxInt & 0x1f)
208 } else {
209 p.From.Offset = v.AuxInt >> 6
210 p.AddRestSourceConst(v.AuxInt & 0x3f)
211 }
212 p.Reg = v.Args[0].Reg()
213 p.To.Type = obj.TYPE_REG
214 p.To.Reg = v.Reg()
215
216 case ssaop.OpLOONG64FMINF,
217 ssaop.OpLOONG64FMIND,
218 ssaop.OpLOONG64FMAXF,
219 ssaop.OpLOONG64FMAXD:
220
221
222
223
224
225
226
227 r0 := v.Args[0].Reg()
228 r1 := v.Args[1].Reg()
229 out := v.Reg()
230 add, fcmp := loong64.AADDD, loong64.ACMPEQD
231 if v.Op == ssaop.OpLOONG64FMINF || v.Op == ssaop.OpLOONG64FMAXF {
232 add = loong64.AADDF
233 fcmp = loong64.ACMPEQF
234 }
235 p1 := s.Prog(add)
236 p1.From.Type = obj.TYPE_REG
237 p1.From.Reg = r0
238 p1.Reg = r1
239 p1.To.Type = obj.TYPE_REG
240 p1.To.Reg = out
241
242 p2 := s.Prog(fcmp)
243 p2.From.Type = obj.TYPE_REG
244 p2.From.Reg = r0
245 p2.Reg = r0
246 p2.To.Type = obj.TYPE_REG
247 p2.To.Reg = loong64.REG_FCC0
248
249 p3 := s.Prog(loong64.ABFPF)
250 p3.To.Type = obj.TYPE_BRANCH
251
252 p4 := s.Prog(fcmp)
253 p4.From.Type = obj.TYPE_REG
254 p4.From.Reg = r1
255 p4.Reg = r1
256 p4.To.Type = obj.TYPE_REG
257 p4.To.Reg = loong64.REG_FCC0
258
259 p5 := s.Prog(loong64.ABFPF)
260 p5.To.Type = obj.TYPE_BRANCH
261
262 p6 := s.Prog(v.Op.Asm())
263 p6.From.Type = obj.TYPE_REG
264 p6.From.Reg = r1
265 p6.Reg = r0
266 p6.To.Type = obj.TYPE_REG
267 p6.To.Reg = out
268
269 nop := s.Prog(obj.ANOP)
270 p3.To.SetTarget(nop)
271 p5.To.SetTarget(nop)
272
273 case ssaop.OpLOONG64SGT,
274 ssaop.OpLOONG64SGTU:
275 p := s.Prog(v.Op.Asm())
276 p.From.Type = obj.TYPE_REG
277 p.From.Reg = v.Args[0].Reg()
278 p.Reg = v.Args[1].Reg()
279 p.To.Type = obj.TYPE_REG
280 p.To.Reg = v.Reg()
281 case ssaop.OpLOONG64ADDVconst,
282 ssaop.OpLOONG64ADDV16const,
283 ssaop.OpLOONG64SUBVconst,
284 ssaop.OpLOONG64ANDconst,
285 ssaop.OpLOONG64ORconst,
286 ssaop.OpLOONG64XORconst,
287 ssaop.OpLOONG64SLLconst,
288 ssaop.OpLOONG64SLLVconst,
289 ssaop.OpLOONG64SRLconst,
290 ssaop.OpLOONG64SRLVconst,
291 ssaop.OpLOONG64SRAconst,
292 ssaop.OpLOONG64SRAVconst,
293 ssaop.OpLOONG64ROTRconst,
294 ssaop.OpLOONG64ROTRVconst,
295 ssaop.OpLOONG64SGTconst,
296 ssaop.OpLOONG64SGTUconst:
297 p := s.Prog(v.Op.Asm())
298 p.From.Type = obj.TYPE_CONST
299 p.From.Offset = v.AuxInt
300 p.Reg = v.Args[0].Reg()
301 p.To.Type = obj.TYPE_REG
302 p.To.Reg = v.Reg()
303
304 case ssaop.OpLOONG64NORconst:
305
306
307 p := s.Prog(loong64.AMOVV)
308 p.From.Type = obj.TYPE_CONST
309 p.From.Offset = v.AuxInt
310 p.To.Type = obj.TYPE_REG
311 p.To.Reg = loong64.REGTMP
312
313 p2 := s.Prog(v.Op.Asm())
314 p2.From.Type = obj.TYPE_REG
315 p2.From.Reg = loong64.REGTMP
316 p2.Reg = v.Args[0].Reg()
317 p2.To.Type = obj.TYPE_REG
318 p2.To.Reg = v.Reg()
319
320 case ssaop.OpLOONG64MOVVconst:
321 r := v.Reg()
322 p := s.Prog(v.Op.Asm())
323 p.From.Type = obj.TYPE_CONST
324 p.From.Offset = v.AuxInt
325 p.To.Type = obj.TYPE_REG
326 p.To.Reg = r
327 if isFPreg(r) {
328
329 p.To.Reg = loong64.REGTMP
330 p = s.Prog(loong64.AMOVV)
331 p.From.Type = obj.TYPE_REG
332 p.From.Reg = loong64.REGTMP
333 p.To.Type = obj.TYPE_REG
334 p.To.Reg = r
335 }
336 case ssaop.OpLOONG64MOVFconst,
337 ssaop.OpLOONG64MOVDconst:
338 p := s.Prog(v.Op.Asm())
339 p.From.Type = obj.TYPE_FCONST
340 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
341 p.To.Type = obj.TYPE_REG
342 p.To.Reg = v.Reg()
343 case ssaop.OpLOONG64CMPEQF,
344 ssaop.OpLOONG64CMPEQD,
345 ssaop.OpLOONG64CMPGEF,
346 ssaop.OpLOONG64CMPGED,
347 ssaop.OpLOONG64CMPGTF,
348 ssaop.OpLOONG64CMPGTD:
349 p := s.Prog(v.Op.Asm())
350 p.From.Type = obj.TYPE_REG
351 p.From.Reg = v.Args[0].Reg()
352 p.Reg = v.Args[1].Reg()
353 p.To.Type = obj.TYPE_REG
354 p.To.Reg = loong64.REG_FCC0
355
356 case ssaop.OpLOONG64FMADDF,
357 ssaop.OpLOONG64FMADDD,
358 ssaop.OpLOONG64FMSUBF,
359 ssaop.OpLOONG64FMSUBD,
360 ssaop.OpLOONG64FNMADDF,
361 ssaop.OpLOONG64FNMADDD,
362 ssaop.OpLOONG64FNMSUBF,
363 ssaop.OpLOONG64FNMSUBD:
364 p := s.Prog(v.Op.Asm())
365
366
367
368 r := v.Reg()
369 x := v.Args[0].Reg()
370 y := v.Args[1].Reg()
371 z := v.Args[2].Reg()
372 p.From.Type = obj.TYPE_REG
373 p.From.Reg = z
374 p.Reg = y
375 p.AddRestSourceReg(x)
376 p.To.Type = obj.TYPE_REG
377 p.To.Reg = r
378
379 case ssaop.OpLOONG64MOVVaddr:
380 p := s.Prog(loong64.AMOVV)
381 p.From.Type = obj.TYPE_ADDR
382 p.From.Reg = v.Args[0].Reg()
383 var wantreg string
384
385
386
387
388
389 switch v.Aux.(type) {
390 default:
391 v.Fatalf("aux is of unknown type %T", v.Aux)
392 case *obj.LSym:
393 wantreg = "SB"
394 ssagen.AddAux(&p.From, v)
395 case *ir.Name:
396 wantreg = "SP"
397 ssagen.AddAux(&p.From, v)
398 case nil:
399
400 wantreg = "SP"
401 p.From.Offset = v.AuxInt
402 }
403 if reg := v.Args[0].RegName(); reg != wantreg {
404 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
405 }
406 p.To.Type = obj.TYPE_REG
407 p.To.Reg = v.Reg()
408
409 case ssaop.OpLOONG64MOVBloadidx,
410 ssaop.OpLOONG64MOVBUloadidx,
411 ssaop.OpLOONG64MOVHloadidx,
412 ssaop.OpLOONG64MOVHUloadidx,
413 ssaop.OpLOONG64MOVWloadidx,
414 ssaop.OpLOONG64MOVWUloadidx,
415 ssaop.OpLOONG64MOVVloadidx,
416 ssaop.OpLOONG64MOVFloadidx,
417 ssaop.OpLOONG64MOVDloadidx:
418 p := s.Prog(v.Op.Asm())
419 p.From.Type = obj.TYPE_MEM
420 p.From.Name = obj.NAME_NONE
421 p.From.Reg = v.Args[0].Reg()
422 p.From.Index = v.Args[1].Reg()
423 p.To.Type = obj.TYPE_REG
424 p.To.Reg = v.Reg()
425
426 case ssaop.OpLOONG64MOVBstoreidx,
427 ssaop.OpLOONG64MOVHstoreidx,
428 ssaop.OpLOONG64MOVWstoreidx,
429 ssaop.OpLOONG64MOVVstoreidx,
430 ssaop.OpLOONG64MOVFstoreidx,
431 ssaop.OpLOONG64MOVDstoreidx:
432 p := s.Prog(v.Op.Asm())
433 p.From.Type = obj.TYPE_REG
434 p.From.Reg = v.Args[2].Reg()
435 p.To.Type = obj.TYPE_MEM
436 p.To.Name = obj.NAME_NONE
437 p.To.Reg = v.Args[0].Reg()
438 p.To.Index = v.Args[1].Reg()
439
440 case ssaop.OpLOONG64MOVBload,
441 ssaop.OpLOONG64MOVBUload,
442 ssaop.OpLOONG64MOVHload,
443 ssaop.OpLOONG64MOVHUload,
444 ssaop.OpLOONG64MOVWload,
445 ssaop.OpLOONG64MOVWUload,
446 ssaop.OpLOONG64MOVVload,
447 ssaop.OpLOONG64MOVFload,
448 ssaop.OpLOONG64MOVDload:
449 p := s.Prog(v.Op.Asm())
450 p.From.Type = obj.TYPE_MEM
451 p.From.Reg = v.Args[0].Reg()
452 ssagen.AddAux(&p.From, v)
453 p.To.Type = obj.TYPE_REG
454 p.To.Reg = v.Reg()
455 case ssaop.OpLOONG64MOVBstore,
456 ssaop.OpLOONG64MOVHstore,
457 ssaop.OpLOONG64MOVWstore,
458 ssaop.OpLOONG64MOVVstore,
459 ssaop.OpLOONG64MOVFstore,
460 ssaop.OpLOONG64MOVDstore:
461 p := s.Prog(v.Op.Asm())
462 p.From.Type = obj.TYPE_REG
463 p.From.Reg = v.Args[1].Reg()
464 p.To.Type = obj.TYPE_MEM
465 p.To.Reg = v.Args[0].Reg()
466 ssagen.AddAux(&p.To, v)
467 case ssaop.OpLOONG64MOVBreg,
468 ssaop.OpLOONG64MOVBUreg,
469 ssaop.OpLOONG64MOVHreg,
470 ssaop.OpLOONG64MOVHUreg,
471 ssaop.OpLOONG64MOVWreg,
472 ssaop.OpLOONG64MOVWUreg:
473 a := v.Args[0]
474 for a.Op == ssaop.OpCopy || a.Op == ssaop.OpLOONG64MOVVreg {
475 a = a.Args[0]
476 }
477 if a.Op == ssaop.OpLoadReg && loong64.REG_R0 <= a.Reg() && a.Reg() <= loong64.REG_R31 {
478
479
480
481
482 t := a.Type
483 switch {
484 case v.Op == ssaop.OpLOONG64MOVBreg && t.Size() == 1 && t.IsSigned(),
485 v.Op == ssaop.OpLOONG64MOVBUreg && t.Size() == 1 && !t.IsSigned(),
486 v.Op == ssaop.OpLOONG64MOVHreg && t.Size() == 2 && t.IsSigned(),
487 v.Op == ssaop.OpLOONG64MOVHUreg && t.Size() == 2 && !t.IsSigned(),
488 v.Op == ssaop.OpLOONG64MOVWreg && t.Size() == 4 && t.IsSigned(),
489 v.Op == ssaop.OpLOONG64MOVWUreg && t.Size() == 4 && !t.IsSigned():
490
491 if v.Reg() == v.Args[0].Reg() {
492 return
493 }
494 p := s.Prog(loong64.AMOVV)
495 p.From.Type = obj.TYPE_REG
496 p.From.Reg = v.Args[0].Reg()
497 p.To.Type = obj.TYPE_REG
498 p.To.Reg = v.Reg()
499 return
500 default:
501 }
502 }
503 fallthrough
504
505 case ssaop.OpLOONG64MOVWF,
506 ssaop.OpLOONG64MOVWD,
507 ssaop.OpLOONG64TRUNCFW,
508 ssaop.OpLOONG64TRUNCDW,
509 ssaop.OpLOONG64MOVVF,
510 ssaop.OpLOONG64MOVVD,
511 ssaop.OpLOONG64TRUNCFV,
512 ssaop.OpLOONG64TRUNCDV,
513 ssaop.OpLOONG64MOVFD,
514 ssaop.OpLOONG64MOVDF,
515 ssaop.OpLOONG64MOVWfpgp,
516 ssaop.OpLOONG64MOVWgpfp,
517 ssaop.OpLOONG64MOVVfpgp,
518 ssaop.OpLOONG64MOVVgpfp,
519 ssaop.OpLOONG64NEGF,
520 ssaop.OpLOONG64NEGD,
521 ssaop.OpLOONG64CLZW,
522 ssaop.OpLOONG64CLZV,
523 ssaop.OpLOONG64CTZW,
524 ssaop.OpLOONG64CTZV,
525 ssaop.OpLOONG64SQRTD,
526 ssaop.OpLOONG64SQRTF,
527 ssaop.OpLOONG64REVB2H,
528 ssaop.OpLOONG64REVB2W,
529 ssaop.OpLOONG64REVB4H,
530 ssaop.OpLOONG64REVBV,
531 ssaop.OpLOONG64BITREV4B,
532 ssaop.OpLOONG64BITREVW,
533 ssaop.OpLOONG64BITREVV,
534 ssaop.OpLOONG64ABSF,
535 ssaop.OpLOONG64ABSD:
536 p := s.Prog(v.Op.Asm())
537 p.From.Type = obj.TYPE_REG
538 p.From.Reg = v.Args[0].Reg()
539 p.To.Type = obj.TYPE_REG
540 p.To.Reg = v.Reg()
541
542 case ssaop.OpLOONG64VPCNT64,
543 ssaop.OpLOONG64VPCNT32,
544 ssaop.OpLOONG64VPCNT16,
545 ssaop.OpLOONG64FRINTND,
546 ssaop.OpLOONG64FRINTZD,
547 ssaop.OpLOONG64FRINTPD,
548 ssaop.OpLOONG64FRINTMD:
549 p := s.Prog(v.Op.Asm())
550 p.From.Type = obj.TYPE_REG
551 p.From.Reg = ((v.Args[0].Reg() - loong64.REG_F0) & 31) + loong64.REG_V0
552 p.To.Type = obj.TYPE_REG
553 p.To.Reg = ((v.Reg() - loong64.REG_F0) & 31) + loong64.REG_V0
554
555 case ssaop.OpLOONG64NEGV:
556
557 p := s.Prog(loong64.ASUBVU)
558 p.From.Type = obj.TYPE_REG
559 p.From.Reg = v.Args[0].Reg()
560 p.Reg = loong64.REGZERO
561 p.To.Type = obj.TYPE_REG
562 p.To.Reg = v.Reg()
563
564 case ssaop.OpLOONG64LoweredZero:
565 ptrReg := v.Args[0].Reg()
566 n := v.AuxInt
567 if n < 16 {
568 v.Fatalf("Zero too small %d", n)
569 }
570
571
572 var off int64
573 for n >= 8 {
574
575 zero8(s, ptrReg, off)
576 off += 8
577 n -= 8
578 }
579 if n != 0 {
580
581 zero8(s, ptrReg, off+n-8)
582 }
583 case ssaop.OpLOONG64LoweredZeroLoop:
584 ptrReg := v.Args[0].Reg()
585 endReg := v.RegTmp()
586 flagReg := int16(loong64.REGTMP)
587 var off int64
588 n := v.AuxInt
589 loopSize := int64(64)
590 if n < 3*loopSize {
591
592
593
594
595
596
597
598
599 v.Fatalf("ZeroLoop size too small %d", n)
600 }
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630 p1 := s.Prog(loong64.AADDV)
631 p1.From.Type = obj.TYPE_CONST
632 p1.From.Offset = n - n%loopSize
633 p1.Reg = ptrReg
634 p1.To.Type = obj.TYPE_REG
635 p1.To.Reg = endReg
636
637 p2 := s.Prog(loong64.AMOVBU)
638 p2.From.Type = obj.TYPE_MEM
639 p2.From.Name = obj.NAME_EXTERN
640 p2.From.Sym = ir.Syms.Loong64HasLSX
641 p2.To.Type = obj.TYPE_REG
642 p2.To.Reg = flagReg
643
644 p3 := s.Prog(loong64.ABNE)
645 p3.From.Type = obj.TYPE_REG
646 p3.From.Reg = flagReg
647 p3.To.Type = obj.TYPE_BRANCH
648
649 for off = 0; off < loopSize; off += 8 {
650 zero8(s, ptrReg, off)
651 }
652
653 p4 := s.Prog(loong64.AADDV)
654 p4.From.Type = obj.TYPE_CONST
655 p4.From.Offset = loopSize
656 p4.To.Type = obj.TYPE_REG
657 p4.To.Reg = ptrReg
658
659 p5 := s.Prog(loong64.ABNE)
660 p5.From.Type = obj.TYPE_REG
661 p5.From.Reg = endReg
662 p5.Reg = ptrReg
663 p5.To.Type = obj.TYPE_BRANCH
664 p5.To.SetTarget(p3.Link)
665
666 p6 := s.Prog(obj.AJMP)
667 p6.To.Type = obj.TYPE_BRANCH
668
669 p7 := s.Prog(loong64.AVXORV)
670 p7.From.Type = obj.TYPE_REG
671 p7.From.Reg = loong64.REG_V31
672 p7.To.Type = obj.TYPE_REG
673 p7.To.Reg = loong64.REG_V31
674 p3.To.SetTarget(p7)
675
676 for off = 0; off < loopSize; off += 16 {
677 zero16(s, loong64.REG_V31, ptrReg, off)
678 }
679
680 p8 := s.Prog(loong64.AADDV)
681 p8.From.Type = obj.TYPE_CONST
682 p8.From.Offset = loopSize
683 p8.To.Type = obj.TYPE_REG
684 p8.To.Reg = ptrReg
685
686 p9 := s.Prog(loong64.ABNE)
687 p9.From.Type = obj.TYPE_REG
688 p9.From.Reg = endReg
689 p9.Reg = ptrReg
690 p9.To.Type = obj.TYPE_BRANCH
691 p9.To.SetTarget(p7.Link)
692
693 p10 := s.Prog(obj.ANOP)
694 p6.To.SetTarget(p10)
695
696
697 n %= loopSize
698
699 for off = 0; n >= 8; off += 8 {
700
701 zero8(s, ptrReg, off)
702 n -= 8
703 }
704
705 if n != 0 {
706 zero8(s, ptrReg, off+n-8)
707 }
708
709 case ssaop.OpLOONG64LoweredMove:
710 dstReg := v.Args[0].Reg()
711 srcReg := v.Args[1].Reg()
712 if dstReg == srcReg {
713 break
714 }
715 tmpReg := int16(loong64.REG_R23)
716 n := v.AuxInt
717 if n < 16 {
718 v.Fatalf("Move too small %d", n)
719 }
720
721 var off int64
722 for n >= 8 {
723
724
725 move8(s, srcReg, dstReg, tmpReg, off)
726 off += 8
727 n -= 8
728 }
729
730 if n != 0 {
731
732
733 move8(s, srcReg, dstReg, tmpReg, off+n-8)
734 }
735 case ssaop.OpLOONG64LoweredMoveLoop:
736 dstReg := v.Args[0].Reg()
737 srcReg := v.Args[1].Reg()
738 if dstReg == srcReg {
739 break
740 }
741 srcEndReg := int16(loong64.REG_R23)
742 tmpReg := int16(loong64.REG_R24)
743 var off int64
744 n := v.AuxInt
745 loopSize := int64(64)
746 if n < 3*loopSize {
747
748
749
750
751
752
753
754
755 v.Fatalf("MoveLoop size too small %d", n)
756 }
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777 p1 := s.Prog(loong64.AADDV)
778 p1.From.Type = obj.TYPE_CONST
779 p1.From.Offset = n - n%loopSize
780 p1.Reg = srcReg
781 p1.To.Type = obj.TYPE_REG
782 p1.To.Reg = srcEndReg
783
784 for off = 0; off < loopSize; off += 8 {
785 move8(s, srcReg, dstReg, tmpReg, off)
786 }
787
788 p2 := s.Prog(loong64.AADDV)
789 p2.From.Type = obj.TYPE_CONST
790 p2.From.Offset = loopSize
791 p2.To.Type = obj.TYPE_REG
792 p2.To.Reg = srcReg
793
794 p3 := s.Prog(loong64.AADDV)
795 p3.From.Type = obj.TYPE_CONST
796 p3.From.Offset = loopSize
797 p3.To.Type = obj.TYPE_REG
798 p3.To.Reg = dstReg
799
800 p4 := s.Prog(loong64.ABNE)
801 p4.From.Type = obj.TYPE_REG
802 p4.From.Reg = srcEndReg
803 p4.Reg = srcReg
804 p4.To.Type = obj.TYPE_BRANCH
805 p4.To.SetTarget(p1.Link)
806
807
808 n %= loopSize
809
810
811 for off = 0; n >= 8; off += 8 {
812 move8(s, srcReg, dstReg, tmpReg, off)
813 n -= 8
814 }
815
816 if n != 0 {
817 move8(s, srcReg, dstReg, tmpReg, off+n-8)
818 }
819
820 case ssaop.OpLOONG64CALLstatic, ssaop.OpLOONG64CALLclosure, ssaop.OpLOONG64CALLinter:
821 s.Call(v)
822 case ssaop.OpLOONG64CALLtail, ssaop.OpLOONG64CALLtailinter:
823 s.TailCall(v)
824 case ssaop.OpLOONG64LoweredWB:
825 p := s.Prog(obj.ACALL)
826 p.To.Type = obj.TYPE_MEM
827 p.To.Name = obj.NAME_EXTERN
828
829 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
830
831 case ssaop.OpLOONG64LoweredPubBarrier:
832
833 p := s.Prog(v.Op.Asm())
834 p.From.Type = obj.TYPE_CONST
835 p.From.Offset = 0x1A
836
837 case ssaop.OpLOONG64LoweredPanicBoundsRR, ssaop.OpLOONG64LoweredPanicBoundsRC, ssaop.OpLOONG64LoweredPanicBoundsCR, ssaop.OpLOONG64LoweredPanicBoundsCC:
838
839 code, signed := ssa.BoundsKind(v.AuxInt).Code()
840 xIsReg := false
841 yIsReg := false
842 xVal := 0
843 yVal := 0
844 switch v.Op {
845 case ssaop.OpLOONG64LoweredPanicBoundsRR:
846 xIsReg = true
847 xVal = int(v.Args[0].Reg() - loong64.REG_R4)
848 yIsReg = true
849 yVal = int(v.Args[1].Reg() - loong64.REG_R4)
850 case ssaop.OpLOONG64LoweredPanicBoundsRC:
851 xIsReg = true
852 xVal = int(v.Args[0].Reg() - loong64.REG_R4)
853 c := v.Aux.(ssa.PanicBoundsC).C
854 if c >= 0 && c <= abi.BoundsMaxConst {
855 yVal = int(c)
856 } else {
857
858 yIsReg = true
859 if yVal == xVal {
860 yVal = 1
861 }
862 p := s.Prog(loong64.AMOVV)
863 p.From.Type = obj.TYPE_CONST
864 p.From.Offset = c
865 p.To.Type = obj.TYPE_REG
866 p.To.Reg = loong64.REG_R4 + int16(yVal)
867 }
868 case ssaop.OpLOONG64LoweredPanicBoundsCR:
869 yIsReg = true
870 yVal = int(v.Args[0].Reg() - loong64.REG_R4)
871 c := v.Aux.(ssa.PanicBoundsC).C
872 if c >= 0 && c <= abi.BoundsMaxConst {
873 xVal = int(c)
874 } else {
875
876 xIsReg = true
877 if xVal == yVal {
878 xVal = 1
879 }
880 p := s.Prog(loong64.AMOVV)
881 p.From.Type = obj.TYPE_CONST
882 p.From.Offset = c
883 p.To.Type = obj.TYPE_REG
884 p.To.Reg = loong64.REG_R4 + int16(xVal)
885 }
886 case ssaop.OpLOONG64LoweredPanicBoundsCC:
887 c := v.Aux.(ssa.PanicBoundsCC).Cx
888 if c >= 0 && c <= abi.BoundsMaxConst {
889 xVal = int(c)
890 } else {
891
892 xIsReg = true
893 p := s.Prog(loong64.AMOVV)
894 p.From.Type = obj.TYPE_CONST
895 p.From.Offset = c
896 p.To.Type = obj.TYPE_REG
897 p.To.Reg = loong64.REG_R4 + int16(xVal)
898 }
899 c = v.Aux.(ssa.PanicBoundsCC).Cy
900 if c >= 0 && c <= abi.BoundsMaxConst {
901 yVal = int(c)
902 } else {
903
904 yIsReg = true
905 yVal = 1
906 p := s.Prog(loong64.AMOVV)
907 p.From.Type = obj.TYPE_CONST
908 p.From.Offset = c
909 p.To.Type = obj.TYPE_REG
910 p.To.Reg = loong64.REG_R4 + int16(yVal)
911 }
912 }
913 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
914
915 p := s.Prog(obj.APCDATA)
916 p.From.SetConst(abi.PCDATA_PanicBounds)
917 p.To.SetConst(int64(c))
918 p = s.Prog(obj.ACALL)
919 p.To.Type = obj.TYPE_MEM
920 p.To.Name = obj.NAME_EXTERN
921 p.To.Sym = ir.Syms.PanicBounds
922
923 case ssaop.OpLOONG64LoweredAtomicLoad8, ssaop.OpLOONG64LoweredAtomicLoad32, ssaop.OpLOONG64LoweredAtomicLoad64:
924
925
926 as := loong64.AMOVV
927 switch v.Op {
928 case ssaop.OpLOONG64LoweredAtomicLoad8:
929 as = loong64.AMOVBU
930 case ssaop.OpLOONG64LoweredAtomicLoad32:
931 as = loong64.AMOVWU
932 }
933 p := s.Prog(as)
934 p.From.Type = obj.TYPE_MEM
935 p.From.Reg = v.Args[0].Reg()
936 p.To.Type = obj.TYPE_REG
937 p.To.Reg = v.Reg0()
938 p1 := s.Prog(loong64.ADBAR)
939 p1.From.Type = obj.TYPE_CONST
940 p1.From.Offset = 0x14
941
942 case ssaop.OpLOONG64LoweredAtomicStore8,
943 ssaop.OpLOONG64LoweredAtomicStore32,
944 ssaop.OpLOONG64LoweredAtomicStore64:
945
946
947
948 movx := loong64.AMOVV
949 switch v.Op {
950 case ssaop.OpLOONG64LoweredAtomicStore8:
951 movx = loong64.AMOVB
952 case ssaop.OpLOONG64LoweredAtomicStore32:
953 movx = loong64.AMOVW
954 }
955 p := s.Prog(loong64.ADBAR)
956 p.From.Type = obj.TYPE_CONST
957 p.From.Offset = 0x12
958
959 p1 := s.Prog(movx)
960 p1.From.Type = obj.TYPE_REG
961 p1.From.Reg = v.Args[1].Reg()
962 p1.To.Type = obj.TYPE_MEM
963 p1.To.Reg = v.Args[0].Reg()
964
965 p2 := s.Prog(loong64.ADBAR)
966 p2.From.Type = obj.TYPE_CONST
967 p2.From.Offset = 0x18
968
969 case ssaop.OpLOONG64LoweredAtomicStore8Variant,
970 ssaop.OpLOONG64LoweredAtomicStore32Variant,
971 ssaop.OpLOONG64LoweredAtomicStore64Variant:
972
973 amswapx := loong64.AAMSWAPDBV
974 switch v.Op {
975 case ssaop.OpLOONG64LoweredAtomicStore32Variant:
976 amswapx = loong64.AAMSWAPDBW
977 case ssaop.OpLOONG64LoweredAtomicStore8Variant:
978 amswapx = loong64.AAMSWAPDBB
979 }
980 p := s.Prog(amswapx)
981 p.From.Type = obj.TYPE_REG
982 p.From.Reg = v.Args[1].Reg()
983 p.To.Type = obj.TYPE_MEM
984 p.To.Reg = v.Args[0].Reg()
985 p.RegTo2 = loong64.REGZERO
986
987 case ssaop.OpLOONG64LoweredAtomicExchange32, ssaop.OpLOONG64LoweredAtomicExchange64:
988
989 amswapx := loong64.AAMSWAPDBV
990 if v.Op == ssaop.OpLOONG64LoweredAtomicExchange32 {
991 amswapx = loong64.AAMSWAPDBW
992 }
993 p := s.Prog(amswapx)
994 p.From.Type = obj.TYPE_REG
995 p.From.Reg = v.Args[1].Reg()
996 p.To.Type = obj.TYPE_MEM
997 p.To.Reg = v.Args[0].Reg()
998 p.RegTo2 = v.Reg0()
999
1000 case ssaop.OpLOONG64LoweredAtomicExchange8Variant:
1001
1002 p := s.Prog(loong64.AAMSWAPDBB)
1003 p.From.Type = obj.TYPE_REG
1004 p.From.Reg = v.Args[1].Reg()
1005 p.To.Type = obj.TYPE_MEM
1006 p.To.Reg = v.Args[0].Reg()
1007 p.RegTo2 = v.Reg0()
1008
1009 case ssaop.OpLOONG64LoweredAtomicAdd32, ssaop.OpLOONG64LoweredAtomicAdd64:
1010
1011
1012 amaddx := loong64.AAMADDDBV
1013 addx := loong64.AADDV
1014 if v.Op == ssaop.OpLOONG64LoweredAtomicAdd32 {
1015 amaddx = loong64.AAMADDDBW
1016 }
1017 p := s.Prog(amaddx)
1018 p.From.Type = obj.TYPE_REG
1019 p.From.Reg = v.Args[1].Reg()
1020 p.To.Type = obj.TYPE_MEM
1021 p.To.Reg = v.Args[0].Reg()
1022 p.RegTo2 = v.Reg0()
1023
1024 p1 := s.Prog(addx)
1025 p1.From.Type = obj.TYPE_REG
1026 p1.From.Reg = v.Args[1].Reg()
1027 p1.Reg = v.Reg0()
1028 p1.To.Type = obj.TYPE_REG
1029 p1.To.Reg = v.Reg0()
1030
1031 case ssaop.OpLOONG64LoweredAtomicCas32, ssaop.OpLOONG64LoweredAtomicCas64:
1032
1033
1034
1035
1036
1037
1038
1039
1040 ll := loong64.ALLV
1041 sc := loong64.ASCV
1042 if v.Op == ssaop.OpLOONG64LoweredAtomicCas32 {
1043 ll = loong64.ALL
1044 sc = loong64.ASC
1045 }
1046
1047 p := s.Prog(loong64.AMOVV)
1048 p.From.Type = obj.TYPE_REG
1049 p.From.Reg = loong64.REGZERO
1050 p.To.Type = obj.TYPE_REG
1051 p.To.Reg = v.Reg0()
1052
1053 p1 := s.Prog(loong64.ADBAR)
1054 p1.From.Type = obj.TYPE_CONST
1055 p1.From.Offset = 0x14
1056
1057 p2 := s.Prog(ll)
1058 p2.From.Type = obj.TYPE_MEM
1059 p2.From.Reg = v.Args[0].Reg()
1060 p2.To.Type = obj.TYPE_REG
1061 p2.To.Reg = loong64.REGTMP
1062
1063 p3 := s.Prog(loong64.ABNE)
1064 p3.From.Type = obj.TYPE_REG
1065 p3.From.Reg = v.Args[1].Reg()
1066 p3.Reg = loong64.REGTMP
1067 p3.To.Type = obj.TYPE_BRANCH
1068
1069 p4 := s.Prog(loong64.AMOVV)
1070 p4.From.Type = obj.TYPE_REG
1071 p4.From.Reg = v.Args[2].Reg()
1072 p4.To.Type = obj.TYPE_REG
1073 p4.To.Reg = v.Reg0()
1074
1075 p5 := s.Prog(sc)
1076 p5.From.Type = obj.TYPE_REG
1077 p5.From.Reg = v.Reg0()
1078 p5.To.Type = obj.TYPE_MEM
1079 p5.To.Reg = v.Args[0].Reg()
1080
1081 p6 := s.Prog(loong64.ABEQ)
1082 p6.From.Type = obj.TYPE_REG
1083 p6.From.Reg = v.Reg0()
1084 p6.To.Type = obj.TYPE_BRANCH
1085 p6.To.SetTarget(p2)
1086
1087 p7 := s.Prog(loong64.ADBAR)
1088 p7.From.Type = obj.TYPE_CONST
1089 p7.From.Offset = 0x12
1090 p3.To.SetTarget(p7)
1091
1092 case ssaop.OpLOONG64LoweredAtomicAnd32,
1093 ssaop.OpLOONG64LoweredAtomicOr32:
1094
1095 p := s.Prog(v.Op.Asm())
1096 p.From.Type = obj.TYPE_REG
1097 p.From.Reg = v.Args[1].Reg()
1098 p.To.Type = obj.TYPE_MEM
1099 p.To.Reg = v.Args[0].Reg()
1100 p.RegTo2 = loong64.REGZERO
1101
1102 case ssaop.OpLOONG64LoweredAtomicAnd32value,
1103 ssaop.OpLOONG64LoweredAtomicAnd64value,
1104 ssaop.OpLOONG64LoweredAtomicOr64value,
1105 ssaop.OpLOONG64LoweredAtomicOr32value:
1106
1107 p := s.Prog(v.Op.Asm())
1108 p.From.Type = obj.TYPE_REG
1109 p.From.Reg = v.Args[1].Reg()
1110 p.To.Type = obj.TYPE_MEM
1111 p.To.Reg = v.Args[0].Reg()
1112 p.RegTo2 = v.Reg0()
1113
1114 case ssaop.OpLOONG64LoweredAtomicCas64Variant, ssaop.OpLOONG64LoweredAtomicCas32Variant:
1115
1116
1117
1118
1119
1120
1121
1122 amcasx := loong64.AAMCASDBV
1123 if v.Op == ssaop.OpLOONG64LoweredAtomicCas32Variant {
1124 amcasx = loong64.AAMCASDBW
1125 }
1126
1127 p := s.Prog(loong64.AMOVV)
1128 p.From.Type = obj.TYPE_REG
1129 p.From.Reg = loong64.REGZERO
1130 p.To.Type = obj.TYPE_REG
1131 p.To.Reg = v.Reg0()
1132
1133 p1 := s.Prog(loong64.AMOVV)
1134 p1.From.Type = obj.TYPE_REG
1135 p1.From.Reg = v.Args[1].Reg()
1136 p1.To.Type = obj.TYPE_REG
1137 p1.To.Reg = loong64.REGTMP
1138
1139 p2 := s.Prog(amcasx)
1140 p2.From.Type = obj.TYPE_REG
1141 p2.From.Reg = v.Args[2].Reg()
1142 p2.To.Type = obj.TYPE_MEM
1143 p2.To.Reg = v.Args[0].Reg()
1144 p2.RegTo2 = loong64.REGTMP
1145
1146 p3 := s.Prog(loong64.ABNE)
1147 p3.From.Type = obj.TYPE_REG
1148 p3.From.Reg = v.Args[1].Reg()
1149 p3.Reg = loong64.REGTMP
1150 p3.To.Type = obj.TYPE_BRANCH
1151
1152 p4 := s.Prog(loong64.AMOVV)
1153 p4.From.Type = obj.TYPE_CONST
1154 p4.From.Offset = 0x1
1155 p4.To.Type = obj.TYPE_REG
1156 p4.To.Reg = v.Reg0()
1157
1158 p5 := s.Prog(obj.ANOP)
1159 p3.To.SetTarget(p5)
1160
1161 case ssaop.OpLOONG64LoweredNilCheck:
1162
1163 p := s.Prog(loong64.AMOVB)
1164 p.From.Type = obj.TYPE_MEM
1165 p.From.Reg = v.Args[0].Reg()
1166 ssagen.AddAux(&p.From, v)
1167 p.To.Type = obj.TYPE_REG
1168 p.To.Reg = loong64.REGTMP
1169 if logopt.Enabled() {
1170 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
1171 }
1172 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
1173 base.WarnfAt(v.Pos, "generated nil check")
1174 }
1175 case ssaop.OpLOONG64FPFlagTrue,
1176 ssaop.OpLOONG64FPFlagFalse:
1177
1178
1179
1180 branch := loong64.ABFPF
1181 if v.Op == ssaop.OpLOONG64FPFlagFalse {
1182 branch = loong64.ABFPT
1183 }
1184 p := s.Prog(loong64.AMOVV)
1185 p.From.Type = obj.TYPE_REG
1186 p.From.Reg = loong64.REGZERO
1187 p.To.Type = obj.TYPE_REG
1188 p.To.Reg = v.Reg()
1189 p2 := s.Prog(branch)
1190 p2.To.Type = obj.TYPE_BRANCH
1191 p3 := s.Prog(loong64.AMOVV)
1192 p3.From.Type = obj.TYPE_CONST
1193 p3.From.Offset = 1
1194 p3.To.Type = obj.TYPE_REG
1195 p3.To.Reg = v.Reg()
1196 p4 := s.Prog(obj.ANOP)
1197 p2.To.SetTarget(p4)
1198 case ssaop.OpLOONG64LoweredGetClosurePtr:
1199
1200 ssagen.CheckLoweredGetClosurePtr(v)
1201 case ssaop.OpLOONG64LoweredGetCallerSP:
1202
1203 p := s.Prog(loong64.AMOVV)
1204 p.From.Type = obj.TYPE_ADDR
1205 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
1206 p.From.Name = obj.NAME_PARAM
1207 p.To.Type = obj.TYPE_REG
1208 p.To.Reg = v.Reg()
1209 case ssaop.OpLOONG64LoweredGetCallerPC:
1210 p := s.Prog(obj.AGETCALLERPC)
1211 p.To.Type = obj.TYPE_REG
1212 p.To.Reg = v.Reg()
1213 case ssaop.OpLOONG64MASKEQZ, ssaop.OpLOONG64MASKNEZ:
1214 p := s.Prog(v.Op.Asm())
1215 p.From.Type = obj.TYPE_REG
1216 p.From.Reg = v.Args[1].Reg()
1217 p.Reg = v.Args[0].Reg()
1218 p.To.Type = obj.TYPE_REG
1219 p.To.Reg = v.Reg()
1220
1221 case ssaop.OpLOONG64PRELD:
1222
1223 p := s.Prog(v.Op.Asm())
1224 p.From.Type = obj.TYPE_MEM
1225 p.From.Reg = v.Args[0].Reg()
1226 p.AddRestSourceConst(v.AuxInt & 0x1f)
1227
1228 case ssaop.OpLOONG64PRELDX:
1229
1230 p := s.Prog(v.Op.Asm())
1231 p.From.Type = obj.TYPE_MEM
1232 p.From.Reg = v.Args[0].Reg()
1233 p.AddRestSourceArgs([]obj.Addr{
1234 {Type: obj.TYPE_CONST, Offset: (v.AuxInt >> 5) & 0x1fffffffff},
1235 {Type: obj.TYPE_CONST, Offset: (v.AuxInt >> 0) & 0x1f},
1236 })
1237
1238 case ssaop.OpLOONG64ADDshiftLLV:
1239
1240
1241 p := s.Prog(v.Op.Asm())
1242 p.From.Type = obj.TYPE_CONST
1243 p.From.Offset = v.AuxInt
1244 p.Reg = v.Args[1].Reg()
1245 p.AddRestSourceReg(v.Args[0].Reg())
1246 p.To.Type = obj.TYPE_REG
1247 p.To.Reg = v.Reg()
1248
1249 case ssaop.OpClobber, ssaop.OpClobberReg:
1250
1251 default:
1252 v.Fatalf("genValue not implemented: %s", v.LongString())
1253 }
1254 }
1255
1256 var blockJump = map[block.BlockKind]struct {
1257 asm, invasm obj.As
1258 }{
1259 block.BlockLOONG64EQZ: {loong64.ABEQ, loong64.ABNE},
1260 block.BlockLOONG64NEZ: {loong64.ABNE, loong64.ABEQ},
1261 block.BlockLOONG64LTZ: {loong64.ABLTZ, loong64.ABGEZ},
1262 block.BlockLOONG64GEZ: {loong64.ABGEZ, loong64.ABLTZ},
1263 block.BlockLOONG64LEZ: {loong64.ABLEZ, loong64.ABGTZ},
1264 block.BlockLOONG64GTZ: {loong64.ABGTZ, loong64.ABLEZ},
1265 block.BlockLOONG64FPT: {loong64.ABFPT, loong64.ABFPF},
1266 block.BlockLOONG64FPF: {loong64.ABFPF, loong64.ABFPT},
1267 block.BlockLOONG64BEQ: {loong64.ABEQ, loong64.ABNE},
1268 block.BlockLOONG64BNE: {loong64.ABNE, loong64.ABEQ},
1269 block.BlockLOONG64BGE: {loong64.ABGE, loong64.ABLT},
1270 block.BlockLOONG64BLT: {loong64.ABLT, loong64.ABGE},
1271 block.BlockLOONG64BLTU: {loong64.ABLTU, loong64.ABGEU},
1272 block.BlockLOONG64BGEU: {loong64.ABGEU, loong64.ABLTU},
1273 }
1274
1275 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
1276 switch b.Kind {
1277 case block.BlockPlain, block.BlockDefer:
1278 if b.Succs[0].Block() != next {
1279 p := s.Prog(obj.AJMP)
1280 p.To.Type = obj.TYPE_BRANCH
1281 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
1282 }
1283 case block.BlockExit, block.BlockRetJmp:
1284 case block.BlockRet:
1285 s.Prog(obj.ARET)
1286 case block.BlockLOONG64EQZ, block.BlockLOONG64NEZ,
1287 block.BlockLOONG64LTZ, block.BlockLOONG64GEZ,
1288 block.BlockLOONG64LEZ, block.BlockLOONG64GTZ,
1289 block.BlockLOONG64BEQ, block.BlockLOONG64BNE,
1290 block.BlockLOONG64BLT, block.BlockLOONG64BGE,
1291 block.BlockLOONG64BLTU, block.BlockLOONG64BGEU,
1292 block.BlockLOONG64FPT, block.BlockLOONG64FPF:
1293 jmp := blockJump[b.Kind]
1294 var p *obj.Prog
1295 switch next {
1296 case b.Succs[0].Block():
1297 p = s.Br(jmp.invasm, b.Succs[1].Block())
1298 case b.Succs[1].Block():
1299 p = s.Br(jmp.asm, b.Succs[0].Block())
1300 default:
1301 if b.Likely != ssa.BranchUnlikely {
1302 p = s.Br(jmp.asm, b.Succs[0].Block())
1303 s.Br(obj.AJMP, b.Succs[1].Block())
1304 } else {
1305 p = s.Br(jmp.invasm, b.Succs[1].Block())
1306 s.Br(obj.AJMP, b.Succs[0].Block())
1307 }
1308 }
1309 switch b.Kind {
1310 case block.BlockLOONG64BEQ, block.BlockLOONG64BNE,
1311 block.BlockLOONG64BGE, block.BlockLOONG64BLT,
1312 block.BlockLOONG64BGEU, block.BlockLOONG64BLTU:
1313 p.From.Type = obj.TYPE_REG
1314 p.From.Reg = b.Controls[0].Reg()
1315 p.Reg = b.Controls[1].Reg()
1316 case block.BlockLOONG64EQZ, block.BlockLOONG64NEZ,
1317 block.BlockLOONG64LTZ, block.BlockLOONG64GEZ,
1318 block.BlockLOONG64LEZ, block.BlockLOONG64GTZ,
1319 block.BlockLOONG64FPT, block.BlockLOONG64FPF:
1320 if !b.Controls[0].Type.IsFlags() {
1321 p.From.Type = obj.TYPE_REG
1322 p.From.Reg = b.Controls[0].Reg()
1323 }
1324 }
1325 case block.BlockLOONG64JUMPTABLE:
1326
1327
1328
1329 p := s.Prog(loong64.AALSLV)
1330 p.From.Type = obj.TYPE_CONST
1331 p.From.Offset = 3
1332 p.Reg = b.Controls[0].Reg()
1333 p.AddRestSourceReg(b.Controls[1].Reg())
1334 p.To.Type = obj.TYPE_REG
1335 p.To.Reg = loong64.REGTMP
1336 p1 := s.Prog(loong64.AMOVV)
1337 p1.From.Type = obj.TYPE_MEM
1338 p1.From.Reg = loong64.REGTMP
1339 p1.From.Offset = 0
1340 p1.To.Type = obj.TYPE_REG
1341 p1.To.Reg = loong64.REGTMP
1342 p2 := s.Prog(obj.AJMP)
1343 p2.To.Type = obj.TYPE_MEM
1344 p2.To.Reg = loong64.REGTMP
1345
1346 s.JumpTables = append(s.JumpTables, b)
1347
1348 default:
1349 b.Fatalf("branch not implemented: %s", b.LongString())
1350 }
1351 }
1352
1353 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1354 p := s.Prog(loadByType(t, reg))
1355 p.From.Type = obj.TYPE_MEM
1356 p.From.Name = obj.NAME_AUTO
1357 p.From.Sym = n.Linksym()
1358 p.From.Offset = n.FrameOffset() + off
1359 p.To.Type = obj.TYPE_REG
1360 p.To.Reg = reg
1361 return p
1362 }
1363
1364 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1365 p = pp.Append(p, storeByType(t, reg), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
1366 p.To.Name = obj.NAME_PARAM
1367 p.To.Sym = n.Linksym()
1368 p.Pos = p.Pos.WithNotStmt()
1369 return p
1370 }
1371
1372
1373 func move8(s *ssagen.State, src, dst, tmp int16, off int64) {
1374
1375 ld := s.Prog(loong64.AMOVV)
1376 ld.From.Type = obj.TYPE_MEM
1377 ld.From.Reg = src
1378 ld.From.Offset = off
1379 ld.To.Type = obj.TYPE_REG
1380 ld.To.Reg = tmp
1381
1382 st := s.Prog(loong64.AMOVV)
1383 st.From.Type = obj.TYPE_REG
1384 st.From.Reg = tmp
1385 st.To.Type = obj.TYPE_MEM
1386 st.To.Reg = dst
1387 st.To.Offset = off
1388 }
1389
1390
1391 func zero8(s *ssagen.State, reg int16, off int64) {
1392
1393 p := s.Prog(loong64.AMOVV)
1394 p.From.Type = obj.TYPE_REG
1395 p.From.Reg = loong64.REGZERO
1396 p.To.Type = obj.TYPE_MEM
1397 p.To.Reg = reg
1398 p.To.Offset = off
1399 }
1400
1401
1402 func zero16(s *ssagen.State, regZero, regBase int16, off int64) {
1403
1404 p := s.Prog(loong64.AVMOVQ)
1405 p.From.Type = obj.TYPE_REG
1406 p.From.Reg = regZero
1407 p.To.Type = obj.TYPE_MEM
1408 p.To.Reg = regBase
1409 p.To.Offset = off
1410 }
1411
View as plain text