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:
423 p := s.Prog(v.Op.Asm())
424 p.From.Type = obj.TYPE_REG
425 p.From.Reg = v.Args[0].Reg()
426 p.To.Type = obj.TYPE_REG
427 p.To.Reg = v.Reg()
428 case ssa.OpRISCV64ADDI, ssa.OpRISCV64ADDIW, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
429 ssa.OpRISCV64SLLI, ssa.OpRISCV64SLLIW, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRAIW,
430 ssa.OpRISCV64SRLI, ssa.OpRISCV64SRLIW, ssa.OpRISCV64SLTI, ssa.OpRISCV64SLTIU,
431 ssa.OpRISCV64RORI, ssa.OpRISCV64RORIW:
432 p := s.Prog(v.Op.Asm())
433 p.From.Type = obj.TYPE_CONST
434 p.From.Offset = v.AuxInt
435 p.Reg = v.Args[0].Reg()
436 p.To.Type = obj.TYPE_REG
437 p.To.Reg = v.Reg()
438 case ssa.OpRISCV64MOVDconst:
439 p := s.Prog(v.Op.Asm())
440 p.From.Type = obj.TYPE_CONST
441 p.From.Offset = v.AuxInt
442 p.To.Type = obj.TYPE_REG
443 p.To.Reg = v.Reg()
444 case ssa.OpRISCV64MOVaddr:
445 p := s.Prog(v.Op.Asm())
446 p.From.Type = obj.TYPE_ADDR
447 p.To.Type = obj.TYPE_REG
448 p.To.Reg = v.Reg()
449
450 var wantreg string
451
452 switch v.Aux.(type) {
453 default:
454 v.Fatalf("aux is of unknown type %T", v.Aux)
455 case *obj.LSym:
456 wantreg = "SB"
457 ssagen.AddAux(&p.From, v)
458 case *ir.Name:
459 wantreg = "SP"
460 ssagen.AddAux(&p.From, v)
461 case nil:
462
463 wantreg = "SP"
464 p.From.Reg = riscv.REG_SP
465 p.From.Offset = v.AuxInt
466 }
467 if reg := v.Args[0].RegName(); reg != wantreg {
468 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
469 }
470 case ssa.OpRISCV64MOVBload, ssa.OpRISCV64MOVHload, ssa.OpRISCV64MOVWload, ssa.OpRISCV64MOVDload,
471 ssa.OpRISCV64MOVBUload, ssa.OpRISCV64MOVHUload, ssa.OpRISCV64MOVWUload,
472 ssa.OpRISCV64FMOVWload, ssa.OpRISCV64FMOVDload:
473 p := s.Prog(v.Op.Asm())
474 p.From.Type = obj.TYPE_MEM
475 p.From.Reg = v.Args[0].Reg()
476 ssagen.AddAux(&p.From, v)
477 p.To.Type = obj.TYPE_REG
478 p.To.Reg = v.Reg()
479 case ssa.OpRISCV64MOVBstore, ssa.OpRISCV64MOVHstore, ssa.OpRISCV64MOVWstore, ssa.OpRISCV64MOVDstore,
480 ssa.OpRISCV64FMOVWstore, ssa.OpRISCV64FMOVDstore:
481 p := s.Prog(v.Op.Asm())
482 p.From.Type = obj.TYPE_REG
483 p.From.Reg = v.Args[1].Reg()
484 p.To.Type = obj.TYPE_MEM
485 p.To.Reg = v.Args[0].Reg()
486 ssagen.AddAux(&p.To, v)
487 case ssa.OpRISCV64MOVBstorezero, ssa.OpRISCV64MOVHstorezero, ssa.OpRISCV64MOVWstorezero, ssa.OpRISCV64MOVDstorezero:
488 p := s.Prog(v.Op.Asm())
489 p.From.Type = obj.TYPE_REG
490 p.From.Reg = riscv.REG_ZERO
491 p.To.Type = obj.TYPE_MEM
492 p.To.Reg = v.Args[0].Reg()
493 ssagen.AddAux(&p.To, v)
494 case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
495 p := s.Prog(v.Op.Asm())
496 p.From.Type = obj.TYPE_REG
497 p.From.Reg = v.Args[0].Reg()
498 p.To.Type = obj.TYPE_REG
499 p.To.Reg = v.Reg()
500 case ssa.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter:
501 s.Call(v)
502 case ssa.OpRISCV64CALLtail:
503 s.TailCall(v)
504 case ssa.OpRISCV64LoweredWB:
505 p := s.Prog(obj.ACALL)
506 p.To.Type = obj.TYPE_MEM
507 p.To.Name = obj.NAME_EXTERN
508
509 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
510 case ssa.OpRISCV64LoweredPanicBoundsA, ssa.OpRISCV64LoweredPanicBoundsB, ssa.OpRISCV64LoweredPanicBoundsC:
511 p := s.Prog(obj.ACALL)
512 p.To.Type = obj.TYPE_MEM
513 p.To.Name = obj.NAME_EXTERN
514 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
515 s.UseArgs(16)
516
517 case ssa.OpRISCV64LoweredAtomicLoad8:
518 s.Prog(riscv.AFENCE)
519 p := s.Prog(riscv.AMOVBU)
520 p.From.Type = obj.TYPE_MEM
521 p.From.Reg = v.Args[0].Reg()
522 p.To.Type = obj.TYPE_REG
523 p.To.Reg = v.Reg0()
524 s.Prog(riscv.AFENCE)
525
526 case ssa.OpRISCV64LoweredAtomicLoad32, ssa.OpRISCV64LoweredAtomicLoad64:
527 as := riscv.ALRW
528 if v.Op == ssa.OpRISCV64LoweredAtomicLoad64 {
529 as = riscv.ALRD
530 }
531 p := s.Prog(as)
532 p.From.Type = obj.TYPE_MEM
533 p.From.Reg = v.Args[0].Reg()
534 p.To.Type = obj.TYPE_REG
535 p.To.Reg = v.Reg0()
536
537 case ssa.OpRISCV64LoweredAtomicStore8:
538 s.Prog(riscv.AFENCE)
539 p := s.Prog(riscv.AMOVB)
540 p.From.Type = obj.TYPE_REG
541 p.From.Reg = v.Args[1].Reg()
542 p.To.Type = obj.TYPE_MEM
543 p.To.Reg = v.Args[0].Reg()
544 s.Prog(riscv.AFENCE)
545
546 case ssa.OpRISCV64LoweredAtomicStore32, ssa.OpRISCV64LoweredAtomicStore64:
547 as := riscv.AAMOSWAPW
548 if v.Op == ssa.OpRISCV64LoweredAtomicStore64 {
549 as = riscv.AAMOSWAPD
550 }
551 p := s.Prog(as)
552 p.From.Type = obj.TYPE_REG
553 p.From.Reg = v.Args[1].Reg()
554 p.To.Type = obj.TYPE_MEM
555 p.To.Reg = v.Args[0].Reg()
556 p.RegTo2 = riscv.REG_ZERO
557
558 case ssa.OpRISCV64LoweredAtomicAdd32, ssa.OpRISCV64LoweredAtomicAdd64:
559 as := riscv.AAMOADDW
560 if v.Op == ssa.OpRISCV64LoweredAtomicAdd64 {
561 as = riscv.AAMOADDD
562 }
563 p := s.Prog(as)
564 p.From.Type = obj.TYPE_REG
565 p.From.Reg = v.Args[1].Reg()
566 p.To.Type = obj.TYPE_MEM
567 p.To.Reg = v.Args[0].Reg()
568 p.RegTo2 = riscv.REG_TMP
569
570 p2 := s.Prog(riscv.AADD)
571 p2.From.Type = obj.TYPE_REG
572 p2.From.Reg = riscv.REG_TMP
573 p2.Reg = v.Args[1].Reg()
574 p2.To.Type = obj.TYPE_REG
575 p2.To.Reg = v.Reg0()
576
577 case ssa.OpRISCV64LoweredAtomicExchange32, ssa.OpRISCV64LoweredAtomicExchange64:
578 as := riscv.AAMOSWAPW
579 if v.Op == ssa.OpRISCV64LoweredAtomicExchange64 {
580 as = riscv.AAMOSWAPD
581 }
582 p := s.Prog(as)
583 p.From.Type = obj.TYPE_REG
584 p.From.Reg = v.Args[1].Reg()
585 p.To.Type = obj.TYPE_MEM
586 p.To.Reg = v.Args[0].Reg()
587 p.RegTo2 = v.Reg0()
588
589 case ssa.OpRISCV64LoweredAtomicCas32, ssa.OpRISCV64LoweredAtomicCas64:
590
591
592
593
594
595
596
597 lr := riscv.ALRW
598 sc := riscv.ASCW
599 if v.Op == ssa.OpRISCV64LoweredAtomicCas64 {
600 lr = riscv.ALRD
601 sc = riscv.ASCD
602 }
603
604 r0 := v.Args[0].Reg()
605 r1 := v.Args[1].Reg()
606 r2 := v.Args[2].Reg()
607 out := v.Reg0()
608
609 p := s.Prog(riscv.AMOV)
610 p.From.Type = obj.TYPE_REG
611 p.From.Reg = riscv.REG_ZERO
612 p.To.Type = obj.TYPE_REG
613 p.To.Reg = out
614
615 p1 := s.Prog(lr)
616 p1.From.Type = obj.TYPE_MEM
617 p1.From.Reg = r0
618 p1.To.Type = obj.TYPE_REG
619 p1.To.Reg = riscv.REG_TMP
620
621 p2 := s.Prog(riscv.ABNE)
622 p2.From.Type = obj.TYPE_REG
623 p2.From.Reg = r1
624 p2.Reg = riscv.REG_TMP
625 p2.To.Type = obj.TYPE_BRANCH
626
627 p3 := s.Prog(sc)
628 p3.From.Type = obj.TYPE_REG
629 p3.From.Reg = r2
630 p3.To.Type = obj.TYPE_MEM
631 p3.To.Reg = r0
632 p3.RegTo2 = riscv.REG_TMP
633
634 p4 := s.Prog(riscv.ABNE)
635 p4.From.Type = obj.TYPE_REG
636 p4.From.Reg = riscv.REG_TMP
637 p4.Reg = riscv.REG_ZERO
638 p4.To.Type = obj.TYPE_BRANCH
639 p4.To.SetTarget(p1)
640
641 p5 := s.Prog(riscv.AMOV)
642 p5.From.Type = obj.TYPE_CONST
643 p5.From.Offset = 1
644 p5.To.Type = obj.TYPE_REG
645 p5.To.Reg = out
646
647 p6 := s.Prog(obj.ANOP)
648 p2.To.SetTarget(p6)
649
650 case ssa.OpRISCV64LoweredAtomicAnd32, ssa.OpRISCV64LoweredAtomicOr32:
651 p := s.Prog(v.Op.Asm())
652 p.From.Type = obj.TYPE_REG
653 p.From.Reg = v.Args[1].Reg()
654 p.To.Type = obj.TYPE_MEM
655 p.To.Reg = v.Args[0].Reg()
656 p.RegTo2 = riscv.REG_ZERO
657
658 case ssa.OpRISCV64LoweredZero:
659 mov, sz := largestMove(v.AuxInt)
660
661
662
663
664
665 p := s.Prog(mov)
666 p.From.Type = obj.TYPE_REG
667 p.From.Reg = riscv.REG_ZERO
668 p.To.Type = obj.TYPE_MEM
669 p.To.Reg = v.Args[0].Reg()
670
671 p2 := s.Prog(riscv.AADD)
672 p2.From.Type = obj.TYPE_CONST
673 p2.From.Offset = sz
674 p2.To.Type = obj.TYPE_REG
675 p2.To.Reg = v.Args[0].Reg()
676
677 p3 := s.Prog(riscv.ABGEU)
678 p3.To.Type = obj.TYPE_BRANCH
679 p3.Reg = v.Args[0].Reg()
680 p3.From.Type = obj.TYPE_REG
681 p3.From.Reg = v.Args[1].Reg()
682 p3.To.SetTarget(p)
683
684 case ssa.OpRISCV64LoweredMove:
685 mov, sz := largestMove(v.AuxInt)
686
687
688
689
690
691
692
693 p := s.Prog(mov)
694 p.From.Type = obj.TYPE_MEM
695 p.From.Reg = v.Args[1].Reg()
696 p.To.Type = obj.TYPE_REG
697 p.To.Reg = riscv.REG_T2
698
699 p2 := s.Prog(mov)
700 p2.From.Type = obj.TYPE_REG
701 p2.From.Reg = riscv.REG_T2
702 p2.To.Type = obj.TYPE_MEM
703 p2.To.Reg = v.Args[0].Reg()
704
705 p3 := s.Prog(riscv.AADD)
706 p3.From.Type = obj.TYPE_CONST
707 p3.From.Offset = sz
708 p3.To.Type = obj.TYPE_REG
709 p3.To.Reg = v.Args[0].Reg()
710
711 p4 := s.Prog(riscv.AADD)
712 p4.From.Type = obj.TYPE_CONST
713 p4.From.Offset = sz
714 p4.To.Type = obj.TYPE_REG
715 p4.To.Reg = v.Args[1].Reg()
716
717 p5 := s.Prog(riscv.ABGEU)
718 p5.To.Type = obj.TYPE_BRANCH
719 p5.Reg = v.Args[1].Reg()
720 p5.From.Type = obj.TYPE_REG
721 p5.From.Reg = v.Args[2].Reg()
722 p5.To.SetTarget(p)
723
724 case ssa.OpRISCV64LoweredNilCheck:
725
726 p := s.Prog(riscv.AMOVB)
727 p.From.Type = obj.TYPE_MEM
728 p.From.Reg = v.Args[0].Reg()
729 ssagen.AddAux(&p.From, v)
730 p.To.Type = obj.TYPE_REG
731 p.To.Reg = riscv.REG_ZERO
732 if logopt.Enabled() {
733 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
734 }
735 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
736 base.WarnfAt(v.Pos, "generated nil check")
737 }
738
739 case ssa.OpRISCV64LoweredGetClosurePtr:
740
741 ssagen.CheckLoweredGetClosurePtr(v)
742
743 case ssa.OpRISCV64LoweredGetCallerSP:
744
745 p := s.Prog(riscv.AMOV)
746 p.From.Type = obj.TYPE_ADDR
747 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
748 p.From.Name = obj.NAME_PARAM
749 p.To.Type = obj.TYPE_REG
750 p.To.Reg = v.Reg()
751
752 case ssa.OpRISCV64LoweredGetCallerPC:
753 p := s.Prog(obj.AGETCALLERPC)
754 p.To.Type = obj.TYPE_REG
755 p.To.Reg = v.Reg()
756
757 case ssa.OpRISCV64DUFFZERO:
758 p := s.Prog(obj.ADUFFZERO)
759 p.To.Type = obj.TYPE_MEM
760 p.To.Name = obj.NAME_EXTERN
761 p.To.Sym = ir.Syms.Duffzero
762 p.To.Offset = v.AuxInt
763
764 case ssa.OpRISCV64DUFFCOPY:
765 p := s.Prog(obj.ADUFFCOPY)
766 p.To.Type = obj.TYPE_MEM
767 p.To.Name = obj.NAME_EXTERN
768 p.To.Sym = ir.Syms.Duffcopy
769 p.To.Offset = v.AuxInt
770
771 case ssa.OpRISCV64LoweredPubBarrier:
772
773 s.Prog(v.Op.Asm())
774
775 case ssa.OpRISCV64LoweredRound32F, ssa.OpRISCV64LoweredRound64F:
776
777
778 case ssa.OpClobber, ssa.OpClobberReg:
779
780
781 default:
782 v.Fatalf("Unhandled op %v", v.Op)
783 }
784 }
785
786 var blockBranch = [...]obj.As{
787 ssa.BlockRISCV64BEQ: riscv.ABEQ,
788 ssa.BlockRISCV64BEQZ: riscv.ABEQZ,
789 ssa.BlockRISCV64BGE: riscv.ABGE,
790 ssa.BlockRISCV64BGEU: riscv.ABGEU,
791 ssa.BlockRISCV64BGEZ: riscv.ABGEZ,
792 ssa.BlockRISCV64BGTZ: riscv.ABGTZ,
793 ssa.BlockRISCV64BLEZ: riscv.ABLEZ,
794 ssa.BlockRISCV64BLT: riscv.ABLT,
795 ssa.BlockRISCV64BLTU: riscv.ABLTU,
796 ssa.BlockRISCV64BLTZ: riscv.ABLTZ,
797 ssa.BlockRISCV64BNE: riscv.ABNE,
798 ssa.BlockRISCV64BNEZ: riscv.ABNEZ,
799 }
800
801 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
802 s.SetPos(b.Pos)
803
804 switch b.Kind {
805 case ssa.BlockDefer:
806
807
808
809 p := s.Prog(riscv.ABNE)
810 p.To.Type = obj.TYPE_BRANCH
811 p.From.Type = obj.TYPE_REG
812 p.From.Reg = riscv.REG_ZERO
813 p.Reg = riscv.REG_A0
814 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
815 if b.Succs[0].Block() != next {
816 p := s.Prog(obj.AJMP)
817 p.To.Type = obj.TYPE_BRANCH
818 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
819 }
820 case ssa.BlockPlain:
821 if b.Succs[0].Block() != next {
822 p := s.Prog(obj.AJMP)
823 p.To.Type = obj.TYPE_BRANCH
824 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
825 }
826 case ssa.BlockExit, ssa.BlockRetJmp:
827 case ssa.BlockRet:
828 s.Prog(obj.ARET)
829 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BNEZ,
830 ssa.BlockRISCV64BLT, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BGEZ,
831 ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
832
833 as := blockBranch[b.Kind]
834 invAs := riscv.InvertBranch(as)
835
836 var p *obj.Prog
837 switch next {
838 case b.Succs[0].Block():
839 p = s.Br(invAs, b.Succs[1].Block())
840 case b.Succs[1].Block():
841 p = s.Br(as, b.Succs[0].Block())
842 default:
843 if b.Likely != ssa.BranchUnlikely {
844 p = s.Br(as, b.Succs[0].Block())
845 s.Br(obj.AJMP, b.Succs[1].Block())
846 } else {
847 p = s.Br(invAs, b.Succs[1].Block())
848 s.Br(obj.AJMP, b.Succs[0].Block())
849 }
850 }
851
852 p.From.Type = obj.TYPE_REG
853 switch b.Kind {
854 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BLT, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
855 if b.NumControls() != 2 {
856 b.Fatalf("Unexpected number of controls (%d != 2): %s", b.NumControls(), b.LongString())
857 }
858 p.From.Reg = b.Controls[0].Reg()
859 p.Reg = b.Controls[1].Reg()
860
861 case ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNEZ, ssa.BlockRISCV64BGEZ, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ:
862 if b.NumControls() != 1 {
863 b.Fatalf("Unexpected number of controls (%d != 1): %s", b.NumControls(), b.LongString())
864 }
865 p.From.Reg = b.Controls[0].Reg()
866 }
867
868 default:
869 b.Fatalf("Unhandled block: %s", b.LongString())
870 }
871 }
872
873 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
874 p := s.Prog(loadByType(t))
875 p.From.Type = obj.TYPE_MEM
876 p.From.Name = obj.NAME_AUTO
877 p.From.Sym = n.Linksym()
878 p.From.Offset = n.FrameOffset() + off
879 p.To.Type = obj.TYPE_REG
880 p.To.Reg = reg
881 return p
882 }
883
884 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
885 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
886 p.To.Name = obj.NAME_PARAM
887 p.To.Sym = n.Linksym()
888 p.Pos = p.Pos.WithNotStmt()
889 return p
890 }
891
View as plain text