1
2
3
4
5 package s390x
6
7 import (
8 "math"
9
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/ir"
12 "cmd/compile/internal/logopt"
13 "cmd/compile/internal/objw"
14 "cmd/compile/internal/ssa"
15 "cmd/compile/internal/ssagen"
16 "cmd/compile/internal/types"
17 "cmd/internal/obj"
18 "cmd/internal/obj/s390x"
19 "internal/abi"
20 )
21
22
23 func ssaMarkMoves(s *ssagen.State, b *ssa.Block) {
24 flive := b.FlagsLiveAtEnd
25 for _, c := range b.ControlValues() {
26 flive = c.Type.IsFlags() || flive
27 }
28 for i := len(b.Values) - 1; i >= 0; i-- {
29 v := b.Values[i]
30 if flive && v.Op == ssa.OpS390XMOVDconst {
31
32 v.Aux = ssa.AuxMark
33 }
34 if v.Type.IsFlags() {
35 flive = false
36 }
37 for _, a := range v.Args {
38 if a.Type.IsFlags() {
39 flive = true
40 }
41 }
42 }
43 }
44
45
46 func loadByType(t *types.Type) obj.As {
47 if t.IsFloat() {
48 switch t.Size() {
49 case 4:
50 return s390x.AFMOVS
51 case 8:
52 return s390x.AFMOVD
53 }
54 } else {
55 switch t.Size() {
56 case 1:
57 if t.IsSigned() {
58 return s390x.AMOVB
59 } else {
60 return s390x.AMOVBZ
61 }
62 case 2:
63 if t.IsSigned() {
64 return s390x.AMOVH
65 } else {
66 return s390x.AMOVHZ
67 }
68 case 4:
69 if t.IsSigned() {
70 return s390x.AMOVW
71 } else {
72 return s390x.AMOVWZ
73 }
74 case 8:
75 return s390x.AMOVD
76 }
77 }
78 panic("bad load type")
79 }
80
81
82 func storeByType(t *types.Type) obj.As {
83 width := t.Size()
84 if t.IsFloat() {
85 switch width {
86 case 4:
87 return s390x.AFMOVS
88 case 8:
89 return s390x.AFMOVD
90 }
91 } else {
92 switch width {
93 case 1:
94 return s390x.AMOVB
95 case 2:
96 return s390x.AMOVH
97 case 4:
98 return s390x.AMOVW
99 case 8:
100 return s390x.AMOVD
101 }
102 }
103 panic("bad store type")
104 }
105
106
107 func moveByType(t *types.Type) obj.As {
108 if t.IsFloat() {
109 return s390x.AFMOVD
110 } else {
111 switch t.Size() {
112 case 1:
113 if t.IsSigned() {
114 return s390x.AMOVB
115 } else {
116 return s390x.AMOVBZ
117 }
118 case 2:
119 if t.IsSigned() {
120 return s390x.AMOVH
121 } else {
122 return s390x.AMOVHZ
123 }
124 case 4:
125 if t.IsSigned() {
126 return s390x.AMOVW
127 } else {
128 return s390x.AMOVWZ
129 }
130 case 8:
131 return s390x.AMOVD
132 }
133 }
134 panic("bad load type")
135 }
136
137
138
139
140
141
142
143 func opregreg(s *ssagen.State, op obj.As, dest, src int16) *obj.Prog {
144 p := s.Prog(op)
145 p.From.Type = obj.TYPE_REG
146 p.To.Type = obj.TYPE_REG
147 p.To.Reg = dest
148 p.From.Reg = src
149 return p
150 }
151
152
153
154
155
156
157
158 func opregregimm(s *ssagen.State, op obj.As, dest, src int16, off int64) *obj.Prog {
159 p := s.Prog(op)
160 p.From.Type = obj.TYPE_CONST
161 p.From.Offset = off
162 p.Reg = src
163 p.To.Reg = dest
164 p.To.Type = obj.TYPE_REG
165 return p
166 }
167
168 func ssaGenValue(s *ssagen.State, v *ssa.Value) {
169 switch v.Op {
170 case ssa.OpS390XSLD, ssa.OpS390XSLW,
171 ssa.OpS390XSRD, ssa.OpS390XSRW,
172 ssa.OpS390XSRAD, ssa.OpS390XSRAW,
173 ssa.OpS390XRLLG, ssa.OpS390XRLL:
174 r := v.Reg()
175 r1 := v.Args[0].Reg()
176 r2 := v.Args[1].Reg()
177 if r2 == s390x.REG_R0 {
178 v.Fatalf("cannot use R0 as shift value %s", v.LongString())
179 }
180 p := opregreg(s, v.Op.Asm(), r, r2)
181 if r != r1 {
182 p.Reg = r1
183 }
184 case ssa.OpS390XRXSBG:
185 r2 := v.Args[1].Reg()
186 i := v.Aux.(s390x.RotateParams)
187 p := s.Prog(v.Op.Asm())
188 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(i.Start)}
189 p.AddRestSourceArgs([]obj.Addr{
190 {Type: obj.TYPE_CONST, Offset: int64(i.End)},
191 {Type: obj.TYPE_CONST, Offset: int64(i.Amount)},
192 {Type: obj.TYPE_REG, Reg: r2},
193 })
194 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
195 case ssa.OpS390XRISBGZ:
196 r1 := v.Reg()
197 r2 := v.Args[0].Reg()
198 i := v.Aux.(s390x.RotateParams)
199 p := s.Prog(v.Op.Asm())
200 p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(i.Start)}
201 p.AddRestSourceArgs([]obj.Addr{
202 {Type: obj.TYPE_CONST, Offset: int64(i.End)},
203 {Type: obj.TYPE_CONST, Offset: int64(i.Amount)},
204 {Type: obj.TYPE_REG, Reg: r2},
205 })
206 p.To = obj.Addr{Type: obj.TYPE_REG, Reg: r1}
207 case ssa.OpS390XADD, ssa.OpS390XADDW,
208 ssa.OpS390XSUB, ssa.OpS390XSUBW,
209 ssa.OpS390XAND, ssa.OpS390XANDW,
210 ssa.OpS390XOR, ssa.OpS390XORW,
211 ssa.OpS390XXOR, ssa.OpS390XXORW:
212 r := v.Reg()
213 r1 := v.Args[0].Reg()
214 r2 := v.Args[1].Reg()
215 p := opregreg(s, v.Op.Asm(), r, r2)
216 if r != r1 {
217 p.Reg = r1
218 }
219 case ssa.OpS390XADDC:
220 r1 := v.Reg0()
221 r2 := v.Args[0].Reg()
222 r3 := v.Args[1].Reg()
223 if r1 == r2 {
224 r2, r3 = r3, r2
225 }
226 p := opregreg(s, v.Op.Asm(), r1, r2)
227 if r3 != r1 {
228 p.Reg = r3
229 }
230 case ssa.OpS390XSUBC:
231 r1 := v.Reg0()
232 r2 := v.Args[0].Reg()
233 r3 := v.Args[1].Reg()
234 p := opregreg(s, v.Op.Asm(), r1, r3)
235 if r1 != r2 {
236 p.Reg = r2
237 }
238 case ssa.OpS390XADDE, ssa.OpS390XSUBE:
239 r2 := v.Args[1].Reg()
240 opregreg(s, v.Op.Asm(), v.Reg0(), r2)
241 case ssa.OpS390XADDCconst:
242 r1 := v.Reg0()
243 r3 := v.Args[0].Reg()
244 i2 := int64(int16(v.AuxInt))
245 opregregimm(s, v.Op.Asm(), r1, r3, i2)
246
247 case ssa.OpS390XMULLD, ssa.OpS390XMULLW,
248 ssa.OpS390XMULHD, ssa.OpS390XMULHDU,
249 ssa.OpS390XFMULS, ssa.OpS390XFMUL, ssa.OpS390XFDIVS, ssa.OpS390XFDIV:
250 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
251 case ssa.OpS390XFSUBS, ssa.OpS390XFSUB,
252 ssa.OpS390XFADDS, ssa.OpS390XFADD:
253 opregreg(s, v.Op.Asm(), v.Reg0(), v.Args[1].Reg())
254 case ssa.OpS390XMLGR:
255
256 r0 := v.Args[0].Reg()
257 r1 := v.Args[1].Reg()
258 if r1 != s390x.REG_R3 {
259 v.Fatalf("We require the multiplcand to be stored in R3 for MLGR %s", v.LongString())
260 }
261 p := s.Prog(s390x.AMLGR)
262 p.From.Type = obj.TYPE_REG
263 p.From.Reg = r0
264 p.To.Reg = s390x.REG_R2
265 p.To.Type = obj.TYPE_REG
266 case ssa.OpS390XFMADD, ssa.OpS390XFMADDS,
267 ssa.OpS390XFMSUB, ssa.OpS390XFMSUBS:
268 r1 := v.Args[1].Reg()
269 r2 := v.Args[2].Reg()
270 p := s.Prog(v.Op.Asm())
271 p.From.Type = obj.TYPE_REG
272 p.From.Reg = r1
273 p.Reg = r2
274 p.To.Type = obj.TYPE_REG
275 p.To.Reg = v.Reg()
276 case ssa.OpS390XFIDBR:
277 switch v.AuxInt {
278 case 0, 1, 3, 4, 5, 6, 7:
279 opregregimm(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg(), v.AuxInt)
280 default:
281 v.Fatalf("invalid FIDBR mask: %v", v.AuxInt)
282 }
283 case ssa.OpS390XCPSDR:
284 p := opregreg(s, v.Op.Asm(), v.Reg(), v.Args[1].Reg())
285 p.Reg = v.Args[0].Reg()
286 case ssa.OpS390XWFMAXDB, ssa.OpS390XWFMAXSB,
287 ssa.OpS390XWFMINDB, ssa.OpS390XWFMINSB:
288 p := opregregimm(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg(), 1 )
289 p.AddRestSource(obj.Addr{Type: obj.TYPE_REG, Reg: v.Args[1].Reg()})
290 case ssa.OpS390XDIVD, ssa.OpS390XDIVW,
291 ssa.OpS390XDIVDU, ssa.OpS390XDIVWU,
292 ssa.OpS390XMODD, ssa.OpS390XMODW,
293 ssa.OpS390XMODDU, ssa.OpS390XMODWU:
294
295
296 dividend := v.Args[0].Reg()
297 divisor := v.Args[1].Reg()
298
299
300
301 var j *obj.Prog
302 if v.Op == ssa.OpS390XDIVD || v.Op == ssa.OpS390XDIVW ||
303 v.Op == ssa.OpS390XMODD || v.Op == ssa.OpS390XMODW {
304
305 var c *obj.Prog
306 c = s.Prog(s390x.ACMP)
307 j = s.Prog(s390x.ABEQ)
308
309 c.From.Type = obj.TYPE_REG
310 c.From.Reg = divisor
311 c.To.Type = obj.TYPE_CONST
312 c.To.Offset = -1
313
314 j.To.Type = obj.TYPE_BRANCH
315
316 }
317
318 p := s.Prog(v.Op.Asm())
319 p.From.Type = obj.TYPE_REG
320 p.From.Reg = divisor
321 p.Reg = 0
322 p.To.Type = obj.TYPE_REG
323 p.To.Reg = dividend
324
325
326 if j != nil {
327 j2 := s.Prog(s390x.ABR)
328 j2.To.Type = obj.TYPE_BRANCH
329
330 var n *obj.Prog
331 if v.Op == ssa.OpS390XDIVD || v.Op == ssa.OpS390XDIVW {
332
333 n = s.Prog(s390x.ANEG)
334 n.To.Type = obj.TYPE_REG
335 n.To.Reg = dividend
336 } else {
337
338 n = s.Prog(s390x.AXOR)
339 n.From.Type = obj.TYPE_REG
340 n.From.Reg = dividend
341 n.To.Type = obj.TYPE_REG
342 n.To.Reg = dividend
343 }
344
345 j.To.SetTarget(n)
346 j2.To.SetTarget(s.Pc())
347 }
348 case ssa.OpS390XADDconst, ssa.OpS390XADDWconst:
349 opregregimm(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg(), v.AuxInt)
350 case ssa.OpS390XMULLDconst, ssa.OpS390XMULLWconst,
351 ssa.OpS390XSUBconst, ssa.OpS390XSUBWconst,
352 ssa.OpS390XANDconst, ssa.OpS390XANDWconst,
353 ssa.OpS390XORconst, ssa.OpS390XORWconst,
354 ssa.OpS390XXORconst, ssa.OpS390XXORWconst:
355 p := s.Prog(v.Op.Asm())
356 p.From.Type = obj.TYPE_CONST
357 p.From.Offset = v.AuxInt
358 p.To.Type = obj.TYPE_REG
359 p.To.Reg = v.Reg()
360 case ssa.OpS390XSLDconst, ssa.OpS390XSLWconst,
361 ssa.OpS390XSRDconst, ssa.OpS390XSRWconst,
362 ssa.OpS390XSRADconst, ssa.OpS390XSRAWconst,
363 ssa.OpS390XRLLconst:
364 p := s.Prog(v.Op.Asm())
365 p.From.Type = obj.TYPE_CONST
366 p.From.Offset = v.AuxInt
367 r := v.Reg()
368 r1 := v.Args[0].Reg()
369 if r != r1 {
370 p.Reg = r1
371 }
372 p.To.Type = obj.TYPE_REG
373 p.To.Reg = r
374 case ssa.OpS390XMOVDaddridx:
375 r := v.Args[0].Reg()
376 i := v.Args[1].Reg()
377 p := s.Prog(s390x.AMOVD)
378 p.From.Scale = 1
379 if i == s390x.REGSP {
380 r, i = i, r
381 }
382 p.From.Type = obj.TYPE_ADDR
383 p.From.Reg = r
384 p.From.Index = i
385 ssagen.AddAux(&p.From, v)
386 p.To.Type = obj.TYPE_REG
387 p.To.Reg = v.Reg()
388 case ssa.OpS390XMOVDaddr:
389 p := s.Prog(s390x.AMOVD)
390 p.From.Type = obj.TYPE_ADDR
391 p.From.Reg = v.Args[0].Reg()
392 ssagen.AddAux(&p.From, v)
393 p.To.Type = obj.TYPE_REG
394 p.To.Reg = v.Reg()
395 case ssa.OpS390XCMP, ssa.OpS390XCMPW, ssa.OpS390XCMPU, ssa.OpS390XCMPWU:
396 opregreg(s, v.Op.Asm(), v.Args[1].Reg(), v.Args[0].Reg())
397 case ssa.OpS390XFCMPS, ssa.OpS390XFCMP:
398 opregreg(s, v.Op.Asm(), v.Args[1].Reg(), v.Args[0].Reg())
399 case ssa.OpS390XCMPconst, ssa.OpS390XCMPWconst:
400 p := s.Prog(v.Op.Asm())
401 p.From.Type = obj.TYPE_REG
402 p.From.Reg = v.Args[0].Reg()
403 p.To.Type = obj.TYPE_CONST
404 p.To.Offset = v.AuxInt
405 case ssa.OpS390XCMPUconst, ssa.OpS390XCMPWUconst:
406 p := s.Prog(v.Op.Asm())
407 p.From.Type = obj.TYPE_REG
408 p.From.Reg = v.Args[0].Reg()
409 p.To.Type = obj.TYPE_CONST
410 p.To.Offset = int64(uint32(v.AuxInt))
411 case ssa.OpS390XMOVDconst:
412 x := v.Reg()
413 p := s.Prog(v.Op.Asm())
414 p.From.Type = obj.TYPE_CONST
415 p.From.Offset = v.AuxInt
416 p.To.Type = obj.TYPE_REG
417 p.To.Reg = x
418 case ssa.OpS390XFMOVSconst, ssa.OpS390XFMOVDconst:
419 x := v.Reg()
420 p := s.Prog(v.Op.Asm())
421 p.From.Type = obj.TYPE_FCONST
422 p.From.Val = math.Float64frombits(uint64(v.AuxInt))
423 p.To.Type = obj.TYPE_REG
424 p.To.Reg = x
425 case ssa.OpS390XADDWload, ssa.OpS390XADDload,
426 ssa.OpS390XMULLWload, ssa.OpS390XMULLDload,
427 ssa.OpS390XSUBWload, ssa.OpS390XSUBload,
428 ssa.OpS390XANDWload, ssa.OpS390XANDload,
429 ssa.OpS390XORWload, ssa.OpS390XORload,
430 ssa.OpS390XXORWload, ssa.OpS390XXORload:
431 p := s.Prog(v.Op.Asm())
432 p.From.Type = obj.TYPE_MEM
433 p.From.Reg = v.Args[1].Reg()
434 ssagen.AddAux(&p.From, v)
435 p.To.Type = obj.TYPE_REG
436 p.To.Reg = v.Reg()
437 case ssa.OpS390XMOVDload,
438 ssa.OpS390XMOVWZload, ssa.OpS390XMOVHZload, ssa.OpS390XMOVBZload,
439 ssa.OpS390XMOVDBRload, ssa.OpS390XMOVWBRload, ssa.OpS390XMOVHBRload,
440 ssa.OpS390XMOVBload, ssa.OpS390XMOVHload, ssa.OpS390XMOVWload,
441 ssa.OpS390XFMOVSload, ssa.OpS390XFMOVDload:
442 p := s.Prog(v.Op.Asm())
443 p.From.Type = obj.TYPE_MEM
444 p.From.Reg = v.Args[0].Reg()
445 ssagen.AddAux(&p.From, v)
446 p.To.Type = obj.TYPE_REG
447 p.To.Reg = v.Reg()
448 case ssa.OpS390XMOVBZloadidx, ssa.OpS390XMOVHZloadidx, ssa.OpS390XMOVWZloadidx,
449 ssa.OpS390XMOVBloadidx, ssa.OpS390XMOVHloadidx, ssa.OpS390XMOVWloadidx, ssa.OpS390XMOVDloadidx,
450 ssa.OpS390XMOVHBRloadidx, ssa.OpS390XMOVWBRloadidx, ssa.OpS390XMOVDBRloadidx,
451 ssa.OpS390XFMOVSloadidx, ssa.OpS390XFMOVDloadidx:
452 r := v.Args[0].Reg()
453 i := v.Args[1].Reg()
454 if i == s390x.REGSP {
455 r, i = i, r
456 }
457 p := s.Prog(v.Op.Asm())
458 p.From.Type = obj.TYPE_MEM
459 p.From.Reg = r
460 p.From.Scale = 1
461 p.From.Index = i
462 ssagen.AddAux(&p.From, v)
463 p.To.Type = obj.TYPE_REG
464 p.To.Reg = v.Reg()
465 case ssa.OpS390XMOVBstore, ssa.OpS390XMOVHstore, ssa.OpS390XMOVWstore, ssa.OpS390XMOVDstore,
466 ssa.OpS390XMOVHBRstore, ssa.OpS390XMOVWBRstore, ssa.OpS390XMOVDBRstore,
467 ssa.OpS390XFMOVSstore, ssa.OpS390XFMOVDstore:
468 p := s.Prog(v.Op.Asm())
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 ssagen.AddAux(&p.To, v)
474 case ssa.OpS390XMOVBstoreidx, ssa.OpS390XMOVHstoreidx, ssa.OpS390XMOVWstoreidx, ssa.OpS390XMOVDstoreidx,
475 ssa.OpS390XMOVHBRstoreidx, ssa.OpS390XMOVWBRstoreidx, ssa.OpS390XMOVDBRstoreidx,
476 ssa.OpS390XFMOVSstoreidx, ssa.OpS390XFMOVDstoreidx:
477 r := v.Args[0].Reg()
478 i := v.Args[1].Reg()
479 if i == s390x.REGSP {
480 r, i = i, r
481 }
482 p := s.Prog(v.Op.Asm())
483 p.From.Type = obj.TYPE_REG
484 p.From.Reg = v.Args[2].Reg()
485 p.To.Type = obj.TYPE_MEM
486 p.To.Reg = r
487 p.To.Scale = 1
488 p.To.Index = i
489 ssagen.AddAux(&p.To, v)
490 case ssa.OpS390XMOVDstoreconst, ssa.OpS390XMOVWstoreconst, ssa.OpS390XMOVHstoreconst, ssa.OpS390XMOVBstoreconst:
491 p := s.Prog(v.Op.Asm())
492 p.From.Type = obj.TYPE_CONST
493 sc := v.AuxValAndOff()
494 p.From.Offset = sc.Val64()
495 p.To.Type = obj.TYPE_MEM
496 p.To.Reg = v.Args[0].Reg()
497 ssagen.AddAux2(&p.To, v, sc.Off64())
498 case ssa.OpS390XMOVBreg, ssa.OpS390XMOVHreg, ssa.OpS390XMOVWreg,
499 ssa.OpS390XMOVBZreg, ssa.OpS390XMOVHZreg, ssa.OpS390XMOVWZreg,
500 ssa.OpS390XLDGR, ssa.OpS390XLGDR,
501 ssa.OpS390XCEFBRA, ssa.OpS390XCDFBRA, ssa.OpS390XCEGBRA, ssa.OpS390XCDGBRA,
502 ssa.OpS390XCFEBRA, ssa.OpS390XCFDBRA, ssa.OpS390XCGEBRA, ssa.OpS390XCGDBRA,
503 ssa.OpS390XCELFBR, ssa.OpS390XCDLFBR, ssa.OpS390XCELGBR, ssa.OpS390XCDLGBR,
504 ssa.OpS390XCLFEBR, ssa.OpS390XCLFDBR, ssa.OpS390XCLGEBR, ssa.OpS390XCLGDBR,
505 ssa.OpS390XLDEBR, ssa.OpS390XLEDBR,
506 ssa.OpS390XFNEG, ssa.OpS390XFNEGS,
507 ssa.OpS390XLPDFR, ssa.OpS390XLNDFR:
508 opregreg(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg())
509 case ssa.OpS390XCLEAR:
510 p := s.Prog(v.Op.Asm())
511 p.From.Type = obj.TYPE_CONST
512 sc := v.AuxValAndOff()
513 p.From.Offset = sc.Val64()
514 p.To.Type = obj.TYPE_MEM
515 p.To.Reg = v.Args[0].Reg()
516 ssagen.AddAux2(&p.To, v, sc.Off64())
517 case ssa.OpCopy:
518 if v.Type.IsMemory() {
519 return
520 }
521 x := v.Args[0].Reg()
522 y := v.Reg()
523 if x != y {
524 opregreg(s, moveByType(v.Type), y, x)
525 }
526 case ssa.OpLoadReg:
527 if v.Type.IsFlags() {
528 v.Fatalf("load flags not implemented: %v", v.LongString())
529 return
530 }
531 p := s.Prog(loadByType(v.Type))
532 ssagen.AddrAuto(&p.From, v.Args[0])
533 p.To.Type = obj.TYPE_REG
534 p.To.Reg = v.Reg()
535 case ssa.OpStoreReg:
536 if v.Type.IsFlags() {
537 v.Fatalf("store flags not implemented: %v", v.LongString())
538 return
539 }
540 p := s.Prog(storeByType(v.Type))
541 p.From.Type = obj.TYPE_REG
542 p.From.Reg = v.Args[0].Reg()
543 ssagen.AddrAuto(&p.To, v)
544 case ssa.OpArgIntReg, ssa.OpArgFloatReg:
545
546
547 for _, a := range v.Block.Func.RegArgs {
548
549
550 addr := ssagen.SpillSlotAddr(a, s390x.REGSP, base.Ctxt.Arch.FixedFrameSize)
551 s.FuncInfo().AddSpill(
552 obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)})
553 }
554 v.Block.Func.RegArgs = nil
555
556 ssagen.CheckArgReg(v)
557 case ssa.OpS390XLoweredGetClosurePtr:
558
559 ssagen.CheckLoweredGetClosurePtr(v)
560 case ssa.OpS390XLoweredRound32F, ssa.OpS390XLoweredRound64F:
561
562 case ssa.OpS390XLoweredGetG:
563 r := v.Reg()
564 p := s.Prog(s390x.AMOVD)
565 p.From.Type = obj.TYPE_REG
566 p.From.Reg = s390x.REGG
567 p.To.Type = obj.TYPE_REG
568 p.To.Reg = r
569 case ssa.OpS390XLoweredGetCallerSP:
570
571 p := s.Prog(s390x.AMOVD)
572 p.From.Type = obj.TYPE_ADDR
573 p.From.Offset = -base.Ctxt.Arch.FixedFrameSize
574 p.From.Name = obj.NAME_PARAM
575 p.To.Type = obj.TYPE_REG
576 p.To.Reg = v.Reg()
577 case ssa.OpS390XLoweredGetCallerPC:
578 p := s.Prog(obj.AGETCALLERPC)
579 p.To.Type = obj.TYPE_REG
580 p.To.Reg = v.Reg()
581 case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter:
582 s.Call(v)
583 case ssa.OpS390XCALLtail:
584 s.TailCall(v)
585 case ssa.OpS390XLoweredWB:
586 p := s.Prog(obj.ACALL)
587 p.To.Type = obj.TYPE_MEM
588 p.To.Name = obj.NAME_EXTERN
589
590 p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
591
592 case ssa.OpS390XLoweredPanicBoundsRR, ssa.OpS390XLoweredPanicBoundsRC, ssa.OpS390XLoweredPanicBoundsCR, ssa.OpS390XLoweredPanicBoundsCC:
593
594 code, signed := ssa.BoundsKind(v.AuxInt).Code()
595 xIsReg := false
596 yIsReg := false
597 xVal := 0
598 yVal := 0
599 switch v.Op {
600 case ssa.OpS390XLoweredPanicBoundsRR:
601 xIsReg = true
602 xVal = int(v.Args[0].Reg() - s390x.REG_R0)
603 yIsReg = true
604 yVal = int(v.Args[1].Reg() - s390x.REG_R0)
605 case ssa.OpS390XLoweredPanicBoundsRC:
606 xIsReg = true
607 xVal = int(v.Args[0].Reg() - s390x.REG_R0)
608 c := v.Aux.(ssa.PanicBoundsC).C
609 if c >= 0 && c <= abi.BoundsMaxConst {
610 yVal = int(c)
611 } else {
612
613 yIsReg = true
614 if yVal == xVal {
615 yVal = 1
616 }
617 p := s.Prog(s390x.AMOVD)
618 p.From.Type = obj.TYPE_CONST
619 p.From.Offset = c
620 p.To.Type = obj.TYPE_REG
621 p.To.Reg = s390x.REG_R0 + int16(yVal)
622 }
623 case ssa.OpS390XLoweredPanicBoundsCR:
624 yIsReg = true
625 yVal = int(v.Args[0].Reg() - s390x.REG_R0)
626 c := v.Aux.(ssa.PanicBoundsC).C
627 if c >= 0 && c <= abi.BoundsMaxConst {
628 xVal = int(c)
629 } else {
630
631 if xVal == yVal {
632 xVal = 1
633 }
634 p := s.Prog(s390x.AMOVD)
635 p.From.Type = obj.TYPE_CONST
636 p.From.Offset = c
637 p.To.Type = obj.TYPE_REG
638 p.To.Reg = s390x.REG_R0 + int16(xVal)
639 }
640 case ssa.OpS390XLoweredPanicBoundsCC:
641 c := v.Aux.(ssa.PanicBoundsCC).Cx
642 if c >= 0 && c <= abi.BoundsMaxConst {
643 xVal = int(c)
644 } else {
645
646 xIsReg = true
647 p := s.Prog(s390x.AMOVD)
648 p.From.Type = obj.TYPE_CONST
649 p.From.Offset = c
650 p.To.Type = obj.TYPE_REG
651 p.To.Reg = s390x.REG_R0 + int16(xVal)
652 }
653 c = v.Aux.(ssa.PanicBoundsCC).Cy
654 if c >= 0 && c <= abi.BoundsMaxConst {
655 yVal = int(c)
656 } else {
657
658 yIsReg = true
659 yVal = 1
660 p := s.Prog(s390x.AMOVD)
661 p.From.Type = obj.TYPE_CONST
662 p.From.Offset = c
663 p.To.Type = obj.TYPE_REG
664 p.To.Reg = s390x.REG_R0 + int16(yVal)
665 }
666 }
667 c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
668
669 p := s.Prog(obj.APCDATA)
670 p.From.SetConst(abi.PCDATA_PanicBounds)
671 p.To.SetConst(int64(c))
672 p = s.Prog(obj.ACALL)
673 p.To.Type = obj.TYPE_MEM
674 p.To.Name = obj.NAME_EXTERN
675 p.To.Sym = ir.Syms.PanicBounds
676
677 case ssa.OpS390XFLOGR, ssa.OpS390XPOPCNT,
678 ssa.OpS390XNEG, ssa.OpS390XNEGW,
679 ssa.OpS390XMOVWBR, ssa.OpS390XMOVDBR:
680 p := s.Prog(v.Op.Asm())
681 p.From.Type = obj.TYPE_REG
682 p.From.Reg = v.Args[0].Reg()
683 p.To.Type = obj.TYPE_REG
684 p.To.Reg = v.Reg()
685 case ssa.OpS390XNOT, ssa.OpS390XNOTW:
686 v.Fatalf("NOT/NOTW generated %s", v.LongString())
687 case ssa.OpS390XSumBytes2, ssa.OpS390XSumBytes4, ssa.OpS390XSumBytes8:
688 v.Fatalf("SumBytes generated %s", v.LongString())
689 case ssa.OpS390XLOCGR:
690 p := s.Prog(v.Op.Asm())
691 p.From.Type = obj.TYPE_CONST
692 p.From.Offset = int64(v.Aux.(s390x.CCMask))
693 p.Reg = v.Args[1].Reg()
694 p.To.Type = obj.TYPE_REG
695 p.To.Reg = v.Reg()
696 case ssa.OpS390XFSQRTS, ssa.OpS390XFSQRT:
697 p := s.Prog(v.Op.Asm())
698 p.From.Type = obj.TYPE_REG
699 p.From.Reg = v.Args[0].Reg()
700 p.To.Type = obj.TYPE_REG
701 p.To.Reg = v.Reg()
702 case ssa.OpS390XLTDBR, ssa.OpS390XLTEBR:
703 opregreg(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[0].Reg())
704 case ssa.OpS390XInvertFlags:
705 v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
706 case ssa.OpS390XFlagEQ, ssa.OpS390XFlagLT, ssa.OpS390XFlagGT, ssa.OpS390XFlagOV:
707 v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
708 case ssa.OpS390XAddTupleFirst32, ssa.OpS390XAddTupleFirst64:
709 v.Fatalf("AddTupleFirst* should never make it to codegen %v", v.LongString())
710 case ssa.OpS390XLoweredNilCheck:
711
712 p := s.Prog(s390x.AMOVBZ)
713 p.From.Type = obj.TYPE_MEM
714 p.From.Reg = v.Args[0].Reg()
715 ssagen.AddAux(&p.From, v)
716 p.To.Type = obj.TYPE_REG
717 p.To.Reg = s390x.REGTMP
718 if logopt.Enabled() {
719 logopt.LogOpt(v.Pos, "nilcheck", "genssa", v.Block.Func.Name)
720 }
721 if base.Debug.Nil != 0 && v.Pos.Line() > 1 {
722 base.WarnfAt(v.Pos, "generated nil check")
723 }
724 case ssa.OpS390XMVC:
725 vo := v.AuxValAndOff()
726 p := s.Prog(s390x.AMVC)
727 p.From.Type = obj.TYPE_CONST
728 p.From.Offset = vo.Val64()
729 p.AddRestSource(obj.Addr{
730 Type: obj.TYPE_MEM,
731 Reg: v.Args[1].Reg(),
732 Offset: vo.Off64(),
733 })
734 p.To.Type = obj.TYPE_MEM
735 p.To.Reg = v.Args[0].Reg()
736 p.To.Offset = vo.Off64()
737 case ssa.OpS390XSTMG2, ssa.OpS390XSTMG3, ssa.OpS390XSTMG4,
738 ssa.OpS390XSTM2, ssa.OpS390XSTM3, ssa.OpS390XSTM4:
739 for i := 2; i < len(v.Args)-1; i++ {
740 if v.Args[i].Reg() != v.Args[i-1].Reg()+1 {
741 v.Fatalf("invalid store multiple %s", v.LongString())
742 }
743 }
744 p := s.Prog(v.Op.Asm())
745 p.From.Type = obj.TYPE_REG
746 p.From.Reg = v.Args[1].Reg()
747 p.Reg = v.Args[len(v.Args)-2].Reg()
748 p.To.Type = obj.TYPE_MEM
749 p.To.Reg = v.Args[0].Reg()
750 ssagen.AddAux(&p.To, v)
751 case ssa.OpS390XLoweredMove:
752
753
754
755
756
757
758
759
760
761
762
763 mvc := s.Prog(s390x.AMVC)
764 mvc.From.Type = obj.TYPE_CONST
765 mvc.From.Offset = 256
766 mvc.AddRestSource(obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()})
767 mvc.To.Type = obj.TYPE_MEM
768 mvc.To.Reg = v.Args[0].Reg()
769
770 for i := 0; i < 2; i++ {
771 movd := s.Prog(s390x.AMOVD)
772 movd.From.Type = obj.TYPE_ADDR
773 movd.From.Reg = v.Args[i].Reg()
774 movd.From.Offset = 256
775 movd.To.Type = obj.TYPE_REG
776 movd.To.Reg = v.Args[i].Reg()
777 }
778
779 cmpu := s.Prog(s390x.ACMPU)
780 cmpu.From.Reg = v.Args[1].Reg()
781 cmpu.From.Type = obj.TYPE_REG
782 cmpu.To.Reg = v.Args[2].Reg()
783 cmpu.To.Type = obj.TYPE_REG
784
785 bne := s.Prog(s390x.ABLT)
786 bne.To.Type = obj.TYPE_BRANCH
787 bne.To.SetTarget(mvc)
788
789 if v.AuxInt > 0 {
790 mvc := s.Prog(s390x.AMVC)
791 mvc.From.Type = obj.TYPE_CONST
792 mvc.From.Offset = v.AuxInt
793 mvc.AddRestSource(obj.Addr{Type: obj.TYPE_MEM, Reg: v.Args[1].Reg()})
794 mvc.To.Type = obj.TYPE_MEM
795 mvc.To.Reg = v.Args[0].Reg()
796 }
797 case ssa.OpS390XLoweredZero:
798
799
800
801
802
803
804
805
806
807
808 clear := s.Prog(s390x.ACLEAR)
809 clear.From.Type = obj.TYPE_CONST
810 clear.From.Offset = 256
811 clear.To.Type = obj.TYPE_MEM
812 clear.To.Reg = v.Args[0].Reg()
813
814 movd := s.Prog(s390x.AMOVD)
815 movd.From.Type = obj.TYPE_ADDR
816 movd.From.Reg = v.Args[0].Reg()
817 movd.From.Offset = 256
818 movd.To.Type = obj.TYPE_REG
819 movd.To.Reg = v.Args[0].Reg()
820
821 cmpu := s.Prog(s390x.ACMPU)
822 cmpu.From.Reg = v.Args[0].Reg()
823 cmpu.From.Type = obj.TYPE_REG
824 cmpu.To.Reg = v.Args[1].Reg()
825 cmpu.To.Type = obj.TYPE_REG
826
827 bne := s.Prog(s390x.ABLT)
828 bne.To.Type = obj.TYPE_BRANCH
829 bne.To.SetTarget(clear)
830
831 if v.AuxInt > 0 {
832 clear := s.Prog(s390x.ACLEAR)
833 clear.From.Type = obj.TYPE_CONST
834 clear.From.Offset = v.AuxInt
835 clear.To.Type = obj.TYPE_MEM
836 clear.To.Reg = v.Args[0].Reg()
837 }
838 case ssa.OpS390XMOVBZatomicload, ssa.OpS390XMOVWZatomicload, ssa.OpS390XMOVDatomicload:
839 p := s.Prog(v.Op.Asm())
840 p.From.Type = obj.TYPE_MEM
841 p.From.Reg = v.Args[0].Reg()
842 ssagen.AddAux(&p.From, v)
843 p.To.Type = obj.TYPE_REG
844 p.To.Reg = v.Reg0()
845 case ssa.OpS390XMOVBatomicstore, ssa.OpS390XMOVWatomicstore, ssa.OpS390XMOVDatomicstore:
846 p := s.Prog(v.Op.Asm())
847 p.From.Type = obj.TYPE_REG
848 p.From.Reg = v.Args[1].Reg()
849 p.To.Type = obj.TYPE_MEM
850 p.To.Reg = v.Args[0].Reg()
851 ssagen.AddAux(&p.To, v)
852 case ssa.OpS390XLAN, ssa.OpS390XLAO:
853
854 op := s.Prog(v.Op.Asm())
855 op.From.Type = obj.TYPE_REG
856 op.From.Reg = v.Args[1].Reg()
857 op.Reg = s390x.REGTMP
858 op.To.Type = obj.TYPE_MEM
859 op.To.Reg = v.Args[0].Reg()
860 case ssa.OpS390XLANfloor, ssa.OpS390XLAOfloor:
861 r := v.Args[0].Reg()
862
863
864
865 ptr := s.Prog(s390x.AANDW)
866 ptr.From.Type = obj.TYPE_CONST
867 ptr.From.Offset = 0xfffffffc
868 ptr.To.Type = obj.TYPE_REG
869 ptr.To.Reg = r
870
871
872
873 op := s.Prog(v.Op.Asm())
874 op.From.Type = obj.TYPE_REG
875 op.From.Reg = v.Args[1].Reg()
876 op.Reg = r
877 op.To.Type = obj.TYPE_MEM
878 op.To.Reg = r
879 case ssa.OpS390XLAA, ssa.OpS390XLAAG:
880 p := s.Prog(v.Op.Asm())
881 p.Reg = v.Reg0()
882 p.From.Type = obj.TYPE_REG
883 p.From.Reg = v.Args[1].Reg()
884 p.To.Type = obj.TYPE_MEM
885 p.To.Reg = v.Args[0].Reg()
886 ssagen.AddAux(&p.To, v)
887 case ssa.OpS390XLoweredAtomicCas32, ssa.OpS390XLoweredAtomicCas64:
888
889
890
891
892
893
894
895
896 cs := s.Prog(v.Op.Asm())
897 cs.From.Type = obj.TYPE_REG
898 cs.From.Reg = v.Args[1].Reg()
899 cs.Reg = v.Args[2].Reg()
900 cs.To.Type = obj.TYPE_MEM
901 cs.To.Reg = v.Args[0].Reg()
902 ssagen.AddAux(&cs.To, v)
903
904
905 movd := s.Prog(s390x.AMOVD)
906 movd.From.Type = obj.TYPE_CONST
907 movd.From.Offset = 0
908 movd.To.Type = obj.TYPE_REG
909 movd.To.Reg = v.Reg0()
910
911
912 bne := s.Prog(s390x.ABNE)
913 bne.To.Type = obj.TYPE_BRANCH
914
915
916 movd = s.Prog(s390x.AMOVD)
917 movd.From.Type = obj.TYPE_CONST
918 movd.From.Offset = 1
919 movd.To.Type = obj.TYPE_REG
920 movd.To.Reg = v.Reg0()
921
922
923 nop := s.Prog(obj.ANOP)
924 bne.To.SetTarget(nop)
925 case ssa.OpS390XLoweredAtomicExchange32, ssa.OpS390XLoweredAtomicExchange64:
926
927
928
929
930
931
932 load := s.Prog(loadByType(v.Type.FieldType(0)))
933 load.From.Type = obj.TYPE_MEM
934 load.From.Reg = v.Args[0].Reg()
935 load.To.Type = obj.TYPE_REG
936 load.To.Reg = v.Reg0()
937 ssagen.AddAux(&load.From, v)
938
939
940 cs := s.Prog(v.Op.Asm())
941 cs.From.Type = obj.TYPE_REG
942 cs.From.Reg = v.Reg0()
943 cs.Reg = v.Args[1].Reg()
944 cs.To.Type = obj.TYPE_MEM
945 cs.To.Reg = v.Args[0].Reg()
946 ssagen.AddAux(&cs.To, v)
947
948
949 bne := s.Prog(s390x.ABNE)
950 bne.To.Type = obj.TYPE_BRANCH
951 bne.To.SetTarget(cs)
952 case ssa.OpS390XSYNC:
953 s.Prog(s390x.ASYNC)
954 case ssa.OpClobber, ssa.OpClobberReg:
955
956 default:
957 v.Fatalf("genValue not implemented: %s", v.LongString())
958 }
959 }
960
961 func blockAsm(b *ssa.Block) obj.As {
962 switch b.Kind {
963 case ssa.BlockS390XBRC:
964 return s390x.ABRC
965 case ssa.BlockS390XCRJ:
966 return s390x.ACRJ
967 case ssa.BlockS390XCGRJ:
968 return s390x.ACGRJ
969 case ssa.BlockS390XCLRJ:
970 return s390x.ACLRJ
971 case ssa.BlockS390XCLGRJ:
972 return s390x.ACLGRJ
973 case ssa.BlockS390XCIJ:
974 return s390x.ACIJ
975 case ssa.BlockS390XCGIJ:
976 return s390x.ACGIJ
977 case ssa.BlockS390XCLIJ:
978 return s390x.ACLIJ
979 case ssa.BlockS390XCLGIJ:
980 return s390x.ACLGIJ
981 }
982 b.Fatalf("blockAsm not implemented: %s", b.LongString())
983 panic("unreachable")
984 }
985
986 func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
987
988 switch b.Kind {
989 case ssa.BlockPlain, ssa.BlockDefer:
990 if b.Succs[0].Block() != next {
991 p := s.Prog(s390x.ABR)
992 p.To.Type = obj.TYPE_BRANCH
993 s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()})
994 }
995 return
996 case ssa.BlockExit, ssa.BlockRetJmp:
997 return
998 case ssa.BlockRet:
999 s.Prog(obj.ARET)
1000 return
1001 }
1002
1003
1004
1005 succs := [...]*ssa.Block{b.Succs[0].Block(), b.Succs[1].Block()}
1006 mask := b.Aux.(s390x.CCMask)
1007
1008
1009
1010
1011
1012
1013 if next == succs[0] {
1014 succs[0], succs[1] = succs[1], succs[0]
1015 mask = mask.Inverse()
1016 }
1017
1018 p := s.Br(blockAsm(b), succs[0])
1019 switch b.Kind {
1020 case ssa.BlockS390XBRC:
1021 p.From.Type = obj.TYPE_CONST
1022 p.From.Offset = int64(mask)
1023 case ssa.BlockS390XCGRJ, ssa.BlockS390XCRJ,
1024 ssa.BlockS390XCLGRJ, ssa.BlockS390XCLRJ:
1025 p.From.Type = obj.TYPE_CONST
1026 p.From.Offset = int64(mask & s390x.NotUnordered)
1027 p.Reg = b.Controls[0].Reg()
1028 p.AddRestSourceReg(b.Controls[1].Reg())
1029 case ssa.BlockS390XCGIJ, ssa.BlockS390XCIJ:
1030 p.From.Type = obj.TYPE_CONST
1031 p.From.Offset = int64(mask & s390x.NotUnordered)
1032 p.Reg = b.Controls[0].Reg()
1033 p.AddRestSourceConst(int64(int8(b.AuxInt)))
1034 case ssa.BlockS390XCLGIJ, ssa.BlockS390XCLIJ:
1035 p.From.Type = obj.TYPE_CONST
1036 p.From.Offset = int64(mask & s390x.NotUnordered)
1037 p.Reg = b.Controls[0].Reg()
1038 p.AddRestSourceConst(int64(uint8(b.AuxInt)))
1039 default:
1040 b.Fatalf("branch not implemented: %s", b.LongString())
1041 }
1042 if next != succs[1] {
1043 s.Br(s390x.ABR, succs[1])
1044 }
1045 }
1046
1047 func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1048 p := s.Prog(loadByType(t))
1049 p.From.Type = obj.TYPE_MEM
1050 p.From.Name = obj.NAME_AUTO
1051 p.From.Sym = n.Linksym()
1052 p.From.Offset = n.FrameOffset() + off
1053 p.To.Type = obj.TYPE_REG
1054 p.To.Reg = reg
1055 return p
1056 }
1057
1058 func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
1059 p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off)
1060 p.To.Name = obj.NAME_PARAM
1061 p.To.Sym = n.Linksym()
1062 p.Pos = p.Pos.WithNotStmt()
1063 return p
1064 }
1065
View as plain text