1
2
3
4
5 package s390xasm
6
7 import (
8 "fmt"
9 "strconv"
10 "strings"
11 )
12
13 var vectorSize = map[int]string{0: "B", 1: "H", 2: "F", 3: "G", 4: "Q"}
14 var vectorCS = map[int]string{0: "BS", 1: "HS", 2: "FS", 3: "GS"}
15
16
17
18
19
20
21
22
23
24
25 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
26 if symname == nil {
27 symname = func(uint64) (string, uint64) { return "", 0 }
28 }
29
30 var args []string
31 opString := inst.Op.String()
32 op := strings.ToUpper(opString)
33 for i := 0; i < len(inst.Args); i++ {
34 if inst.Args[i] == nil {
35 break
36 }
37 switch inst.Args[i].(type) {
38 case Disp12, Disp20:
39 var temp []string
40 switch inst.Args[i+1].(type) {
41 case Index:
42 for j := 0; j < 3; j++ {
43 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
44 }
45 args = append(args, mem_operandx(temp))
46 i = i + 2
47 case Base:
48 for j := 0; j < 2; j++ {
49 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
50 }
51 args = append(args, mem_operand(temp))
52 i = i + 1
53 case VReg:
54 for j := 0; j < 3; j++ {
55 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
56 }
57 args = append(args, mem_operandv(temp))
58 i = i + 2
59 case Len:
60 for j := 0; j < 3; j++ {
61 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
62 }
63 ar1, ar2 := mem_operandl(temp)
64 args = append(args, ar1, ar2)
65 i = i + 2
66 default:
67 for j := 0; j < 3; j++ {
68 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
69 }
70 args = append(args, mem_operandx(temp))
71 i = i + 2
72 }
73 default:
74 args = append(args, plan9Arg(&inst, pc, symname, inst.Args[i]))
75 }
76 }
77 if strings.HasPrefix(op, "V") || strings.Contains(op, "WFC") || strings.Contains(op, "WFK") {
78 args = args[:len(args)-1]
79 }
80
81 switch inst.Op {
82 default:
83 switch len(args) {
84 case 0:
85 return op
86 case 1:
87 return fmt.Sprintf("%s %s", op, args[0])
88 case 2:
89 if reverseOperandOrder(inst.Op) {
90 args[0], args[1] = args[1], args[0]
91 }
92 case 3:
93 if reverseOperandOrder(inst.Op) {
94 args[0], args[2] = args[2], args[0]
95 } else if reverseAllOperands(inst.Op) {
96 args[0], args[1], args[2] = args[1], args[2], args[0]
97 }
98 case 4:
99 if reverseOperandOrder(inst.Op) {
100 args[0], args[3] = args[3], args[0]
101 } else if reverseAllOperands(inst.Op) {
102 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
103 }
104 }
105 case LCGR, LCGFR:
106 switch inst.Op {
107 case LCGR:
108 op = "NEG"
109 case LCGFR:
110 op = "NEGW"
111 }
112 if args[0] == args[1] {
113 args = args[:1]
114 } else {
115 args[0], args[1] = args[1], args[0]
116 }
117 case LD, LE, LG, LGF, LLGF, LGH, LLGH, LGB, LLGC, LDY, LEY, LRVG, LRV, LRVH:
118 args[0], args[1] = args[1], args[0]
119 switch inst.Op {
120 case LG:
121 op = "MOVD"
122 case LGF:
123 op = "MOVW"
124 case LLGF:
125 op = "MOVWZ"
126 case LGH:
127 op = "MOVH"
128 case LLGH:
129 op = "MOVHZ"
130 case LGB:
131 op = "MOVB"
132 case LLGC:
133 op = "MOVBZ"
134 case LDY, LD:
135 op = "FMOVD"
136 case LEY, LE:
137 op = "FMOVS"
138 case LRVG:
139 op = "MOVDBR"
140 case LRV:
141 op = "MOVWBR"
142 case LRVH:
143 op = "MOVHBR"
144 }
145 case LA, LAY, LARL:
146 args[0], args[1] = args[1], args[0]
147 op = "MOVD"
148
149 case LAA, LAAG, LAAL, LAALG, LAN, LANG, LAX, LAXG, LAO, LAOG:
150 args[0], args[1] = args[1], args[0]
151 case LM, LMY, LMG:
152 switch inst.Op {
153 case LM, LMY:
154 op = "LMY"
155 }
156 args[0], args[1], args[2] = args[2], args[0], args[1]
157
158 case STM, STMY, STMG:
159 switch inst.Op {
160 case STM, STMY:
161 op = "STMY"
162 }
163 case ST, STY, STG, STHY, STCY, STRVG, STRV:
164 switch inst.Op {
165 case ST, STY:
166 op = "MOVW"
167 case STHY:
168 op = "MOVH"
169 case STCY:
170 op = "MOVB"
171 case STG:
172 op = "MOVD"
173 case STRVG:
174 op = "MOVDBR"
175 case STRV:
176 op = "MOVWBR"
177 }
178 case LGR, LGFR, LGHR, LGBR, LLGFR, LLGHR, LLGCR, LRVGR, LRVR, LDR:
179 switch inst.Op {
180 case LGR:
181 op = "MOVD"
182 case LGFR:
183 op = "MOVW"
184 case LGHR:
185 op = "MOVH"
186 case LGBR:
187 op = "MOVB"
188 case LLGFR:
189 op = "MOVWZ"
190 case LLGHR:
191 op = "MOVHZ"
192 case LLGCR:
193 op = "MOVBZ"
194 case LRVGR:
195 op = "MOVDBR"
196 case LRVR:
197 op = "MOVWBR"
198 case LDR:
199 op = "FMOVD"
200 }
201 args[0], args[1] = args[1], args[0]
202 case LZDR:
203 op = "FMOVD"
204 return op + " " + "$0" + ", " + args[0]
205 case LZER:
206 op = "FMOVS"
207 return op + " " + "$0" + ", " + args[0]
208 case STD, STDY, STE, STEY:
209 switch inst.Op {
210 case STD, STDY:
211 op = "FMOVD"
212 case STE, STEY:
213 op = "FMOVS"
214 }
215
216 case LGHI, LLILH, LLIHL, LLIHH, LGFI, LLILF, LLIHF:
217 switch inst.Op {
218 case LGFI:
219 op = "MOVW"
220 case LGHI:
221 num, err := strconv.ParseInt(args[1][1:], 10, 16)
222 if err != nil {
223 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
224 }
225 if num == int64(int8(num)) {
226 op = "MOVB"
227 } else {
228 op = "MOVH"
229 }
230 default:
231 op = "MOVD"
232 }
233 args[0], args[1] = args[1], args[0]
234 case ARK, AGRK, ALGRK:
235 switch inst.Op {
236 case ARK:
237 op = "ADDW"
238 case AGRK:
239 op = "ADD"
240 case ALGRK:
241 op = "ADDC"
242 }
243 if args[0] == args[1] {
244 args[0], args[1] = args[2], args[0]
245 args = args[:2]
246 } else {
247 args[0], args[2] = args[2], args[0]
248 }
249 case AGHIK, AHIK, ALGHSIK:
250 num, err := strconv.ParseInt(args[2][1:], 10, 32)
251 if err != nil {
252 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
253 }
254 switch inst.Op {
255 case AGHIK:
256 if num < 0 {
257 op = "SUB"
258 args[2] = args[2][:1] + args[2][2:]
259 } else {
260 op = "ADD"
261 }
262 case AHIK:
263 op = "ADDW"
264 case ALGHSIK:
265 if num < 0 {
266 op = "SUBC"
267 args[2] = args[2][:1] + args[2][2:]
268 } else {
269 op = "ADDC"
270 }
271 }
272 args[0], args[2] = args[2], args[0]
273 case AGHI, AHI, AGFI, AFI, AR, ALCGR:
274 num, err := strconv.ParseInt(args[1][1:], 10, 32)
275 if err != nil {
276 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
277 }
278 switch inst.Op {
279 case AGHI, AGFI:
280 if num < 0 {
281 op = "SUB"
282 args[1] = args[1][:1] + args[1][2:]
283 } else {
284 op = "ADD"
285 }
286 case AHI, AFI, AR:
287 op = "ADDW"
288 case ALCGR:
289 op = "ADDE"
290 }
291 args[0], args[1] = args[1], args[0]
292 case AEBR, ADBR, DDBR, DEBR, MDBR, MEEBR, SDBR, SEBR, LPDBR, LNDBR, LPDFR, LNDFR, LCDFR, LCEBR, LEDBR, LDEBR, SQDBR, SQEBR:
293 switch inst.Op {
294 case AEBR:
295 op = "FADDS"
296 case ADBR:
297 op = "FADD"
298 case DDBR:
299 op = "FDIV"
300 case DEBR:
301 op = "FDIVS"
302 case MDBR:
303 op = "FMUL"
304 case MEEBR:
305 op = "FMULS"
306 case SDBR:
307 op = "FSUB"
308 case SEBR:
309 op = "FSUBS"
310 case LPDBR:
311 op = "FABS"
312 case LNDBR:
313 op = "FNABS"
314 case LCDFR:
315 op = "FNEG"
316 case LCEBR:
317 op = "FNEGS"
318 case SQDBR:
319 op = "FSQRT"
320 case SQEBR:
321 op = "FSQRTS"
322 }
323 args[0], args[1] = args[1], args[0]
324 case SR, SGR, SLGR, SLFI:
325 switch inst.Op {
326 case SR, SLFI:
327 op = "SUBW"
328 case SGR:
329 op = "SUB"
330 case SLGR:
331 op = "SUBC"
332 }
333 args[0], args[1] = args[1], args[0]
334 case SGRK, SLGRK, SRK:
335 switch inst.Op {
336 case SGRK:
337 op = "SUB"
338 case SLGRK:
339 op = "SUBC"
340 case SRK:
341 op = "SUBW"
342 }
343 if args[0] == args[1] {
344 args[0], args[1] = args[2], args[0]
345 args = args[:2]
346 } else {
347 args[0], args[2] = args[2], args[0]
348 }
349 case SLBGR:
350 op = "SUBE"
351 args[0], args[1] = args[1], args[0]
352 case MADBR:
353 op = "FMADD"
354 args[0], args[1], args[2] = args[1], args[2], args[0]
355 case VFM:
356 op = "WFMDB"
357 args[0], args[1], args[2] = args[1], args[2], args[0]
358 args = args[0:3]
359 case VFS:
360 op = "WFSDB"
361 args[0], args[2] = args[2], args[0]
362 args = args[0:3]
363 case MSGFR, MHI, MSFI, MSGFI:
364 switch inst.Op {
365 case MSGFR, MHI, MSFI:
366 op = "MULLW"
367 case MSGFI:
368 op = "MULLD"
369 }
370 args[0], args[1] = args[1], args[0]
371
372 case NGR, NR, NILL, NILF, NILH, OGR, OR, OILL, OILF, OILH, XGR, XR, XILF:
373 op = bitwise_op(inst.Op)
374 args[0], args[1] = args[1], args[0]
375 switch inst.Op {
376 case NILL:
377 if int(inst.Args[1].(Sign16)) < 0 {
378 op = "ANDW"
379 }
380
381 case NILF:
382 if int(inst.Args[1].(Sign32)) < 0 {
383 op = "AND"
384 }
385 case OILF:
386 if int(inst.Args[1].(Sign32)) < 0 {
387 op = "ORW"
388 }
389 case XILF:
390 if int(inst.Args[1].(Sign32)) < 0 {
391 op = "XORW"
392 }
393 }
394
395 case NGRK, NRK, OGRK, ORK, XGRK, XRK:
396 op = bitwise_op(inst.Op)
397 args[0], args[1], args[2] = args[1], args[2], args[0]
398 case SLLG, SRLG, SLLK, SRLK, RLL, RLLG, SRAK, SRAG:
399 switch inst.Op {
400 case SLLG:
401 op = "SLD"
402 case SRLG:
403 op = "SRD"
404 case SLLK:
405 op = "SLW"
406 case SRLK:
407 op = "SRW"
408 case SRAK:
409 op = "SRAW"
410 case SRAG:
411 op = "SRAD"
412 }
413 args[0], args[2] = args[2], args[0]
414 case TRAP2, SVC:
415 op = "SYSALL"
416 case CR, CLR, CGR, CLGR, KDBR, CDBR, CEBR, CGHI, CHI, CGFI, CLGFI, CFI, CLFI:
417 switch inst.Op {
418 case CGHI, CGFI, CGR:
419 op = "CMP"
420 case CHI, CFI, CR:
421 op = "CMPW"
422 case CLGFI, CLGR:
423 op = "CMPU"
424 case CLFI, CLR:
425 op = "CMPWU"
426 case CDBR:
427 op = "FCMPU"
428 case KDBR:
429 op = "FCMPO"
430 }
431 case CEFBRA, CDFBRA, CEGBRA, CDGBRA, CELFBR, CDLFBR, CELGBR, CDLGBR, CFEBRA, CFDBRA, CGEBRA, CGDBRA, CLFEBR, CLFDBR, CLGEBR, CLGDBR:
432 args[0], args[1] = args[2], args[0]
433 args = args[:2]
434 case CGRJ, CGIJ:
435 mask, err := strconv.Atoi(args[2][1:])
436 if err != nil {
437 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
438 }
439 var check bool
440 switch mask & 0xf {
441 case 2:
442 op = "CMPBGT"
443 check = true
444 case 4:
445 op = "CMPBLT"
446 check = true
447 case 6:
448 op = "CMPBNE"
449 check = true
450 case 8:
451 op = "CMPBEQ"
452 check = true
453 case 10:
454 op = "CMPBGE"
455 check = true
456 case 12:
457 op = "CMPBLE"
458 check = true
459 }
460 if check {
461 args[2] = args[3]
462 args = args[:3]
463 }
464 case CLGRJ, CLGIJ:
465 mask, err := strconv.Atoi(args[2][1:])
466 if err != nil {
467 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
468 }
469 var check bool
470 switch mask & 0xf {
471 case 2:
472 op = "CMPUBGT"
473 check = true
474 case 4:
475 op = "CMPUBLT"
476 check = true
477 case 7:
478 op = "CMPUBNE"
479 check = true
480 case 8:
481 op = "CMPUBEQ"
482 check = true
483 case 10:
484 op = "CMPUBGE"
485 check = true
486 case 12:
487 op = "CMPUBLE"
488 check = true
489 }
490 if check {
491 args[2] = args[3]
492 args = args[:3]
493 }
494 case CLRJ, CRJ, CIJ, CLIJ:
495 args[0], args[1], args[2] = args[2], args[0], args[1]
496 case BRC, BRCL:
497 mask, err := strconv.Atoi(args[0][1:])
498 if err != nil {
499 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
500 }
501 opStr, check := branch_relative_op(mask, inst.Op)
502 if opStr != "" {
503 op = opStr
504 }
505 if check {
506 args[0] = args[1]
507 args = args[:1]
508 }
509 case BCR:
510 mask, err := strconv.Atoi(args[0][1:])
511 if err != nil {
512 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
513 }
514 opStr := branchOnConditionOp(mask, inst.Op)
515 if opStr != "" {
516 op = opStr
517 }
518 if op == "SYNC" || op == "NOPH" {
519 return op
520 }
521 if op == "RET" {
522 args = args[:0]
523 return op
524 }
525 case LOCGR:
526 mask, err := strconv.Atoi(args[2][1:])
527 if err != nil {
528 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
529 }
530 var check bool
531 switch mask & 0xf {
532 case 2:
533 op = "MOVDGT"
534 check = true
535 case 4:
536 op = "MOVDLT"
537 check = true
538 case 7:
539 op = "MOVDNE"
540 check = true
541 case 8:
542 op = "MOVDEQ"
543 check = true
544 case 10:
545 op = "MOVDGE"
546 check = true
547 case 12:
548 op = "MOVDLE"
549 check = true
550 }
551 if check {
552 args[0], args[1] = args[1], args[0]
553 args = args[:2]
554 } else {
555 args[0], args[2] = args[2], args[0]
556 }
557 case BRASL:
558 op = "CALL"
559 args[0] = args[1]
560 args = args[:1]
561 case X, XY, XG:
562 switch inst.Op {
563 case X, XY:
564 op = "XORW"
565 case XG:
566 op = "XOR"
567 }
568 case N, NY, NG, O, OY, OG, XC, NC, OC, MVC, MVCIN, CLC:
569 switch inst.Op {
570 case N, NY:
571 op = "ANDW"
572 case NG:
573 op = "AND"
574 case O, OY:
575 op = "ORW"
576 case OG:
577 op = "OR"
578 }
579 args[0], args[1] = args[1], args[0]
580 case S, SY, SLBG, SLG, SG:
581 switch inst.Op {
582 case S, SY:
583 op = "SUBW"
584 case SLBG:
585 op = "SUBE"
586 case SLG:
587 op = "SUBC"
588 case SG:
589 op = "SUB"
590 }
591 args[0], args[1] = args[1], args[0]
592 case MSG, MSY, MS:
593 switch inst.Op {
594 case MSG:
595 op = "MULLD"
596 case MSY, MS:
597 op = "MULLW"
598 }
599 case A, AY, ALCG, ALG, AG:
600 switch inst.Op {
601 case A, AY:
602 op = "ADDW"
603 case ALCG:
604 op = "ADDE"
605 case ALG:
606 op = "ADDC"
607 case AG:
608 op = "ADD"
609 }
610 args[0], args[1] = args[1], args[0]
611 case RISBG, RISBGN, RISBHG, RISBLG, RNSBG, RXSBG, ROSBG:
612 switch inst.Op {
613 case RNSBG, RXSBG, ROSBG:
614 num, err := strconv.Atoi(args[2][1:])
615 if err != nil {
616 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
617 }
618 if ((num >> 7) & 0x1) != 0 {
619 op = op + "T"
620 }
621 case RISBG, RISBGN, RISBHG, RISBLG:
622 num, err := strconv.Atoi(args[3][1:])
623 if err != nil {
624 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
625 }
626 if ((num >> 7) & 0x1) != 0 {
627 op = op + "Z"
628 }
629 }
630 if len(args) == 5 {
631 args[0], args[1], args[2], args[3], args[4] = args[2], args[3], args[4], args[1], args[0]
632 } else {
633 args[0], args[1], args[2], args[3] = args[2], args[3], args[1], args[0]
634 }
635
636 case VEC, VECL, VCLZ, VCTZ, VREPI, VPOPCT:
637 mask, err := strconv.Atoi(args[2][1:])
638 if err != nil {
639 return fmt.Sprintf("GoSyntax: error in converting Atoi for %q:%s", op, err)
640 }
641 val := mask & 0x7
642 if val >= 0 && val < 4 {
643 op = op + vectorSize[val]
644 args = args[:2]
645 } else {
646 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
647 }
648 switch inst.Op {
649 case VCLZ, VCTZ, VREPI, VPOPCT:
650 args[0], args[1] = args[1], args[0]
651 default:
652 }
653
654 case VA, VS, VACC, VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM, VREP, VERLLV, VESLV, VSCBI, VSUM, VSUMG, VSUMQ, VMH, VMLH, VML, VME, VMLE, VMO, VMLO:
655 mask, err := strconv.Atoi(args[3][1:])
656 if err != nil {
657 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
658 }
659 val := mask & 0x7
660 switch inst.Op {
661 case VA, VS, VACC, VSCBI:
662 if val >= 0 && val < 5 {
663 if args[0] == args[2] {
664 args[0], args[1] = args[1], args[0]
665 args = args[:2]
666 } else if inst.Op == VS {
667 if args[0] == args[1] {
668 args[0] = args[2]
669 args = args[:2]
670 } else {
671 args[0], args[2] = args[2], args[0]
672 args = args[:3]
673 }
674 } else {
675 args[0], args[1], args[2] = args[1], args[2], args[0]
676 args = args[:3]
677 }
678 op = op + vectorSize[val]
679 } else {
680 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
681 }
682 case VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM:
683 if val >= 0 && val < 4 {
684 op = op + vectorSize[val]
685 args[0], args[1], args[2] = args[1], args[2], args[0]
686 args = args[:3]
687 } else {
688 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
689 }
690 case VREP, VERLLV, VESLV:
691 if val >= 0 && val < 4 {
692 op = op + vectorSize[val]
693 args[0], args[2] = args[2], args[0]
694 args = args[:3]
695 } else {
696 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
697 }
698 case VSUM, VSUMG, VSUMQ:
699 var off int
700 switch inst.Op {
701 case VSUM:
702 off = 0
703 case VSUMG:
704 off = 1
705 case VSUMQ:
706 off = 2
707 }
708 if (val > (-1 + off)) && (val < (2 + off)) {
709 op = op + vectorSize[val]
710 } else {
711 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
712 }
713 args = args[:3]
714 case VML, VMH, VMLH, VME, VMLE, VMO, VMLO:
715 if val >= 0 && val < 3 {
716 op = op + vectorSize[val]
717 }
718 if op == "VML" && val == 2 {
719 op = op + "W"
720 }
721 if args[0] == args[2] {
722 args[0], args[1] = args[1], args[0]
723 args = args[:2]
724 } else {
725 args[0], args[1], args[2] = args[1], args[2], args[0]
726 args = args[:3]
727 }
728 }
729
730 case VGFMA, VERIM, VMAH, VMALH:
731 mask, err := strconv.Atoi(args[4][1:])
732 if err != nil {
733 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
734 }
735 val := mask & 0x7
736 args = args[:4]
737 var off int
738 switch inst.Op {
739 case VMAH, VMALH:
740 off = -1
741 }
742
743 if val >= 0 && val < (4+off) {
744 op = op + vectorSize[val]
745 } else {
746 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
747 }
748 switch inst.Op {
749 case VGFMA, VMAH, VMALH:
750 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
751 default:
752 args[0], args[3] = args[3], args[0]
753 }
754 case VSTRC, VFAE, VFEE, VFENE:
755 var off uint8
756 switch inst.Op {
757 case VSTRC:
758 off = uint8(1)
759 default:
760 off = uint8(0)
761 }
762 m1, err := strconv.Atoi(args[3+off][1:])
763 if err != nil {
764 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
765 }
766 m2, err := strconv.Atoi(args[4+off][1:])
767 if err != nil {
768 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
769 }
770 index := m1 & 0x3
771 if index < 0 || index > 2 {
772 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
773 }
774 switch m2 {
775 case 0:
776 op = op + vectorSize[index]
777 case 1:
778 op = op + vectorCS[index]
779 case 2:
780 op = op + "Z" + vectorSize[index]
781 case 3:
782 op = op + "Z" + vectorCS[index]
783 default:
784 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
785 }
786 switch inst.Op {
787 case VSTRC:
788 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
789 default:
790 args[0], args[1], args[2] = args[1], args[2], args[0]
791 }
792 args = args[:3+off]
793
794 case VCEQ, VCH, VCHL:
795 m4, err := strconv.Atoi(args[3][1:])
796 if err != nil {
797 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
798 }
799 m5, err := strconv.Atoi(args[4][1:])
800 if err != nil {
801 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
802 }
803 val := (m4 & 0x7)
804 if m5 == 0 {
805 if val >= 0 && val < 4 {
806 op = op + vectorSize[val]
807 args[0], args[1], args[2] = args[1], args[2], args[0]
808 args = args[:3]
809 } else {
810 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
811 }
812 } else if m5 == 1 {
813 if val >= 0 && val < 4 {
814 op = op + vectorCS[val]
815 args[0], args[1], args[2] = args[1], args[2], args[0]
816 args = args[:3]
817 } else {
818 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
819 }
820 } else {
821 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
822 }
823 case VFMA, VFMS, VMSL:
824 m5, err := strconv.Atoi(args[4][1:])
825 if err != nil {
826 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
827 }
828 m6, err := strconv.Atoi(args[5][1:])
829 if err != nil {
830 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
831 }
832 switch inst.Op {
833 case VMSL:
834 if m5 == 3 && m6 == 8 {
835 op = op + "EG"
836 } else if m5 == 3 && m6 == 4 {
837 op = op + "OG"
838 } else if m5 == 3 && m6 == 12 {
839 op = op + "EOG"
840 } else if m5 == 3 {
841 op = op + "G"
842 }
843 default:
844 if m5 == 0 && m6 == 3 {
845 op = op + "DB"
846 } else if m5 == 8 && m6 == 3 {
847 op = "W" + op[1:] + "DB"
848 } else {
849 return fmt.Sprintf("specification exception is recognized for %q with m5: %v m6: %v \n", op, m5, m6)
850 }
851 }
852 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
853 args = args[:4]
854
855 case VFCE, VFCH, VFCHE:
856 m4, err := strconv.Atoi(args[3][1:])
857 if err != nil {
858 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
859 }
860 m5, err := strconv.Atoi(args[4][1:])
861 if err != nil {
862 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
863 }
864 m6, err := strconv.Atoi(args[5][1:])
865 if err != nil {
866 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
867 }
868 if m5 == 0 {
869 if m4 == 3 && m6 == 0 {
870 op = op + "DB"
871 } else if m4 == 3 && m6 == 1 {
872 op = op + "DBS"
873 } else {
874 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
875 }
876
877 } else if m5 == 8 {
878 if m4 == 3 && m6 == 0 {
879 op = "W" + op[1:] + "DB"
880 } else if m4 == 3 && m6 == 1 {
881 op = "W" + op[1:] + "DBS"
882 } else {
883 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
884 }
885 } else {
886 return fmt.Sprintf("specification exception is recognized for %q with m5: %v \n", op, m5)
887 }
888 args[0], args[1], args[2] = args[1], args[2], args[0]
889 args = args[:3]
890
891 case VFTCI:
892 m4, err := strconv.Atoi(args[3][1:])
893 if err != nil {
894 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
895 }
896 m5, err := strconv.Atoi(args[4][1:])
897 if err != nil {
898 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
899 }
900 val := (m4 & 0x7)
901 if m5 == 0 {
902 switch val {
903 case 2:
904 op = op + "SB"
905 case 3:
906 op = op + "DB"
907 default:
908 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
909 }
910 } else if m5 == 8 {
911 switch val {
912 case 2:
913 op = "W" + op[1:] + "SB"
914 case 3:
915 op = "W" + op[1:] + "DB"
916 case 4:
917 op = "W" + op[1:] + "XB"
918 default:
919 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
920 }
921 } else {
922 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
923 }
924 args[0], args[2] = args[2], args[0]
925 args = args[:3]
926 case VAC, VACCC:
927 mask, err := strconv.Atoi(args[4][1:])
928 if err != nil {
929 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
930 }
931 if mask&0x04 == 0 {
932 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
933 }
934 op = op + "Q"
935 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
936 args = args[:4]
937 case VL, VLREP:
938 switch inst.Op {
939 case VL:
940 args[0], args[1] = args[1], args[0]
941 case VLREP:
942 args[0], args[1] = args[1], args[0]
943 mask, err := strconv.Atoi(args[2][1:])
944 if err != nil {
945 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
946 }
947 if mask >= 0 && mask < 4 {
948 op = op + vectorSize[mask]
949 }
950 }
951 args = args[:2]
952 case VST, VSTEB, VSTEH, VSTEF, VSTEG, VLEB, VLEH, VLEF, VLEG:
953 m, err := strconv.Atoi(args[2][1:])
954 if err != nil {
955 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
956 }
957 switch inst.Op {
958 case VST:
959 if m == 0 || (m > 2 && m < 5) {
960 args = args[:2]
961 } else {
962 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
963 }
964 case VLEB, VLEH, VLEF, VLEG:
965 args[0], args[2] = args[2], args[0]
966 default:
967 args[0], args[1], args[2] = args[2], args[0], args[1]
968 }
969 case VSTM, VSTL, VESL, VESRA, VLM, VERLL, VLVG:
970 switch inst.Op {
971 case VSTM, VLM:
972 m, err := strconv.Atoi(args[3][1:])
973 if err != nil {
974 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
975 }
976 if !(m == 0 || (m > 2 && m < 5)) {
977 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
978 }
979 if inst.Op == VLM {
980 args[0], args[1], args[2] = args[2], args[0], args[1]
981 }
982 args = args[:3]
983 case VESL, VESRA, VERLL, VLVG:
984 m, err := strconv.Atoi(args[3][1:])
985 if err != nil {
986 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
987 }
988 if m >= 0 && m < 4 {
989 op = op + vectorSize[m]
990 } else {
991 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
992 }
993 switch inst.Op {
994 case VLVG:
995 args[0], args[2] = args[2], args[0]
996 args = args[:3]
997 default:
998 if args[0] == args[1] {
999 args[0] = args[2]
1000 args = args[:2]
1001 break
1002 }
1003 args[0], args[2] = args[2], args[0]
1004 args = args[:3]
1005 }
1006 case VSTL:
1007 args[0], args[1] = args[1], args[0]
1008 args = args[:3]
1009 }
1010 case VGBM:
1011 val, err := strconv.Atoi(args[1][1:])
1012 if err != nil {
1013 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
1014 }
1015 if val == 0 {
1016 op = "VZERO"
1017 args = args[:1]
1018 } else if val == 0xffff {
1019 op = "VONE"
1020 args = args[:1]
1021 } else {
1022 args[0], args[1] = args[1], args[0]
1023 args = args[:2]
1024 }
1025 case VN, VNC, VO, VX, VNO:
1026 if args[0] == args[2] {
1027 args = args[:2]
1028 args[0], args[1] = args[1], args[0]
1029 } else {
1030 args[0], args[1], args[2] = args[1], args[2], args[0]
1031 }
1032 if op == "VNO" {
1033 op = op + "T"
1034 }
1035 case VGEG, VGEF, VSCEG, VSCEF:
1036 args[0], args[2] = args[2], args[0]
1037
1038 }
1039 if args != nil {
1040 op += " " + strings.Join(args, ", ")
1041 }
1042
1043 return op
1044 }
1045
1046
1047
1048 func branch_relative_op(mask int, opconst Op) (op string, check bool) {
1049 switch mask & 0xf {
1050 case 1:
1051 op = "BVS"
1052 check = true
1053 case 2:
1054 op = "BGT"
1055 check = true
1056 case 4:
1057 op = "BLT"
1058 check = true
1059 case 5:
1060 op = "BLTU"
1061 check = true
1062 case 7:
1063 op = "BNE"
1064 check = true
1065 case 8:
1066 op = "BEQ"
1067 check = true
1068 case 10:
1069 op = "BGE"
1070 check = true
1071 case 12:
1072 op = "BLE"
1073 check = true
1074 case 13:
1075 op = "BLEU"
1076 check = true
1077 case 15:
1078 op = "BR"
1079 check = true
1080 }
1081 return op, check
1082 }
1083
1084
1085
1086 func branchOnConditionOp(mask int, opconst Op) (op string) {
1087 switch mask & 0xf {
1088 case 0:
1089 op = "NOPH"
1090 case 14:
1091 op = "SYNC"
1092 case 15:
1093 op = "RET"
1094 }
1095 return op
1096 }
1097
1098
1099 func bitwise_op(op Op) string {
1100 var ret string
1101 switch op {
1102 case NGR, NGRK, NILL:
1103 ret = "AND"
1104 case NR, NRK, NILH, NILF:
1105 ret = "ANDW"
1106 case OGR, OGRK, OILF:
1107 ret = "OR"
1108 case OR, ORK, OILH, OILL:
1109 ret = "ORW"
1110 case XGR, XGRK, XILF:
1111 ret = "XOR"
1112 case XR, XRK:
1113 ret = "XORW"
1114 }
1115 return ret
1116 }
1117
1118
1119 func mem_operand(args []string) string {
1120 if args[0] != "" && args[1] != "" {
1121 args[0] = fmt.Sprintf("%s(%s)", args[0], args[1])
1122 } else if args[0] != "" {
1123 args[0] = fmt.Sprintf("$%s", args[0])
1124 } else if args[1] != "" {
1125 args[0] = fmt.Sprintf("(%s)", args[1])
1126 } else {
1127 args[0] = ""
1128 }
1129 return args[0]
1130 }
1131
1132
1133 func mem_operandx(args []string) string {
1134 if args[1] != "" && args[2] != "" {
1135 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
1136 } else if args[1] != "" {
1137 args[1] = fmt.Sprintf("(%s)", args[1])
1138 } else if args[2] != "" {
1139 args[1] = fmt.Sprintf("(%s)", args[2])
1140 } else if args[0] != "" {
1141 args[1] = ""
1142 }
1143 if args[0] != "" && args[1] != "" {
1144 args[0] = fmt.Sprintf("%s%s", args[0], args[1])
1145 } else if args[0] != "" {
1146 args[0] = fmt.Sprintf("$%s", args[0])
1147 } else if args[1] != "" {
1148 args[0] = fmt.Sprintf("%s", args[1])
1149 } else {
1150 args[0] = ""
1151 }
1152 return args[0]
1153 }
1154
1155
1156 func mem_operandv(args []string) string {
1157 if args[1] != "" && args[2] != "" {
1158 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
1159 } else if args[1] != "" {
1160 args[1] = fmt.Sprintf("(%s*1)", args[1])
1161 } else if args[2] != "" {
1162 args[1] = fmt.Sprintf("(%s)", args[2])
1163 } else if args[0] != "" {
1164 args[1] = ""
1165 }
1166 if args[0] != "" && args[1] != "" {
1167 args[0] = fmt.Sprintf("%s%s", args[0], args[1])
1168 } else if args[0] != "" {
1169 args[0] = fmt.Sprintf("$%s", args[0])
1170 } else if args[1] != "" {
1171 args[0] = fmt.Sprintf("%s", args[1])
1172 } else {
1173 args[0] = ""
1174 }
1175 return args[0]
1176 }
1177
1178
1179 func mem_operandl(args []string) (string, string) {
1180 if args[0] != "" && args[2] != "" {
1181 args[0] = fmt.Sprintf("%s(%s)", args[0], args[2])
1182 } else if args[2] != "" {
1183 args[0] = fmt.Sprintf("(%s)", args[2])
1184 } else {
1185 args[0] = fmt.Sprintf("%s", args[0])
1186 }
1187 return args[0], args[1]
1188 }
1189
1190
1191
1192
1193 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
1194 switch arg.(type) {
1195 case Reg:
1196 if arg == R13 {
1197 return "g"
1198 }
1199 return strings.ToUpper(arg.String(pc)[1:])
1200 case Base:
1201 if arg == R13 {
1202 return "g"
1203 }
1204 s := arg.String(pc)
1205 if s != "" {
1206 return strings.ToUpper(s[1 : len(s)-1])
1207 }
1208 return "R0"
1209 case Index:
1210 if arg == R13 {
1211 return "g"
1212 }
1213 s := arg.String(pc)
1214 if s != "" {
1215 return strings.ToUpper(s[1:])
1216 }
1217 return ""
1218 case VReg:
1219 return strings.ToUpper(arg.String(pc)[1:])
1220 case Disp20, Disp12:
1221 numstr := arg.String(pc)
1222 num, err := strconv.Atoi(numstr[:len(numstr)])
1223 if err != nil {
1224 return fmt.Sprintf("plan9Arg: error in converting Atoi:%s", err)
1225 }
1226 if num == 0 {
1227 return ""
1228 } else {
1229 return strconv.Itoa(num)
1230 }
1231 case RegIm12, RegIm16, RegIm24, RegIm32:
1232 addr, err := strconv.ParseUint(arg.String(pc)[2:], 16, 64)
1233 if err != nil {
1234 return fmt.Sprintf("plan9Arg: error in converting ParseUint:%s", err)
1235 }
1236 off := int(addr - pc)
1237 s, base := symname(addr)
1238 if s != "" && addr == base {
1239 return fmt.Sprintf("%s(SB)", s)
1240 }
1241 off = off / inst.Len
1242 return fmt.Sprintf("%v(PC)", off)
1243 case Imm, Sign8, Sign16, Sign32:
1244 numImm := arg.String(pc)
1245 switch arg.(type) {
1246 case Sign32, Sign16, Imm:
1247 num, err := strconv.ParseInt(numImm, 10, 64)
1248 if err != nil {
1249 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
1250 }
1251 switch inst.Op {
1252 case LLIHF:
1253 num = num << 32
1254 case LLILH:
1255 num = num << 16
1256 case NILH:
1257 num = (num << 16) | int64(0xFFFF)
1258 case OILH:
1259 num = num << 16
1260 }
1261 numImm = fmt.Sprintf("%d", num)
1262 }
1263 return fmt.Sprintf("$%s", numImm)
1264 case Mask, Len:
1265 num := arg.String(pc)
1266 return fmt.Sprintf("$%s", num)
1267 }
1268 return fmt.Sprintf("???(%v)", arg)
1269 }
1270
1271
1272 func reverseOperandOrder(op Op) bool {
1273 switch op {
1274 case LOCR, MLGR:
1275 return true
1276 case LTEBR, LTDBR, LCDBR, LGDR:
1277 return true
1278 case VLEIB, VLEIH, VLEIF, VLEIG, VPDI:
1279 return true
1280 case VSLDB:
1281 return true
1282 }
1283 return false
1284 }
1285
1286
1287 func reverseAllOperands(op Op) bool {
1288 switch op {
1289 case VLVGP:
1290 return true
1291 case VSEL, VPERM:
1292 return true
1293 }
1294 return false
1295 }
1296
View as plain text