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