s390x: add s390x disassembler support for the plan9

Change-Id: I0eb9a10535175bb70dbab5737c4e02e68fd44c94
Reviewed-on: https://go-review.googlesource.com/c/arch/+/620475
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Vishwanatha HD <vishwanatha.hd@ibm.com>
diff --git a/s390x/s390xasm/decode_test.go b/s390x/s390xasm/decode_test.go
index 5ca0b74..29bce8e 100644
--- a/s390x/s390xasm/decode_test.go
+++ b/s390x/s390xasm/decode_test.go
@@ -75,6 +75,8 @@
 			switch syntax {
 			case "gnu":
 				out = GNUSyntax(inst, pc)
+			case "plan9":
+				out = GoSyntax(inst, pc, nil)
 			default:
 				t.Errorf("unknown syntax %q", syntax)
 				continue
diff --git a/s390x/s390xasm/plan9.go b/s390x/s390xasm/plan9.go
new file mode 100644
index 0000000..b4df0b8
--- /dev/null
+++ b/s390x/s390xasm/plan9.go
@@ -0,0 +1,1282 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package s390xasm
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+var vectorSize = map[int]string{0: "B", 1: "H", 2: "F", 3: "G", 4: "Q"}
+var vectorCS = map[int]string{0: "BS", 1: "HS", 2: "FS", 3: "GS"}
+
+// GoSyntax returns the Go assembler syntax for the instruction.
+// The syntax was originally defined by Plan 9.
+// The inst relates to single instruction.
+// The pc is the program counter of the instruction, used for
+// expanding PC-relative addresses into absolute ones.
+// The symname function queries the symbol table for the program
+// being disassembled. Given a target address it returns the name
+// and base address of the symbol containing the target, if any;
+// otherwise it returns "", 0.
+func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
+	if symname == nil {
+		symname = func(uint64) (string, uint64) { return "", 0 }
+	}
+
+	var args []string
+	opString := inst.Op.String()
+	op := strings.ToUpper(opString)
+	for i := 0; i < len(inst.Args); i++ {
+		if inst.Args[i] == nil {
+			break
+		}
+		switch inst.Args[i].(type) {
+		case Disp12, Disp20:
+			var temp []string
+			switch inst.Args[i+1].(type) {
+			case Index: // D(X,B)
+				for j := 0; j < 3; j++ {
+					temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
+				}
+				args = append(args, mem_operandx(temp))
+				i = i + 2
+			case Base: // D(B)
+				for j := 0; j < 2; j++ {
+					temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
+				}
+				args = append(args, mem_operand(temp))
+				i = i + 1
+			case VReg: // D(B)
+				for j := 0; j < 3; j++ {
+					temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
+				}
+				args = append(args, mem_operandv(temp))
+				i = i + 2
+			case Len: // D(L,B)
+				for j := 0; j < 3; j++ {
+					temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
+				}
+				ar1, ar2 := mem_operandl(temp)
+				args = append(args, ar1, ar2)
+				i = i + 2
+			default: // D(R,B)
+				for j := 0; j < 3; j++ {
+					temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j]))
+				}
+				args = append(args, mem_operandx(temp))
+				i = i + 2
+			}
+		default:
+			args = append(args, plan9Arg(&inst, pc, symname, inst.Args[i]))
+		}
+	}
+	if strings.HasPrefix(op, "V") || strings.Contains(op, "WFC") || strings.Contains(op, "WFK") {
+		args = args[:len(args)-1]
+	}
+
+	switch inst.Op {
+	default:
+		switch len(args) {
+		case 0:
+			return op
+		case 1:
+			return fmt.Sprintf("%s %s", op, args[0])
+		case 2:
+			if reverseOperandOrder(inst.Op) {
+				args[0], args[1] = args[1], args[0]
+			}
+		case 3:
+			if reverseOperandOrder(inst.Op) {
+				args[0], args[2] = args[2], args[0]
+			} else if reverseAllOperands(inst.Op) {
+				args[0], args[1], args[2] = args[1], args[2], args[0]
+			}
+		case 4:
+			if reverseOperandOrder(inst.Op) {
+				args[0], args[3] = args[3], args[0]
+			} else if reverseAllOperands(inst.Op) {
+				args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
+			}
+		}
+	case LCGR, LCGFR:
+		switch inst.Op {
+		case LCGR:
+			op = "NEG"
+		case LCGFR:
+			op = "NEGW"
+		}
+		if args[0] == args[1] {
+			args = args[:1]
+		} else {
+			args[0], args[1] = args[1], args[0]
+		}
+	case LD, LE, LG, LGF, LLGF, LGH, LLGH, LGB, LLGC, LDY, LEY, LRVG, LRV, LRVH:
+		args[0], args[1] = args[1], args[0]
+		switch inst.Op {
+		case LG:
+			op = "MOVD"
+		case LGF:
+			op = "MOVW"
+		case LLGF:
+			op = "MOVWZ"
+		case LGH:
+			op = "MOVH"
+		case LLGH:
+			op = "MOVHZ"
+		case LGB:
+			op = "MOVB"
+		case LLGC:
+			op = "MOVBZ"
+		case LDY, LD:
+			op = "FMOVD"
+		case LEY, LE:
+			op = "FMOVS"
+		case LRVG:
+			op = "MOVDBR"
+		case LRV:
+			op = "MOVWBR"
+		case LRVH:
+			op = "MOVHBR"
+		}
+	case LA, LAY:
+		args[0], args[1] = args[1], args[0]
+		op = "MOVD"
+
+	case LAA, LAAG, LAAL, LAALG, LAN, LANG, LAX, LAXG, LAO, LAOG:
+		args[0], args[1] = args[1], args[0]
+	case LM, LMY, LMG: // Load Multiple
+		switch inst.Op {
+		case LM, LMY:
+			op = "LMY"
+		}
+		args[0], args[1], args[2] = args[2], args[0], args[1]
+
+	case STM, STMY, STMG: // Store Multiple
+		switch inst.Op {
+		case STM, STMY:
+			op = "STMY"
+		}
+	case ST, STY, STG, STHY, STCY, STRVG, STRV:
+		switch inst.Op {
+		case ST, STY:
+			op = "MOVW"
+		case STHY:
+			op = "MOVH"
+		case STCY:
+			op = "MOVB"
+		case STG:
+			op = "MOVD"
+		case STRVG:
+			op = "MOVDBR"
+		case STRV:
+			op = "MOVWBR"
+		}
+	case LGR, LGFR, LGHR, LGBR, LLGFR, LLGHR, LLGCR, LRVGR, LRVR, LDR:
+		switch inst.Op {
+		case LGR:
+			op = "MOVD"
+		case LGFR:
+			op = "MOVW"
+		case LGHR:
+			op = "MOVH"
+		case LGBR:
+			op = "MOVB"
+		case LLGFR:
+			op = "MOVWZ"
+		case LLGHR:
+			op = "MOVHZ"
+		case LLGCR:
+			op = "MOVBZ"
+		case LRVGR:
+			op = "MOVDBR"
+		case LRVR:
+			op = "MOVWBR"
+		case LDR:
+			op = "FMOVD"
+		}
+		args[0], args[1] = args[1], args[0]
+	case LZDR:
+		op = "FMOVD"
+		return op + " " + "$0" + ", " + args[0]
+	case LZER:
+		op = "FMOVS"
+		return op + " " + "$0" + ", " + args[0]
+	case STD, STDY, STE, STEY:
+		switch inst.Op {
+		case STD, STDY:
+			op = "FMOVD"
+		case STE, STEY:
+			op = "FMOVS"
+		}
+
+	case LGHI, LLILH, LLIHL, LLIHH, LGFI, LLILF, LLIHF:
+		switch inst.Op {
+		case LGFI:
+			op = "MOVW"
+		case LGHI:
+			num, err := strconv.ParseInt(args[1][1:], 10, 16)
+			if err != nil {
+				return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
+			}
+			if num == int64(int8(num)) {
+				op = "MOVB"
+			} else {
+				op = "MOVH"
+			}
+		default:
+			op = "MOVD"
+		}
+		args[0], args[1] = args[1], args[0]
+	case ARK, AGRK, ALGRK:
+		switch inst.Op {
+		case ARK:
+			op = "ADDW"
+		case AGRK:
+			op = "ADD"
+		case ALGRK:
+			op = "ADDC"
+		}
+		if args[0] == args[1] {
+			args[0], args[1] = args[2], args[0]
+			args = args[:2]
+		} else {
+			args[0], args[1], args[2] = args[2], args[1], args[0]
+		}
+	case AGHIK, AHIK, ALGHSIK:
+		num, err := strconv.ParseInt(args[2][1:], 10, 32)
+		if err != nil {
+			return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
+		}
+		switch inst.Op {
+		case AGHIK:
+			if num < 0 {
+				op = "SUB"
+				args[2] = args[2][:1] + args[2][2:]
+			} else {
+				op = "ADD"
+			}
+		case AHIK:
+			op = "ADDW"
+		case ALGHSIK:
+			if num < 0 {
+				op = "SUBC"
+				args[2] = args[2][:1] + args[2][2:]
+			} else {
+				op = "ADDC"
+			}
+		}
+		args[0], args[1], args[2] = args[2], args[1], args[0]
+	case AGHI, AHI, AGFI, AFI, AR, ALCGR:
+		num, err := strconv.ParseInt(args[1][1:], 10, 32)
+		if err != nil {
+			return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
+		}
+		switch inst.Op {
+		case AGHI, AGFI:
+			if num < 0 {
+				op = "SUB"
+				args[1] = args[1][:1] + args[1][2:]
+			} else {
+				op = "ADD"
+			}
+		case AHI, AFI, AR:
+			op = "ADDW"
+		case ALCGR:
+			op = "ADDE"
+		}
+		args[0], args[1] = args[1], args[0]
+	case AEBR, ADBR, DDBR, DEBR, MDBR, MEEBR, SDBR, SEBR, LPDBR, LNDBR, LPDFR, LNDFR, LCDFR, LCEBR, LEDBR, LDEBR, SQDBR, SQEBR:
+		switch inst.Op {
+		case AEBR:
+			op = "FADDS"
+		case ADBR:
+			op = "FADD"
+		case DDBR:
+			op = "FDIV"
+		case DEBR:
+			op = "FDIVS"
+		case MDBR:
+			op = "FMUL"
+		case MEEBR:
+			op = "FMULS"
+		case SDBR:
+			op = "FSUB"
+		case SEBR:
+			op = "FSUBS"
+		case LPDBR:
+			op = "FABS"
+		case LNDBR:
+			op = "FNABS"
+		case LCDFR:
+			op = "FNEG"
+		case LCEBR:
+			op = "FNEGS"
+		case SQDBR:
+			op = "FSQRT"
+		case SQEBR:
+			op = "FSQRTS"
+		}
+		args[0], args[1] = args[1], args[0]
+	case SR, SGR, SLGR, SLFI:
+		switch inst.Op {
+		case SR, SLFI:
+			op = "SUBW"
+		case SGR:
+			op = "SUB"
+		case SLGR:
+			op = "SUBC"
+		}
+		args[0], args[1] = args[1], args[0]
+	case SGRK, SLGRK, SRK:
+		switch inst.Op {
+		case SGRK:
+			op = "SUB"
+		case SLGRK:
+			op = "SUBC"
+		case SRK:
+			op = "SUBW"
+		}
+		if args[0] == args[1] {
+			args[0], args[1] = args[2], args[0]
+			args = args[:2]
+		} else {
+			args[0], args[1], args[2] = args[2], args[1], args[0]
+		}
+	case SLBGR:
+		op = "SUBE"
+		args[0], args[1] = args[1], args[0]
+	case MSGFR, MHI, MSFI, MSGFI:
+		switch inst.Op {
+		case MSGFR, MHI, MSFI:
+			op = "MULLW"
+		case MSGFI:
+			op = "MULLD"
+		}
+		args[0], args[1] = args[1], args[0]
+
+	case NGR, NR, NILL, NILF, NILH, OGR, OR, OILL, OILF, OILH, XGR, XR, XILF:
+		op = bitwise_op(inst.Op)
+		args[0], args[1] = args[1], args[0]
+		switch inst.Op {
+		case NILL:
+			if int(inst.Args[1].(Sign16)) < 0 {
+				op = "ANDW"
+			}
+
+		case NILF:
+			if int(inst.Args[1].(Sign32)) < 0 {
+				op = "AND"
+			}
+		case OILF:
+			if int(inst.Args[1].(Sign32)) < 0 {
+				op = "ORW"
+			}
+		case XILF:
+			if int(inst.Args[1].(Sign32)) < 0 {
+				op = "XORW"
+			}
+		}
+
+	case NGRK, NRK, OGRK, ORK, XGRK, XRK: // opcode R1, R2, R3
+		op = bitwise_op(inst.Op)
+		args[0], args[1], args[2] = args[1], args[2], args[0]
+	case SLLG, SRLG, SLLK, SRLK, RLL, RLLG, SRAK, SRAG:
+		switch inst.Op {
+		case SLLG:
+			op = "SLD"
+		case SRLG:
+			op = "SRD"
+		case SLLK:
+			op = "SLW"
+		case SRLK:
+			op = "SRW"
+		case SRAK:
+			op = "SRAW"
+		case SRAG:
+			op = "SRAD"
+		}
+		args[0], args[1], args[2] = args[2], args[1], args[0]
+	case TRAP2, SVC:
+		op = "SYSALL"
+	case CR, CLR, CGR, CLGR, KDBR, CDBR, CEBR, CGHI, CHI, CGFI, CLGFI, CFI, CLFI:
+		switch inst.Op {
+		case CGHI, CGFI, CGR:
+			op = "CMP"
+		case CHI, CFI, CR:
+			op = "CMPW"
+		case CLGFI, CLGR:
+			op = "CMPU"
+		case CLFI, CLR:
+			op = "CMPWU"
+		case CDBR:
+			op = "FCMPU"
+		case KDBR:
+			op = "FCMPO"
+		}
+	case CEFBRA, CDFBRA, CEGBRA, CDGBRA, CELFBR, CDLFBR, CELGBR, CDLGBR, CFEBRA, CFDBRA, CGEBRA, CGDBRA, CLFEBR, CLFDBR, CLGEBR, CLGDBR:
+		args[0], args[1] = args[2], args[0]
+		args = args[:2]
+	case CGRJ, CGIJ:
+		mask, err := strconv.Atoi(args[2][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		var check bool
+		switch mask & 0xf {
+		case 2:
+			op = "CMPBGT"
+			check = true
+		case 4:
+			op = "CMPBLT"
+			check = true
+		case 6:
+			op = "CMPBNE"
+			check = true
+		case 8:
+			op = "CMPBEQ"
+			check = true
+		case 10:
+			op = "CMPBGE"
+			check = true
+		case 12:
+			op = "CMPBLE"
+			check = true
+		}
+		if check {
+			args[2] = args[3]
+			args = args[:3]
+		}
+	case CLGRJ, CLGIJ:
+		mask, err := strconv.Atoi(args[2][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		var check bool
+		switch mask & 0xf {
+		case 2:
+			op = "CMPUBGT"
+			check = true
+		case 4:
+			op = "CMPUBLT"
+			check = true
+		case 7:
+			op = "CMPUBNE"
+			check = true
+		case 8:
+			op = "CMPUBEQ"
+			check = true
+		case 10:
+			op = "CMPUBGE"
+			check = true
+		case 12:
+			op = "CMPUBLE"
+			check = true
+		}
+		if check {
+			args[2] = args[3]
+			args = args[:3]
+		}
+	case CLRJ, CRJ, CIJ, CLIJ:
+		args[0], args[1], args[2], args[3] = args[2], args[0], args[1], args[3]
+	case BRC, BRCL:
+		mask, err := strconv.Atoi(args[0][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		opStr, check := branch_relative_op(mask, inst.Op)
+		if opStr != "" {
+			op = opStr
+		}
+		if check {
+			args[0] = args[1]
+			args = args[:1]
+		}
+	case BCR:
+		mask, err := strconv.Atoi(args[0][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		opStr, check := branchOnConditionOp(mask, inst.Op)
+		if opStr != "" {
+			op = opStr
+		}
+		if op == "SYNC" || op == "NOPH" {
+			return op
+		}
+		if check {
+			args[0] = args[1]
+			args = args[:1]
+		}
+	case LOCGR:
+		mask, err := strconv.Atoi(args[2][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		var check bool
+		switch mask & 0xf {
+		case 2: //Greaterthan (M=2)
+			op = "MOVDGT"
+			check = true
+		case 4: //Lessthan (M=4)
+			op = "MOVDLT"
+			check = true
+		case 7: // Not Equal (M=7)
+			op = "MOVDNE"
+			check = true
+		case 8: // Equal (M=8)
+			op = "MOVDEQ"
+			check = true
+		case 10: // Greaterthan or Equal (M=10)
+			op = "MOVDGE"
+			check = true
+		case 12: // Lessthan or Equal (M=12)
+			op = "MOVDLE"
+			check = true
+		}
+		if check {
+			args[0], args[1] = args[1], args[0]
+			args = args[:2]
+		} else {
+			args[0], args[1], args[2] = args[2], args[1], args[0]
+		}
+	case BRASL:
+		op = "CALL" // BL
+		args[0] = args[1]
+		args = args[:1]
+	case X, XY, XG:
+		switch inst.Op {
+		case X, XY:
+			op = "XORW"
+		case XG:
+			op = "XOR"
+		}
+	case N, NY, NG, O, OY, OG, XC, NC, OC, MVC, MVCIN, CLC:
+		switch inst.Op {
+		case N, NY:
+			op = "ANDW"
+		case NG:
+			op = "AND"
+		case O, OY:
+			op = "ORW"
+		case OG:
+			op = "OR"
+		}
+		args[0], args[1] = args[1], args[0]
+	case S, SY, SLBG, SLG, SG:
+		switch inst.Op {
+		case S, SY:
+			op = "SUBW"
+		case SLBG:
+			op = "SUBE"
+		case SLG:
+			op = "SUBC"
+		case SG:
+			op = "SUB"
+		}
+		args[0], args[1] = args[1], args[0]
+	case MSG, MSY, MS:
+		switch inst.Op {
+		case MSG:
+			op = "MULLD"
+		case MSY, MS:
+			op = "MULLW"
+		}
+	case A, AY, ALCG, ALG, AG:
+		switch inst.Op {
+		case A, AY:
+			op = "ADDW"
+		case ALCG:
+			op = "ADDE"
+		case ALG:
+			op = "ADDC"
+		case AG:
+			op = "ADD"
+		}
+		args[0], args[1] = args[1], args[0]
+	case RISBG, RISBGN, RISBHG, RISBLG, RNSBG, RXSBG, ROSBG:
+		switch inst.Op {
+		case RNSBG, RXSBG, ROSBG:
+			num, err := strconv.Atoi(args[2][1:])
+			if err != nil {
+				return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+			}
+			if ((num >> 7) & 0x1) != 0 {
+				op = op + "T"
+			}
+		case RISBG, RISBGN, RISBHG, RISBLG:
+			num, err := strconv.Atoi(args[3][1:])
+			if err != nil {
+				return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+			}
+			if ((num >> 7) & 0x1) != 0 {
+				op = op + "Z"
+			}
+		}
+		if len(args) == 5 {
+			args[0], args[1], args[2], args[3], args[4] = args[2], args[3], args[4], args[1], args[0]
+		} else {
+			args[0], args[1], args[2], args[3] = args[2], args[3], args[1], args[0]
+		}
+
+	case VEC, VECL, VCLZ, VCTZ, VREPI, VPOPCT: //mnemonic V1, V2, M3
+		mask, err := strconv.Atoi(args[2][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi for %q:%s", op, err)
+		}
+		val := mask & 0x7
+		if val >= 0 && val < 4 {
+			op = op + vectorSize[val]
+			args = args[:2]
+		} else {
+			return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+		}
+		switch inst.Op {
+		case VCLZ, VCTZ, VREPI, VPOPCT:
+			args[0], args[1] = args[1], args[0]
+		default:
+		}
+		//Mnemonic V1, V2, V3, M4 or Mnemonic V1, I2, I3, M4 or Mnemonic V1, V3, I2, M4
+	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:
+		mask, err := strconv.Atoi(args[3][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		val := mask & 0x7
+		switch inst.Op {
+		case VA, VS, VACC, VSCBI:
+			if val >= 0 && val < 5 {
+				if args[0] == args[2] {
+					args[0], args[1] = args[1], args[0]
+					args = args[:2]
+				} else if inst.Op == VS {
+					if args[0] == args[1] {
+						args[0] = args[2]
+						args = args[:2]
+					} else {
+						args[0], args[2] = args[2], args[0]
+						args = args[:3]
+					}
+				} else {
+					args[0], args[1], args[2] = args[1], args[2], args[0]
+					args = args[:3]
+				}
+				op = op + vectorSize[val]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+			}
+		case VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM:
+			if val >= 0 && val < 4 {
+				op = op + vectorSize[val]
+				args[0], args[1], args[2] = args[1], args[2], args[0]
+				args = args[:3]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+			}
+		case VREP, VERLLV, VESLV:
+			if val >= 0 && val < 4 {
+				op = op + vectorSize[val]
+				args[0], args[1], args[2] = args[2], args[1], args[0]
+				args = args[:3]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+			}
+		case VSUM, VSUMG, VSUMQ:
+			var off int
+			switch inst.Op {
+			case VSUM:
+				off = 0
+			case VSUMG:
+				off = 1
+			case VSUMQ:
+				off = 2
+			}
+			if (val > (-1 + off)) && (val < (2 + off)) {
+				op = op + vectorSize[val]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+			}
+			args = args[:3]
+		case VML, VMH, VMLH, VME, VMLE, VMO, VMLO:
+			if val >= 0 && val < 3 {
+				op = op + vectorSize[val]
+			}
+			if op == "VML" && val == 2 {
+				op = op + "W"
+			}
+			if args[0] == args[2] {
+				args[0], args[1] = args[1], args[0]
+				args = args[:2]
+			} else {
+				args[0], args[1], args[2] = args[1], args[2], args[0]
+				args = args[:3]
+			}
+		}
+
+	case VGFMA, VERIM, VMAH, VMALH: // Mnemonic V1, V2, V3, V4/I4, M5
+		mask, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		val := mask & 0x7
+		args = args[:4]
+		var off int
+		switch inst.Op {
+		case VMAH, VMALH:
+			off = -1
+		}
+
+		if val >= 0 && val < (4+off) {
+			op = op + vectorSize[val]
+		} else {
+			return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+		}
+		switch inst.Op {
+		case VGFMA, VMAH, VMALH:
+			args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
+		default:
+			args[0], args[3] = args[3], args[0]
+		}
+	case VSTRC, VFAE, VFEE, VFENE:
+		var off uint8
+		switch inst.Op {
+		case VSTRC:
+			off = uint8(1)
+		default:
+			off = uint8(0)
+		}
+		m1, err := strconv.Atoi(args[3+off][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		m2, err := strconv.Atoi(args[4+off][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		index := m1 & 0x3
+		if index < 0 || index > 2 {
+			return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
+		}
+		switch m2 {
+		case 0:
+			op = op + vectorSize[index]
+		case 1:
+			op = op + vectorCS[index]
+		case 2:
+			op = op + "Z" + vectorSize[index]
+		case 3:
+			op = op + "Z" + vectorCS[index]
+		default:
+			return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2)
+		}
+		switch inst.Op {
+		case VSTRC:
+			args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
+		default:
+			args[0], args[1], args[2] = args[1], args[2], args[0]
+		}
+		args = args[:3+off]
+
+	case VCEQ, VCH, VCHL: // Mnemonic V1, V2, V3, M4, M5
+		m4, err := strconv.Atoi(args[3][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		m5, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		val := (m4 & 0x7)
+		if m5 == 0 {
+			if val >= 0 && val < 4 {
+				op = op + vectorSize[val]
+				args[0], args[1], args[2] = args[1], args[2], args[0]
+				args = args[:3]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
+			}
+		} else if m5 == 1 {
+			if val >= 0 && val < 4 {
+				op = op + vectorCS[val]
+				args[0], args[1], args[2] = args[1], args[2], args[0]
+				args = args[:3]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
+			}
+		} else {
+			return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
+		}
+	case VFMA, VFMS, VMSL: //Mnemonic V1, V2, V3, V4, M5, M6
+		m5, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		m6, err := strconv.Atoi(args[5][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		switch inst.Op {
+		case VMSL:
+			if m5 == 3 && m6 == 8 {
+				op = op + "EG"
+			} else if m5 == 3 && m6 == 4 {
+				op = op + "OG"
+			} else if m5 == 3 && m6 == 12 {
+				op = op + "EOG"
+			} else if m5 == 3 {
+				op = op + "G"
+			}
+		default:
+			if m5 == 0 && m6 == 3 {
+				op = op + "DB"
+			} else if m5 == 8 && m6 == 3 {
+				op = "W" + op[1:] + "DB"
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with m5: %v m6: %v \n", op, m5, m6)
+			}
+		}
+		args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
+		args = args[:4]
+
+	case VFCE, VFCH, VFCHE: //Mnemonic V1,V2,V3,M4,M5,M6
+		m4, err := strconv.Atoi(args[3][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		m5, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		m6, err := strconv.Atoi(args[5][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		if m5 == 0 {
+			if m4 == 3 && m6 == 0 {
+				op = op + "DB"
+			} else if m4 == 3 && m6 == 1 {
+				op = op + "DBS"
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
+			}
+
+		} else if m5 == 8 {
+			if m4 == 3 && m6 == 0 {
+				op = "W" + op[1:] + "DB"
+			} else if m4 == 3 && m6 == 1 {
+				op = "W" + op[1:] + "DBS"
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6)
+			}
+		} else {
+			return fmt.Sprintf("specification exception is recognized for %q with m5: %v \n", op, m5)
+		}
+		args[0], args[1], args[2] = args[1], args[2], args[0]
+		args = args[:3]
+
+	case VFTCI:
+		m4, err := strconv.Atoi(args[3][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		m5, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err)
+		}
+		val := (m4 & 0x7)
+		if m5 == 0 {
+			switch val {
+			case 2:
+				op = op + "SB"
+			case 3:
+				op = op + "DB"
+			default:
+				return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
+			}
+		} else if m5 == 8 {
+			switch val {
+			case 2:
+				op = "W" + op[1:] + "SB"
+			case 3:
+				op = "W" + op[1:] + "DB"
+			case 4:
+				op = "W" + op[1:] + "XB"
+			default:
+				return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4)
+			}
+		} else {
+			return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5)
+		}
+		args[0], args[1], args[2] = args[2], args[1], args[0]
+		args = args[:3]
+	case VAC, VACCC:
+		mask, err := strconv.Atoi(args[4][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		if mask&0x04 == 0 {
+			return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask)
+		}
+		op = op + "Q"
+		args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0]
+		args = args[:4]
+	case VL, VLREP:
+		switch inst.Op {
+		case VL:
+			args[0], args[1] = args[1], args[0]
+		case VLREP:
+			args[0], args[1] = args[1], args[0]
+			mask, err := strconv.Atoi(args[2][1:])
+			if err != nil {
+				return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+			}
+			if mask >= 0 && mask < 4 {
+				op = op + vectorSize[mask]
+			}
+		}
+		args = args[:2]
+	case VST, VSTEB, VSTEH, VSTEF, VSTEG, VLEB, VLEH, VLEF, VLEG: //Mnemonic V1, D2(X2,B2), M3
+		m, err := strconv.Atoi(args[2][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		switch inst.Op {
+		case VST:
+			if m == 0 || (m > 2 && m < 5) {
+				args = args[:2]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
+			}
+		case VLEB, VLEH, VLEF, VLEG:
+			args[0], args[2] = args[2], args[0]
+		default:
+			args[0], args[1], args[2] = args[2], args[0], args[1]
+		}
+	case VSTM, VSTL, VESL, VESRA, VLM, VERLL, VLVG: //Mnemonic V1, V3, D2(B2)[,M4] or V1, R3,D2(B2)
+		switch inst.Op {
+		case VSTM, VLM:
+			m, err := strconv.Atoi(args[3][1:])
+			if err != nil {
+				return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+			}
+			if !(m == 0 || (m > 2 && m < 5)) {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
+			}
+			if inst.Op == VLM {
+				args[0], args[1], args[2] = args[2], args[0], args[1]
+			}
+			args = args[:3]
+		case VESL, VESRA, VERLL, VLVG:
+			m, err := strconv.Atoi(args[3][1:])
+			if err != nil {
+				return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+			}
+			if m >= 0 && m < 4 {
+				op = op + vectorSize[m]
+			} else {
+				return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m)
+			}
+			switch inst.Op {
+			case VLVG:
+				args[0], args[2] = args[2], args[0]
+				args = args[:3]
+			default:
+				if args[0] == args[1] {
+					args[0], args[1] = args[2], args[1]
+					args = args[:2]
+					break
+				}
+				args[0], args[2] = args[2], args[0]
+				args = args[:3]
+			}
+		case VSTL:
+			args[0], args[1] = args[1], args[0]
+			args = args[:3]
+		}
+	case VGBM:
+		val, err := strconv.Atoi(args[1][1:])
+		if err != nil {
+			return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err)
+		}
+		if val == 0 {
+			op = "VZERO"
+			args = args[:1]
+		} else if val == 0xffff {
+			op = "VONE"
+			args = args[:1]
+		} else {
+			args[0], args[1] = args[1], args[0]
+			args = args[:2]
+		}
+	case VN, VNC, VO, VX, VNO: //mnemonic V1, V2, V3
+		if args[0] == args[2] {
+			args = args[:2]
+			args[0], args[1] = args[1], args[0]
+		} else {
+			args[0], args[1], args[2] = args[1], args[2], args[0]
+		}
+		if op == "VNO" {
+			op = op + "T"
+		}
+	case VGEG, VGEF, VSCEG, VSCEF: //Mnemonic V1, D2(V2, B2), M3
+		args[0], args[2] = args[2], args[0]
+
+	}
+	if args != nil {
+		op += " " + strings.Join(args, ", ")
+	}
+
+	return op
+}
+
+// This function returns corresponding extended mnemonic for the given
+// branch on relative mnemonic.
+func branch_relative_op(mask int, opconst Op) (op string, check bool) {
+	switch mask & 0xf {
+	case 2:
+		op = "BGT"
+		check = true
+	case 4:
+		op = "BLT"
+		check = true
+	case 5:
+		op = "BLTU"
+		check = true
+	case 7:
+		op = "BNE"
+		check = true
+	case 8:
+		op = "BEQ"
+		check = true
+	case 10:
+		op = "BGE"
+		check = true
+	case 12:
+		op = "BLE"
+		check = true
+	case 13:
+		op = "BLEU"
+		check = true
+	case 15:
+		op = "JMP" // BR
+		check = true
+	}
+	return op, check
+}
+
+// This function returns corresponding extended mnemonic for the given
+// brach on condition mnemonic.
+func branchOnConditionOp(mask int, opconst Op) (op string, check bool) {
+	switch mask & 0xf {
+	case 0:
+		op = "NOPH"
+	case 14:
+		op = "SYNC"
+	case 15:
+		op = "JMP"
+		check = true
+	}
+	return op, check
+}
+
+// This function returns corresponding plan9 mnemonic for the native bitwise mnemonic.
+func bitwise_op(op Op) string {
+	var ret string
+	switch op {
+	case NGR, NGRK, NILL:
+		ret = "AND"
+	case NR, NRK, NILH, NILF:
+		ret = "ANDW"
+	case OGR, OGRK, OILF:
+		ret = "OR"
+	case OR, ORK, OILH, OILL:
+		ret = "ORW"
+	case XGR, XGRK, XILF:
+		ret = "XOR"
+	case XR, XRK:
+		ret = "XORW"
+	}
+	return ret
+}
+
+// This function parses memory operand of type D(B)
+func mem_operand(args []string) string {
+	if args[0] != "" && args[1] != "" {
+		args[0] = fmt.Sprintf("%s(%s)", args[0], args[1])
+	} else if args[0] != "" {
+		args[0] = fmt.Sprintf("$%s", args[0])
+	} else if args[1] != "" {
+		args[0] = fmt.Sprintf("(%s)", args[1])
+	} else {
+		args[0] = ""
+	}
+	return args[0]
+}
+
+// This function parses memory operand of type D(X,B)
+func mem_operandx(args []string) string {
+	if args[1] != "" && args[2] != "" {
+		args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
+	} else if args[1] != "" {
+		args[1] = fmt.Sprintf("(%s)", args[1])
+	} else if args[2] != "" {
+		args[1] = fmt.Sprintf("(%s)", args[2])
+	} else if args[0] != "" {
+		args[1] = ""
+	}
+	if args[0] != "" && args[1] != "" {
+		args[0] = fmt.Sprintf("%s%s", args[0], args[1])
+	} else if args[0] != "" {
+		args[0] = fmt.Sprintf("$%s", args[0])
+	} else if args[1] != "" {
+		args[0] = fmt.Sprintf("%s", args[1])
+	} else {
+		args[0] = ""
+	}
+	return args[0]
+}
+
+// This function parses memory operand of type D(V,B)
+func mem_operandv(args []string) string {
+	if args[1] != "" && args[2] != "" {
+		args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1])
+	} else if args[1] != "" {
+		args[1] = fmt.Sprintf("(%s*1)", args[1])
+	} else if args[2] != "" {
+		args[1] = fmt.Sprintf("(%s)", args[2])
+	} else if args[0] != "" {
+		args[1] = ""
+	}
+	if args[0] != "" && args[1] != "" {
+		args[0] = fmt.Sprintf("%s%s", args[0], args[1])
+	} else if args[0] != "" {
+		args[0] = fmt.Sprintf("$%s", args[0])
+	} else if args[1] != "" {
+		args[0] = fmt.Sprintf("%s", args[1])
+	} else {
+		args[0] = ""
+	}
+	return args[0]
+}
+
+// This function parses memory operand of type D(L,B)
+func mem_operandl(args []string) (string, string) {
+	if args[0] != "" && args[2] != "" {
+		args[0] = fmt.Sprintf("%s(%s)", args[0], args[2])
+	} else if args[2] != "" {
+		args[0] = fmt.Sprintf("(%s)", args[2])
+	} else {
+		args[0] = fmt.Sprintf("%s", args[0])
+	}
+	return args[0], args[1]
+}
+
+// plan9Arg formats arg (which is the argIndex's arg in inst) according to Plan 9 rules.
+// NOTE: because Plan9Syntax is the only caller of this func, and it receives a copy
+// of inst, it's ok to modify inst.Args here.
+func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
+	switch arg.(type) {
+	case Reg:
+		if arg == R13 {
+			return "g"
+		}
+		return strings.ToUpper(arg.String(pc)[1:])
+	case Base:
+		if arg == R13 {
+			return "g"
+		}
+		s := arg.String(pc)
+		if s != "" {
+			return strings.ToUpper(s[1 : len(s)-1])
+		}
+		return "R0"
+	case Index:
+		if arg == R13 {
+			return "g"
+		}
+		s := arg.String(pc)
+		if s != "" {
+			return strings.ToUpper(s[1:])
+		}
+		return ""
+	case VReg:
+		return strings.ToUpper(arg.String(pc)[1:])
+	case Disp20, Disp12:
+		numstr := arg.String(pc)
+		num, err := strconv.Atoi(numstr[:len(numstr)])
+		if err != nil {
+			return fmt.Sprintf("plan9Arg: error in converting Atoi:%s", err)
+		}
+		if num == 0 {
+			return ""
+		} else {
+			return strconv.Itoa(num)
+		}
+	case RegIm12, RegIm16, RegIm24, RegIm32:
+		addr, err := strconv.ParseUint(arg.String(pc)[2:], 16, 64)
+		if err != nil {
+			return fmt.Sprintf("plan9Arg: error in converting ParseUint:%s", err)
+		}
+		off := int(addr - pc)
+		s, base := symname(addr)
+		if s != "" && addr == base {
+			return fmt.Sprintf("%s(SB)", s)
+		}
+		off = off / inst.Len
+		return fmt.Sprintf("%v(PC)", off)
+	case Imm, Sign8, Sign16, Sign32:
+		numImm := arg.String(pc)
+		switch arg.(type) {
+		case Sign32, Sign16, Imm:
+			num, err := strconv.ParseInt(numImm, 10, 64)
+			if err != nil {
+				return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err)
+			}
+			switch inst.Op {
+			case LLIHF:
+				num = num << 32
+			case LLILH:
+				num = num << 16
+			case NILH:
+				num = (num << 16) | int64(0xFFFF)
+			case OILH:
+				num = num << 16
+			}
+			numImm = fmt.Sprintf("%d", num)
+		}
+		return fmt.Sprintf("$%s", numImm)
+	case Mask, Len:
+		num := arg.String(pc)
+		return fmt.Sprintf("$%s", num)
+	}
+	return fmt.Sprintf("???(%v)", arg)
+}
+
+// It checks any 2 args of given instructions to swap or not
+func reverseOperandOrder(op Op) bool {
+	switch op {
+	case LOCR, MLGR:
+		return true
+	case LTEBR, LTDBR:
+		return true
+	case VLEIB, VLEIH, VLEIF, VLEIG, VPDI:
+		return true
+	case VSLDB:
+		return true
+	}
+	return false
+}
+
+// It checks whether to reverse all the args of given mnemonic or not
+func reverseAllOperands(op Op) bool {
+	switch op {
+	case VLVGP: //3-operand list
+		return true
+	case VSEL, VPERM: //4-Operand list
+		return true
+	}
+	return false
+}
diff --git a/s390x/s390xasm/testdata/decode.txt b/s390x/s390xasm/testdata/decode.txt
new file mode 100644
index 0000000..f04715b
--- /dev/null
+++ b/s390x/s390xasm/testdata/decode.txt
@@ -0,0 +1,162 @@
+    b9040021|	plan9	MOVD R1, R2
+    b9140043|	plan9	MOVW R3, R4
+    b9070065|	plan9	MOVH R5, R6
+    b9060087|	plan9	MOVB R7, R8
+    b9160021|	plan9	MOVWZ R1, R2
+    b9850032|	plan9	MOVHZ R2, R3
+    b9840054|	plan9	MOVBZ R4, R5
+    b90f0021|	plan9	MOVDBR R1, R2
+    b91f0043|	plan9	MOVWBR R3, R4
+    b9e28010|	plan9	MOVDEQ R0, R1
+    b9e2a032|	plan9	MOVDGE R2, R3
+    b9e22054|	plan9	MOVDGT R4, R5
+    b9e2c076|	plan9	MOVDLE R6, R7
+    b9e24098|	plan9	MOVDLT R8, R9
+    b9e270ba|	plan9	MOVDNE R10, R11
+    b9f23012|	plan9	LOCR $3, R2, R1
+    b9e27065|	plan9	MOVDNE R5, R6
+e310f0000004|	plan9	MOVD (R15), R1
+e320f0000014|	plan9	MOVW (R15), R2
+e330f0000015|	plan9	MOVH (R15), R3
+e340f0000077|	plan9	MOVB (R15), R4
+e350f0000016|	plan9	MOVWZ (R15), R5
+e360f0000091|	plan9	MOVHZ (R15), R6
+e370f0000090|	plan9	MOVBZ (R15), R7
+e380f000000f|	plan9	MOVDBR (R15), R8
+e390f000001e|	plan9	MOVWBR (R15), R9
+e310fff8ff24|	plan9	MOVD R1, -8(R15)
+e320fff8ff50|	plan9	MOVW R2, -8(R15)
+e330fff8ff70|	plan9	MOVH R3, -8(R15)
+e340fff8ff72|	plan9	MOVB R4, -8(R15)
+e350fff8ff2f|	plan9	MOVDBR R5, -8(R15)
+e360fff8ff3e|	plan9	MOVWBR R6, -8(R15)
+c01efffffffe|	plan9	MOVD $-8589934592, R1
+c021fffe0000|	plan9	MOVW $-131072, R2
+    a739fe00|	plan9	MOVH $-512, R3
+    a749ffff|	plan9	MOVB $-1, R4
+    b9e81022|	plan9	ADD R1, R2
+    b9e81032|	plan9	ADD R1, R2, R3
+    a71b2000|	plan9	ADD $8192, R1
+ec21200000d9|	plan9	ADD $8192, R1, R2
+c21800008000|	plan9	ADD $32768, R1
+    b9ea1022|	plan9	ADDC R1, R2
+    b9ea1032|	plan9	ADDC R1, R2, R3
+ec21000100db|	plan9	ADDC $1, R1, R2
+ec21ffff00db|	plan9	SUBC $1, R1, R2
+        1a21|	plan9	ADDW R1, R2
+    b9f81032|	plan9	ADDW R1, R2, R3
+    a71a2000|	plan9	ADDW $8192, R1
+ec21200000d8|	plan9	ADDW $8192, R1, R2
+    b9880021|	plan9	ADDE R1, R2
+e3201000000a|	plan9	ADDC (R1), R2
+    5a605000|	plan9	ADDW (R5), R6
+    5a807fff|	plan9	ADDW 4095(R7), R8
+e3201fffff5a|	plan9	ADDW -1(R1), R2
+e34030000188|	plan9	ADDE 4096(R3), R4
+e34230000188|	plan9	ADDE 4096(R3)(R2*1), R4
+    b9090043|	plan9	SUB R3, R4
+    b9e93054|	plan9	SUB R3, R4, R5
+    a73be000|	plan9	SUB $8192, R3
+ec43e00000d9|	plan9	SUB $8192, R3, R4
+    b90b0021|	plan9	SUBC R1, R2
+ec43ffff00db|	plan9	SUBC $1, R3, R4
+    b9eb2043|	plan9	SUBC R2, R3, R4
+        1b43|	plan9	SUBW R3, R4
+    b9f93054|	plan9	SUBW R3, R4, R5
+c21500002000|	plan9	SUBW $8192, R1
+e320400f0089|	plan9	SUBE 15(R4), R2
+e32040080009|	plan9	SUB 8(R4), R2
+    5b204000|	plan9	SUBW (R4), R2
+e3204fffff5b|	plan9	SUBW -1(R4), R2
+    b91c0076|	plan9	MULLW R6, R7
+    a76c2000|	plan9	MULLW $8192, R6
+c2810000000f|	plan9	MULLW $15, R8
+c281ffff7fff|	plan9	MULLW $-32769, R8
+c21080000000|	plan9	MULLD $-2147483648, R1
+    b9860021|	plan9	MLGR R1, R2
+    b9030011|	plan9	NEG R1
+    b9030021|	plan9	NEG R1, R2
+    b9130011|	plan9	NEGW R1
+    b9130021|	plan9	NEGW R1, R2
+    b9830022|	plan9	FLOGR R2, R2
+    b9800021|	plan9	AND R1, R2
+    b9e42031|	plan9	AND R1, R2, R3
+    a517ffff|	plan9	ANDW $-1, R1
+c01bffff0000|	plan9	AND $-65536, R1
+        1421|	plan9	ANDW R1, R2
+    b9f42031|	plan9	ANDW R1, R2, R3
+c01b00000001|	plan9	ANDW $1, R1
+    a5160001|	plan9	ANDW $131071, R1
+c01b00010000|	plan9	ANDW $65536, R1
+    a517fffe|	plan9	ANDW $-2, R1
+    a517000f|	plan9	AND $15, R1
+e32010000080|	plan9	AND (R1), R2
+    54201000|	plan9	ANDW (R1), R2
+e32010000154|	plan9	ANDW 4096(R1), R2
+    b9810021|	plan9	OR R1, R2
+    b9e62031|	plan9	OR R1, R2, R3
+    a51a0001|	plan9	ORW $65536, R1
+    a51bffff|	plan9	ORW $-1, R1
+    a51b0001|	plan9	ORW $1, R1
+        1621|	plan9	ORW R1, R2
+c01d0001ffff|	plan9	OR $131071, R1
+c01dffffffff|	plan9	ORW $-1, R1
+    b9f62031|	plan9	ORW R1, R2, R3
+e32010000081|	plan9	OR (R1), R2
+    56201000|	plan9	ORW (R1), R2
+e3201fffff56|	plan9	ORW -1(R1), R2
+    b9820021|	plan9	XOR R1, R2
+    b9e72031|	plan9	XOR R1, R2, R3
+c01700000001|	plan9	XOR $1, R1
+c0170001ffff|	plan9	XOR $131071, R1
+c01700010000|	plan9	XOR $65536, R1
+        1721|	plan9	XORW R1, R2
+    b9f72031|	plan9	XORW R1, R2, R3
+c017fffffffe|	plan9	XORW $-2, R1
+        0700|	plan9	NOPH
+        07e0|	plan9	SYNC
+    b92e0024|	plan9	KM R2, R4
+    b92f0026|	plan9	KMC R2, R6
+    b93f0028|	plan9	KLMD R2, R8
+    b93e0004|	plan9	KIMD R0, R4
+    b93a0008|	plan9	KDSA R0, R8
+    b9296024|	plan9	KMA R2, R6, R4
+    b92d6024|	plan9	KMCTR R2, R6, R4
+e743400000f3|	plan9	VAB V3, V4
+e743600000f3|	plan9	VAB V3, V6, V4
+e743400010f3|	plan9	VAH V3, V4
+e743600010f3|	plan9	VAH V3, V6, V4
+e743400020f3|	plan9	VAF V3, V4
+e743600020f3|	plan9	VAF V3, V6, V4
+e743400030f3|	plan9	VAG V3, V4
+e743600030f3|	plan9	VAG V3, V6, V4
+e743400040f3|	plan9	VAQ V3, V4
+e743600040f3|	plan9	VAQ V3, V6, V4
+e734600000f7|	plan9	VSB V6, V4, V3
+e722100000f7|	plan9	VSB V1, V2
+e734600010f7|	plan9	VSH V6, V4, V3
+e722100010f7|	plan9	VSH V1, V2
+e734600020f7|	plan9	VSF V6, V4, V3
+e722100020f7|	plan9	VSF V1, V2
+e734600030f7|	plan9	VSG V6, V4, V3
+e722100030f7|	plan9	VSG V1, V2
+e734600040f7|	plan9	VSQ V6, V4, V3
+e722100040f7|	plan9	VSQ V1, V2
+e7824000608a|	plan9	VSTRCB V2, V4, V6, V8
+e7824100608a|	plan9	VSTRCH V2, V4, V6, V8
+e7824200608a|	plan9	VSTRCF V2, V4, V6, V8
+e7824010608a|	plan9	VSTRCBS V2, V4, V6, V8
+e7824110608a|	plan9	VSTRCHS V2, V4, V6, V8
+e7824210608a|	plan9	VSTRCFS V2, V4, V6, V8
+e710ffff0044|	plan9	VONE V1
+e70000000844|	plan9	VZERO V16
+e70210000068|	plan9	VN V2, V1, V0
+e71010000468|	plan9	VN V16, V1
+e70210000069|	plan9	VNC V2, V1, V0
+e71010000469|	plan9	VNC V16, V1
+e7021000006a|	plan9	VO V2, V1, V0
+e7101000046a|	plan9	VO V16, V1
+e7021000006d|	plan9	VX V2, V1, V0
+e7101000046d|	plan9	VX V16, V1
+e7101000046b|	plan9	VNOT V16, V1
+e78340000062|	plan9	VLVGP R3, R4, V8