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