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.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.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS,
287 ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES,
288 ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD,
289 ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED,
290 ssa.OpRISCV64FSGNJD:
291 r := v.Reg()
292 r1 := v.Args[0].Reg()
293 r2 := v.Args[1].Reg()
294 p := s.Prog(v.Op.Asm())
295 p.From.Type = obj.TYPE_REG
296 p.From.Reg = r2
297 p.Reg = r1
298 p.To.Type = obj.TYPE_REG
299 p.To.Reg = r
300 case ssa.OpRISCV64LoweredMuluhilo:
301 r0 := v.Args[0].Reg()
302 r1 := v.Args[1].Reg()
303 p := s.Prog(riscv.AMULHU)
304 p.From.Type = obj.TYPE_REG
305 p.From.Reg = r1
306 p.Reg = r0
307 p.To.Type = obj.TYPE_REG
308 p.To.Reg = v.Reg0()
309 p1 := s.Prog(riscv.AMUL)
310 p1.From.Type = obj.TYPE_REG
311 p1.From.Reg = r1
312 p1.Reg = r0
313 p1.To.Type = obj.TYPE_REG
314 p1.To.Reg = v.Reg1()
315 case ssa.OpRISCV64LoweredMuluover:
316 r0 := v.Args[0].Reg()
317 r1 := v.Args[1].Reg()
318 p := s.Prog(riscv.AMULHU)
319 p.From.Type = obj.TYPE_REG
320 p.From.Reg = r1
321 p.Reg = r0
322 p.To.Type = obj.TYPE_REG
323 p.To.Reg = v.Reg1()
324 p1 := s.Prog(riscv.AMUL)
325 p1.From.Type = obj.TYPE_REG
326 p1.From.Reg = r1
327 p1.Reg = r0
328 p1.To.Type = obj.TYPE_REG
329 p1.To.Reg = v.Reg0()
330 p2 := s.Prog(riscv.ASNEZ)
331 p2.From.Type = obj.TYPE_REG
332 p2.From.Reg = v.Reg1()
333 p2.To.Type = obj.TYPE_REG
334 p2.To.Reg = v.Reg1()
335 case ssa.OpRISCV64FMADDD, ssa.OpRISCV64FMSUBD, ssa.OpRISCV64FNMADDD, ssa.OpRISCV64FNMSUBD,
336 ssa.OpRISCV64FMADDS, ssa.OpRISCV64FMSUBS, ssa.OpRISCV64FNMADDS, ssa.OpRISCV64FNMSUBS:
337 r := v.Reg()
338 r1 := v.Args[0].Reg()
339 r2 := v.Args[1].Reg()
340 r3 := v.Args[2].Reg()
341 p := s.Prog(v.Op.Asm())
342 p.From.Type = obj.TYPE_REG
343 p.From.Reg = r2
344 p.Reg = r1
345 p.AddRestSource(obj.Addr{Type: obj.TYPE_REG, Reg: r3})
346 p.To.Type = obj.TYPE_REG
347 p.To.Reg = r
348 case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FABSD, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
349 ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX,
350 ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
351 ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD,
352 ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW:
353 p := s.Prog(v.Op.Asm())
354 p.From.Type = obj.TYPE_REG
355 p.From.Reg = v.Args[0].Reg()
356 p.To.Type = obj.TYPE_REG
357 p.To.Reg = v.Reg()
358 case ssa.OpRISCV64ADDI, ssa.OpRISCV64ADDIW, ssa.OpRISCV64XORI, ssa.OpRISCV64ORI, ssa.OpRISCV64ANDI,
359 ssa.OpRISCV64SLLI, ssa.OpRISCV64SRAI, ssa.OpRISCV64SRAIW, ssa.OpRISCV64SRLI, ssa.OpRISCV64SRLIW, ssa.OpRISCV64SLTI,
360 ssa.OpRISCV64SLTIU:
361 p := s.Prog(v.Op.Asm())
362 p.From.Type = obj.TYPE_CONST
363 p.From.Offset = v.AuxInt
364 p.Reg = v.Args[0].Reg()
365 p.To.Type = obj.TYPE_REG
366 p.To.Reg = v.Reg()
367 case ssa.OpRISCV64MOVDconst:
368 p := s.Prog(v.Op.Asm())
369 p.From.Type = obj.TYPE_CONST
370 p.From.Offset = v.AuxInt
371 p.To.Type = obj.TYPE_REG
372 p.To.Reg = v.Reg()
373 case ssa.OpRISCV64MOVaddr:
374 p := s.Prog(v.Op.Asm())
375 p.From.Type = obj.TYPE_ADDR
376 p.To.Type = obj.TYPE_REG
377 p.To.Reg = v.Reg()
378
379 var wantreg string
380
381 switch v.Aux.(type) {
382 default:
383 v.Fatalf("aux is of unknown type %T", v.Aux)
384 case *obj.LSym:
385 wantreg = "SB"
386 ssagen.AddAux(&p.From, v)
387 case *ir.Name:
388 wantreg = "SP"
389 ssagen.AddAux(&p.From, v)
390 case nil:
391
392 wantreg = "SP"
393 p.From.Reg = riscv.REG_SP
394 p.From.Offset = v.AuxInt
395 }
396 if reg := v.Args[0].RegName(); reg != wantreg {
397 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
398 }
399 case ssa.OpRISCV64MOVBload, ssa.OpRISCV64MOVHload, ssa.OpRISCV64MOVWload, ssa.OpRISCV64MOVDload,
400 ssa.OpRISCV64MOVBUload, ssa.OpRISCV64MOVHUload, ssa.OpRISCV64MOVWUload,
401 ssa.OpRISCV64FMOVWload, ssa.OpRISCV64FMOVDload:
402 p := s.Prog(v.Op.Asm())
403 p.From.Type = obj.TYPE_MEM
404 p.From.Reg = v.Args[0].Reg()
405 ssagen.AddAux(&p.From, v)
406 p.To.Type = obj.TYPE_REG
407 p.To.Reg = v.Reg()
408 case ssa.OpRISCV64MOVBstore, ssa.OpRISCV64MOVHstore, ssa.OpRISCV64MOVWstore, ssa.OpRISCV64MOVDstore,
409 ssa.OpRISCV64FMOVWstore, ssa.OpRISCV64FMOVDstore:
410 p := s.Prog(v.Op.Asm())
411 p.From.Type = obj.TYPE_REG
412 p.From.Reg = v.Args[1].Reg()
413 p.To.Type = obj.TYPE_MEM
414 p.To.Reg = v.Args[0].Reg()
415 ssagen.AddAux(&p.To, v)
416 case ssa.OpRISCV64MOVBstorezero, ssa.OpRISCV64MOVHstorezero, ssa.OpRISCV64MOVWstorezero, ssa.OpRISCV64MOVDstorezero:
417 p := s.Prog(v.Op.Asm())
418 p.From.Type = obj.TYPE_REG
419 p.From.Reg = riscv.REG_ZERO
420 p.To.Type = obj.TYPE_MEM
421 p.To.Reg = v.Args[0].Reg()
422 ssagen.AddAux(&p.To, v)
423 case ssa.OpRISCV64SEQZ, ssa.OpRISCV64SNEZ:
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.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter:
430 s.Call(v)
431 case ssa.OpRISCV64CALLtail:
432 s.TailCall(v)
433 case ssa.OpRISCV64LoweredWB:
434 p := s.Prog(obj.ACALL)
435 p.To.Type = obj.TYPE_MEM
436 p.To.Name = obj.NAME_EXTERN
437
438 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
439 case ssa.OpRISCV64LoweredPanicBoundsA, ssa.OpRISCV64LoweredPanicBoundsB, ssa.OpRISCV64LoweredPanicBoundsC:
440 p := s.Prog(obj.ACALL)
441 p.To.Type = obj.TYPE_MEM
442 p.To.Name = obj.NAME_EXTERN
443 p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
444 s.UseArgs(16)
445
446 case ssa.OpRISCV64LoweredAtomicLoad8:
447 s.Prog(riscv.AFENCE)
448 p := s.Prog(riscv.AMOVBU)
449 p.From.Type = obj.TYPE_MEM
450 p.From.Reg = v.Args[0].Reg()
451 p.To.Type = obj.TYPE_REG
452 p.To.Reg = v.Reg0()
453 s.Prog(riscv.AFENCE)
454
455 case ssa.OpRISCV64LoweredAtomicLoad32, ssa.OpRISCV64LoweredAtomicLoad64:
456 as := riscv.ALRW
457 if v.Op == ssa.OpRISCV64LoweredAtomicLoad64 {
458 as = riscv.ALRD
459 }
460 p := s.Prog(as)
461 p.From.Type = obj.TYPE_MEM
462 p.From.Reg = v.Args[0].Reg()
463 p.To.Type = obj.TYPE_REG
464 p.To.Reg = v.Reg0()
465
466 case ssa.OpRISCV64LoweredAtomicStore8:
467 s.Prog(riscv.AFENCE)
468 p := s.Prog(riscv.AMOVB)
469 p.From.Type = obj.TYPE_REG
470 p.From.Reg = v.Args[1].Reg()
471 p.To.Type = obj.TYPE_MEM
472 p.To.Reg = v.Args[0].Reg()
473 s.Prog(riscv.AFENCE)
474
475 case ssa.OpRISCV64LoweredAtomicStore32, ssa.OpRISCV64LoweredAtomicStore64:
476 as := riscv.AAMOSWAPW
477 if v.Op == ssa.OpRISCV64LoweredAtomicStore64 {
478 as = riscv.AAMOSWAPD
479 }
480 p := s.Prog(as)
481 p.From.Type = obj.TYPE_REG
482 p.From.Reg = v.Args[1].Reg()
483 p.To.Type = obj.TYPE_MEM
484 p.To.Reg = v.Args[0].Reg()
485 p.RegTo2 = riscv.REG_ZERO
486
487 case ssa.OpRISCV64LoweredAtomicAdd32, ssa.OpRISCV64LoweredAtomicAdd64:
488 as := riscv.AAMOADDW
489 if v.Op == ssa.OpRISCV64LoweredAtomicAdd64 {
490 as = riscv.AAMOADDD
491 }
492 p := s.Prog(as)
493 p.From.Type = obj.TYPE_REG
494 p.From.Reg = v.Args[1].Reg()
495 p.To.Type = obj.TYPE_MEM
496 p.To.Reg = v.Args[0].Reg()
497 p.RegTo2 = riscv.REG_TMP
498
499 p2 := s.Prog(riscv.AADD)
500 p2.From.Type = obj.TYPE_REG
501 p2.From.Reg = riscv.REG_TMP
502 p2.Reg = v.Args[1].Reg()
503 p2.To.Type = obj.TYPE_REG
504 p2.To.Reg = v.Reg0()
505
506 case ssa.OpRISCV64LoweredAtomicExchange32, ssa.OpRISCV64LoweredAtomicExchange64:
507 as := riscv.AAMOSWAPW
508 if v.Op == ssa.OpRISCV64LoweredAtomicExchange64 {
509 as = riscv.AAMOSWAPD
510 }
511 p := s.Prog(as)
512 p.From.Type = obj.TYPE_REG
513 p.From.Reg = v.Args[1].Reg()
514 p.To.Type = obj.TYPE_MEM
515 p.To.Reg = v.Args[0].Reg()
516 p.RegTo2 = v.Reg0()
517
518 case ssa.OpRISCV64LoweredAtomicCas32, ssa.OpRISCV64LoweredAtomicCas64:
519
520
521
522
523
524
525
526 lr := riscv.ALRW
527 sc := riscv.ASCW
528 if v.Op == ssa.OpRISCV64LoweredAtomicCas64 {
529 lr = riscv.ALRD
530 sc = riscv.ASCD
531 }
532
533 r0 := v.Args[0].Reg()
534 r1 := v.Args[1].Reg()
535 r2 := v.Args[2].Reg()
536 out := v.Reg0()
537
538 p := s.Prog(riscv.AMOV)
539 p.From.Type = obj.TYPE_REG
540 p.From.Reg = riscv.REG_ZERO
541 p.To.Type = obj.TYPE_REG
542 p.To.Reg = out
543
544 p1 := s.Prog(lr)
545 p1.From.Type = obj.TYPE_MEM
546 p1.From.Reg = r0
547 p1.To.Type = obj.TYPE_REG
548 p1.To.Reg = riscv.REG_TMP
549
550 p2 := s.Prog(riscv.ABNE)
551 p2.From.Type = obj.TYPE_REG
552 p2.From.Reg = r1
553 p2.Reg = riscv.REG_TMP
554 p2.To.Type = obj.TYPE_BRANCH
555
556 p3 := s.Prog(sc)
557 p3.From.Type = obj.TYPE_REG
558 p3.From.Reg = r2
559 p3.To.Type = obj.TYPE_MEM
560 p3.To.Reg = r0
561 p3.RegTo2 = riscv.REG_TMP
562
563 p4 := s.Prog(riscv.ABNE)
564 p4.From.Type = obj.TYPE_REG
565 p4.From.Reg = riscv.REG_TMP
566 p4.Reg = riscv.REG_ZERO
567 p4.To.Type = obj.TYPE_BRANCH
568 p4.To.SetTarget(p1)
569
570 p5 := s.Prog(riscv.AMOV)
571 p5.From.Type = obj.TYPE_CONST
572 p5.From.Offset = 1
573 p5.To.Type = obj.TYPE_REG
574 p5.To.Reg = out
575
576 p6 := s.Prog(obj.ANOP)
577 p2.To.SetTarget(p6)
578
579 case ssa.OpRISCV64LoweredAtomicAnd32, ssa.OpRISCV64LoweredAtomicOr32:
580 p := s.Prog(v.Op.Asm())
581 p.From.Type = obj.TYPE_REG
582 p.From.Reg = v.Args[1].Reg()
583 p.To.Type = obj.TYPE_MEM
584 p.To.Reg = v.Args[0].Reg()
585 p.RegTo2 = riscv.REG_ZERO
586
587 case ssa.OpRISCV64LoweredZero:
588 mov, sz := largestMove(v.AuxInt)
589
590
591
592
593
594 p := s.Prog(mov)
595 p.From.Type = obj.TYPE_REG
596 p.From.Reg = riscv.REG_ZERO
597 p.To.Type = obj.TYPE_MEM
598 p.To.Reg = v.Args[0].Reg()
599
600 p2 := s.Prog(riscv.AADD)
601 p2.From.Type = obj.TYPE_CONST
602 p2.From.Offset = sz
603 p2.To.Type = obj.TYPE_REG
604 p2.To.Reg = v.Args[0].Reg()
605
606 p3 := s.Prog(riscv.ABGEU)
607 p3.To.Type = obj.TYPE_BRANCH
608 p3.Reg = v.Args[0].Reg()
609 p3.From.Type = obj.TYPE_REG
610 p3.From.Reg = v.Args[1].Reg()
611 p3.To.SetTarget(p)
612
613 case ssa.OpRISCV64LoweredMove:
614 mov, sz := largestMove(v.AuxInt)
615
616
617
618
619
620
621
622 p := s.Prog(mov)
623 p.From.Type = obj.TYPE_MEM
624 p.From.Reg = v.Args[1].Reg()
625 p.To.Type = obj.TYPE_REG
626 p.To.Reg = riscv.REG_T2
627
628 p2 := s.Prog(mov)
629 p2.From.Type = obj.TYPE_REG
630 p2.From.Reg = riscv.REG_T2
631 p2.To.Type = obj.TYPE_MEM
632 p2.To.Reg = v.Args[0].Reg()
633
634 p3 := s.Prog(riscv.AADD)
635 p3.From.Type = obj.TYPE_CONST
636 p3.From.Offset = sz
637 p3.To.Type = obj.TYPE_REG
638 p3.To.Reg = v.Args[0].Reg()
639
640 p4 := s.Prog(riscv.AADD)
641 p4.From.Type = obj.TYPE_CONST
642 p4.From.Offset = sz
643 p4.To.Type = obj.TYPE_REG
644 p4.To.Reg = v.Args[1].Reg()
645
646 p5 := s.Prog(riscv.ABGEU)
647 p5.To.Type = obj.TYPE_BRANCH
648 p5.Reg = v.Args[1].Reg()
649 p5.From.Type = obj.TYPE_REG
650 p5.From.Reg = v.Args[2].Reg()
651 p5.To.SetTarget(p)
652
653 case ssa.OpRISCV64LoweredNilCheck:
654
655
656 p := s.Prog(riscv.AMOVB)
657 p.From.Type = obj.TYPE_MEM
658 p.From.Reg = v.Args[0].Reg()
659 ssagen.AddAux(&p.From, v)
660 p.To.Type = obj.TYPE_REG
661 p.To.Reg = riscv.REG_ZERO
662 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
663 base.WarnfAt(v.Pos, "generated nil check")
664 }
665
666 case ssa.OpRISCV64LoweredGetClosurePtr:
667
668 ssagen.CheckLoweredGetClosurePtr(v)
669
670 case ssa.OpRISCV64LoweredGetCallerSP:
671
672 p := s.Prog(riscv.AMOV)
673 p.From.Type = obj.TYPE_ADDR
674 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
675 p.From.Name = obj.NAME_PARAM
676 p.To.Type = obj.TYPE_REG
677 p.To.Reg = v.Reg()
678
679 case ssa.OpRISCV64LoweredGetCallerPC:
680 p := s.Prog(obj.AGETCALLERPC)
681 p.To.Type = obj.TYPE_REG
682 p.To.Reg = v.Reg()
683
684 case ssa.OpRISCV64DUFFZERO:
685 p := s.Prog(obj.ADUFFZERO)
686 p.To.Type = obj.TYPE_MEM
687 p.To.Name = obj.NAME_EXTERN
688 p.To.Sym = ir.Syms.Duffzero
689 p.To.Offset = v.AuxInt
690
691 case ssa.OpRISCV64DUFFCOPY:
692 p := s.Prog(obj.ADUFFCOPY)
693 p.To.Type = obj.TYPE_MEM
694 p.To.Name = obj.NAME_EXTERN
695 p.To.Sym = ir.Syms.Duffcopy
696 p.To.Offset = v.AuxInt
697
698 case ssa.OpRISCV64LoweredPubBarrier:
699
700 s.Prog(v.Op.Asm())
701
702 case ssa.OpRISCV64LoweredRound32F, ssa.OpRISCV64LoweredRound64F:
703
704
705 case ssa.OpClobber, ssa.OpClobberReg:
706
707
708 default:
709 v.Fatalf("Unhandled op %v", v.Op)
710 }
711 }
712
713 var blockBranch = [...]obj.As{
714 ssa.BlockRISCV64BEQ: riscv.ABEQ,
715 ssa.BlockRISCV64BEQZ: riscv.ABEQZ,
716 ssa.BlockRISCV64BGE: riscv.ABGE,
717 ssa.BlockRISCV64BGEU: riscv.ABGEU,
718 ssa.BlockRISCV64BGEZ: riscv.ABGEZ,
719 ssa.BlockRISCV64BGTZ: riscv.ABGTZ,
720 ssa.BlockRISCV64BLEZ: riscv.ABLEZ,
721 ssa.BlockRISCV64BLT: riscv.ABLT,
722 ssa.BlockRISCV64BLTU: riscv.ABLTU,
723 ssa.BlockRISCV64BLTZ: riscv.ABLTZ,
724 ssa.BlockRISCV64BNE: riscv.ABNE,
725 ssa.BlockRISCV64BNEZ: riscv.ABNEZ,
726 }
727
728 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
729 s.SetPos(b.Pos)
730
731 switch b.Kind {
732 case ssa.BlockDefer:
733
734
735
736 p := s.Prog(riscv.ABNE)
737 p.To.Type = obj.TYPE_BRANCH
738 p.From.Type = obj.TYPE_REG
739 p.From.Reg = riscv.REG_ZERO
740 p.Reg = riscv.REG_A0
741 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[1].Block()})
742 if b.Succs[0].Block() != next {
743 p := s.Prog(obj.AJMP)
744 p.To.Type = obj.TYPE_BRANCH
745 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
746 }
747 case ssa.BlockPlain:
748 if b.Succs[0].Block() != next {
749 p := s.Prog(obj.AJMP)
750 p.To.Type = obj.TYPE_BRANCH
751 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
752 }
753 case ssa.BlockExit, ssa.BlockRetJmp:
754 case ssa.BlockRet:
755 s.Prog(obj.ARET)
756 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BNEZ,
757 ssa.BlockRISCV64BLT, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BGEZ,
758 ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
759
760 as := blockBranch[b.Kind]
761 invAs := riscv.InvertBranch(as)
762
763 var p *obj.Prog
764 switch next {
765 case b.Succs[0].Block():
766 p = s.Br(invAs, b.Succs[1].Block())
767 case b.Succs[1].Block():
768 p = s.Br(as, b.Succs[0].Block())
769 default:
770 if b.Likely != ssa.BranchUnlikely {
771 p = s.Br(as, b.Succs[0].Block())
772 s.Br(obj.AJMP, b.Succs[1].Block())
773 } else {
774 p = s.Br(invAs, b.Succs[1].Block())
775 s.Br(obj.AJMP, b.Succs[0].Block())
776 }
777 }
778
779 p.From.Type = obj.TYPE_REG
780 switch b.Kind {
781 case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BLT, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU:
782 if b.NumControls() != 2 {
783 b.Fatalf("Unexpected number of controls (%d != 2): %s", b.NumControls(), b.LongString())
784 }
785 p.From.Reg = b.Controls[0].Reg()
786 p.Reg = b.Controls[1].Reg()
787
788 case ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNEZ, ssa.BlockRISCV64BGEZ, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ:
789 if b.NumControls() != 1 {
790 b.Fatalf("Unexpected number of controls (%d != 1): %s", b.NumControls(), b.LongString())
791 }
792 p.From.Reg = b.Controls[0].Reg()
793 }
794
795 default:
796 b.Fatalf("Unhandled block: %s", b.LongString())
797 }
798 }
799
800 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
801 p := s.Prog(loadByType(t))
802 p.From.Type = obj.TYPE_MEM
803 p.From.Name = obj.NAME_AUTO
804 p.From.Sym = n.Linksym()
805 p.From.Offset = n.FrameOffset() + off
806 p.To.Type = obj.TYPE_REG
807 p.To.Reg = reg
808 return p
809 }
810
811 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
812 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
813 p.To.Name = obj.NAME_PARAM
814 p.To.Sym = n.Linksym()
815 p.Pos = p.Pos.WithNotStmt()
816 return p
817 }
818
View as plain text