aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--arm.risu218
-rwxr-xr-xbuild-all-archs3
-rw-r--r--comms.c34
-rwxr-xr-xconfigure4
-rw-r--r--loongarch64.risu2881
-rw-r--r--reginfo.c183
-rw-r--r--risu.c526
-rw-r--r--risu.h95
-rw-r--r--risu_aarch64.c6
-rw-r--r--risu_arm.c6
-rw-r--r--risu_i386.c4
-rw-r--r--risu_loongarch64.c50
-rw-r--r--risu_m68k.c4
-rw-r--r--risu_ppc64.c4
-rw-r--r--risu_reginfo_aarch64.c226
-rw-r--r--risu_reginfo_aarch64.h49
-rw-r--r--risu_reginfo_arm.c10
-rw-r--r--risu_reginfo_i386.c12
-rw-r--r--risu_reginfo_loongarch64.c268
-rw-r--r--risu_reginfo_loongarch64.h26
-rw-r--r--risu_reginfo_m68k.c10
-rw-r--r--risu_reginfo_ppc64.c39
-rw-r--r--risu_reginfo_ppc64.h3
-rw-r--r--risu_reginfo_s390x.c140
-rw-r--r--risu_reginfo_s390x.h25
-rw-r--r--risu_s390x.c51
-rwxr-xr-xrisugen2
-rw-r--r--risugen_loongarch64.pm530
-rw-r--r--risugen_s390x.pm186
-rw-r--r--s390x.risu81
-rw-r--r--test_loongarch64.s92
-rw-r--r--test_s390x.S53
33 files changed, 5182 insertions, 641 deletions
diff --git a/Makefile b/Makefile
index 6ab014a..ad7f879 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ CFLAGS ?= -g
ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) -U$(ARCH) $(BUILD_INC) $(CFLAGS) $(EXTRA_CFLAGS)
PROG=risu
-SRCS=risu.c comms.c reginfo.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
+SRCS=risu.c comms.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
HDRS=risu.h risu_reginfo_$(ARCH).h
BINS=test_$(ARCH).bin
diff --git a/arm.risu b/arm.risu
index 048215b..adebf37 100644
--- a/arm.risu
+++ b/arm.risu
@@ -456,6 +456,9 @@ VLDST_UNDEF A1c 1111 0100 1 x 0 0 any:8 11 any2:10
# space (table A7-9 in DDI0406B)
# We include UNDEF combinations here; there are no
# UNPREDICTABLE encodings we need to avoid.
+# We avoid size encodings that are fp16 under the v8.2-FP16 extension:
+# sz=1 for the float insns which have a 1-bit size field in bit 20,
+# and instead hard-wire that bit to 0.
###########################################################
VHADD A1 1111 001 u 0 d sz:2 vn:4 vd:4 0000 n q m 0 vm:4
@@ -471,9 +474,9 @@ VORN A1 1111 0010 0 d 11 vn:4 vd:4 0001 n q m 1 vm:4
VEOR_VBIT A1 1111 0011 0 d op:2 vn:4 vd:4 0001 n q m 1 vm:4
VQSUB A1 1111 001 u 0 d sz:2 vn:4 vd:4 0010 n q m 1 vm:4
VCGT A1 1111 001 u 0 d sz:2 vn:4 vd:4 0011 n q m 0 vm:4
-VCGT A2 1111 0011 0 d 1 sz vn:4 vd:4 1110 n q m 0 vm:4
+VCGT A2 1111 0011 0 d 1 0 vn:4 vd:4 1110 n q m 0 vm:4
VCGE A1 1111 001 u 0 d sz:2 vn:4 vd:4 0011 n q m 1 vm:4
-VCGE A2 1111 0011 0 d 0 sz vn:4 vd:4 1110 n q m 0 vm:4
+VCGE A2 1111 0011 0 d 0 0 vn:4 vd:4 1110 n q m 0 vm:4
VSHL A1 1111 001 u 0 d sz:2 vn:4 vd:4 0100 n q m 0 vm:4
VQSHL A1 1111 001 u 0 d sz:2 vn:4 vd:4 0100 n q m 1 vm:4
VRSHL A1 1111 001 u 0 d sz:2 vn:4 vd:4 0101 n q m 0 vm:4
@@ -486,7 +489,7 @@ VADD A1 1111 0010 0 d sz:2 vn:4 vd:4 1000 n q m 0 vm:4
VSUB A1 1111 0011 0 d sz:2 vn:4 vd:4 1000 n q m 0 vm:4
VTST A1 1111 0010 0 d sz:2 vn:4 vd:4 1000 n q m 1 vm:4
VCEQ A1 1111 0011 0 d sz:2 vn:4 vd:4 1000 n q m 1 vm:4
-VCEQ A2 1111 0010 0 d 0 sz vn:4 vd:4 1110 n q m 0 vm:4
+VCEQ A2 1111 0010 0 d 0 0 vn:4 vd:4 1110 n q m 0 vm:4
VMLA A1 1111 001 op 0 d sz:2 vn:4 vd:4 1001 n q m 0 vm:4
VMUL A1 1111 001 op 0 d sz:2 vn:4 vd:4 1001 n q m 1 vm:4
VPMAX A1 1111 001 u 0 d sz:2 vn:4 vd:4 1010 n q m 0 vm:4
@@ -495,22 +498,22 @@ VQDMULH A1 1111 0010 0 d sz:2 vn:4 vd:4 1011 n q m 0 vm:4
VQRDMULH A1 1111 0011 0 d sz:2 vn:4 vd:4 1011 n q m 0 vm:4
VPADD A1 1111 0010 0 d sz:2 vn:4 vd:4 1011 n q m 1 vm:4
# NB: VFM is VFPv4 only. There is no Neon encoding for VFNM.
-VFM A1 1111 0010 0 d op sz vn:4 vd:4 1100 n q m 1 vm:4
-VADD_float A1 1111 0010 0 d 0 sz vn:4 vd:4 1101 n q m 0 vm:4
-VSUB_float A1 1111 0010 0 d 1 sz vn:4 vd:4 1101 n q m 0 vm:4
-VPADD_float A1 1111 0011 0 d 0 sz vn:4 vd:4 1101 n q m 0 vm:4
-VABD_float A1 1111 0011 0 d 1 sz vn:4 vd:4 1101 n q m 0 vm:4
-VMLA_float A1 1111 0010 0 d 0 sz vn:4 vd:4 1101 n q m 1 vm:4
-VMLS_float A1 1111 0010 0 d 1 sz vn:4 vd:4 1101 n q m 1 vm:4
-VMUL_float A1 1111 0011 0 d 0 sz vn:4 vd:4 1101 n q m 1 vm:4
-VACGE A1 1111 0011 0 d 0 sz vn:4 vd:4 1110 n q m 1 vm:4
-VACGT A1 1111 0011 0 d 1 sz vn:4 vd:4 1110 n q m 1 vm:4
-VMAX_float A1 1111 0010 0 d 0 sz vn:4 vd:4 1111 n q m 0 vm:4
-VMIN_float A1 1111 0010 0 d 1 sz vn:4 vd:4 1111 n q m 0 vm:4
-VPMAX_float A1 1111 0011 0 d 0 sz vn:4 vd:4 1111 n q m 0 vm:4
-VPMIN_float A1 1111 0011 0 d 1 sz vn:4 vd:4 1111 n q m 0 vm:4
-VRECPS A1 1111 0010 0 d 0 sz vn:4 vd:4 1111 n q m 1 vm:4
-VRSQRTS A1 1111 0010 0 d 1 sz vn:4 vd:4 1111 n q m 1 vm:4
+VFM A1 1111 0010 0 d op 0 vn:4 vd:4 1100 n q m 1 vm:4
+VADD_float A1 1111 0010 0 d 0 0 vn:4 vd:4 1101 n q m 0 vm:4
+VSUB_float A1 1111 0010 0 d 1 0 vn:4 vd:4 1101 n q m 0 vm:4
+VPADD_float A1 1111 0011 0 d 0 0 vn:4 vd:4 1101 n q m 0 vm:4
+VABD_float A1 1111 0011 0 d 1 0 vn:4 vd:4 1101 n q m 0 vm:4
+VMLA_float A1 1111 0010 0 d 0 0 vn:4 vd:4 1101 n q m 1 vm:4
+VMLS_float A1 1111 0010 0 d 1 0 vn:4 vd:4 1101 n q m 1 vm:4
+VMUL_float A1 1111 0011 0 d 0 0 vn:4 vd:4 1101 n q m 1 vm:4
+VACGE A1 1111 0011 0 d 0 0 vn:4 vd:4 1110 n q m 1 vm:4
+VACGT A1 1111 0011 0 d 1 0 vn:4 vd:4 1110 n q m 1 vm:4
+VMAX_float A1 1111 0010 0 d 0 0 vn:4 vd:4 1111 n q m 0 vm:4
+VMIN_float A1 1111 0010 0 d 1 0 vn:4 vd:4 1111 n q m 0 vm:4
+VPMAX_float A1 1111 0011 0 d 0 0 vn:4 vd:4 1111 n q m 0 vm:4
+VPMIN_float A1 1111 0011 0 d 1 0 vn:4 vd:4 1111 n q m 0 vm:4
+VRECPS A1 1111 0010 0 d 0 0 vn:4 vd:4 1111 n q m 1 vm:4
+VRSQRTS A1 1111 0010 0 d 1 0 vn:4 vd:4 1111 n q m 1 vm:4
########### Neon 1 reg + modified immediate ###############
# Instructions from the Neon "1 reg + modified immediate"
@@ -577,15 +580,19 @@ VQDMULL A1 1111 0010 1 d sz:2 vn:4 vd:4 1101 n 0 m 0 vm:4 { $sz != 3; }
# (table A7-11 in DDI0406B)
# UNDEF cases included.
# sz = 11 is in vext/vtbl/vtbx/vdup/2reg-misc space.
+# We avoid f=1 sz=01 which is v8.2-FP16
###########################################################
# includes float variants
-VMLA_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 0 0 0 f n 1 m 0 vm:4 { $sz != 3; }
-VMLS_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 0 1 0 f n 1 m 0 vm:4 { $sz != 3; }
+VMLA_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 0 0 0 f n 1 m 0 vm:4 \
+ { $sz != 3 && ($f == 0 || $sz != 1); }
+VMLS_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 0 1 0 f n 1 m 0 vm:4 \
+ { $sz != 3 && ($f == 0 || $sz != 1); }
VMLAL_scalar A2 1111 001 u 1 d sz:2 vn:4 vd:4 0 0 1 0 n 1 m 0 vm:4 { $sz != 3; }
VMLSL_scalar A2 1111 001 u 1 d sz:2 vn:4 vd:4 0 1 1 0 n 1 m 0 vm:4 { $sz != 3; }
VQDMLAL_scalar A2 1111 0010 1 d sz:2 vn:4 vd:4 0 0 11 n 1 m 0 vm:4 { $sz != 3; }
VQDMLSL_scalar A2 1111 0010 1 d sz:2 vn:4 vd:4 0 1 11 n 1 m 0 vm:4 { $sz != 3; }
-VMUL_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 100 f n 1 m 0 vm:4 { $sz != 3; }
+VMUL_scalar A1 1111 001 q 1 d sz:2 vn:4 vd:4 100 f n 1 m 0 vm:4 \
+ { $sz != 3 && ($f == 0 || $sz != 1); }
VMULL_scalar A2 1111 001 u 1 d sz:2 vn:4 vd:4 1010 n 1 m 0 vm:4 { $sz != 3; }
VQDMULL_scalar A2 1111 0010 1 d sz:2 vn:4 vd:4 1011 n 1 m 0 vm:4 { $sz != 3; }
VQDMULH_scalar A2 1111 001 q 1 d sz:2 vn:4 vd:4 1100 n 1 m 0 vm:4 { $sz != 3; }
@@ -595,6 +602,7 @@ VQRDMULH_scalar A2 1111 001 q 1 d sz:2 vn:4 vd:4 1101 n 1 m 0 vm:4 { $sz != 3; }
# Instructions from the Neon "2 regs miscellaneous" space
# (table A7-13 in DDI0406B)
# UNDEF cases included.
+# We avoid f=1 sz=01 which is v8.2-FP16
###########################################################
VREV A1 1111 0011 1 d 11 sz:2 00 vd:4 000 op:2 q m 0 vm:4
VPADDL A1 1111 0011 1 d 11 sz:2 00 vd:4 0010 op q m 0 vm:4
@@ -605,13 +613,13 @@ VMVN A1 1111 0011 1 d 11 sz:2 00 vd:4 0 1011 q m 0 vm:4
VPADAL A1 1111 0011 1 d 11 sz:2 00 vd:4 0110 op q m 0 vm:4
VQABS A1 1111 0011 1 d 11 sz:2 00 vd:4 0111 0 q m 0 vm:4
VQNEG A1 1111 0011 1 d 11 sz:2 00 vd:4 0111 1 q m 0 vm:4
-VCGT0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 000 q m 0 vm:4
-VCGE0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 001 q m 0 vm:4
-VCEQ0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 010 q m 0 vm:4
-VCLE0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 011 q m 0 vm:4
-VCLT0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 100 q m 0 vm:4
-VABS A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 110 q m 0 vm:4
-VNEG A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 111 q m 0 vm:4
+VCGT0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 000 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VCGE0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 001 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VCEQ0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 010 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VCLE0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 011 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VCLT0 A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 100 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VABS A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 110 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VNEG A1 1111 0011 1 d 11 sz:2 01 vd:4 0 f 111 q m 0 vm:4 { $f == 0 || $sz != 1; }
VSWP A1 1111 0011 1 d 11 sz:2 10 vd:4 00000 q m 0 vm:4
# d == m gives UNKNOWN results, so avoid it
VTRN A1 1111 0011 1 d 11 sz:2 10 vd:4 00001 q m 0 vm:4 { ($d != $m) || ($vd != $vm); }
@@ -624,10 +632,10 @@ VSHLL A2 1111 0011 1 d 11 sz:2 10 vd:4 0011 0 0 m 0 vm:4
# float-halfprec (A8.6.299)
# NB that half-precision needs at least an A9; A8 doesn't have it
VCVT_half A1 1111 0011 1 d 11 sz:2 10 vd:4 011 op 0 0 m 0 vm:4
-VRECPE A1 1111 0011 1 d 11 sz:2 11 vd:4 010 f 0 q m 0 vm:4
-VRSQRTE A1 1111 0011 1 d 11 sz:2 11 vd:4 010 f 1 q m 0 vm:4
-# float to int, neon versions (A8.6.294)
-VCVT_neon A1 1111 0011 1 d 11 sz:2 11 vd:4 0 11 op:2 q m 0 vm:4
+VRECPE A1 1111 0011 1 d 11 sz:2 11 vd:4 010 f 0 q m 0 vm:4 { $f == 0 || $sz != 1; }
+VRSQRTE A1 1111 0011 1 d 11 sz:2 11 vd:4 010 f 1 q m 0 vm:4 { $f == 0 || $sz != 1; }
+# float to int, neon versions (A8.6.294); avoid sz=01 which is FP16
+VCVT_neon A1 1111 0011 1 d 11 sz:2 11 vd:4 0 11 op:2 q m 0 vm:4 { $sz != 1; }
########### Neon other ####################################
# Instructions which have their own entry in the top level
@@ -649,6 +657,8 @@ VDUP_scalar A1 1111 0011 1 d 11 imm:4 vd:4 11000 q m 0 vm:4
# "VFP data-processing instructions" space
# as described in DDI0406B table A7-16 and the subtables
# it refers to.
+# These don't include fp16, which has [11:9] 0b100
+# (described in the Arm ARM as [11:9] 0b10 and a 2-bit size field)
###########################################################
# VMLA, VMLS
@@ -752,7 +762,7 @@ VLDM A2b cond:4 110 p 0 d w 1 rn:4 vd:4 1010 00 imm:6 \
# UNDEF cases for both A1 and A2: P==U && W==1
VLDM A1c cond:4 110 p u d 1 1 rn:4 vd:4 101 x imm:8 !constraints { $p == $u; }
-# VSTR
+# VSTR (no overlap with VSTR_f16)
# both A1 and A2 encodings, U = 1
VSTR A1a cond:4 1101 1 d 00 rn:4 vd:4 101 x imm:8 \
!memory { reg_plus_imm($rn, $imm * 4); }
@@ -760,7 +770,7 @@ VSTR A1a cond:4 1101 1 d 00 rn:4 vd:4 101 x imm:8 \
VSTR A1b cond:4 1101 0 d 00 rn:4 vd:4 101 x imm:8 \
!memory { reg_minus_imm($rn, $imm * 4); }
-# VLDR
+# VLDR (no overlap with VLDR_f16)
# both A1 and A2 encodings, U = 1
VLDR A1a cond:4 1101 1 d 01 rn:4 vd:4 101 x imm:8 \
!memory { reg_plus_imm($rn, $imm * 4); }
@@ -799,9 +809,9 @@ VMOV_core_double A1 cond:4 1100 010 op:1 rt2:4 rt:4 1011 00 m:1 1 vm:4 { $op ==
# VSEL
VSEL A1 1111 11100 d cc:2 vn:4 vd:4 101 sz n 0 m 0 vm:4
# VMINNM and VMAXNM
-# neon
-VMINMAXNM A1 1111 00110 d op sz vn:4 vd:4 1111 n q m 1 vm:4
-# vfp
+# neon: sz=0 (avoiding sz=1 which is FP16)
+VMINMAXNM A1 1111 00110 d op 0 vn:4 vd:4 1111 n q m 1 vm:4
+# vfp (does not overlap with FP16)
VMINMAXNM A2 1111 11101 d 00 vn:4 vd:4 101 sz n op m 0 vm:4
# Crypto
@@ -842,8 +852,8 @@ VCVT_rm A1 1111 11101 d 1111 rm:2 vd:4 101 sz op 1 m 0 vm:4
# 64<->16 conversions (see also pattern earlier which is the sz==0 case)
VCVT_B_TT_64 A1 cond:4 1110 1 d 11 001 op vd:4 101 1 t 1 m 0 vm:4
-# VCVT with rounding mode specified, neon
-VCVT_rm_neon A1 1111 00111 d 11 size:2 11 vd:4 00 rm:2 op q m 0 vm:4
+# VCVT with rounding mode specified, neon; avoid sz=0b01 which is FP16
+VCVT_rm_neon A1 1111 00111 d 11 size:2 11 vd:4 00 rm:2 op q m 0 vm:4 { $size != 1; }
# CRC
# Note that sz == 0b11 is UNPREDICTABLE (either UNDEF, NOP or as if == 0b10)
@@ -879,16 +889,128 @@ VFMSL A1 1111110 01 d:1 10 vn:4 vd:4 1000 n:1 q:1 m:1 1 vm:4
VFMAL_s A1 11111110 0 d:1 00 vn:4 vd:4 1000 n:1 q:1 m:1 1 vm:4
VFMSL_s A1 11111110 1 d:1 00 vn:4 vd:4 1000 n:1 q:1 m:1 1 vm:4
+@v8_2_fp16
+
+# v8.2-FP16 adds a lot of "and 16-bit flavour" to existing insn encodings;
+# these patterns are arranged in the same order as the earlier v7 patterns.
+# Pattern names follow the non-fp16 names with a _f16 suffix.
+
+# FP16: neon 3-reg-same: bit 20 sz=1 for f16
+VCGT_f16 A2 1111 0011 0 d 1 1 vn:4 vd:4 1110 n q m 0 vm:4
+VCGE_f16 A2 1111 0011 0 d 0 1 vn:4 vd:4 1110 n q m 0 vm:4
+VCEQ_f16 A2 1111 0010 0 d 0 1 vn:4 vd:4 1110 n q m 0 vm:4
+VFM_f16 A1 1111 0010 0 d op 1 vn:4 vd:4 1100 n q m 1 vm:4
+VADD_float_f16 A1 1111 0010 0 d 0 1 vn:4 vd:4 1101 n q m 0 vm:4
+VSUB_float_f16 A1 1111 0010 0 d 1 1 vn:4 vd:4 1101 n q m 0 vm:4
+VPADD_float_f16 A1 1111 0011 0 d 0 1 vn:4 vd:4 1101 n q m 0 vm:4
+VABD_float_f16 A1 1111 0011 0 d 1 1 vn:4 vd:4 1101 n q m 0 vm:4
+VMLA_float_f16 A1 1111 0010 0 d 0 1 vn:4 vd:4 1101 n q m 1 vm:4
+VMLS_float_f16 A1 1111 0010 0 d 1 1 vn:4 vd:4 1101 n q m 1 vm:4
+VMUL_float_f16 A1 1111 0011 0 d 0 1 vn:4 vd:4 1101 n q m 1 vm:4
+VACGE_f16 A1 1111 0011 0 d 0 1 vn:4 vd:4 1110 n q m 1 vm:4
+VACGT_f16 A1 1111 0011 0 d 1 1 vn:4 vd:4 1110 n q m 1 vm:4
+VMAX_float_f16 A1 1111 0010 0 d 0 1 vn:4 vd:4 1111 n q m 0 vm:4
+VMIN_float_f16 A1 1111 0010 0 d 1 1 vn:4 vd:4 1111 n q m 0 vm:4
+VPMAX_float_f16 A1 1111 0011 0 d 0 1 vn:4 vd:4 1111 n q m 0 vm:4
+VPMIN_float_f16 A1 1111 0011 0 d 1 1 vn:4 vd:4 1111 n q m 0 vm:4
+VRECPS_f16 A1 1111 0010 0 d 0 1 vn:4 vd:4 1111 n q m 1 vm:4
+VRSQRTS_f16 A1 1111 0010 0 d 1 1 vn:4 vd:4 1111 n q m 1 vm:4
+
+# FP16: neon 2-reg-scalar : f=1 sz=01
+VMLA_scalar_f16 A1 1111 001 q 1 d 01 vn:4 vd:4 0 0 0 f n 1 m 0 vm:4
+VMLS_scalar_f16 A1 1111 001 q 1 d 01 vn:4 vd:4 0 1 0 f n 1 m 0 vm:4
+VMUL_scalar_f16 A1 1111 001 q 1 d 01 vn:4 vd:4 100 f n 1 m 0 vm:4
+
+# FP16: Neon 2-reg-shift
+# this doesn't overlap with the non-fp16 insn, which has 111 in [11:9]
+VCVT_f16 A1 1111 001 u 1 d imm:6 vd:4 110 op 0 q m 1 vm:4 { ($imm & 0x38) != 0; }
+
+# FP16: neon 2-reg-misc: f=1 sz=01
+VCGT0_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 000 q m 0 vm:4
+VCGE0_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 001 q m 0 vm:4
+VCEQ0_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 010 q m 0 vm:4
+VCLE0_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 011 q m 0 vm:4
+VCLT0_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 100 q m 0 vm:4
+VABS_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 110 q m 0 vm:4
+VNEG_f16 A1 1111 0011 1 d 11 01 01 vd:4 0 f 111 q m 0 vm:4
+VRECPE_f16 A1 1111 0011 1 d 11 01 11 vd:4 010 f 0 q m 0 vm:4
+VRSQRTE_f16 A1 1111 0011 1 d 11 01 11 vd:4 010 f 1 q m 0 vm:4
+VCVT_neon_f16 A1 1111 0011 1 d 11 01 11 vd:4 0 11 op:2 q m 0 vm:4
+
+# FP16: vfp: these have no overlap with non-fp16 patterns, where [11:9] is 101
+VMLA_f16 A2 cond:4 11100 d 00 vn:4 vd:4 1001 n op m 0 vm:4
+VNMLA_f16 A1 cond:4 11100 d 01 vn:4 vd:4 1001 n op m 0 vm:4
+VNMUL_f16 A2 cond:4 11100 d 10 vn:4 vd:4 1001 n 1 m 0 vm:4
+VMUL_f16 A2 cond:4 11100 d 10 vn:4 vd:4 1001 n 0 m 0 vm:4
+VADD_f16 A2 cond:4 11100 d 11 vn:4 vd:4 1001 n 0 m 0 vm:4
+VSUB_f16 A2 cond:4 11100 d 11 vn:4 vd:4 1001 n 1 m 0 vm:4
+VDIV_f16 A1 cond:4 11101 d 00 vn:4 vd:4 1001 n 0 m 0 vm:4
+VMOV_imm_f16 A2 cond:4 11101 d 11 immh:4 vd:4 1001 0000 imml:4
+VABS_f16 A2 cond:4 11101 d 11 0000 vd:4 1001 1 1 m 0 vm:4
+VNEG_f16 A2 cond:4 11101 d 11 0001 vd:4 1001 0 1 m 0 vm:4
+VSQRT_f16 A1 cond:4 11101 d 11 0001 vd:4 1001 1 1 m 0 vm:4
+VCMP_f16 A1 cond:4 11101 d 11 0100 vd:4 1001 e 1 m 0 vm:4
+VCMP_f16 A2 cond:4 11101 d 11 0101 vd:4 1001 e 1 0 0 0000
+VCVT_a_f16 A1 cond:4 11101 d 111 000 vd:4 1001 op 1 m 0 vm:4
+VCVT_b_f16 A1 cond:4 11101 d 111 10 x vd:4 1001 op 1 m 0 vm:4
+# VCVT between fp and fixed point (A.8.6.297); same UNPREDICTABLE as non-fp16
+# sx==1 case first:
+VCVT_c_f16 A1 cond:4 11101 d 111 op 1 u vd:4 1001 1 1 i 0 imm:4
+# sx==0, bit 3 == 0
+VCVT_d_f16 A1 cond:4 11101 d 111 op 1 u vd:4 1001 0 1 i 0 0 imm:3
+# sx==0, bit 3 == 1, bits 2..0 and 5 0
+VCVT_e_f16 A1 cond:4 11101 d 111 op 1 u vd:4 1001 0 1 0 0 1000
+VFM_f16 A2 cond:4 11101 d 10 vn:4 vd:4 1001 n op m 0 vm:4
+VFNM_f16 A1 cond:4 11101 d 01 vn:4 vd:4 1001 n op m 0 vm:4
+# both A1 and A2 encodings, U = 1
+VSTR_f16 A1a cond:4 1101 1 d 00 rn:4 vd:4 1001 imm:8 \
+ !memory { reg_plus_imm($rn, $imm * 2); }
+# both A1 and A2 encodings, U = 0
+VSTR_f16 A1b cond:4 1101 0 d 00 rn:4 vd:4 1001 imm:8 \
+ !memory { reg_minus_imm($rn, $imm * 2); }
+# both A1 and A2 encodings, U = 1
+VLDR_f16 A1a cond:4 1101 1 d 01 rn:4 vd:4 1001 imm:8 \
+ !memory { reg_plus_imm($rn, $imm * 2); }
+# both A1 and A2 encodings, U = 0
+VLDR_f16 A1b cond:4 1101 0 d 01 rn:4 vd:4 1001 imm:8 \
+ !memory { reg_minus_imm($rn, $imm * 2); }
+
+# FP16: v8-only insns
+# Neon insns with sz=0b01
+VCVT_rm_neon_f16 A1 1111 00111 d 11 01 11 vd:4 00 rm:2 op q m 0 vm:4
+VRINTX_neon_f16 A1 1111 00111 d 11 01 10 vd:4 01001 q m 0 vm:4
+VRINTZ_neon_f16 A1 1111 00111 d 11 01 10 vd:4 01011 q m 0 vm:4
+VRINTANPM_neon_f16 A1 1111 00111 d 11 01 10 vd:4 01 op:3 q m 0 vm:4
+# Neon insn with sz=1
+VMINMAXNM_f16 A1 1111 00110 d op 1 vn:4 vd:4 1111 n q m 1 vm:4
+# VFP insns which don't overlap non-fp16 rules (which have 101 in [11:9])
+VCVT_rm_f16 A1 1111 11101 d 1111 rm:2 vd:4 1001 op 1 m 0 vm:4
+VSEL_f16 A1 1111 11100 d cc:2 vn:4 vd:4 1001 n 0 m 0 vm:4
+VMINMAXNM_f16 A2 1111 11101 d 00 vn:4 vd:4 1001 n op m 0 vm:4
+VRINTX_f16 A1 cond:4 11101 d 110111 vd:4 1001 0 1 m 0 vm:4
+VRINTZR_f16 A1 cond:4 11101 d 110110 vd:4 1001 op 1 m 0 vm:4
+VRINTANPM_f16 A1 1111 11101 d 1110 rmode:2 vd:4 1001 0 1 m 0 vm:4
+
+# FP16: Insns which are new for v8.2 FP16:
+VINS_f16 A1 1111 11101 d 110000 vd:4 101011 m 0 vm:4
+VMOVX_f16 A1 1111 11101 d 110000 vd:4 101001 m 0 vm:4
+# VMOV between general-purpose register and half-precision
+VMOV_core_f16 A1 cond:4 1110000 op:1 vn:4 rt:4 1001 n 0010000
+
+@v8_2_fp16_v8_3_compnum
+# These are only present if both v8.2-FP16 and v8.3-CompNum are implemented
+# sz=0 for FP16
+VCADD_f16 A1 1111110 rot:1 1 d:1 0 0 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
+VCMLA_f16 A1 1111110 rot:2 d:1 1 0 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
+VCMLA_s_f16 A1 11111110 0 d:1 rot:2 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
+
#
# ARMv8.3 extensions
#
@v8_3_compnum
-# Disable fp16 until qemu supports it.
-VCADD A1 1111110 rot:1 1 d:1 0 s:1 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4 \
-!constraints { $s != 0; }
-
-VCMLA A1 1111110 rot:2 d:1 1 s:1 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4 \
-!constraints { $s != 0; }
-VCMLA_s A1 11111110 s:1 d:1 rot:2 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4 \
-!constraints { $s != 0; }
+# We avoid the FP16 parts of this, which are in @v8_2_fp16_v8_3_compnum,
+# so here s=1
+VCADD A1 1111110 rot:1 1 d:1 0 1 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
+VCMLA A1 1111110 rot:2 d:1 1 1 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
+VCMLA_s A1 11111110 1 d:1 rot:2 vn:4 vd:4 1000 n:1 q:1 m:1 0 vm:4
diff --git a/build-all-archs b/build-all-archs
index e5dcfc8..e89851b 100755
--- a/build-all-archs
+++ b/build-all-archs
@@ -91,7 +91,8 @@ program_exists() {
for triplet in i386-linux-gnu i686-linux-gnu x86_64-linux-gnu \
aarch64-linux-gnu arm-linux-gnueabihf \
m68k-linux-gnu \
- powerpc64le-linux-gnu powerpc64-linux-gnu ; do
+ powerpc64le-linux-gnu powerpc64-linux-gnu \
+ s390x-linux-gnu ; do
if ! program_exists "${triplet}-gcc"; then
echo "Skipping ${triplet}: no compiler found"
diff --git a/comms.c b/comms.c
index 6946fd9..21968da 100644
--- a/comms.c
+++ b/comms.c
@@ -31,7 +31,7 @@ int apprentice_connect(const char *hostname, int port)
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
- exit(1);
+ exit(EXIT_FAILURE);
}
struct hostent *hostinfo;
sa.sin_family = AF_INET;
@@ -39,12 +39,12 @@ int apprentice_connect(const char *hostname, int port)
hostinfo = gethostbyname(hostname);
if (!hostinfo) {
fprintf(stderr, "Unknown host %s\n", hostname);
- exit(1);
+ exit(EXIT_FAILURE);
}
sa.sin_addr = *(struct in_addr *) hostinfo->h_addr;
if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
perror("connect");
- exit(1);
+ exit(EXIT_FAILURE);
}
return sock;
}
@@ -56,13 +56,13 @@ int master_connect(int port)
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
- exit(1);
+ exit(EXIT_FAILURE);
}
int sora = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sora, sizeof(sora)) !=
0) {
perror("setsockopt(SO_REUSEADDR)");
- exit(1);
+ exit(EXIT_FAILURE);
}
sa.sin_family = AF_INET;
@@ -70,11 +70,11 @@ int master_connect(int port)
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
perror("bind");
- exit(1);
+ exit(EXIT_FAILURE);
}
if (listen(sock, 1) < 0) {
perror("listen");
- exit(1);
+ exit(EXIT_FAILURE);
}
/* Just block until we get a connection */
fprintf(stderr, "master: waiting for connection on port %d...\n",
@@ -84,7 +84,7 @@ int master_connect(int port)
int nsock = accept(sock, (struct sockaddr *) &csa, &csasz);
if (nsock < 0) {
perror("accept");
- exit(1);
+ exit(EXIT_FAILURE);
}
/* We're done with the server socket now */
close(sock);
@@ -104,7 +104,7 @@ static void recv_bytes(int sock, void *pkt, int pktlen)
continue;
}
perror("read failed");
- exit(1);
+ exit(EXIT_FAILURE);
}
pktlen -= i;
p += i;
@@ -127,7 +127,7 @@ static void recv_and_discard_bytes(int sock, int pktlen)
continue;
}
perror("read failed");
- exit(1);
+ exit(EXIT_FAILURE);
}
pktlen -= i;
}
@@ -168,7 +168,7 @@ ssize_t safe_writev(int fd, struct iovec *iov_in, int iovcnt)
* Note that both ends must agree on the length of the
* block of data.
*/
-int send_data_pkt(int sock, void *pkt, int pktlen)
+RisuResult send_data_pkt(int sock, void *pkt, int pktlen)
{
unsigned char resp;
/* First we send the packet length as a network-order 32 bit value.
@@ -186,17 +186,17 @@ int send_data_pkt(int sock, void *pkt, int pktlen)
if (safe_writev(sock, iov, 2) == -1) {
perror("writev failed");
- exit(1);
+ exit(EXIT_FAILURE);
}
if (read(sock, &resp, 1) != 1) {
perror("read failed");
- exit(1);
+ exit(EXIT_FAILURE);
}
return resp;
}
-int recv_data_pkt(int sock, void *pkt, int pktlen)
+RisuResult recv_data_pkt(int sock, void *pkt, int pktlen)
{
uint32_t net_pktlen;
recv_bytes(sock, &net_pktlen, sizeof(net_pktlen));
@@ -206,10 +206,10 @@ int recv_data_pkt(int sock, void *pkt, int pktlen)
* a response back.
*/
recv_and_discard_bytes(sock, net_pktlen);
- return 1;
+ return RES_BAD_IO;
}
recv_bytes(sock, pkt, pktlen);
- return 0;
+ return RES_OK;
}
void send_response_byte(int sock, int resp)
@@ -217,6 +217,6 @@ void send_response_byte(int sock, int resp)
unsigned char r = resp;
if (write(sock, &r, 1) != 1) {
perror("write failed");
- exit(1);
+ exit(EXIT_FAILURE);
}
}
diff --git a/configure b/configure
index ca2d7db..2f7c580 100755
--- a/configure
+++ b/configure
@@ -58,6 +58,8 @@ guess_arch() {
ARCH="m68k"
elif check_define __powerpc64__ ; then
ARCH="ppc64"
+ elif check_define __s390x__ ; then
+ ARCH="s390x"
else
echo "This cpu is not supported by risu. Try -h. " >&2
exit 1
@@ -139,7 +141,7 @@ Some influential environment variables:
prefixed with the given string.
ARCH force target architecture instead of trying to detect it.
- Valid values=[arm|aarch64|ppc64|ppc64le|m68k]
+ Valid values=[arm|aarch64|m68k|ppc64|ppc64le|s390x]
CC C compiler command
CFLAGS C compiler flags
diff --git a/loongarch64.risu b/loongarch64.risu
new file mode 100644
index 0000000..8ee2452
--- /dev/null
+++ b/loongarch64.risu
@@ -0,0 +1,2881 @@
+###############################################################################
+# Copyright (c) 2022 Loongson Technology Corporation Limited
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# based on aarch64.risu by Claudio Fontana
+# based on arm.risu by Peter Maydell
+###############################################################################
+
+# Input file for risugen defining LoongArch64 instructions
+.mode loongarch64
+
+#
+# Fixed point arithmetic operation instruction
+#
+add_w LA64 0000 00000001 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+add_d LA64 0000 00000001 00001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sub_w LA64 0000 00000001 00010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sub_d LA64 0000 00000001 00011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+slt LA64 0000 00000001 00100 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sltu LA64 0000 00000001 00101 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+slti LA64 0000 001000 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+sltui LA64 0000 001001 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+nor LA64 0000 00000001 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+and LA64 0000 00000001 01001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+or LA64 0000 00000001 01010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+xor LA64 0000 00000001 01011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+orn LA64 0000 00000001 01100 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+andn LA64 0000 00000001 01101 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mul_w LA64 0000 00000001 11000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mul_d LA64 0000 00000001 11011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulh_w LA64 0000 00000001 11001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulh_d LA64 0000 00000001 11100 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulh_wu LA64 0000 00000001 11010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulh_du LA64 0000 00000001 11101 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulw_d_w LA64 0000 00000001 11110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mulw_d_wu LA64 0000 00000001 11111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+
+#div.{w[u]/d[u]} rd,rj,rk
+# div.w{u}, mod.w[u] rk, rj, need in [0x0 ~0x7FFFFFFF]
+# use function set_reg_w($reg)
+div_w LA64 0000 00000010 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { set_reg_w($rj); set_reg_w($rk); }
+div_wu LA64 0000 00000010 00010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { set_reg_w($rj); set_reg_w($rk); }
+div_d LA64 0000 00000010 00100 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+div_du LA64 0000 00000010 00110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mod_w LA64 0000 00000010 00001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { set_reg_w($rj); set_reg_w($rk); }
+mod_wu LA64 0000 00000010 00011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { set_reg_w($rj); set_reg_w($rk); }
+mod_d LA64 0000 00000010 00101 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+mod_du LA64 0000 00000010 00111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+
+alsl_w LA64 0000 00000000 010 sa2:2 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+alsl_wu LA64 0000 00000000 011 sa2:2 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+alsl_d LA64 0000 00000010 110 sa2:2 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+lu12i_w LA64 0001 010 si20:20 rd:5 \
+ !constraints { $rd != 2; }
+lu32i_d LA64 0001 011 si20:20 rd:5 \
+ !constraints { $rd != 2; }
+lu52i_d LA64 0000 001100 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+addi_w LA64 0000 001010 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+addi_d LA64 0000 001011 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+addu16i_d LA64 0001 00 si16:16 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+andi LA64 0000 001101 ui12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+ori LA64 0000 001110 ui12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+xori LA64 0000 001111 ui12:12 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+
+#
+# Fixed point shift operation instruction
+#
+sll_w LA64 0000 00000001 01110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sll_d LA64 0000 00000001 10001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+srl_w LA64 0000 00000001 01111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+srl_d LA64 0000 00000001 10010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sra_w LA64 0000 00000001 10000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+sra_d LA64 0000 00000001 10011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+rotr_w LA64 0000 00000001 10110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+rotr_d LA64 0000 00000001 10111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+slli_w LA64 0000 00000100 00001 ui5:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+slli_d LA64 0000 00000100 0001 ui6:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+srli_w LA64 0000 00000100 01001 ui5:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+srli_d LA64 0000 00000100 0101 ui6:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+srai_w LA64 0000 00000100 10001 ui5:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+srai_d LA64 0000 00000100 1001 ui6:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+rotri_w LA64 0000 00000100 11001 ui5:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+rotri_d LA64 0000 00000100 1101 ui6:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+
+#
+# Fixed point bit operation instruction
+#
+ext_w_h LA64 0000 00000000 00000 10110 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+ext_w_b LA64 0000 00000000 00000 10111 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+clo_w LA64 0000 00000000 00000 00100 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+clz_w LA64 0000 00000000 00000 00101 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+cto_w LA64 0000 00000000 00000 00110 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+ctz_w LA64 0000 00000000 00000 00111 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+clo_d LA64 0000 00000000 00000 01000 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+clz_d LA64 0000 00000000 00000 01001 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+cto_d LA64 0000 00000000 00000 01010 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+ctz_d LA64 0000 00000000 00000 01011 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revb_2h LA64 0000 00000000 00000 01100 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revb_4h LA64 0000 00000000 00000 01101 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revb_2w LA64 0000 00000000 00000 01110 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revb_d LA64 0000 00000000 00000 01111 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revh_2w LA64 0000 00000000 00000 10000 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+revh_d LA64 0000 00000000 00000 10001 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+bitrev_4b LA64 0000 00000000 00000 10010 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+bitrev_8b LA64 0000 00000000 00000 10011 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+bitrev_w LA64 0000 00000000 00000 10100 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+bitrev_d LA64 0000 00000000 00000 10101 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2; }
+bytepick_w LA64 0000 00000000 100 sa2:2 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+bytepick_d LA64 0000 00000000 11 sa3:3 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+maskeqz LA64 0000 00000001 00110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+masknez LA64 0000 00000001 00111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+bstrins_w LA64 0000 0000011 msbw:5 0 lsbw:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2 && $msbw >= $lsbw; }
+bstrins_d LA64 0000 000010 msbd:6 lsbd:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2 && $msbd >= $lsbd; }
+bstrpick_w LA64 0000 0000011 msbw:5 1 lsbw:5 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2 && $msbw >= $lsbw; }
+bstrpick_d LA64 0000 000011 msbd:6 lsbd:6 rj:5 rd:5 \
+ !constraints { $rj != 2 && $rd != 2 && $msbd >= $lsbd; }
+
+#
+# Fixed point load/store instruction
+#
+ld_b LA64 0010 100000 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_h LA64 0010 100001 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_w LA64 0010 100010 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_d LA64 0010 100011 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_bu LA64 0010 101000 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_hu LA64 0010 101001 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ld_wu LA64 0010 101010 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+st_b LA64 0010 100100 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+st_h LA64 0010 100101 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+st_w LA64 0010 100110 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+st_d LA64 0010 100111 si12:12 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+ldx_b LA64 0011 10000000 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_h LA64 0011 10000000 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_w LA64 0011 10000000 10000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_d LA64 0011 10000000 11000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_bu LA64 0011 10000010 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_hu LA64 0011 10000010 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+ldx_wu LA64 0011 10000010 10000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+stx_b LA64 0011 10000001 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rd != $rj && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+stx_h LA64 0011 10000001 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rd != $rj && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+stx_w LA64 0011 10000001 10000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rd != $rj && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+stx_d LA64 0011 10000001 11000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rd != $rj && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+preld LA64 0010 101011 si12:12 rj:5 hint:5 \
+ !constraints { $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+dbar LA64 0011 10000111 00100 hint:15
+ibar LA64 0011 10000111 00101 hint:15
+ldptr_w LA64 0010 0100 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+ldptr_d LA64 0010 0110 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+stptr_w LA64 0010 0101 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+stptr_d LA64 0010 0111 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != $rd && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+
+#
+# Fixed point atomic instruction
+#
+ll_w LA64 0010 0000 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+ll_d LA64 0010 0010 si14:14 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si14, 14) * 4); }
+
+amswap_w LA64 0011 10000110 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amswap_d LA64 0011 10000110 00001 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amadd_w LA64 0011 10000110 00010 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amadd_d LA64 0011 10000110 00011 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amand_w LA64 0011 10000110 00100 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amand_d LA64 0011 10000110 00101 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amor_w LA64 0011 10000110 00110 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amor_d LA64 0011 10000110 00111 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amxor_w LA64 0011 10000110 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amxor_d LA64 0011 10000110 01001 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_w LA64 0011 10000110 01010 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_d LA64 0011 10000110 01011 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_w LA64 0011 10000110 01100 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_d LA64 0011 10000110 01101 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_wu LA64 0011 10000110 01110 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_du LA64 0011 10000110 01111 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_wu LA64 0011 10000110 10000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_du LA64 0011 10000110 10001 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+
+amswap_db_w LA64 0011 10000110 10010 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amswap_db_d LA64 0011 10000110 10011 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amadd_db_w LA64 0011 10000110 10100 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amadd_db_d LA64 0011 10000110 10101 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amand_db_w LA64 0011 10000110 10110 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amand_db_d LA64 0011 10000110 10111 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amor_db_w LA64 0011 10000110 11000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amor_db_d LA64 0011 10000110 11001 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amxor_db_w LA64 0011 10000110 11010 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+amxor_db_d LA64 0011 10000110 11011 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_db_w LA64 0011 10000110 11100 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_db_d LA64 0011 10000110 11101 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_db_w LA64 0011 10000110 11110 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_db_d LA64 0011 10000110 11111 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_db_wu LA64 0011 10000111 00000 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammax_db_du LA64 0011 10000111 00001 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_db_wu LA64 0011 10000111 00010 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+ammin_db_du LA64 0011 10000111 00011 rk:5 rj:5 rd:5 \
+ !constraints { $rj != 0 && $rd != $rj && $rj != $rk && $rd != $rk && $rk != 2 && $rj != 2 && $rd != 2; } \
+ !memory { reg_plus_reg($rj, 0); }
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w LA64 0000 00000010 01000 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crc_w_h_w LA64 0000 00000010 01001 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crc_w_w_w LA64 0000 00000010 01010 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crc_w_d_w LA64 0000 00000010 01011 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crcc_w_b_w LA64 0000 00000010 01100 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crcc_w_h_w LA64 0000 00000010 01101 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crcc_w_w_w LA64 0000 00000010 01110 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+crcc_w_d_w LA64 0000 00000010 01111 rk:5 rj:5 rd:5 \
+ !constraints { $rk != 2 && $rj != 2 && $rd != 2; }
+
+#
+# Floating point arithmetic operation instruction
+#
+fadd_s LA64 0000 00010000 00001 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fadd_d LA64 0000 00010000 00010 fk:5 fj:5 fd:5
+fsub_s LA64 0000 00010000 00101 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fsub_d LA64 0000 00010000 00110 fk:5 fj:5 fd:5
+fmul_s LA64 0000 00010000 01001 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmul_d LA64 0000 00010000 01010 fk:5 fj:5 fd:5
+fdiv_s LA64 0000 00010000 01101 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fdiv_d LA64 0000 00010000 01110 fk:5 fj:5 fd:5
+fmadd_s LA64 0000 10000001 fa:5 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmadd_d LA64 0000 10000010 fa:5 fk:5 fj:5 fd:5
+fmsub_s LA64 0000 10000101 fa:5 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmsub_d LA64 0000 10000110 fa:5 fk:5 fj:5 fd:5
+fnmadd_s LA64 0000 10001001 fa:5 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fnmadd_d LA64 0000 10001010 fa:5 fk:5 fj:5 fd:5
+fnmsub_s LA64 0000 10001101 fa:5 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fnmsub_d LA64 0000 10001110 fa:5 fk:5 fj:5 fd:5
+fmax_s LA64 0000 00010000 10001 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmax_d LA64 0000 00010000 10010 fk:5 fj:5 fd:5
+fmin_s LA64 0000 00010000 10101 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmin_d LA64 0000 00010000 10110 fk:5 fj:5 fd:5
+fmaxa_s LA64 0000 00010000 11001 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmaxa_d LA64 0000 00010000 11010 fk:5 fj:5 fd:5
+fmina_s LA64 0000 00010000 11101 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmina_d LA64 0000 00010000 11110 fk:5 fj:5 fd:5
+fabs_s LA64 0000 00010001 01000 00001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fabs_d LA64 0000 00010001 01000 00010 fj:5 fd:5
+fneg_s LA64 0000 00010001 01000 00101 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fneg_d LA64 0000 00010001 01000 00110 fj:5 fd:5
+fsqrt_s LA64 0000 00010001 01000 10001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fsqrt_d LA64 0000 00010001 01000 10010 fj:5 fd:5
+frecip_s LA64 0000 00010001 01000 10101 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+frecip_d LA64 0000 00010001 01000 10110 fj:5 fd:5
+frsqrt_s LA64 0000 00010001 01000 11001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+frsqrt_d LA64 0000 00010001 01000 11010 fj:5 fd:5
+fscaleb_s LA64 0000 00010001 00001 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fscaleb_d LA64 0000 00010001 00010 fk:5 fj:5 fd:5
+flogb_s LA64 0000 00010001 01000 01001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+flogb_d LA64 0000 00010001 01000 01010 fj:5 fd:5
+fcopysign_s LA64 0000 00010001 00101 fk:5 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fcopysign_d LA64 0000 00010001 00110 fk:5 fj:5 fd:5
+fclass_s LA64 0000 00010001 01000 01101 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fclass_d LA64 0000 00010001 01000 01110 fj:5 fd:5
+
+#
+# Floating point compare instruction
+#
+fcmp_cond_s LA64 0000 11000001 cond:5 fk:5 fj:5 00 cd:3 \
+ !constraints { $cond > 0 && $cond < 0x12; }
+fcmp_cond_d LA64 0000 11000010 cond:5 fk:5 fj:5 00 cd:3 \
+ !constraints { $cond > 0 && $cond < 0x12; }
+
+#
+# Floating point conversion instruction
+#
+fcvt_s_d LA64 0000 00010001 10010 00110 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fcvt_d_s LA64 0000 00010001 10010 01001 fj:5 fd:5
+ftintrm_w_s LA64 0000 00010001 10100 00001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrm_w_d LA64 0000 00010001 10100 00010 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrm_l_s LA64 0000 00010001 10100 01001 fj:5 fd:5
+ftintrm_l_d LA64 0000 00010001 10100 01010 fj:5 fd:5
+ftintrp_w_s LA64 0000 00010001 10100 10001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrp_w_d LA64 0000 00010001 10100 10010 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrp_l_s LA64 0000 00010001 10100 11001 fj:5 fd:5
+ftintrp_l_d LA64 0000 00010001 10100 11010 fj:5 fd:5
+ftintrz_w_s LA64 0000 00010001 10101 00001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrz_w_d LA64 0000 00010001 10101 00010 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrz_l_s LA64 0000 00010001 10101 01001 fj:5 fd:5
+ftintrz_l_d LA64 0000 00010001 10101 01010 fj:5 fd:5
+ftintrne_w_s LA64 0000 00010001 10101 10001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrne_w_d LA64 0000 00010001 10101 10010 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftintrne_l_s LA64 0000 00010001 10101 11001 fj:5 fd:5
+ftintrne_l_d LA64 0000 00010001 10101 11010 fj:5 fd:5
+ftint_w_s LA64 0000 00010001 10110 00001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftint_w_d LA64 0000 00010001 10110 00010 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ftint_l_s LA64 0000 00010001 10110 01001 fj:5 fd:5
+ftint_l_d LA64 0000 00010001 10110 01010 fj:5 fd:5
+ffint_s_w LA64 0000 00010001 11010 00100 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ffint_s_l LA64 0000 00010001 11010 00110 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+ffint_d_w LA64 0000 00010001 11010 01000 fj:5 fd:5
+ffint_d_l LA64 0000 00010001 11010 01010 fj:5 fd:5
+frint_s LA64 0000 00010001 11100 10001 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+frint_d LA64 0000 00010001 11100 10010 fj:5 fd:5
+
+#
+# Floating point move instruction
+#
+fmov_s LA64 0000 00010001 01001 00101 fj:5 fd:5 \
+ !post { nanbox_s($fd); }
+fmov_d LA64 0000 00010001 01001 00110 fj:5 fd:5
+fsel LA64 0000 11010000 00 ca:3 fk:5 fj:5 fd:5
+movgr2fr_w LA64 0000 00010001 01001 01001 rj:5 fd:5 \
+ !constraints { $rj != 2; } \
+ !post { nanbox_s($fd); }
+movgr2fr_d LA64 0000 00010001 01001 01010 rj:5 fd:5 \
+ !constraints { $rj != 2; }
+movgr2frh_w LA64 0000 00010001 01001 01011 rj:5 fd:5 \
+ !constraints { $rj != 2; }
+movfr2gr_s LA64 0000 00010001 01001 01101 fj:5 rd:5 \
+ !constraints { $rd != 2; }
+movfr2gr_d LA64 0000 00010001 01001 01110 fj:5 rd:5 \
+ !constraints { $rd != 2; }
+movfrh2gr_s LA64 0000 00010001 01001 01111 fj:5 rd:5 \
+ !constraints { $rd != 2; }
+movfr2cf LA64 0000 00010001 01001 10100 fj:5 00 cd:3
+movcf2fr LA64 0000 00010001 01001 10101 00 cj:3 fd:5
+movgr2cf LA64 0000 00010001 01001 10110 rj:5 00 cd:3 \
+ !constraints { $rj != 2; }
+movcf2gr LA64 0000 00010001 01001 10111 00 cj:3 rd:5 \
+ !constraints { $rd != 2; }
+
+#
+# Floating point load/store instruction
+#
+fld_s LA64 0010 101100 si12:12 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); } \
+ !post { nanbox_s($fd); }
+fst_s LA64 0010 101101 si12:12 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+fld_d LA64 0010 101110 si12:12 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+fst_d LA64 0010 101111 si12:12 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+fldx_s LA64 0011 10000011 00000 rk:5 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); } \
+ !post { nanbox_s($fd); }
+fldx_d LA64 0011 10000011 01000 rk:5 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+fstx_s LA64 0011 10000011 10000 rk:5 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+fstx_d LA64 0011 10000011 11000 rk:5 rj:5 fd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+
+#
+# LSX instructions
+#
+
+vadd_b LSX 0111 00000000 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadd_h LSX 0111 00000000 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadd_w LSX 0111 00000000 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadd_d LSX 0111 00000000 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadd_q LSX 0111 00010010 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsub_b LSX 0111 00000000 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsub_h LSX 0111 00000000 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsub_w LSX 0111 00000000 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsub_d LSX 0111 00000000 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsub_q LSX 0111 00010010 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vaddi_bu LSX 0111 00101000 10100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddi_hu LSX 0111 00101000 10101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddi_wu LSX 0111 00101000 10110 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddi_du LSX 0111 00101000 10111 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubi_bu LSX 0111 00101000 11000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubi_hu LSX 0111 00101000 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubi_wu LSX 0111 00101000 11010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubi_du LSX 0111 00101000 11011 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vneg_b LSX 0111 00101001 11000 01100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vneg_h LSX 0111 00101001 11000 01101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vneg_w LSX 0111 00101001 11000 01110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vneg_d LSX 0111 00101001 11000 01111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsadd_b LSX 0111 00000100 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_h LSX 0111 00000100 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_w LSX 0111 00000100 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_d LSX 0111 00000100 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_bu LSX 0111 00000100 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_hu LSX 0111 00000100 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_wu LSX 0111 00000100 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsadd_du LSX 0111 00000100 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vssub_b LSX 0111 00000100 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_h LSX 0111 00000100 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_w LSX 0111 00000100 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_d LSX 0111 00000100 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_bu LSX 0111 00000100 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_hu LSX 0111 00000100 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_wu LSX 0111 00000100 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssub_du LSX 0111 00000100 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vhaddw_h_b LSX 0111 00000101 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_w_h LSX 0111 00000101 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_d_w LSX 0111 00000101 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_q_d LSX 0111 00000101 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_hu_bu LSX 0111 00000101 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_wu_hu LSX 0111 00000101 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_du_wu LSX 0111 00000101 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhaddw_qu_du LSX 0111 00000101 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vhsubw_h_b LSX 0111 00000101 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_w_h LSX 0111 00000101 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_d_w LSX 0111 00000101 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_q_d LSX 0111 00000101 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_hu_bu LSX 0111 00000101 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_wu_hu LSX 0111 00000101 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_du_wu LSX 0111 00000101 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vhsubw_qu_du LSX 0111 00000101 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vaddwev_h_b LSX 0111 00000001 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_w_h LSX 0111 00000001 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_d_w LSX 0111 00000001 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_q_d LSX 0111 00000001 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_h_b LSX 0111 00000010 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_w_h LSX 0111 00000010 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_d_w LSX 0111 00000010 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_q_d LSX 0111 00000010 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsubwev_h_b LSX 0111 00000010 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_w_h LSX 0111 00000010 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_d_w LSX 0111 00000010 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_q_d LSX 0111 00000010 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_h_b LSX 0111 00000010 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_w_h LSX 0111 00000010 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_d_w LSX 0111 00000010 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_q_d LSX 0111 00000010 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vaddwev_h_bu LSX 0111 00000010 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_w_hu LSX 0111 00000010 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_d_wu LSX 0111 00000010 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_q_du LSX 0111 00000010 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_h_bu LSX 0111 00000011 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_w_hu LSX 0111 00000011 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_d_wu LSX 0111 00000011 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_q_du LSX 0111 00000011 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsubwev_h_bu LSX 0111 00000011 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_w_hu LSX 0111 00000011 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_d_wu LSX 0111 00000011 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwev_q_du LSX 0111 00000011 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_h_bu LSX 0111 00000011 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_w_hu LSX 0111 00000011 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_d_wu LSX 0111 00000011 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsubwod_q_du LSX 0111 00000011 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vaddwev_h_bu_b LSX 0111 00000011 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_w_hu_h LSX 0111 00000011 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_d_wu_w LSX 0111 00000011 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwev_q_du_d LSX 0111 00000011 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_h_bu_b LSX 0111 00000100 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_w_hu_h LSX 0111 00000100 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_d_wu_w LSX 0111 00000100 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vaddwod_q_du_d LSX 0111 00000100 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vavg_b LSX 0111 00000110 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_h LSX 0111 00000110 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_w LSX 0111 00000110 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_d LSX 0111 00000110 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_bu LSX 0111 00000110 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_hu LSX 0111 00000110 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_wu LSX 0111 00000110 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavg_du LSX 0111 00000110 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_b LSX 0111 00000110 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_h LSX 0111 00000110 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_w LSX 0111 00000110 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_d LSX 0111 00000110 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_bu LSX 0111 00000110 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_hu LSX 0111 00000110 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_wu LSX 0111 00000110 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vavgr_du LSX 0111 00000110 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vabsd_b LSX 0111 00000110 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_h LSX 0111 00000110 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_w LSX 0111 00000110 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_d LSX 0111 00000110 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_bu LSX 0111 00000110 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_hu LSX 0111 00000110 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_wu LSX 0111 00000110 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vabsd_du LSX 0111 00000110 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vadda_b LSX 0111 00000101 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadda_h LSX 0111 00000101 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadda_w LSX 0111 00000101 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vadda_d LSX 0111 00000101 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmax_b LSX 0111 00000111 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_h LSX 0111 00000111 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_w LSX 0111 00000111 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_d LSX 0111 00000111 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmaxi_b LSX 0111 00101001 00000 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmaxi_h LSX 0111 00101001 00001 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmaxi_w LSX 0111 00101001 00010 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmaxi_d LSX 0111 00101001 00011 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+
+vmax_bu LSX 0111 00000111 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_hu LSX 0111 00000111 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_wu LSX 0111 00000111 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmax_du LSX 0111 00000111 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaxi_bu LSX 0111 00101001 01000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaxi_hu LSX 0111 00101001 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaxi_wu LSX 0111 00101001 01010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaxi_du LSX 0111 00101001 01011 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmin_b LSX 0111 00000111 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_h LSX 0111 00000111 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_w LSX 0111 00000111 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_d LSX 0111 00000111 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmini_b LSX 0111 00101001 00100 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmini_h LSX 0111 00101001 00101 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmini_w LSX 0111 00101001 00110 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+vmini_d LSX 0111 00101001 00111 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);} \
+ !post { clean_lsx_result($vd); }
+
+vmin_bu LSX 0111 00000111 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_hu LSX 0111 00000111 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_wu LSX 0111 00000111 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmin_du LSX 0111 00000111 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmini_bu LSX 0111 00101001 01100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmini_hu LSX 0111 00101001 01101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmini_wu LSX 0111 00101001 01110 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmini_du LSX 0111 00101001 01111 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmul_b LSX 0111 00001000 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmul_h LSX 0111 00001000 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmul_w LSX 0111 00001000 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmul_d LSX 0111 00001000 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_b LSX 0111 00001000 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_h LSX 0111 00001000 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_w LSX 0111 00001000 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_d LSX 0111 00001000 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_bu LSX 0111 00001000 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_hu LSX 0111 00001000 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_wu LSX 0111 00001000 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmuh_du LSX 0111 00001000 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmulwev_h_b LSX 0111 00001001 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_w_h LSX 0111 00001001 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_d_w LSX 0111 00001001 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_q_d LSX 0111 00001001 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_h_b LSX 0111 00001001 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_w_h LSX 0111 00001001 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_d_w LSX 0111 00001001 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_q_d LSX 0111 00001001 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_h_bu LSX 0111 00001001 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_w_hu LSX 0111 00001001 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_d_wu LSX 0111 00001001 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_q_du LSX 0111 00001001 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_h_bu LSX 0111 00001001 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_w_hu LSX 0111 00001001 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_d_wu LSX 0111 00001001 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_q_du LSX 0111 00001001 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_h_bu_b LSX 0111 00001010 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_w_hu_h LSX 0111 00001010 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_d_wu_w LSX 0111 00001010 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwev_q_du_d LSX 0111 00001010 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_h_bu_b LSX 0111 00001010 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_w_hu_h LSX 0111 00001010 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_d_wu_w LSX 0111 00001010 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmulwod_q_du_d LSX 0111 00001010 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmadd_b LSX 0111 00001010 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmadd_h LSX 0111 00001010 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmadd_w LSX 0111 00001010 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmadd_d LSX 0111 00001010 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmsub_b LSX 0111 00001010 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmsub_h LSX 0111 00001010 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmsub_w LSX 0111 00001010 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmsub_d LSX 0111 00001010 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmaddwev_h_b LSX 0111 00001010 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_w_h LSX 0111 00001010 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_d_w LSX 0111 00001010 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_q_d LSX 0111 00001010 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_h_b LSX 0111 00001010 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_w_h LSX 0111 00001010 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_d_w LSX 0111 00001010 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_q_d LSX 0111 00001010 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_h_bu LSX 0111 00001011 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_w_hu LSX 0111 00001011 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_d_wu LSX 0111 00001011 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_q_du LSX 0111 00001011 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_h_bu LSX 0111 00001011 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_w_hu LSX 0111 00001011 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_d_wu LSX 0111 00001011 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_q_du LSX 0111 00001011 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_h_bu_b LSX 0111 00001011 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_w_hu_h LSX 0111 00001011 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_d_wu_w LSX 0111 00001011 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwev_q_du_d LSX 0111 00001011 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_h_bu_b LSX 0111 00001011 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_w_hu_h LSX 0111 00001011 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_d_wu_w LSX 0111 00001011 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmaddwod_q_du_d LSX 0111 00001011 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vdiv_b LSX 0111 00001110 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_h LSX 0111 00001110 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_w LSX 0111 00001110 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_d LSX 0111 00001110 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_bu LSX 0111 00001110 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_hu LSX 0111 00001110 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_wu LSX 0111 00001110 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vdiv_du LSX 0111 00001110 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_b LSX 0111 00001110 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_h LSX 0111 00001110 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_w LSX 0111 00001110 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_d LSX 0111 00001110 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_bu LSX 0111 00001110 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_hu LSX 0111 00001110 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_wu LSX 0111 00001110 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmod_du LSX 0111 00001110 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsat_b LSX 0111 00110010 01000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_h LSX 0111 00110010 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_w LSX 0111 00110010 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_d LSX 0111 00110010 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_bu LSX 0111 00110010 10000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_hu LSX 0111 00110010 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_wu LSX 0111 00110010 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsat_du LSX 0111 00110010 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vexth_h_b LSX 0111 00101001 11101 11000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_w_h LSX 0111 00101001 11101 11001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_d_w LSX 0111 00101001 11101 11010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_q_d LSX 0111 00101001 11101 11011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_hu_bu LSX 0111 00101001 11101 11100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_wu_hu LSX 0111 00101001 11101 11101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_du_wu LSX 0111 00101001 11101 11110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vexth_qu_du LSX 0111 00101001 11101 11111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsigncov_b LSX 0111 00010010 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsigncov_h LSX 0111 00010010 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsigncov_w LSX 0111 00010010 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsigncov_d LSX 0111 00010010 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vmskltz_b LSX 0111 00101001 11000 10000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmskltz_h LSX 0111 00101001 11000 10001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmskltz_w LSX 0111 00101001 11000 10010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmskltz_d LSX 0111 00101001 11000 10011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmskgez_b LSX 0111 00101001 11000 10100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vmsknz_b LSX 0111 00101001 11000 11000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vand_v LSX 0111 00010010 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vor_v LSX 0111 00010010 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vxor_v LSX 0111 00010010 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vnor_v LSX 0111 00010010 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vandn_v LSX 0111 00010010 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vorn_v LSX 0111 00010010 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vandi_b LSX 0111 00111101 00 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vori_b LSX 0111 00111101 01 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vxori_b LSX 0111 00111101 10 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vnori_b LSX 0111 00111101 11 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsll_b LSX 0111 00001110 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsll_h LSX 0111 00001110 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsll_w LSX 0111 00001110 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsll_d LSX 0111 00001110 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslli_b LSX 0111 00110010 11000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslli_h LSX 0111 00110010 11000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslli_w LSX 0111 00110010 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslli_d LSX 0111 00110010 1101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrl_b LSX 0111 00001110 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrl_h LSX 0111 00001110 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrl_w LSX 0111 00001110 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrl_d LSX 0111 00001110 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrli_b LSX 0111 00110011 00000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrli_h LSX 0111 00110011 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrli_w LSX 0111 00110011 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrli_d LSX 0111 00110011 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsra_b LSX 0111 00001110 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsra_h LSX 0111 00001110 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsra_w LSX 0111 00001110 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsra_d LSX 0111 00001110 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrai_b LSX 0111 00110011 01000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrai_h LSX 0111 00110011 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrai_w LSX 0111 00110011 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrai_d LSX 0111 00110011 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vrotr_b LSX 0111 00001110 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotr_h LSX 0111 00001110 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotr_w LSX 0111 00001110 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotr_d LSX 0111 00001110 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotri_b LSX 0111 00101010 00000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotri_h LSX 0111 00101010 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotri_w LSX 0111 00101010 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vrotri_d LSX 0111 00101010 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsllwil_h_b LSX 0111 00110000 10000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsllwil_w_h LSX 0111 00110000 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsllwil_d_w LSX 0111 00110000 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vextl_q_d LSX 0111 00110000 10010 00000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsllwil_hu_bu LSX 0111 00110000 11000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsllwil_wu_hu LSX 0111 00110000 11000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsllwil_du_wu LSX 0111 00110000 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vextl_qu_du LSX 0111 00110000 11010 00000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrlr_b LSX 0111 00001111 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlr_h LSX 0111 00001111 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlr_w LSX 0111 00001111 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlr_d LSX 0111 00001111 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlri_b LSX 0111 00101010 01000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlri_h LSX 0111 00101010 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlri_w LSX 0111 00101010 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlri_d LSX 0111 00101010 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrar_b LSX 0111 00001111 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrar_h LSX 0111 00001111 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrar_w LSX 0111 00001111 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrar_d LSX 0111 00001111 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrari_b LSX 0111 00101010 10000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrari_h LSX 0111 00101010 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrari_w LSX 0111 00101010 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrari_d LSX 0111 00101010 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrln_b_h LSX 0111 00001111 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrln_h_w LSX 0111 00001111 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrln_w_d LSX 0111 00001111 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsran_b_h LSX 0111 00001111 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsran_h_w LSX 0111 00001111 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsran_w_d LSX 0111 00001111 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrlni_b_h LSX 0111 00110100 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlni_h_w LSX 0111 00110100 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlni_w_d LSX 0111 00110100 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlni_d_q LSX 0111 00110100 001 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrani_b_h LSX 0111 00110101 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrani_h_w LSX 0111 00110101 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrani_w_d LSX 0111 00110101 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrani_d_q LSX 0111 00110101 101 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrlrn_b_h LSX 0111 00001111 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlrn_h_w LSX 0111 00001111 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlrn_w_d LSX 0111 00001111 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarn_b_h LSX 0111 00001111 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarn_h_w LSX 0111 00001111 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarn_w_d LSX 0111 00001111 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsrlrni_b_h LSX 0111 00110100 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlrni_h_w LSX 0111 00110100 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlrni_w_d LSX 0111 00110100 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrlrni_d_q LSX 0111 00110100 011 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarni_b_h LSX 0111 00110101 11000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarni_h_w LSX 0111 00110101 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarni_w_d LSX 0111 00110101 1101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsrarni_d_q LSX 0111 00110101 111 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vssrln_b_h LSX 0111 00001111 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrln_h_w LSX 0111 00001111 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrln_w_d LSX 0111 00001111 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_b_h LSX 0111 00001111 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_h_w LSX 0111 00001111 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_w_d LSX 0111 00001111 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrln_bu_h LSX 0111 00010000 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrln_hu_w LSX 0111 00010000 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrln_wu_d LSX 0111 00010000 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_bu_h LSX 0111 00010000 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_hu_w LSX 0111 00010000 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssran_wu_d LSX 0111 00010000 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vssrlni_b_h LSX 0111 00110100 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_h_w LSX 0111 00110100 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_w_d LSX 0111 00110100 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_d_q LSX 0111 00110100 101 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_b_h LSX 0111 00110110 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_h_w LSX 0111 00110110 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_w_d LSX 0111 00110110 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_d_q LSX 0111 00110110 001 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_bu_h LSX 0111 00110100 11000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_hu_w LSX 0111 00110100 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_wu_d LSX 0111 00110100 1101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlni_du_q LSX 0111 00110100 111 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_bu_h LSX 0111 00110110 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_hu_w LSX 0111 00110110 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_wu_d LSX 0111 00110110 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrani_du_q LSX 0111 00110110 011 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vssrlrn_b_h LSX 0111 00010000 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrn_h_w LSX 0111 00010000 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrn_w_d LSX 0111 00010000 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_b_h LSX 0111 00010000 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_h_w LSX 0111 00010000 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_w_d LSX 0111 00010000 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrn_bu_h LSX 0111 00010000 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrn_hu_w LSX 0111 00010000 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrn_wu_d LSX 0111 00010000 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_bu_h LSX 0111 00010000 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_hu_w LSX 0111 00010000 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarn_wu_d LSX 0111 00010000 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vssrlrni_b_h LSX 0111 00110101 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_h_w LSX 0111 00110101 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_w_d LSX 0111 00110101 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_d_q LSX 0111 00110101 001 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_b_h LSX 0111 00110110 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_h_w LSX 0111 00110110 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_w_d LSX 0111 00110110 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_d_q LSX 0111 00110110 101 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_hu_w LSX 0111 00110101 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_wu_d LSX 0111 00110101 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrlrni_du_q LSX 0111 00110101 011 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_bu_h LSX 0111 00110110 11000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_hu_w LSX 0111 00110110 11001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_wu_d LSX 0111 00110110 1101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vssrarni_du_q LSX 0111 00110110 111 imm:7 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vclo_b LSX 0111 00101001 11000 00000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclo_h LSX 0111 00101001 11000 00001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclo_w LSX 0111 00101001 11000 00010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclo_d LSX 0111 00101001 11000 00011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclz_b LSX 0111 00101001 11000 00100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclz_h LSX 0111 00101001 11000 00101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclz_w LSX 0111 00101001 11000 00110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vclz_d LSX 0111 00101001 11000 00111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vpcnt_b LSX 0111 00101001 11000 01000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpcnt_h LSX 0111 00101001 11000 01001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpcnt_w LSX 0111 00101001 11000 01010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpcnt_d LSX 0111 00101001 11000 01011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vbitclr_b LSX 0111 00010000 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclr_h LSX 0111 00010000 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclr_w LSX 0111 00010000 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclr_d LSX 0111 00010000 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclri_b LSX 0111 00110001 00000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclri_h LSX 0111 00110001 00000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclri_w LSX 0111 00110001 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitclri_d LSX 0111 00110001 0001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitset_b LSX 0111 00010000 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitset_h LSX 0111 00010000 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitset_w LSX 0111 00010000 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitset_d LSX 0111 00010000 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitseti_b LSX 0111 00110001 01000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitseti_h LSX 0111 00110001 01000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitseti_w LSX 0111 00110001 01001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitseti_d LSX 0111 00110001 0101 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrev_b LSX 0111 00010001 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrev_h LSX 0111 00010001 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrev_w LSX 0111 00010001 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrev_d LSX 0111 00010001 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrevi_b LSX 0111 00110001 10000 01 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrevi_h LSX 0111 00110001 10000 1 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrevi_w LSX 0111 00110001 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbitrevi_d LSX 0111 00110001 1001 imm:6 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfrstp_b LSX 0111 00010010 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrstp_h LSX 0111 00010010 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrstpi_b LSX 0111 00101001 10100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrstpi_h LSX 0111 00101001 10101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfadd_s LSX 0111 00010011 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfadd_d LSX 0111 00010011 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfsub_s LSX 0111 00010011 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfsub_d LSX 0111 00010011 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmul_s LSX 0111 00010011 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmul_d LSX 0111 00010011 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfdiv_s LSX 0111 00010011 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfdiv_d LSX 0111 00010011 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfmadd_s LSX 0000 10010001 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmadd_d LSX 0000 10010010 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmsub_s LSX 0000 10010101 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmsub_d LSX 0000 10010110 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfnmadd_s LSX 0000 10011001 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfnmadd_d LSX 0000 10011010 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfnmsub_s LSX 0000 10011101 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfnmsub_d LSX 0000 10011110 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfmax_s LSX 0111 00010011 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmax_d LSX 0111 00010011 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmin_s LSX 0111 00010011 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmin_d LSX 0111 00010011 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfmaxa_s LSX 0111 00010100 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmaxa_d LSX 0111 00010100 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmina_s LSX 0111 00010100 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfmina_d LSX 0111 00010100 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vflogb_s LSX 0111 00101001 11001 10001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vflogb_d LSX 0111 00101001 11001 10010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfclass_s LSX 0111 00101001 11001 10101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfclass_d LSX 0111 00101001 11001 10110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfsqrt_s LSX 0111 00101001 11001 11001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfsqrt_d LSX 0111 00101001 11001 11010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrecip_s LSX 0111 00101001 11001 11101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrecip_d LSX 0111 00101001 11001 11110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrsqrt_s LSX 0111 00101001 11010 00001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrsqrt_d LSX 0111 00101001 11010 00010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfcvtl_s_h LSX 0111 00101001 11011 11010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfcvth_s_h LSX 0111 00101001 11011 11011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfcvtl_d_s LSX 0111 00101001 11011 11100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfcvth_d_s LSX 0111 00101001 11011 11101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfcvt_h_s LSX 0111 00010100 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfcvt_s_d LSX 0111 00010100 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfrint_s LSX 0111 00101001 11010 01101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrint_d LSX 0111 00101001 11010 01110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrm_s LSX 0111 00101001 11010 10001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrm_d LSX 0111 00101001 11010 10010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrp_s LSX 0111 00101001 11010 10101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrp_d LSX 0111 00101001 11010 10110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrz_s LSX 0111 00101001 11010 11001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrz_d LSX 0111 00101001 11010 11010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrne_s LSX 0111 00101001 11010 11101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vfrintrne_d LSX 0111 00101001 11010 11110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vftint_w_s LSX 0111 00101001 11100 01100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftint_l_d LSX 0111 00101001 11100 01101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrm_w_s LSX 0111 00101001 11100 01110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrm_l_d LSX 0111 00101001 11100 01111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrp_w_s LSX 0111 00101001 11100 10000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrp_l_d LSX 0111 00101001 11100 10001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrz_w_s LSX 0111 00101001 11100 10010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrz_l_d LSX 0111 00101001 11100 10011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrne_w_s LSX 0111 00101001 11100 10100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrne_l_d LSX 0111 00101001 11100 10101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftint_wu_s LSX 0111 00101001 11100 10110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftint_lu_d LSX 0111 00101001 11100 10111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrz_wu_s LSX 0111 00101001 11100 11100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrz_lu_d LSX 0111 00101001 11100 11101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftint_w_d LSX 0111 00010100 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrm_w_d LSX 0111 00010100 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrp_w_d LSX 0111 00010100 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrz_w_d LSX 0111 00010100 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrne_w_d LSX 0111 00010100 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintl_l_s LSX 0111 00101001 11101 00000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftinth_l_s LSX 0111 00101001 11101 00001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrml_l_s LSX 0111 00101001 11101 00010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrmh_l_s LSX 0111 00101001 11101 00011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrpl_l_s LSX 0111 00101001 11101 00100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrph_l_s LSX 0111 00101001 11101 00101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrzl_l_s LSX 0111 00101001 11101 00110 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrzh_l_s LSX 0111 00101001 11101 00111 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrnel_l_s LSX 0111 00101001 11101 01000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vftintrneh_l_s LSX 0111 00101001 11101 01001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vffint_s_w LSX 0111 00101001 11100 00000 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffint_s_wu LSX 0111 00101001 11100 00001 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffint_d_l LSX 0111 00101001 11100 00010 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffint_d_lu LSX 0111 00101001 11100 00011 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffintl_d_w LSX 0111 00101001 11100 00100 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffinth_d_w LSX 0111 00101001 11100 00101 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vffint_s_l LSX 0111 00010100 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vseq_b LSX 0111 00000000 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseq_h LSX 0111 00000000 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseq_w LSX 0111 00000000 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseq_d LSX 0111 00000000 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseqi_b LSX 0111 00101000 00000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseqi_h LSX 0111 00101000 00001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseqi_w LSX 0111 00101000 00010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vseqi_d LSX 0111 00101000 00011 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vsle_b LSX 0111 00000000 00100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_h LSX 0111 00000000 00101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_w LSX 0111 00000000 00110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_d LSX 0111 00000000 00111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_b LSX 0111 00101000 00100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_h LSX 0111 00101000 00101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_w LSX 0111 00101000 00110 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_d LSX 0111 00101000 00111 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_bu LSX 0111 00000000 01000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_hu LSX 0111 00000000 01001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_wu LSX 0111 00000000 01010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vsle_du LSX 0111 00000000 01011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_bu LSX 0111 00101000 01000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_hu LSX 0111 00101000 01000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_wu LSX 0111 00101000 01010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslei_du LSX 0111 00101000 01010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vslt_b LSX 0111 00000000 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_h LSX 0111 00000000 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_w LSX 0111 00000000 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_d LSX 0111 00000000 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_b LSX 0111 00101000 01100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_h LSX 0111 00101000 01101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_w LSX 0111 00101000 01110 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_d LSX 0111 00101000 01111 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_bu LSX 0111 00000000 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_hu LSX 0111 00000000 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_wu LSX 0111 00000000 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslt_du LSX 0111 00000000 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_bu LSX 0111 00101000 10000 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_hu LSX 0111 00101000 10001 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_wu LSX 0111 00101000 10010 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vslti_du LSX 0111 00101000 10011 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vfcmp_cond_s LSX 0000 11000101 cond:5 vk:5 vj:5 vd:5 \
+ !constraints { $cond > 0 && $cond < 0x12; } \
+ !post { clean_lsx_result($vd); }
+vfcmp_cond_d LSX 0000 11000110 cond:5 vk:5 vj:5 vd:5 \
+ !constraints { $cond > 0 && $cond < 0x12; } \
+ !post { clean_lsx_result($vd); }
+
+vbitsel_v LSX 0000 11010001 va:5 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vbitseli_b LSX 0111 00111100 01 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vseteqz_v LSX 0111 00101001 11001 00110 vj:5 00 cd:3
+vsetnez_v LSX 0111 00101001 11001 00111 vj:5 00 cd:3
+vsetanyeqz_b LSX 0111 00101001 11001 01000 vj:5 00 cd:3
+vsetanyeqz_h LSX 0111 00101001 11001 01001 vj:5 00 cd:3
+vsetanyeqz_w LSX 0111 00101001 11001 01010 vj:5 00 cd:3
+vsetanyeqz_d LSX 0111 00101001 11001 01011 vj:5 00 cd:3
+vsetallnez_b LSX 0111 00101001 11001 01100 vj:5 00 cd:3
+vsetallnez_h LSX 0111 00101001 11001 01101 vj:5 00 cd:3
+vsetallnez_w LSX 0111 00101001 11001 01110 vj:5 00 cd:3
+vsetallnez_d LSX 0111 00101001 11001 01111 vj:5 00 cd:3
+
+vinsgr2vr_b LSX 0111 00101110 10111 0 imm:4 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vinsgr2vr_h LSX 0111 00101110 10111 10 imm:3 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vinsgr2vr_w LSX 0111 00101110 10111 110 imm:2 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vinsgr2vr_d LSX 0111 00101110 10111 1110 imm:1 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vpickve2gr_b LSX 0111 00101110 11111 0 imm:4 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_h LSX 0111 00101110 11111 10 imm:3 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_w LSX 0111 00101110 11111 110 imm:2 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_d LSX 0111 00101110 11111 1110 imm:1 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_bu LSX 0111 00101111 00111 0 imm:4 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_hu LSX 0111 00101111 00111 10 imm:3 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_wu LSX 0111 00101111 00111 110 imm:2 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+vpickve2gr_du LSX 0111 00101111 00111 1110 imm:1 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+
+vreplgr2vr_b LSX 0111 00101001 11110 00000 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplgr2vr_h LSX 0111 00101001 11110 00001 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplgr2vr_w LSX 0111 00101001 11110 00010 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplgr2vr_d LSX 0111 00101001 11110 00011 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; } \
+ !post { clean_lsx_result($vd); }
+
+vreplve_b LSX 0111 00010010 00100 rk:5 vj:5 vd:5 \
+ !constraints { $rk != 2 && $rk != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplve_h LSX 0111 00010010 00101 rk:5 vj:5 vd:5 \
+ !constraints { $rk != 2 && $rk != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplve_w LSX 0111 00010010 00110 rk:5 vj:5 vd:5 \
+ !constraints { $rk != 2 && $rk != 0; } \
+ !post { clean_lsx_result($vd); }
+vreplve_d LSX 0111 00010010 00111 rk:5 vj:5 vd:5 \
+ !constraints { $rk != 2 && $rk != 0; } \
+ !post { clean_lsx_result($vd); }
+
+vreplvei_b LSX 0111 00101111 01111 0 imm:4 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vreplvei_h LSX 0111 00101111 01111 10 imm:3 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vreplvei_w LSX 0111 00101111 01111 110 imm:2 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vreplvei_d LSX 0111 00101111 01111 1110 imm:1 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vbsll_v LSX 0111 00101000 11100 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vbsrl_v LSX 0111 00101000 11101 imm:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vpackev_b LSX 0111 00010001 01100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackev_h LSX 0111 00010001 01101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackev_w LSX 0111 00010001 01110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackev_d LSX 0111 00010001 01111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackod_b LSX 0111 00010001 10000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackod_h LSX 0111 00010001 10001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackod_w LSX 0111 00010001 10010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpackod_d LSX 0111 00010001 10011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vpickev_b LSX 0111 00010001 11100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickev_h LSX 0111 00010001 11101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickev_w LSX 0111 00010001 11110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickev_d LSX 0111 00010001 11111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickod_b LSX 0111 00010010 00000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickod_h LSX 0111 00010010 00001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickod_w LSX 0111 00010010 00010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vpickod_d LSX 0111 00010010 00011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vilvl_b LSX 0111 00010001 10100 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvl_h LSX 0111 00010001 10101 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvl_w LSX 0111 00010001 10110 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvl_d LSX 0111 00010001 10111 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvh_b LSX 0111 00010001 11000 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvh_h LSX 0111 00010001 11001 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvh_w LSX 0111 00010001 11010 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vilvh_d LSX 0111 00010001 11011 vk:5 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vshuf4i_b LSX 0111 00111001 00 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vshuf4i_h LSX 0111 00111001 01 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vshuf4i_w LSX 0111 00111001 10 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vshuf4i_d LSX 0111 00111001 11 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vpermi_w LSX 0111 00111110 01 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vextrins_d LSX 0111 00111000 00 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vextrins_w LSX 0111 00111000 01 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vextrins_h LSX 0111 00111000 10 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+vextrins_b LSX 0111 00111000 11 imm:8 vj:5 vd:5 \
+ !post { clean_lsx_result($vd); }
+
+vld LSX 0010 110000 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); } \
+ !post { clean_lsx_result($vd); }
+vst LSX 0010 110001 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); } \
+ !post { clean_lsx_result($vd); }
+vldx LSX 0011 10000100 00000 rk:5 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); } \
+ !post { clean_lsx_result($vd); }
+vstx LSX 0011 10000100 01000 rk:5 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); } \
+ !post { clean_lsx_result($vd); }
+
+vldrepl_d LSX 0011 00000001 0 si9:9 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si9, 9) * 8); } \
+ !post { clean_lsx_result($vd); }
+vldrepl_w LSX 0011 00000010 si10:10 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si10, 10) * 4); } \
+ !post { clean_lsx_result($vd); }
+vldrepl_h LSX 0011 0000010 si11:11 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si11, 11) * 2); } \
+ !post { clean_lsx_result($vd); }
+vldrepl_b LSX 0011 000010 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); } \
+ !post { clean_lsx_result($vd); }
+
+vstelm_d LSX 0011 00010001 0 si1:1 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 8); } \
+ !post { clean_lsx_result($vd); }
+vstelm_w LSX 0011 00010010 si2:2 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 4); } \
+ !post { clean_lsx_result($vd); }
+vstelm_h LSX 0011 0001010 si3:3 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 2); } \
+ !post { clean_lsx_result($vd); }
+vstelm_b LSX 0011 000110 si4:4 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8)); } \
+ !post { clean_lsx_result($vd); }
+
+vldi LSX 0111 00111110 00 si13:13 vd:5 \
+ !constraints { $si13 >= 0 && $si13 <= 12; } \
+ !post { clean_lsx_result($vd); }
+
+#
+# LASX instructions
+#
+
+xvadd_b LASX 0111 01000000 10100 vk:5 vj:5 vd:5
+xvadd_h LASX 0111 01000000 10101 vk:5 vj:5 vd:5
+xvadd_w LASX 0111 01000000 10110 vk:5 vj:5 vd:5
+xvadd_d LASX 0111 01000000 10111 vk:5 vj:5 vd:5
+xvadd_q LASX 0111 01010010 11010 vk:5 vj:5 vd:5
+xvsub_b LASX 0111 01000000 11000 vk:5 vj:5 vd:5
+xvsub_h LASX 0111 01000000 11001 vk:5 vj:5 vd:5
+xvsub_w LASX 0111 01000000 11010 vk:5 vj:5 vd:5
+xvsub_d LASX 0111 01000000 11011 vk:5 vj:5 vd:5
+xvsub_q LASX 0111 01010010 11011 vk:5 vj:5 vd:5
+
+xvaddi_bu LASX 0111 01101000 10100 imm:5 vj:5 vd:5
+xvaddi_hu LASX 0111 01101000 10101 imm:5 vj:5 vd:5
+xvaddi_wu LASX 0111 01101000 10110 imm:5 vj:5 vd:5
+xvaddi_du LASX 0111 01101000 10111 imm:5 vj:5 vd:5
+xvsubi_bu LASX 0111 01101000 11000 imm:5 vj:5 vd:5
+xvsubi_hu LASX 0111 01101000 11001 imm:5 vj:5 vd:5
+xvsubi_wu LASX 0111 01101000 11010 imm:5 vj:5 vd:5
+xvsubi_du LASX 0111 01101000 11011 imm:5 vj:5 vd:5
+
+xvneg_b LASX 0111 01101001 11000 01100 vj:5 vd:5
+xvneg_h LASX 0111 01101001 11000 01101 vj:5 vd:5
+xvneg_w LASX 0111 01101001 11000 01110 vj:5 vd:5
+xvneg_d LASX 0111 01101001 11000 01111 vj:5 vd:5
+
+xvsadd_b LASX 0111 01000100 01100 vk:5 vj:5 vd:5
+xvsadd_h LASX 0111 01000100 01101 vk:5 vj:5 vd:5
+xvsadd_w LASX 0111 01000100 01110 vk:5 vj:5 vd:5
+xvsadd_d LASX 0111 01000100 01111 vk:5 vj:5 vd:5
+xvsadd_bu LASX 0111 01000100 10100 vk:5 vj:5 vd:5
+xvsadd_hu LASX 0111 01000100 10101 vk:5 vj:5 vd:5
+xvsadd_wu LASX 0111 01000100 10110 vk:5 vj:5 vd:5
+xvsadd_du LASX 0111 01000100 10111 vk:5 vj:5 vd:5
+
+xvssub_b LASX 0111 01000100 10000 vk:5 vj:5 vd:5
+xvssub_h LASX 0111 01000100 10001 vk:5 vj:5 vd:5
+xvssub_w LASX 0111 01000100 10010 vk:5 vj:5 vd:5
+xvssub_d LASX 0111 01000100 10011 vk:5 vj:5 vd:5
+xvssub_bu LASX 0111 01000100 11000 vk:5 vj:5 vd:5
+xvssub_hu LASX 0111 01000100 11001 vk:5 vj:5 vd:5
+xvssub_wu LASX 0111 01000100 11010 vk:5 vj:5 vd:5
+xvssub_du LASX 0111 01000100 11011 vk:5 vj:5 vd:5
+
+xvhaddw_h_b LASX 0111 01000101 01000 vk:5 vj:5 vd:5
+xvhaddw_w_h LASX 0111 01000101 01001 vk:5 vj:5 vd:5
+xvhaddw_d_w LASX 0111 01000101 01010 vk:5 vj:5 vd:5
+xvhaddw_q_d LASX 0111 01000101 01011 vk:5 vj:5 vd:5
+xvhaddw_hu_bu LASX 0111 01000101 10000 vk:5 vj:5 vd:5
+xvhaddw_wu_hu LASX 0111 01000101 10001 vk:5 vj:5 vd:5
+xvhaddw_du_wu LASX 0111 01000101 10010 vk:5 vj:5 vd:5
+xvhaddw_qu_du LASX 0111 01000101 10011 vk:5 vj:5 vd:5
+
+xvhsubw_h_b LASX 0111 01000101 01100 vk:5 vj:5 vd:5
+xvhsubw_w_h LASX 0111 01000101 01101 vk:5 vj:5 vd:5
+xvhsubw_d_w LASX 0111 01000101 01110 vk:5 vj:5 vd:5
+xvhsubw_q_d LASX 0111 01000101 01111 vk:5 vj:5 vd:5
+xvhsubw_hu_bu LASX 0111 01000101 10100 vk:5 vj:5 vd:5
+xvhsubw_wu_hu LASX 0111 01000101 10101 vk:5 vj:5 vd:5
+xvhsubw_du_wu LASX 0111 01000101 10110 vk:5 vj:5 vd:5
+xvhsubw_qu_du LASX 0111 01000101 10111 vk:5 vj:5 vd:5
+
+xvaddwev_h_b LASX 0111 01000001 11100 vk:5 vj:5 vd:5
+xvaddwev_w_h LASX 0111 01000001 11101 vk:5 vj:5 vd:5
+xvaddwev_d_w LASX 0111 01000001 11110 vk:5 vj:5 vd:5
+xvaddwev_q_d LASX 0111 01000001 11111 vk:5 vj:5 vd:5
+xvaddwod_h_b LASX 0111 01000010 00100 vk:5 vj:5 vd:5
+xvaddwod_w_h LASX 0111 01000010 00101 vk:5 vj:5 vd:5
+xvaddwod_d_w LASX 0111 01000010 00110 vk:5 vj:5 vd:5
+xvaddwod_q_d LASX 0111 01000010 00111 vk:5 vj:5 vd:5
+
+xvsubwev_h_b LASX 0111 01000010 00000 vk:5 vj:5 vd:5
+xvsubwev_w_h LASX 0111 01000010 00001 vk:5 vj:5 vd:5
+xvsubwev_d_w LASX 0111 01000010 00010 vk:5 vj:5 vd:5
+xvsubwev_q_d LASX 0111 01000010 00011 vk:5 vj:5 vd:5
+xvsubwod_h_b LASX 0111 01000010 01000 vk:5 vj:5 vd:5
+xvsubwod_w_h LASX 0111 01000010 01001 vk:5 vj:5 vd:5
+xvsubwod_d_w LASX 0111 01000010 01010 vk:5 vj:5 vd:5
+xvsubwod_q_d LASX 0111 01000010 01011 vk:5 vj:5 vd:5
+
+xvaddwev_h_bu LASX 0111 01000010 11100 vk:5 vj:5 vd:5
+xvaddwev_w_hu LASX 0111 01000010 11101 vk:5 vj:5 vd:5
+xvaddwev_d_wu LASX 0111 01000010 11110 vk:5 vj:5 vd:5
+xvaddwev_q_du LASX 0111 01000010 11111 vk:5 vj:5 vd:5
+xvaddwod_h_bu LASX 0111 01000011 00100 vk:5 vj:5 vd:5
+xvaddwod_w_hu LASX 0111 01000011 00101 vk:5 vj:5 vd:5
+xvaddwod_d_wu LASX 0111 01000011 00110 vk:5 vj:5 vd:5
+xvaddwod_q_du LASX 0111 01000011 00111 vk:5 vj:5 vd:5
+
+xvsubwev_h_bu LASX 0111 01000011 00000 vk:5 vj:5 vd:5
+xvsubwev_w_hu LASX 0111 01000011 00001 vk:5 vj:5 vd:5
+xvsubwev_d_wu LASX 0111 01000011 00010 vk:5 vj:5 vd:5
+xvsubwev_q_du LASX 0111 01000011 00011 vk:5 vj:5 vd:5
+xvsubwod_h_bu LASX 0111 01000011 01000 vk:5 vj:5 vd:5
+xvsubwod_w_hu LASX 0111 01000011 01001 vk:5 vj:5 vd:5
+xvsubwod_d_wu LASX 0111 01000011 01010 vk:5 vj:5 vd:5
+xvsubwod_q_du LASX 0111 01000011 01011 vk:5 vj:5 vd:5
+
+xvaddwev_h_bu_b LASX 0111 01000011 11100 vk:5 vj:5 vd:5
+xvaddwev_w_hu_h LASX 0111 01000011 11101 vk:5 vj:5 vd:5
+xvaddwev_d_wu_w LASX 0111 01000011 11110 vk:5 vj:5 vd:5
+xvaddwev_q_du_d LASX 0111 01000011 11111 vk:5 vj:5 vd:5
+xvaddwod_h_bu_b LASX 0111 01000100 00000 vk:5 vj:5 vd:5
+xvaddwod_w_hu_h LASX 0111 01000100 00001 vk:5 vj:5 vd:5
+xvaddwod_d_wu_w LASX 0111 01000100 00010 vk:5 vj:5 vd:5
+xvaddwod_q_du_d LASX 0111 01000100 00011 vk:5 vj:5 vd:5
+
+xvavg_b LASX 0111 01000110 01000 vk:5 vj:5 vd:5
+xvavg_h LASX 0111 01000110 01001 vk:5 vj:5 vd:5
+xvavg_w LASX 0111 01000110 01010 vk:5 vj:5 vd:5
+xvavg_d LASX 0111 01000110 01011 vk:5 vj:5 vd:5
+xvavg_bu LASX 0111 01000110 01100 vk:5 vj:5 vd:5
+xvavg_hu LASX 0111 01000110 01101 vk:5 vj:5 vd:5
+xvavg_wu LASX 0111 01000110 01110 vk:5 vj:5 vd:5
+xvavg_du LASX 0111 01000110 01111 vk:5 vj:5 vd:5
+xvavgr_b LASX 0111 01000110 10000 vk:5 vj:5 vd:5
+xvavgr_h LASX 0111 01000110 10001 vk:5 vj:5 vd:5
+xvavgr_w LASX 0111 01000110 10010 vk:5 vj:5 vd:5
+xvavgr_d LASX 0111 01000110 10011 vk:5 vj:5 vd:5
+xvavgr_bu LASX 0111 01000110 10100 vk:5 vj:5 vd:5
+xvavgr_hu LASX 0111 01000110 10101 vk:5 vj:5 vd:5
+xvavgr_wu LASX 0111 01000110 10110 vk:5 vj:5 vd:5
+xvavgr_du LASX 0111 01000110 10111 vk:5 vj:5 vd:5
+
+xvabsd_b LASX 0111 01000110 00000 vk:5 vj:5 vd:5
+xvabsd_h LASX 0111 01000110 00001 vk:5 vj:5 vd:5
+xvabsd_w LASX 0111 01000110 00010 vk:5 vj:5 vd:5
+xvabsd_d LASX 0111 01000110 00011 vk:5 vj:5 vd:5
+xvabsd_bu LASX 0111 01000110 00100 vk:5 vj:5 vd:5
+xvabsd_hu LASX 0111 01000110 00101 vk:5 vj:5 vd:5
+xvabsd_wu LASX 0111 01000110 00110 vk:5 vj:5 vd:5
+xvabsd_du LASX 0111 01000110 00111 vk:5 vj:5 vd:5
+
+xvadda_b LASX 0111 01000101 11000 vk:5 vj:5 vd:5
+xvadda_h LASX 0111 01000101 11001 vk:5 vj:5 vd:5
+xvadda_w LASX 0111 01000101 11010 vk:5 vj:5 vd:5
+xvadda_d LASX 0111 01000101 11011 vk:5 vj:5 vd:5
+
+xvmax_b LASX 0111 01000111 00000 vk:5 vj:5 vd:5
+xvmax_h LASX 0111 01000111 00001 vk:5 vj:5 vd:5
+xvmax_w LASX 0111 01000111 00010 vk:5 vj:5 vd:5
+xvmax_d LASX 0111 01000111 00011 vk:5 vj:5 vd:5
+xvmax_bu LASX 0111 01000111 01000 vk:5 vj:5 vd:5
+xvmax_hu LASX 0111 01000111 01001 vk:5 vj:5 vd:5
+xvmax_wu LASX 0111 01000111 01010 vk:5 vj:5 vd:5
+xvmax_du LASX 0111 01000111 01011 vk:5 vj:5 vd:5
+
+xvmaxi_b LASX 0111 01101001 00000 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmaxi_h LASX 0111 01101001 00001 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmaxi_w LASX 0111 01101001 00010 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmaxi_d LASX 0111 01101001 00011 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmaxi_bu LASX 0111 01101001 01000 imm:5 vj:5 vd:5
+xvmaxi_hu LASX 0111 01101001 01001 imm:5 vj:5 vd:5
+xvmaxi_wu LASX 0111 01101001 01010 imm:5 vj:5 vd:5
+xvmaxi_du LASX 0111 01101001 01011 imm:5 vj:5 vd:5
+
+xvmin_b LASX 0111 01000111 00100 vk:5 vj:5 vd:5
+xvmin_h LASX 0111 01000111 00101 vk:5 vj:5 vd:5
+xvmin_w LASX 0111 01000111 00110 vk:5 vj:5 vd:5
+xvmin_d LASX 0111 01000111 00111 vk:5 vj:5 vd:5
+xvmin_bu LASX 0111 01000111 01100 vk:5 vj:5 vd:5
+xvmin_hu LASX 0111 01000111 01101 vk:5 vj:5 vd:5
+xvmin_wu LASX 0111 01000111 01110 vk:5 vj:5 vd:5
+xvmin_du LASX 0111 01000111 01111 vk:5 vj:5 vd:5
+
+xvmini_b LASX 0111 01101001 00100 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmini_h LASX 0111 01101001 00101 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmini_w LASX 0111 01101001 00110 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmini_d LASX 0111 01101001 00111 imm:5 vj:5 vd:5 \
+ !constraints { $imm = sextract($imm, 5);}
+xvmini_bu LASX 0111 01101001 01100 imm:5 vj:5 vd:5
+xvmini_hu LASX 0111 01101001 01101 imm:5 vj:5 vd:5
+xvmini_wu LASX 0111 01101001 01110 imm:5 vj:5 vd:5
+xvmini_du LASX 0111 01101001 01111 imm:5 vj:5 vd:5
+
+xvmul_b LASX 0111 01001000 01000 vk:5 vj:5 vd:5
+xvmul_h LASX 0111 01001000 01001 vk:5 vj:5 vd:5
+xvmul_w LASX 0111 01001000 01010 vk:5 vj:5 vd:5
+xvmul_d LASX 0111 01001000 01011 vk:5 vj:5 vd:5
+xvmuh_b LASX 0111 01001000 01100 vk:5 vj:5 vd:5
+xvmuh_h LASX 0111 01001000 01101 vk:5 vj:5 vd:5
+xvmuh_w LASX 0111 01001000 01110 vk:5 vj:5 vd:5
+xvmuh_d LASX 0111 01001000 01111 vk:5 vj:5 vd:5
+xvmuh_bu LASX 0111 01001000 10000 vk:5 vj:5 vd:5
+xvmuh_hu LASX 0111 01001000 10001 vk:5 vj:5 vd:5
+xvmuh_wu LASX 0111 01001000 10010 vk:5 vj:5 vd:5
+xvmuh_du LASX 0111 01001000 10011 vk:5 vj:5 vd:5
+
+xvmulwev_h_b LASX 0111 01001001 00000 vk:5 vj:5 vd:5
+xvmulwev_w_h LASX 0111 01001001 00001 vk:5 vj:5 vd:5
+xvmulwev_d_w LASX 0111 01001001 00010 vk:5 vj:5 vd:5
+xvmulwev_q_d LASX 0111 01001001 00011 vk:5 vj:5 vd:5
+xvmulwod_h_b LASX 0111 01001001 00100 vk:5 vj:5 vd:5
+xvmulwod_w_h LASX 0111 01001001 00101 vk:5 vj:5 vd:5
+xvmulwod_d_w LASX 0111 01001001 00110 vk:5 vj:5 vd:5
+xvmulwod_q_d LASX 0111 01001001 00111 vk:5 vj:5 vd:5
+xvmulwev_h_bu LASX 0111 01001001 10000 vk:5 vj:5 vd:5
+xvmulwev_w_hu LASX 0111 01001001 10001 vk:5 vj:5 vd:5
+xvmulwev_d_wu LASX 0111 01001001 10010 vk:5 vj:5 vd:5
+xvmulwev_q_du LASX 0111 01001001 10011 vk:5 vj:5 vd:5
+xvmulwod_h_bu LASX 0111 01001001 10100 vk:5 vj:5 vd:5
+xvmulwod_w_hu LASX 0111 01001001 10101 vk:5 vj:5 vd:5
+xvmulwod_d_wu LASX 0111 01001001 10110 vk:5 vj:5 vd:5
+xvmulwod_q_du LASX 0111 01001001 10111 vk:5 vj:5 vd:5
+xvmulwev_h_bu_b LASX 0111 01001010 00000 vk:5 vj:5 vd:5
+xvmulwev_w_hu_h LASX 0111 01001010 00001 vk:5 vj:5 vd:5
+xvmulwev_d_wu_w LASX 0111 01001010 00010 vk:5 vj:5 vd:5
+xvmulwev_q_du_d LASX 0111 01001010 00011 vk:5 vj:5 vd:5
+xvmulwod_h_bu_b LASX 0111 01001010 00100 vk:5 vj:5 vd:5
+xvmulwod_w_hu_h LASX 0111 01001010 00101 vk:5 vj:5 vd:5
+xvmulwod_d_wu_w LASX 0111 01001010 00110 vk:5 vj:5 vd:5
+xvmulwod_q_du_d LASX 0111 01001010 00111 vk:5 vj:5 vd:5
+
+xvmadd_b LASX 0111 01001010 10000 vk:5 vj:5 vd:5
+xvmadd_h LASX 0111 01001010 10001 vk:5 vj:5 vd:5
+xvmadd_w LASX 0111 01001010 10010 vk:5 vj:5 vd:5
+xvmadd_d LASX 0111 01001010 10011 vk:5 vj:5 vd:5
+xvmsub_b LASX 0111 01001010 10100 vk:5 vj:5 vd:5
+xvmsub_h LASX 0111 01001010 10101 vk:5 vj:5 vd:5
+xvmsub_w LASX 0111 01001010 10110 vk:5 vj:5 vd:5
+xvmsub_d LASX 0111 01001010 10111 vk:5 vj:5 vd:5
+
+xvmaddwev_h_b LASX 0111 01001010 11000 vk:5 vj:5 vd:5
+xvmaddwev_w_h LASX 0111 01001010 11001 vk:5 vj:5 vd:5
+xvmaddwev_d_w LASX 0111 01001010 11010 vk:5 vj:5 vd:5
+xvmaddwev_q_d LASX 0111 01001010 11011 vk:5 vj:5 vd:5
+xvmaddwod_h_b LASX 0111 01001010 11100 vk:5 vj:5 vd:5
+xvmaddwod_w_h LASX 0111 01001010 11101 vk:5 vj:5 vd:5
+xvmaddwod_d_w LASX 0111 01001010 11110 vk:5 vj:5 vd:5
+xvmaddwod_q_d LASX 0111 01001010 11111 vk:5 vj:5 vd:5
+xvmaddwev_h_bu LASX 0111 01001011 01000 vk:5 vj:5 vd:5
+xvmaddwev_w_hu LASX 0111 01001011 01001 vk:5 vj:5 vd:5
+xvmaddwev_d_wu LASX 0111 01001011 01010 vk:5 vj:5 vd:5
+xvmaddwev_q_du LASX 0111 01001011 01011 vk:5 vj:5 vd:5
+xvmaddwod_h_bu LASX 0111 01001011 01100 vk:5 vj:5 vd:5
+xvmaddwod_w_hu LASX 0111 01001011 01101 vk:5 vj:5 vd:5
+xvmaddwod_d_wu LASX 0111 01001011 01110 vk:5 vj:5 vd:5
+xvmaddwod_q_du LASX 0111 01001011 01111 vk:5 vj:5 vd:5
+xvmaddwev_h_bu_b LASX 0111 01001011 11000 vk:5 vj:5 vd:5
+xvmaddwev_w_hu_h LASX 0111 01001011 11001 vk:5 vj:5 vd:5
+xvmaddwev_d_wu_w LASX 0111 01001011 11010 vk:5 vj:5 vd:5
+xvmaddwev_q_du_d LASX 0111 01001011 11011 vk:5 vj:5 vd:5
+xvmaddwod_h_bu_b LASX 0111 01001011 11100 vk:5 vj:5 vd:5
+xvmaddwod_w_hu_h LASX 0111 01001011 11101 vk:5 vj:5 vd:5
+xvmaddwod_d_wu_w LASX 0111 01001011 11110 vk:5 vj:5 vd:5
+xvmaddwod_q_du_d LASX 0111 01001011 11111 vk:5 vj:5 vd:5
+
+xvdiv_b LASX 0111 01001110 00000 vk:5 vj:5 vd:5
+xvdiv_h LASX 0111 01001110 00001 vk:5 vj:5 vd:5
+xvdiv_w LASX 0111 01001110 00010 vk:5 vj:5 vd:5
+xvdiv_d LASX 0111 01001110 00011 vk:5 vj:5 vd:5
+xvmod_b LASX 0111 01001110 00100 vk:5 vj:5 vd:5
+xvmod_h LASX 0111 01001110 00101 vk:5 vj:5 vd:5
+xvmod_w LASX 0111 01001110 00110 vk:5 vj:5 vd:5
+xvmod_d LASX 0111 01001110 00111 vk:5 vj:5 vd:5
+xvdiv_bu LASX 0111 01001110 01000 vk:5 vj:5 vd:5
+xvdiv_hu LASX 0111 01001110 01001 vk:5 vj:5 vd:5
+xvdiv_wu LASX 0111 01001110 01010 vk:5 vj:5 vd:5
+xvdiv_du LASX 0111 01001110 01011 vk:5 vj:5 vd:5
+xvmod_bu LASX 0111 01001110 01100 vk:5 vj:5 vd:5
+xvmod_hu LASX 0111 01001110 01101 vk:5 vj:5 vd:5
+xvmod_wu LASX 0111 01001110 01110 vk:5 vj:5 vd:5
+xvmod_du LASX 0111 01001110 01111 vk:5 vj:5 vd:5
+
+xvsat_b LASX 0111 01110010 01000 01 imm:3 vj:5 vd:5
+xvsat_h LASX 0111 01110010 01000 1 imm:4 vj:5 vd:5
+xvsat_w LASX 0111 01110010 01001 imm:5 vj:5 vd:5
+xvsat_d LASX 0111 01110010 0101 imm:6 vj:5 vd:5
+xvsat_bu LASX 0111 01110010 10000 01 imm:3 vj:5 vd:5
+xvsat_hu LASX 0111 01110010 10000 1 imm:4 vj:5 vd:5
+xvsat_wu LASX 0111 01110010 10001 imm:5 vj:5 vd:5
+xvsat_du LASX 0111 01110010 1001 imm:6 vj:5 vd:5
+
+xvexth_h_b LASX 0111 01101001 11101 11000 vj:5 vd:5
+xvexth_w_h LASX 0111 01101001 11101 11001 vj:5 vd:5
+xvexth_d_w LASX 0111 01101001 11101 11010 vj:5 vd:5
+xvexth_q_d LASX 0111 01101001 11101 11011 vj:5 vd:5
+xvexth_hu_bu LASX 0111 01101001 11101 11100 vj:5 vd:5
+xvexth_wu_hu LASX 0111 01101001 11101 11101 vj:5 vd:5
+xvexth_du_wu LASX 0111 01101001 11101 11110 vj:5 vd:5
+xvexth_qu_du LASX 0111 01101001 11101 11111 vj:5 vd:5
+
+vext2xv_h_b LASX 0111 01101001 11110 00100 vj:5 vd:5
+vext2xv_w_b LASX 0111 01101001 11110 00101 vj:5 vd:5
+vext2xv_d_b LASX 0111 01101001 11110 00110 vj:5 vd:5
+vext2xv_w_h LASX 0111 01101001 11110 00111 vj:5 vd:5
+vext2xv_d_h LASX 0111 01101001 11110 01000 vj:5 vd:5
+vext2xv_d_w LASX 0111 01101001 11110 01001 vj:5 vd:5
+vext2xv_hu_bu LASX 0111 01101001 11110 01010 vj:5 vd:5
+vext2xv_wu_bu LASX 0111 01101001 11110 01011 vj:5 vd:5
+vext2xv_du_bu LASX 0111 01101001 11110 01100 vj:5 vd:5
+vext2xv_wu_hu LASX 0111 01101001 11110 01101 vj:5 vd:5
+vext2xv_du_hu LASX 0111 01101001 11110 01110 vj:5 vd:5
+vext2xv_du_wu LASX 0111 01101001 11110 01111 vj:5 vd:5
+
+xvsigncov_b LASX 0111 01010010 11100 vk:5 vj:5 vd:5
+xvsigncov_h LASX 0111 01010010 11101 vk:5 vj:5 vd:5
+xvsigncov_w LASX 0111 01010010 11110 vk:5 vj:5 vd:5
+xvsigncov_d LASX 0111 01010010 11111 vk:5 vj:5 vd:5
+
+xvmskltz_b LASX 0111 01101001 11000 10000 vj:5 vd:5
+xvmskltz_h LASX 0111 01101001 11000 10001 vj:5 vd:5
+xvmskltz_w LASX 0111 01101001 11000 10010 vj:5 vd:5
+xvmskltz_d LASX 0111 01101001 11000 10011 vj:5 vd:5
+xvmskgez_b LASX 0111 01101001 11000 10100 vj:5 vd:5
+xvmsknz_b LASX 0111 01101001 11000 11000 vj:5 vd:5
+
+xvldi LASX 0111 01111110 00 si13:13 vd:5 \
+ !constraints { $si13 >= 0 && $si13 <= 12; }
+
+xvand_v LASX 0111 01010010 01100 vk:5 vj:5 vd:5
+xvor_v LASX 0111 01010010 01101 vk:5 vj:5 vd:5
+xvxor_v LASX 0111 01010010 01110 vk:5 vj:5 vd:5
+xvnor_v LASX 0111 01010010 01111 vk:5 vj:5 vd:5
+xvandn_v LASX 0111 01010010 10000 vk:5 vj:5 vd:5
+xvorn_v LASX 0111 01010010 10001 vk:5 vj:5 vd:5
+
+xvandi_b LASX 0111 01111101 00 imm:8 vj:5 vd:5
+xvori_b LASX 0111 01111101 01 imm:8 vj:5 vd:5
+xvxori_b LASX 0111 01111101 10 imm:8 vj:5 vd:5
+xvnori_b LASX 0111 01111101 11 imm:8 vj:5 vd:5
+
+xvsll_b LASX 0111 01001110 10000 vk:5 vj:5 vd:5
+xvsll_h LASX 0111 01001110 10001 vk:5 vj:5 vd:5
+xvsll_w LASX 0111 01001110 10010 vk:5 vj:5 vd:5
+xvsll_d LASX 0111 01001110 10011 vk:5 vj:5 vd:5
+xvslli_b LASX 0111 01110010 11000 01 imm:3 vj:5 vd:5
+xvslli_h LASX 0111 01110010 11000 1 imm:4 vj:5 vd:5
+xvslli_w LASX 0111 01110010 11001 imm:5 vj:5 vd:5
+xvslli_d LASX 0111 01110010 1101 imm:6 vj:5 vd:5
+xvsrl_b LASX 0111 01001110 10100 vk:5 vj:5 vd:5
+xvsrl_h LASX 0111 01001110 10101 vk:5 vj:5 vd:5
+xvsrl_w LASX 0111 01001110 10110 vk:5 vj:5 vd:5
+xvsrl_d LASX 0111 01001110 10111 vk:5 vj:5 vd:5
+xvsrli_b LASX 0111 01110011 00000 01 imm:3 vj:5 vd:5
+xvsrli_h LASX 0111 01110011 00000 1 imm:4 vj:5 vd:5
+xvsrli_w LASX 0111 01110011 00001 imm:5 vj:5 vd:5
+xvsrli_d LASX 0111 01110011 0001 imm:6 vj:5 vd:5
+xvsra_b LASX 0111 01001110 11000 vk:5 vj:5 vd:5
+xvsra_h LASX 0111 01001110 11001 vk:5 vj:5 vd:5
+xvsra_w LASX 0111 01001110 11010 vk:5 vj:5 vd:5
+xvsra_d LASX 0111 01001110 11011 vk:5 vj:5 vd:5
+xvsrai_b LASX 0111 01110011 01000 01 imm:3 vj:5 vd:5
+xvsrai_h LASX 0111 01110011 01000 1 imm:4 vj:5 vd:5
+xvsrai_w LASX 0111 01110011 01001 imm:5 vj:5 vd:5
+xvsrai_d LASX 0111 01110011 0101 imm:6 vj:5 vd:5
+xvrotr_b LASX 0111 01001110 11100 vk:5 vj:5 vd:5
+xvrotr_h LASX 0111 01001110 11101 vk:5 vj:5 vd:5
+xvrotr_w LASX 0111 01001110 11110 vk:5 vj:5 vd:5
+xvrotr_d LASX 0111 01001110 11111 vk:5 vj:5 vd:5
+xvrotri_b LASX 0111 01101010 00000 01 imm:3 vj:5 vd:5
+xvrotri_h LASX 0111 01101010 00000 1 imm:4 vj:5 vd:5
+xvrotri_w LASX 0111 01101010 00001 imm:5 vj:5 vd:5
+xvrotri_d LASX 0111 01101010 0001 imm:6 vj:5 vd:5
+
+xvsllwil_h_b LASX 0111 01110000 10000 01 imm:3 vj:5 vd:5
+xvsllwil_w_h LASX 0111 01110000 10000 1 imm:4 vj:5 vd:5
+xvsllwil_d_w LASX 0111 01110000 10001 imm:5 vj:5 vd:5
+xvextl_q_d LASX 0111 01110000 10010 00000 vj:5 vd:5
+xvsllwil_hu_bu LASX 0111 01110000 11000 01 imm:3 vj:5 vd:5
+xvsllwil_wu_hu LASX 0111 01110000 11000 1 imm:4 vj:5 vd:5
+xvsllwil_du_wu LASX 0111 01110000 11001 imm:5 vj:5 vd:5
+xvextl_qu_du LASX 0111 01110000 11010 00000 vj:5 vd:5
+
+xvsrlr_b LASX 0111 01001111 00000 vk:5 vj:5 vd:5
+xvsrlr_h LASX 0111 01001111 00001 vk:5 vj:5 vd:5
+xvsrlr_w LASX 0111 01001111 00010 vk:5 vj:5 vd:5
+xvsrlr_d LASX 0111 01001111 00011 vk:5 vj:5 vd:5
+xvsrlri_b LASX 0111 01101010 01000 01 imm:3 vj:5 vd:5
+xvsrlri_h LASX 0111 01101010 01000 1 imm:4 vj:5 vd:5
+xvsrlri_w LASX 0111 01101010 01001 imm:5 vj:5 vd:5
+xvsrlri_d LASX 0111 01101010 0101 imm:6 vj:5 vd:5
+xvsrar_b LASX 0111 01001111 00100 vk:5 vj:5 vd:5
+xvsrar_h LASX 0111 01001111 00101 vk:5 vj:5 vd:5
+xvsrar_w LASX 0111 01001111 00110 vk:5 vj:5 vd:5
+xvsrar_d LASX 0111 01001111 00111 vk:5 vj:5 vd:5
+xvsrari_b LASX 0111 01101010 10000 01 imm:3 vj:5 vd:5
+xvsrari_h LASX 0111 01101010 10000 1 imm:4 vj:5 vd:5
+xvsrari_w LASX 0111 01101010 10001 imm:5 vj:5 vd:5
+xvsrari_d LASX 0111 01101010 1001 imm:6 vj:5 vd:5
+
+xvsrln_b_h LASX 0111 01001111 01001 vk:5 vj:5 vd:5
+xvsrln_h_w LASX 0111 01001111 01010 vk:5 vj:5 vd:5
+xvsrln_w_d LASX 0111 01001111 01011 vk:5 vj:5 vd:5
+xvsran_b_h LASX 0111 01001111 01101 vk:5 vj:5 vd:5
+xvsran_h_w LASX 0111 01001111 01110 vk:5 vj:5 vd:5
+xvsran_w_d LASX 0111 01001111 01111 vk:5 vj:5 vd:5
+
+xvsrlni_b_h LASX 0111 01110100 00000 1 imm:4 vj:5 vd:5
+xvsrlni_h_w LASX 0111 01110100 00001 imm:5 vj:5 vd:5
+xvsrlni_w_d LASX 0111 01110100 0001 imm:6 vj:5 vd:5
+xvsrlni_d_q LASX 0111 01110100 001 imm:7 vj:5 vd:5
+xvsrani_b_h LASX 0111 01110101 10000 1 imm:4 vj:5 vd:5
+xvsrani_h_w LASX 0111 01110101 10001 imm:5 vj:5 vd:5
+xvsrani_w_d LASX 0111 01110101 1001 imm:6 vj:5 vd:5
+xvsrani_d_q LASX 0111 01110101 101 imm:7 vj:5 vd:5
+
+xvsrlrn_b_h LASX 0111 01001111 10001 vk:5 vj:5 vd:5
+xvsrlrn_h_w LASX 0111 01001111 10010 vk:5 vj:5 vd:5
+xvsrlrn_w_d LASX 0111 01001111 10011 vk:5 vj:5 vd:5
+xvsrarn_b_h LASX 0111 01001111 10101 vk:5 vj:5 vd:5
+xvsrarn_h_w LASX 0111 01001111 10110 vk:5 vj:5 vd:5
+xvsrarn_w_d LASX 0111 01001111 10111 vk:5 vj:5 vd:5
+
+xvsrlrni_b_h LASX 0111 01110100 01000 1 imm:4 vj:5 vd:5
+xvsrlrni_h_w LASX 0111 01110100 01001 imm:5 vj:5 vd:5
+xvsrlrni_w_d LASX 0111 01110100 0101 imm:6 vj:5 vd:5
+xvsrlrni_d_q LASX 0111 01110100 011 imm:7 vj:5 vd:5
+xvsrarni_b_h LASX 0111 01110101 11000 1 imm:4 vj:5 vd:5
+xvsrarni_h_w LASX 0111 01110101 11001 imm:5 vj:5 vd:5
+xvsrarni_w_d LASX 0111 01110101 1101 imm:6 vj:5 vd:5
+xvsrarni_d_q LASX 0111 01110101 111 imm:7 vj:5 vd:5
+
+xvssrln_b_h LASX 0111 01001111 11001 vk:5 vj:5 vd:5
+xvssrln_h_w LASX 0111 01001111 11010 vk:5 vj:5 vd:5
+xvssrln_w_d LASX 0111 01001111 11011 vk:5 vj:5 vd:5
+xvssran_b_h LASX 0111 01001111 11101 vk:5 vj:5 vd:5
+xvssran_h_w LASX 0111 01001111 11110 vk:5 vj:5 vd:5
+xvssran_w_d LASX 0111 01001111 11111 vk:5 vj:5 vd:5
+xvssrln_bu_h LASX 0111 01010000 01001 vk:5 vj:5 vd:5
+xvssrln_hu_w LASX 0111 01010000 01010 vk:5 vj:5 vd:5
+xvssrln_wu_d LASX 0111 01010000 01011 vk:5 vj:5 vd:5
+xvssran_bu_h LASX 0111 01010000 01101 vk:5 vj:5 vd:5
+xvssran_hu_w LASX 0111 01010000 01110 vk:5 vj:5 vd:5
+xvssran_wu_d LASX 0111 01010000 01111 vk:5 vj:5 vd:5
+
+xvssrlni_b_h LASX 0111 01110100 10000 1 imm:4 vj:5 vd:5
+xvssrlni_h_w LASX 0111 01110100 10001 imm:5 vj:5 vd:5
+xvssrlni_w_d LASX 0111 01110100 1001 imm:6 vj:5 vd:5
+xvssrlni_d_q LASX 0111 01110100 101 imm:7 vj:5 vd:5
+xvssrani_b_h LASX 0111 01110110 00000 1 imm:4 vj:5 vd:5
+xvssrani_h_w LASX 0111 01110110 00001 imm:5 vj:5 vd:5
+xvssrani_w_d LASX 0111 01110110 0001 imm:6 vj:5 vd:5
+xvssrani_d_q LASX 0111 01110110 001 imm:7 vj:5 vd:5
+xvssrlni_bu_h LASX 0111 01110100 11000 1 imm:4 vj:5 vd:5
+xvssrlni_hu_w LASX 0111 01110100 11001 imm:5 vj:5 vd:5
+xvssrlni_wu_d LASX 0111 01110100 1101 imm:6 vj:5 vd:5
+xvssrlni_du_q LASX 0111 01110100 111 imm:7 vj:5 vd:5
+xvssrani_bu_h LASX 0111 01110110 01000 1 imm:4 vj:5 vd:5
+xvssrani_hu_w LASX 0111 01110110 01001 imm:5 vj:5 vd:5
+xvssrani_wu_d LASX 0111 01110110 0101 imm:6 vj:5 vd:5
+xvssrani_du_q LASX 0111 01110110 011 imm:7 vj:5 vd:5
+
+xvssrlrn_b_h LASX 0111 01010000 00001 vk:5 vj:5 vd:5
+xvssrlrn_h_w LASX 0111 01010000 00010 vk:5 vj:5 vd:5
+xvssrlrn_w_d LASX 0111 01010000 00011 vk:5 vj:5 vd:5
+xvssrarn_b_h LASX 0111 01010000 00101 vk:5 vj:5 vd:5
+xvssrarn_h_w LASX 0111 01010000 00110 vk:5 vj:5 vd:5
+xvssrarn_w_d LASX 0111 01010000 00111 vk:5 vj:5 vd:5
+xvssrlrn_bu_h LASX 0111 01010000 10001 vk:5 vj:5 vd:5
+xvssrlrn_hu_w LASX 0111 01010000 10010 vk:5 vj:5 vd:5
+xvssrlrn_wu_d LASX 0111 01010000 10011 vk:5 vj:5 vd:5
+xvssrarn_bu_h LASX 0111 01010000 10101 vk:5 vj:5 vd:5
+xvssrarn_hu_w LASX 0111 01010000 10110 vk:5 vj:5 vd:5
+xvssrarn_wu_d LASX 0111 01010000 10111 vk:5 vj:5 vd:5
+
+xvssrlrni_b_h LASX 0111 01110101 00000 1 imm:4 vj:5 vd:5
+xvssrlrni_h_w LASX 0111 01110101 00001 imm:5 vj:5 vd:5
+xvssrlrni_w_d LASX 0111 01110101 0001 imm:6 vj:5 vd:5
+xvssrlrni_d_q LASX 0111 01110101 001 imm:7 vj:5 vd:5
+xvssrarni_b_h LASX 0111 01110110 10000 1 imm:4 vj:5 vd:5
+xvssrarni_h_w LASX 0111 01110110 10001 imm:5 vj:5 vd:5
+xvssrarni_w_d LASX 0111 01110110 1001 imm:6 vj:5 vd:5
+xvssrarni_d_q LASX 0111 01110110 101 imm:7 vj:5 vd:5
+xvssrlrni_bu_h LASX 0111 01110101 01000 1 imm:4 vj:5 vd:5
+xvssrlrni_hu_w LASX 0111 01110101 01001 imm:5 vj:5 vd:5
+xvssrlrni_wu_d LASX 0111 01110101 0101 imm:6 vj:5 vd:5
+xvssrlrni_du_q LASX 0111 01110101 011 imm:7 vj:5 vd:5
+xvssrarni_bu_h LASX 0111 01110110 11000 1 imm:4 vj:5 vd:5
+xvssrarni_hu_w LASX 0111 01110110 11001 imm:5 vj:5 vd:5
+xvssrarni_wu_d LASX 0111 01110110 1101 imm:6 vj:5 vd:5
+xvssrarni_du_q LASX 0111 01110110 111 imm:7 vj:5 vd:5
+
+xvclo_b LASX 0111 01101001 11000 00000 vj:5 vd:5
+xvclo_h LASX 0111 01101001 11000 00001 vj:5 vd:5
+xvclo_w LASX 0111 01101001 11000 00010 vj:5 vd:5
+xvclo_d LASX 0111 01101001 11000 00011 vj:5 vd:5
+xvclz_b LASX 0111 01101001 11000 00100 vj:5 vd:5
+xvclz_h LASX 0111 01101001 11000 00101 vj:5 vd:5
+xvclz_w LASX 0111 01101001 11000 00110 vj:5 vd:5
+xvclz_d LASX 0111 01101001 11000 00111 vj:5 vd:5
+
+xvpcnt_b LASX 0111 01101001 11000 01000 vj:5 vd:5
+xvpcnt_h LASX 0111 01101001 11000 01001 vj:5 vd:5
+xvpcnt_w LASX 0111 01101001 11000 01010 vj:5 vd:5
+xvpcnt_d LASX 0111 01101001 11000 01011 vj:5 vd:5
+
+xvbitclr_b LASX 0111 01010000 11000 vk:5 vj:5 vd:5
+xvbitclr_h LASX 0111 01010000 11001 vk:5 vj:5 vd:5
+xvbitclr_w LASX 0111 01010000 11010 vk:5 vj:5 vd:5
+xvbitclr_d LASX 0111 01010000 11011 vk:5 vj:5 vd:5
+xvbitclri_b LASX 0111 01110001 00000 01 imm:3 vj:5 vd:5
+xvbitclri_h LASX 0111 01110001 00000 1 imm:4 vj:5 vd:5
+xvbitclri_w LASX 0111 01110001 00001 imm:5 vj:5 vd:5
+xvbitclri_d LASX 0111 01110001 0001 imm:6 vj:5 vd:5
+
+xvbitset_b LASX 0111 01010000 11100 vk:5 vj:5 vd:5
+xvbitset_h LASX 0111 01010000 11101 vk:5 vj:5 vd:5
+xvbitset_w LASX 0111 01010000 11110 vk:5 vj:5 vd:5
+xvbitset_d LASX 0111 01010000 11111 vk:5 vj:5 vd:5
+xvbitseti_b LASX 0111 01110001 01000 01 imm:3 vj:5 vd:5
+xvbitseti_h LASX 0111 01110001 01000 1 imm:4 vj:5 vd:5
+xvbitseti_w LASX 0111 01110001 01001 imm:5 vj:5 vd:5
+xvbitseti_d LASX 0111 01110001 0101 imm:6 vj:5 vd:5
+
+xvbitrev_b LASX 0111 01010001 00000 vk:5 vj:5 vd:5
+xvbitrev_h LASX 0111 01010001 00001 vk:5 vj:5 vd:5
+xvbitrev_w LASX 0111 01010001 00010 vk:5 vj:5 vd:5
+xvbitrev_d LASX 0111 01010001 00011 vk:5 vj:5 vd:5
+xvbitrevi_b LASX 0111 01110001 10000 01 imm:3 vj:5 vd:5
+xvbitrevi_h LASX 0111 01110001 10000 1 imm:4 vj:5 vd:5
+xvbitrevi_w LASX 0111 01110001 10001 imm:5 vj:5 vd:5
+xvbitrevi_d LASX 0111 01110001 1001 imm:6 vj:5 vd:5
+
+xvfrstp_b LASX 0111 01010010 10110 vk:5 vj:5 vd:5
+xvfrstp_h LASX 0111 01010010 10111 vk:5 vj:5 vd:5
+xvfrstpi_b LASX 0111 01101001 10100 imm:5 vj:5 vd:5
+xvfrstpi_h LASX 0111 01101001 10101 imm:5 vj:5 vd:5
+
+xvfadd_s LASX 0111 01010011 00001 vk:5 vj:5 vd:5
+xvfadd_d LASX 0111 01010011 00010 vk:5 vj:5 vd:5
+xvfsub_s LASX 0111 01010011 00101 vk:5 vj:5 vd:5
+xvfsub_d LASX 0111 01010011 00110 vk:5 vj:5 vd:5
+xvfmul_s LASX 0111 01010011 10001 vk:5 vj:5 vd:5
+xvfmul_d LASX 0111 01010011 10010 vk:5 vj:5 vd:5
+xvfdiv_s LASX 0111 01010011 10101 vk:5 vj:5 vd:5
+xvfdiv_d LASX 0111 01010011 10110 vk:5 vj:5 vd:5
+
+xvfmadd_s LASX 0000 10100001 xa:5 vk:5 vj:5 vd:5
+xvfmadd_d LASX 0000 10100010 xa:5 vk:5 vj:5 vd:5
+xvfmsub_s LASX 0000 10100101 xa:5 vk:5 vj:5 vd:5
+xvfmsub_d LASX 0000 10100110 xa:5 vk:5 vj:5 vd:5
+xvfnmadd_s LASX 0000 10101001 xa:5 vk:5 vj:5 vd:5
+xvfnmadd_d LASX 0000 10101010 xa:5 vk:5 vj:5 vd:5
+xvfnmsub_s LASX 0000 10101101 xa:5 vk:5 vj:5 vd:5
+xvfnmsub_d LASX 0000 10101110 xa:5 vk:5 vj:5 vd:5
+
+xvfmax_s LASX 0111 01010011 11001 vk:5 vj:5 vd:5
+xvfmax_d LASX 0111 01010011 11010 vk:5 vj:5 vd:5
+xvfmin_s LASX 0111 01010011 11101 vk:5 vj:5 vd:5
+xvfmin_d LASX 0111 01010011 11110 vk:5 vj:5 vd:5
+
+xvfmaxa_s LASX 0111 01010100 00001 vk:5 vj:5 vd:5
+xvfmaxa_d LASX 0111 01010100 00010 vk:5 vj:5 vd:5
+xvfmina_s LASX 0111 01010100 00101 vk:5 vj:5 vd:5
+xvfmina_d LASX 0111 01010100 00110 vk:5 vj:5 vd:5
+
+xvflogb_s LASX 0111 01101001 11001 10001 vj:5 vd:5
+xvflogb_d LASX 0111 01101001 11001 10010 vj:5 vd:5
+
+xvfclass_s LASX 0111 01101001 11001 10101 vj:5 vd:5
+xvfclass_d LASX 0111 01101001 11001 10110 vj:5 vd:5
+
+xvfsqrt_s LASX 0111 01101001 11001 11001 vj:5 vd:5
+xvfsqrt_d LASX 0111 01101001 11001 11010 vj:5 vd:5
+xvfrecip_s LASX 0111 01101001 11001 11101 vj:5 vd:5
+xvfrecip_d LASX 0111 01101001 11001 11110 vj:5 vd:5
+xvfrsqrt_s LASX 0111 01101001 11010 00001 vj:5 vd:5
+xvfrsqrt_d LASX 0111 01101001 11010 00010 vj:5 vd:5
+
+xvfcvtl_s_h LASX 0111 01101001 11011 11010 vj:5 vd:5
+xvfcvth_s_h LASX 0111 01101001 11011 11011 vj:5 vd:5
+xvfcvtl_d_s LASX 0111 01101001 11011 11100 vj:5 vd:5
+xvfcvth_d_s LASX 0111 01101001 11011 11101 vj:5 vd:5
+xvfcvt_h_s LASX 0111 01010100 01100 vk:5 vj:5 vd:5
+xvfcvt_s_d LASX 0111 01010100 01101 vk:5 vj:5 vd:5
+
+xvfrintrne_s LASX 0111 01101001 11010 11101 vj:5 vd:5
+xvfrintrne_d LASX 0111 01101001 11010 11110 vj:5 vd:5
+xvfrintrz_s LASX 0111 01101001 11010 11001 vj:5 vd:5
+xvfrintrz_d LASX 0111 01101001 11010 11010 vj:5 vd:5
+xvfrintrp_s LASX 0111 01101001 11010 10101 vj:5 vd:5
+xvfrintrp_d LASX 0111 01101001 11010 10110 vj:5 vd:5
+xvfrintrm_s LASX 0111 01101001 11010 10001 vj:5 vd:5
+xvfrintrm_d LASX 0111 01101001 11010 10010 vj:5 vd:5
+xvfrint_s LASX 0111 01101001 11010 01101 vj:5 vd:5
+xvfrint_d LASX 0111 01101001 11010 01110 vj:5 vd:5
+
+xvftintrne_w_s LASX 0111 01101001 11100 10100 vj:5 vd:5
+xvftintrne_l_d LASX 0111 01101001 11100 10101 vj:5 vd:5
+xvftintrz_w_s LASX 0111 01101001 11100 10010 vj:5 vd:5
+xvftintrz_l_d LASX 0111 01101001 11100 10011 vj:5 vd:5
+xvftintrp_w_s LASX 0111 01101001 11100 10000 vj:5 vd:5
+xvftintrp_l_d LASX 0111 01101001 11100 10001 vj:5 vd:5
+xvftintrm_w_s LASX 0111 01101001 11100 01110 vj:5 vd:5
+xvftintrm_l_d LASX 0111 01101001 11100 01111 vj:5 vd:5
+xvftint_w_s LASX 0111 01101001 11100 01100 vj:5 vd:5
+xvftint_l_d LASX 0111 01101001 11100 01101 vj:5 vd:5
+xvftintrz_wu_s LASX 0111 01101001 11100 11100 vj:5 vd:5
+xvftintrz_lu_d LASX 0111 01101001 11100 11101 vj:5 vd:5
+xvftint_wu_s LASX 0111 01101001 11100 10110 vj:5 vd:5
+xvftint_lu_d LASX 0111 01101001 11100 10111 vj:5 vd:5
+
+xvftintrne_w_d LASX 0111 01010100 10111 vk:5 vj:5 vd:5
+xvftintrz_w_d LASX 0111 01010100 10110 vk:5 vj:5 vd:5
+xvftintrp_w_d LASX 0111 01010100 10101 vk:5 vj:5 vd:5
+xvftintrm_w_d LASX 0111 01010100 10100 vk:5 vj:5 vd:5
+xvftint_w_d LASX 0111 01010100 10011 vk:5 vj:5 vd:5
+
+xvftintrnel_l_s LASX 0111 01101001 11101 01000 vj:5 vd:5
+xvftintrneh_l_s LASX 0111 01101001 11101 01001 vj:5 vd:5
+xvftintrzl_l_s LASX 0111 01101001 11101 00110 vj:5 vd:5
+xvftintrzh_l_s LASX 0111 01101001 11101 00111 vj:5 vd:5
+xvftintrpl_l_s LASX 0111 01101001 11101 00100 vj:5 vd:5
+xvftintrph_l_s LASX 0111 01101001 11101 00101 vj:5 vd:5
+xvftintrml_l_s LASX 0111 01101001 11101 00010 vj:5 vd:5
+xvftintrmh_l_s LASX 0111 01101001 11101 00011 vj:5 vd:5
+xvftintl_l_s LASX 0111 01101001 11101 00000 vj:5 vd:5
+xvftinth_l_s LASX 0111 01101001 11101 00001 vj:5 vd:5
+
+xvffint_s_w LASX 0111 01101001 11100 00000 vj:5 vd:5
+xvffint_d_l LASX 0111 01101001 11100 00010 vj:5 vd:5
+xvffint_s_wu LASX 0111 01101001 11100 00001 vj:5 vd:5
+xvffint_d_lu LASX 0111 01101001 11100 00011 vj:5 vd:5
+xvffintl_d_w LASX 0111 01101001 11100 00100 vj:5 vd:5
+xvffinth_d_w LASX 0111 01101001 11100 00101 vj:5 vd:5
+xvffint_s_l LASX 0111 01010100 10000 vk:5 vj:5 vd:5
+
+xvseq_b LASX 0111 01000000 00000 vk:5 vj:5 vd:5
+xvseq_h LASX 0111 01000000 00001 vk:5 vj:5 vd:5
+xvseq_w LASX 0111 01000000 00010 vk:5 vj:5 vd:5
+xvseq_d LASX 0111 01000000 00011 vk:5 vj:5 vd:5
+xvseqi_b LASX 0111 01101000 00000 si5:5 vj:5 vd:5
+xvseqi_h LASX 0111 01101000 00001 si5:5 vj:5 vd:5
+xvseqi_w LASX 0111 01101000 00010 si5:5 vj:5 vd:5
+xvseqi_d LASX 0111 01101000 00011 si5:5 vj:5 vd:5
+
+xvsle_b LASX 0111 01000000 00100 vk:5 vj:5 vd:5
+xvsle_h LASX 0111 01000000 00101 vk:5 vj:5 vd:5
+xvsle_w LASX 0111 01000000 00110 vk:5 vj:5 vd:5
+xvsle_d LASX 0111 01000000 00111 vk:5 vj:5 vd:5
+xvslei_b LASX 0111 01101000 00100 si5:5 vj:5 vd:5
+xvslei_h LASX 0111 01101000 00101 si5:5 vj:5 vd:5
+xvslei_w LASX 0111 01101000 00110 si5:5 vj:5 vd:5
+xvslei_d LASX 0111 01101000 00111 si5:5 vj:5 vd:5
+xvsle_bu LASX 0111 01000000 01000 vk:5 vj:5 vd:5
+xvsle_hu LASX 0111 01000000 01001 vk:5 vj:5 vd:5
+xvsle_wu LASX 0111 01000000 01010 vk:5 vj:5 vd:5
+xvsle_du LASX 0111 01000000 01011 vk:5 vj:5 vd:5
+xvslei_bu LASX 0111 01101000 01000 imm:5 vj:5 vd:5
+xvslei_hu LASX 0111 01101000 01001 imm:5 vj:5 vd:5
+xvslei_wu LASX 0111 01101000 01010 imm:5 vj:5 vd:5
+xvslei_du LASX 0111 01101000 01011 imm:5 vj:5 vd:5
+
+xvslt_b LASX 0111 01000000 01100 vk:5 vj:5 vd:5
+xvslt_h LASX 0111 01000000 01101 vk:5 vj:5 vd:5
+xvslt_w LASX 0111 01000000 01110 vk:5 vj:5 vd:5
+xvslt_d LASX 0111 01000000 01111 vk:5 vj:5 vd:5
+xvslti_b LASX 0111 01101000 01100 si5:5 vj:5 vd:5
+xvslti_h LASX 0111 01101000 01101 si5:5 vj:5 vd:5
+xvslti_w LASX 0111 01101000 01110 si5:5 vj:5 vd:5
+xvslti_d LASX 0111 01101000 01111 si5:5 vj:5 vd:5
+xvslt_bu LASX 0111 01000000 10000 vk:5 vj:5 vd:5
+xvslt_hu LASX 0111 01000000 10001 vk:5 vj:5 vd:5
+xvslt_wu LASX 0111 01000000 10010 vk:5 vj:5 vd:5
+xvslt_du LASX 0111 01000000 10011 vk:5 vj:5 vd:5
+xvslti_bu LASX 0111 01101000 10000 imm:5 vj:5 vd:5
+xvslti_hu LASX 0111 01101000 10001 imm:5 vj:5 vd:5
+xvslti_wu LASX 0111 01101000 10010 imm:5 vj:5 vd:5
+xvslti_du LASX 0111 01101000 10011 imm:5 vj:5 vd:5
+
+xvfcmp_cond_s LASX 0000 11001001 cond:5 vk:5 vj:5 vd:5 \
+ !constraints { $cond > 0 && $cond < 0x12; }
+xvfcmp_cond_d LASX 0000 11001010 cond:5 vk:5 vj:5 vd:5 \
+ !constraints { $cond > 0 && $cond < 0x12; }
+
+xvbitsel_v LASX 0000 11010010 xa:5 vk:5 vj:5 vd:5
+xvbitseli_b LASX 0111 01111100 01 imm:8 vj:5 vd:5
+
+xvseteqz_v LASX 0111 01101001 11001 00110 vj:5 00 cd:3
+xvsetnez_v LASX 0111 01101001 11001 00111 vj:5 00 cd:3
+xvsetanyeqz_b LASX 0111 01101001 11001 01000 vj:5 00 cd:3
+xvsetanyeqz_h LASX 0111 01101001 11001 01001 vj:5 00 cd:3
+xvsetanyeqz_w LASX 0111 01101001 11001 01010 vj:5 00 cd:3
+xvsetanyeqz_d LASX 0111 01101001 11001 01011 vj:5 00 cd:3
+xvsetallnez_b LASX 0111 01101001 11001 01100 vj:5 00 cd:3
+xvsetallnez_h LASX 0111 01101001 11001 01101 vj:5 00 cd:3
+xvsetallnez_w LASX 0111 01101001 11001 01110 vj:5 00 cd:3
+xvsetallnez_d LASX 0111 01101001 11001 01111 vj:5 00 cd:3
+
+xvinsgr2vr_w LASX 0111 01101110 10111 10 imm:3 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; }
+xvinsgr2vr_d LASX 0111 01101110 10111 110 imm:2 rj:5 vd:5 \
+ !constraints { $rj != 2 && $rj != 0; }
+xvpickve2gr_w LASX 0111 01101110 11111 10 imm:3 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+xvpickve2gr_d LASX 0111 01101110 11111 110 imm:2 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+xvpickve2gr_wu LASX 0111 01101111 00111 10 imm:3 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+xvpickve2gr_du LASX 0111 01101111 00111 110 imm:2 vj:5 rd:5 \
+ !constraints { $rd != 2 && $rd != 0; }
+
+xvrepl128vei_b LASX 0111 01101111 01111 0 imm:4 vj:5 vd:5
+xvrepl128vei_h LASX 0111 01101111 01111 10 imm:3 vj:5 vd:5
+xvrepl128vei_w LASX 0111 01101111 01111 110 imm:2 vj:5 vd:5
+xvrepl128vei_d LASX 0111 01101111 01111 1110 imm:1 vj:5 vd:5
+
+xvreplve_b LASX 0111 01010010 00100 rk:5 vj:5 vd:5
+xvreplve_h LASX 0111 01010010 00101 rk:5 vj:5 vd:5
+xvreplve_w LASX 0111 01010010 00110 rk:5 vj:5 vd:5
+xvreplve_d LASX 0111 01010010 00111 rk:5 vj:5 vd:5
+
+xvreplve0_b LASX 0111 01110000 01110 00000 vj:5 vd:5
+xvreplve0_h LASX 0111 01110000 01111 00000 vj:5 vd:5
+xvreplve0_w LASX 0111 01110000 01111 10000 vj:5 vd:5
+xvreplve0_d LASX 0111 01110000 01111 11000 vj:5 vd:5
+xvreplve0_q LASX 0111 01110000 01111 11100 vj:5 vd:5
+
+xvinsve0_w LASX 0111 01101111 11111 10 imm:3 vj:5 vd:5
+xvinsve0_d LASX 0111 01101111 11111 110 imm:2 vj:5 vd:5
+
+xvpickve_w LASX 0111 01110000 00111 10 imm:3 vj:5 vd:5
+xvpickve_d LASX 0111 01110000 00111 110 imm:2 vj:5 vd:5
+
+xvbsll_v LASX 0111 01101000 11100 imm:5 vj:5 vd:5
+xvbsrl_v LASX 0111 01101000 11101 imm:5 vj:5 vd:5
+
+xvpackev_b LASX 0111 01010001 01100 vk:5 vj:5 vd:5
+xvpackev_h LASX 0111 01010001 01101 vk:5 vj:5 vd:5
+xvpackev_w LASX 0111 01010001 01110 vk:5 vj:5 vd:5
+xvpackev_d LASX 0111 01010001 01111 vk:5 vj:5 vd:5
+xvpackod_b LASX 0111 01010001 10000 vk:5 vj:5 vd:5
+xvpackod_h LASX 0111 01010001 10001 vk:5 vj:5 vd:5
+xvpackod_w LASX 0111 01010001 10010 vk:5 vj:5 vd:5
+xvpackod_d LASX 0111 01010001 10011 vk:5 vj:5 vd:5
+
+xvpickev_b LASX 0111 01010001 11100 vk:5 vj:5 vd:5
+xvpickev_h LASX 0111 01010001 11101 vk:5 vj:5 vd:5
+xvpickev_w LASX 0111 01010001 11110 vk:5 vj:5 vd:5
+xvpickev_d LASX 0111 01010001 11111 vk:5 vj:5 vd:5
+xvpickod_b LASX 0111 01010010 00000 vk:5 vj:5 vd:5
+xvpickod_h LASX 0111 01010010 00001 vk:5 vj:5 vd:5
+xvpickod_w LASX 0111 01010010 00010 vk:5 vj:5 vd:5
+xvpickod_d LASX 0111 01010010 00011 vk:5 vj:5 vd:5
+
+xvilvl_b LASX 0111 01010001 10100 vk:5 vj:5 vd:5
+xvilvl_h LASX 0111 01010001 10101 vk:5 vj:5 vd:5
+xvilvl_w LASX 0111 01010001 10110 vk:5 vj:5 vd:5
+xvilvl_d LASX 0111 01010001 10111 vk:5 vj:5 vd:5
+xvilvh_b LASX 0111 01010001 11000 vk:5 vj:5 vd:5
+xvilvh_h LASX 0111 01010001 11001 vk:5 vj:5 vd:5
+xvilvh_w LASX 0111 01010001 11010 vk:5 vj:5 vd:5
+xvilvh_d LASX 0111 01010001 11011 vk:5 vj:5 vd:5
+
+#xvshuf_b LASX 0000 11010110 xa:5 vk:5 vj:5 vd:5
+#xvshuf_h LASX 0111 01010111 10101 vk:5 vj:5 vd:5
+#xvshuf_w LASX 0111 01010111 10110 vk:5 vj:5 vd:5
+#xvshuf_d LASX 0111 01010111 10111 vk:5 vj:5 vd:5
+
+xvperm_w LASX 0111 01010111 11010 vk:5 vj:5 vd:5
+
+xvshuf4i_b LASX 0111 01111001 00 imm:8 vj:5 vd:5
+xvshuf4i_h LASX 0111 01111001 01 imm:8 vj:5 vd:5
+xvshuf4i_w LASX 0111 01111001 10 imm:8 vj:5 vd:5
+xvshuf4i_d LASX 0111 01111001 11 imm:8 vj:5 vd:5
+
+xvpermi_w LASX 0111 01111110 01 imm:8 vj:5 vd:5
+xvpermi_d LASX 0111 01111110 10 imm:8 vj:5 vd:5
+#xvpermi_q LASX 0111 01111110 11 imm:8 vj:5 vd:5
+
+xvextrins_d LASX 0111 01111000 00 imm:8 vj:5 vd:5
+xvextrins_w LASX 0111 01111000 01 imm:8 vj:5 vd:5
+xvextrins_h LASX 0111 01111000 10 imm:8 vj:5 vd:5
+xvextrins_b LASX 0111 01111000 11 imm:8 vj:5 vd:5
+
+xvld LASX 0010 110010 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+xvst LASX 0010 110011 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+xvldx LASX 0011 10000100 10000 rk:5 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+xvstx LASX 0011 10000100 11000 rk:5 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != $rk && $rk != 2 && $rj != 2; } \
+ !memory { reg_plus_reg($rj, $rk); }
+
+xvldrepl_d LASX 0011 00100001 0 si9:9 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si9, 9) * 8); }
+xvldrepl_w LASX 0011 00100010 si10:10 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si10, 10) * 4); }
+xvldrepl_h LASX 0011 0010010 si11:11 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si11, 11) * 2); }
+xvldrepl_b LASX 0011 001010 si12:12 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si12, 12)); }
+
+xvstelm_d LASX 0011 00110001 si2:2 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 8); }
+xvstelm_w LASX 0011 0011001 si3:3 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 4); }
+xvstelm_h LASX 0011 001101 si4:4 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 2); }
+xvstelm_b LASX 0011 00111 si5:5 si8:8 rj:5 vd:5 \
+ !constraints { $rj != 0 && $rj != 2; } \
+ !memory { reg_plus_imm($rj, sextract($si8, 8) * 2); }
diff --git a/reginfo.c b/reginfo.c
deleted file mode 100644
index dd42ae2..0000000
--- a/reginfo.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2017 Linaro Limited
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Peter Maydell (Linaro) - initial implementation
- *****************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-
-#include "risu.h"
-
-struct reginfo master_ri, apprentice_ri;
-
-uint8_t apprentice_memblock[MEMBLOCKLEN];
-
-static int mem_used;
-static int packet_mismatch;
-
-int send_register_info(write_fn write_fn, void *uc)
-{
- struct reginfo ri;
- trace_header_t header;
- int op;
-
- reginfo_init(&ri, uc);
- op = get_risuop(&ri);
-
- /* Write a header with PC/op to keep in sync */
- header.pc = get_pc(&ri);
- header.risu_op = op;
- if (write_fn(&header, sizeof(header)) != 0) {
- return -1;
- }
-
- switch (op) {
- case OP_TESTEND:
- write_fn(&ri, reginfo_size());
- /* if we are tracing write_fn will return 0 unlike a remote
- end, hence we force return of 1 here */
- return 1;
- case OP_SETMEMBLOCK:
- memblock = (void *)(uintptr_t)get_reginfo_paramreg(&ri);
- break;
- case OP_GETMEMBLOCK:
- set_ucontext_paramreg(uc,
- get_reginfo_paramreg(&ri) + (uintptr_t)memblock);
- break;
- case OP_COMPAREMEM:
- return write_fn(memblock, MEMBLOCKLEN);
- break;
- case OP_COMPARE:
- default:
- /* Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
- return write_fn(&ri, reginfo_size());
- }
- return 0;
-}
-
-/* Read register info from the socket and compare it with that from the
- * ucontext. Return 0 for match, 1 for end-of-test, 2 for mismatch.
- * NB: called from a signal handler.
- *
- * We don't have any kind of identifying info in the incoming data
- * that says whether it is register or memory data, so if the two
- * sides get out of sync then we will fail obscurely.
- */
-int recv_and_compare_register_info(read_fn read_fn,
- respond_fn resp_fn, void *uc)
-{
- int resp = 0, op;
- trace_header_t header;
-
- reginfo_init(&master_ri, uc);
- op = get_risuop(&master_ri);
-
- if (read_fn(&header, sizeof(header)) != 0) {
- return -1;
- }
-
- if (header.risu_op != op) {
- /* We are out of sync */
- resp = 2;
- resp_fn(resp);
- return resp;
- }
-
- /* send OK for the header */
- resp_fn(0);
-
- switch (op) {
- case OP_COMPARE:
- case OP_TESTEND:
- default:
- /* Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
- if (read_fn(&apprentice_ri, reginfo_size())) {
- packet_mismatch = 1;
- resp = 2;
- } else if (!reginfo_is_eq(&master_ri, &apprentice_ri)) {
- /* register mismatch */
- resp = 2;
- } else if (op == OP_TESTEND) {
- resp = 1;
- }
- resp_fn(resp);
- break;
- case OP_SETMEMBLOCK:
- memblock = (void *)(uintptr_t)get_reginfo_paramreg(&master_ri);
- break;
- case OP_GETMEMBLOCK:
- set_ucontext_paramreg(uc, get_reginfo_paramreg(&master_ri) +
- (uintptr_t)memblock);
- break;
- case OP_COMPAREMEM:
- mem_used = 1;
- if (read_fn(apprentice_memblock, MEMBLOCKLEN)) {
- packet_mismatch = 1;
- resp = 2;
- } else if (memcmp(memblock, apprentice_memblock, MEMBLOCKLEN) != 0) {
- /* memory mismatch */
- resp = 2;
- }
- resp_fn(resp);
- break;
- }
-
- return resp;
-}
-
-/* Print a useful report on the status of the last comparison
- * done in recv_and_compare_register_info(). This is called on
- * exit, so need not restrict itself to signal-safe functions.
- * Should return 0 if it was a good match (ie end of test)
- * and 1 for a mismatch.
- */
-int report_match_status(int trace)
-{
- int resp = 0;
- fprintf(stderr, "match status...\n");
- if (packet_mismatch) {
- fprintf(stderr, "packet mismatch (probably disagreement "
- "about UNDEF on load/store)\n");
- /* We don't have valid reginfo from the apprentice side
- * so stop now rather than printing anything about it.
- */
- fprintf(stderr, "%s reginfo:\n", trace ? "this" : "master");
- reginfo_dump(&master_ri, stderr);
- return 1;
- }
- if (!reginfo_is_eq(&master_ri, &apprentice_ri)) {
- fprintf(stderr, "mismatch on regs!\n");
- resp = 1;
- }
- if (mem_used
- && memcmp(memblock, &apprentice_memblock, MEMBLOCKLEN) != 0) {
- fprintf(stderr, "mismatch on memory!\n");
- resp = 1;
- }
- if (!resp) {
- fprintf(stderr, "match!\n");
- return 0;
- }
-
- fprintf(stderr, "%s reginfo:\n", trace ? "this" : "master");
- reginfo_dump(&master_ri, stderr);
- fprintf(stderr, "%s reginfo:\n", trace ? "trace" : "apprentice");
- reginfo_dump(&apprentice_ri, stderr);
-
- if (trace) {
- reginfo_dump_mismatch(&apprentice_ri, &master_ri, stderr);
- } else {
- reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr);
- }
- return resp;
-}
diff --git a/risu.c b/risu.c
index 01525d2..36fc82a 100644
--- a/risu.c
+++ b/risu.c
@@ -28,138 +28,298 @@
#include "config.h"
#include "risu.h"
-void *memblock;
+enum {
+ MASTER = 0, APPRENTICE = 1
+};
-int apprentice_fd, master_fd;
-int trace;
-size_t signal_count;
+static struct reginfo ri[2];
+static uint8_t other_memblock[MEMBLOCKLEN];
+static trace_header_t header;
+
+/* Memblock pointer into the execution image. */
+static void *memblock;
+
+static int comm_fd;
+static bool trace;
+static size_t signal_count;
#ifdef HAVE_ZLIB
#include <zlib.h>
-gzFile gz_trace_file;
+static gzFile gz_trace_file;
#define TRACE_TYPE "compressed"
#else
#define TRACE_TYPE "uncompressed"
#endif
-sigjmp_buf jmpbuf;
+static sigjmp_buf jmpbuf;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-/* Master functions */
-
-int read_sock(void *ptr, size_t bytes)
-{
- return recv_data_pkt(master_fd, ptr, bytes);
-}
+/* I/O functions */
-int write_trace(void *ptr, size_t bytes)
+static RisuResult read_buffer(void *ptr, size_t bytes)
{
size_t res;
+ if (!trace) {
+ return recv_data_pkt(comm_fd, ptr, bytes);
+ }
+
#ifdef HAVE_ZLIB
- if (master_fd == STDOUT_FILENO) {
+ if (comm_fd == STDIN_FILENO) {
#endif
- res = write(master_fd, ptr, bytes);
+ res = read(comm_fd, ptr, bytes);
#ifdef HAVE_ZLIB
} else {
- res = gzwrite(gz_trace_file, ptr, bytes);
+ res = gzread(gz_trace_file, ptr, bytes);
}
#endif
- return (res == bytes) ? 0 : 1;
-}
-
-void respond_sock(int r)
-{
- send_response_byte(master_fd, r);
-}
-
-/* Apprentice function */
-int write_sock(void *ptr, size_t bytes)
-{
- return send_data_pkt(apprentice_fd, ptr, bytes);
+ return res == bytes ? RES_OK : RES_BAD_IO;
}
-int read_trace(void *ptr, size_t bytes)
+static RisuResult write_buffer(void *ptr, size_t bytes)
{
size_t res;
+ if (!trace) {
+ return send_data_pkt(comm_fd, ptr, bytes);
+ }
+
#ifdef HAVE_ZLIB
- if (apprentice_fd == STDIN_FILENO) {
+ if (comm_fd == STDOUT_FILENO) {
#endif
- res = read(apprentice_fd, ptr, bytes);
+ res = write(comm_fd, ptr, bytes);
#ifdef HAVE_ZLIB
} else {
- res = gzread(gz_trace_file, ptr, bytes);
+ res = gzwrite(gz_trace_file, ptr, bytes);
}
#endif
- return (res == bytes) ? 0 : 1;
+ return res == bytes ? RES_OK : RES_BAD_IO;
+}
+
+static void respond(RisuResult r)
+{
+ if (!trace) {
+ send_response_byte(comm_fd, r);
+ }
}
-void respond_trace(int r)
+static RisuResult send_register_info(void *uc, void *siaddr)
{
- switch (r) {
- case 0: /* test ok */
- case 1: /* end of test */
+ uint64_t paramreg;
+ RisuResult res;
+ RisuOp op;
+ void *extra;
+
+ reginfo_init(&ri[MASTER], uc, siaddr);
+ op = get_risuop(&ri[MASTER]);
+
+ /* Write a header with PC/op to keep in sync */
+ header.magic = RISU_MAGIC;
+ header.pc = get_pc(&ri[MASTER]);
+ header.risu_op = op;
+
+ switch (op) {
+ case OP_TESTEND:
+ case OP_COMPARE:
+ case OP_SIGILL:
+ header.size = reginfo_size(&ri[MASTER]);
+ extra = &ri[MASTER];
+ break;
+ case OP_COMPAREMEM:
+ header.size = MEMBLOCKLEN;
+ extra = memblock;
+ break;
+ case OP_SETMEMBLOCK:
+ case OP_GETMEMBLOCK:
+ header.size = 0;
+ extra = NULL;
break;
default:
- /* mismatch - if tracing we need to report, otherwise barf */
- if (!trace) {
- abort();
+ abort();
+ }
+
+ res = write_buffer(&header, sizeof(header));
+ if (res != RES_OK) {
+ return res;
+ }
+ if (extra) {
+ res = write_buffer(extra, header.size);
+ if (res != RES_OK) {
+ return res;
}
+ }
+
+ switch (op) {
+ case OP_COMPARE:
+ case OP_SIGILL:
+ case OP_COMPAREMEM:
+ break;
+ case OP_TESTEND:
+ return RES_END;
+ case OP_SETMEMBLOCK:
+ paramreg = get_reginfo_paramreg(&ri[MASTER]);
+ memblock = (void *)(uintptr_t)paramreg;
+ break;
+ case OP_GETMEMBLOCK:
+ paramreg = get_reginfo_paramreg(&ri[MASTER]);
+ set_ucontext_paramreg(uc, paramreg + (uintptr_t)memblock);
break;
+ default:
+ abort();
}
+ return RES_OK;
}
-void master_sigill(int sig, siginfo_t *si, void *uc)
+static void master_sigill(int sig, siginfo_t *si, void *uc)
{
- int r;
+ RisuResult r;
signal_count++;
- if (trace) {
- r = send_register_info(write_trace, uc);
+ r = send_register_info(uc, si->si_addr);
+ if (r == RES_OK) {
+ advance_pc(uc);
} else {
- r = recv_and_compare_register_info(read_sock, respond_sock, uc);
+ siglongjmp(jmpbuf, r);
}
+}
+
+static RisuResult recv_register_info(struct reginfo *ri)
+{
+ RisuResult res;
+
+ res = read_buffer(&header, sizeof(header));
+ if (res != RES_OK) {
+ return res;
+ }
+
+ if (header.magic != RISU_MAGIC) {
+ /* If the magic number is wrong, we can't trust the rest. */
+ return RES_BAD_MAGIC;
+ }
+
+ switch (header.risu_op) {
+ case OP_COMPARE:
+ case OP_TESTEND:
+ case OP_SIGILL:
+ /* If we can't store the data, report invalid size. */
+ if (header.size > sizeof(*ri)) {
+ return RES_BAD_SIZE;
+ }
+ respond(RES_OK);
+ res = read_buffer(ri, header.size);
+ if (res == RES_OK && header.size != reginfo_size(ri)) {
+ /* The payload size is not self-consistent with the data. */
+ return RES_BAD_SIZE;
+ }
+ return res;
+
+ case OP_COMPAREMEM:
+ if (header.size != MEMBLOCKLEN) {
+ return RES_BAD_SIZE;
+ }
+ respond(RES_OK);
+ return read_buffer(other_memblock, MEMBLOCKLEN);
+
+ case OP_SETMEMBLOCK:
+ case OP_GETMEMBLOCK:
+ return header.size == 0 ? RES_OK : RES_BAD_SIZE;
- switch (r) {
- case 0:
- /* match OK */
- advance_pc(uc);
- return;
default:
- /* mismatch, or end of test */
- siglongjmp(jmpbuf, 1);
+ return RES_BAD_OP;
}
}
-void apprentice_sigill(int sig, siginfo_t *si, void *uc)
+static RisuResult recv_and_compare_register_info(void *uc, void *siaddr)
{
- int r;
- signal_count++;
+ uint64_t paramreg;
+ RisuResult res;
+ RisuOp op;
- if (trace) {
- r = recv_and_compare_register_info(read_trace, respond_trace, uc);
- } else {
- r = send_register_info(write_sock, uc);
+ reginfo_init(&ri[APPRENTICE], uc, siaddr);
+
+ res = recv_register_info(&ri[MASTER]);
+ if (res != RES_OK) {
+ goto done;
}
- switch (r) {
- case 0:
- /* match OK */
- advance_pc(uc);
- return;
- case 1:
- /* end of test */
- exit(0);
- default:
- /* mismatch */
- if (trace) {
- siglongjmp(jmpbuf, 1);
+ op = get_risuop(&ri[APPRENTICE]);
+
+ switch (op) {
+ case OP_COMPARE:
+ case OP_TESTEND:
+ case OP_SIGILL:
+ /*
+ * If we have nothing to compare against, report an op mismatch.
+ * Otherwise allow the compare to continue, and assume that
+ * something in the reginfo will be different.
+ */
+ if (header.risu_op != OP_COMPARE &&
+ header.risu_op != OP_TESTEND &&
+ header.risu_op != OP_SIGILL) {
+ res = RES_MISMATCH_OP;
+ } else if (!reginfo_is_eq(&ri[MASTER], &ri[APPRENTICE])) {
+ /* register mismatch */
+ res = RES_MISMATCH_REG;
+ } else if (op != header.risu_op) {
+ /* The reginfo matched. We should have matched op. */
+ res = RES_MISMATCH_OP;
+ } else if (op == OP_TESTEND) {
+ res = RES_END;
+ }
+ break;
+
+ case OP_SETMEMBLOCK:
+ if (op != header.risu_op) {
+ res = RES_MISMATCH_OP;
+ break;
+ }
+ paramreg = get_reginfo_paramreg(&ri[APPRENTICE]);
+ memblock = (void *)(uintptr_t)paramreg;
+ break;
+
+ case OP_GETMEMBLOCK:
+ if (op != header.risu_op) {
+ res = RES_MISMATCH_OP;
+ break;
}
- exit(1);
+ paramreg = get_reginfo_paramreg(&ri[APPRENTICE]);
+ set_ucontext_paramreg(uc, paramreg + (uintptr_t)memblock);
+ break;
+
+ case OP_COMPAREMEM:
+ if (op != header.risu_op) {
+ res = RES_MISMATCH_OP;
+ break;
+ }
+ if (memcmp(memblock, other_memblock, MEMBLOCKLEN) != 0) {
+ /* memory mismatch */
+ res = RES_MISMATCH_MEM;
+ }
+ break;
+
+ default:
+ abort();
+ }
+
+ done:
+ /* On error, tell master to exit. */
+ respond(res == RES_OK ? RES_OK : RES_END);
+ return res;
+}
+
+static void apprentice_sigill(int sig, siginfo_t *si, void *uc)
+{
+ RisuResult r;
+ signal_count++;
+
+ r = recv_and_compare_register_info(uc, si->si_addr);
+ if (r == RES_OK) {
+ advance_pc(uc);
+ } else {
+ siglongjmp(jmpbuf, r);
}
}
@@ -169,20 +329,20 @@ static void set_sigill_handler(void (*fn) (int, siginfo_t *, void *))
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = fn;
- sa.sa_flags = SA_SIGINFO;
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGILL, &sa, 0) != 0) {
perror("sigaction");
- exit(1);
+ exit(EXIT_FAILURE);
}
}
typedef void entrypoint_fn(void);
uintptr_t image_start_address;
-entrypoint_fn *image_start;
+static entrypoint_fn *image_start;
-void load_image(const char *imgfile)
+static void load_image(const char *imgfile)
{
/* Load image file into memory as executable */
struct stat st;
@@ -190,11 +350,11 @@ void load_image(const char *imgfile)
int fd = open(imgfile, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "failed to open image file %s\n", imgfile);
- exit(1);
+ exit(EXIT_FAILURE);
}
if (fstat(fd, &st) != 0) {
perror("fstat");
- exit(1);
+ exit(EXIT_FAILURE);
}
size_t len = st.st_size;
void *addr;
@@ -207,63 +367,125 @@ void load_image(const char *imgfile)
0);
if (!addr) {
perror("mmap");
- exit(1);
+ exit(EXIT_FAILURE);
}
close(fd);
image_start = addr;
image_start_address = (uintptr_t) addr;
}
-int master(void)
+static int master(void)
{
- if (sigsetjmp(jmpbuf, 1)) {
+ RisuResult res = sigsetjmp(jmpbuf, 1);
+
+ switch (res) {
+ case RES_OK:
+ set_sigill_handler(&master_sigill);
+ fprintf(stderr, "starting master image at 0x%"PRIxPTR"\n",
+ image_start_address);
+ fprintf(stderr, "starting image\n");
+ image_start();
+ fprintf(stderr, "image returned unexpectedly\n");
+ return EXIT_FAILURE;
+
+ case RES_END:
#ifdef HAVE_ZLIB
- if (trace && master_fd != STDOUT_FILENO) {
+ if (trace && comm_fd != STDOUT_FILENO) {
gzclose(gz_trace_file);
}
#endif
- close(master_fd);
- if (trace) {
- fprintf(stderr, "trace complete after %zd checkpoints\n",
- signal_count);
- return 0;
- } else {
- return report_match_status(0);
- }
+ close(comm_fd);
+ return EXIT_SUCCESS;
+
+ case RES_BAD_IO:
+ fprintf(stderr, "i/o error after %zd checkpoints\n", signal_count);
+ return EXIT_FAILURE;
+
+ default:
+ fprintf(stderr, "unexpected result %d\n", res);
+ return EXIT_FAILURE;
}
- set_sigill_handler(&master_sigill);
- fprintf(stderr, "starting master image at 0x%"PRIxPTR"\n",
- image_start_address);
- fprintf(stderr, "starting image\n");
- image_start();
- fprintf(stderr, "image returned unexpectedly\n");
- exit(1);
}
-int apprentice(void)
+static const char *op_name(RisuOp op)
{
- if (sigsetjmp(jmpbuf, 1)) {
-#ifdef HAVE_ZLIB
- if (trace && apprentice_fd != STDIN_FILENO) {
- gzclose(gz_trace_file);
- }
-#endif
- close(apprentice_fd);
- fprintf(stderr, "finished early after %zd checkpoints\n", signal_count);
- return report_match_status(1);
+ switch (op) {
+ case OP_SIGILL:
+ return "SIGILL";
+ case OP_COMPARE:
+ return "COMPARE";
+ case OP_TESTEND:
+ return "TESTEND";
+ case OP_SETMEMBLOCK:
+ return "SETMEMBLOCK";
+ case OP_GETMEMBLOCK:
+ return "GETMEMBLOCK";
+ case OP_COMPAREMEM:
+ return "COMPAREMEM";
+ }
+ abort();
+}
+
+static int apprentice(void)
+{
+ RisuResult res = sigsetjmp(jmpbuf, 1);
+
+ switch (res) {
+ case RES_OK:
+ set_sigill_handler(&apprentice_sigill);
+ fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
+ image_start_address);
+ fprintf(stderr, "starting image\n");
+ image_start();
+ fprintf(stderr, "image returned unexpectedly\n");
+ return EXIT_FAILURE;
+
+ case RES_END:
+ return EXIT_SUCCESS;
+
+ case RES_MISMATCH_REG:
+ fprintf(stderr, "Mismatch reg after %zd checkpoints\n", signal_count);
+ fprintf(stderr, "master reginfo:\n");
+ reginfo_dump(&ri[MASTER], stderr);
+ fprintf(stderr, "apprentice reginfo:\n");
+ reginfo_dump(&ri[APPRENTICE], stderr);
+ reginfo_dump_mismatch(&ri[MASTER], &ri[APPRENTICE], stderr);
+ return EXIT_FAILURE;
+
+ case RES_MISMATCH_MEM:
+ fprintf(stderr, "Mismatch mem after %zd checkpoints\n", signal_count);
+ return EXIT_FAILURE;
+
+ case RES_MISMATCH_OP:
+ /* Out of sync, but both opcodes are known valid. */
+ fprintf(stderr, "Mismatch header after %zd checkpoints\n"
+ "mismatch detail (master : apprentice):\n"
+ " opcode: %s vs %s\n",
+ signal_count, op_name(header.risu_op),
+ op_name(get_risuop(&ri[APPRENTICE])));
+ return EXIT_FAILURE;
+
+ case RES_BAD_IO:
+ fprintf(stderr, "I/O error\n");
+ return EXIT_FAILURE;
+ case RES_BAD_MAGIC:
+ fprintf(stderr, "Unexpected magic number: %#08x\n", header.magic);
+ return EXIT_FAILURE;
+ case RES_BAD_SIZE:
+ fprintf(stderr, "Unexpected payload size: %u\n", header.size);
+ return EXIT_FAILURE;
+ case RES_BAD_OP:
+ fprintf(stderr, "Unexpected opcode: %d\n", header.risu_op);
+ return EXIT_FAILURE;
+ default:
+ fprintf(stderr, "Unexpected result %d\n", res);
+ return EXIT_FAILURE;
}
- set_sigill_handler(&apprentice_sigill);
- fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
- image_start_address);
- fprintf(stderr, "starting image\n");
- image_start();
- fprintf(stderr, "image returned unexpectedly\n");
- exit(1);
}
-int ismaster;
+static int ismaster;
-void usage(void)
+static void usage(void)
{
fprintf(stderr,
"Usage: risu [--master] [--host <ip>] [--port <port>] <image file>"
@@ -328,6 +550,7 @@ int main(int argc, char **argv)
char *trace_fn = NULL;
struct option *longopts;
char *shortopts;
+ stack_t ss;
longopts = setup_options(&shortopts);
@@ -344,7 +567,7 @@ int main(int argc, char **argv)
break;
case 't':
trace_fn = optarg;
- trace = 1;
+ trace = true;
break;
case 'h':
hostname = optarg;
@@ -355,7 +578,7 @@ int main(int argc, char **argv)
break;
case '?':
usage();
- exit(1);
+ return EXIT_FAILURE;
default:
assert(c >= FIRST_ARCH_OPT);
process_arch_opt(c, optarg);
@@ -363,44 +586,57 @@ int main(int argc, char **argv)
}
}
+ if (trace) {
+ if (strcmp(trace_fn, "-") == 0) {
+ comm_fd = ismaster ? STDOUT_FILENO : STDIN_FILENO;
+ } else {
+ if (ismaster) {
+ comm_fd = open(trace_fn, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ } else {
+ comm_fd = open(trace_fn, O_RDONLY);
+ }
+#ifdef HAVE_ZLIB
+ gz_trace_file = gzdopen(comm_fd, ismaster ? "wb9" : "rb");
+#endif
+ }
+ } else {
+ if (ismaster) {
+ fprintf(stderr, "master port %d\n", port);
+ comm_fd = master_connect(port);
+ } else {
+ fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
+ comm_fd = apprentice_connect(hostname, port);
+ }
+ }
+
imgfile = argv[optind];
if (!imgfile) {
fprintf(stderr, "Error: must specify image file name\n\n");
usage();
- exit(1);
+ return EXIT_FAILURE;
}
load_image(imgfile);
+ /* create alternate stack */
+ ss.ss_sp = malloc(SIGSTKSZ);
+ if (ss.ss_sp == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ ss.ss_size = SIGSTKSZ;
+ ss.ss_flags = 0;
+ if (sigaltstack(&ss, NULL) == -1) {
+ perror("sigaltstac");
+ exit(EXIT_FAILURE);
+ }
+
+ /* E.g. select requested SVE vector length. */
+ arch_init();
+
if (ismaster) {
- if (trace) {
- if (strcmp(trace_fn, "-") == 0) {
- master_fd = STDOUT_FILENO;
- } else {
- master_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
-#ifdef HAVE_ZLIB
- gz_trace_file = gzdopen(master_fd, "wb9");
-#endif
- }
- } else {
- fprintf(stderr, "master port %d\n", port);
- master_fd = master_connect(port);
- }
return master();
} else {
- if (trace) {
- if (strcmp(trace_fn, "-") == 0) {
- apprentice_fd = STDIN_FILENO;
- } else {
- apprentice_fd = open(trace_fn, O_RDONLY);
-#ifdef HAVE_ZLIB
- gz_trace_file = gzdopen(apprentice_fd, "rb");
-#endif
- }
- } else {
- fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
- apprentice_fd = apprentice_connect(hostname, port);
- }
return apprentice();
}
}
diff --git a/risu.h b/risu.h
index 8d2d646..2c43384 100644
--- a/risu.h
+++ b/risu.h
@@ -17,11 +17,13 @@
#include <ucontext.h>
#include <stdio.h>
#include <getopt.h>
+#include <stdbool.h>
/* Extra option processing for architectures */
extern const struct option * const arch_long_opts;
extern const char * const arch_extra_help;
void process_arch_opt(int opt, const char *arg);
+void arch_init(void);
#define FIRST_ARCH_OPT 0x100
/* GCC computed include to pull in the correct risu_reginfo_*.h for
@@ -33,22 +35,33 @@ void process_arch_opt(int opt, const char *arg);
#include REGINFO_HEADER(ARCH)
-/* Socket related routines */
-int master_connect(int port);
-int apprentice_connect(const char *hostname, int port);
-int send_data_pkt(int sock, void *pkt, int pktlen);
-int recv_data_pkt(int sock, void *pkt, int pktlen);
-void send_response_byte(int sock, int resp);
-
extern uintptr_t image_start_address;
-extern void *memblock;
/* Ops code under test can request from risu: */
-#define OP_COMPARE 0
-#define OP_TESTEND 1
-#define OP_SETMEMBLOCK 2
-#define OP_GETMEMBLOCK 3
-#define OP_COMPAREMEM 4
+typedef enum {
+ /* Any other sigill besides the destignated undefined insn. */
+ OP_SIGILL = -1,
+
+ /* These are generated by the designated undefined insn. */
+ OP_COMPARE = 0,
+ OP_TESTEND = 1,
+ OP_SETMEMBLOCK = 2,
+ OP_GETMEMBLOCK = 3,
+ OP_COMPAREMEM = 4,
+} RisuOp;
+
+/* Result of operation */
+typedef enum {
+ RES_OK = 0,
+ RES_END,
+ RES_MISMATCH_REG,
+ RES_MISMATCH_MEM,
+ RES_MISMATCH_OP,
+ RES_BAD_IO,
+ RES_BAD_MAGIC,
+ RES_BAD_SIZE,
+ RES_BAD_OP,
+} RisuResult;
/* The memory block should be this long */
#define MEMBLOCKLEN 8192
@@ -61,47 +74,26 @@ extern void *memblock;
struct reginfo;
typedef struct {
- uintptr_t pc;
+ uint32_t magic;
+ uint32_t size;
uint32_t risu_op;
+ uintptr_t pc;
} trace_header_t;
-/* Functions operating on reginfo */
-
-/* Function prototypes for read/write helper functions.
- *
- * We pass the helper function to send_register_info and
- * recv_and_compare_register_info which can either be backed by the
- * traditional network socket or a trace file.
- */
-typedef int (*write_fn) (void *ptr, size_t bytes);
-typedef int (*read_fn) (void *ptr, size_t bytes);
-typedef void (*respond_fn) (int response);
+#define RISU_MAGIC (('R' << 24) | ('I' << 16) | ('S' << 8) | 'U')
-/* Send the register information from the struct ucontext down the socket.
- * Return the response code from the master.
- * NB: called from a signal handler.
- */
-int send_register_info(write_fn write_fn, void *uc);
+/* Socket related routines */
+int master_connect(int port);
+int apprentice_connect(const char *hostname, int port);
+RisuResult send_data_pkt(int sock, void *pkt, int pktlen);
+RisuResult recv_data_pkt(int sock, void *pkt, int pktlen);
+void send_response_byte(int sock, int resp);
-/* Read register info from the socket and compare it with that from the
- * ucontext. Return 0 for match, 1 for end-of-test, 2 for mismatch.
- * NB: called from a signal handler.
- */
-int recv_and_compare_register_info(read_fn read_fn,
- respond_fn respond, void *uc);
-
-/* Print a useful report on the status of the last comparison
- * done in recv_and_compare_register_info(). This is called on
- * exit, so need not restrict itself to signal-safe functions.
- * Should return 0 if it was a good match (ie end of test)
- * and 1 for a mismatch.
- */
-int report_match_status(int trace);
+/* Functions operating on reginfo */
/* Interface provided by CPU-specific code: */
-/* Move the PC past this faulting insn by adjusting ucontext
- */
+/* Move the PC past this faulting insn by adjusting ucontext. */
void advance_pc(void *uc);
/* Set the parameter register in a ucontext_t to the specified value.
@@ -113,16 +105,17 @@ void set_ucontext_paramreg(void *vuc, uint64_t value);
/* Return the value of the parameter register from a reginfo. */
uint64_t get_reginfo_paramreg(struct reginfo *ri);
-/* Return the risu operation number we have been asked to do,
- * or -1 if this was a SIGILL for a non-risuop insn.
+/*
+ * Return the risu operation number we have been asked to do,
+ * or OP_SIGILL if this was a SIGILL for a non-risuop insn.
*/
-int get_risuop(struct reginfo *ri);
+RisuOp get_risuop(struct reginfo *ri);
/* Return the PC from a reginfo */
uintptr_t get_pc(struct reginfo *ri);
/* initialize structure from a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc);
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr);
/* return 1 if structs are equal, 0 otherwise. */
int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
@@ -134,6 +127,6 @@ int reginfo_dump(struct reginfo *ri, FILE * f);
int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f);
/* return size of reginfo */
-const int reginfo_size(void);
+int reginfo_size(struct reginfo *ri);
#endif /* RISU_H */
diff --git a/risu_aarch64.c b/risu_aarch64.c
index 492d141..f8a8412 100644
--- a/risu_aarch64.c
+++ b/risu_aarch64.c
@@ -29,16 +29,16 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
return ri->regs[0];
}
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
{
/* Return the risuop we have been asked to do
- * (or -1 if this was a SIGILL for a non-risuop insn)
+ * (or OP_SIGILL if this was a SIGILL for a non-risuop insn)
*/
uint32_t insn = ri->faulting_insn;
uint32_t op = insn & 0xf;
uint32_t key = insn & ~0xf;
uint32_t risukey = 0x00005af0;
- return (key != risukey) ? -1 : op;
+ return (key != risukey) ? OP_SIGILL : op;
}
uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_arm.c b/risu_arm.c
index 5fcb2a5..a20bf73 100644
--- a/risu_arm.c
+++ b/risu_arm.c
@@ -56,17 +56,17 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
return ri->gpreg[0];
}
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
{
/* Return the risuop we have been asked to do
- * (or -1 if this was a SIGILL for a non-risuop insn)
+ * (or OP_SIGILL if this was a SIGILL for a non-risuop insn)
*/
uint32_t insn = ri->faulting_insn;
int isz = ri->faulting_insn_size;
uint32_t op = insn & 0xf;
uint32_t key = insn & ~0xf;
uint32_t risukey = (isz == 2) ? 0xdee0 : 0xe7fe5af0;
- return (key != risukey) ? -1 : op;
+ return (key != risukey) ? OP_SIGILL : op;
}
uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_i386.c b/risu_i386.c
index 9962b8f..127e816 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -38,12 +38,12 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
return ri->gregs[REG_E(AX)];
}
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
{
if ((ri->faulting_insn & 0xf8ffff) == 0xc0b90f) { /* UD1 %xxx,%eax */
return (ri->faulting_insn >> 16) & 7;
}
- return -1;
+ return OP_SIGILL;
}
uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_loongarch64.c b/risu_loongarch64.c
new file mode 100644
index 0000000..b6c59cf
--- /dev/null
+++ b/risu_loongarch64.c
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * Copyright (c) 2022 Loongson Technology Corporation Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * based on Peter Maydell's risu_arm.c
+ *****************************************************************************/
+
+#include <asm/types.h>
+#include <signal.h>
+#include <asm/ucontext.h>
+
+#include "risu.h"
+
+void advance_pc(void *vuc)
+{
+ struct ucontext *uc = vuc;
+ uc->uc_mcontext.sc_pc += 4;
+}
+
+void set_ucontext_paramreg(void *vuc, uint64_t value)
+{
+ struct ucontext *uc = vuc;
+ uc->uc_mcontext.sc_regs[4] = value;
+}
+
+uint64_t get_reginfo_paramreg(struct reginfo *ri)
+{
+ return ri->regs[4];
+}
+
+RisuOp get_risuop(struct reginfo *ri)
+{
+ /* Return the risuop we have been asked to do
+ * (or OP_SIGILL if this was a SIGILL for a non-risuop insn)
+ */
+ uint32_t insn = ri->faulting_insn;
+ uint32_t op = insn & 0xf;
+ uint32_t key = insn & ~0xf;
+ uint32_t risukey = 0x000001f0;
+ return (key != risukey) ? OP_SIGILL : op;
+}
+
+uintptr_t get_pc(struct reginfo *ri)
+{
+ return ri->pc;
+}
diff --git a/risu_m68k.c b/risu_m68k.c
index 1056eef..acdd57a 100644
--- a/risu_m68k.c
+++ b/risu_m68k.c
@@ -25,13 +25,13 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
return ri->gregs[R_A0];
}
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
{
uint32_t insn = ri->faulting_insn;
uint32_t op = insn & 0xf;
uint32_t key = insn & ~0xf;
uint32_t risukey = 0x4afc7000;
- return (key != risukey) ? -1 : op;
+ return (key != risukey) ? OP_SIGILL : op;
}
uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_ppc64.c b/risu_ppc64.c
index a3028f7..9df8d58 100644
--- a/risu_ppc64.c
+++ b/risu_ppc64.c
@@ -32,13 +32,13 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
return ri->gregs[0];
}
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
{
uint32_t insn = ri->faulting_insn;
uint32_t op = insn & 0xf;
uint32_t key = insn & ~0xf;
uint32_t risukey = 0x00005af0;
- return (key != risukey) ? -1 : op;
+ return (key != risukey) ? OP_SIGILL : op;
}
uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 00d1c8b..1244454 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -19,16 +19,12 @@
#include <stdbool.h>
#include <inttypes.h>
#include <assert.h>
+#include <errno.h>
#include <sys/prctl.h>
#include "risu.h"
#include "risu_reginfo_aarch64.h"
-#ifndef SVE_MAGIC
-const struct option * const arch_long_opts;
-const char * const arch_extra_help;
-#else
-
/* Should we test SVE register state */
static int test_sve;
static const struct option extra_opts[] = {
@@ -39,56 +35,59 @@ static const struct option extra_opts[] = {
const struct option * const arch_long_opts = &extra_opts[0];
const char * const arch_extra_help
= " --test-sve=<vq> Compare SVE registers with VQ\n";
-#endif
void process_arch_opt(int opt, const char *arg)
{
-#ifdef SVE_MAGIC
- long want, got;
-
assert(opt == FIRST_ARCH_OPT);
test_sve = strtol(arg, 0, 10);
if (test_sve <= 0 || test_sve > SVE_VQ_MAX) {
fprintf(stderr, "Invalid value for VQ (1-%d)\n", SVE_VQ_MAX);
- exit(1);
+ exit(EXIT_FAILURE);
}
- want = sve_vl_from_vq(test_sve);
- got = prctl(PR_SVE_SET_VL, want);
- if (want != got) {
- if (got < 0) {
- perror("prctl PR_SVE_SET_VL");
- } else {
- fprintf(stderr, "Unsupported value for VQ (%d != %d)\n",
- test_sve, (int)sve_vq_from_vl(got));
+}
+
+void arch_init(void)
+{
+ long want, got;
+
+ if (test_sve) {
+ want = sve_vl_from_vq(test_sve);
+ got = prctl(PR_SVE_SET_VL, want);
+ if (want != got) {
+ if (got >= 0) {
+ fprintf(stderr, "Unsupported VQ for SVE (%d != %d)\n",
+ test_sve, (int)sve_vq_from_vl(got));
+ } else if (errno == EINVAL) {
+ fprintf(stderr, "System does not support SVE\n");
+ } else {
+ perror("prctl PR_SVE_SET_VL");
+ }
+ exit(EXIT_FAILURE);
}
- exit(1);
}
-#else
- abort();
-#endif
}
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
{
- int size = offsetof(struct reginfo, simd.end);
-#ifdef SVE_MAGIC
- if (test_sve) {
- size = offsetof(struct reginfo, sve.end);
+ int size = offsetof(struct reginfo, extra);
+
+ if (ri->sve_vl) {
+ int vq = sve_vq_from_vl(ri->sve_vl);
+ size += RISU_SVE_REGS_SIZE(vq);
+ } else {
+ size += RISU_SIMD_REGS_SIZE;
}
-#endif
return size;
}
/* reginfo_init: initialize with a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
{
int i;
struct _aarch64_ctx *ctx, *extra = NULL;
struct fpsimd_context *fp = NULL;
-#ifdef SVE_MAGIC
struct sve_context *sve = NULL;
-#endif
/* necessary to be able to compare with memcmp later */
memset(ri, 0, sizeof(*ri));
@@ -110,14 +109,12 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
case FPSIMD_MAGIC:
fp = (void *)ctx;
break;
-#ifdef SVE_MAGIC
case SVE_MAGIC:
sve = (void *)ctx;
break;
case EXTRA_MAGIC:
extra = (void *)((struct extra_context *)(ctx))->datap;
break;
-#endif
case 0:
/* End of list. */
ctx = extra;
@@ -137,7 +134,6 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
ri->fpsr = fp->fpsr;
ri->fpcr = fp->fpcr;
-#ifdef SVE_MAGIC
if (test_sve) {
int vq = test_sve;
@@ -145,6 +141,7 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
fprintf(stderr, "risu_reginfo_aarch64: failed to get SVE state\n");
return;
}
+
if (sve->vl != sve_vl_from_vq(vq)) {
fprintf(stderr, "risu_reginfo_aarch64: "
"unexpected SVE state: %d != %d\n",
@@ -152,52 +149,30 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
return;
}
- ri->sve.vl = sve->vl;
-
- if (sve->head.size < SVE_SIG_CONTEXT_SIZE(vq)) {
- if (sve->head.size == sizeof(*sve)) {
- /* SVE state is empty -- not an error. */
- } else {
- fprintf(stderr, "risu_reginfo_aarch64: "
- "failed to get complete SVE state\n");
- }
+ if (sve->head.size <= SVE_SIG_CONTEXT_SIZE(0)) {
+ /* Only AdvSIMD state is present. */
+ } else if (sve->head.size < SVE_SIG_CONTEXT_SIZE(vq)) {
+ fprintf(stderr, "risu_reginfo_aarch64: "
+ "failed to get complete SVE state\n");
+ return;
+ } else {
+ ri->sve_vl = sve->vl;
+ memcpy(reginfo_zreg(ri, vq, 0),
+ (char *)sve + SVE_SIG_REGS_OFFSET,
+ SVE_SIG_REGS_SIZE(vq));
return;
}
-
- /* Copy ZREG's one at a time */
- for (i = 0; i < SVE_NUM_ZREGS; i++) {
- memcpy(&ri->sve.zregs[i],
- (void *)sve + SVE_SIG_ZREG_OFFSET(vq, i),
- SVE_SIG_ZREG_SIZE(vq));
- }
-
- /* Copy PREG's one at a time */
- for (i = 0; i < SVE_NUM_PREGS; i++) {
- memcpy(&ri->sve.pregs[i],
- (void *)sve + SVE_SIG_PREG_OFFSET(vq, i),
- SVE_SIG_PREG_SIZE(vq));
- }
-
- /* Finally the FFR */
- memcpy(&ri->sve.ffr, (void *)sve + SVE_SIG_FFR_OFFSET(vq),
- SVE_SIG_FFR_SIZE(vq));
-
- return;
}
-#endif /* SVE_MAGIC */
- for (i = 0; i < 32; i++) {
- ri->simd.vregs[i] = fp->vregs[i];
- }
+ memcpy(reginfo_vreg(ri, 0), fp->vregs, RISU_SIMD_REGS_SIZE);
}
/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
{
- return memcmp(r1, r2, reginfo_size()) == 0;
+ return memcmp(r1, r2, reginfo_size(r1)) == 0;
}
-#ifdef SVE_MAGIC
static int sve_zreg_is_eq(int vq, const void *z1, const void *z2)
{
return memcmp(z1, z2, vq * 16) == 0;
@@ -225,23 +200,24 @@ static void sve_dump_preg_diff(FILE *f, int vq, const uint16_t *p1,
fprintf(f, "\n");
}
-static void sve_dump_zreg_diff(FILE *f, int vq, const __uint128_t *z1,
- const __uint128_t *z2)
+static void sve_dump_zreg_diff(FILE *f, int vq, const uint64_t *za,
+ const uint64_t *zb)
{
const char *pad = "";
int q;
for (q = 0; q < vq; ++q) {
- if (z1[q] != z2[q]) {
+ uint64_t za0 = za[2 * q], za1 = za[2 * q + 1];
+ uint64_t zb0 = zb[2 * q], zb1 = zb[2 * q + 1];
+
+ if (za0 != zb0 || za1 != zb1) {
fprintf(f, "%sq%-2d: %016" PRIx64 "%016" PRIx64
- " vs %016" PRIx64 "%016" PRIx64"\n", pad, q,
- (uint64_t)(z1[q] >> 64), (uint64_t)z1[q],
- (uint64_t)(z2[q] >> 64), (uint64_t)z2[q]);
+ " vs %016" PRIx64 "%016" PRIx64"\n",
+ pad, q, za1, za0, zb1, zb0);
pad = " ";
}
}
}
-#endif
/* reginfo_dump: print state to a stream, returns nonzero on success */
int reginfo_dump(struct reginfo *ri, FILE * f)
@@ -259,40 +235,41 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
fprintf(f, " fpsr : %08x\n", ri->fpsr);
fprintf(f, " fpcr : %08x\n", ri->fpcr);
-#ifdef SVE_MAGIC
- if (test_sve) {
- int q, vq = test_sve;
+ if (ri->sve_vl) {
+ int vq = sve_vq_from_vl(ri->sve_vl);
+ int q;
- fprintf(f, " vl : %d\n", ri->sve.vl);
+ fprintf(f, " vl : %d\n", ri->sve_vl);
- for (i = 0; i < 32; i++) {
- fprintf(f, " Z%-2d q%-2d: %016" PRIx64 "%016" PRIx64 "\n", i, 0,
- (uint64_t)(ri->sve.zregs[i][0] >> 64),
- (uint64_t)ri->sve.zregs[i][0]);
+ for (i = 0; i < SVE_NUM_ZREGS; i++) {
+ uint64_t *z = reginfo_zreg(ri, vq, i);
+
+ fprintf(f, " Z%-2d q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
+ i, 0, z[1], z[0]);
for (q = 1; q < vq; ++q) {
- fprintf(f, " q%-2d: %016" PRIx64 "%016" PRIx64 "\n", q,
- (uint64_t)(ri->sve.zregs[i][q] >> 64),
- (uint64_t)ri->sve.zregs[i][q]);
+ fprintf(f, " q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
+ q, z[q * 2 + 1], z[q * 2]);
}
}
- for (i = 0; i < 16; i++) {
- fprintf(f, " P%-2d : ", i);
- sve_dump_preg(f, vq, &ri->sve.pregs[i][0]);
+ for (i = 0; i < SVE_NUM_PREGS + 1; i++) {
+ uint16_t *p = reginfo_preg(ri, vq, i);
+
+ if (i == SVE_NUM_PREGS) {
+ fprintf(f, " FFR : ");
+ } else {
+ fprintf(f, " P%-2d : ", i);
+ }
+ sve_dump_preg(f, vq, p);
fprintf(f, "\n");
}
- fprintf(f, " FFR : ");
- sve_dump_preg(f, vq, &ri->sve.ffr[0]);
- fprintf(f, "\n");
-
return !ferror(f);
}
-#endif
for (i = 0; i < 32; i++) {
- fprintf(f, " V%-2d : %016" PRIx64 "%016" PRIx64 "\n", i,
- (uint64_t) (ri->simd.vregs[i] >> 64),
- (uint64_t) (ri->simd.vregs[i]));
+ uint64_t *v = reginfo_vreg(ri, i);
+ fprintf(f, " V%-2d : %016" PRIx64 "%016" PRIx64 "\n",
+ i, v[1], v[0]);
}
return !ferror(f);
@@ -336,46 +313,47 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
fprintf(f, " fpcr : %08x vs %08x\n", m->fpcr, a->fpcr);
}
-#ifdef SVE_MAGIC
- if (test_sve) {
- int vq = sve_vq_from_vl(m->sve.vl);
+ if (m->sve_vl != a->sve_vl) {
+ fprintf(f, " vl : %d vs %d\n", m->sve_vl, a->sve_vl);
+ }
- if (m->sve.vl != a->sve.vl) {
- fprintf(f, " vl : %d vs %d\n", m->sve.vl, a->sve.vl);
- }
+ if (m->sve_vl) {
+ int vq = sve_vq_from_vl(m->sve_vl);
for (i = 0; i < SVE_NUM_ZREGS; i++) {
- if (!sve_zreg_is_eq(vq, &m->sve.zregs[i], &a->sve.zregs[i])) {
+ uint64_t *zm = reginfo_zreg(m, vq, i);
+ uint64_t *za = reginfo_zreg(a, vq, i);
+
+ if (!sve_zreg_is_eq(vq, zm, za)) {
fprintf(f, " Z%-2d ", i);
- sve_dump_zreg_diff(f, vq, &m->sve.zregs[i][0],
- &a->sve.zregs[i][0]);
+ sve_dump_zreg_diff(f, vq, zm, za);
}
}
- for (i = 0; i < SVE_NUM_PREGS; i++) {
- if (!sve_preg_is_eq(vq, &m->sve.pregs[i], &a->sve.pregs[i])) {
- fprintf(f, " P%-2d : ", i);
- sve_dump_preg_diff(f, vq, &m->sve.pregs[i][0],
- &a->sve.pregs[i][0]);
+ for (i = 0; i < SVE_NUM_PREGS + 1; i++) {
+ uint16_t *pm = reginfo_preg(m, vq, i);
+ uint16_t *pa = reginfo_preg(a, vq, i);
+
+ if (!sve_preg_is_eq(vq, pm, pa)) {
+ if (i == SVE_NUM_PREGS) {
+ fprintf(f, " FFR : ");
+ } else {
+ fprintf(f, " P%-2d : ", i);
+ }
+ sve_dump_preg_diff(f, vq, pm, pa);
}
}
- if (!sve_preg_is_eq(vq, &m->sve.ffr, &a->sve.ffr)) {
- fprintf(f, " FFR : ");
- sve_dump_preg_diff(f, vq, &m->sve.pregs[i][0], &a->sve.pregs[i][0]);
- }
-
return !ferror(f);
}
-#endif
for (i = 0; i < 32; i++) {
- if (m->simd.vregs[i] != a->simd.vregs[i]) {
+ uint64_t *mv = reginfo_vreg(m, i);
+ uint64_t *av = reginfo_vreg(a, i);
+
+ if (mv[0] != av[0] || mv[1] != av[1]) {
fprintf(f, " V%-2d : "
"%016" PRIx64 "%016" PRIx64 " vs "
- "%016" PRIx64 "%016" PRIx64 "\n", i,
- (uint64_t) (m->simd.vregs[i] >> 64),
- (uint64_t) m->simd.vregs[i],
- (uint64_t) (a->simd.vregs[i] >> 64),
- (uint64_t) a->simd.vregs[i]);
+ "%016" PRIx64 "%016" PRIx64 "\n",
+ i, mv[1], mv[0], av[1], av[0]);
}
}
diff --git a/risu_reginfo_aarch64.h b/risu_reginfo_aarch64.h
index c33b86f..536c12b 100644
--- a/risu_reginfo_aarch64.h
+++ b/risu_reginfo_aarch64.h
@@ -13,29 +13,17 @@
#ifndef RISU_REGINFO_AARCH64_H
#define RISU_REGINFO_AARCH64_H
-#include <signal.h> /* for SVE_MAGIC */
-
-struct simd_reginfo {
- __uint128_t vregs[32];
- char end[0];
-};
-
-#ifdef SVE_MAGIC
-struct sve_reginfo {
- /* SVE */
- uint16_t vl; /* current VL */
- __uint128_t zregs[SVE_NUM_ZREGS][SVE_VQ_MAX];
- uint16_t pregs[SVE_NUM_PREGS][SVE_VQ_MAX];
- uint16_t ffr[SVE_VQ_MAX];
- char end[0];
-};
-#endif
+#include <signal.h>
/* The kernel headers set this based on future arch extensions.
The current arch maximum is 16. Save space below. */
#undef SVE_VQ_MAX
#define SVE_VQ_MAX 16
+#define ROUND_UP(SIZE, POW2) (((SIZE) + (POW2) - 1) & -(POW2))
+#define RISU_SVE_REGS_SIZE(VQ) ROUND_UP(SVE_SIG_REGS_SIZE(VQ), 16)
+#define RISU_SIMD_REGS_SIZE (32 * 16)
+
struct reginfo {
uint64_t fault_address;
uint64_t regs[31];
@@ -47,13 +35,28 @@ struct reginfo {
/* FP/SIMD */
uint32_t fpsr;
uint32_t fpcr;
+ uint16_t sve_vl;
+ uint16_t reserved;
- union {
- struct simd_reginfo simd;
-#ifdef SVE_MAGIC
- struct sve_reginfo sve;
-#endif
- };
+ char extra[RISU_SVE_REGS_SIZE(SVE_VQ_MAX)]
+ __attribute__((aligned(16)));
};
+static inline uint64_t *reginfo_vreg(struct reginfo *ri, int i)
+{
+ return (uint64_t *)&ri->extra[i * 16];
+}
+
+static inline uint64_t *reginfo_zreg(struct reginfo *ri, int vq, int i)
+{
+ return (uint64_t *)&ri->extra[SVE_SIG_ZREG_OFFSET(vq, i) -
+ SVE_SIG_REGS_OFFSET];
+}
+
+static inline uint16_t *reginfo_preg(struct reginfo *ri, int vq, int i)
+{
+ return (uint16_t *)&ri->extra[SVE_SIG_PREG_OFFSET(vq, i) -
+ SVE_SIG_REGS_OFFSET];
+}
+
#endif /* RISU_REGINFO_AARCH64_H */
diff --git a/risu_reginfo_arm.c b/risu_reginfo_arm.c
index 3662f12..85a39ac 100644
--- a/risu_reginfo_arm.c
+++ b/risu_reginfo_arm.c
@@ -36,9 +36,13 @@ void process_arch_opt(int opt, const char *arg)
abort();
}
-const int reginfo_size(void)
+void arch_init(void)
{
- return sizeof(struct reginfo);
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
}
static void reginfo_init_vfp(struct reginfo *ri, ucontext_t *uc)
@@ -114,7 +118,7 @@ static void reginfo_init_vfp(struct reginfo *ri, ucontext_t *uc)
}
}
-void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
{
memset(ri, 0, sizeof(*ri)); /* necessary for memcmp later */
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index 194e0ad..834b2ed 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -69,14 +69,18 @@ void process_arch_opt(int opt, const char *arg)
fprintf(stderr,
"Unable to parse '%s' in '%s' into an xfeatures integer mask\n",
endptr, arg);
- exit(1);
+ exit(EXIT_FAILURE);
}
}
}
-const int reginfo_size(void)
+void arch_init(void)
{
- return sizeof(struct reginfo);
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
}
static void *xsave_feature_buf(struct _xstate *xs, int feature)
@@ -98,7 +102,7 @@ static void *xsave_feature_buf(struct _xstate *xs, int feature)
}
/* reginfo_init: initialize with a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
{
int i, nvecregs;
struct _fpstate *fp;
diff --git a/risu_reginfo_loongarch64.c b/risu_reginfo_loongarch64.c
new file mode 100644
index 0000000..09a1eb6
--- /dev/null
+++ b/risu_reginfo_loongarch64.c
@@ -0,0 +1,268 @@
+/******************************************************************************
+ * Copyright (c) 2022 Loongson Technology Corporation Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * based on Peter Maydell's risu_reginfo_arm.c
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <asm/types.h>
+#include <signal.h>
+#include <asm/ucontext.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <sys/prctl.h>
+
+#include "risu.h"
+#include "risu_reginfo_loongarch64.h"
+
+const struct option * const arch_long_opts;
+const char * const arch_extra_help;
+
+struct _ctx_layout {
+ struct sctx_info *addr;
+ unsigned int size;
+};
+
+struct extctx_layout {
+ unsigned long size;
+ unsigned int flags;
+ struct _ctx_layout fpu;
+ struct _ctx_layout lsx;
+ struct _ctx_layout lasx;
+ struct _ctx_layout end;
+};
+
+void process_arch_opt(int opt, const char *arg)
+{
+ abort();
+}
+
+void arch_init(void)
+{
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
+}
+
+static int parse_extcontext(struct sigcontext *sc, struct extctx_layout *extctx)
+{
+ uint32_t magic, size;
+ struct sctx_info *info = (struct sctx_info *)&sc->sc_extcontext;
+
+ while(1) {
+ magic = (uint32_t)info->magic;
+ size = (uint32_t)info->size;
+ switch (magic) {
+ case 0: /* END*/
+ return 0;
+ case FPU_CTX_MAGIC:
+ if (size < (sizeof(struct sctx_info) +
+ sizeof(struct fpu_context))) {
+ return -1;
+ }
+ extctx->fpu.addr = info;
+ break;
+ case LSX_CTX_MAGIC:
+ if (size < (sizeof(struct sctx_info) +
+ sizeof(struct lsx_context))) {
+ return -1;
+ }
+ extctx->lsx.addr = info;
+ break;
+ case LASX_CTX_MAGIC:
+ if (size < (sizeof(struct sctx_info) +
+ sizeof(struct lasx_context))) {
+ return -1;
+ }
+ extctx->lasx.addr = info;
+ break;
+ default:
+ return -1;
+ }
+ info = (struct sctx_info *)((char *)info +size);
+ }
+ return 0;
+}
+
+/* reginfo_init: initialize with a ucontext */
+void reginfo_init(struct reginfo *ri, ucontext_t *context, void *siaddr)
+{
+ int i;
+ struct ucontext *uc = (struct ucontext *)context;
+ struct extctx_layout extctx;
+
+ memset(&extctx, 0, sizeof(struct extctx_layout));
+ memset(ri, 0, sizeof(*ri));
+
+ for (i = 1; i < 32; i++) {
+ ri->regs[i] = uc->uc_mcontext.sc_regs[i]; //sp:r3, tp:r2
+ }
+
+ ri->regs[2] = 0xdeadbeefdeadbeef;
+ ri->pc = uc->uc_mcontext.sc_pc - (unsigned long)image_start_address;
+ ri->flags = uc->uc_mcontext.sc_flags;
+ ri->faulting_insn = *(uint32_t *)uc->uc_mcontext.sc_pc;
+
+ parse_extcontext(&uc->uc_mcontext, &extctx);
+ if (extctx.lasx.addr) {
+ struct sctx_info *info = extctx.lasx.addr;
+ struct lasx_context *lasx_ctx = (struct lasx_context *)((char *)info +
+ sizeof(struct sctx_info));
+ for (i = 0; i < 32; i++) {
+ ri->vregs[4 * i] = lasx_ctx->regs[4 * i];
+ ri->vregs[4 * i + 1] = lasx_ctx->regs[4 * i + 1];
+ ri->vregs[4 * i + 2] = lasx_ctx->regs[4 * i + 2];
+ ri->vregs[4 * i + 3] = lasx_ctx->regs[4 * i + 3];
+ }
+ ri->fcsr = lasx_ctx->fcsr;
+ ri->fcc = lasx_ctx->fcc;
+ ri->vl = 256;
+ } else if (extctx.lsx.addr) {
+ struct sctx_info *info = extctx.lsx.addr;
+ struct lsx_context *lsx_ctx = (struct lsx_context *)((char *)info +
+ sizeof(struct sctx_info));
+ for (i = 0; i < 32; i++) {
+ ri->vregs[4 * i] = lsx_ctx->regs[4 * i + 1];
+ ri->vregs[4 * i + 1] = lsx_ctx->regs[4 * i + 1];
+ }
+ ri->fcsr = lsx_ctx->fcsr;
+ ri->fcc = lsx_ctx->fcc;
+ ri->vl = 128;
+ } else if (extctx.fpu.addr) {
+ struct sctx_info *info = extctx.fpu.addr;
+ struct fpu_context *fpu_ctx = (struct fpu_context *)((char *)info +
+ sizeof(struct sctx_info));
+ for(i = 0; i < 32; i++) {
+ ri->vregs[4 * i] = fpu_ctx->regs[4 * i];
+ }
+ ri->fcsr = fpu_ctx->fcsr;
+ ri->fcc = fpu_ctx->fcc;
+ ri->vl = 64;
+ }
+}
+
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+{
+ return !memcmp(r1, r2, sizeof(*r1));
+}
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+int reginfo_dump(struct reginfo *ri, FILE * f)
+{
+ int i;
+ fprintf(f, " faulting insn %08x\n", ri->faulting_insn);
+
+ for (i = 0; i < 32; i++) {
+ fprintf(f, " r%-2d : %016" PRIx64 "\n", i, ri->regs[i]);
+ }
+
+ fprintf(f, " pc : %016" PRIx64 "\n", ri->pc);
+ fprintf(f, " flags : %08x\n", ri->flags);
+ fprintf(f, " fcc : %016" PRIx64 "\n", ri->fcc);
+ fprintf(f, " fcsr : %08x\n", ri->fcsr);
+ fprintf(f, " vl : %016" PRIx64 "\n", ri->vl);
+
+ if (ri->vl == 256) {
+ for (i = 0; i < 32; i++) {
+ fprintf(f, " vreg%-2d : {%016lx, %016lx, %016lx, %016lx}\n", i,
+ ri->vregs[4 * i + 3], ri->vregs[4 * i + 2],
+ ri->vregs[4 * i + 1], ri->vregs[4 * i]);
+ }
+ } else if (ri->vl == 128) {
+ for (i = 0; i < 32; i++) {
+ fprintf(f, " vreg%-2d : {%016lx, %016lx}\n", i,
+ ri->vregs[4 * i + 1], ri->vregs[4 * i]);
+ }
+ } else if (ri->vl == 64) {
+ for (i = 0; i < 32; i++) {
+ fprintf(f, " vreg%-2d : %016lx\n", i, ri->vregs[4 * i]);
+ }
+ }
+
+ return !ferror(f);
+}
+
+/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */
+int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
+{
+ int i;
+ fprintf(f, "mismatch detail (master : apprentice):\n");
+
+ if (m->vl != a->vl) {
+ fprintf(f, " vl mismatch %08lx vs %08lx\n", m->vl, a->vl);
+ }
+
+ if (m->faulting_insn != a->faulting_insn) {
+ fprintf(f, " faulting insn mismatch %08x vs %08x\n",
+ m->faulting_insn, a->faulting_insn);
+ }
+ /* r2:tp, r3:sp */
+ for (i = 0; i < 32; i++) {
+ if (m->regs[i] != a->regs[i]) {
+ fprintf(f, " r%-2d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i, m->regs[i], a->regs[i]);
+ }
+ }
+
+ if (m->pc != a->pc) {
+ fprintf(f, " pc : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->pc, a->pc);
+ }
+ if (m->flags != a->flags) {
+ fprintf(f, " flags : %08x vs %08x\n", m->flags, a->flags);
+ }
+ if (m->fcc != a->fcc) {
+ fprintf(f, " fcc : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->fcc, a->fcc);
+ }
+ if (m->fcsr != a->fcsr) {
+ fprintf(f, " fcsr : %08x vs %08x\n", m->fcsr, a->fcsr);
+ }
+
+ if (m->vl == 256) {
+ for (i = 0; i < 32; i++) {
+ if (m->vregs[4 * i + 3] != a->vregs[4 * i + 3] ||
+ m->vregs[4 * i + 2] != a->vregs[4 * i + 2] ||
+ m->vregs[4 * i + 1] != a->vregs[4 * i + 1] ||
+ m->vregs[4 * i] != a->vregs[4 * i]) {
+ fprintf(f, " vreg%-2d : {%016lx, %016lx, %016lx, %016lx} vs"
+ " {%016lx, %016lx, %016lx, %016lx}\n", i,
+ m->vregs[4 * i + 3], m->vregs[4 * i + 2],
+ m->vregs[4 * i + 1], m->vregs[4 * i],
+ a->vregs[4 * i + 3], a->vregs[4 * i + 2],
+ a->vregs[4 * i + 1], a->vregs[4 * i]);
+ }
+ }
+ } else if (m->vl == 128) {
+ for (i = 0; i < 32; i++) {
+ if (m->vregs[4 * i + 1] != a->vregs[4 * i + 1] ||
+ m->vregs[4 * i] != a->vregs[4 * i]) {
+ fprintf(f, " vreg%-2d : {%016lx, %016lx} vs {%016lx, %016lx}\n",
+ i, m->vregs[4 * i + 1], m->vregs[4 * i],
+ a->vregs[4 * i + 1], m->vregs[4 * i]);
+ }
+ }
+ } else if (m->vl == 64) {
+ for (i = 0; i < 32; i++) {
+ if (m->vregs[4 * i] != a->vregs[4 * i]) {
+ fprintf(f, " vreg%-2d : %016lx vs %016lx\n", i,
+ m->vregs[4 * i], a->vregs[4 * i]);
+ }
+ }
+ }
+
+ return !ferror(f);
+}
diff --git a/risu_reginfo_loongarch64.h b/risu_reginfo_loongarch64.h
new file mode 100644
index 0000000..892b477
--- /dev/null
+++ b/risu_reginfo_loongarch64.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2022 Loongson Technology Corporation Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * based on Peter Maydell's risu_reginfo_arm.h
+ *****************************************************************************/
+
+#ifndef RISU_REGINFO_LOONGARCH64_H
+#define RISU_REGINFO_LOONGARCH64_H
+
+struct reginfo {
+ uint64_t regs[32];
+ uint64_t pc;
+ uint64_t fcc;
+ uint32_t flags;
+ uint32_t fcsr;
+ uint32_t faulting_insn;
+ uint64_t vregs[4 * 32];
+ uint64_t vl;
+};
+
+#endif /* RISU_REGINFO_LOONGARCH64_H */
diff --git a/risu_reginfo_m68k.c b/risu_reginfo_m68k.c
index 32b28c8..e29da84 100644
--- a/risu_reginfo_m68k.c
+++ b/risu_reginfo_m68k.c
@@ -23,13 +23,17 @@ void process_arch_opt(int opt, const char *arg)
abort();
}
-const int reginfo_size(void)
+void arch_init(void)
{
- return sizeof(struct reginfo);
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
}
/* reginfo_init: initialize with a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
{
int i;
memset(ri, 0, sizeof(*ri));
diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index 071c951..bbdd63c 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -32,15 +32,20 @@ void process_arch_opt(int opt, const char *arg)
abort();
}
-const int reginfo_size(void)
+void arch_init(void)
{
- return sizeof(struct reginfo);
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
}
/* reginfo_init: initialize with a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc)
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
{
int i;
+
memset(ri, 0, sizeof(*ri));
ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.regs->nip);
@@ -50,16 +55,11 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
ri->gregs[i] = uc->uc_mcontext.gp_regs[i];
}
- for (i = 0; i < NFPREG; i++) {
- ri->fpregs[i] = uc->uc_mcontext.fp_regs[i];
- }
+ memcpy(ri->fpregs, uc->uc_mcontext.fp_regs, 32 * sizeof(double));
+ ri->fpscr = uc->uc_mcontext.fp_regs[32];
- for (i = 0; i < 32; i++) {
- ri->vrregs.vrregs[i][0] = uc->uc_mcontext.v_regs->vrregs[i][0];
- ri->vrregs.vrregs[i][1] = uc->uc_mcontext.v_regs->vrregs[i][1];
- ri->vrregs.vrregs[i][2] = uc->uc_mcontext.v_regs->vrregs[i][2];
- ri->vrregs.vrregs[i][3] = uc->uc_mcontext.v_regs->vrregs[i][3];
- }
+ memcpy(ri->vrregs.vrregs, uc->uc_mcontext.v_regs->vrregs,
+ sizeof(ri->vrregs.vrregs[0]) * 32);
ri->vrregs.vscr = uc->uc_mcontext.v_regs->vscr;
ri->vrregs.vrsave = uc->uc_mcontext.v_regs->vrsave;
}
@@ -87,10 +87,6 @@ int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
}
for (i = 0; i < 32; i++) {
- if (isnan(m->fpregs[i]) && isnan(a->fpregs[i])) {
- continue;
- }
-
if (m->fpregs[i] != a->fpregs[i]) {
return 0;
}
@@ -137,10 +133,10 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
fprintf(f, "\tdscr : %16lx\n\n", ri->gregs[44]);
for (i = 0; i < 16; i++) {
- fprintf(f, "\tf%2d: %.4f\tf%2d: %.4f\n", i, ri->fpregs[i],
+ fprintf(f, "\tf%2d: %016lx\tf%2d: %016lx\n", i, ri->fpregs[i],
i + 16, ri->fpregs[i + 16]);
}
- fprintf(f, "\tfpscr: %f\n\n", ri->fpregs[32]);
+ fprintf(f, "\tfpscr: %016lx\n\n", ri->fpscr);
for (i = 0; i < 32; i++) {
fprintf(f, "vr%02d: %8x, %8x, %8x, %8x\n", i,
@@ -177,13 +173,10 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
}
for (i = 0; i < 32; i++) {
- if (isnan(m->fpregs[i]) && isnan(a->fpregs[i])) {
- continue;
- }
-
if (m->fpregs[i] != a->fpregs[i]) {
fprintf(f, "Mismatch: Register f%d\n", i);
- fprintf(f, "m: [%f] != a: [%f]\n", m->fpregs[i], a->fpregs[i]);
+ fprintf(f, "m: [%016lx] != a: [%016lx]\n",
+ m->fpregs[i], a->fpregs[i]);
}
}
diff --git a/risu_reginfo_ppc64.h b/risu_reginfo_ppc64.h
index 7f2c962..4b1d8bd 100644
--- a/risu_reginfo_ppc64.h
+++ b/risu_reginfo_ppc64.h
@@ -20,7 +20,8 @@ struct reginfo {
uint64_t nip;
uint64_t prev_addr;
gregset_t gregs;
- fpregset_t fpregs;
+ uint64_t fpregs[32];
+ uint64_t fpscr;
vrregset_t vrregs;
};
diff --git a/risu_reginfo_s390x.c b/risu_reginfo_s390x.c
new file mode 100644
index 0000000..3fd91b9
--- /dev/null
+++ b/risu_reginfo_s390x.c
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * Copyright 2023 Red Hat Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Thomas Huth - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <signal.h>
+#include <asm/ucontext.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <sys/user.h>
+
+#include "risu.h"
+#include "risu_reginfo_s390x.h"
+
+
+const struct option * const arch_long_opts;
+const char * const arch_extra_help;
+
+void process_arch_opt(int opt, const char *arg)
+{
+ abort();
+}
+
+void arch_init(void)
+{
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
+}
+
+/* reginfo_init: initialize with a ucontext */
+void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
+{
+ struct ucontext_extended *uce = (struct ucontext_extended *)uc;
+
+ memset(ri, 0, sizeof(*ri));
+
+ /*
+ * We can get the size of the instruction by looking at the
+ * first two bits of the instruction
+ */
+ switch (*(uint8_t *)siaddr >> 6) {
+ case 0:
+ ri->faulting_insn = *(uint16_t *)siaddr;
+ ri->faulting_insn_len = 2;
+ break;
+ case 3:
+ ri->faulting_insn = ((*(uint32_t *)siaddr) << 16)
+ | *(uint16_t *)(siaddr + 4);
+ ri->faulting_insn_len = 6;
+ break;
+ default:
+ ri->faulting_insn = *(uint32_t *)siaddr;
+ ri->faulting_insn_len = 4;
+ }
+
+ ri->psw_mask = uce->uc_mcontext.regs.psw.mask;
+ ri->pc_offset = (uintptr_t)siaddr - image_start_address;
+
+ memcpy(ri->gprs, uce->uc_mcontext.regs.gprs, sizeof(ri->gprs));
+
+ ri->fpc = uc->uc_mcontext.fpregs.fpc;
+ memcpy(ri->fprs, &uc->uc_mcontext.fpregs.fprs, sizeof(ri->fprs));
+}
+
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
+{
+ return m->pc_offset == a->pc_offset &&
+ m->fpc == a->fpc &&
+ memcmp(m->gprs, a->gprs, sizeof(m->gprs)) == 0 &&
+ memcmp(&m->fprs, &a->fprs, sizeof(m->fprs)) == 0;
+}
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+int reginfo_dump(struct reginfo *ri, FILE * f)
+{
+ int i;
+
+ fprintf(f, " faulting insn 0x%" PRIx64 "\n", ri->faulting_insn);
+ fprintf(f, " PSW mask 0x%" PRIx64 "\n", ri->psw_mask);
+ fprintf(f, " PC offset 0x%" PRIx64 "\n\n", ri->pc_offset);
+
+ for (i = 0; i < 16/2; i++) {
+ fprintf(f, "\tr%d: %16lx\tr%02d: %16lx\n", i, ri->gprs[i],
+ i + 8, ri->gprs[i + 8]);
+ }
+ fprintf(f, "\n");
+
+ for (i = 0; i < 16/2; i++) {
+ fprintf(f, "\tf%d: %16lx\tf%02d: %16lx\n",
+ i, *(uint64_t *)&ri->fprs[i],
+ i + 8, *(uint64_t *)&ri->fprs[i + 8]);
+ }
+ fprintf(f, "\tFPC: %8x\n\n", ri->fpc);
+
+ return !ferror(f);
+}
+
+int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
+{
+ int i;
+
+ if (m->pc_offset != a->pc_offset) {
+ fprintf(f, "Mismatch: PC offset master: [%016lx] - PC offset apprentice: [%016lx]\n",
+ m->pc_offset, a->pc_offset);
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (m->gprs[i] != a->gprs[i]) {
+ fprintf(f, "Mismatch: r%d master: [%016lx] - r%d apprentice: [%016lx]\n",
+ i, m->gprs[i], i, a->gprs[i]);
+ }
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (*(uint64_t *)&m->fprs[i] != *(uint64_t *)&a->fprs[i]) {
+ fprintf(f, "Mismatch: f%d master: [%016lx] - f%d apprentice: [%016lx]\n",
+ i, *(uint64_t *)&m->fprs[i],
+ i, *(uint64_t *)&a->fprs[i]);
+ }
+ }
+
+ if (m->fpc != a->fpc) {
+ fprintf(f, "Mismatch: FPC master: [%08x] - FPC apprentice: [%08x]\n",
+ m->fpc, a->fpc);
+ }
+
+ return !ferror(f);
+}
diff --git a/risu_reginfo_s390x.h b/risu_reginfo_s390x.h
new file mode 100644
index 0000000..c65fff7
--- /dev/null
+++ b/risu_reginfo_s390x.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright 2023 Red Hat Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Thomas Huth - initial implementation
+ *****************************************************************************/
+
+#ifndef RISU_REGINFO_S390X_H
+#define RISU_REGINFO_S390X_H
+
+struct reginfo {
+ uint64_t psw_mask;
+ uint64_t pc_offset;
+ uint64_t faulting_insn;
+ int faulting_insn_len;
+ uint32_t fpc;
+ uint64_t gprs[16];
+ uint64_t fprs[16];
+};
+
+#endif /* RISU_REGINFO_S390X_H */
diff --git a/risu_s390x.c b/risu_s390x.c
new file mode 100644
index 0000000..cf9c72c
--- /dev/null
+++ b/risu_s390x.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * Copyright 2023 Red Hat Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Thomas Huth - initial implementation
+ *****************************************************************************/
+
+#include <sys/user.h>
+
+#include "risu.h"
+
+void advance_pc(void *vuc)
+{
+ /*
+ * Note: The PSW address already points to the next instruction
+ * after we get a SIGILL, so we must not advance it here!
+ */
+}
+
+void set_ucontext_paramreg(void *vuc, uint64_t value)
+{
+ ucontext_t *uc = vuc;
+ uc->uc_mcontext.gregs[0] = value;
+}
+
+uint64_t get_reginfo_paramreg(struct reginfo *ri)
+{
+ return ri->gprs[0];
+}
+
+RisuOp get_risuop(struct reginfo *ri)
+{
+ uint32_t insn = ri->faulting_insn;
+ uint32_t op = insn & 0xff;
+ uint32_t key = insn & ~0xff;
+
+ if (ri->faulting_insn_len == 4 && key == 0x835a0f00) {
+ return op;
+ }
+
+ return OP_SIGILL;
+}
+
+uintptr_t get_pc(struct reginfo *ri)
+{
+ return ri->pc_offset;
+}
diff --git a/risugen b/risugen
index e690b18..2800b8b 100755
--- a/risugen
+++ b/risugen
@@ -43,7 +43,7 @@ my @pattern_re = (); # include pattern
my @not_pattern_re = (); # exclude pattern
# Valid block names (keys in blocks hash)
-my %valid_blockname = ( constraints => 1, memory => 1 );
+my %valid_blockname = ( constraints => 1, memory => 1, post =>1 );
sub parse_risu_directive($$@)
{
diff --git a/risugen_loongarch64.pm b/risugen_loongarch64.pm
new file mode 100644
index 0000000..98fbd48
--- /dev/null
+++ b/risugen_loongarch64.pm
@@ -0,0 +1,530 @@
+#!/usr/bin/perl -w
+###############################################################################
+# Copyright (c) 2022 Loongson Technology Corporation Limited
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# based on Peter Maydell (Linaro) - initial implementation
+###############################################################################
+
+# risugen -- generate a test binary file for use with risu
+# See 'risugen --help' for usage information.
+package risugen_loongarch64;
+
+use strict;
+use warnings;
+
+use risugen_common;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(write_test_code);
+
+my $periodic_reg_random = 1;
+
+# Maximum alignment restriction permitted for a memory op.
+my $MAXALIGN = 64;
+
+my $OP_COMPARE = 0; # compare registers
+my $OP_TESTEND = 1; # end of test, stop
+my $OP_SETMEMBLOCK = 2; # r4 is address of memory block (8192 bytes)
+my $OP_GETMEMBLOCK = 3; # add the address of memory block to r4
+my $OP_COMPAREMEM = 4; # compare memory block
+
+sub write_risuop($)
+{
+ my ($op) = @_;
+ insn32(0x000001f0 | $op);
+}
+
+sub write_set_fcsr($)
+{
+ my ($fcsr) = @_;
+ # movgr2fcsr r0, r0
+ insn32(0x0114c000);
+}
+
+# Global used to communicate between align(x) and reg() etc.
+my $alignment_restriction;
+
+sub set_reg_w($)
+{
+ my($reg)=@_;
+ # Set reg [0x0, 0x7FFFFFFF]
+
+ # $reg << 33
+ # slli.d $reg, $reg, 33
+ insn32(0x410000 | 33 << 10 | $reg << 5 | $reg);
+ # $reg >> 33
+ # srli.d $reg, $reg, 33
+ insn32(0x450000 | 33 << 10 | $reg << 5 | $reg);
+
+ return $reg;
+}
+
+sub nanbox_s($)
+{
+ my ($fpreg)=@_;
+
+ # Set $fpreg register high 32bit ffffffff
+ # use r1 as a temp register
+ # r1 = r1 | ~(r0)
+ write_mov_ri(1, -1);
+
+ # movgr2frh.w $fpreg ,$1
+ insn32(0x114ac00 | 1 << 5 | $fpreg);
+
+ return $fpreg;
+}
+
+sub clean_lsx_result($)
+{
+ my ($vreg) = @_;
+
+ # xvinsgr2vr.d vd, r0, 2;
+ insn32(0x76ebe000 | 2 << 10 | $vreg);
+ # xvinsgr2vr.d vd, r0, 3;
+ insn32(0x76ebe000 | 3 << 10 | $vreg);
+
+ return $vreg;
+}
+
+sub align($)
+{
+ my ($a) = @_;
+ if (!is_pow_of_2($a) || ($a < 0) || ($a > $MAXALIGN)) {
+ die "bad align() value $a\n";
+ }
+ $alignment_restriction = $a;
+}
+
+sub write_sub_rrr($$$)
+{
+ my ($rd, $rj, $rk) = @_;
+ # sub.d rd, rj, rk
+ insn32(0x00118000 | $rk << 10 | $rj << 5 | $rd);
+}
+
+sub write_mov_rr($$$)
+{
+ my($rd, $rj, $rk) = @_;
+ # add.d rd, rj, r0
+ insn32(0x00108000 | 0 << 10 | $rj << 5 | $rd);
+}
+
+sub write_mov_ri($$)
+{
+ my ($rd, $imm) = @_;
+
+ if ($imm >= -0x80000000 && $imm <= 0x7fffffff) {
+ # lu12i.w rd, si20
+ insn32(0x14000000 | (($imm >> 12) & 0xfffff) << 5 | $rd);
+ # ori rd, rd, ui12
+ insn32(0x03800000 | ($imm & 0xfff) << 10 | $rd << 5 | $rd);
+ } else {
+ die "unhandled immediate load";
+ }
+}
+
+sub write_get_offset()
+{
+ # Emit code to get a random offset within the memory block, of the
+ # right alignment, into r4
+ # We require the offset to not be within 256 bytes of either
+ # end, to (more than) allow for the worst case data transfer, which is
+ # 16 * 64 bit regs
+ my $offset = (rand(2048 - 512) + 256) & ~($alignment_restriction - 1);
+ write_mov_ri(4, $offset);
+ write_risuop($OP_GETMEMBLOCK);
+}
+
+sub reg_plus_reg($$@)
+{
+ my ($base, $idx, @trashed) = @_;
+ my $savedidx = 0;
+ if ($idx == 4) {
+ # Save the index into some other register for the
+ # moment, because the risuop will trash r4.
+ $idx = 5;
+ $idx++ if $idx == $base;
+ $savedidx = 1;
+ write_mov_rr($idx, 4, 0);
+ }
+ # Get a random offset within the memory block, of the
+ # right alignment.
+ write_get_offset();
+
+ write_sub_rrr($base, 4, $idx);
+ if ($base != 4) {
+ if ($savedidx) {
+ write_mov_rr(4, $idx, 0);
+ write_mov_ri($idx, 0);
+ } else {
+ write_mov_ri(4, 0);
+ }
+ } else {
+ if ($savedidx) {
+ write_mov_ri($idx, 0);
+ }
+ }
+
+ if (grep $_ == $base, @trashed) {
+ return -1;
+ }
+ return $base;
+}
+
+sub reg_plus_imm($$@)
+{
+ # Handle reg + immediate addressing mode
+ my ($base, $imm, @trashed) = @_;
+
+ write_get_offset();
+ # Now r4 is the address we want to do the access to,
+ # so set the basereg by doing the inverse of the
+ # addressing mode calculation, ie base = r4 - imm
+ # We could do this more cleverly with a sub immediate.
+ if ($base != 4) {
+ write_mov_ri($base, $imm);
+ write_sub_rrr($base, 4, $base);
+ # Clear r4 to avoid register compare mismatches
+ # when the memory block location differs between machines.
+ write_mov_ri(4, 0);
+ }else {
+ # We borrow r1 as a temporary (not a problem
+ # as long as we don't leave anything in a register
+ # which depends on the location of the memory block)
+ write_mov_ri(1, $imm);
+ write_sub_rrr($base, 4, 1);
+ }
+
+ if (grep $_ == $base, @trashed) {
+ return -1;
+ }
+ return $base;
+}
+
+sub write_pc_adr($$)
+{
+ my($rd, $imm) = @_;
+ # pcaddi (si20 | 2bit 0) + pc
+ insn32(0x18000000 | $imm << 5 | $rd);
+}
+
+sub write_and($$$)
+{
+ my($rd, $rj, $rk) = @_;
+ # and rd, rj, rk
+ insn32(0x148000 | $rk << 10 | $rj << 5 | $rd);
+}
+
+sub write_align_reg($$)
+{
+ my ($rd, $align) = @_;
+ # rd = rd & ~($align -1);
+ # use r1 as a temp register.
+ write_mov_ri(1, $align -1);
+ write_sub_rrr(1, 0, 1);
+ write_and($rd, $rd, 1);
+}
+
+sub write_jump_fwd($)
+{
+ my($len) = @_;
+ # b pc + len
+ my ($offslo, $offshi) = (($len / 4 + 1) & 0xffff, ($len / 4 + 1) >> 16);
+ insn32(0x50000000 | $offslo << 10 | $offshi);
+}
+
+sub write_memblock_setup()
+{
+ my $align = $MAXALIGN;
+ my $datalen = 8192 + $align;
+ if (($align > 255) || !is_pow_of_2($align) || $align < 4) {
+ die "bad alignment!";
+ }
+
+ # Set r4 to (datablock + (align-1)) & ~(align-1)
+ # datablock is at PC + (4 * 4 instructions) = PC + 16
+ write_pc_adr(4, (4 * 4) + ($align - 1)); #insn 1
+ write_align_reg(4, $align); #insn 2
+ write_risuop($OP_SETMEMBLOCK); #insn 3
+ write_jump_fwd($datalen); #insn 4
+
+ for(my $i = 0; $i < $datalen / 4; $i++) {
+ insn32(rand(0xffffffff));
+ }
+}
+
+# Write random fp value of passed precision (1=single, 2=double, 4=quad)
+sub write_random_fpreg_var($)
+{
+ my ($precision) = @_;
+ my $randomize_low = 0;
+
+ if ($precision != 1 && $precision != 2 && $precision != 4) {
+ die "write_random_fpreg: invalid precision.\n";
+ }
+
+ my ($low, $high);
+ my $r = rand(100);
+ if ($r < 5) {
+ # +-0 (5%)
+ $low = $high = 0;
+ $high |= 0x80000000 if (rand() < 0.5);
+ } elsif ($r < 10) {
+ # NaN (5%)
+ # (plus a tiny chance of generating +-Inf)
+ $randomize_low = 1;
+ $high = rand(0xffffffff) | 0x7ff00000;
+ } elsif ($r < 15) {
+ # Infinity (5%)
+ $low = 0;
+ $high = 0x7ff00000;
+ $high |= 0x80000000 if (rand() < 0.5);
+ } elsif ($r < 30) {
+ # Denormalized number (15%)
+ # (plus tiny chance of +-0)
+ $randomize_low = 1;
+ $high = rand(0xffffffff) & ~0x7ff00000;
+ } else {
+ # Normalized number (70%)
+ # (plus a small chance of the other cases)
+ $randomize_low = 1;
+ $high = rand(0xffffffff);
+ }
+
+ for (my $i = 1; $i < $precision; $i++) {
+ if ($randomize_low) {
+ $low = rand(0xffffffff);
+ }
+ insn32($low);
+ }
+ insn32($high);
+}
+
+sub write_random_loongarch64_fpdata()
+{
+ # Load floating point registers
+ my $align = 16;
+ my $datalen = 32 * 16 + $align;
+ my $off = 0;
+ write_pc_adr(5, (4 * 4) + $align); # insn 1 pcaddi
+ write_pc_adr(4, (3 * 4) + ($align - 1)); # insn 2 pcaddi
+ write_align_reg(4, $align); # insn 3 andi
+ write_jump_fwd($datalen); # insn 4 b pc + len
+
+ # Align safety
+ for (my $i = 0; $i < ($align / 4); $i++) {
+ insn32(rand(0xffffffff));
+ }
+
+ for (my $i = 0; $i < 32; $i++) {
+ write_random_fpreg_var(4); # double
+ }
+
+ $off = 0;
+ for (my $i = 0; $i < 32; $i++) {
+ my $tmp_reg = 6;
+ # r5 is fp register initial val
+ # r4 is aligned base address
+ # copy memory from r5 to r4
+ # ld.d r6, r5, $off
+ # st.d r6, r4, $off
+ # $off = $off + 16
+ insn32(0x28c00000 | $off << 10 | 5 << 5 | $tmp_reg);
+ insn32(0x29c00000 | $off << 10 | 4 << 5 | $tmp_reg);
+ $off = $off + 8;
+ insn32(0x28c00000 | $off << 10 | 5 << 5 | $tmp_reg);
+ insn32(0x29c00000 | $off << 10 | 4 << 5 | $tmp_reg);
+ $off = $off + 8;
+ }
+
+ $off = 0;
+ for (my $i = 0; $i < 32; $i++) {
+ # fld.d fd, r4, $off
+ insn32(0x2b800000 | $off << 10 | 4 << 5 | $i);
+ $off = $off + 16;
+ }
+}
+
+sub write_random_regdata()
+{
+ # General purpose registers, skip r2
+ write_mov_ri(1, rand(0x7fffffff)); # init r1
+ for (my $i = 3; $i < 32; $i++) {
+ write_mov_ri($i, rand(0x7fffffff));
+ }
+}
+
+sub write_random_register_data($)
+{
+ my ($fp_enabled) = @_;
+
+ # Set fcc0 ~ fcc7
+ # movgr2cf $fcc0, $zero
+ insn32(0x114d800);
+ # movgr2cf $fcc1, $zero
+ insn32(0x114d801);
+ # movgr2cf $fcc2, $zero
+ insn32(0x114d802);
+ # movgr2cf $fcc3, $zero
+ insn32(0x114d803);
+ # movgr2cf $fcc4, $zero
+ insn32(0x114d804);
+ # movgr2cf $fcc5, $zero
+ insn32(0x114d805);
+ # movgr2cf $fcc6, $zero
+ insn32(0x114d806);
+ # movgr2cf $fcc7, $zero
+ insn32(0x114d807);
+
+ if ($fp_enabled) {
+ # Load floating point registers
+ write_random_loongarch64_fpdata();
+
+ # Write random LASX data.
+ for (my $i = 0; $i < 32; $i++) {
+ my $tmp_reg = 6;
+ # $fi is lasx register initial value.
+ # movfr2gr.d r6 fi
+ insn32(0x114b800 | $i << 5 | $tmp_reg);
+ # xvreplgr2vr_d $i r6
+ insn32(0x769f0c00 | 6 << 5 | $i);
+ }
+ }
+
+ write_random_regdata();
+ write_risuop($OP_COMPARE);
+}
+
+sub gen_one_insn($$)
+{
+ # Given an instruction-details array, generate an instruction
+ my $constraintfailures = 0;
+
+ INSN: while(1) {
+ my ($forcecond, $rec) = @_;
+ my $insn = int(rand(0xffffffff));
+ my $insnname = $rec->{name};
+ my $insnwidth = $rec->{width};
+ my $fixedbits = $rec->{fixedbits};
+ my $fixedbitmask = $rec->{fixedbitmask};
+ my $constraint = $rec->{blocks}{"constraints"};
+ my $memblock = $rec->{blocks}{"memory"};
+ my $post = $rec->{blocks}{"post"};
+
+ $insn &= ~$fixedbitmask;
+ $insn |= $fixedbits;
+
+ if (defined $constraint) {
+ # User-specified constraint: evaluate in an environment
+ # with variables set corresponding to the variable fields.
+ my $v = eval_with_fields($insnname, $insn, $rec, "constraints", $constraint);
+ if(!$v) {
+ $constraintfailures++;
+ if ($constraintfailures > 10000) {
+ print "10000 consecutive constraint failures for $insnname constraints string:\n$constraint\n";
+ exit (1);
+ }
+ next INSN;
+ }
+ }
+
+ # OK, we got a good one
+ $constraintfailures = 0;
+
+ my $basereg;
+
+ if (defined $memblock) {
+ # This is a load or store. We simply evaluate the block,
+ # which is expected to be a call to a function which emits
+ # the code to set up the base register and returns the
+ # number of the base register.
+ # Default alignment requirement for ARM is 4 bytes,
+ # we use 16 for Aarch64, although often unnecessary and overkill.
+ align(16);
+ $basereg = eval_with_fields($insnname, $insn, $rec, "memory", $memblock);
+ }
+
+ insn32($insn);
+
+ if (defined $post) {
+ # The hook for doing things after emitting the instruction.
+ my $resultreg;
+ $resultreg = eval_with_fields($insnname, $insn, $rec, "post", $post);
+ }
+
+ if (defined $memblock) {
+ # Clean up following a memory access instruction:
+ # we need to turn the (possibly written-back) basereg
+ # into an offset from the base of the memory block,
+ # to avoid making register values depend on memory layout.
+ # $basereg -1 means the basereg was a target of a load
+ # (and so it doesn't contain a memory address after the op)
+ if ($basereg != -1) {
+ write_mov_ri($basereg, 0);
+ }
+ write_risuop($OP_COMPAREMEM);
+ }
+ return;
+ }
+}
+
+sub write_test_code($)
+{
+ my ($params) = @_;
+
+ my $condprob = $params->{ 'condprob' };
+ my $fcsr = $params->{'fpscr'};
+ my $numinsns = $params->{ 'numinsns' };
+ my $fp_enabled = $params->{ 'fp_enabled' };
+ my $outfile = $params->{ 'outfile' };
+
+ my %insn_details = %{ $params->{ 'details' } };
+ my @keys = @{ $params->{ 'keys' } };
+
+ open_bin($outfile);
+
+ # Convert from probability that insn will be conditional to
+ # probability of forcing insn to unconditional
+ $condprob = 1 - $condprob;
+
+ # TODO better random number generator?
+ srand(0);
+
+ print "Generating code using patterns: @keys...\n";
+ progress_start(78, $numinsns);
+
+ if ($fp_enabled) {
+ write_set_fcsr($fcsr);
+ }
+
+ if (grep { defined($insn_details{$_}->{blocks}->{"memory"}) } @keys) {
+ write_memblock_setup();
+ }
+ # Memblock setup doesn't clean its registers, so this must come afterwards.
+ write_random_register_data($fp_enabled);
+
+ for my $i (1..$numinsns) {
+ my $insn_enc = $keys[int rand (@keys)];
+ my $forcecond = (rand() < $condprob) ? 1 : 0;
+ gen_one_insn($forcecond, $insn_details{$insn_enc});
+ write_risuop($OP_COMPARE);
+ # Rewrite the registers periodically. This avoids the tendency
+ # for the VFP registers to decay to NaNs and zeroes.
+ if ($periodic_reg_random && ($i % 100) == 0) {
+ write_random_register_data($fp_enabled);
+ }
+ progress_update($i);
+ }
+ write_risuop($OP_TESTEND);
+ progress_end();
+ close_bin();
+}
+
+1;
diff --git a/risugen_s390x.pm b/risugen_s390x.pm
new file mode 100644
index 0000000..260e2dd
--- /dev/null
+++ b/risugen_s390x.pm
@@ -0,0 +1,186 @@
+#!/usr/bin/perl -w
+###############################################################################
+# Copyright 2023 Red Hat Inc.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Thomas Huth - initial implementation (based on risugen_ppc64.pm etc.)
+###############################################################################
+
+# risugen -- generate a test binary file for use with risu
+# See 'risugen --help' for usage information.
+package risugen_s390x;
+
+use strict;
+use warnings;
+
+use risugen_common;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(write_test_code);
+
+my $periodic_reg_random = 1;
+
+# Maximum alignment restriction permitted for a memory op.
+my $MAXALIGN = 64;
+
+sub write_mov_ri($$$)
+{
+ my ($r, $imm_h, $imm_l) = @_;
+
+ # LGFI
+ insn16(0xc0 << 8 | $r << 4 | 0x1);
+ insn32($imm_l);
+ # IIHF r,imm_high
+ insn16(0xc0 << 8 | $r << 4 | 0x8);
+ insn32($imm_h);
+}
+
+sub write_mov_fp($$)
+{
+ my ($r, $imm) = @_;
+
+ write_mov_ri(0, ~$imm, $imm);
+ # LDGR
+ insn32(0xb3c1 << 16 | $r << 4);
+}
+
+sub write_random_regdata()
+{
+ # Floating point registers
+ for (my $i = 0; $i < 16; $i++) {
+ write_mov_fp($i, rand(0xffffffff));
+ }
+
+ # Load FPC (via r0)
+ write_mov_ri(0, 0, (rand(0xffffffff) & 0x00fcff77));
+ insn32(0xb3840000);
+
+ # general purpose registers
+ for (my $i = 0; $i < 16; $i++) {
+ write_mov_ri($i, rand(0xffffffff), rand(0xffffffff));
+ }
+}
+
+my $OP_COMPARE = 0; # compare registers
+my $OP_TESTEND = 1; # end of test, stop
+
+sub write_random_register_data()
+{
+ write_random_regdata();
+ write_risuop($OP_COMPARE);
+}
+
+sub gen_one_insn($$)
+{
+ # Given an instruction-details array, generate an instruction
+ my $constraintfailures = 0;
+
+ INSN: while(1) {
+ my ($forcecond, $rec) = @_;
+ my $insn = int(rand(0xffffffff));
+ my $insnname = $rec->{name};
+ my $insnwidth = $rec->{width};
+ my $fixedbits = $rec->{fixedbits};
+ my $fixedbitmask = $rec->{fixedbitmask};
+ my $constraint = $rec->{blocks}{"constraints"};
+ my $memblock = $rec->{blocks}{"memory"};
+
+ $insn &= ~$fixedbitmask;
+ $insn |= $fixedbits;
+
+ if (defined $constraint) {
+ # user-specified constraint: evaluate in an environment
+ # with variables set corresponding to the variable fields.
+ my $v = eval_with_fields($insnname, $insn, $rec, "constraints", $constraint);
+ if (!$v) {
+ $constraintfailures++;
+ if ($constraintfailures > 10000) {
+ print "10000 consecutive constraint failures for $insnname constraints string:\n$constraint\n";
+ exit (1);
+ }
+ next INSN;
+ }
+ }
+
+ # OK, we got a good one
+ $constraintfailures = 0;
+
+ my $basereg;
+
+ if (defined $memblock) {
+ die "memblock handling has not been implemented yet."
+ }
+
+ if ($insnwidth == 16) {
+ insn16(($insn >> 16) & 0xffff);
+ } else {
+ insn32($insn);
+ }
+
+ return;
+ }
+}
+
+sub write_risuop($)
+{
+ my ($op) = @_;
+ insn32(0x835a0f00 | $op);
+}
+
+sub write_test_code($)
+{
+ my ($params) = @_;
+
+ my $condprob = $params->{ 'condprob' };
+ my $numinsns = $params->{ 'numinsns' };
+ my $outfile = $params->{ 'outfile' };
+
+ my %insn_details = %{ $params->{ 'details' } };
+ my @keys = @{ $params->{ 'keys' } };
+
+ set_endian(1);
+
+ open_bin($outfile);
+
+ # convert from probability that insn will be conditional to
+ # probability of forcing insn to unconditional
+ $condprob = 1 - $condprob;
+
+ # TODO better random number generator?
+ srand(0);
+
+ print "Generating code using patterns: @keys...\n";
+ progress_start(78, $numinsns);
+
+ if (grep { defined($insn_details{$_}->{blocks}->{"memory"}) } @keys) {
+ write_memblock_setup();
+ }
+
+ # memblock setup doesn't clean its registers, so this must come afterwards.
+ write_random_register_data();
+
+ for my $i (1..$numinsns) {
+ my $insn_enc = $keys[int rand (@keys)];
+ #dump_insn_details($insn_enc, $insn_details{$insn_enc});
+ my $forcecond = (rand() < $condprob) ? 1 : 0;
+ gen_one_insn($forcecond, $insn_details{$insn_enc});
+ write_risuop($OP_COMPARE);
+ # Rewrite the registers periodically. This avoids the tendency
+ # for the VFP registers to decay to NaNs and zeroes.
+ if ($periodic_reg_random && ($i % 100) == 0) {
+ write_random_register_data();
+ }
+ progress_update($i);
+ }
+ write_risuop($OP_TESTEND);
+ progress_end();
+ close_bin();
+}
+
+1;
diff --git a/s390x.risu b/s390x.risu
new file mode 100644
index 0000000..1661be6
--- /dev/null
+++ b/s390x.risu
@@ -0,0 +1,81 @@
+###############################################################################
+# Copyright 2023 Red Hat Inc.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Thomas Huth - initial implementation
+###############################################################################
+
+.mode s390x
+
+# format:RR Add (register + register, 32 bit)
+AR Z 00011010 r1:4 r2:4
+
+# format:RRE Add (register + register, 64 bit)
+AGR Z 10111001 00001000 00000000 r1:4 r2:4
+
+# format:RRE Add (register + register, 32 bit to 64 bit)
+AGFR Z 10111001 00011000 00000000 r1:4 r2:4
+
+# format:RRF-a Add (three registers, 32 bit)
+ARK STFLE45 10111001 11111000 r3:4 0000 r1:4 r2:4
+
+# format:RRF-a Add (three registers, 64 bit)
+AGRK STFLE45 10111001 11101000 r3:4 0000 r1:4 r2:4
+
+
+# format:RRE Add Halfword Immediate (32 bit)
+AHI Z 10100111 r1:4 1010 i2:16
+
+# format:RI Add Halfword Immediate (64 bit)
+AGHI Z 10100111 r1:4 1011 i2:16
+
+
+# format:RR Add Logical (32 bit)
+ALR Z 00011110 r1:4 r2:4
+
+# format:RRE Add Logical (64 bit)
+ALGR Z 10111001 00001010 00000000 r1:4 r2:4
+
+# format:RRE Add Logical (32 bit to 64 bit)
+ALGFR Z 10111001 00011010 00000000 r1:4 r2:4
+
+
+# format:RRF-c Population Count
+POPCNT STFLE45 10111001 11100001 m3:4 0000 r1:4 r2:4
+
+
+###### Binary floating point instructions ######
+
+# format:RRE ADD (short BFP)
+AEBR BFP 10110011 00001010 00000000 r1:4 r2:4
+
+# format:RRE ADD (long BFP)
+ADBR BFP 10110011 00011010 00000000 r1:4 r2:4
+
+# format:RRE ADD (extended BFP)
+AXBR BFP 10110011 01001010 00000000 r1:4 r2:4
+
+
+# format:RRE COMPARE (short BFP)
+CEBR BFP 10110011 00001001 00000000 r1:4 r2:4
+
+# format:RRE COMPARE (long BFP)
+CDBR BFP 10110011 00011001 00000000 r1:4 r2:4
+
+# format:RRE COMPARE (extended BFP)
+CXBR BFP 10110011 01001001 00000000 r1:4 r2:4
+
+
+# format:RRF-e LOAD FP INTEGER (short BFP)
+FIEBRA BFP 10110011 01010111 m3:4 m4:4 r1:4 r2:4
+
+# format:RRF-e LOAD FP INTEGER (long BFP)
+FIDBRA BFP 10110011 01011111 m3:4 m4:4 r1:4 r2:4
+
+# format:RRF-e LOAD FP INTEGER (extended BFP)
+FIXBRA BFP 10110011 01000111 m3:4 m4:4 r1:4 r2:4
+
diff --git a/test_loongarch64.s b/test_loongarch64.s
new file mode 100644
index 0000000..431416d
--- /dev/null
+++ b/test_loongarch64.s
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * Copyright (c) 2022 Loongson Technology Corporation Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * rhich accompanies this distribution, and is available at
+ * http://rrr.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * based on test_arm.s by Peter Maydell
+ *****************************************************************************/
+
+/* Initialise the gp regs */
+# $r0 is always 0
+addi.w $r1, $r0, 1
+#r2 tp skip r2
+#r3 sp
+addi.w $r3, $r0, 3
+addi.w $r4, $r0, 4
+addi.w $r5, $r0, 5
+addi.w $r6, $r0, 6
+addi.w $r7, $r0, 7
+addi.w $r8, $r0, 8
+addi.w $r9, $r0, 9
+addi.w $r10, $r0, 10
+addi.w $r11, $r0, 11
+addi.w $r12, $r0, 12
+addi.w $r13, $r0, 13
+addi.w $r14, $r0, 14
+addi.w $r15, $r0, 15
+addi.w $r16, $r0, 16
+addi.w $r17, $r0, 17
+addi.w $r18, $r0, 18
+addi.w $r19, $r0, 19
+addi.w $r20, $r0, 20
+addi.w $r21, $r0, 21
+addi.w $r22, $r0, 22
+addi.w $r23, $r0, 23
+addi.w $r24, $r0, 24
+addi.w $r25, $r0, 25
+addi.w $r26, $r0, 26
+addi.w $r27, $r0, 27
+addi.w $r28, $r0, 28
+addi.w $r29, $r0, 29
+addi.w $r30, $r0, 30
+addi.w $r31, $r0, 31
+
+/* Initialise the fp regs */
+movgr2fr.d $f0, $r0
+movgr2fr.d $f1, $r1
+movgr2fr.d $f2, $r0
+movgr2fr.d $f3, $r0
+movgr2fr.d $f4, $r4
+movgr2fr.d $f5, $r5
+movgr2fr.d $f6, $r6
+movgr2fr.d $f7, $r7
+movgr2fr.d $f8, $r8
+movgr2fr.d $f9, $r9
+movgr2fr.d $f10, $r10
+movgr2fr.d $f11, $r11
+movgr2fr.d $f12, $r12
+movgr2fr.d $f13, $r13
+movgr2fr.d $f14, $r14
+movgr2fr.d $f15, $r15
+movgr2fr.d $f16, $r16
+movgr2fr.d $f17, $r17
+movgr2fr.d $f18, $r18
+movgr2fr.d $f19, $r19
+movgr2fr.d $f20, $r20
+movgr2fr.d $f21, $r21
+movgr2fr.d $f22, $r22
+movgr2fr.d $f23, $r23
+movgr2fr.d $f24, $r24
+movgr2fr.d $f25, $r25
+movgr2fr.d $f26, $r26
+movgr2fr.d $f27, $r27
+movgr2fr.d $f28, $r28
+movgr2fr.d $f29, $r29
+movgr2fr.d $f30, $r30
+movgr2fr.d $f31, $r31
+movgr2cf $fcc0, $r0
+movgr2cf $fcc1, $r0
+movgr2cf $fcc2, $r0
+movgr2cf $fcc3, $r0
+movgr2cf $fcc4, $r0
+movgr2cf $fcc5, $r0
+movgr2cf $fcc6, $r0
+movgr2cf $fcc7, $r0
+
+/* do compare. */
+.int 0x000001f0
+/* exit test */
+.int 0x000001f1
diff --git a/test_s390x.S b/test_s390x.S
new file mode 100644
index 0000000..16f3c6f
--- /dev/null
+++ b/test_s390x.S
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * Copyright 2023 Red Hat Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Thomas Huth - initial implementation
+ *****************************************************************************/
+
+ /* Initialise the general purpose registers */
+ lgfi %r0, 0
+ lgfi %r1, 0x1111111
+ lgfi %r2, 0x2222222
+ lgfi %r3, 0x3333333
+ lgfi %r4, 0x4444444
+ lgfi %r5, 0x5555555
+ lgfi %r6, 0x6666666
+ lgfi %r7, 0x7777777
+ lgfi %r8, 0x8888888
+ lgfi %r9, 0x9999999
+ lgfi %r10, 0xaaaaaaa
+ lgfi %r11, 0xbbbbbbb
+ lgfi %r12, 0xccccccc
+ lgfi %r13, 0xddddddd
+ lgfi %r14, 0xeeeeeee
+ lgfi %r15, 0xfffffff
+
+ /* Initialize floating point registers */
+ ldgr %f0,%r0
+ ldgr %f1,%r1
+ ldgr %f2,%r2
+ ldgr %f3,%r3
+ ldgr %f4,%r4
+ ldgr %f5,%r5
+ ldgr %f6,%r6
+ ldgr %f7,%r7
+ ldgr %f8,%r8
+ ldgr %f9,%r9
+ ldgr %f10,%r10
+ ldgr %f11,%r11
+ ldgr %f12,%r12
+ ldgr %f13,%r13
+ ldgr %f14,%r14
+ ldgr %f15,%r15
+
+ /* do compare */
+ .int 0x835a0f00
+ nop
+
+ /* exit test */
+ .int 0x835a0f01