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