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:
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 MSGFR, MHI, MSFI, MSGFI:
353 switch inst.Op {
354 case MSGFR, MHI, MSFI:
355 op = "MULLW"
356 case MSGFI:
357 op = "MULLD"
358 }
359 args[0], args[1] = args[1], args[0]
360
361 case NGR, NR, NILL, NILF, NILH, OGR, OR, OILL, OILF, OILH, XGR, XR, XILF:
362 op = bitwise_op(inst.Op)
363 args[0], args[1] = args[1], args[0]
364 switch inst.Op {
365 case NILL:
366 if int(inst.Args[1].(Sign16)) < 0 {
367 op = "ANDW"
368 }
369
370 case NILF:
371 if int(inst.Args[1].(Sign32)) < 0 {
372 op = "AND"
373 }
374 case OILF:
375 if int(inst.Args[1].(Sign32)) < 0 {
376 op = "ORW"
377 }
378 case XILF:
379 if int(inst.Args[1].(Sign32)) < 0 {
380 op = "XORW"
381 }
382 }
383
384 case NGRK, NRK, OGRK, ORK, XGRK, XRK:
385 op = bitwise_op(inst.Op)
386 args[0], args[1], args[2] = args[1], args[2], args[0]
387 case SLLG, SRLG, SLLK, SRLK, RLL, RLLG, SRAK, SRAG:
388 switch inst.Op {
389 case SLLG:
390 op = "SLD"
391 case SRLG:
392 op = "SRD"
393 case SLLK:
394 op = "SLW"
395 case SRLK:
396 op = "SRW"
397 case SRAK:
398 op = "SRAW"
399 case SRAG:
400 op = "SRAD"
401 }
402 args[0], args[2] = args[2], args[0]
403 case TRAP2, SVC:
404 op = "SYSALL"
405 case CR, CLR, CGR, CLGR, KDBR, CDBR, CEBR, CGHI, CHI, CGFI, CLGFI, CFI, CLFI:
406 switch inst.Op {
407 case CGHI, CGFI, CGR:
408 op = "CMP"
409 case CHI, CFI, CR:
410 op = "CMPW"
411 case CLGFI, CLGR:
412 op = "CMPU"
413 case CLFI, CLR:
414 op = "CMPWU"
415 case CDBR:
416 op = "FCMPU"
417 case KDBR:
418 op = "FCMPO"
419 }
420 case CEFBRA, CDFBRA, CEGBRA, CDGBRA, CELFBR, CDLFBR, CELGBR, CDLGBR, CFEBRA, CFDBRA, CGEBRA, CGDBRA, CLFEBR, CLFDBR, CLGEBR, CLGDBR:
421 args[0], args[1] = args[2], args[0]
422 args = args[:2]
423 case CGRJ, CGIJ:
424 mask, err := strconv.Atoi(args[2][1:])
425 if err != nil {
426 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
427 }
428 var check bool
429 switch mask & 0xf {
430 case 2:
431 op = "CMPBGT"
432 check = true
433 case 4:
434 op = "CMPBLT"
435 check = true
436 case 6:
437 op = "CMPBNE"
438 check = true
439 case 8:
440 op = "CMPBEQ"
441 check = true
442 case 10:
443 op = "CMPBGE"
444 check = true
445 case 12:
446 op = "CMPBLE"
447 check = true
448 }
449 if check {
450 args[2] = args[3]
451 args = args[:3]
452 }
453 case CLGRJ, CLGIJ:
454 mask, err := strconv.Atoi(args[2][1:])
455 if err != nil {
456 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
457 }
458 var check bool
459 switch mask & 0xf {
460 case 2:
461 op = "CMPUBGT"
462 check = true
463 case 4:
464 op = "CMPUBLT"
465 check = true
466 case 7:
467 op = "CMPUBNE"
468 check = true
469 case 8:
470 op = "CMPUBEQ"
471 check = true
472 case 10:
473 op = "CMPUBGE"
474 check = true
475 case 12:
476 op = "CMPUBLE"
477 check = true
478 }
479 if check {
480 args[2] = args[3]
481 args = args[:3]
482 }
483 case CLRJ, CRJ, CIJ, CLIJ:
484 args[0], args[1], args[2] = args[2], args[0], args[1]
485 case BRC, BRCL:
486 mask, err := strconv.Atoi(args[0][1:])
487 if err != nil {
488 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
489 }
490 opStr, check := branch_relative_op(mask, inst.Op)
491 if opStr != "" {
492 op = opStr
493 }
494 if check {
495 args[0] = args[1]
496 args = args[:1]
497 }
498 case BCR:
499 mask, err := strconv.Atoi(args[0][1:])
500 if err != nil {
501 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
502 }
503 opStr, check := branchOnConditionOp(mask, inst.Op)
504 if opStr != "" {
505 op = opStr
506 }
507 if op == "SYNC" || op == "NOPH" {
508 return op
509 }
510 if check {
511 args[0] = args[1]
512 args = args[:1]
513 }
514 case LOCGR:
515 mask, err := strconv.Atoi(args[2][1:])
516 if err != nil {
517 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
518 }
519 var check bool
520 switch mask & 0xf {
521 case 2:
522 op = "MOVDGT"
523 check = true
524 case 4:
525 op = "MOVDLT"
526 check = true
527 case 7:
528 op = "MOVDNE"
529 check = true
530 case 8:
531 op = "MOVDEQ"
532 check = true
533 case 10:
534 op = "MOVDGE"
535 check = true
536 case 12:
537 op = "MOVDLE"
538 check = true
539 }
540 if check {
541 args[0], args[1] = args[1], args[0]
542 args = args[:2]
543 } else {
544 args[0], args[2] = args[2], args[0]
545 }
546 case BRASL:
547 op = "CALL"
548 args[0] = args[1]
549 args = args[:1]
550 case X, XY, XG:
551 switch inst.Op {
552 case X, XY:
553 op = "XORW"
554 case XG:
555 op = "XOR"
556 }
557 case N, NY, NG, O, OY, OG, XC, NC, OC, MVC, MVCIN, CLC:
558 switch inst.Op {
559 case N, NY:
560 op = "ANDW"
561 case NG:
562 op = "AND"
563 case O, OY:
564 op = "ORW"
565 case OG:
566 op = "OR"
567 }
568 args[0], args[1] = args[1], args[0]
569 case S, SY, SLBG, SLG, SG:
570 switch inst.Op {
571 case S, SY:
572 op = "SUBW"
573 case SLBG:
574 op = "SUBE"
575 case SLG:
576 op = "SUBC"
577 case SG:
578 op = "SUB"
579 }
580 args[0], args[1] = args[1], args[0]
581 case MSG, MSY, MS:
582 switch inst.Op {
583 case MSG:
584 op = "MULLD"
585 case MSY, MS:
586 op = "MULLW"
587 }
588 case A, AY, ALCG, ALG, AG:
589 switch inst.Op {
590 case A, AY:
591 op = "ADDW"
592 case ALCG:
593 op = "ADDE"
594 case ALG:
595 op = "ADDC"
596 case AG:
597 op = "ADD"
598 }
599 args[0], args[1] = args[1], args[0]
600 case RISBG, RISBGN, RISBHG, RISBLG, RNSBG, RXSBG, ROSBG:
601 switch inst.Op {
602 case RNSBG, RXSBG, ROSBG:
603 num, err := strconv.Atoi(args[2][1:])
604 if err != nil {
605 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
606 }
607 if ((num >> 7) & 0x1) != 0 {
608 op = op + "T"
609 }
610 case RISBG, RISBGN, RISBHG, RISBLG:
611 num, err := strconv.Atoi(args[3][1:])
612 if err != nil {
613 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
614 }
615 if ((num >> 7) & 0x1) != 0 {
616 op = op + "Z"
617 }
618 }
619 if len(args) == 5 {
620 args[0], args[1], args[2], args[3], args[4] = args[2], args[3], args[4], args[1], args[0]
621 } else {
622 args[0], args[1], args[2], args[3] = args[2], args[3], args[1], args[0]
623 }
624
625 case VEC, VECL, VCLZ, VCTZ, VREPI, VPOPCT:
626 mask, err := strconv.Atoi(args[2][1:])
627 if err != nil {
628 return fmt.Sprintf("GoSyntax: error in converting Atoi for %q:%s", op, err)
629 }
630 val := mask & 0x7
631 if val >= 0 && val < 4 {
632 op = op + vectorSize[val]
633 args = args[:2]
634 } else {
635 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
636 }
637 switch inst.Op {
638 case VCLZ, VCTZ, VREPI, VPOPCT:
639 args[0], args[1] = args[1], args[0]
640 default:
641 }
642
643 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:
644 mask, err := strconv.Atoi(args[3][1:])
645 if err != nil {
646 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
647 }
648 val := mask & 0x7
649 switch inst.Op {
650 case VA, VS, VACC, VSCBI:
651 if val >= 0 && val < 5 {
652 if args[0] == args[2] {
653 args[0], args[1] = args[1], args[0]
654 args = args[:2]
655 } else if inst.Op == VS {
656 if args[0] == args[1] {
657 args[0] = args[2]
658 args = args[:2]
659 } else {
660 args[0], args[2] = args[2], args[0]
661 args = args[:3]
662 }
663 } else {
664 args[0], args[1], args[2] = args[1], args[2], args[0]
665 args = args[:3]
666 }
667 op = op + vectorSize[val]
668 } else {
669 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
670 }
671 case VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM:
672 if val >= 0 && val < 4 {
673 op = op + vectorSize[val]
674 args[0], args[1], args[2] = args[1], args[2], args[0]
675 args = args[:3]
676 } else {
677 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
678 }
679 case VREP, VERLLV, VESLV:
680 if val >= 0 && val < 4 {
681 op = op + vectorSize[val]
682 args[0], args[2] = args[2], args[0]
683 args = args[:3]
684 } else {
685 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
686 }
687 case VSUM, VSUMG, VSUMQ:
688 var off int
689 switch inst.Op {
690 case VSUM:
691 off = 0
692 case VSUMG:
693 off = 1
694 case VSUMQ:
695 off = 2
696 }
697 if (val > (-1 + off)) && (val < (2 + off)) {
698 op = op + vectorSize[val]
699 } else {
700 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
701 }
702 args = args[:3]
703 case VML, VMH, VMLH, VME, VMLE, VMO, VMLO:
704 if val >= 0 && val < 3 {
705 op = op + vectorSize[val]
706 }
707 if op == "VML" && val == 2 {
708 op = op + "W"
709 }
710 if args[0] == args[2] {
711 args[0], args[1] = args[1], args[0]
712 args = args[:2]
713 } else {
714 args[0], args[1], args[2] = args[1], args[2], args[0]
715 args = args[:3]
716 }
717 }
718
719 case VGFMA, VERIM, VMAH, VMALH:
720 mask, err := strconv.Atoi(args[4][1:])
721 if err != nil {
722 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
723 }
724 val := mask & 0x7
725 args = args[:4]
726 var off int
727 switch inst.Op {
728 case VMAH, VMALH:
729 off = -1
730 }
731
732 if val >= 0 && val < (4+off) {
733 op = op + vectorSize[val]
734 } else {
735 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
736 }
737 switch inst.Op {
738 case VGFMA, VMAH, VMALH:
739 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
740 default:
741 args[0], args[3] = args[3], args[0]
742 }
743 case VSTRC, VFAE, VFEE, VFENE:
744 var off uint8
745 switch inst.Op {
746 case VSTRC:
747 off = uint8(1)
748 default:
749 off = uint8(0)
750 }
751 m1, err := strconv.Atoi(args[3+off][1:])
752 if err != nil {
753 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
754 }
755 m2, err := strconv.Atoi(args[4+off][1:])
756 if err != nil {
757 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
758 }
759 index := m1 & 0x3
760 if index < 0 || index > 2 {
761 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
762 }
763 switch m2 {
764 case 0:
765 op = op + vectorSize[index]
766 case 1:
767 op = op + vectorCS[index]
768 case 2:
769 op = op + "Z" + vectorSize[index]
770 case 3:
771 op = op + "Z" + vectorCS[index]
772 default:
773 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
774 }
775 switch inst.Op {
776 case VSTRC:
777 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
778 default:
779 args[0], args[1], args[2] = args[1], args[2], args[0]
780 }
781 args = args[:3+off]
782
783 case VCEQ, VCH, VCHL:
784 m4, err := strconv.Atoi(args[3][1:])
785 if err != nil {
786 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
787 }
788 m5, err := strconv.Atoi(args[4][1:])
789 if err != nil {
790 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
791 }
792 val := (m4 & 0x7)
793 if m5 == 0 {
794 if val >= 0 && val < 4 {
795 op = op + vectorSize[val]
796 args[0], args[1], args[2] = args[1], args[2], args[0]
797 args = args[:3]
798 } else {
799 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
800 }
801 } else if m5 == 1 {
802 if val >= 0 && val < 4 {
803 op = op + vectorCS[val]
804 args[0], args[1], args[2] = args[1], args[2], args[0]
805 args = args[:3]
806 } else {
807 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
808 }
809 } else {
810 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
811 }
812 case VFMA, VFMS, VMSL:
813 m5, err := strconv.Atoi(args[4][1:])
814 if err != nil {
815 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
816 }
817 m6, err := strconv.Atoi(args[5][1:])
818 if err != nil {
819 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
820 }
821 switch inst.Op {
822 case VMSL:
823 if m5 == 3 && m6 == 8 {
824 op = op + "EG"
825 } else if m5 == 3 && m6 == 4 {
826 op = op + "OG"
827 } else if m5 == 3 && m6 == 12 {
828 op = op + "EOG"
829 } else if m5 == 3 {
830 op = op + "G"
831 }
832 default:
833 if m5 == 0 && m6 == 3 {
834 op = op + "DB"
835 } else if m5 == 8 && m6 == 3 {
836 op = "W" + op[1:] + "DB"
837 } else {
838 return fmt.Sprintf("specification exception is recognized for %q with m5: %v m6: %v \n", op, m5, m6)
839 }
840 }
841 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
842 args = args[:4]
843
844 case VFCE, VFCH, VFCHE:
845 m4, err := strconv.Atoi(args[3][1:])
846 if err != nil {
847 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
848 }
849 m5, err := strconv.Atoi(args[4][1:])
850 if err != nil {
851 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
852 }
853 m6, err := strconv.Atoi(args[5][1:])
854 if err != nil {
855 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
856 }
857 if m5 == 0 {
858 if m4 == 3 && m6 == 0 {
859 op = op + "DB"
860 } else if m4 == 3 && m6 == 1 {
861 op = op + "DBS"
862 } else {
863 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
864 }
865
866 } else if m5 == 8 {
867 if m4 == 3 && m6 == 0 {
868 op = "W" + op[1:] + "DB"
869 } else if m4 == 3 && m6 == 1 {
870 op = "W" + op[1:] + "DBS"
871 } else {
872 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
873 }
874 } else {
875 return fmt.Sprintf("specification exception is recognized for %q with m5: %v \n", op, m5)
876 }
877 args[0], args[1], args[2] = args[1], args[2], args[0]
878 args = args[:3]
879
880 case VFTCI:
881 m4, err := strconv.Atoi(args[3][1:])
882 if err != nil {
883 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
884 }
885 m5, err := strconv.Atoi(args[4][1:])
886 if err != nil {
887 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
888 }
889 val := (m4 & 0x7)
890 if m5 == 0 {
891 switch val {
892 case 2:
893 op = op + "SB"
894 case 3:
895 op = op + "DB"
896 default:
897 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
898 }
899 } else if m5 == 8 {
900 switch val {
901 case 2:
902 op = "W" + op[1:] + "SB"
903 case 3:
904 op = "W" + op[1:] + "DB"
905 case 4:
906 op = "W" + op[1:] + "XB"
907 default:
908 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
909 }
910 } else {
911 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
912 }
913 args[0], args[2] = args[2], args[0]
914 args = args[:3]
915 case VAC, VACCC:
916 mask, err := strconv.Atoi(args[4][1:])
917 if err != nil {
918 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
919 }
920 if mask&0x04 == 0 {
921 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
922 }
923 op = op + "Q"
924 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
925 args = args[:4]
926 case VL, VLREP:
927 switch inst.Op {
928 case VL:
929 args[0], args[1] = args[1], args[0]
930 case VLREP:
931 args[0], args[1] = args[1], args[0]
932 mask, err := strconv.Atoi(args[2][1:])
933 if err != nil {
934 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
935 }
936 if mask >= 0 && mask < 4 {
937 op = op + vectorSize[mask]
938 }
939 }
940 args = args[:2]
941 case VST, VSTEB, VSTEH, VSTEF, VSTEG, VLEB, VLEH, VLEF, VLEG:
942 m, err := strconv.Atoi(args[2][1:])
943 if err != nil {
944 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
945 }
946 switch inst.Op {
947 case VST:
948 if m == 0 || (m > 2 && m < 5) {
949 args = args[:2]
950 } else {
951 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
952 }
953 case VLEB, VLEH, VLEF, VLEG:
954 args[0], args[2] = args[2], args[0]
955 default:
956 args[0], args[1], args[2] = args[2], args[0], args[1]
957 }
958 case VSTM, VSTL, VESL, VESRA, VLM, VERLL, VLVG:
959 switch inst.Op {
960 case VSTM, VLM:
961 m, err := strconv.Atoi(args[3][1:])
962 if err != nil {
963 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
964 }
965 if !(m == 0 || (m > 2 && m < 5)) {
966 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
967 }
968 if inst.Op == VLM {
969 args[0], args[1], args[2] = args[2], args[0], args[1]
970 }
971 args = args[:3]
972 case VESL, VESRA, VERLL, VLVG:
973 m, err := strconv.Atoi(args[3][1:])
974 if err != nil {
975 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
976 }
977 if m >= 0 && m < 4 {
978 op = op + vectorSize[m]
979 } else {
980 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
981 }
982 switch inst.Op {
983 case VLVG:
984 args[0], args[2] = args[2], args[0]
985 args = args[:3]
986 default:
987 if args[0] == args[1] {
988 args[0] = args[2]
989 args = args[:2]
990 break
991 }
992 args[0], args[2] = args[2], args[0]
993 args = args[:3]
994 }
995 case VSTL:
996 args[0], args[1] = args[1], args[0]
997 args = args[:3]
998 }
999 case VGBM:
1000 val, err := strconv.Atoi(args[1][1:])
1001 if err != nil {
1002 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
1003 }
1004 if val == 0 {
1005 op = "VZERO"
1006 args = args[:1]
1007 } else if val == 0xffff {
1008 op = "VONE"
1009 args = args[:1]
1010 } else {
1011 args[0], args[1] = args[1], args[0]
1012 args = args[:2]
1013 }
1014 case VN, VNC, VO, VX, VNO:
1015 if args[0] == args[2] {
1016 args = args[:2]
1017 args[0], args[1] = args[1], args[0]
1018 } else {
1019 args[0], args[1], args[2] = args[1], args[2], args[0]
1020 }
1021 if op == "VNO" {
1022 op = op + "T"
1023 }
1024 case VGEG, VGEF, VSCEG, VSCEF:
1025 args[0], args[2] = args[2], args[0]
1026
1027 }
1028 if args != nil {
1029 op += " " + strings.Join(args, ", ")
1030 }
1031
1032 return op
1033 }
1034
1035
1036
1037 func branch_relative_op(mask int, opconst Op) (op string, check bool) {
1038 switch mask & 0xf {
1039 case 2:
1040 op = "BGT"
1041 check = true
1042 case 4:
1043 op = "BLT"
1044 check = true
1045 case 5:
1046 op = "BLTU"
1047 check = true
1048 case 7:
1049 op = "BNE"
1050 check = true
1051 case 8:
1052 op = "BEQ"
1053 check = true
1054 case 10:
1055 op = "BGE"
1056 check = true
1057 case 12:
1058 op = "BLE"
1059 check = true
1060 case 13:
1061 op = "BLEU"
1062 check = true
1063 case 15:
1064 op = "JMP"
1065 check = true
1066 }
1067 return op, check
1068 }
1069
1070
1071
1072 func branchOnConditionOp(mask int, opconst Op) (op string, check bool) {
1073 switch mask & 0xf {
1074 case 0:
1075 op = "NOPH"
1076 case 14:
1077 op = "SYNC"
1078 case 15:
1079 op = "JMP"
1080 check = true
1081 }
1082 return op, check
1083 }
1084
1085
1086 func bitwise_op(op Op) string {
1087 var ret string
1088 switch op {
1089 case NGR, NGRK, NILL:
1090 ret = "AND"
1091 case NR, NRK, NILH, NILF:
1092 ret = "ANDW"
1093 case OGR, OGRK, OILF:
1094 ret = "OR"
1095 case OR, ORK, OILH, OILL:
1096 ret = "ORW"
1097 case XGR, XGRK, XILF:
1098 ret = "XOR"
1099 case XR, XRK:
1100 ret = "XORW"
1101 }
1102 return ret
1103 }
1104
1105
1106 func mem_operand(args []string) string {
1107 if args[0] != "" && args[1] != "" {
1108 args[0] = fmt.Sprintf("%s(%s)", args[0], args[1])
1109 } else if args[0] != "" {
1110 args[0] = fmt.Sprintf("$%s", args[0])
1111 } else if args[1] != "" {
1112 args[0] = fmt.Sprintf("(%s)", args[1])
1113 } else {
1114 args[0] = ""
1115 }
1116 return args[0]
1117 }
1118
1119
1120 func mem_operandx(args []string) string {
1121 if args[1] != "" && args[2] != "" {
1122 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
1123 } else if args[1] != "" {
1124 args[1] = fmt.Sprintf("(%s)", args[1])
1125 } else if args[2] != "" {
1126 args[1] = fmt.Sprintf("(%s)", args[2])
1127 } else if args[0] != "" {
1128 args[1] = ""
1129 }
1130 if args[0] != "" && args[1] != "" {
1131 args[0] = fmt.Sprintf("%s%s", args[0], args[1])
1132 } else if args[0] != "" {
1133 args[0] = fmt.Sprintf("$%s", args[0])
1134 } else if args[1] != "" {
1135 args[0] = fmt.Sprintf("%s", args[1])
1136 } else {
1137 args[0] = ""
1138 }
1139 return args[0]
1140 }
1141
1142
1143 func mem_operandv(args []string) string {
1144 if args[1] != "" && args[2] != "" {
1145 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
1146 } else if args[1] != "" {
1147 args[1] = fmt.Sprintf("(%s*1)", args[1])
1148 } else if args[2] != "" {
1149 args[1] = fmt.Sprintf("(%s)", args[2])
1150 } else if args[0] != "" {
1151 args[1] = ""
1152 }
1153 if args[0] != "" && args[1] != "" {
1154 args[0] = fmt.Sprintf("%s%s", args[0], args[1])
1155 } else if args[0] != "" {
1156 args[0] = fmt.Sprintf("$%s", args[0])
1157 } else if args[1] != "" {
1158 args[0] = fmt.Sprintf("%s", args[1])
1159 } else {
1160 args[0] = ""
1161 }
1162 return args[0]
1163 }
1164
1165
1166 func mem_operandl(args []string) (string, string) {
1167 if args[0] != "" && args[2] != "" {
1168 args[0] = fmt.Sprintf("%s(%s)", args[0], args[2])
1169 } else if args[2] != "" {
1170 args[0] = fmt.Sprintf("(%s)", args[2])
1171 } else {
1172 args[0] = fmt.Sprintf("%s", args[0])
1173 }
1174 return args[0], args[1]
1175 }
1176
1177
1178
1179
1180 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
1181 switch arg.(type) {
1182 case Reg:
1183 if arg == R13 {
1184 return "g"
1185 }
1186 return strings.ToUpper(arg.String(pc)[1:])
1187 case Base:
1188 if arg == R13 {
1189 return "g"
1190 }
1191 s := arg.String(pc)
1192 if s != "" {
1193 return strings.ToUpper(s[1 : len(s)-1])
1194 }
1195 return "R0"
1196 case Index:
1197 if arg == R13 {
1198 return "g"
1199 }
1200 s := arg.String(pc)
1201 if s != "" {
1202 return strings.ToUpper(s[1:])
1203 }
1204 return ""
1205 case VReg:
1206 return strings.ToUpper(arg.String(pc)[1:])
1207 case Disp20, Disp12:
1208 numstr := arg.String(pc)
1209 num, err := strconv.Atoi(numstr[:len(numstr)])
1210 if err != nil {
1211 return fmt.Sprintf("plan9Arg: error in converting Atoi:%s", err)
1212 }
1213 if num == 0 {
1214 return ""
1215 } else {
1216 return strconv.Itoa(num)
1217 }
1218 case RegIm12, RegIm16, RegIm24, RegIm32:
1219 addr, err := strconv.ParseUint(arg.String(pc)[2:], 16, 64)
1220 if err != nil {
1221 return fmt.Sprintf("plan9Arg: error in converting ParseUint:%s", err)
1222 }
1223 off := int(addr - pc)
1224 s, base := symname(addr)
1225 if s != "" && addr == base {
1226 return fmt.Sprintf("%s(SB)", s)
1227 }
1228 off = off / inst.Len
1229 return fmt.Sprintf("%v(PC)", off)
1230 case Imm, Sign8, Sign16, Sign32:
1231 numImm := arg.String(pc)
1232 switch arg.(type) {
1233 case Sign32, Sign16, Imm:
1234 num, err := strconv.ParseInt(numImm, 10, 64)
1235 if err != nil {
1236 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
1237 }
1238 switch inst.Op {
1239 case LLIHF:
1240 num = num << 32
1241 case LLILH:
1242 num = num << 16
1243 case NILH:
1244 num = (num << 16) | int64(0xFFFF)
1245 case OILH:
1246 num = num << 16
1247 }
1248 numImm = fmt.Sprintf("%d", num)
1249 }
1250 return fmt.Sprintf("$%s", numImm)
1251 case Mask, Len:
1252 num := arg.String(pc)
1253 return fmt.Sprintf("$%s", num)
1254 }
1255 return fmt.Sprintf("???(%v)", arg)
1256 }
1257
1258
1259 func reverseOperandOrder(op Op) bool {
1260 switch op {
1261 case LOCR, MLGR:
1262 return true
1263 case LTEBR, LTDBR:
1264 return true
1265 case VLEIB, VLEIH, VLEIF, VLEIG, VPDI:
1266 return true
1267 case VSLDB:
1268 return true
1269 }
1270 return false
1271 }
1272
1273
1274 func reverseAllOperands(op Op) bool {
1275 switch op {
1276 case VLVGP:
1277 return true
1278 case VSEL, VPERM:
1279 return true
1280 }
1281 return false
1282 }
1283
View as plain text