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/ssa/block"
14 "cmd/compile/internal/ssa/ssaop"
15 "cmd/compile/internal/ssagen"
16 "cmd/compile/internal/types"
17 "cmd/internal/obj"
18 "cmd/internal/obj/riscv"
19 "internal/abi"
20 "internal/buildcfg"
21 )
22
23
24 var ssaRegToReg = []int16{
25 riscv.REG_X0,
26
27 riscv.REG_X2,
28 riscv.REG_X3,
29 riscv.REG_X4,
30 riscv.REG_X5,
31 riscv.REG_X6,
32 riscv.REG_X7,
33 riscv.REG_X8,
34 riscv.REG_X9,
35 riscv.REG_X10,
36 riscv.REG_X11,
37 riscv.REG_X12,
38 riscv.REG_X13,
39 riscv.REG_X14,
40 riscv.REG_X15,
41 riscv.REG_X16,
42 riscv.REG_X17,
43 riscv.REG_X18,
44 riscv.REG_X19,
45 riscv.REG_X20,
46 riscv.REG_X21,
47 riscv.REG_X22,
48 riscv.REG_X23,
49 riscv.REG_X24,
50 riscv.REG_X25,
51 riscv.REG_X26,
52 riscv.REG_X27,
53 riscv.REG_X28,
54 riscv.REG_X29,
55 riscv.REG_X30,
56 riscv.REG_X31,
57 riscv.REG_F0,
58 riscv.REG_F1,
59 riscv.REG_F2,
60 riscv.REG_F3,
61 riscv.REG_F4,
62 riscv.REG_F5,
63 riscv.REG_F6,
64 riscv.REG_F7,
65 riscv.REG_F8,
66 riscv.REG_F9,
67 riscv.REG_F10,
68 riscv.REG_F11,
69 riscv.REG_F12,
70 riscv.REG_F13,
71 riscv.REG_F14,
72 riscv.REG_F15,
73 riscv.REG_F16,
74 riscv.REG_F17,
75 riscv.REG_F18,
76 riscv.REG_F19,
77 riscv.REG_F20,
78 riscv.REG_F21,
79 riscv.REG_F22,
80 riscv.REG_F23,
81 riscv.REG_F24,
82 riscv.REG_F25,
83 riscv.REG_F26,
84 riscv.REG_F27,
85 riscv.REG_F28,
86 riscv.REG_F29,
87 riscv.REG_F30,
88 riscv.REG_F31,
89 0,
90 }
91
92 func loadByType(t *types.Type) obj.As {
93 width := t.Size()
94
95 if t.IsFloat() {
96 switch width {
97 case 4:
98 return riscv.AMOVF
99 case 8:
100 return riscv.AMOVD
101 default:
102 base.Fatalf("unknown float width for load %d in type %v", width, t)
103 return 0
104 }
105 }
106
107 switch width {
108 case 1:
109 if t.IsSigned() {
110 return riscv.AMOVB
111 } else {
112 return riscv.AMOVBU
113 }
114 case 2:
115 if t.IsSigned() {
116 return riscv.AMOVH
117 } else {
118 return riscv.AMOVHU
119 }
120 case 4:
121 if t.IsSigned() {
122 return riscv.AMOVW
123 } else {
124 return riscv.AMOVWU
125 }
126 case 8:
127 return riscv.AMOV
128 default:
129 base.Fatalf("unknown width for load %d in type %v", width, t)
130 return 0
131 }
132 }
133
134
135 func storeByType(t *types.Type) obj.As {
136 width := t.Size()
137
138 if t.IsFloat() {
139 switch width {
140 case 4:
141 return riscv.AMOVF
142 case 8:
143 return riscv.AMOVD
144 default:
145 base.Fatalf("unknown float width for store %d in type %v", width, t)
146 return 0
147 }
148 }
149
150 switch width {
151 case 1:
152 return riscv.AMOVB
153 case 2:
154 return riscv.AMOVH
155 case 4:
156 return riscv.AMOVW
157 case 8:
158 return riscv.AMOV
159 default:
160 base.Fatalf("unknown width for store %d in type %v", width, t)
161 return 0
162 }
163 }
164
165
166
167
168
169
170
171
172
173
174 func largestMove(alignment int64) (obj.As, int64) {
175 switch {
176 case alignment%8 == 0:
177 return riscv.AMOV, 8
178 case alignment%4 == 0:
179 return riscv.AMOVW, 4
180 case alignment%2 == 0:
181 return riscv.AMOVH, 2
182 default:
183 return riscv.AMOVB, 1
184 }
185 }
186
187 var fracMovOps = []obj.As{riscv.AMOVB, riscv.AMOVH, riscv.AMOVW, riscv.AMOV}
188
189
190
191 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {}
192
193 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
194 s.SetPos(v.Pos)
195
196 switch v.Op {
197 case ssaop.OpInitMem:
198
199 case ssaop.OpArg:
200
201 case ssaop.OpPhi:
202 ssagen.CheckLoweredPhi(v)
203 case ssaop.OpCopy, ssaop.OpRISCV64MOVDreg:
204 if v.Type.IsMemory() {
205 return
206 }
207 rs := v.Args[0].Reg()
208 rd := v.Reg()
209 if rs == rd {
210 return
211 }
212 as := riscv.AMOV
213 if v.Type.IsFloat() {
214 as = riscv.AMOVD
215 }
216 p := s.Prog(as)
217 p.From.Type = obj.TYPE_REG
218 p.From.Reg = rs
219 p.To.Type = obj.TYPE_REG
220 p.To.Reg = rd
221 case ssaop.OpRISCV64MOVDnop:
222
223 case ssaop.OpLoadReg:
224 if v.Type.IsFlags() {
225 v.Fatalf("load flags not implemented: %v", v.LongString())
226 return
227 }
228 p := s.Prog(loadByType(v.Type))
229 ssagen.AddrAuto(&p.From, v.Args[0])
230 p.To.Type = obj.TYPE_REG
231 p.To.Reg = v.Reg()
232 case ssaop.OpStoreReg:
233 if v.Type.IsFlags() {
234 v.Fatalf("store flags not implemented: %v", v.LongString())
235 return
236 }
237 p := s.Prog(storeByType(v.Type))
238 p.From.Type = obj.TYPE_REG
239 p.From.Reg = v.Args[0].Reg()
240 ssagen.AddrAuto(&p.To, v)
241 case ssaop.OpArgIntReg, ssaop.OpArgFloatReg:
242
243
244 for _, a := range v.Block.Func.RegArgs {
245
246
247 addr := ssagen.SpillSlotAddr(a, riscv.REG_SP, base.Ctxt.Arch.FixedFrameSize)
248 s.FuncInfo().AddSpill(
249 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
250 }
251 v.Block.Func.RegArgs = nil
252
253 ssagen.CheckArgReg(v)
254 case ssaop.OpSP, ssaop.OpSB, ssaop.OpGetG:
255
256 case ssaop.OpRISCV64MOVBreg, ssaop.OpRISCV64MOVHreg, ssaop.OpRISCV64MOVWreg,
257 ssaop.OpRISCV64MOVBUreg, ssaop.OpRISCV64MOVHUreg, ssaop.OpRISCV64MOVWUreg:
258 a := v.Args[0]
259 for a.Op == ssaop.OpCopy || a.Op == ssaop.OpRISCV64MOVDreg {
260 a = a.Args[0]
261 }
262 as := v.Op.Asm()
263 rs := v.Args[0].Reg()
264 rd := v.Reg()
265 if a.Op == ssaop.OpLoadReg {
266 t := a.Type
267 switch {
268 case v.Op == ssaop.OpRISCV64MOVBreg && t.Size() == 1 && t.IsSigned(),
269 v.Op == ssaop.OpRISCV64MOVHreg && t.Size() == 2 && t.IsSigned(),
270 v.Op == ssaop.OpRISCV64MOVWreg && t.Size() == 4 && t.IsSigned(),
271 v.Op == ssaop.OpRISCV64MOVBUreg && t.Size() == 1 && !t.IsSigned(),
272 v.Op == ssaop.OpRISCV64MOVHUreg && t.Size() == 2 && !t.IsSigned(),
273 v.Op == ssaop.OpRISCV64MOVWUreg && t.Size() == 4 && !t.IsSigned():
274
275 if rs == rd {
276 return
277 }
278 as = riscv.AMOV
279 default:
280 }
281 }
282 p := s.Prog(as)
283 p.From.Type = obj.TYPE_REG
284 p.From.Reg = rs
285 p.To.Type = obj.TYPE_REG
286 p.To.Reg = rd
287 case ssaop.OpRISCV64ADD, ssaop.OpRISCV64SUB, ssaop.OpRISCV64SUBW, ssaop.OpRISCV64XNOR, ssaop.OpRISCV64XOR,
288 ssaop.OpRISCV64OR, ssaop.OpRISCV64ORN, ssaop.OpRISCV64AND, ssaop.OpRISCV64ANDN,
289 ssaop.OpRISCV64SLL, ssaop.OpRISCV64SLLW, ssaop.OpRISCV64SRA, ssaop.OpRISCV64SRAW, ssaop.OpRISCV64SRL, ssaop.OpRISCV64SRLW,
290 ssaop.OpRISCV64SLT, ssaop.OpRISCV64SLTU, ssaop.OpRISCV64MUL, ssaop.OpRISCV64MULW, ssaop.OpRISCV64MULH,
291 ssaop.OpRISCV64MULHU, ssaop.OpRISCV64DIV, ssaop.OpRISCV64DIVU, ssaop.OpRISCV64DIVW,
292 ssaop.OpRISCV64DIVUW, ssaop.OpRISCV64REM, ssaop.OpRISCV64REMU, ssaop.OpRISCV64REMW,
293 ssaop.OpRISCV64REMUW,
294 ssaop.OpRISCV64ROL, ssaop.OpRISCV64ROLW, ssaop.OpRISCV64ROR, ssaop.OpRISCV64RORW,
295 ssaop.OpRISCV64FADDS, ssaop.OpRISCV64FSUBS, ssaop.OpRISCV64FMULS, ssaop.OpRISCV64FDIVS,
296 ssaop.OpRISCV64FEQS, ssaop.OpRISCV64FNES, ssaop.OpRISCV64FLTS, ssaop.OpRISCV64FLES,
297 ssaop.OpRISCV64FADDD, ssaop.OpRISCV64FSUBD, ssaop.OpRISCV64FMULD, ssaop.OpRISCV64FDIVD,
298 ssaop.OpRISCV64FEQD, ssaop.OpRISCV64FNED, ssaop.OpRISCV64FLTD, ssaop.OpRISCV64FLED, ssaop.OpRISCV64FSGNJD,
299 ssaop.OpRISCV64MIN, ssaop.OpRISCV64MAX, ssaop.OpRISCV64MINU, ssaop.OpRISCV64MAXU,
300 ssaop.OpRISCV64SH1ADD, ssaop.OpRISCV64SH2ADD, ssaop.OpRISCV64SH3ADD,
301 ssaop.OpRISCV64CZEROEQZ, ssaop.OpRISCV64CZERONEZ:
302 r := v.Reg()
303 r1 := v.Args[0].Reg()
304 r2 := v.Args[1].Reg()
305 p := s.Prog(v.Op.Asm())
306 p.From.Type = obj.TYPE_REG
307 p.From.Reg = r2
308 p.Reg = r1
309 p.To.Type = obj.TYPE_REG
310 p.To.Reg = r
311
312 case ssaop.OpRISCV64LoweredFMAXD, ssaop.OpRISCV64LoweredFMIND, ssaop.OpRISCV64LoweredFMAXS, ssaop.OpRISCV64LoweredFMINS:
313
314
315
316
317
318
319
320
321
322
323
324 r0 := v.Args[0].Reg()
325 r1 := v.Args[1].Reg()
326 out := v.Reg()
327 add, feq := riscv.AFADDD, riscv.AFEQD
328 if v.Op == ssaop.OpRISCV64LoweredFMAXS || v.Op == ssaop.OpRISCV64LoweredFMINS {
329 add = riscv.AFADDS
330 feq = riscv.AFEQS
331 }
332
333 p1 := s.Prog(add)
334 p1.From.Type = obj.TYPE_REG
335 p1.From.Reg = r0
336 p1.Reg = r1
337 p1.To.Type = obj.TYPE_REG
338 p1.To.Reg = out
339
340 p2 := s.Prog(feq)
341 p2.From.Type = obj.TYPE_REG
342 p2.From.Reg = r0
343 p2.Reg = r0
344 p2.To.Type = obj.TYPE_REG
345 p2.To.Reg = riscv.REG_TMP
346
347 p3 := s.Prog(riscv.ABEQ)
348 p3.From.Type = obj.TYPE_REG
349 p3.From.Reg = riscv.REG_ZERO
350 p3.Reg = riscv.REG_TMP
351 p3.To.Type = obj.TYPE_BRANCH
352
353 p4 := s.Prog(feq)
354 p4.From.Type = obj.TYPE_REG
355 p4.From.Reg = r1
356 p4.Reg = r1
357 p4.To.Type = obj.TYPE_REG
358 p4.To.Reg = riscv.REG_TMP
359
360 p5 := s.Prog(riscv.ABEQ)
361 p5.From.Type = obj.TYPE_REG
362 p5.From.Reg = riscv.REG_ZERO
363 p5.Reg = riscv.REG_TMP
364 p5.To.Type = obj.TYPE_BRANCH
365
366 p6 := s.Prog(v.Op.Asm())
367 p6.From.Type = obj.TYPE_REG
368 p6.From.Reg = r1
369 p6.Reg = r0
370 p6.To.Type = obj.TYPE_REG
371 p6.To.Reg = out
372
373 nop := s.Prog(obj.ANOP)
374 p3.To.SetTarget(nop)
375 p5.To.SetTarget(nop)
376
377 case ssaop.OpRISCV64LoweredMuluhilo:
378 r0 := v.Args[0].Reg()
379 r1 := v.Args[1].Reg()
380 p := s.Prog(riscv.AMULHU)
381 p.From.Type = obj.TYPE_REG
382 p.From.Reg = r1
383 p.Reg = r0
384 p.To.Type = obj.TYPE_REG
385 p.To.Reg = v.Reg0()
386 p1 := s.Prog(riscv.AMUL)
387 p1.From.Type = obj.TYPE_REG
388 p1.From.Reg = r1
389 p1.Reg = r0
390 p1.To.Type = obj.TYPE_REG
391 p1.To.Reg = v.Reg1()
392 case ssaop.OpRISCV64LoweredMuluover:
393 r0 := v.Args[0].Reg()
394 r1 := v.Args[1].Reg()
395 p := s.Prog(riscv.AMULHU)
396 p.From.Type = obj.TYPE_REG
397 p.From.Reg = r1
398 p.Reg = r0
399 p.To.Type = obj.TYPE_REG
400 p.To.Reg = v.Reg1()
401 p1 := s.Prog(riscv.AMUL)
402 p1.From.Type = obj.TYPE_REG
403 p1.From.Reg = r1
404 p1.Reg = r0
405 p1.To.Type = obj.TYPE_REG
406 p1.To.Reg = v.Reg0()
407 p2 := s.Prog(riscv.ASNEZ)
408 p2.From.Type = obj.TYPE_REG
409 p2.From.Reg = v.Reg1()
410 p2.To.Type = obj.TYPE_REG
411 p2.To.Reg = v.Reg1()
412 case ssaop.OpRISCV64FMADDD, ssaop.OpRISCV64FMSUBD, ssaop.OpRISCV64FNMADDD, ssaop.OpRISCV64FNMSUBD,
413 ssaop.OpRISCV64FMADDS, ssaop.OpRISCV64FMSUBS, ssaop.OpRISCV64FNMADDS, ssaop.OpRISCV64FNMSUBS:
414 r := v.Reg()
415 r1 := v.Args[0].Reg()
416 r2 := v.Args[1].Reg()
417 r3 := v.Args[2].Reg()
418 p := s.Prog(v.Op.Asm())
419 p.From.Type = obj.TYPE_REG
420 p.From.Reg = r2
421 p.Reg = r1
422 p.AddRestSource(obj.Addr{Type: obj.TYPE_REG, Reg: r3})
423 p.To.Type = obj.TYPE_REG
424 p.To.Reg = r
425 case ssaop.OpRISCV64FSQRTS, ssaop.OpRISCV64FSQRTD,
426 ssaop.OpRISCV64FNEGS, ssaop.OpRISCV64FNEGD,
427 ssaop.OpRISCV64FABSS, ssaop.OpRISCV64FABSD,
428 ssaop.OpRISCV64FMVSX, ssaop.OpRISCV64FMVXS, ssaop.OpRISCV64FMVDX, ssaop.OpRISCV64FMVXD,
429 ssaop.OpRISCV64FCVTSW, ssaop.OpRISCV64FCVTSL, ssaop.OpRISCV64FCVTWS, ssaop.OpRISCV64FCVTLS,
430 ssaop.OpRISCV64FCVTDW, ssaop.OpRISCV64FCVTDL, ssaop.OpRISCV64FCVTWD, ssaop.OpRISCV64FCVTLD, ssaop.OpRISCV64FCVTDS, ssaop.OpRISCV64FCVTSD,
431 ssaop.OpRISCV64FCLASSS, ssaop.OpRISCV64FCLASSD,
432 ssaop.OpRISCV64NOT, ssaop.OpRISCV64NEG, ssaop.OpRISCV64NEGW, ssaop.OpRISCV64CLZ, ssaop.OpRISCV64CLZW, ssaop.OpRISCV64CTZ, ssaop.OpRISCV64CTZW,
433 ssaop.OpRISCV64REV8, ssaop.OpRISCV64CPOP, ssaop.OpRISCV64CPOPW:
434 p := s.Prog(v.Op.Asm())
435 p.From.Type = obj.TYPE_REG
436 p.From.Reg = v.Args[0].Reg()
437 p.To.Type = obj.TYPE_REG
438 p.To.Reg = v.Reg()
439 case ssaop.OpRISCV64ADDI, ssaop.OpRISCV64ADDIW, ssaop.OpRISCV64XORI, ssaop.OpRISCV64ORI, ssaop.OpRISCV64ANDI,
440 ssaop.OpRISCV64SLLI, ssaop.OpRISCV64SLLIW, ssaop.OpRISCV64SRAI, ssaop.OpRISCV64SRAIW,
441 ssaop.OpRISCV64SRLI, ssaop.OpRISCV64SRLIW, ssaop.OpRISCV64SLTI, ssaop.OpRISCV64SLTIU,
442 ssaop.OpRISCV64RORI, ssaop.OpRISCV64RORIW:
443 p := s.Prog(v.Op.Asm())
444 p.From.Type = obj.TYPE_CONST
445 p.From.Offset = v.AuxInt
446 p.Reg = v.Args[0].Reg()
447 p.To.Type = obj.TYPE_REG
448 p.To.Reg = v.Reg()
449 case ssaop.OpRISCV64MOVDconst:
450 p := s.Prog(v.Op.Asm())
451 p.From.Type = obj.TYPE_CONST
452 p.From.Offset = v.AuxInt
453 p.To.Type = obj.TYPE_REG
454 p.To.Reg = v.Reg()
455 case ssaop.OpRISCV64FMOVDconst, ssaop.OpRISCV64FMOVFconst:
456 p := s.Prog(v.Op.Asm())
457 p.From.Type = obj.TYPE_FCONST
458 p.From.Val = v.AuxFloat()
459 p.From.Name = obj.NAME_NONE
460 p.From.Reg = obj.REG_NONE
461 p.To.Type = obj.TYPE_REG
462 p.To.Reg = v.Reg()
463 case ssaop.OpRISCV64MOVaddr:
464 p := s.Prog(v.Op.Asm())
465 p.From.Type = obj.TYPE_ADDR
466 p.To.Type = obj.TYPE_REG
467 p.To.Reg = v.Reg()
468
469 var wantreg string
470
471 switch v.Aux.(type) {
472 default:
473 v.Fatalf("aux is of unknown type %T", v.Aux)
474 case *obj.LSym:
475 wantreg = "SB"
476 ssagen.AddAux(&p.From, v)
477 case *ir.Name:
478 wantreg = "SP"
479 ssagen.AddAux(&p.From, v)
480 case nil:
481
482 wantreg = "SP"
483 p.From.Reg = riscv.REG_SP
484 p.From.Offset = v.AuxInt
485 }
486 if reg := v.Args[0].RegName(); reg != wantreg {
487 v.Fatalf("bad reg %s for symbol type %T, want %s", reg, v.Aux, wantreg)
488 }
489 case ssaop.OpRISCV64MOVBload, ssaop.OpRISCV64MOVHload, ssaop.OpRISCV64MOVWload, ssaop.OpRISCV64MOVDload,
490 ssaop.OpRISCV64MOVBUload, ssaop.OpRISCV64MOVHUload, ssaop.OpRISCV64MOVWUload,
491 ssaop.OpRISCV64FMOVWload, ssaop.OpRISCV64FMOVDload:
492 p := s.Prog(v.Op.Asm())
493 p.From.Type = obj.TYPE_MEM
494 p.From.Reg = v.Args[0].Reg()
495 ssagen.AddAux(&p.From, v)
496 p.To.Type = obj.TYPE_REG
497 p.To.Reg = v.Reg()
498 case ssaop.OpRISCV64MOVBstore, ssaop.OpRISCV64MOVHstore, ssaop.OpRISCV64MOVWstore, ssaop.OpRISCV64MOVDstore,
499 ssaop.OpRISCV64FMOVWstore, ssaop.OpRISCV64FMOVDstore:
500 p := s.Prog(v.Op.Asm())
501 p.From.Type = obj.TYPE_REG
502 p.From.Reg = v.Args[1].Reg()
503 p.To.Type = obj.TYPE_MEM
504 p.To.Reg = v.Args[0].Reg()
505 ssagen.AddAux(&p.To, v)
506 case ssaop.OpRISCV64MOVBstorezero, ssaop.OpRISCV64MOVHstorezero, ssaop.OpRISCV64MOVWstorezero, ssaop.OpRISCV64MOVDstorezero:
507 p := s.Prog(v.Op.Asm())
508 p.From.Type = obj.TYPE_REG
509 p.From.Reg = riscv.REG_ZERO
510 p.To.Type = obj.TYPE_MEM
511 p.To.Reg = v.Args[0].Reg()
512 ssagen.AddAux(&p.To, v)
513 case ssaop.OpRISCV64SEQZ, ssaop.OpRISCV64SNEZ:
514 p := s.Prog(v.Op.Asm())
515 p.From.Type = obj.TYPE_REG
516 p.From.Reg = v.Args[0].Reg()
517 p.To.Type = obj.TYPE_REG
518 p.To.Reg = v.Reg()
519 case ssaop.OpRISCV64CALLstatic, ssaop.OpRISCV64CALLclosure, ssaop.OpRISCV64CALLinter:
520 s.Call(v)
521 case ssaop.OpRISCV64CALLtail, ssaop.OpRISCV64CALLtailinter:
522 s.TailCall(v)
523 case ssaop.OpRISCV64LoweredWB:
524 p := s.Prog(obj.ACALL)
525 p.To.Type = obj.TYPE_MEM
526 p.To.Name = obj.NAME_EXTERN
527
528 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
529
530 case ssaop.OpRISCV64LoweredPanicBoundsRR, ssaop.OpRISCV64LoweredPanicBoundsRC, ssaop.OpRISCV64LoweredPanicBoundsCR, ssaop.OpRISCV64LoweredPanicBoundsCC:
531
532 code, signed := ssa.BoundsKind(v.AuxInt).Code()
533 xIsReg := false
534 yIsReg := false
535 xVal := 0
536 yVal := 0
537 switch v.Op {
538 case ssaop.OpRISCV64LoweredPanicBoundsRR:
539 xIsReg = true
540 xVal = int(v.Args[0].Reg() - riscv.REG_X5)
541 yIsReg = true
542 yVal = int(v.Args[1].Reg() - riscv.REG_X5)
543 case ssaop.OpRISCV64LoweredPanicBoundsRC:
544 xIsReg = true
545 xVal = int(v.Args[0].Reg() - riscv.REG_X5)
546 c := v.Aux.(ssa.PanicBoundsC).C
547 if c >= 0 && c <= abi.BoundsMaxConst {
548 yVal = int(c)
549 } else {
550
551 yIsReg = true
552 if yVal == xVal {
553 yVal = 1
554 }
555 p := s.Prog(riscv.AMOV)
556 p.From.Type = obj.TYPE_CONST
557 p.From.Offset = c
558 p.To.Type = obj.TYPE_REG
559 p.To.Reg = riscv.REG_X5 + int16(yVal)
560 }
561 case ssaop.OpRISCV64LoweredPanicBoundsCR:
562 yIsReg = true
563 yVal = int(v.Args[0].Reg() - riscv.REG_X5)
564 c := v.Aux.(ssa.PanicBoundsC).C
565 if c >= 0 && c <= abi.BoundsMaxConst {
566 xVal = int(c)
567 } else {
568
569 if xVal == yVal {
570 xVal = 1
571 }
572 p := s.Prog(riscv.AMOV)
573 p.From.Type = obj.TYPE_CONST
574 p.From.Offset = c
575 p.To.Type = obj.TYPE_REG
576 p.To.Reg = riscv.REG_X5 + int16(xVal)
577 }
578 case ssaop.OpRISCV64LoweredPanicBoundsCC:
579 c := v.Aux.(ssa.PanicBoundsCC).Cx
580 if c >= 0 && c <= abi.BoundsMaxConst {
581 xVal = int(c)
582 } else {
583
584 xIsReg = true
585 p := s.Prog(riscv.AMOV)
586 p.From.Type = obj.TYPE_CONST
587 p.From.Offset = c
588 p.To.Type = obj.TYPE_REG
589 p.To.Reg = riscv.REG_X5 + int16(xVal)
590 }
591 c = v.Aux.(ssa.PanicBoundsCC).Cy
592 if c >= 0 && c <= abi.BoundsMaxConst {
593 yVal = int(c)
594 } else {
595
596 yIsReg = true
597 yVal = 1
598 p := s.Prog(riscv.AMOV)
599 p.From.Type = obj.TYPE_CONST
600 p.From.Offset = c
601 p.To.Type = obj.TYPE_REG
602 p.To.Reg = riscv.REG_X5 + int16(yVal)
603 }
604 }
605 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
606
607 p := s.Prog(obj.APCDATA)
608 p.From.SetConst(abi.PCDATA_PanicBounds)
609 p.To.SetConst(int64(c))
610 p = s.Prog(obj.ACALL)
611 p.To.Type = obj.TYPE_MEM
612 p.To.Name = obj.NAME_EXTERN
613 p.To.Sym = ir.Syms.PanicBounds
614
615 case ssaop.OpRISCV64LoweredAtomicLoad8:
616 p1 := s.Prog(riscv.AFENCE)
617 p1.From.Type = obj.TYPE_SPECIAL
618 p1.From.Offset = int64(riscv.SPOP_FENCE_RW)
619 p1.To.Type = obj.TYPE_SPECIAL
620 p1.To.Offset = int64(riscv.SPOP_FENCE_RW)
621
622 p := s.Prog(riscv.AMOVBU)
623 p.From.Type = obj.TYPE_MEM
624 p.From.Reg = v.Args[0].Reg()
625 p.To.Type = obj.TYPE_REG
626 p.To.Reg = v.Reg0()
627
628 p2 := s.Prog(riscv.AFENCE)
629 p2.From.Type = obj.TYPE_SPECIAL
630 p2.From.Offset = int64(riscv.SPOP_FENCE_R)
631 p2.To.Type = obj.TYPE_SPECIAL
632 p2.To.Offset = int64(riscv.SPOP_FENCE_RW)
633
634 case ssaop.OpRISCV64LoweredAtomicLoad32, ssaop.OpRISCV64LoweredAtomicLoad64:
635 as := riscv.ALRW
636 if v.Op == ssaop.OpRISCV64LoweredAtomicLoad64 {
637 as = riscv.ALRD
638 }
639 p := s.Prog(as)
640 p.From.Type = obj.TYPE_MEM
641 p.From.Reg = v.Args[0].Reg()
642 p.To.Type = obj.TYPE_REG
643 p.To.Reg = v.Reg0()
644
645 case ssaop.OpRISCV64LoweredAtomicStore8:
646 p1 := s.Prog(riscv.AFENCE)
647 p1.From.Type = obj.TYPE_SPECIAL
648 p1.From.Offset = int64(riscv.SPOP_FENCE_RW)
649 p1.To.Type = obj.TYPE_SPECIAL
650 p1.To.Offset = int64(riscv.SPOP_FENCE_W)
651
652 p := s.Prog(riscv.AMOVB)
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
658 p2 := s.Prog(riscv.AFENCE)
659 p2.From.Type = obj.TYPE_SPECIAL
660 p2.From.Offset = int64(riscv.SPOP_FENCE_RW)
661 p2.To.Type = obj.TYPE_SPECIAL
662 p2.To.Offset = int64(riscv.SPOP_FENCE_RW)
663
664 case ssaop.OpRISCV64LoweredAtomicStore32, ssaop.OpRISCV64LoweredAtomicStore64:
665 as := riscv.AAMOSWAPW
666 if v.Op == ssaop.OpRISCV64LoweredAtomicStore64 {
667 as = riscv.AAMOSWAPD
668 }
669 p := s.Prog(as)
670 p.From.Type = obj.TYPE_REG
671 p.From.Reg = v.Args[1].Reg()
672 p.To.Type = obj.TYPE_MEM
673 p.To.Reg = v.Args[0].Reg()
674 p.RegTo2 = riscv.REG_ZERO
675
676 case ssaop.OpRISCV64LoweredAtomicAdd32, ssaop.OpRISCV64LoweredAtomicAdd64:
677 as := riscv.AAMOADDW
678 if v.Op == ssaop.OpRISCV64LoweredAtomicAdd64 {
679 as = riscv.AAMOADDD
680 }
681 p := s.Prog(as)
682 p.From.Type = obj.TYPE_REG
683 p.From.Reg = v.Args[1].Reg()
684 p.To.Type = obj.TYPE_MEM
685 p.To.Reg = v.Args[0].Reg()
686 p.RegTo2 = riscv.REG_TMP
687
688 p2 := s.Prog(riscv.AADD)
689 p2.From.Type = obj.TYPE_REG
690 p2.From.Reg = riscv.REG_TMP
691 p2.Reg = v.Args[1].Reg()
692 p2.To.Type = obj.TYPE_REG
693 p2.To.Reg = v.Reg0()
694
695 case ssaop.OpRISCV64LoweredAtomicExchange32, ssaop.OpRISCV64LoweredAtomicExchange64:
696 as := riscv.AAMOSWAPW
697 if v.Op == ssaop.OpRISCV64LoweredAtomicExchange64 {
698 as = riscv.AAMOSWAPD
699 }
700 p := s.Prog(as)
701 p.From.Type = obj.TYPE_REG
702 p.From.Reg = v.Args[1].Reg()
703 p.To.Type = obj.TYPE_MEM
704 p.To.Reg = v.Args[0].Reg()
705 p.RegTo2 = v.Reg0()
706
707 case ssaop.OpRISCV64LoweredAtomicCas32, ssaop.OpRISCV64LoweredAtomicCas64:
708
709
710
711
712
713
714
715 lr := riscv.ALRW
716 sc := riscv.ASCW
717 if v.Op == ssaop.OpRISCV64LoweredAtomicCas64 {
718 lr = riscv.ALRD
719 sc = riscv.ASCD
720 }
721
722 r0 := v.Args[0].Reg()
723 r1 := v.Args[1].Reg()
724 r2 := v.Args[2].Reg()
725 out := v.Reg0()
726
727 p := s.Prog(riscv.AMOV)
728 p.From.Type = obj.TYPE_REG
729 p.From.Reg = riscv.REG_ZERO
730 p.To.Type = obj.TYPE_REG
731 p.To.Reg = out
732
733 p1 := s.Prog(lr)
734 p1.From.Type = obj.TYPE_MEM
735 p1.From.Reg = r0
736 p1.To.Type = obj.TYPE_REG
737 p1.To.Reg = riscv.REG_TMP
738
739 p2 := s.Prog(riscv.ABNE)
740 p2.From.Type = obj.TYPE_REG
741 p2.From.Reg = r1
742 p2.Reg = riscv.REG_TMP
743 p2.To.Type = obj.TYPE_BRANCH
744
745 p3 := s.Prog(sc)
746 p3.From.Type = obj.TYPE_REG
747 p3.From.Reg = r2
748 p3.To.Type = obj.TYPE_MEM
749 p3.To.Reg = r0
750 p3.RegTo2 = riscv.REG_TMP
751
752 p4 := s.Prog(riscv.ABNE)
753 p4.From.Type = obj.TYPE_REG
754 p4.From.Reg = riscv.REG_TMP
755 p4.Reg = riscv.REG_ZERO
756 p4.To.Type = obj.TYPE_BRANCH
757 p4.To.SetTarget(p1)
758
759 p5 := s.Prog(riscv.AMOV)
760 p5.From.Type = obj.TYPE_CONST
761 p5.From.Offset = 1
762 p5.To.Type = obj.TYPE_REG
763 p5.To.Reg = out
764
765 p6 := s.Prog(obj.ANOP)
766 p2.To.SetTarget(p6)
767
768 case ssaop.OpRISCV64LoweredAtomicAnd32, ssaop.OpRISCV64LoweredAtomicOr32:
769 p := s.Prog(v.Op.Asm())
770 p.From.Type = obj.TYPE_REG
771 p.From.Reg = v.Args[1].Reg()
772 p.To.Type = obj.TYPE_MEM
773 p.To.Reg = v.Args[0].Reg()
774 p.RegTo2 = riscv.REG_ZERO
775
776 case ssaop.OpRISCV64LoweredAtomicAnd32value, ssaop.OpRISCV64LoweredAtomicAnd64value,
777 ssaop.OpRISCV64LoweredAtomicOr32value, ssaop.OpRISCV64LoweredAtomicOr64value:
778 p := s.Prog(v.Op.Asm())
779 p.From.Type = obj.TYPE_REG
780 p.From.Reg = v.Args[1].Reg()
781 p.To.Type = obj.TYPE_MEM
782 p.To.Reg = v.Args[0].Reg()
783 p.RegTo2 = v.Reg0()
784
785 case ssaop.OpRISCV64LoweredZero:
786 ptr := v.Args[0].Reg()
787 n, align := v.AuxSizeAndAlign()
788 mov, sz := largestMove(align)
789
790
791 var off int64
792 for n >= sz {
793 zeroOp(s, mov, ptr, off)
794 off += sz
795 n -= sz
796 }
797
798 for i := len(fracMovOps) - 1; i >= 0; i-- {
799 tsz := int64(1 << i)
800 if n < tsz {
801 continue
802 }
803 zeroOp(s, fracMovOps[i], ptr, off)
804 off += tsz
805 n -= tsz
806 }
807
808 case ssaop.OpRISCV64LoweredZeroLoop:
809 ptr := v.Args[0].Reg()
810 n, align := v.AuxSizeAndAlign()
811 mov, sz := largestMove(align)
812 chunk := 8 * sz
813
814 if n <= 3*chunk {
815 v.Fatalf("ZeroLoop too small:%d, expect:%d", n, 3*chunk)
816 }
817
818 tmp := v.RegTmp()
819
820 if n >= 1<<31 {
821 p := s.Prog(riscv.AMOV)
822 p.From.Type = obj.TYPE_CONST
823 p.From.Offset = n - n%chunk
824 p.To.Type = obj.TYPE_REG
825 p.To.Reg = tmp
826 }
827 p := s.Prog(riscv.AADD)
828 if n >= 1<<31 {
829 p.From.Type = obj.TYPE_REG
830 p.From.Reg = tmp
831 } else {
832 p.From.Type = obj.TYPE_CONST
833 p.From.Offset = n - n%chunk
834 }
835 p.Reg = ptr
836 p.To.Type = obj.TYPE_REG
837 p.To.Reg = tmp
838
839 for i := int64(0); i < 8; i++ {
840 zeroOp(s, mov, ptr, sz*i)
841 }
842
843 p2 := s.Prog(riscv.AADD)
844 p2.From.Type = obj.TYPE_CONST
845 p2.From.Offset = chunk
846 p2.To.Type = obj.TYPE_REG
847 p2.To.Reg = ptr
848
849 p3 := s.Prog(riscv.ABNE)
850 p3.From.Reg = tmp
851 p3.From.Type = obj.TYPE_REG
852 p3.Reg = ptr
853 p3.To.Type = obj.TYPE_BRANCH
854 p3.To.SetTarget(p.Link)
855
856 n %= chunk
857
858
859 var off int64
860 for n >= sz {
861 zeroOp(s, mov, ptr, off)
862 off += sz
863 n -= sz
864 }
865
866 for i := len(fracMovOps) - 1; i >= 0; i-- {
867 tsz := int64(1 << i)
868 if n < tsz {
869 continue
870 }
871 zeroOp(s, fracMovOps[i], ptr, off)
872 off += tsz
873 n -= tsz
874 }
875
876 case ssaop.OpRISCV64LoweredMove:
877 dst := v.Args[0].Reg()
878 src := v.Args[1].Reg()
879 if dst == src {
880 break
881 }
882
883 n, align := v.AuxSizeAndAlign()
884 mov, sz := largestMove(align)
885
886 var off int64
887 tmp := int16(riscv.REG_X5)
888 for n >= sz {
889 moveOp(s, mov, dst, src, tmp, off)
890 off += sz
891 n -= sz
892 }
893
894 for i := len(fracMovOps) - 1; i >= 0; i-- {
895 tsz := int64(1 << i)
896 if n < tsz {
897 continue
898 }
899 moveOp(s, fracMovOps[i], dst, src, tmp, off)
900 off += tsz
901 n -= tsz
902 }
903
904 case ssaop.OpRISCV64LoweredMoveLoop:
905 dst := v.Args[0].Reg()
906 src := v.Args[1].Reg()
907 if dst == src {
908 break
909 }
910
911 n, align := v.AuxSizeAndAlign()
912 mov, sz := largestMove(align)
913 chunk := 8 * sz
914
915 if n <= 3*chunk {
916 v.Fatalf("MoveLoop too small:%d, expect:%d", n, 3*chunk)
917 }
918 tmp := int16(riscv.REG_X5)
919
920 if n >= 1<<31 {
921 p := s.Prog(riscv.AMOV)
922 p.From.Type = obj.TYPE_CONST
923 p.From.Offset = n - n%chunk
924 p.To.Type = obj.TYPE_REG
925 p.To.Reg = riscv.REG_X6
926 }
927 p := s.Prog(riscv.AADD)
928 if n >= 1<<31 {
929 p.From.Type = obj.TYPE_REG
930 p.From.Reg = riscv.REG_X6
931 } else {
932 p.From.Type = obj.TYPE_CONST
933 p.From.Offset = n - n%chunk
934 }
935 p.Reg = src
936 p.To.Type = obj.TYPE_REG
937 p.To.Reg = riscv.REG_X6
938
939 for i := int64(0); i < 8; i++ {
940 moveOp(s, mov, dst, src, tmp, sz*i)
941 }
942
943 p1 := s.Prog(riscv.AADD)
944 p1.From.Type = obj.TYPE_CONST
945 p1.From.Offset = chunk
946 p1.To.Type = obj.TYPE_REG
947 p1.To.Reg = src
948
949 p2 := s.Prog(riscv.AADD)
950 p2.From.Type = obj.TYPE_CONST
951 p2.From.Offset = chunk
952 p2.To.Type = obj.TYPE_REG
953 p2.To.Reg = dst
954
955 p3 := s.Prog(riscv.ABNE)
956 p3.From.Reg = riscv.REG_X6
957 p3.From.Type = obj.TYPE_REG
958 p3.Reg = src
959 p3.To.Type = obj.TYPE_BRANCH
960 p3.To.SetTarget(p.Link)
961
962 n %= chunk
963
964 var off int64
965 for n >= sz {
966 moveOp(s, mov, dst, src, tmp, off)
967 off += sz
968 n -= sz
969 }
970
971 for i := len(fracMovOps) - 1; i >= 0; i-- {
972 tsz := int64(1 << i)
973 if n < tsz {
974 continue
975 }
976 moveOp(s, fracMovOps[i], dst, src, tmp, off)
977 off += tsz
978 n -= tsz
979 }
980
981 case ssaop.OpRISCV64LoweredNilCheck:
982
983 p := s.Prog(riscv.AMOVB)
984 p.From.Type = obj.TYPE_MEM
985 p.From.Reg = v.Args[0].Reg()
986 ssagen.AddAux(&p.From, v)
987 p.To.Type = obj.TYPE_REG
988 p.To.Reg = riscv.REG_ZERO
989 if logopt.Enabled() {
990 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
991 }
992 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
993 base.WarnfAt(v.Pos, "generated nil check")
994 }
995
996 case ssaop.OpRISCV64LoweredGetClosurePtr:
997
998 ssagen.CheckLoweredGetClosurePtr(v)
999
1000 case ssaop.OpRISCV64LoweredGetCallerSP:
1001
1002 p := s.Prog(riscv.AMOV)
1003 p.From.Type = obj.TYPE_ADDR
1004 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
1005 p.From.Name = obj.NAME_PARAM
1006 p.To.Type = obj.TYPE_REG
1007 p.To.Reg = v.Reg()
1008
1009 case ssaop.OpRISCV64LoweredGetCallerPC:
1010 p := s.Prog(obj.AGETCALLERPC)
1011 p.To.Type = obj.TYPE_REG
1012 p.To.Reg = v.Reg()
1013
1014 case ssaop.OpRISCV64LoweredPubBarrier:
1015
1016 p := s.Prog(v.Op.Asm())
1017 p.From.Type = obj.TYPE_SPECIAL
1018 p.From.Offset = int64(riscv.SPOP_FENCE_W)
1019 p.To.Type = obj.TYPE_SPECIAL
1020 p.To.Offset = int64(riscv.SPOP_FENCE_W)
1021
1022 case ssaop.OpRISCV64LoweredRound32F, ssaop.OpRISCV64LoweredRound64F:
1023
1024
1025 case ssaop.OpClobber, ssaop.OpClobberReg:
1026
1027
1028 default:
1029 v.Fatalf("Unhandled op %v", v.Op)
1030 }
1031 }
1032
1033 var blockBranch = [...]obj.As{
1034 block.BlockRISCV64BEQ: riscv.ABEQ,
1035 block.BlockRISCV64BEQZ: riscv.ABEQZ,
1036 block.BlockRISCV64BGE: riscv.ABGE,
1037 block.BlockRISCV64BGEU: riscv.ABGEU,
1038 block.BlockRISCV64BGEZ: riscv.ABGEZ,
1039 block.BlockRISCV64BGTZ: riscv.ABGTZ,
1040 block.BlockRISCV64BLEZ: riscv.ABLEZ,
1041 block.BlockRISCV64BLT: riscv.ABLT,
1042 block.BlockRISCV64BLTU: riscv.ABLTU,
1043 block.BlockRISCV64BLTZ: riscv.ABLTZ,
1044 block.BlockRISCV64BNE: riscv.ABNE,
1045 block.BlockRISCV64BNEZ: riscv.ABNEZ,
1046 }
1047
1048 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
1049 s.SetPos(b.Pos)
1050
1051 switch b.Kind {
1052 case block.BlockPlain, block.BlockDefer:
1053 if b.Succs[0].Block() != next {
1054 p := s.Prog(obj.AJMP)
1055 p.To.Type = obj.TYPE_BRANCH
1056 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
1057 }
1058 case block.BlockExit, block.BlockRetJmp:
1059 case block.BlockRet:
1060 s.Prog(obj.ARET)
1061 case block.BlockRISCV64BEQ, block.BlockRISCV64BEQZ, block.BlockRISCV64BNE, block.BlockRISCV64BNEZ,
1062 block.BlockRISCV64BLT, block.BlockRISCV64BLEZ, block.BlockRISCV64BGE, block.BlockRISCV64BGEZ,
1063 block.BlockRISCV64BLTZ, block.BlockRISCV64BGTZ, block.BlockRISCV64BLTU, block.BlockRISCV64BGEU:
1064
1065 as := blockBranch[b.Kind]
1066 invAs := riscv.InvertBranch(as)
1067
1068 var p *obj.Prog
1069 switch next {
1070 case b.Succs[0].Block():
1071 p = s.Br(invAs, b.Succs[1].Block())
1072 case b.Succs[1].Block():
1073 p = s.Br(as, b.Succs[0].Block())
1074 default:
1075 if b.Likely != ssa.BranchUnlikely {
1076 p = s.Br(as, b.Succs[0].Block())
1077 s.Br(obj.AJMP, b.Succs[1].Block())
1078 } else {
1079 p = s.Br(invAs, b.Succs[1].Block())
1080 s.Br(obj.AJMP, b.Succs[0].Block())
1081 }
1082 }
1083
1084 p.From.Type = obj.TYPE_REG
1085 switch b.Kind {
1086 case block.BlockRISCV64BEQ, block.BlockRISCV64BNE, block.BlockRISCV64BLT, block.BlockRISCV64BGE, block.BlockRISCV64BLTU, block.BlockRISCV64BGEU:
1087 if b.NumControls() != 2 {
1088 b.Fatalf("Unexpected number of controls (%d != 2): %s", b.NumControls(), b.LongString())
1089 }
1090 p.From.Reg = b.Controls[0].Reg()
1091 p.Reg = b.Controls[1].Reg()
1092
1093 case block.BlockRISCV64BEQZ, block.BlockRISCV64BNEZ, block.BlockRISCV64BGEZ, block.BlockRISCV64BLEZ, block.BlockRISCV64BLTZ, block.BlockRISCV64BGTZ:
1094 if b.NumControls() != 1 {
1095 b.Fatalf("Unexpected number of controls (%d != 1): %s", b.NumControls(), b.LongString())
1096 }
1097 p.From.Reg = b.Controls[0].Reg()
1098 }
1099
1100 case block.BlockRISCV64JUMPTABLE:
1101
1102
1103
1104 var p *obj.Prog
1105 if buildcfg.GORISCV64 >= 22 {
1106 p = s.Prog(riscv.ASH3ADD)
1107 p.From.Type = obj.TYPE_REG
1108 p.From.Reg = b.Controls[1].Reg()
1109 p.Reg = b.Controls[0].Reg()
1110 p.To.Type = obj.TYPE_REG
1111 p.To.Reg = riscv.REG_TMP
1112 } else {
1113 p = s.Prog(riscv.ASLLI)
1114 p.From.Type = obj.TYPE_CONST
1115 p.From.Offset = 3
1116 p.Reg = b.Controls[0].Reg()
1117 p.To.Type = obj.TYPE_REG
1118 p.To.Reg = riscv.REG_TMP
1119
1120 p = s.Prog(riscv.AADD)
1121 p.From.Type = obj.TYPE_REG
1122 p.From.Reg = riscv.REG_TMP
1123 p.Reg = b.Controls[1].Reg()
1124 p.To.Type = obj.TYPE_REG
1125 p.To.Reg = riscv.REG_TMP
1126 }
1127
1128 p = s.Prog(riscv.AMOV)
1129 p.From.Type = obj.TYPE_MEM
1130 p.From.Reg = riscv.REG_TMP
1131 p.To.Type = obj.TYPE_REG
1132 p.To.Reg = riscv.REG_TMP
1133
1134 p = s.Prog(obj.AJMP)
1135 p.To.Type = obj.TYPE_MEM
1136 p.To.Reg = riscv.REG_TMP
1137
1138 s.JumpTables = append(s.JumpTables, b)
1139
1140 default:
1141 b.Fatalf("Unhandled block: %s", b.LongString())
1142 }
1143 }
1144
1145 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1146 p := s.Prog(loadByType(t))
1147 p.From.Type = obj.TYPE_MEM
1148 p.From.Name = obj.NAME_AUTO
1149 p.From.Sym = n.Linksym()
1150 p.From.Offset = n.FrameOffset() + off
1151 p.To.Type = obj.TYPE_REG
1152 p.To.Reg = reg
1153 return p
1154 }
1155
1156 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1157 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
1158 p.To.Name = obj.NAME_PARAM
1159 p.To.Sym = n.Linksym()
1160 p.Pos = p.Pos.WithNotStmt()
1161 return p
1162 }
1163
1164 func zeroOp(s *ssagen.State, mov obj.As, reg int16, off int64) {
1165 p := s.Prog(mov)
1166 p.From.Type = obj.TYPE_REG
1167 p.From.Reg = riscv.REG_ZERO
1168 p.To.Type = obj.TYPE_MEM
1169 p.To.Reg = reg
1170 p.To.Offset = off
1171 return
1172 }
1173
1174 func moveOp(s *ssagen.State, mov obj.As, dst int16, src int16, tmp int16, off int64) {
1175 p := s.Prog(mov)
1176 p.From.Type = obj.TYPE_MEM
1177 p.From.Reg = src
1178 p.From.Offset = off
1179 p.To.Type = obj.TYPE_REG
1180 p.To.Reg = tmp
1181
1182 p1 := s.Prog(mov)
1183 p1.From.Type = obj.TYPE_REG
1184 p1.From.Reg = tmp
1185 p1.To.Type = obj.TYPE_MEM
1186 p1.To.Reg = dst
1187 p1.To.Offset = off
1188
1189 return
1190 }
1191
View as plain text