1
2
3
4
5 package riscv64
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/objw"
11 "cmd/compile/internal/ssa"
12 "cmd/compile/internal/ssagen"
13 "cmd/compile/internal/types"
14 "cmd/internal/obj"
15 "cmd/internal/obj/riscv"
16 )
17
18
19 var ssaRegToReg = []int16{
20 riscv.REG_X0,
21
22 riscv.REG_X2,
23 riscv.REG_X3,
24 riscv.REG_X4,
25 riscv.REG_X5,
26 riscv.REG_X6,
27 riscv.REG_X7,
28 riscv.REG_X8,
29 riscv.REG_X9,
30 riscv.REG_X10,
31 riscv.REG_X11,
32 riscv.REG_X12,
33 riscv.REG_X13,
34 riscv.REG_X14,
35 riscv.REG_X15,
36 riscv.REG_X16,
37 riscv.REG_X17,
38 riscv.REG_X18,
39 riscv.REG_X19,
40 riscv.REG_X20,
41 riscv.REG_X21,
42 riscv.REG_X22,
43 riscv.REG_X23,
44 riscv.REG_X24,
45 riscv.REG_X25,
46 riscv.REG_X26,
47 riscv.REG_X27,
48 riscv.REG_X28,
49 riscv.REG_X29,
50 riscv.REG_X30,
51 riscv.REG_X31,
52 riscv.REG_F0,
53 riscv.REG_F1,
54 riscv.REG_F2,
55 riscv.REG_F3,
56 riscv.REG_F4,
57 riscv.REG_F5,
58 riscv.REG_F6,
59 riscv.REG_F7,
60 riscv.REG_F8,
61 riscv.REG_F9,
62 riscv.REG_F10,
63 riscv.REG_F11,
64 riscv.REG_F12,
65 riscv.REG_F13,
66 riscv.REG_F14,
67 riscv.REG_F15,
68 riscv.REG_F16,
69 riscv.REG_F17,
70 riscv.REG_F18,
71 riscv.REG_F19,
72 riscv.REG_F20,
73 riscv.REG_F21,
74 riscv.REG_F22,
75 riscv.REG_F23,
76 riscv.REG_F24,
77 riscv.REG_F25,
78 riscv.REG_F26,
79 riscv.REG_F27,
80 riscv.REG_F28,
81 riscv.REG_F29,
82 riscv.REG_F30,
83 riscv.REG_F31,
84 0,
85 }
86
87 func loadByType(t *types.Type) obj.As {
88 width := t.Size()
89
90 if t.IsFloat() {
91 switch width {
92 case 4:
93 return riscv.AMOVF
94 case 8:
95 return riscv.AMOVD
96 default:
97 base.Fatalf("unknown float width for load %d in type %v", width, t)
98 return 0
99 }
100 }
101
102 switch width {
103 case 1:
104 if t.IsSigned() {
105 return riscv.AMOVB
106 } else {
107 return riscv.AMOVBU
108 }
109 case 2:
110 if t.IsSigned() {
111 return riscv.AMOVH
112 } else {
113 return riscv.AMOVHU
114 }
115 case 4:
116 if t.IsSigned() {
117 return riscv.AMOVW
118 } else {
119 return riscv.AMOVWU
120 }
121 case 8:
122 return riscv.AMOV
123 default:
124 base.Fatalf("unknown width for load %d in type %v", width, t)
125 return 0
126 }
127 }
128
129
130 func storeByType(t *types.Type) obj.As {
131 width := t.Size()
132
133 if t.IsFloat() {
134 switch width {
135 case 4:
136 return riscv.AMOVF
137 case 8:
138 return riscv.AMOVD
139 default:
140 base.Fatalf("unknown float width for store %d in type %v", width, t)
141 return 0
142 }
143 }
144
145 switch width {
146 case 1:
147 return riscv.AMOVB
148 case 2:
149 return riscv.AMOVH
150 case 4:
151 return riscv.AMOVW
152 case 8:
153 return riscv.AMOV
154 default:
155 base.Fatalf("unknown width for store %d in type %v", width, t)
156 return 0
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169 func largestMove(alignment int64) (obj.As, int64) {
170 switch {
171 case alignment%8 == 0:
172 return riscv.AMOV, 8
173 case alignment%4 == 0:
174 return riscv.AMOVW, 4
175 case alignment%2 == 0:
176 return riscv.AMOVH, 2
177 default:
178 return riscv.AMOVB, 1
179 }
180 }
181
182
183
184 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {}
185
186 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
187 s.SetPos(v.Pos)
188
189 switch v.Op {
190 case ssa.OpInitMem:
191
192 case ssa.OpArg:
193
194 case ssa.OpPhi:
195 ssagen.CheckLoweredPhi(v)
196 case ssa.OpCopy, ssa.OpRISCV64MOVDreg:
197 if v.Type.IsMemory() {
198 return
199 }
200 rs := v.Args[0].Reg()
201 rd := v.Reg()
202 if rs == rd {
203 return
204 }
205 as := riscv.AMOV
206 if v.Type.IsFloat() {
207 as = riscv.AMOVD
208 }
209 p := s.Prog(as)
210 p.From.Type = obj.TYPE_REG
211 p.From.Reg = rs
212 p.To.Type = obj.TYPE_REG
213 p.To.Reg = rd
214 case ssa.OpRISCV64MOVDnop:
215
216 case ssa.OpLoadReg:
217 if v.Type.IsFlags() {
218 v.Fatalf("load flags not implemented: %v", v.LongString())
219 return
220 }
221 p := s.Prog(loadByType(v.Type))
222 ssagen.AddrAuto(&p.From, v.Args[0])
223 p.To.Type = obj.TYPE_REG
224 p.To.Reg = v.Reg()
225 case ssa.OpStoreReg:
226 if v.Type.IsFlags() {
227 v.Fatalf("store flags not implemented: %v", v.LongString())
228 return
229 }
230 p := s.Prog(storeByType(v.Type))
231 p.From.Type = obj.TYPE_REG
232 p.From.Reg = v.Args[0].Reg()
233 ssagen.AddrAuto(&p.To, v)
234 case ssa.OpArgIntReg, ssa.OpArgFloatReg:
235
236
237 for _, a := range v.Block.Func.RegArgs {
238
239
240 addr := ssagen.SpillSlotAddr(a, riscv.REG_SP, base.Ctxt.Arch.FixedFrameSize)
241 s.FuncInfo().AddSpill(
242 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
243 }
244 v.Block.Func.RegArgs = nil
245
246 ssagen.CheckArgReg(v)
247 case ssa.OpSP, ssa.OpSB, ssa.OpGetG:
248
249 case ssa.OpRISCV64MOVBreg, ssa.OpRISCV64MOVHreg, ssa.OpRISCV64MOVWreg,
250 ssa.OpRISCV64MOVBUreg, ssa.OpRISCV64MOVHUreg, ssa.OpRISCV64MOVWUreg:
251 a := v.Args[0]
252 for a.Op == ssa.OpCopy || a.Op == ssa.OpRISCV64MOVDreg {
253 a = a.Args[0]
254 }
255 as := v.Op.Asm()
256 rs := v.Args[0].Reg()
257 rd := v.Reg()
258 if a.Op == ssa.OpLoadReg {
259 t := a.Type
260 switch {
261 case v.Op == ssa.OpRISCV64MOVBreg && t.Size() == 1 && t.IsSigned(),
262 v.Op == ssa.OpRISCV64MOVHreg && t.Size() == 2 && t.IsSigned(),
263 v.Op == ssa.OpRISCV64MOVWreg && t.Size() == 4 && t.IsSigned(),
264 v.Op == ssa.OpRISCV64MOVBUreg && t.Size() == 1 && !t.IsSigned(),
265 v.Op == ssa.OpRISCV64MOVHUreg && t.Size() == 2 && !t.IsSigned(),
266 v.Op == ssa.OpRISCV64MOVWUreg && t.Size() == 4 && !t.IsSigned():
267
268 if rs == rd {
269 return
270 }
271 as = riscv.AMOV
272 default:
273 }
274 }
275 p := s.Prog(as)
276 p.From.Type = obj.TYPE_REG
277 p.From.Reg = rs
278 p.To.Type = obj.TYPE_REG
279 p.To.Reg = rd
280 case ssa.OpRISCV64ADD, ssa.OpRISCV64SUB, ssa.OpRISCV64SUBW, ssa.OpRISCV64XOR, ssa.OpRISCV64OR, ssa.OpRISCV64AND,
281 ssa.OpRISCV64SLL, ssa.OpRISCV64SLLW, ssa.OpRISCV64SRA, ssa.OpRISCV64SRAW, ssa.OpRISCV64SRL, ssa.OpRISCV64SRLW,
282 ssa.OpRISCV64SLT, ssa.OpRISCV64SLTU, ssa.OpRISCV64MUL, ssa.OpRISCV64MULW, ssa.OpRISCV64MULH,
283 ssa.OpRISCV64MULHU, ssa.OpRISCV64DIV, ssa.OpRISCV64DIVU, ssa.OpRISCV64DIVW,
284 ssa.OpRISCV64DIVUW, ssa.OpRISCV64REM, ssa.OpRISCV64REMU, ssa.OpRISCV64REMW,
285 ssa.OpRISCV64REMUW,
286 ssa.OpRISCV64ROL, ssa.OpRISCV64ROLW, ssa.OpRISCV64ROR, ssa.OpRISCV64RORW,
287 ssa.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS,
288 ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES,
289 ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD,
290 ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED,
291 ssa.OpRISCV64FSGNJD:
292 r := v.Reg()
293 r1 := v.Args[0].Reg()
294 r2 := v.Args[1].Reg()
295 p := s.Prog(v.Op.Asm())
296 p.From.Type = obj.TYPE_REG
297 p.From.Reg = r2
298 p.Reg = r1
299 p.To.Type = obj.TYPE_REG
300 p.To.Reg = r
301
302 case ssa.OpRISCV64LoweredFMAXD, ssa.OpRISCV64LoweredFMIND, ssa.OpRISCV64LoweredFMAXS, ssa.OpRISCV64LoweredFMINS:
303
304
305
306
307
308
309
310
311
312
313
314 r0 := v.Args[0].Reg()
315 r1 := v.Args[1].Reg()
316 out := v.Reg()
317 add, feq := riscv.AFADDD, riscv.AFEQD
318 if v.Op == ssa.OpRISCV64LoweredFMAXS || v.Op == ssa.OpRISCV64LoweredFMINS {
319 add = riscv.AFADDS
320 feq = riscv.AFEQS
321 }
322
323 p1 := s.Prog(add)
324 p1.From.Type = obj.TYPE_REG
325 p1.From.Reg = r0
326 p1.Reg = r1
327 p1.To.Type = obj.TYPE_REG
328 p1.To.Reg = out
329
330 p2 := s.Prog(feq)
331 p2.From.Type = obj.TYPE_REG
332 p2.From.Reg = r0
333 p2.Reg = r0
334 p2.To.Type = obj.TYPE_REG
335 p2.To.Reg = riscv.REG_TMP
336
337 p3 := s.Prog(riscv.ABEQ)
338 p3.From.Type = obj.TYPE_REG
339 p3.From.Reg = riscv.REG_ZERO
340 p3.Reg = riscv.REG_TMP
341 p3.To.Type = obj.TYPE_BRANCH
342
343 p4 := s.Prog(feq)
344 p4.From.Type = obj.TYPE_REG
345 p4.From.Reg = r1
346 p4.Reg = r1
347 p4.To.Type = obj.TYPE_REG
348 p4.To.Reg = riscv.REG_TMP
349
350 p5 := s.Prog(riscv.ABEQ)
351 p5.From.Type = obj.TYPE_REG
352 p5.From.Reg = riscv.REG_ZERO
353 p5.Reg = riscv.REG_TMP
354 p5.To.Type = obj.TYPE_BRANCH
355
356 p6 := s.Prog(v.Op.Asm())
357 p6.From.Type = obj.TYPE_REG
358 p6.From.Reg = r1
359 p6.Reg = r0
360 p6.To.Type = obj.TYPE_REG
361 p6.To.Reg = out
362
363 nop := s.Prog(obj.ANOP)
364 p3.To.SetTarget(nop)
365 p5.To.SetTarget(nop)
366
367 case ssa.OpRISCV64LoweredMuluhilo:
368 r0 := v.Args[0].Reg()
369 r1 := v.Args[1].Reg()
370 p := s.Prog(riscv.AMULHU)
371 p.From.Type = obj.TYPE_REG
372 p.From.Reg = r1
373 p.Reg = r0
374 p.To.Type = obj.TYPE_REG
375 p.To.Reg = v.Reg0()
376 p1 := s.Prog(riscv.AMUL)
377 p1.From.Type = obj.TYPE_REG
378 p1.From.Reg = r1
379 p1.Reg = r0
380 p1.To.Type = obj.TYPE_REG
381 p1.To.Reg = v.Reg1()
382 case ssa.OpRISCV64LoweredMuluover:
383 r0 := v.Args[0].Reg()
384 r1 := v.Args[1].Reg()
385 p := s.Prog(riscv.AMULHU)
386 p.From.Type = obj.TYPE_REG
387 p.From.Reg = r1
388 p.Reg = r0
389 p.To.Type = obj.TYPE_REG
390 p.To.Reg = v.Reg1()
391 p1 := s.Prog(riscv.AMUL)
392 p1.From.Type = obj.TYPE_REG
393 p1.From.Reg = r1
394 p1.Reg = r0
395 p1.To.Type = obj.TYPE_REG
396 p1.To.Reg = v.Reg0()
397 p2 := s.Prog(riscv.ASNEZ)
398 p2.From.Type = obj.TYPE_REG
399 p2.From.Reg = v.Reg1()
400 p2.To.Type = obj.TYPE_REG
401 p2.To.Reg = v.Reg1()
402 case ssa.OpRISCV64FMADDD, ssa.OpRISCV64FMSUBD, ssa.OpRISCV64FNMADDD, ssa.OpRISCV64FNMSUBD,
403 ssa.OpRISCV64FMADDS, ssa.OpRISCV64FMSUBS, ssa.OpRISCV64FNMADDS, ssa.OpRISCV64FNMSUBS:
404 r := v.Reg()
405 r1 := v.Args[0].Reg()
406 r2 := v.Args[1].Reg()
407 r3 := v.Args[2].Reg()
408 p := s.Prog(v.Op.Asm())
409 p.From.Type = obj.TYPE_REG
410 p.From.Reg = r2
411 p.Reg = r1
412 p.AddRestSource(obj.Addr{Type: obj.TYPE_REG, Reg: r3})
413 p.To.Type = obj.TYPE_REG
414 p.To.Reg = r
415 case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FABSD, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
416 ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX,
417 ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
418 ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD,
419 ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW:
420 p := s.Prog(v.Op.Asm())
421 p.From.Type = obj.TYPE_REG
422 p.From.Reg = v.Args[0].Reg()
423 p.To.Type = obj.TYPE_REG
424 p.To.Reg = v.Reg()
425 case ssa.OpRISCV64ADDI, ssa.OpRISCV64ADDIW, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
426 ssa.OpRISCV64SLLI, ssa.OpRISCV64SLLIW, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRAIW,
427 ssa.OpRISCV64SRLI, ssa.OpRISCV64SRLIW, ssa.OpRISCV64SLTI, ssa.OpRISCV64SLTIU,
428 ssa.OpRISCV64RORI, ssa.OpRISCV64RORIW:
429 p := s.Prog(v.Op.Asm())
430 p.From.Type = obj.TYPE_CONST
431 p.From.Offset = v.AuxInt
432 p.Reg = v.Args[0].Reg()
433 p.To.Type = obj.TYPE_REG
434 p.To.Reg = v.Reg()
435 case ssa.OpRISCV64MOVDconst:
436 p := s.Prog(v.Op.Asm())
437 p.From.Type = obj.TYPE_CONST
438 p.From.Offset = v.AuxInt
439 p.To.Type = obj.TYPE_REG
440 p.To.Reg = v.Reg()
441 case ssa.OpRISCV64MOVaddr:
442 p := s.Prog(v.Op.Asm())
443 p.From.Type = obj.TYPE_ADDR
444 p.To.Type = obj.TYPE_REG
445 p.To.Reg = v.Reg()
446
447 var wantreg string
448
449 switch v.Aux.(type) {
450 default:
451 v.Fatalf("aux is of unknown type %T", v.Aux)
452 case *obj.LSym:
453 wantreg = "SB"
454 ssagen.AddAux(&p.From, v)
455 case *ir.Name:
456 wantreg = "SP"
457 ssagen.AddAux(&p.From, v)
458 case nil:
459
460 wantreg = "SP"
461 p.From.Reg = riscv.REG_SP
462 p.From.Offset = v.AuxInt
463 }
464 if reg := v.Args[0].RegName(); reg != wantreg {
465 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
466 }
467 case ssa.OpRISCV64MOVBload, ssa.OpRISCV64MOVHload, ssa.OpRISCV64MOVWload, ssa.OpRISCV64MOVDload,
468 ssa.OpRISCV64MOVBUload, ssa.OpRISCV64MOVHUload, ssa.OpRISCV64MOVWUload,
469 ssa.OpRISCV64FMOVWload, ssa.OpRISCV64FMOVDload:
470 p := s.Prog(v.Op.Asm())
471 p.From.Type = obj.TYPE_MEM
472 p.From.Reg = v.Args[0].Reg()
473 ssagen.AddAux(&p.From, v)
474 p.To.Type = obj.TYPE_REG
475 p.To.Reg = v.Reg()
476 case ssa.OpRISCV64MOVBstore, ssa.OpRISCV64MOVHstore, ssa.OpRISCV64MOVWstore, ssa.OpRISCV64MOVDstore,
477 ssa.OpRISCV64FMOVWstore, ssa.OpRISCV64FMOVDstore:
478 p := s.Prog(v.Op.Asm())
479 p.From.Type = obj.TYPE_REG
480 p.From.Reg = v.Args[1].Reg()
481 p.To.Type = obj.TYPE_MEM
482 p.To.Reg = v.Args[0].Reg()
483 ssagen.AddAux(&p.To, v)
484 case ssa.OpRISCV64MOVBstorezero, ssa.OpRISCV64MOVHstorezero, ssa.OpRISCV64MOVWstorezero, ssa.OpRISCV64MOVDstorezero:
485 p := s.Prog(v.Op.Asm())
486 p.From.Type = obj.TYPE_REG
487 p.From.Reg = riscv.REG_ZERO
488 p.To.Type = obj.TYPE_MEM
489 p.To.Reg = v.Args[0].Reg()
490 ssagen.AddAux(&p.To, v)
491 case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
492 p := s.Prog(v.Op.Asm())
493 p.From.Type = obj.TYPE_REG
494 p.From.Reg = v.Args[0].Reg()
495 p.To.Type = obj.TYPE_REG
496 p.To.Reg = v.Reg()
497 case ssa.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter:
498 s.Call(v)
499 case ssa.OpRISCV64CALLtail:
500 s.TailCall(v)
501 case ssa.OpRISCV64LoweredWB:
502 p := s.Prog(obj.ACALL)
503 p.To.Type = obj.TYPE_MEM
504 p.To.Name = obj.NAME_EXTERN
505
506 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
507 case ssa.OpRISCV64LoweredPanicBoundsA, ssa.OpRISCV64LoweredPanicBoundsB, ssa.OpRISCV64LoweredPanicBoundsC:
508 p := s.Prog(obj.ACALL)
509 p.To.Type = obj.TYPE_MEM
510 p.To.Name = obj.NAME_EXTERN
511 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
512 s.UseArgs(16)
513
514 case ssa.OpRISCV64LoweredAtomicLoad8:
515 s.Prog(riscv.AFENCE)
516 p := s.Prog(riscv.AMOVBU)
517 p.From.Type = obj.TYPE_MEM
518 p.From.Reg = v.Args[0].Reg()
519 p.To.Type = obj.TYPE_REG
520 p.To.Reg = v.Reg0()
521 s.Prog(riscv.AFENCE)
522
523 case ssa.OpRISCV64LoweredAtomicLoad32, ssa.OpRISCV64LoweredAtomicLoad64:
524 as := riscv.ALRW
525 if v.Op == ssa.OpRISCV64LoweredAtomicLoad64 {
526 as = riscv.ALRD
527 }
528 p := s.Prog(as)
529 p.From.Type = obj.TYPE_MEM
530 p.From.Reg = v.Args[0].Reg()
531 p.To.Type = obj.TYPE_REG
532 p.To.Reg = v.Reg0()
533
534 case ssa.OpRISCV64LoweredAtomicStore8:
535 s.Prog(riscv.AFENCE)
536 p := s.Prog(riscv.AMOVB)
537 p.From.Type = obj.TYPE_REG
538 p.From.Reg = v.Args[1].Reg()
539 p.To.Type = obj.TYPE_MEM
540 p.To.Reg = v.Args[0].Reg()
541 s.Prog(riscv.AFENCE)
542
543 case ssa.OpRISCV64LoweredAtomicStore32, ssa.OpRISCV64LoweredAtomicStore64:
544 as := riscv.AAMOSWAPW
545 if v.Op == ssa.OpRISCV64LoweredAtomicStore64 {
546 as = riscv.AAMOSWAPD
547 }
548 p := s.Prog(as)
549 p.From.Type = obj.TYPE_REG
550 p.From.Reg = v.Args[1].Reg()
551 p.To.Type = obj.TYPE_MEM
552 p.To.Reg = v.Args[0].Reg()
553 p.RegTo2 = riscv.REG_ZERO
554
555 case ssa.OpRISCV64LoweredAtomicAdd32, ssa.OpRISCV64LoweredAtomicAdd64:
556 as := riscv.AAMOADDW
557 if v.Op == ssa.OpRISCV64LoweredAtomicAdd64 {
558 as = riscv.AAMOADDD
559 }
560 p := s.Prog(as)
561 p.From.Type = obj.TYPE_REG
562 p.From.Reg = v.Args[1].Reg()
563 p.To.Type = obj.TYPE_MEM
564 p.To.Reg = v.Args[0].Reg()
565 p.RegTo2 = riscv.REG_TMP
566
567 p2 := s.Prog(riscv.AADD)
568 p2.From.Type = obj.TYPE_REG
569 p2.From.Reg = riscv.REG_TMP
570 p2.Reg = v.Args[1].Reg()
571 p2.To.Type = obj.TYPE_REG
572 p2.To.Reg = v.Reg0()
573
574 case ssa.OpRISCV64LoweredAtomicExchange32, ssa.OpRISCV64LoweredAtomicExchange64:
575 as := riscv.AAMOSWAPW
576 if v.Op == ssa.OpRISCV64LoweredAtomicExchange64 {
577 as = riscv.AAMOSWAPD
578 }
579 p := s.Prog(as)
580 p.From.Type = obj.TYPE_REG
581 p.From.Reg = v.Args[1].Reg()
582 p.To.Type = obj.TYPE_MEM
583 p.To.Reg = v.Args[0].Reg()
584 p.RegTo2 = v.Reg0()
585
586 case ssa.OpRISCV64LoweredAtomicCas32, ssa.OpRISCV64LoweredAtomicCas64:
587
588
589
590
591
592
593
594 lr := riscv.ALRW
595 sc := riscv.ASCW
596 if v.Op == ssa.OpRISCV64LoweredAtomicCas64 {
597 lr = riscv.ALRD
598 sc = riscv.ASCD
599 }
600
601 r0 := v.Args[0].Reg()
602 r1 := v.Args[1].Reg()
603 r2 := v.Args[2].Reg()
604 out := v.Reg0()
605
606 p := s.Prog(riscv.AMOV)
607 p.From.Type = obj.TYPE_REG
608 p.From.Reg = riscv.REG_ZERO
609 p.To.Type = obj.TYPE_REG
610 p.To.Reg = out
611
612 p1 := s.Prog(lr)
613 p1.From.Type = obj.TYPE_MEM
614 p1.From.Reg = r0
615 p1.To.Type = obj.TYPE_REG
616 p1.To.Reg = riscv.REG_TMP
617
618 p2 := s.Prog(riscv.ABNE)
619 p2.From.Type = obj.TYPE_REG
620 p2.From.Reg = r1
621 p2.Reg = riscv.REG_TMP
622 p2.To.Type = obj.TYPE_BRANCH
623
624 p3 := s.Prog(sc)
625 p3.From.Type = obj.TYPE_REG
626 p3.From.Reg = r2
627 p3.To.Type = obj.TYPE_MEM
628 p3.To.Reg = r0
629 p3.RegTo2 = riscv.REG_TMP
630
631 p4 := s.Prog(riscv.ABNE)
632 p4.From.Type = obj.TYPE_REG
633 p4.From.Reg = riscv.REG_TMP
634 p4.Reg = riscv.REG_ZERO
635 p4.To.Type = obj.TYPE_BRANCH
636 p4.To.SetTarget(p1)
637
638 p5 := s.Prog(riscv.AMOV)
639 p5.From.Type = obj.TYPE_CONST
640 p5.From.Offset = 1
641 p5.To.Type = obj.TYPE_REG
642 p5.To.Reg = out
643
644 p6 := s.Prog(obj.ANOP)
645 p2.To.SetTarget(p6)
646
647 case ssa.OpRISCV64LoweredAtomicAnd32, ssa.OpRISCV64LoweredAtomicOr32:
648 p := s.Prog(v.Op.Asm())
649 p.From.Type = obj.TYPE_REG
650 p.From.Reg = v.Args[1].Reg()
651 p.To.Type = obj.TYPE_MEM
652 p.To.Reg = v.Args[0].Reg()
653 p.RegTo2 = riscv.REG_ZERO
654
655 case ssa.OpRISCV64LoweredZero:
656 mov, sz := largestMove(v.AuxInt)
657
658
659
660
661
662 p := s.Prog(mov)
663 p.From.Type = obj.TYPE_REG
664 p.From.Reg = riscv.REG_ZERO
665 p.To.Type = obj.TYPE_MEM
666 p.To.Reg = v.Args[0].Reg()
667
668 p2 := s.Prog(riscv.AADD)
669 p2.From.Type = obj.TYPE_CONST
670 p2.From.Offset = sz
671 p2.To.Type = obj.TYPE_REG
672 p2.To.Reg = v.Args[0].Reg()
673
674 p3 := s.Prog(riscv.ABGEU)
675 p3.To.Type = obj.TYPE_BRANCH
676 p3.Reg = v.Args[0].Reg()
677 p3.From.Type = obj.TYPE_REG
678 p3.From.Reg = v.Args[1].Reg()
679 p3.To.SetTarget(p)
680
681 case ssa.OpRISCV64LoweredMove:
682 mov, sz := largestMove(v.AuxInt)
683
684
685
686
687
688
689
690 p := s.Prog(mov)
691 p.From.Type = obj.TYPE_MEM
692 p.From.Reg = v.Args[1].Reg()
693 p.To.Type = obj.TYPE_REG
694 p.To.Reg = riscv.REG_T2
695
696 p2 := s.Prog(mov)
697 p2.From.Type = obj.TYPE_REG
698 p2.From.Reg = riscv.REG_T2
699 p2.To.Type = obj.TYPE_MEM
700 p2.To.Reg = v.Args[0].Reg()
701
702 p3 := s.Prog(riscv.AADD)
703 p3.From.Type = obj.TYPE_CONST
704 p3.From.Offset = sz
705 p3.To.Type = obj.TYPE_REG
706 p3.To.Reg = v.Args[0].Reg()
707
708 p4 := s.Prog(riscv.AADD)
709 p4.From.Type = obj.TYPE_CONST
710 p4.From.Offset = sz
711 p4.To.Type = obj.TYPE_REG
712 p4.To.Reg = v.Args[1].Reg()
713
714 p5 := s.Prog(riscv.ABGEU)
715 p5.To.Type = obj.TYPE_BRANCH
716 p5.Reg = v.Args[1].Reg()
717 p5.From.Type = obj.TYPE_REG
718 p5.From.Reg = v.Args[2].Reg()
719 p5.To.SetTarget(p)
720
721 case ssa.OpRISCV64LoweredNilCheck:
722
723
724 p := s.Prog(riscv.AMOVB)
725 p.From.Type = obj.TYPE_MEM
726 p.From.Reg = v.Args[0].Reg()
727 ssagen.AddAux(&p.From, v)
728 p.To.Type = obj.TYPE_REG
729 p.To.Reg = riscv.REG_ZERO
730 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
731 base.WarnfAt(v.Pos, "generated nil check")
732 }
733
734 case ssa.OpRISCV64LoweredGetClosurePtr:
735
736 ssagen.CheckLoweredGetClosurePtr(v)
737
738 case ssa.OpRISCV64LoweredGetCallerSP:
739
740 p := s.Prog(riscv.AMOV)
741 p.From.Type = obj.TYPE_ADDR
742 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
743 p.From.Name = obj.NAME_PARAM
744 p.To.Type = obj.TYPE_REG
745 p.To.Reg = v.Reg()
746
747 case ssa.OpRISCV64LoweredGetCallerPC:
748 p := s.Prog(obj.AGETCALLERPC)
749 p.To.Type = obj.TYPE_REG
750 p.To.Reg = v.Reg()
751
752 case ssa.OpRISCV64DUFFZERO:
753 p := s.Prog(obj.ADUFFZERO)
754 p.To.Type = obj.TYPE_MEM
755 p.To.Name = obj.NAME_EXTERN
756 p.To.Sym = ir.Syms.Duffzero
757 p.To.Offset = v.AuxInt
758
759 case ssa.OpRISCV64DUFFCOPY:
760 p := s.Prog(obj.ADUFFCOPY)
761 p.To.Type = obj.TYPE_MEM
762 p.To.Name = obj.NAME_EXTERN
763 p.To.Sym = ir.Syms.Duffcopy
764 p.To.Offset = v.AuxInt
765
766 case ssa.OpRISCV64LoweredPubBarrier:
767
768 s.Prog(v.Op.Asm())
769
770 case ssa.OpRISCV64LoweredRound32F, ssa.OpRISCV64LoweredRound64F:
771
772
773 case ssa.OpClobber, ssa.OpClobberReg:
774
775
776 default:
777 v.Fatalf("Unhandled op %v", v.Op)
778 }
779 }
780
781 var blockBranch = [...]obj.As{
782 ssa.BlockRISCV64BEQ: riscv.ABEQ,
783 ssa.BlockRISCV64BEQZ: riscv.ABEQZ,
784 ssa.BlockRISCV64BGE: riscv.ABGE,
785 ssa.BlockRISCV64BGEU: riscv.ABGEU,
786 ssa.BlockRISCV64BGEZ: riscv.ABGEZ,
787 ssa.BlockRISCV64BGTZ: riscv.ABGTZ,
788 ssa.BlockRISCV64BLEZ: riscv.ABLEZ,
789 ssa.BlockRISCV64BLT: riscv.ABLT,
790 ssa.BlockRISCV64BLTU: riscv.ABLTU,
791 ssa.BlockRISCV64BLTZ: riscv.ABLTZ,
792 ssa.BlockRISCV64BNE: riscv.ABNE,
793 ssa.BlockRISCV64BNEZ: riscv.ABNEZ,
794 }
795
796 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
797 s.SetPos(b.Pos)
798
799 switch b.Kind {
800 case ssa.BlockDefer:
801
802
803
804 p := s.Prog(riscv.ABNE)
805 p.To.Type = obj.TYPE_BRANCH
806 p.From.Type = obj.TYPE_REG
807 p.From.Reg = riscv.REG_ZERO
808 p.Reg = riscv.REG_A0
809 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
810 if b.Succs[0].Block() != next {
811 p := s.Prog(obj.AJMP)
812 p.To.Type = obj.TYPE_BRANCH
813 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
814 }
815 case ssa.BlockPlain:
816 if b.Succs[0].Block() != next {
817 p := s.Prog(obj.AJMP)
818 p.To.Type = obj.TYPE_BRANCH
819 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
820 }
821 case ssa.BlockExit, ssa.BlockRetJmp:
822 case ssa.BlockRet:
823 s.Prog(obj.ARET)
824 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BNEZ,
825 ssa.BlockRISCV64BLT, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BGEZ,
826 ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
827
828 as := blockBranch[b.Kind]
829 invAs := riscv.InvertBranch(as)
830
831 var p *obj.Prog
832 switch next {
833 case b.Succs[0].Block():
834 p = s.Br(invAs, b.Succs[1].Block())
835 case b.Succs[1].Block():
836 p = s.Br(as, b.Succs[0].Block())
837 default:
838 if b.Likely != ssa.BranchUnlikely {
839 p = s.Br(as, b.Succs[0].Block())
840 s.Br(obj.AJMP, b.Succs[1].Block())
841 } else {
842 p = s.Br(invAs, b.Succs[1].Block())
843 s.Br(obj.AJMP, b.Succs[0].Block())
844 }
845 }
846
847 p.From.Type = obj.TYPE_REG
848 switch b.Kind {
849 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BLT, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
850 if b.NumControls() != 2 {
851 b.Fatalf("Unexpected number of controls (%d != 2): %s", b.NumControls(), b.LongString())
852 }
853 p.From.Reg = b.Controls[0].Reg()
854 p.Reg = b.Controls[1].Reg()
855
856 case ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNEZ, ssa.BlockRISCV64BGEZ, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ:
857 if b.NumControls() != 1 {
858 b.Fatalf("Unexpected number of controls (%d != 1): %s", b.NumControls(), b.LongString())
859 }
860 p.From.Reg = b.Controls[0].Reg()
861 }
862
863 default:
864 b.Fatalf("Unhandled block: %s", b.LongString())
865 }
866 }
867
868 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
869 p := s.Prog(loadByType(t))
870 p.From.Type = obj.TYPE_MEM
871 p.From.Name = obj.NAME_AUTO
872 p.From.Sym = n.Linksym()
873 p.From.Offset = n.FrameOffset() + off
874 p.To.Type = obj.TYPE_REG
875 p.To.Reg = reg
876 return p
877 }
878
879 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
880 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
881 p.To.Name = obj.NAME_PARAM
882 p.To.Sym = n.Linksym()
883 p.Pos = p.Pos.WithNotStmt()
884 return p
885 }
886
View as plain text