diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | arm.risu | 218 | ||||
-rwxr-xr-x | build-all-archs | 3 | ||||
-rw-r--r-- | comms.c | 34 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | loongarch64.risu | 2881 | ||||
-rw-r--r-- | reginfo.c | 183 | ||||
-rw-r--r-- | risu.c | 526 | ||||
-rw-r--r-- | risu.h | 95 | ||||
-rw-r--r-- | risu_aarch64.c | 6 | ||||
-rw-r--r-- | risu_arm.c | 6 | ||||
-rw-r--r-- | risu_i386.c | 4 | ||||
-rw-r--r-- | risu_loongarch64.c | 50 | ||||
-rw-r--r-- | risu_m68k.c | 4 | ||||
-rw-r--r-- | risu_ppc64.c | 4 | ||||
-rw-r--r-- | risu_reginfo_aarch64.c | 226 | ||||
-rw-r--r-- | risu_reginfo_aarch64.h | 49 | ||||
-rw-r--r-- | risu_reginfo_arm.c | 10 | ||||
-rw-r--r-- | risu_reginfo_i386.c | 12 | ||||
-rw-r--r-- | risu_reginfo_loongarch64.c | 268 | ||||
-rw-r--r-- | risu_reginfo_loongarch64.h | 26 | ||||
-rw-r--r-- | risu_reginfo_m68k.c | 10 | ||||
-rw-r--r-- | risu_reginfo_ppc64.c | 39 | ||||
-rw-r--r-- | risu_reginfo_ppc64.h | 3 | ||||
-rw-r--r-- | risu_reginfo_s390x.c | 140 | ||||
-rw-r--r-- | risu_reginfo_s390x.h | 25 | ||||
-rw-r--r-- | risu_s390x.c | 51 | ||||
-rwxr-xr-x | risugen | 2 | ||||
-rw-r--r-- | risugen_loongarch64.pm | 530 | ||||
-rw-r--r-- | risugen_s390x.pm | 186 | ||||
-rw-r--r-- | s390x.risu | 81 | ||||
-rw-r--r-- | test_loongarch64.s | 92 | ||||
-rw-r--r-- | test_s390x.S | 53 |
33 files changed, 5182 insertions, 641 deletions
@@ -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 @@ -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" @@ -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); } } @@ -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; -} @@ -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(); } } @@ -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) @@ -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; +} @@ -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 |