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