You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
1
|
2
|
3
(1) |
4
|
5
|
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
|
13
|
14
|
15
|
16
|
17
|
18
|
19
(3) |
|
20
|
21
|
22
(5) |
23
(4) |
24
(2) |
25
(4) |
26
|
|
27
|
28
|
29
|
30
(1) |
|
|
|
|
From: Carl L. <ca...@so...> - 2020-09-22 16:50:01
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=336b8c514dbfc177283ee71b803b67f5145e8bf7 commit 336b8c514dbfc177283ee71b803b67f5145e8bf7 Author: Carl Love <ce...@us...> Date: Mon Sep 21 15:57:26 2020 -0500 Prefixed load-store support Diff: --- NEWS | 1 + none/tests/ppc64/Makefile.am | 11 +- none/tests/ppc64/test_isa_3_1_RT.c | 507 ++++++++++++++++++++++++++++ none/tests/ppc64/test_isa_3_1_RT.stderr.exp | 2 + none/tests/ppc64/test_isa_3_1_RT.stdout.exp | 148 ++++++++ none/tests/ppc64/test_isa_3_1_XT.c | 479 ++++++++++++++++++++++++++ none/tests/ppc64/test_isa_3_1_XT.stderr.exp | 2 + none/tests/ppc64/test_isa_3_1_XT.stdout.exp | 119 +++++++ 8 files changed, 1264 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index eacf97bf6a..13bfe4fa1e 100644 --- a/NEWS +++ b/NEWS @@ -238,6 +238,7 @@ n-i-bz Add support for the Linux io_uring system calls n-i-bz sys_statx: don't complain if both |filename| and |buf| are NULL. n-i-bz Fix non-glibc build of test suite with s390x_features n-i-bz MinGW, include/valgrind.h: Fix detection of 64-bit mode +423195 PPC ISA 3.1 support is missing, part 1 (3.16.0.RC1: 18 May 2020, git 6052ee66a0cf5234e8e2a2b49a8760226bc13b92) (3.16.0.RC2: 19 May 2020, git 940ec1ca69a09f7fdae3e800b7359f85c13c4b37) diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am index a43e527fe6..e029e7398f 100644 --- a/none/tests/ppc64/Makefile.am +++ b/none/tests/ppc64/Makefile.am @@ -49,10 +49,10 @@ EXTRA_DIST = \ test_isa_3_0_altivec.stdout.exp-LE test_isa_3_0_altivec.vgtest \ test_isa_3_0_other.stderr.exp \ test_isa_3_0_other.stdout.exp-LE test_isa_3_0_other.vgtest \ + test_isa_3_1_RT.vgtest test_isa_3_1_RT.stderr.exp test_isa_3_1_RT.stdout.exp \ + test_isa_3_1_XT.vgtest test_isa_3_1_XT.stderr.exp test_isa_3_1_XT.stdout.exp \ subnormal_test.stderr.exp subnormal_test.stdout.exp \ subnormal_test.vgtest -# test_isa_3_1_RT.vgtest test_isa_3_1_RT.stderr.exp test_isa_3_1_RT.stdout.exp -# test_isa_3_1_XT.vgtest test_isa_3_1_XT.stderr.exp test_isa_3_1_XT.stdout.exp # test_isa_3_1_VRT.vgtest test_isa_3_1_VRT.stderr.exp test_isa_3_1_VRT.stdout.exp # test_isa_3_1_Misc.vgtest test_isa_3_1_Misc.stderr.exp test_isa_3_1_Misc.stdout.exp # test_isa_3_1_AT.vgtest test_isa_3_1_AT.stderr.exp test_isa_3_1_AT.stdout.exp @@ -64,11 +64,11 @@ check_PROGRAMS = \ test_dfp1 test_dfp2 test_dfp3 test_dfp4 test_dfp5 \ test_isa_2_07_part1 test_isa_2_07_part2 \ test_isa_3_0 \ + test_isa_3_1_RT test_isa_3_1_XT \ subnormal_test \ test_tm test_touch_tm ldst_multiple data-cache-instructions \ power6_mf_gpr std_reg_imm \ twi_tdi tw_td power6_bcmp -# test_isa_3_1_RT test_isa_3_1_XT # test_isa_3_1_Misc test_isa_3_1_VRT test_isa_3_1_AT AM_CFLAGS += @FLAG_M64@ @@ -77,8 +77,9 @@ AM_CCASFLAGS += @FLAG_M64@ allexec_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@ -#test_isa_3_1_XT_SOURCES = test_isa_3_1_XT.c test_isa_3_1_common.c -#test_isa_3_1_RT_SOURCES = test_isa_3_1_RT.c test_isa_3_1_common.c +test_isa_3_1_XT_SOURCES = test_isa_3_1_XT.c test_isa_3_1_common.c +test_isa_3_1_RT_SOURCES = test_isa_3_1_RT.c test_isa_3_1_common.c + #test_isa_3_1_VRT_SOURCES = test_isa_3_1_VRT.c test_isa_3_1_common.c #test_isa_3_1_AT_SOURCES = test_isa_3_1_AT.c test_isa_3_1_common.c #test_isa_3_1_Misc_SOURCES = test_isa_3_1_Misc.c test_isa_3_1_common.c diff --git a/none/tests/ppc64/test_isa_3_1_RT.c b/none/tests/ppc64/test_isa_3_1_RT.c new file mode 100644 index 0000000000..fc33c76722 --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_RT.c @@ -0,0 +1,507 @@ +/* + * Valgrind testcase for PowerPC ISA 3.1 + * + * Copyright (C) 2019-2020 Will Schmidt <wil...@vn...> + * + * 64bit build: + * gcc -Winline -Wall -g -O -mregnames -maltivec -m64 + */ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <altivec.h> +#include <malloc.h> + +#include <string.h> +#include <signal.h> +#include <setjmp.h> + +/* Condition Register fields. + These are used to capture the condition register values immediately after + the instruction under test is executed. This is done to help prevent other + test overhead (switch statements, result compares, etc) from disturbing + the test case results. */ +unsigned long current_cr; +unsigned long current_fpscr; + + +struct test_list_t current_test; + +#include "isa_3_1_helpers.h" + +#ifdef HAS_ISA_3_1 + +static void test_plbz_off0 (void) { + __asm__ __volatile__ ("plbz %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plbz_off8 (void) { + __asm__ __volatile__ ("plbz %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plbz_off16 (void) { + __asm__ __volatile__ ("plbz %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plbz_off32 (void) { + __asm__ __volatile__ ("plbz %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plbz_off64 (void) { + __asm__ __volatile__ ("plbz %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plhz_off0 (void) { + __asm__ __volatile__ ("plhz %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plhz_off8 (void) { + __asm__ __volatile__ ("plhz %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plhz_off16 (void) { + __asm__ __volatile__ ("plhz %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plhz_off32 (void) { + __asm__ __volatile__ ("plhz %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plhz_off64 (void) { + __asm__ __volatile__ ("plhz %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plha_off0 (void) { + __asm__ __volatile__ ("plha %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plha_off8 (void) { + __asm__ __volatile__ ("plha %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plha_off16 (void) { + __asm__ __volatile__ ("plha %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plha_off32 (void) { + __asm__ __volatile__ ("plha %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plha_off64 (void) { + __asm__ __volatile__ ("plha %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwz_off0 (void) { + __asm__ __volatile__ ("plwz %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwz_off8 (void) { + __asm__ __volatile__ ("plwz %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwz_off16 (void) { + __asm__ __volatile__ ("plwz %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwz_off32 (void) { + __asm__ __volatile__ ("plwz %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwz_off64 (void) { + __asm__ __volatile__ ("plwz %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwa_off0 (void) { + __asm__ __volatile__ ("plwa %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwa_off8 (void) { + __asm__ __volatile__ ("plwa %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwa_off16 (void) { + __asm__ __volatile__ ("plwa %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwa_off32 (void) { + __asm__ __volatile__ ("plwa %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plwa_off64 (void) { + __asm__ __volatile__ ("plwa %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pld_off0 (void) { + __asm__ __volatile__ ("pld %0, 0(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pld_off8 (void) { + __asm__ __volatile__ ("pld %0, 8(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pld_off16 (void) { + __asm__ __volatile__ ("pld %0, 16(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pld_off32 (void) { + __asm__ __volatile__ ("pld %0, 32(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pld_off64 (void) { + __asm__ __volatile__ ("pld %0, 64(%1), 0" : "=r" (rt) : "r" (ra) ); +} +static void test_pstb_off0 (void) { + __asm__ __volatile__ ("pstb %0, 0(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstb_off8 (void) { + __asm__ __volatile__ ("pstb %0, 8(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstb_off16 (void) { + __asm__ __volatile__ ("pstb %0, 16(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstb_off32 (void) { + __asm__ __volatile__ ("pstb %0, 32(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_psth_off0 (void) { + __asm__ __volatile__ ("psth %0, 0(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_psth_off8 (void) { + __asm__ __volatile__ ("psth %0, 8(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_psth_off16 (void) { + __asm__ __volatile__ ("psth %0, 16(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_psth_off32 (void) { + __asm__ __volatile__ ("psth %0, 32(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstw_off0 (void) { + __asm__ __volatile__ ("pstw %0, 0(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstw_off8 (void) { + __asm__ __volatile__ ("pstw %0, 8(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstw_off16 (void) { + __asm__ __volatile__ ("pstw %0, 16(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstw_off32 (void) { + __asm__ __volatile__ ("pstw %0, 32(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstd_off0 (void) { + __asm__ __volatile__ ("pstd %0, 0(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstd_off8 (void) { + __asm__ __volatile__ ("pstd %0, 8(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstd_off16 (void) { + __asm__ __volatile__ ("pstd %0, 16(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_pstd_off32 (void) { + __asm__ __volatile__ ("pstd %0, 32(%1), 0" :: "r" (rs), "r" (ra) ); +} +static void test_paddi_0 (void) { + __asm__ __volatile__ ("paddi %0, %1, 0, 0" : "=r" (rt) : "r" (ra) ); +} +static void test_paddi_12 (void) { + __asm__ __volatile__ ("paddi %0, %1, 12, 0" : "=r" (rt) : "r" (ra) ); +} +static void test_paddi_48 (void) { + __asm__ __volatile__ ("paddi %0, %1, 48, 0" : "=r" (rt) : "r" (ra) ); +} +static void test_paddi_98 (void) { + __asm__ __volatile__ ("paddi %0, %1, 98, 0" : "=r" (rt) : "r" (ra) ); +} +static void test_plq_off0 (void) { + __asm__ __volatile__ ("plq 26, 0(%0), 0" :: "r" (ra) ); +} +static void test_plq_off8 (void) { + __asm__ __volatile__ ("plq 26, 8(%0), 0" :: "r" (ra) ); +} +static void test_plq_off16 (void) { + __asm__ __volatile__ ("plq 26, 16(%0), 0" :: "r" (ra) ); +} +static void test_plq_off32 (void) { + __asm__ __volatile__ ("plq 26, 32(%0), 0" :: "r" (ra) ); +} +static void test_plq_off48 (void) { + __asm__ __volatile__ ("plq 26, 48(%0), 0" :: "r" (ra) ); +} +static void test_plq_off64 (void) { + __asm__ __volatile__ ("plq 26, 64(%0), 0" :: "r" (ra) ); +} +static void test_pstq_off0 (void) { + __asm__ __volatile__ ("pstq 24, 0(%0), 0" :: "r" (ra) ); +} +static void test_pstq_off8 (void) { + __asm__ __volatile__ ("pstq 24, 8(%0), 0" :: "r" (ra) ); +} +static void test_pstq_off16 (void) { + __asm__ __volatile__ ("pstq 24, 16(%0), 0" :: "r" (ra) ); +} +static void test_pstq_off32 (void) { + __asm__ __volatile__ ("pstq 24, 32(%0), 0" :: "r" (ra) ); +} +static void test_pstq_off64 (void) { + __asm__ __volatile__ ("pstq 24, 64(%0), 0" :: "r" (ra) ); +} + +static test_list_t testgroup_generic[] = { + { &test_paddi_0, "paddi 0", "RT,RA,SI,R"}, /* bcwp */ + { &test_paddi_12, "paddi 12", "RT,RA,SI,R"}, /* bcwp */ + { &test_paddi_48, "paddi 48", "RT,RA,SI,R"}, /* bcwp */ + { &test_paddi_98, "paddi 98", "RT,RA,SI,R"}, /* bcwp */ + { &test_plbz_off0, "plbz off0", "RT,D(RA),R"}, /* bcwp */ + { &test_plbz_off8, "plbz off8", "RT,D(RA),R"}, /* bcwp */ + { &test_plbz_off16, "plbz off16", "RT,D(RA),R"}, /* bcwp */ + { &test_plbz_off32, "plbz off32", "RT,D(RA),R"}, /* bcwp */ + { &test_plbz_off64, "plbz off64", "RT,D(RA),R"}, /* bcwp */ + { &test_pld_off0, "pld off0", "RT,D(RA),R"}, /* bcwp */ + { &test_pld_off8, "pld off8", "RT,D(RA),R"}, /* bcwp */ + { &test_pld_off16, "pld off16", "RT,D(RA),R"}, /* bcwp */ + { &test_pld_off32, "pld off32", "RT,D(RA),R"}, /* bcwp */ + { &test_pld_off64, "pld off64", "RT,D(RA),R"}, /* bcwp */ + { &test_plha_off0, "plha off0", "RT,D(RA),R"}, /* bcwp */ + { &test_plha_off8, "plha off8", "RT,D(RA),R"}, /* bcwp */ + { &test_plha_off16, "plha off16", "RT,D(RA),R"}, /* bcwp */ + { &test_plha_off32, "plha off32", "RT,D(RA),R"}, /* bcwp */ + { &test_plha_off64, "plha off64", "RT,D(RA),R"}, /* bcwp */ + { &test_plhz_off0, "plhz off0", "RT,D(RA),R"}, /* bcwp */ + { &test_plhz_off8, "plhz off8", "RT,D(RA),R"}, /* bcwp */ + { &test_plhz_off16, "plhz off16", "RT,D(RA),R"}, /* bcwp */ + { &test_plhz_off32, "plhz off32", "RT,D(RA),R"}, /* bcwp */ + { &test_plhz_off64, "plhz off64", "RT,D(RA),R"}, /* bcwp */ + { &test_plq_off0, "plq off0", "RTp,D(RA),R"}, /* bcwp */ + { &test_plq_off8, "plq off8", "RTp,D(RA),R"}, /* bcwp */ + { &test_plq_off16, "plq off16", "RTp,D(RA),R"}, /* bcwp */ + { &test_plq_off32, "plq off32", "RTp,D(RA),R"}, /* bcwp */ + { &test_plq_off48, "plq off48", "RTp,D(RA),R"}, /* bcwp */ + { &test_plq_off64, "plq off64", "RTp,D(RA),R"}, /* bcwp */ + { &test_plwa_off0, "plwa off0", "RT,D(RA),R"}, /* bcwp */ + { &test_plwa_off8, "plwa off8", "RT,D(RA),R"}, /* bcwp */ + { &test_plwa_off16, "plwa off16", "RT,D(RA),R"}, /* bcwp */ + { &test_plwa_off32, "plwa off32", "RT,D(RA),R"}, /* bcwp */ + { &test_plwa_off64, "plwa off64", "RT,D(RA),R"}, /* bcwp */ + { &test_plwz_off0, "plwz off0", "RT,D(RA),R"}, /* bcwp */ + { &test_plwz_off8, "plwz off8", "RT,D(RA),R"}, /* bcwp */ + { &test_plwz_off16, "plwz off16", "RT,D(RA),R"}, /* bcwp */ + { &test_plwz_off32, "plwz off32", "RT,D(RA),R"}, /* bcwp */ + { &test_plwz_off64, "plwz off64", "RT,D(RA),R"}, /* bcwp */ + { &test_pstb_off0, "pstb off0", "RS,D(RA),R"}, /* bcwp */ + { &test_pstb_off8, "pstb off8", "RS,D(RA),R"}, /* bcwp */ + { &test_pstb_off16, "pstb off16", "RS,D(RA),R"}, /* bcwp */ + { &test_pstb_off32, "pstb off32", "RS,D(RA),R"}, /* bcwp */ + { &test_pstd_off0, "pstd off0", "RS,D(RA),R"}, /* bcwp */ + { &test_pstd_off8, "pstd off8", "RS,D(RA),R"}, /* bcwp */ + { &test_pstd_off16, "pstd off16", "RS,D(RA),R"}, /* bcwp */ + { &test_pstd_off32, "pstd off32", "RS,D(RA),R"}, /* bcwp */ + { &test_psth_off0, "psth off0", "RS,D(RA),R"}, /* bcwp */ + { &test_psth_off8, "psth off8", "RS,D(RA),R"}, /* bcwp */ + { &test_psth_off16, "psth off16", "RS,D(RA),R"}, /* bcwp */ + { &test_psth_off32, "psth off32", "RS,D(RA),R"}, /* bcwp */ + { &test_pstq_off0, "pstq off0", "RSp,D(RA),R"}, /* bcwp */ + { &test_pstq_off8, "pstq off8", "RSp,D(RA),R"}, /* bcwp */ + { &test_pstq_off16, "pstq off16", "RSp,D(RA),R"}, /* bcwp */ + { &test_pstq_off32, "pstq off32", "RSp,D(RA),R"}, /* bcwp */ + { &test_pstq_off64, "pstq off64", "RSp,D(RA),R"}, /* bcwp */ + { &test_pstw_off0, "pstw off0", "RS,D(RA),R"}, /* bcwp */ + { &test_pstw_off8, "pstw off8", "RS,D(RA),R"}, /* bcwp */ + { &test_pstw_off16, "pstw off16", "RS,D(RA),R"}, /* bcwp */ + { &test_pstw_off32, "pstw off32", "RS,D(RA),R"}, /* bcwp */ + { NULL, NULL }, +}; + +/* Allow skipping of tests. */ +unsigned long test_count=0xffff; +unsigned long skip_count=0; +unsigned long setup_only=0; + +/* Set up a setjmp/longjmp to gently handle our SIGILLs and SIGSEGVs. */ +static jmp_buf mybuf; + +/* This (testfunction_generic) is meant to handle all of the instruction + variations. The helpers set up the register and iterator values + as is appropriate for the instruction being tested. */ +static void testfunction_generic (const char* instruction_name, + test_func_t test_function, + unsigned int ignore_flags, + char * cur_form) { + + identify_form_components (instruction_name , cur_form); + debug_show_form (instruction_name, cur_form); + set_up_iterators (); + debug_show_iter_ranges (); + initialize_buffer (0); + debug_dump_buffer (); + + for (vrai = 0; vrai < a_iters ; vrai+=a_inc) { + for (vrbi = 0; vrbi < b_iters ; vrbi+=b_inc) { + for (vrci = 0; vrci < c_iters ; vrci+=c_inc) { + for (vrmi = 0; (vrmi < m_iters) ; vrmi+=m_inc) { + CHECK_OVERRIDES + debug_show_current_iteration (); + // Be sure to initialize the target registers first. + initialize_target_registers (); + initialize_source_registers (); + printf ("%s", instruction_name); + print_register_header (); + printf( " =>"); fflush (stdout); + if (!setup_only) { + if (enable_setjmp) { + if ( setjmp ( mybuf ) ) { + printf("signal tripped. (FIXME)\n"); + continue; + } + } + (*test_function) (); + } + print_register_footer (); + print_result_buffer (); + printf ("\n"); + } + } + } + } +} + +void mykillhandler ( int x ) { longjmp (mybuf, 1); } +void mysegvhandler ( int x ) { longjmp (mybuf, 1); } + +static void do_tests ( void ) +{ + int groupcount; + char * cur_form; + test_group_t group_function = &testfunction_generic; + test_list_t *tests = testgroup_generic; + + struct sigaction kill_action, segv_action; + struct sigaction old_kill_action, old_segv_action; + if (enable_setjmp) { + kill_action.sa_handler = mykillhandler; + segv_action.sa_handler = mysegvhandler; + sigemptyset ( &kill_action.sa_mask ); + sigemptyset ( &segv_action.sa_mask ); + kill_action.sa_flags = SA_NODEFER; + segv_action.sa_flags = SA_NODEFER; + sigaction ( SIGILL, &kill_action, &old_kill_action); + sigaction ( SIGSEGV, &segv_action, &old_segv_action); + } + + for (groupcount = 0; tests[groupcount].name != NULL; groupcount++) { + cur_form = strdup(tests[groupcount].form); + current_test = tests[groupcount]; + if (groupcount < skip_count) continue; + if (verbose) printf("Test #%d ,", groupcount); + if (verbose > 1) printf(" instruction %s (v=%d)", current_test.name, verbose); + (*group_function) (current_test.name, current_test.func, 0, cur_form ); + printf ("\n"); + if (groupcount >= (skip_count+test_count)) break; + } + if (debug_show_labels) printf("\n"); + printf ("All done. Tested %d different instruction groups\n", groupcount); +} + +static void usage (void) +{ + fprintf(stderr, + "Usage: test_isa_XXX [OPTIONS]\n" + "\t-h: display this help and exit\n" + "\t-v: increase verbosity\n" + "\t-a <foo> : limit number of a-iterations to <foo>\n" + "\t-b <foo> : limit number of b-iterations to <foo>\n" + "\t-c <foo> : limit number of c-iterations to <foo>\n" + "\t-n <foo> : limit to this number of tests.\n" + "\t-r <foo>: run only test # <foo> \n" + "\t\n" + "\t-j :enable setjmp to recover from illegal insns. \n" + "\t-m :(dev only?) lock VRM value to zero.\n" + "\t-z :(dev only?) lock MC value to zero.\n" + "\t-p :(dev only?) disable prefix instructions\n" + "\t-s <foo>: skip <foo> tests \n" + "\t-c <foo>: stop after running <foo> # of tests \n" + "\t-f : Do the test setup but do not actually execute the test instruction. \n" + ); +} + +int main (int argc, char **argv) +{ + int c; + while ((c = getopt(argc, argv, "dhjvmpfzs:a:b:c:n:r:")) != -1) { + switch (c) { + case 'h': + usage(); + return 0; + + case 'v': + verbose++; + break; + + /* Options related to limiting the test iterations. */ + case 'a': + a_limit=atoi (optarg); + printf ("limiting a-iters to %ld.\n", a_limit); + break; + case 'b': + b_limit=atoi (optarg); + printf ("limiting b-iters to %ld.\n", b_limit); + break; + case 'c': + c_limit=atoi (optarg); + printf ("limiting c-iters to %ld.\n", c_limit); + break; + case 'n': // run this number of tests. + test_count=atoi (optarg); + printf ("limiting to %ld tests\n", test_count); + break; + case 'r': // run just test #<foo>. + skip_count=atoi (optarg); + test_count=0; + if (verbose) printf("Running only test number %ld\n", skip_count); + break; + case 's': // skip this number of tests. + skip_count=atoi (optarg); + printf ("skipping %ld tests\n", skip_count); + break; + + /* debug options. */ + case 'd': + dump_tables=1; + printf("DEBUG:dump_tables.\n"); + break; + case 'f': + setup_only=1; + printf("DEBUG:setup_only.\n"); + break; + case 'j': + enable_setjmp=1; + printf ("DEBUG:setjmp enabled.\n"); + break; + case 'm': + vrm_override=1; + printf ("DEBUG:vrm override enabled.\n"); + break; + case 'p': + prefix_override=1; + printf ("DEBUG:prefix override enabled.\n"); + break; + case 'z': + mc_override=1; + printf ("DEBUG:MC override enabled.\n"); + break; + default: + usage(); + fprintf(stderr, "Unknown argument: '%c'\n", c); + } + } + + generic_prologue (); + build_vsx_table (); + build_args_table (); + build_float_vsx_tables (); + + if (dump_tables) { + dump_float_vsx_tables (); + dump_vsxargs (); + } + + do_tests (); + + return 0; +} + +#else // HAS_ISA_3_1 +int main (int argc, char **argv) +{ + printf("NO ISA 3.1 SUPPORT\n"); + return 0; +} +#endif diff --git a/none/tests/ppc64/test_isa_3_1_RT.stderr.exp b/none/tests/ppc64/test_isa_3_1_RT.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_RT.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/ppc64/test_isa_3_1_RT.stdout.exp b/none/tests/ppc64/test_isa_3_1_RT.stdout.exp new file mode 100644 index 0000000000..4ebe7e162a --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_RT.stdout.exp @@ -0,0 +1,148 @@ +paddi 0 102030405060708 => 102030405060708 +paddi 0 a5b4c3d2e1f00918 => a5b4c3d2e1f00918 +paddi 0 fff7fffafff3fff1 => fff7fffafff3fff1 +paddi 0 7ff7000100030005 => 7ff7000100030005 +paddi 0 ffe7111022203330 => ffe7111022203330 +paddi 0 0 => 0 + +paddi 12 102030405060708 => 102030405060714 +paddi 12 a5b4c3d2e1f00918 => a5b4c3d2e1f00924 +paddi 12 fff7fffafff3fff1 => fff7fffafff3fffd +paddi 12 7ff7000100030005 => 7ff7000100030011 +paddi 12 ffe7111022203330 => ffe711102220333c +paddi 12 0 => c + +paddi 48 102030405060708 => 102030405060738 +paddi 48 a5b4c3d2e1f00918 => a5b4c3d2e1f00948 +paddi 48 fff7fffafff3fff1 => fff7fffafff40021 +paddi 48 7ff7000100030005 => 7ff7000100030035 +paddi 48 ffe7111022203330 => ffe7111022203360 +paddi 48 0 => 30 + +paddi 98 102030405060708 => 10203040506076a +paddi 98 a5b4c3d2e1f00918 => a5b4c3d2e1f0097a +paddi 98 fff7fffafff3fff1 => fff7fffafff40053 +paddi 98 7ff7000100030005 => 7ff7000100030067 +paddi 98 ffe7111022203330 => ffe7111022203392 +paddi 98 0 => 62 + +plbz off0 (&buffer) => 59 + +plbz off8 (&buffer) => 7 + +plbz off16 (&buffer) => 0 + +plbz off32 (&buffer) => 5 + +plbz off64 (&buffer) => 88 + +pld off0 (&buffer) => 3fe00094e0007359 + +pld off8 (&buffer) => 7ff7020304057607 + +pld off16 (&buffer) => 7ff0000000007000 + +pld off32 (&buffer) => 5a05a05a05a07a05 + +pld off64 (&buffer) => ffeeddccbbaa7988 + +plha off0 (&buffer) => 7359 + +plha off8 (&buffer) => 7607 + +plha off16 (&buffer) => 7000 + +plha off32 (&buffer) => 7a05 + +plha off64 (&buffer) => 7988 + +plhz off0 (&buffer) => 7359 + +plhz off8 (&buffer) => 7607 + +plhz off16 (&buffer) => 7000 + +plhz off32 (&buffer) => 7a05 + +plhz off64 (&buffer) => 7988 + +plq off0 (&buffer) => 3fe00094e0007359 7ff7020304057607 + +plq off8 (&buffer) => 7ff7020304057607 7ff0000000007000 + +plq off16 (&buffer) => 7ff0000000007000 7f0000007f007000 + +plq off32 (&buffer) => 5a05a05a05a07a05 102030405067708 + +plq off48 (&buffer) => fedcba9876547210 123456789ab7def + +plq off64 (&buffer) => ffeeddccbbaa7988 1112111211127112 + +plwa off0 (&buffer) => ffffffffe0007359 + +plwa off8 (&buffer) => 4057607 + +plwa off16 (&buffer) => 7000 + +plwa off32 (&buffer) => 5a07a05 + +plwa off64 (&buffer) => ffffffffbbaa7988 + +plwz off0 (&buffer) => e0007359 + +plwz off8 (&buffer) => 4057607 + +plwz off16 (&buffer) => 7000 + +plwz off32 (&buffer) => 5a07a05 + +plwz off64 (&buffer) => bbaa7988 + +pstb off0 (&buffer) 102030405060708 => [3fe00094e0007308 - - - - - - - ] + +pstb off8 (&buffer) 102030405060708 => [ - 7ff7020304057608 - - - - - - ] + +pstb off16 (&buffer) 102030405060708 => [ - - 7ff0000000007008 - - - - - ] + +pstb off32 (&buffer) 102030405060708 => [ - - - - 5a05a05a05a07a08 - - - ] + +pstd off0 (&buffer) 102030405060708 => [0102030405060708 - - - - - - - ] + +pstd off8 (&buffer) 102030405060708 => [ - 0102030405060708 - - - - - - ] + +pstd off16 (&buffer) 102030405060708 => [ - - 0102030405060708 - - - - - ] + +pstd off32 (&buffer) 102030405060708 => [ - - - - 0102030405060708 - - - ] + +psth off0 (&buffer) 102030405060708 => [3fe00094e0000708 - - - - - - - ] + +psth off8 (&buffer) 102030405060708 => [ - 7ff7020304050708 - - - - - - ] + +psth off16 (&buffer) 102030405060708 => [ - - 7ff0000000000708 - - - - - ] + +psth off32 (&buffer) 102030405060708 => [ - - - - 5a05a05a05a00708 - - - ] + +pstq off0 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [0102030405060708 a5b4c3d2e1f00918 - - - - - - ] +pstq off0 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [0102030405060708 a5b4c3d2e1f00918 - - - - - - ] + +pstq off8 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - 0102030405060708 a5b4c3d2e1f00918 - - - - - ] +pstq off8 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - 0102030405060708 a5b4c3d2e1f00918 - - - - - ] + +pstq off16 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - - 0102030405060708 a5b4c3d2e1f00918 - - - - ] +pstq off16 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - - 0102030405060708 a5b4c3d2e1f00918 - - - - ] + +pstq off32 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - - - - 0102030405060708 a5b4c3d2e1f00918 - - ] +pstq off32 (&buffer) 102030405060708 a5b4c3d2e1f00918 => [ - - - - 0102030405060708 a5b4c3d2e1f00918 - - ] + +pstq off64 (&buffer) 102030405060708 a5b4c3d2e1f00918 => +pstq off64 (&buffer) 102030405060708 a5b4c3d2e1f00918 => + +pstw off0 (&buffer) 102030405060708 => [3fe0009405060708 - - - - - - - ] + +pstw off8 (&buffer) 102030405060708 => [ - 7ff7020305060708 - - - - - - ] + +pstw off16 (&buffer) 102030405060708 => [ - - 7ff0000005060708 - - - - - ] + +pstw off32 (&buffer) 102030405060708 => [ - - - - 5a05a05a05060708 - - - ] + +All done. Tested 61 different instruction groups diff --git a/none/tests/ppc64/test_isa_3_1_XT.c b/none/tests/ppc64/test_isa_3_1_XT.c new file mode 100644 index 0000000000..dfe11c3c6c --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_XT.c @@ -0,0 +1,479 @@ +/* + * Valgrind testcase for PowerPC ISA 3.1 + * + * Copyright (C) 2019-2020 Will Schmidt <wil...@vn...> + * + * 64bit build: + * gcc -Winline -Wall -g -O -mregnames -maltivec -m64 + */ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <altivec.h> +#include <malloc.h> + +#include <string.h> +#include <signal.h> +#include <setjmp.h> + +/* Condition Register fields. + These are used to capture the condition register values immediately after + the instruction under test is executed. This is done to help prevent other + test overhead (switch statements, result compares, etc) from disturbing + the test case results. */ +unsigned long current_cr; +unsigned long current_fpscr; + + +struct test_list_t current_test; + +#include "isa_3_1_helpers.h" + +#ifdef HAS_ISA_3_1 + +static void test_plfd_64 (void) { + __asm__ __volatile__ ("plfd 28, 64(%0), 0" :: "r" (ra) ); +} +static void test_plfd_32 (void) { + __asm__ __volatile__ ("plfd 28, 32(%0), 0" :: "r" (ra) ); +} +static void test_plfd_16 (void) { + __asm__ __volatile__ ("plfd 28, 16(%0), 0" :: "r" (ra) ); +} +static void test_plfd_8 (void) { + __asm__ __volatile__ ("plfd 28, 8(%0), 0" :: "r" (ra) ); +} +static void test_plfd_4 (void) { + __asm__ __volatile__ ("plfd 28, 4(%0), 0" :: "r" (ra) ); +} +static void test_plfd_0 (void) { + __asm__ __volatile__ ("plfd 28, 0(%0), 0" :: "r" (ra) ); +} +static void test_plfs_64 (void) { + __asm__ __volatile__ ("plfs 28, 64(%0), 0" :: "r" (ra) ); +} +static void test_plfs_32 (void) { + __asm__ __volatile__ ("plfs 28, 32(%0), 0" :: "r" (ra) ); +} +static void test_plfs_16 (void) { + __asm__ __volatile__ ("plfs 28, 16(%0), 0" :: "r" (ra) ); +} +static void test_plfs_8 (void) { + __asm__ __volatile__ ("plfs 28, 8(%0), 0" :: "r" (ra) ); +} +static void test_plfs_4 (void) { + __asm__ __volatile__ ("plfs 28, 4(%0), 0" :: "r" (ra) ); +} +static void test_plfs_0 (void) { + __asm__ __volatile__ ("plfs 28, 0(%0), 0" :: "r" (ra) ); +} +static void test_pstfd_32 (void) { + __asm__ __volatile__ ("pstfd 26, 32(%0), 0" :: "r" (ra) ); +} +static void test_pstfd_16 (void) { + __asm__ __volatile__ ("pstfd 26, 16(%0), 0" :: "r" (ra) ); +} +static void test_pstfd_8 (void) { + __asm__ __volatile__ ("pstfd 26, 8(%0), 0" :: "r" (ra) ); +} +static void test_pstfd_4 (void) { + __asm__ __volatile__ ("pstfd 26, 4(%0), 0" :: "r" (ra) ); +} +static void test_pstfd_0 (void) { + __asm__ __volatile__ ("pstfd 26, 0(%0), 0" :: "r" (ra) ); +} +static void test_pstfs_32 (void) { + __asm__ __volatile__ ("pstfs 26, 32(%0), 0" :: "r" (ra) ); +} +static void test_pstfs_16 (void) { + __asm__ __volatile__ ("pstfs 26, 16(%0), 0" :: "r" (ra) ); +} +static void test_pstfs_8 (void) { + __asm__ __volatile__ ("pstfs 26, 8(%0), 0" :: "r" (ra) ); +} +static void test_pstfs_4 (void) { + __asm__ __volatile__ ("pstfs 26, 4(%0), 0" :: "r" (ra) ); +} +static void test_pstfs_0 (void) { + __asm__ __volatile__ ("pstfs 26, 0(%0), 0" :: "r" (ra) ); +} +static void test_plxsd_64 (void) { + __asm__ __volatile__ ("plxsd %0, 64(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxsd_32 (void) { + __asm__ __volatile__ ("plxsd %0, 32(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxsd_16 (void) { + __asm__ __volatile__ ("plxsd %0, 16(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxsd_8 (void) { + __asm__ __volatile__ ("plxsd %0, 8(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxsd_4 (void) { + __asm__ __volatile__ ("plxsd %0, 4(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxsd_0 (void) { + __asm__ __volatile__ ("plxsd %0, 0(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_64 (void) { + __asm__ __volatile__ ("plxssp %0, 64(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_32 (void) { + __asm__ __volatile__ ("plxssp %0, 32(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_16 (void) { + __asm__ __volatile__ ("plxssp %0, 16(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_8 (void) { + __asm__ __volatile__ ("plxssp %0, 8(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_4 (void) { + __asm__ __volatile__ ("plxssp %0, 4(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxssp_0 (void) { + __asm__ __volatile__ ("plxssp %0, 0(%1), 0" : "=v" (vrt) : "r" (ra) ); +} +static void test_plxv_16_0 (void) { + __asm__ __volatile__ ("plxv %x0, 16(%1), 0" : "=wa" (vec_xt) : "r" (ra) ); +} +static void test_plxv_8_0 (void) { + __asm__ __volatile__ ("plxv %x0, 8(%1), 0" : "=wa" (vec_xt) : "r" (ra) ); +} +static void test_plxv_4_0 (void) { + __asm__ __volatile__ ("plxv %x0, 4(%1), 0" : "=wa" (vec_xt) : "r" (ra) ); +} +static void test_plxv_0_0 (void) { + __asm__ __volatile__ ("plxv %x0, 0(%1), 0" : "=wa" (vec_xt) : "r" (ra) ); +} +static void test_pstxsd_64 (void) { + __asm__ __volatile__ ("pstxsd 22, 64(%0), 0" :: "r" (ra) ); +} +static void test_pstxsd_32 (void) { + __asm__ __volatile__ ("pstxsd 22, 32(%0), 0" :: "r" (ra) ); +} +static void test_pstxsd_16 (void) { + __asm__ __volatile__ ("pstxsd 22, 16(%0), 0" :: "r" (ra) ); +} +static void test_pstxsd_8 (void) { + __asm__ __volatile__ ("pstxsd 22, 8(%0), 0" :: "r" (ra) ); +} +static void test_pstxsd_4 (void) { + __asm__ __volatile__ ("pstxsd 22, 4(%0), 0" :: "r" (ra) ); +} +static void test_pstxsd_0 (void) { + __asm__ __volatile__ ("pstxsd 22, 0(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_64 (void) { + __asm__ __volatile__ ("pstxssp 22, 64(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_32 (void) { + __asm__ __volatile__ ("pstxssp 22, 32(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_16 (void) { + __asm__ __volatile__ ("pstxssp 22, 16(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_8 (void) { + __asm__ __volatile__ ("pstxssp 22, 8(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_4 (void) { + __asm__ __volatile__ ("pstxssp 22, 4(%0), 0" :: "r" (ra) ); +} +static void test_pstxssp_0 (void) { + __asm__ __volatile__ ("pstxssp 22, 0(%0), 0" :: "r" (ra) ); +} +static void test_pstxv_16 (void) { + __asm__ __volatile__ ("pstxv %x0, 16(%1), 0" :: "wa" (vec_xs), "r" (ra) ); +} +static void test_pstxv_8 (void) { + __asm__ __volatile__ ("pstxv %x0, 8(%1), 0" :: "wa" (vec_xs), "r" (ra) ); +} +static void test_pstxv_4 (void) { + __asm__ __volatile__ ("pstxv %x0, 4(%1), 0" :: "wa" (vec_xs), "r" (ra) ); +} +static void test_pstxv_0 (void) { + __asm__ __volatile__ ("pstxv %x0, 0(%1), 0" :: "wa" (vec_xs), "r" (ra) ); +} + +static test_list_t testgroup_generic[] = { + { &test_plfd_0, "plfd 0", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfd_4, "plfd 4", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfd_8, "plfd 8", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfd_16, "plfd 16", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfd_32, "plfd 32", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfd_64, "plfd 64", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_0, "plfs 0", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_4, "plfs 4", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_8, "plfs 8", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_16, "plfs 16", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_32, "plfs 32", "FRT,D(RA),R"}, /* bcwp */ + { &test_plfs_64, "plfs 64", "FRT,D(RA),R"}, /* bcwp */ + { &test_plxsd_0, "plxsd 0", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxsd_4, "plxsd 4", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxsd_8, "plxsd 8", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxsd_16, "plxsd 16", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxsd_32, "plxsd 32", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxsd_64, "plxsd 64", "VRT,D(RA),R", 0b00110000}, /* bcwp */ + { &test_plxssp_0, "plxssp 0", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxssp_4, "plxssp 4", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxssp_8, "plxssp 8", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxssp_16, "plxssp 16", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxssp_32, "plxssp 32", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxssp_64, "plxssp 64", "VRT,D(RA),R", 0b00001111}, /* bcwp */ + { &test_plxv_0_0, "plxv 0_0", "XT,D(RA),R"}, /* bcwp */ + { &test_plxv_4_0, "plxv 4_0", "XT,D(RA),R"}, /* bcwp */ + { &test_plxv_8_0, "plxv 8_0", "XT,D(RA),R"}, /* bcwp */ + { &test_plxv_16_0, "plxv 16_0", "XT,D(RA),R"}, /* bcwp */ + { &test_pstfd_0, "pstfd 0", "FRS,D(RA),R", 0b00110000}, /* bcwp */ + { &test_pstfd_4, "pstfd 4", "FRS,D(RA),R", 0b00110000}, /* bcwp */ + { &test_pstfd_8, "pstfd 8", "FRS,D(RA),R", 0b00110000}, /* bcwp */ + { &test_pstfd_16, "pstfd 16", "FRS,D(RA),R", 0b00110000}, /* bcwp */ + { &test_pstfd_32, "pstfd 32", "FRS,D(RA),R", 0b00110000}, /* bcwp */ + { &test_pstfs_0, "pstfs 0", "FRS,D(RA),R", 0b00001111}, /* bcwp */ + { &test_pstfs_4, "pstfs 4", "FRS,D(RA),R", 0b00001111}, /* bcwp */ + { &test_pstfs_8, "pstfs 8", "FRS,D(RA),R", 0b00001111}, /* bcwp */ + { &test_pstfs_16, "pstfs 16", "FRS,D(RA),R", 0b00001111}, /* bcwp */ + { &test_pstfs_32, "pstfs 32", "FRS,D(RA),R", 0b00001111}, /* bcwp */ + { &test_pstxsd_0, "pstxsd 0", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxsd_4, "pstxsd 4", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxsd_8, "pstxsd 8", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxsd_16, "pstxsd 16", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxsd_32, "pstxsd 32", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxsd_64, "pstxsd 64", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_0, "pstxssp 0", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_4, "pstxssp 4", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_8, "pstxssp 8", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_16, "pstxssp 16", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_32, "pstxssp 32", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxssp_64, "pstxssp 64", "VRS,D(RA),R"}, /* bcwp */ + { &test_pstxv_0, "pstxv 0", "XS,D(RA),R"}, /* bcwp */ + { &test_pstxv_4, "pstxv 4", "XS,D(RA),R"}, /* bcwp */ + { &test_pstxv_8, "pstxv 8", "XS,D(RA),R"}, /* bcwp */ + { &test_pstxv_16, "pstxv 16", "XS,D(RA),R"}, /* bcwp */ + { NULL, NULL }, +}; + +/* Allow skipping of tests. */ +unsigned long test_count=0xffff; +unsigned long skip_count=0; +unsigned long setup_only=0; + +/* Set up a setjmp/longjmp to gently handle our SIGILLs and SIGSEGVs. */ +static jmp_buf mybuf; + +/* This (testfunction_generic) is meant to handle all of the instruction + variations. The helpers set up the register and iterator values + as is appropriate for the instruction being tested. */ +static void testfunction_generic (const char* instruction_name, + test_func_t test_function, + unsigned int ignore_flags, + char * cur_form) { + + identify_form_components (instruction_name , cur_form); + debug_show_form (instruction_name, cur_form); + set_up_iterators (); + debug_show_iter_ranges (); + initialize_buffer (0); + debug_dump_buffer (); + + for (vrai = 0; vrai < a_iters ; vrai+=a_inc) { + for (vrbi = 0; vrbi < b_iters ; vrbi+=b_inc) { + for (vrci = 0; vrci < c_iters ; vrci+=c_inc) { + for (vrmi = 0; (vrmi < m_iters) ; vrmi+=m_inc) { + CHECK_OVERRIDES + debug_show_current_iteration (); + // Be sure to initialize the target registers first. + initialize_target_registers (); + initialize_source_registers (); + printf ("%s", instruction_name); + print_register_header (); + printf( " =>"); fflush (stdout); + if (!setup_only) { + if (enable_setjmp) { + if ( setjmp ( mybuf ) ) { + printf("signal tripped. (FIXME)\n"); + continue; + } + } + (*test_function) (); + } + print_register_footer (); + print_result_buffer (); + printf ("\n"); + } + } + } + } +} + +void mykillhandler ( int x ) { longjmp (mybuf, 1); } +void mysegvhandler ( int x ) { longjmp (mybuf, 1); } + +static void do_tests ( void ) +{ + int groupcount; + char * cur_form; + test_group_t group_function = &testfunction_generic; + test_list_t *tests = testgroup_generic; + + struct sigaction kill_action, segv_action; + struct sigaction old_kill_action, old_segv_action; + if (enable_setjmp) { + kill_action.sa_handler = mykillhandler; + segv_action.sa_handler = mysegvhandler; + sigemptyset ( &kill_action.sa_mask ); + sigemptyset ( &segv_action.sa_mask ); + kill_action.sa_flags = SA_NODEFER; + segv_action.sa_flags = SA_NODEFER; + sigaction ( SIGILL, &kill_action, &old_kill_action); + sigaction ( SIGSEGV, &segv_action, &old_segv_action); + } + + for (groupcount = 0; tests[groupcount].name != NULL; groupcount++) { + cur_form = strdup(tests[groupcount].form); + current_test = tests[groupcount]; + if (groupcount < skip_count) continue; + if (verbose) printf("Test #%d ,", groupcount); + if (verbose > 1) printf(" instruction %s (v=%d)", current_test.name, verbose); + (*group_function) (current_test.name, current_test.func, 0, cur_form ); + printf ("\n"); + if (groupcount >= (skip_count+test_count)) break; + } + if (debug_show_labels) printf("\n"); + printf ("All done. Tested %d different instruction groups\n", groupcount); +} + +static void usage (void) +{ + fprintf(stderr, + "Usage: test_isa_XXX [OPTIONS]\n" + "\t-h: display this help and exit\n" + "\t-v: increase verbosity\n" + "\t-a <foo> : limit number of a-iterations to <foo>\n" + "\t-b <foo> : limit number of b-iterations to <foo>\n" + "\t-c <foo> : limit number of c-iterations to <foo>\n" + "\t-n <foo> : limit to this number of tests.\n" + "\t-r <foo>: run only test # <foo> \n" + "\t\n" + "\t-j :enable setjmp to recover from illegal insns. \n" + "\t-m :(dev only?) lock VRM value to zero.\n" + "\t-z :(dev only?) lock MC value to zero.\n" + "\t-p :(dev only?) disable prefix instructions\n" + "\t-s <foo>: skip <foo> tests \n" + "\t-c <foo>: stop after running <foo> # of tests \n" + "\t-f : Do the test setup but do not actually execute the test instruction. \n" + ); +} + +int main (int argc, char **argv) +{ + int c; + while ((c = getopt(argc, argv, "dhjvmpfzs:a:b:c:n:r:")) != -1) { + switch (c) { + case 'h': + usage(); + return 0; + + case 'v': + verbose++; + break; + + /* Options related to limiting the test iterations. */ + case 'a': + a_limit=atoi (optarg); + printf ("limiting a-iters to %ld.\n", a_limit); + break; + case 'b': + b_limit=atoi (optarg); + printf ("limiting b-iters to %ld.\n", b_limit); + break; + case 'c': + c_limit=atoi (optarg); + printf ("limiting c-iters to %ld.\n", c_limit); + break; + case 'n': // run this number of tests. + test_count=atoi (optarg); + printf ("limiting to %ld tests\n", test_count); + break; + case 'r': // run just test #<foo>. + skip_count=atoi (optarg); + test_count=0; + if (verbose) printf("Running only test number %ld\n", skip_count); + break; + case 's': // skip this number of tests. + skip_count=atoi (optarg); + printf ("skipping %ld tests\n", skip_count); + break; + + /* debug options. */ + case 'd': + dump_tables=1; + printf("DEBUG:dump_tables.\n"); + break; + case 'f': + setup_only=1; + printf("DEBUG:setup_only.\n"); + break; + case 'j': + enable_setjmp=1; + printf ("DEBUG:setjmp enabled.\n"); + break; + case 'm': + vrm_override=1; + printf ("DEBUG:vrm override enabled.\n"); + break; + case 'p': + prefix_override=1; + printf ("DEBUG:prefix override enabled.\n"); + break; + case 'z': + mc_override=1; + printf ("DEBUG:MC override enabled.\n"); + break; + default: + usage(); + fprintf(stderr, "Unknown argument: '%c'\n", c); + } + } + + generic_prologue (); + build_vsx_table (); + build_args_table (); + build_float_vsx_tables (); + + if (dump_tables) { + dump_float_vsx_tables (); + dump_vsxargs (); + } + + do_tests (); + + return 0; +} + +#else // HAS_ISA_3_1 +int main (int argc, char **argv) +{ + printf("NO ISA 3.1 SUPPORT\n"); + return 0; +} +#endif diff --git a/none/tests/ppc64/test_isa_3_1_XT.stderr.exp b/none/tests/ppc64/test_isa_3_1_XT.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_XT.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/ppc64/test_isa_3_1_XT.stdout.exp b/none/tests/ppc64/test_isa_3_1_XT.stdout.exp new file mode 100644 index 0000000000..aec8e1270e --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_XT.stdout.exp @@ -0,0 +1,119 @@ +plfd 0 (&buffer) => 5.000710e-01 + +plfd 4 (&buffer) => 2.752739e-289 + +plfd 8 (&buffer) => nan + +plfd 16 (&buffer) => nan + +plfd 32 (&buffer) => 4.574798e+125 + +plfd 64 (&buffer) => -1.734010e+308 + +plfs 0 (&buffer) => -3.702336e+19 + +plfs 4 (&buffer) => 1.750018e+00 + +plfs 8 (&buffer) => 1.568827e-36 + +plfs 16 (&buffer) => 4.017803e-41 + +plfs 32 (&buffer) => 1.509115e-35 + +plfs 64 (&buffer) => -5.202476e-03 + +plxsd 0 (&buffer) => 3fe00094e0007359,0000000000000000 5.00070989e-01 +Zero + +plxsd 4 (&buffer) => 40576073fe00094,0000000000000000 2.75273943e-289 +Zero + +plxsd 8 (&buffer) => 7ff7020304057607,0000000000000000 NaN +Zero + +plxsd 16 (&buffer) => 7ff0000000007000,0000000000000000 NaN +Zero + +plxsd 32 (&buffer) => 5a05a05a05a07a05,0000000000000000 4.57479788e+125 +Zero + +plxsd 64 (&buffer) => ffeeddccbbaa7988,0000000000000000 -1.73401015e+308 +Zero + +plxssp 0 (&buffer) => c4000e6b20000000,0000000000000000 -5.12225e+02 1.08420e-19 +Zero +Zero + +plxssp 4 (&buffer) => 3ffc001280000000,0000000000000000 1.96875e+00 -Zero +Zero +Zero + +plxssp 8 (&buffer) => 3880aec0e0000000,0000000000000000 6.13607e-05 -3.68935e+19 +Zero +Zero + +plxssp 16 (&buffer) => 378c000000000000,0000000000000000 1.66893e-05 +Zero +Zero +Zero + +plxssp 32 (&buffer) => 38b40f40a0000000,0000000000000000 8.58591e-05 -1.08420e-19 +Zero +Zero + +plxssp 64 (&buffer) => bf754f3100000000,0000000000000000 -9.58240e-01 +Zero +Zero +Zero + +plxv 0_0 (&buffer) => 3fe00094e0007359 7ff7020304057607 + +plxv 4_0 (&buffer) => 40576073fe00094 70007ff70203 + +plxv 8_0 (&buffer) => 7ff7020304057607 7ff0000000007000 + +plxv 16_0 (&buffer) => 7ff0000000007000 7f0000007f007000 + +pstfd 0 (&buffer) 43dfe000003fe000 43eff000000ff000 => [ { 9.18734324e+18} 43dfe000003fe000 - - - - - - - ] +pstfd 0 (&buffer) 43eff000000ff000 43efefffffcff000 => [ { 1.84107153e+19} 43eff000000ff000 - - - - - - - ] + +pstfd 4 (&buffer) 43dfe000003fe000 43eff000000ff000 => [ { 1.77310647e-307} 003fe000e0007359 { NaN} 7ff7020343dfe000 - - - - - - ] +pstfd 4 (&buffer) 43eff000000ff000 43efefffffcff000 => [ { +Den} 000ff000e0007359 { NaN} 7ff7020343eff000 - - - - - - ] + +pstfd 8 (&buffer) 43dfe000003fe000 43eff000000ff000 => [ - { 9.18734324e+18} 43dfe000003fe000 - - - - - - ] +pstfd 8 (&buffer) 43eff000000ff000 43efefffffcff000 => [ - { 1.84107153e+19} 43eff000000ff000 - - - - - - ] + +pstfd 16 (&buffer) 43dfe000003fe000 43eff000000ff000 => [ - - { 9.18734324e+18} 43dfe000003fe000 - - - - - ] +pstfd 16 (&buffer) 43eff000000ff000 43efefffffcff000 => [ - - { 1.84107153e+19} 43eff000000ff000 - - - - - ] + +pstfd 32 (&buffer) 43dfe000003fe000 43eff000000ff000 => [ - - - - { 9.18734324e+18} 43dfe000003fe000 - - - ] +pstfd 32 (&buffer) 43eff000000ff000 43efefffffcff000 => [ - - - - { 1.84107153e+19} 43eff000000ff000 - - - ] + +pstfs 0 (&buffer) 000000005eff0000 000000005f7f8000 => [ ( 1.75002e+00 9.18734e+18) 3fe000945eff0000 - - - - - - - ] +pstfs 0 (&buffer) 000000005f7f8000 000000005f7f8000 => [ ( 1.75002e+00 1.84107e+19) 3fe000945f7f8000 - - - - - - - ] + +pstfs 4 (&buffer) 000000005eff0000 000000005f7f8000 => [ ( 9.18734e+18 -3.70234e+19) 5eff0000e0007359 - - - - - - - ] +pstfs 4 (&buffer) 000000005f7f8000 000000005f7f8000 => [ ( 1.84107e+19 -3.70234e+19) 5f7f8000e0007359 - - - - - - - ] + +pstfs 8 (&buffer) 000000005eff0000 000000005f7f8000 => [ - ( NaN 9.18734e+18) 7ff702035eff0000 - - - - - - ] +pstfs 8 (&buffer) 000000005f7f8000 000000005f7f8000 => [ - ( NaN 1.84107e+19) 7ff702035f7f8000 - - - - - - ] + +pstfs 16 (&buffer) 000000005eff0000 000000005f7f8000 => [ - - ( NaN 9.18734e+18) 7ff000005eff0000 - - - - - ] +pstfs 16 (&buffer) 000000005f7f8000 000000005f7f8000 => [ - - ( NaN 1.84107e+19) 7ff000005f7f8000 - - - - - ] + +pstfs 32 (&buffer) 000000005eff0000 000000005f7f8000 => [ - - - - ( 9.40312e+15 9.18734e+18) 5a05a05a5eff0000 - - - ] +pstfs 32 (&buffer) 000000005f7f8000 000000005f7f8000 => [ - - - - ( 9.40312e+15 1.84107e+19) 5a05a05a5f7f8000 - - - ] + +pstxsd 0 (&buffer) => [0000000000000000 - - - - - - - ] + +pstxsd 4 (&buffer) => [00000000e0007359 7ff7020300000000 - - - - - - ] + +pstxsd 8 (&buffer) => [ - 0000000000000000 - - - - - - ] + +pstxsd 16 (&buffer) => [ - - 0000000000000000 - - - - - ] + +pstxsd 32 (&buffer) => [ - - - - 0000000000000000 - - - ] + +pstxsd 64 (&buffer) => + +pstxssp 0 (&buffer) => [3fe0009400000000 - - - - - - - ] + +pstxssp 4 (&buffer) => [00000000e0007359 - - - - - - - ] + +pstxssp 8 (&buffer) => [ - 7ff7020300000000 - - - - - - ] + +pstxssp 16 (&buffer) => [ - - 7ff0000000000000 - - - - - ] + +pstxssp 32 (&buffer) => [ - - - - 5a05a05a00000000 - - - ] + +pstxssp 64 (&buffer) => + +pstxv 0 (&buffer) 7f800000ff800000,ff8000007f800000 => [7f800000ff800000 ff8000007f800000 - - - - - - ] + +pstxv 4 (&buffer) 7f800000ff800000,ff8000007f800000 => [ff800000e0007359 7f8000007f800000 7ff00000ff800000 - - - - - ] + +pstxv 8 (&buffer) 7f800000ff800000,ff8000007f800000 => [ - 7f800000ff800000 ff8000007f800000 - - - - - ] + +pstxv 16 (&buffer) 7f800000ff800000,ff8000007f800000 => [ - - 7f800000ff800000 ff8000007f800000 - - - - ] + +All done. Tested 54 different instruction groups |
|
From: Carl L. <ca...@so...> - 2020-09-22 16:49:51
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=2a88a98f5b69ac7cdd06e682b2158fd8a31399c9 commit 2a88a98f5b69ac7cdd06e682b2158fd8a31399c9 Author: Carl Love <ce...@us...> Date: Mon Sep 21 15:56:22 2020 -0500 valgrind isa 3.1 foundation header files and other common parts associated with the initial isa v3.1 support Diff: --- configure.ac | 22 +- none/tests/ppc64/Makefile.am | 27 +- none/tests/ppc64/isa_3_1_helpers.h | 112 ++ none/tests/ppc64/isa_3_1_register_defines.h | 50 + none/tests/ppc64/test_isa_3_1_AT.vgtest | 3 + none/tests/ppc64/test_isa_3_1_Misc.vgtest | 2 + none/tests/ppc64/test_isa_3_1_RT.vgtest | 2 + none/tests/ppc64/test_isa_3_1_VRT.vgtest | 2 + none/tests/ppc64/test_isa_3_1_XT.vgtest | 2 + none/tests/ppc64/test_isa_3_1_common.c | 2188 +++++++++++++++++++++++++++ tests/check_ppc64_auxv_cap | 4 +- 11 files changed, 2410 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 1a89d05e5e..085c98993e 100755 --- a/configure.ac +++ b/configure.ac @@ -1455,7 +1455,9 @@ AC_HWCAP_CONTAINS_FLAG([arch_2_05],[HWCAP_HAS_ISA_2_05]) AC_HWCAP_CONTAINS_FLAG([arch_2_06],[HWCAP_HAS_ISA_2_06]) AC_HWCAP_CONTAINS_FLAG([arch_2_07],[HWCAP_HAS_ISA_2_07]) AC_HWCAP_CONTAINS_FLAG([arch_3_00],[HWCAP_HAS_ISA_3_00]) +AC_HWCAP_CONTAINS_FLAG([arch_3_01],[HWCAP_HAS_ISA_3_1]) AC_HWCAP_CONTAINS_FLAG([htm],[HWCAP_HAS_HTM]) +AC_HWCAP_CONTAINS_FLAG([mma],[HWCAP_HAS_MMA]) # ISA Levels AM_CONDITIONAL(HAS_ISA_2_05, [test x$HWCAP_HAS_ISA_2_05 = xyes]) @@ -1624,7 +1626,7 @@ AM_CONDITIONAL(SUPPORTS_HTM, test x$ac_compiler_supports_htm = xyes \ -a x$ac_compiler_sees_htm_builtins = xyes \ -a x$HWCAP_HAS_HTM = xyes ) -# isa 3.0 checking +# isa 3.0 checking. (actually 3.0 or newer) AC_MSG_CHECKING([that assembler knows ISA 3.00 ]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -1638,9 +1640,27 @@ ac_asm_have_isa_3_00=no AC_MSG_RESULT([no]) ]) +# isa 3.01 checking +AC_MSG_CHECKING([that assembler knows ISA 3.1 ]) + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +]], [[ + __asm__ __volatile__("brh 1,2 "); +]])], [ +ac_asm_have_isa_3_1=yes +AC_MSG_RESULT([yes]) +], [ +ac_asm_have_isa_3_1=no +AC_MSG_RESULT([no]) +]) + + AM_CONDITIONAL(HAS_ISA_3_00, [test x$ac_asm_have_isa_3_00 = xyes \ -a x$HWCAP_HAS_ISA_3_00 = xyes]) +AM_CONDITIONAL(HAS_ISA_3_1, [test x$ac_asm_have_isa_3_1 = xyes \ + -a x$HWCAP_HAS_ISA_3_1 = xyes]) + # Check for pthread_create@GLIBC2.0 AC_MSG_CHECKING([for pthread_create@GLIBC2.0()]) diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am index 9bc0d0a764..a43e527fe6 100644 --- a/none/tests/ppc64/Makefile.am +++ b/none/tests/ppc64/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.tool-tests.am dist_noinst_SCRIPTS = filter_stderr -noinst_HEADERS = ppc64_helpers.h +noinst_HEADERS = ppc64_helpers.h isa_3_1_helpers.h EXTRA_DIST = \ jm-int.stderr.exp jm-int.stdout.exp jm-int.vgtest jm-int.stdout.exp-LE \ @@ -51,6 +51,11 @@ EXTRA_DIST = \ test_isa_3_0_other.stdout.exp-LE test_isa_3_0_other.vgtest \ subnormal_test.stderr.exp subnormal_test.stdout.exp \ subnormal_test.vgtest +# test_isa_3_1_RT.vgtest test_isa_3_1_RT.stderr.exp test_isa_3_1_RT.stdout.exp +# test_isa_3_1_XT.vgtest test_isa_3_1_XT.stderr.exp test_isa_3_1_XT.stdout.exp +# test_isa_3_1_VRT.vgtest test_isa_3_1_VRT.stderr.exp test_isa_3_1_VRT.stdout.exp +# test_isa_3_1_Misc.vgtest test_isa_3_1_Misc.stderr.exp test_isa_3_1_Misc.stdout.exp +# test_isa_3_1_AT.vgtest test_isa_3_1_AT.stderr.exp test_isa_3_1_AT.stdout.exp check_PROGRAMS = \ allexec \ @@ -63,7 +68,8 @@ check_PROGRAMS = \ test_tm test_touch_tm ldst_multiple data-cache-instructions \ power6_mf_gpr std_reg_imm \ twi_tdi tw_td power6_bcmp - +# test_isa_3_1_RT test_isa_3_1_XT +# test_isa_3_1_Misc test_isa_3_1_VRT test_isa_3_1_AT AM_CFLAGS += @FLAG_M64@ AM_CXXFLAGS += @FLAG_M64@ @@ -71,6 +77,12 @@ AM_CCASFLAGS += @FLAG_M64@ allexec_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@ +#test_isa_3_1_XT_SOURCES = test_isa_3_1_XT.c test_isa_3_1_common.c +#test_isa_3_1_RT_SOURCES = test_isa_3_1_RT.c test_isa_3_1_common.c +#test_isa_3_1_VRT_SOURCES = test_isa_3_1_VRT.c test_isa_3_1_common.c +#test_isa_3_1_AT_SOURCES = test_isa_3_1_AT.c test_isa_3_1_common.c +#test_isa_3_1_Misc_SOURCES = test_isa_3_1_Misc.c test_isa_3_1_common.c + if HAS_ALTIVEC BUILD_FLAG_ALTIVEC = -maltivec ALTIVEC_FLAG = -DHAS_ALTIVEC @@ -128,6 +140,14 @@ BUILD_FLAGS_ISA_3_00 = ISA_3_00_FLAG = endif +if HAS_ISA_3_1 +BUILD_FLAGS_ISA_3_1 = -mcpu=power10 +ISA_3_1_FLAG = -DHAS_ISA_3_1 +else +BUILD_FLAGS_ISA_3_1 = +ISA_3_1_FLAG = +endif + test_isa_2_06_part1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(VSX_FLAG) \ @FLAG_M64@ $(ALTIVEC_FLAG) $(BUILD_FLAG_VSX) @@ -161,6 +181,9 @@ test_touch_tm_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(HTM_FLAG) test_isa_3_0_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(HTM_FLAG) $(ISA_3_00_FLAG) \ @FLAG_M64@ $(BUILD_FLAGS_ISA_3_00) +test_isa_3_1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(ISA_3_1_FLAG) \ + @FLAG_M64@ $(BUILD_FLAGS_ISA_3_1) + subnormal_test_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames $(VSX_FLAG) $(ISA_2_06_FLAG) \ @FLAG_M64@ $(ALTIVEC_FLAG) $(BUILD_FLAG_VSX) $(BUILD_FLAGS_ISA_2_06) diff --git a/none/tests/ppc64/isa_3_1_helpers.h b/none/tests/ppc64/isa_3_1_helpers.h new file mode 100644 index 0000000000..dfc0422cbc --- /dev/null +++ b/none/tests/ppc64/isa_3_1_helpers.h @@ -0,0 +1,112 @@ +/* isa_3_1_helpers.h */ + +#include "isa_3_1_register_defines.h" + +extern unsigned long a_iters,b_iters,c_iters, m_iters; +extern unsigned long vrai,vrbi,vrci,vrmi; +extern unsigned long a_inc, b_inc, c_inc, m_inc; +extern unsigned long a_limit,b_limit,c_limit; +extern vector unsigned long long vrt, vra, vrb, vrc; +extern vector unsigned long long vrm; +extern vector unsigned long long vec_xa; +extern vector unsigned long long vec_xb; +extern vector unsigned long long vec_xc; +extern vector unsigned long long vec_xs; +extern vector unsigned long long vec_xt; +extern unsigned long long dcmx; + +extern unsigned long current_cr; +extern unsigned long current_fpscr; + +typedef void (*test_func_t) (void); +struct test_list_t { + test_func_t func; + const char *name; + const char *form; + unsigned long mask; /* holds SP or DP indicators. */ +}; +typedef struct test_list_t test_list_t; +extern struct test_list_t current_test; +typedef void (*test_group_t) (const char *name, test_func_t func, + unsigned int unused, char * cur_form); + +/* Misc options for debug. */ +/* setup_only indicates to do all of the register initializations, + but skip the instruction test. */ +extern unsigned long setup_only; +extern int verbose; +extern unsigned long prefix_override; +extern unsigned long vrm_override; +extern unsigned long mc_override; +extern unsigned long enable_setjmp; +extern unsigned long dump_tables; +extern void debug_show_form(const char *, char *); +extern void debug_show_current_iteration(); +extern void debug_dump_buffer(); + +extern void identify_form_components(const char *, const char *); +extern void dump_vsxargs(); +extern void generic_prologue(); +extern void build_args_table(); +extern void build_vsx_table(); +extern void print_register_header(); +extern void print_register_footer(); +extern void debug_show_iter_ranges(); +extern void print_result_buffer(); +extern void dump_float_vsx_tables(); +extern void build_float_vsx_tables(); +extern void initialize_target_registers(); +extern void initialize_source_registers(); +extern void set_up_iterators(); +extern void initialize_buffer(int); + +extern int verbose; +#define debug_printf(X) if (verbose>0) printf(X); +#define debug_show_labels (verbose>0) +#define debug_show_iters (verbose>1) +#define debug_show_raw_values (verbose>2) +#define debug_show_all_regs (verbose>5) +#define debug_show_tables (verbose>6) + + +#define CHECK_OVERRIDES { \ + if (vrm_override && vrmi > 0) continue; \ + if (prefix_override && strncmp("p", instruction_name, 1) == 0) { \ + if (verbose) printf("Skipping prefix insn test %s\n",instruction_name); \ + continue; \ + } \ +} + +/* CR helpers. */ + +#define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7" + +#define SET_CR(_arg) \ + __asm__ __volatile__ ("mtcr %0" : : "b"(_arg) : ALLCR ); + +#define SET_CR0_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x80,%0 " : : "b" (_arg):"cr0"); +#define SET_CR1_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x40,%0 " : : "b" (_arg):"cr1"); +#define SET_CR2_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x20,%0 " : : "b" (_arg):"cr2"); +#define SET_CR3_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x10,%0 " : : "b" (_arg):"cr3"); +#define SET_CR4_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x08,%0 " : : "r" (_arg):"cr4"); +#define SET_CR5_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x04,%0 " : : "r" (_arg):"cr5"); +#define SET_CR6_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x02,%0 " : : "r" (_arg):"cr6"); +#define SET_CR7_FIELD(_arg) __asm__ __volatile__ ("mtocrf 0x01,%0 " : : "r" (_arg):"cr7"); + +#define SET_XER(_arg) __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" ); +#define GET_CR(_lval) __asm__ __volatile__ ("mfcr %0" : "=b"(_lval) ) +#define GET_XER(_lval) __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) ) +#define SET_CR_ZERO SET_CR(0) + +/* ************** */ +/* FPSCR helpers. */ +#define SET_FPSCR_ZERO \ + do { \ + double _d = 0.0; \ + __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \ + } while (0); + +#define GET_FPSCR(_arg) \ + __asm__ __volatile__ ("mffs %0" : "=f"(_arg) ); + + diff --git a/none/tests/ppc64/isa_3_1_register_defines.h b/none/tests/ppc64/isa_3_1_register_defines.h new file mode 100644 index 0000000000..e4d021e5c0 --- /dev/null +++ b/none/tests/ppc64/isa_3_1_register_defines.h @@ -0,0 +1,50 @@ +/* register definitions used in tests for isa_3_1. */ + +/* ACC / Accumulator. + An ACC is associated with a set of four VSR registers. + Each ACC contains four 128-bit rows. + Each row of each ACC is aliased to a specific VSR in the following manner. + ACC[0][0] == VSR[0]; ACC[0][1] == VSR[1]; ACC[0][2] == VSR[2]; ACC[0][3] == VSR[3] + ... + ACC[7][0] == VSR[28]; ACC[7][0] == VSR[28]; ACC[7][0] == VSR[28]; ACC[7][0] == VSR[28] +*/ +#define ACCNUM 4 +register vector long long TEST_ACC0 __asm__ ("vs16"); +register vector long long TEST_ACC1 __asm__ ("vs17"); +register vector long long TEST_ACC2 __asm__ ("vs18"); +register vector long long TEST_ACC3 __asm__ ("vs19"); + +/* XSp and XTp use the same register pair, defined here as 20 and 21. + { also XSp,XTp in scripts } */ +register vector long long XTp0 __asm__ ("vs20"); // XTp[0];XSp[0]; +register vector long long XTp1 __asm__ ("vs21"); // XTp[1];XSp[1]; + +// xa,xb,xc references are mapped to a specific vector register. +// out of order to allow xap mapped over xa and xc. +register vector long long xa __asm__ ("vs22"); // also xap. +register vector long long xc __asm__ ("vs23"); // also 2nd half of xap. +register vector long long xb __asm__ ("vs24"); +register vector long long xt __asm__ ("vs25"); + +/* frs,frb (variable named frsb) both use the same register pair. + (top half of vs26,vs27) */ +register double frsb __asm__ ("fr26"); +register double frsbp __asm__ ("fr27"); +/* frt,frtp register pair. (top half of vs28,vs29) */ +register double frt __asm__ ("vs28"); +register double frtp __asm__ ("vs29"); + +register uint64_t ra __asm__ ("r20"); +register uint64_t rb __asm__ ("r21"); +register uint64_t rc __asm__ ("r22"); +register uint64_t rs __asm__ ("r24"); /* rsp part 1 */ +register uint64_t rsp __asm__ ("r25"); /* rsp part 2 */ +register uint64_t rt __asm__ ("r26"); /* rtp part 1 */ +register uint64_t rtp __asm__ ("r27"); /* rtp part 2 */ + +extern unsigned long long vsrd; +extern unsigned long get_vsrhd_vs26(); +extern unsigned long get_vsrhd_vs27(); +extern unsigned long get_vsrhd_vs28(); +extern unsigned long get_vsrhd_vs29(); + diff --git a/none/tests/ppc64/test_isa_3_1_AT.vgtest b/none/tests/ppc64/test_isa_3_1_AT.vgtest new file mode 100644 index 0000000000..e39ffd22a5 --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_AT.vgtest @@ -0,0 +1,3 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_1 +prereq: ../../../tests/check_ppc64_auxv_cap mma +prog: test_isa_3_1_AT diff --git a/none/tests/ppc64/test_isa_3_1_Misc.vgtest b/none/tests/ppc64/test_isa_3_1_Misc.vgtest new file mode 100644 index 0000000000..3802934054 --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_Misc.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_1 +prog: test_isa_3_1_Misc diff --git a/none/tests/ppc64/test_isa_3_1_RT.vgtest b/none/tests/ppc64/test_isa_3_1_RT.vgtest new file mode 100644 index 0000000000..5aad9de09f --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_RT.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_1 +prog: test_isa_3_1_RT diff --git a/none/tests/ppc64/test_isa_3_1_VRT.vgtest b/none/tests/ppc64/test_isa_3_1_VRT.vgtest new file mode 100644 index 0000000000..96d57b2c28 --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_VRT.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_1 +prog: test_isa_3_1_VRT diff --git a/none/tests/ppc64/test_isa_3_1_XT.vgtest b/none/tests/ppc64/test_isa_3_1_XT.vgtest new file mode 100644 index 0000000000..cc717eab14 --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_XT.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/check_ppc64_auxv_cap arch_3_1 +prog: test_isa_3_1_XT diff --git a/none/tests/ppc64/test_isa_3_1_common.c b/none/tests/ppc64/test_isa_3_1_common.c new file mode 100644 index 0000000000..585fd0c90f --- /dev/null +++ b/none/tests/ppc64/test_isa_3_1_common.c @@ -0,0 +1,2188 @@ +/* test_isa_3_1_common.c */ + +/* Copyright (C) 2020, IBM + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + The GNU General Public License is contained in the file COPYING. + */ + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "isa_3_1_register_defines.h" +#include "isa_3_1_helpers.h" +#include "tests/malloc.h" // memalign + +/* post_test indicates to the printf helpers if we are pre- or post- + instruction execution, subsequently used to suppress register + output when those register contents are not useful. */ +unsigned long post_test; +/* increase verbosity for increasing amounts of debug output. */ +int verbose = 0; +#define DEADBEEF 0x1111111111111111ULL + +vector unsigned long long vec_xa; +vector unsigned long long vec_xb; +vector unsigned long long vec_xc; +vector unsigned long long vec_xs; +vector unsigned long long vec_xt; +unsigned long long dcmx; + +/* Iterator controls. These are adjusted as appropriate for the tests + being exercised. See set_up_iterators () below. +*/ +unsigned long a_iters, b_iters, c_iters, m_iters; +unsigned long a_inc, b_inc, c_inc, m_inc; +unsigned long vrai, vrbi, vrci, vrmi; +unsigned long a_limit = 0xffff, b_limit = 0xffff, c_limit = 0xffff; + +vector unsigned long long vrt, vra, vrb, vrc; +vector unsigned long long vrm; + +/* Debug: Set these to allow skipping of test subsets that + have nonzero vrm or mc values. +*/ +unsigned long prefix_override = 0; +unsigned long vrm_override = 0; +unsigned long mc_override = 0; +unsigned long enable_setjmp = 0; +unsigned long dump_tables = 0; + +/* condition register misc. */ +extern unsigned long current_cr; +extern unsigned long current_fpscr; + +/* Helpers to manage when our output fields require special handling. + This includes scenarios including: + - some parts of the output fields are Undefined. + - some parts of the output field contain *estimated* data that needs to be + truncated when printed. + - Some parts of the output need to be reported as INF or NAN. + - The contents need to be interpreted as single or double precision. +*/ +// Double precision indicators. +#define DP0 0b00100000 +#define DP1 0b00010000 +#define DOUBLE_MASK 0b00110000 +// Single precision indicators. +#define SP0 0b00001000 +#define SP1 0b00000100 +#define SP2 0b00000010 +#define SP3 0b00000001 +#define SINGLE_MASK 0b00001111 +// Estimated output indicators. +#define SINGLE_EST_MASK 0b01000000 +#define DOUBLE_EST_MASK 0b10000000 +// bfloat16 indicators. +#define B16_MASK 0b1111111100000000 +#define B16_0 0b1000000000000000 +#define B16_1 0b0100000000000000 +#define B16_2 0b0010000000000000 +#define B16_3 0b0001000000000000 +#define B16_4 0b0000100000000000 +#define B16_5 0b0000010000000000 +#define B16_6 0b0000001000000000 +#define B16_7 0b0000000100000000 + +/* Instruction Form indicators. + These are set based on the instruction name and the associated + instruction form. These are subsequently used to help initialize + the incoming register contents when testing the specific instruction. +*/ +bool has_ra, has_rb, has_rc, has_rs, has_rt; +bool has_rtp, has_rsp; +bool has_vra, has_vrb, has_vrc, has_vrm, has_vrt; +bool has_xa, has_xb, has_xc, has_xs, has_xt; +bool has_xap; +bool uses_xc_as_blend_mask; +bool has_xsp, has_xtp; +bool has_frb, has_frbp; // frb* uses same regs as frsp. +bool has_frs, has_frsp; +bool has_frt, has_frtp; +bool uses_CRBIT, uses_RC, uses_MC; +bool uses_cr; +bool is_divide_or_modulo; +bool is_insert_double; +bool is_testlsb; +bool has_rs_as_value_source; +bool has_dcmx; +unsigned long is_clear_or_insert_insns; +unsigned long is_mtvsr_insn; +unsigned long is_cmp_insn; +bool has_ra_target; +bool uses_dfp128_input; +bool uses_dfp128_output; +bool uses_acc; // Accumulator related. +bool uses_acc_src; +bool uses_acc_dest; +bool uses_acc_vsrs; +bool uses_buffer; // Buffer related. +bool uses_load_buffer, uses_store_buffer, uses_any_buffer; +bool uses_quad; +unsigned long output_mask; // Output field special handling. +bool instruction_is_sp, instruction_is_sp_estimate; +bool instruction_is_dp, instruction_is_dp_estimate; +bool instruction_is_b16; + +unsigned long long min (unsigned long long a, unsigned long long b) { + if ( a < b ) + return a; + return b; +} + +/* Parse the 'form' field to mark and identify arguments to the instruction. */ +void identify_form_components (const char *instruction_name, + const char *cur_form) +{ + has_ra = ((strstr (cur_form, ",RA") != NULL) || + (strstr (cur_form, "(RA)") != NULL)); + has_ra_target = (strncmp (cur_form, "RA,", 3) == 0); + has_rb = strstr (cur_form, ",RB") != NULL; + has_rc = strstr (cur_form, ",RC") != NULL; + has_rs = ((strstr (cur_form, ",RS") != NULL) || + (strncmp (cur_form, "RS", 2) == 0)); + has_rsp = (strncmp (cur_form, "RSp", 3) == 0); + has_rt = (strncmp (cur_form, "RT", 2) == 0); + has_rtp = (strncmp (cur_form, "RTp", 3) == 0); + + has_vra = strstr (cur_form, "VRA") != NULL; + has_vrb = strstr (cur_form, "VRB") != NULL; + has_vrc = strstr (cur_form, "VRC") != NULL; + has_vrm = strstr (cur_form, "VRM") != NULL; + has_vrt = (strncmp (cur_form, "VRT", 3) == 0); + + has_frb = strstr (cur_form, "FRB") != NULL; + has_frbp = strstr (cur_form, "FRBp") != NULL; + has_frs = strstr (cur_form, "FRS") != NULL; + has_frsp = strstr (cur_form, "FRSp") != NULL; + has_frt = strstr (cur_form, "FRT") != NULL; + has_frtp = strstr (cur_form, "FRTp") != NULL; + + has_xa = strstr (cur_form, ",XA") != NULL; + has_xap = strstr (cur_form, ",XAp") != NULL; + has_xb = strstr (cur_form, ",XB") != NULL; + has_xc = strstr (cur_form, ",XC") != NULL; + has_xs = (strncmp (cur_form, "XS", 2) == 0); + has_xsp = (strncmp (cur_form, "XSp", 3) == 0); + has_xt = (strncmp (cur_form, "XT", 2) == 0); + has_xtp = (strncmp (cur_form, "XTp", 3) == 0); + + uses_acc_src = (strstr (cur_form, "AS") != NULL); + uses_acc_dest = (strstr (cur_form, "AT") != NULL); +/* These (xxm*acc) are special cases where the acc_src is used, but we + need to read the associated _vsrs on the way out. +*/ + uses_acc_vsrs = ( + (strstr (instruction_name, "xxmfacc") != NULL) || + (strstr (instruction_name, "xxmtacc") != NULL) ); + uses_acc = uses_acc_src || uses_acc_dest || uses_acc_vsrs; + + uses_dfp128_input = ( + (strncmp (instruction_name, "dctf", 4) == 0)); + uses_dfp128_output = ( + (strncmp (instruction_name, "dcff", 4) == 0)); + is_divide_or_modulo = ( + (strncmp (instruction_name, "vdiv", 4) == 0) || + (strncmp (instruction_name, "pmvdiv", 6) == 0) || + (strncmp (instruction_name, "vmod", 4) == 0) || + (strncmp (instruction_name, "pmvmod", 6) == 0) ); + is_insert_double = ( + (strncmp (instruction_name, "vinsd", 5) == 0) ); + is_testlsb = ( + (strncmp (instruction_name, "xvtlsbb", 7) == 0) ); + uses_xc_as_blend_mask = ( + (strncmp (instruction_name, "xxblend", 7) == 0) ); + has_dcmx = strstr (cur_form, "DCMX") != NULL; + uses_CRBIT = ( + (strncmp (cur_form, "BF", 2) == 0) || + (strstr (cur_form, ",BI") != 0)); + uses_RC = ( + (strstr (instruction_name, ".") != NULL )); + uses_MC = ( + (strstr (instruction_name, ",MC") != NULL )); + uses_cr = ( + (strstr (instruction_name, "setbcr") != 0) || + (strstr (instruction_name, "setnbcr") != 0)); +/* The lxvkq instruction loads special values into a VSX vector, so although + this looks like a load, it is excluded from the uses_load_buffer set + because it does not load a value from a buffer. */ + uses_load_buffer = ( + (strncmp (instruction_name, "ld", 2) == 0) || + (strncmp (instruction_name, "lq", 2) == 0) || + (strncmp (instruction_name, "plq", 3) == 0) || + (strncmp (instruction_name, "plx", 3) == 0) || + (strncmp (instruction_name, "pmlx", 4) == 0) || + (strncmp (instruction_name, "lxv", 3) == 0) || + ( (strncmp (instruction_name, "lxva", 4) == 0) && + (strncmp (instruction_name, "lxvkq", 5) != 0)) ); + uses_store_buffer = ( + (strncmp (instruction_name, "pmst", 4) == 0) || + (strncmp (instruction_name, "pst", 3) == 0) || + (strncmp (instruction_name, "st", 2) == 0)); + uses_any_buffer = (strstr (cur_form, "(RA)") != NULL); + uses_buffer = uses_any_buffer||uses_load_buffer||uses_store_buffer; + + uses_quad = (uses_buffer && (strstr (instruction_name, "q") != NULL)); + + has_rs_as_value_source = ( + (strcmp (cur_form, "RA,RS,RB") == 0) || + (strcmp (cur_form, "RA,RS") == 0) ); + + is_clear_or_insert_insns = ( + (strncmp (instruction_name, "vclr", 4) == 0) || + (strncmp (instruction_name, "vins", 4) == 0) ); + + /* This is used by a helper function to control the CR field output when + the instruction is a compare, otherwise it is likely a bitfield check. */ + is_cmp_insn = ( (strstr (cur_form, "cmp") != NULL)); + + is_mtvsr_insn = ( (strncmp (instruction_name, "mtvsr", 5) == 0)); + + /* If the instruction output needs to be something other than a hex dump, + a mask will have been defined as part of the test_list_t structure. + This includes instructions that return estimated values, as well as + those that return NAN results which contain sign bits that need to be + filtered out. */ + output_mask = ( current_test.mask ); + instruction_is_dp = ( current_test.mask & DOUBLE_MASK ); + instruction_is_dp_estimate = ( current_test.mask & DOUBLE_EST_MASK ); + instruction_is_sp = ( current_test.mask & SINGLE_MASK ); + instruction_is_sp_estimate = ( current_test.mask & SINGLE_EST_MASK ); + instruction_is_b16 = ( current_test.mask & B16_MASK ); +} + +void display_form_components (char * cur_form) { + printf (" %s\n", cur_form); + printf ("Instruction form elements: "); + if (has_ra) printf ("ra "); + if (has_rb) printf ("rb "); + if (has_rc) printf ("rc "); + if (has_rs) printf ("rs "); + if (has_rsp) printf ("rsp "); + if (has_rt) printf ("rt "); + if (has_rtp) printf ("rtp "); + if (has_vra) printf ("vra "); + if (has_vrb) printf ("vrb "); + if (has_vrc) printf ("vrc "); + if (has_vrm) printf ("vrm "); + if (has_vrt) printf ("vrt "); + + if (has_frb) printf ("frb "); + if (has_frbp) printf ("frbp "); + if (has_frs) printf ("frs "); + if (has_frsp) printf ("frsp "); + if (has_frt) printf ("frt "); + if (has_frtp) printf ("frtp "); + if (has_xa) printf ("xa "); + if (has_xap) printf ("xap "); + if (has_xb) printf ("xb "); + if (has_xc) printf ("xc "); + if (has_xs) printf ("xs "); + if (has_xsp) printf ("xsp "); + if (has_xt) printf ("xt "); + if (has_xtp) printf ("xtp "); + if (uses_acc_src) printf ("AS "); + if (uses_acc_dest) printf ("AT "); + printf ("\n"); + if (uses_dfp128_input) + printf ("uses dfp128 input.\n"); + if (uses_dfp128_output) + printf ("uses dfp128 output.\n"); + if (has_ra_target) + printf ("ra is a target register.\n"); + if (has_rs_as_value_source) + printf ("rs is a value source.\n"); + if (uses_xc_as_blend_mask) + printf ("uses xc as a blend mask.\n"); + if (is_clear_or_insert_insns) + printf ("is a clear or insert insn.\n"); + if (is_insert_double) + printf ("is an insert doubleword.\n"); + if (is_testlsb) + printf ("tests lsb.\n"); + if (uses_buffer) + printf ("uses_buffer: (l:%d s:%d ?:%d)\n", + uses_load_buffer, uses_store_buffer, uses_any_buffer); + if (uses_quad) + printf ("is a quad load or store.\n"); + if (is_cmp_insn) + printf ("is a compare instruction.\n"); + if (uses_CRBIT) + printf ("instruction references a CR.\n"); + if (uses_cr) + printf ("instruction reads CR bits.\n"); + if (uses_MC) + printf ("Instruction uses MC.\n"); + if (uses_RC) + printf ("Instruction uses Record Bit (cr6).\n"); + if (uses_acc) + printf ("Instruction uses ACC: (src:%d, dst:%d, vsrs:%d).\n", + uses_acc_src, uses_acc_dest, uses_acc_vsrs); + if (output_mask) { + printf ("Instruction results are masked: "); + printf (" (%lx) ", output_mask); + printf ("%s ", instruction_is_sp?"SP ":""); + printf ("%s ", instruction_is_sp_estimate?"SP Estimate ":""); + printf ("%s ", instruction_is_dp?"DP ":""); + printf ("%s ", instruction_is_dp_estimate?"DP Estimate ":""); + printf ("%s ", instruction_is_b16?"bfloat16 ":""); + } + printf ("\n"); +} + +long long mask64[] = { 0x0, 0x00000000ffffffff, 0xffffffff55555555, + 0x5555aaaaaaaa5555, 0xaaaa00000000aaaa }; +#define MASK64SIZE 5 +unsigned long long vrm_mask[] = { 0x0, 0x8000000000000000, + 0x8000000000000000, 0x0 }; +#define VRMMASK_SIZE 4 + +// Helpers to print double/float values. +// Union to help handle referencing hex/float/double values. +union rosetta_t { + unsigned long long ull; + unsigned long long ullp[2]; + float flt; + float fltp[2]; + uint16_t uint16s[4]; + double dbl; +}; + +void generic_print_float_as_hex (float f) { + union rosetta_t stone; + stone.ullp[0] = stone.ullp[1] = 0; //init + stone.flt = f; + printf (" %016llx", stone.ull); +} + +void generic_print_ull_as_float (unsigned long long ull) { + union rosetta_t stone; + stone.ullp[0] = stone.ullp[1] = 0; //init + stone.ull = ull; + printf (" %f", stone.flt); +} + +void generic_print_ull_as_double (unsigned long long ull) { + union rosetta_t stone; + stone.ullp[0] = stone.ullp[1] = 0; //init + stone.ull = ull; + printf (" %e", stone.dbl); +} + +void generic_print_double_as_hex (double d) { + union rosetta_t stone; + stone.ullp[0] = stone.ullp[1] = 0; //init + stone.dbl = d; + printf (" %016llx", stone.ull); +} + +// SP in a 32-bit field. +#define SP_SIGNBIT_MASK 0x80000000 +#define SP_EXPONENT_MASK 0x7f800000 +#define SP_FRACTION_MASK 0x007fffff + +// DP (64-bit). +#define DP_SIGNBIT_MASK 0x8000000000000000UL +#define DP_EXPONENT_MASK 0x7ff0000000000000UL +#define DP_FRACTION_MASK 0x000fffffffffffffUL + +// B16 bfloat16. +#define BF16_SIGNBIT_MASK 0x8000 +#define BF16_EXPONENT_MASK 0x7f80 +#define BF16_FRACTION_MASK 0x007f + +/* + - NAN and Zero values need the sign bit display suppressed. (See comments + in jm-insns.c, approx line 7203). + - Some instructions return estimated values, which are calculated + to a different level of precision within valgrind. Those + instructions need their outputs limited to a specific number of + digits as seen below. */ + +// NAN - Maximum biased exponent and a nonzero mantissa (fraction). +#define PRINT_SP_NAN printf (" NaN"); +// DEN - Exp == 0 and Frac != 0 +#define PRINT_SP_PLUS_DEN printf (" +Den"); +#define PRINT_SP_MINUS_DEN printf (" -Den"); +// INF - Maximum biased exponent and a zero mantissa. +#define PRINT_SP_INF printf (" Inf"); +#define PRINT_SP_PLUS_INF printf (" +Inf"); +#define PRINT_SP_MINUS_INF printf (" -Inf"); +#define PRINT_SP_FLOAT(x) printf ("%13.05e", x); +#define PRINT_SP_FLOAT_EST(x) printf ("%13.03e", x); +#define PRINT_SP_FLOAT_PLUS_ZERO printf (" +Zero"); +#define PRINT_SP_FLOAT_MINUS_ZERO printf (" -Zero"); + +/* Print a SINGLE (16 bit) SP value out of the left part of a 32-bit field. */ +void special_print_sp_value (uint32_t value) { + int signbit; + int exponent; + unsigned long long fraction; + union rosetta_t stone; + + stone.ull = value; + signbit = value & SP_SIGNBIT_MASK; + exponent = (value & SP_EXPONENT_MASK); + fraction = value & SP_FRACTION_MASK; + + if (debug_show_raw_values) { + printf ("\nsp_debug: v:%08x s: %d %3x %8llx %f , ", + value, signbit?1:0, exponent, fraction, stone.flt); + } + if (exponent == SP_EXPONENT_MASK && fraction == 0 ) { + if (signbit) + PRINT_SP_MINUS_INF + else + PRINT_SP_PLUS_INF + } else if (exponent == SP_EXPONENT_MASK && fraction != 0 ) { + PRINT_SP_NAN + } else if (exponent == 0 && fraction == 0 ) { + if (signbit) + PRINT_SP_FLOAT_MINUS_ZERO + else + PRINT_SP_FLOAT_PLUS_ZERO + } else if (exponent == 0 && fraction != 0 ) { + if (signbit) + PRINT_SP_MINUS_DEN + else + PRINT_SP_PLUS_DEN + } else if (instruction_is_sp_estimate) { + PRINT_SP_FLOAT_EST (stone.flt); + } else { + PRINT_SP_FLOAT (stone.flt); + } +} + +void dissect_sp_value (unsigned long long foo) { + if (debug_show_raw_values) { + printf ("RAW sp::%4llx ", foo); + printf (" [s:"); + printf ("%x", (foo & SP_SIGNBIT_MASK)>0); + printf (" e:"); + printf ("%4llx", foo & SP_EXPONENT_MASK); + printf (" f:"); + printf ("%4llx", foo & SP_FRACTION_MASK); + printf ("] "); + } + special_print_sp_value (foo); + printf (" "); +} + +/* Print one DP values out of our vec_ field. */ +#define PRINT_DP_NAN printf (" NaN"); +#define PRINT_DP_MINUS_DEN printf (" -Den"); +#define PRINT_DP_PLUS_DEN printf (" +Den"); +#define PRINT_DP_MINUS_INF printf (" -Inf"); +#define PRINT_DP_PLUS_INF printf (" +InF"); +#define PRINT_DP_FLOAT(x) printf (" %15.08e", x); +#define PRINT_DP_FLOAT_EST(x) printf (" %15.02e", x); +#define PRINT_DP_FLOAT_PLUS_ZERO printf (" +Zero"); +#define PRINT_DP_FLOAT_MINUS_ZERO printf (" -Zero"); +#define PRINT_DP_FLOAT_ZERO printf (" 0.000000e+000"); +void special_print_dp_value (unsigned long long value) { + unsigned long long signbit; + unsigned long long exponent; + unsigned long long fraction; + union rosetta_t stone; + + stone.ull = value; + signbit = (value & DP_SIGNBIT_MASK) > 0; + exponent = value & DP_EXPONENT_MASK; // >> double_exponent_shift; + fraction = value & DP_FRACTION_MASK; + if (verbose>2) + printf ("\ndb_debug: %16llx s:%d %3llx %8llx %llx , ", + value, signbit?1:0, exponent, fraction, stone.ull); + if (exponent == DP_EXPONENT_MASK /* MAX */ && fraction == 0 ) { + if (signbit) + PRINT_DP_MINUS_INF + else + PRINT_DP_PLUS_INF + } else if (exponent == DP_EXPONENT_MASK && fraction != 0 ) { + PRINT_DP_NAN + } else if (exponent == 0 && fraction == 0 ) { + if (signbit) + PRINT_DP_FLOAT_MINUS_ZERO + else + PRINT_DP_FLOAT_PLUS_ZERO + } else if (exponent == 0 && fraction != 0 ) { + if (signbit) + PRINT_DP_MINUS_DEN + else + PRINT_DP_PLUS_DEN + } else if (instruction_is_dp_estimate) { + PRINT_DP_FLOAT_EST (stone.dbl); + } else { + PRINT_DP_FLOAT (stone.dbl); + } +} + +void dissect_dp_value (unsigned long long foo) { + if (debug_show_raw_values) { + printf ("RAW dp::%llx", (foo)); + printf (" [sign:"); + printf ("%x ", (foo & DP_SIGNBIT_MASK) > 0); + printf (" expbits:"); + printf ("%3llx", foo & DP_EXPONENT_MASK ); + printf (" frac:"); + printf ("%16llx", foo & DP_FRACTION_MASK); + printf ("] "); + } + special_print_dp_value (foo); + printf (" "); +} + +// NAN - Maximum biased exponent and a nonzero mantissa (fraction). +#define PRINT_BF16_NAN printf (" NaN"); +// DEN - Exp == 0 and Frac != 0 +#define PRINT_BF16_PLUS_DEN printf (" +Den"); +#define PRINT_BF16_MINUS_DEN printf (" -Den"); +// INF - Maximum biased exponent and a zero mantissa. +#define PRINT_BF16_INF printf (" Inf"); +#define PRINT_BF16_PLUS_INF printf (" +Inf"); +#define PRINT_BF16_MINUS_INF printf (" -Inf"); +#define PRINT_BF16_FLOAT(x) printf (" 0x%04x", x); +#define PRINT_BF16_FLOAT_PLUS_ZERO printf (" +Zero"); +#define PRINT_BF16_FLOAT_MINUS_ZERO printf (" -Zero"); +/* print a single bfloat16 value. */ +void special_print_bf16_value (uint16_t value) { + int signbit; + int exponent; + unsigned long long fraction; + union rosetta_t stone; + signbit = value & BF16_SIGNBIT_MASK; + exponent = (value & BF16_EXPONENT_MASK); + fraction = (value & BF16_FRACTION_MASK); + stone.ull = value; + if (debug_show_raw_values) { + printf ("\nbf16_debug: v:%08x s: %d %3x %8llx %f , ", + value, signbit?1:0, exponent, fraction, stone.flt); + } else if (verbose > 0) { + printf (" v:%08x", value); + } + if (exponent == BF16_EXPONENT_MASK && fraction == 0 ) { + if (signbit) + PRINT_BF16_MINUS_INF + else + PRINT_BF16_PLUS_INF + } else if (exponent == BF16_EXPONENT_MASK && fraction != 0 ) { + PRINT_BF16_NAN + } else if (exponent == 0 && fraction == 0 ) { + if (signbit) + PRINT_BF16_FLOAT_MINUS_ZERO + else + PRINT_BF16_FLOAT_PLUS_ZERO + } else if (exponent == 0 && fraction != 0 ) { + if (signbit) + PRINT_BF16_MINUS_DEN + else + PRINT_BF16_PLUS_DEN + } else + PRINT_BF16_FLOAT (value); +} + +/* ******************** */ +/* Accumulator related. */ +/* Note that our tests to set and clear the acc both read and write + from and to the associated VSRs, so some tests may be + self-fulfilling. */ +void push_vsrs_to_acc () { + if (!setup_only) + __asm__ __volatile__ ("xxmtacc 4 "); // $ACCNUM +} + +void push_acc_to_vsrs () { + if (!setup_only) + __asm__ __volatile__ ("xxmfacc 4 "); // $ACCNUM +} + + +void __print_splat_or_sp(long long vv) { + if (vv == DEADBEEF) + printf (" * "); + else { + special_print_sp_value (0xffffffff & (vv>>32)); + special_print_sp_value (0xffffffff & (vv)); + } +} + +void __print_splat_or_dp(long long vv) { + if (vv == DEADBEEF) + printf (" * "); + else { + special_print_dp_value (vv); + } +} + +void __print_splat_or_raw(long long vv) { + if (vv == DEADBEEF) + printf (" * "); + else + printf ("%llx ", vv); +} + +void print_accumulator () { + if (uses_acc || debug_show_all_regs) { + push_acc_to_vsrs (); + if (debug_show_labels) printf (" Acc[]:"); + if (instruction_is_sp) { + printf (" ("); + __print_splat_or_sp(TEST_ACC0[0]); + __print_splat_or_sp(TEST_ACC0[1]); + __print_splat_or_sp(TEST_ACC1[0]); + __print_splat_or_sp(TEST_ACC1[1]); + __print_splat_or_sp(TEST_ACC2[0]); + __print_splat_or_sp(TEST_ACC2[1]); + __print_splat_or_sp(TEST_ACC3[0]); + __print_splat_or_sp(TEST_ACC3[1]); + printf (")"); + } else if (instruction_is_dp) { + printf (" {"); + __print_splat_or_dp(TEST_ACC0[0]); + __print_splat_or_sp(TEST_ACC0[1]); + __print_splat_or_dp(TEST_ACC1[0]); + __print_splat_or_sp(TEST_ACC1[1]); + __print_splat_or_dp(TEST_ACC2[0]); + __print_splat_or_sp(TEST_ACC2[1]); + __print_splat_or_dp(TEST_ACC3[0]); + __print_splat_or_sp(TEST_ACC3[1]); + printf ("}"); + } else { + printf (" ["); + __print_splat_or_raw(TEST_ACC0[0]); + __print_splat_or_raw(TEST_ACC0[1]); + __print_splat_or_raw(TEST_ACC1[0]); + __print_splat_or_raw(TEST_ACC1[1]); + __print_splat_or_raw(TEST_ACC2[0]); + __print_splat_or_raw(TEST_ACC2[1]); + __print_splat_or_raw(TEST_ACC3[0]); + __print_splat_or_raw(TEST_ACC3[1]); + printf ("]"); + } + } +} + + +/* ************** */ +/* The bit definitions for the FPSCR are as follows. +Bit (s) Description +0:31 Reserved +32 Floating-Point Exception Summary (FX) +33 Floating-Point Enabled Exception Summary (FEX) +34 Floating-Point Invalid Operation Exception Summary (VX) +35 Floating-Point Overflow Exception (OX) +36 Floating-Point Underflow Exception (UX) +37 Floating-Point Zero Divide Exception (ZX) +38 Floating-Point Inexact Exception (XX) +39 Floating-Point Invalid Operation Exception (SNaN) (VXSNAN) +40 Floating-Point Invalid Operation Exception (∞ - ∞) (VXISI) +41 Floating-Point Invalid Operation Exception (∞ ÷ ∞) (VXIDI) +42 Floating-Point Invalid Operation Exception (0 ÷ 0) (VXZDZ) +43 Floating-Point Invalid Operation Exception (∞ × 0) (VXIMZ) +44 Floating-Point Invalid Operation Exception (Invalid Compare) (VXVC) +45 Floating-Point Fraction Rounded (FR) +46 Floating-Point Fraction Inexact (FI) +47:51 Floating-Point Result Flags (FPRF) +47 Floating-Point Result Class Descriptor (C) +48:51 Floating-Point Condition Code (FPCC) + 48 Floating-Point Less Than or Negative (FL or <) + 49 Floating-Point Greater Than or Positive (FG or >) + 50 Floating-Point Equal or Zero (FE or = ) + 51 Floating-Point Unordered or NaN (FU or ?) +52 Reserved +53 Floating-Point Invalid Operation Exception (Software-Defined Condition) (VXSOFT) +54 Floating-Point Invalid Operation Exception (Invalid Square Root) (VXSQRT) +55 Floating-Point Invalid Operation Exception (Invalid Integer Convert) (VXCVI) +56 Floating-Point Invalid Operation Exception Enable (VE) +57 Floating-Point Overflow Exception Enable (OE) +58 Floating-Point Underflow Exception Enable (UE) +59 Floating-Point Zero Divide Exception Enable (ZE) +60 Floating-Point Inexact Exception Enable (XE) +61 Floating-Point Non-IEEE Mode (NI) +62:63 Floating-Point Rounding Control (RN) + 00 Round to Nearest + 01 Round toward Zero + 10 Round toward +Infinity + 11 Round toward -Infinity +*/ +/* Valgrind currently tracks the rounding mode, C and FPCC fields + of the FPSCR. Additional checking in the testcase is not + necessary or beneficial. */ + +#define FPCC_C_BIT (0x1 << (63-47)) +#define FPCC_FL_BIT (0x1 << (63-48)) +#define FPCC_FG_BIT (0x1 << (63-49)) +#define FPCC_FE_BIT (0x1 << (63-50)) +#define FPCC_FU_BIT (0x1 << (63-51)) +#define FPCC_FPRF_MASK \ + FPCC_C_BIT | FPCC_FL_BIT | FPCC_FG_BIT | FPCC_FE_BIT | FPCC_FU_BIT + +#define FPSCR_RN_BIT62 (0x1 << (63-62)) +#define FPSCR_RN_BIT63 (0x1 << (63-63)) + +#define CRFIELD_BIT0 0x8 +#define CRFIELD_BIT1 0x4 +#define CRFIELD_BIT2 0x2 +#define CRFIELD_BIT3 0x1 + +/* Display the condition register bits. */ +int cr_overflow_set (unsigned this_cr) { + return (this_cr & CRFIELD_BIT3); +} + +int cr_zero_set (unsigned this_cr) { + return (this_cr & CRFIELD_BIT2); +} + +int cr_positive_set (unsigned this_cr) { + return (this_cr & CRFIELD_BIT1); +} + +int cr_negative_set (unsigned this_cr) { + return (this_cr & CRFIELD_BIT0); +} + +/* This function (__dissect_cr) takes a bitfield directly. */ +static void __dissect_cr (unsigned this_cr) { + extern unsigned long is_cmp_insn; + printf ("["); + if (cr_negative_set (this_cr)) + printf ("%s", is_cmp_insn ? " (LT) 0x1 = Negative 0b1 " : "1"); + else + printf ("%s", verbose ? "0" : "0"); + + if (cr_positive_set (this_cr)) + printf ("%s", is_cmp_insn ? " (GT) 0x2 = Positive fg_flag (zero/inf/denorm) " : "1"); + else + printf ("%s", verbose ? "0" : "0"); + + if (cr_zero_set (this_cr)) + printf ("%s", is_cmp_insn ? " (EQ) 0x4 = Zero fe_flag (zero/nan/inf/neg/e_b<-970" : "1"); + else + printf ("%s", verbose ? "0" : "0"); + + if (cr_overflow_set (this_cr)) + printf ("%s", is_cmp_insn ? " (SO) 0x8 = Overflow 0b0" : "1"); + else + printf ("%s", verbose ? "0" : "0"); + printf ("]"); +} + +/* Extract one CR field */ +int extract_cr_rn (unsigned long chosen_cr, unsigned long rn) { + unsigned int masked_cr; + unsigned long shifted_value; + shifted_value = chosen_cr >> ( ( (7 - rn) * 4 ) ); + masked_cr = shifted_value & 0xf; + return masked_cr; +} + +/* Display one CR field */ +void dissect_cr_rn (unsigned long chosen_cr, unsigned long rn) { + unsigned int masked_cr; + if (debug_show_labels) printf (" RC/CR (%ld):", rn ); + masked_cr = extract_cr_rn (chosen_cr, rn); + printf ("%ld:", rn); + __dissect_cr (masked_cr); +} + +char * fpscr_strings[] = { +" 0-RSVD", " 1-RSVD", " 2-RSVD", " 3-RSVD", " 4-RSVD", " 5-RSVD", " 6-RSVD", +" 7-RSVD", " 8-RSVD", " 9-RSVD", "10-RSVD", "11-RSVD", "12-RSVD", "13-RSVD", +"14-RSVD", "15-RSVD", "16-RSVD", "17-RSVD", "18-RSVD", "19-RSVD", "20-RSVD", +"21-RSVD", "22-RSVD", "23-RSVD", "24-RSVD", "25-RSVD", "26-RSVD", "27-RSVD", +"28-RSVD", "29-DRN0", "30-DRN1", "31-DRN2", +/* 32 */ "FX", "FEX", "VX", +/* 35 */ "OX", "UX", "ZX", "XX", "VXSNAN", +/* 40 */ "VXISI (inf-inf)", "VXIDI (inf/inf)", "VXZDZ (0/0)", +/* 43 */ "VXIMZ (inf*0)", "VXVC", +/* 45 */ "FR", "FI", +/* 47 */ "FPRF-C", "FPCC-FL", "FPCC-FG", +/* 50 */ "FPCC-FE", "FPCC-FU", +/* 52 */ "52-RSVD", "FXSOFT", "VXSQRT", +/* 55 */ "VXCVI", "VE", "OE", "UE", "ZE", +/* 60 */ "XE", "NI", "RN-bit62", "RN-bit63" +}; +/* Display only the fpscr bits that are valid under valgrind. + * Valgrind tracks the C (FPSCR[47]), FPCC (FPSCR[48:51) + * DRN (FPSCR[29:31]) and RN (FPSCR[62:63]). */ +void dissect_fpscr_valgrind (unsigned long local_fpscr) { + int i; + long mybit; + + /* Print DRN fields */ + for (i = 29; i < 32; i++) { + mybit = 1LL << (63 - i); + if (mybit & local_fpscr) { + printf (" %s", fpscr_strings[i]); + } + } + + /* Print C and FPCC fields */ + for (i = 47; i < 52; i++) { + mybit = 1LL << (63 - i); + if (mybit & local_fpscr) { + printf (" %s", fpscr_strings[i]); + } + } + + /* Print RN field */ + for (i = 62; i < 64; i++) { + mybit = 1LL << (63 - i); + if (mybit & local_fpscr) { + printf (" %s", fpscr_strings[i]); + } + } +} + +/* + * This prints the entire FPSCR field. This is only called under higher + * verbosities, as valgrind does not track most of these bits. + */ +void dissect_fpscr_raw (unsigned long local_fpscr) { +/* Due to the additional involved logic, the rounding mode (RN) bits 61-62 + * are handled within dissect_fpscr_rounding_mode (). */ + int i; + long mybit; + for (i = 0; i < 61; i++) { + /* also note that the bit numbering is backwards. */ + mybit = 1LL << (63 - i); + if (mybit & local_fpscr) { + printf (" %s", fpscr_strings[i]); + } + } +} + +void dissect_fpscr (unsigned long local_fpscr) { + if (verbose > 2) { + printf (" [[ fpscr:%lx ]] ", local_fpscr); + dissect_fpscr_raw (local_fpscr); + } else { + dissect_fpscr_valgrind (local_fpscr); + } +} + + +/* *************** */ +/* Buffer Helpers. +Define both a base and a reference buffer. When printing results, only print +the values when there is a difference between the two. */ +#define BUFFER_SIZE 12 +/* Note: Watch the alignment of the buffer, some loads/stores may require +stronger alignments. */ +__attribute__ ( (aligned (16))) unsigned long long buffer[2*BUFFER_SIZE]; +__attribute__ ( (aligned (16))) unsigned long long reference_buffer[2*BUFFER_SIZE]; +unsigned long changed_index[2*BUFFER_SIZE]; +void initialize_buffer (int t) +{ + int x; + for (x = 0; x < BUFFER_SIZE; x++) + /* We don't want each of the 32-bit chunks to be identical since loads + * of a byte from the wrong 32-bit chuck may be difficult to spot. + * Load these up with values that are also interesting if SP/DP, etc. + */ + switch ( (t+x)%BUFFER_SIZE) { + case 0: buffer[x] = 0x3fe00094e0007359; break; // sp + case 1: buffer[x] = 0x7ff7020304057607; break; // nan + case 2: buffer[x] = 0x7ff0000000007000; break; // inf + case 3: buffer[x] = 0x7f0000007f007000; break; // sp pair. + case 4: buffer[x] = 0x5a05a05a05a07a05; break; + case 5: buffer[x] = 0x0102030405067708; break; + case 6: buffer[x] = 0xfedcba9876547210; break; + case 7: buffer[x] = 0x0123456789ab7def; break; + case 8: buffer[x] = 0xffeeddccbbaa7988; break; + default: buffer[x] = 0x1112111211127112* (x-8); break; + } + for (x = 0; x < BUFFER_SIZE; x++) + reference_buffer[x] = buffer[x]; +} + +/* Buffer printing helper. This only displays the contents if they have + changed with respect to the reference buffer, or if running under + high verbosity. */ +void dump_changed_buffer (unsigned long range) { + int x; + int buffer_changed = 0; + + for (x = 0; (x < BUFFER_SIZE) && (x<range) ; x++) { + changed_index[x] = 0; + if (buffer[x] !=reference_buffer[x]) { + buffer_changed = 1; + changed_index[x] = 1; + if (verbose>2) + printf (" {idx %d %016llx %016llx}", + x, reference_buffer[x] , buffer[x] ); + } + } + if (verbose>2 || buffer_changed) { + printf (" ["); + for (x = 0; x < BUFFER_SIZE && (x<range); x++) { + if (x) printf (" "); + if (verbose > 0) + printf ("%s%016llx", changed_index[x] == 1?"*":" ", buffer[x] ); + if (changed_index[x]) { + if (instruction_is_sp) { + printf (" ("); + special_print_sp_value (0xffffffff & buffer[x] >> 32 ); + printf (" "); + special_print_sp_value (0xffffffff & buffer[x]); + printf (") "); + } else if (instruction_is_dp) { + printf (" {"); + special_print_dp_value (buffer[x]); + printf ("} "); + } + printf ("%016llx", buffer[x]); + } else + printf (" - "); + } + printf ("]"); + } +} + +void dump_raw_buffer () { + int x; + printf ("buffer:["); + for (x = 0; x < BUFFER_SIZE ; x++) { + if (x%4 == 0) printf (" (%d)", x); + printf ("%016llx ", buffer[x]); + } + printf ("]"); +} + +void dump_small_buffer (void) { + dump_changed_buffer (8); +} + +void dump_large_buffer (void) { + dump_changed_buffer (8); +} + +void dump_buffer () { +if (verbose>1) printf (" buffer:"); + if (uses_quad) { + dump_large_buffer (); + } else { + dump_small_buffer (); + } +} + +void print_undefined () { + if (verbose>1) + printf (" [Undef]"); + else + printf (" "); +} + +/* print the input 64-bit vector as 32-bit SP lumps. */ +void print_vec_as_sp (unsigned long long ull64) { + printf (" %08llx", ull64 >> 32 ); + printf (" %08llx", ull64 & 0xffff ); +} + +/*------------------------------------------------------------------*/ +/* Decimal Floating Point (DFP) helper functions */ +/*------------------------------------------------------------------*/ +#define NOT(x) ( ( ( x ) == 0) ? 1 : 0) +#define GET(x,y) ( ( ( x ) & ( 0x1UL << ( y ) ) ) >> ( y ) ) +#define PUT(x,y) ( ( x )<< ( y ) ) + +unsigned long dpb_to_bcd ( unsigned long chunk ) +{ + int a, b, c, d, e, f, g, h, i, j, k, m; + int p, q, r, s, t, u, v, w, x, y; + unsigned long value; + + /* convert 10 bit densely packed BCD to BCD */ + p = GET ( chunk, 9 ); + q = GET ( chunk, 8 ); + r = GET ( chunk, 7 ); + s = GET ( chunk, 6 ); + t = GET ( chunk, 5 ); + u = GET ( chunk, 4 ); + v = GET ( chunk, 3 ); + w = GET ( chunk, 2 ); + x = GET ( chunk, 1 ); + y = GET ( chunk, 0 ); + + /* The BCD bit values are given by the following boolean equations.*/ + a = ( NOT (s) & v & w ) | ( t & v & w & s ) | ( v & w & NOT (x) ); + b = ( p & s & x & NOT (t) ) | ( p & NOT (w) ) | ( p & NOT (v) ); + c = ( q & s & x & NOT (t) ) | ( q & NOT (w) ) | ( q & NOT (v) ); + d =r; + e = ( v & NOT (w) & x ) | ( s & v & w & x ) | ( NOT (t) & v & x & w ); + f = ( p & t & v & w & x & NOT (s) ) | ( s & NOT (x) & v ) | ( s & NOT (v) ); + g = ( q & t & w & v & x & NOT (s) ) | ( t & NOT (x) & v ) | ( t & NOT (v) ); + h = u; + i = ( t & v & w & x ) | ( s & v & w & x ) | ( v & NOT (w) & NOT (x) ); + j = ( p & NOT (s) & NOT (t) & w & v ) | ( s & v & NOT (w) & x ) + | ( p & w & NOT (x) & v ) | ( w & NOT (v) ); + k = ( q & NOT (s) & NOT (t) & v & w ) | ( t & v & NOT (w) & x ) + | ( q & v & w & NOT (x) ) | ( x & NOT (v) ); + m = y; + + value = PUT (a, 11) | PUT (b, 10) | PUT (c, 9) | PUT (d, 8) | PUT (e, 7) + | PUT (f, 6) | PUT (g, 5) | PUT (h, 4) | PUT (i, 3) | PUT (j, 2) + | PUT (k, 1) | PUT (m, 0); + return value; +} +#undef NOT +#undef GET +#undef PUT + +/* get_declet (). Return a 10-bit declet, beginning at the 'start' + * offset. + * + * | dword1 | dword0 | + * | 0 63|64 127| + */ +#define TEN_BITS 0x03ffULL + +int get_declet (int start, uint64_t dword1, uint64_t dword0) { + unsigned long local_declet; + unsigned int dword0_shift; + unsigned int dword1_shift; + + dword1_shift = 63 - (start + 9); + dword0_shift = 127 - (start + 9); + + if (verbose>5) printf ("\n%s (%d) %016lx %016lx", + __FUNCTION__, start, dword1, dword0); + + if ( (start + 9) < 63) { /* fully within dword1 */ + local_declet = (dword1 >> dword1_shift) & TEN_BITS; + + } else if (start >= 65) {/* fully within dword0 */ + local_declet = (dword0 >> dword0_shift) & TEN_BITS; + + } else { /* straddling the two dwords*/ + unsigned long mask_dword0; + unsigned long mask_dword1; + + mask_dword1 = TEN_BITS >> (64 - dword0_shift); + mask_dword0 = TEN_BITS << (dword0_shift); + local_declet = + ( (dword1 & mask_dword1) << (64-dword0_shift)) + + ( (dword0 & mask_dword0) >> dword0_shift); + } + return local_declet; +} + +int get_bcd_digit_from_dpd (int start, uint64_t dword1, + uint64_t dword0) { + long bcd_digit; + long declet; + + declet = get_declet (start, dword1, dword0); + bcd_digit = dpb_to_bcd (declet); + return bcd_digit; +} + +/* For DFP finite numbers, the combination field (G field) is a + * combination of the exponent and the LMD (Left Most Digit) of the + * significand. The fields are encoded/decoded as described in the + * table here. + * 00 01 10 -< Exponent bits. + * 0: 00000 01000 10000 + * ... + * 7: 00111 01111 10111 + * 8: 11000 11010 11100 + * 9: 11001 11011 11101 (encoded special field). + * | + * ^ LMD value. +*/ +#define DFP_GFIELD_MASK 0x7c00000000000000UL +#define DFP_GFIELD_SHIFT 58 +//The exponent bias value is 101 for DFP Short, 398 +//for DFP Long, and 6176 for DFP Extended. +#define DFP128_EXPONENT_BIAS 6176 +#define DFP64_EXPONENT_BIAS 398 + +unsigned int special_field_LMD (uint64_t dword1) { + unsigned long g_field_specials; + int left_two_bits; + int right_three_bits; + + g_field_specials = (dword1 & DFP_GFIELD_MASK) >> DFP_GFIELD_SHIFT; + left_two_bits = (g_field_specials & 0x18) >> 3; + right_three_bits = g_field_specials & 0x07; + + /* The LMD result maps directly to the right_three_bits value as + * long as the left two bits are 0b00, 0b01, 0b10. So a compare + * against 3 is sufficient to determine if we can return the right + * three bits directly. (LMD values 0..7). + */ + if (left_two_bits < 3) { + return (right_three_bits); + } + + /* LMD values of 8 or 9 require a bit of swizzle, but a check of + * the right-most bit is sufficient to determine whether LMD value + * is 8 or 9. + */ + if (right_three_bits & 0x1) + return 9; + else + return 8; +} + +/* Returns the exponent bits, as decoded from the G field. */ +int special_field_exponent_bits (unsigned long dword1) { + unsigned long g_field_specials; + int left_two_bits; + int right_three_bits; + + g_field_specials = (dword1 & DFP_GFIELD_MASK) >> DFP_GFIELD_SHIFT; + left_two_bits = (g_field_specials & 0x18) >> 3; + right_three_bits = g_field_specials & 0x07; + + /* The special field exponent bits maps directly to the left_two_bits + * value as long as the left two bits are 0b00, 0b01, 0b10. So a compare + * against 3 is sufficient for those values. + */ + if (left_two_bits < 3) { + return (left_two_bits); + } + + switch (right_three_bits) { + case 0: + case 1: return 0x0; + case 2: + case 3: return 0x1; + case 4: + case 5: return 0x2; + case 6: /* Infinity */ return 0x0; + case 7: /* NaN */ return 0x0; + } + return -1; /* should never hit this */ +} + +/* The 'exponent left' shift is for moving the leftmost two bits + * of the exponent down to where they can be easily merged with the + * rest of the exponent. + */ +#define DFP128_EXPONENT_RIGHT_MASK 0x03ffc00000000000 +#define DFP64_EXPONENT_RIGHT_MASK 0x03fc000000000000 +#define DFP128_EXPONENT_RIGHT_MASK_SHIFT 46 +#define DFP64_EXPONENT_RIGHT_MASK_SHIFT 50 +#define DFP128_EXPONENT_LEFT_SHIFT 12 +#define DFP64_EXPONENT_LEFT_SHIFT 8 + +#define DFP_NAN 0x1f +#define DFP_INF 0x1e +#define DFP_SIGNALING_NAN_BIT 0x0200000000000000 + +/* return the dfp exponent from the leading dword. */ +signed long dfp128_exponent (unsigned long dword1) { + unsigned long exponent_left; + unsigned long exponent_right; + unsigned long biased_exponent; + signed long exponent; + + exponent_left = special_field_exponent_bits (dword1); + exponent_right = (dword1 & DFP128_EXPONENT_RIGHT_MASK); + biased_exponent = (exponent_left << DFP128_EXPONENT_LEFT_SHIFT) + + (exponent_right >> DFP128_EXPONENT_RIGHT_MASK_SHIFT); + + /* Unbias the exponent. */ + exponent = biased_exponent - DFP128_EXPONENT_BIAS; + return exponent; +} + +/* Interpret the paired 64-bit values as a extended (quad) 128 bit DFP. + * + * | Significand | Combination Field/ | | + * | sign bit | Encoded Exponent | remainder of significand | + * |0 |1 17|18 127| + * ^ (bit0) Significand sign bit. + * ^ (bit 1:17) Combination field. Contains high bits of + * exponent (encoded), LMD of significand (encoded), + * and the remainder of the exponent. First five bits + * will indicate special cases NAN or INF. + * ^ (bit 18:127) Remainder of the + * significand. + */ + +#define DFP128_COMBINATION_MASK 0x7fffc +#define DFP64_COMBINATION_MASK 0x7ffc +#define DFP128_COMBINATION_SHIFT 46 +#define DFP64_COMBINATION_SHIFT 50 +#define DFP_SPECIAL_SYMBOLS_MASK 0x1f +#define DFP_SPECIAL_SYMBOLS_SHIFT 58 + +#define DFP_NAN 0x1f +#define DFP_INF 0x1e +#define DFP_SIGNALING_NAN_BIT 0x0200000000000000 + +#define DFP128_T_START 18 + +void dissect_dfp128_float (uint64_t dword1, uint64_t dword0) { + long signbit; + signed long exponent; + unsigned long gfield_special_symbols; + unsigned long lmd_digit; + unsigned long bcd_digits[13]; + int i; + int silent = 0; // suppress leading zeros from the output. + + if (debug_show_raw_values) + printf ("DFP128R:%016lx, %016lx", dword1, dword0); + + signbit = (dword1 >> 63); + + if (signbit) printf (" -"); + else printf (" "); + + gfield_special_symbols = + ((dword1 >> DFP_SPECIAL_SYMBOLS_SHIFT) & DFP_SPECIAL_SYMBOLS_MASK); + + switch (gfield_special_symbols) { + case DFP_INF: + printf ( "inf "); + break; + + case DFP_NAN: + if (dword1 & DFP_SIGNALING_NAN_BIT) + printf ("SNaN "); + else + printf ("QNaN "); + break; + + default: + // printf ( "Finite "); + exponent = dfp128_exponent (dword1); + // printf ("Exponent: %d Bias: %d ", exponent, DFP128_EXPONENT_BIAS ); + + lmd_digit = special_field_LMD (dword1); + for (i = 0; i < 11; i++) { + bcd_digits[i] = get_bcd_digit_from_dpd ( (DFP128_T_START + + 10 * i), dword1, dword0); + } + if (lmd_digit) { + silent++; + printf ("%01lx", lmd_digit); + } else { + printf (" "); + } + for (i = 0; i < 11; i++) { + if (bcd_digits[i] || silent ) { + silent++; + printf ("%01lx", bcd_digits[i]); + } else { + /* always print at least the last zero */ + if (i == 10) + printf ("0"); + else + printf (" "); + } + } + printf (" * 10^"); + printf ("%ld", exponent); + } +} + +void print_vsr (int vsr_to_print) { +unsigned long long blob1 = 0, blob2 = 0; + switch (vsr_to_print) { + case 26: + __asm__ __volatile__ ("mfvsrd %0, 26":"=r" (blob1)); + __asm__ __volatile__ ("mfvsrld %0, 26":"=r" (blob2)); + break; + case 27: + __asm__ __volatile__ ("mfvsrd %0, 27":"=r" (blob1)); + __asm__ __volatile__ ("mfvsrld %0, 27":"=r" (blob2)); + break; + case 28: + __asm__ __volatile__ ("mfvsrd %0, 28":"=r" (blob1)); + __asm__ __volatile__ ("mfvsrld %0, 28":"=r" (blob2)); + break; + case 29: + __asm__ __volatile__ ("mfvsrd %0, 29":"=r" (blob1)); + __asm__ __volatile__ ("mfvsrld %0, 29":"=r" (blob2)); + break; + default: + printf ("Add entry for VSR %d to %s in %s.\n", vsr_to_print, __FUNCTION__, __FILE__); + } +if (debug_show_labels) + printf (" VSR (%d):", vsr_to_print); +printf (" %llx, %llx ", blob1, blob2); +} + +void print_frt () { + unsigned long long value1, value3; + if (has_frt || debug_show_all_regs ) { + if (debug_show_labels) printf (" frt%s:", has_frtp?"p":"" ); + /* If the result is a dfp128 value, the dfp128 value is + contained in the frt, frtp values which are split across + a pair of VSRs. */ + if (uses_dfp128_output) { + if (verbose) print_vsr (28); + if (verbose) print_vsr (29); + value1 = get_vsrhd_vs28 (); + value3 = get_vsrhd_vs29 (); + dissect_dfp128_float (value1, value3); + } else { + if (debug_show_raw_values) generic_print_float_as_hex (frt); + printf (" %e", frt); + if (has_frtp) { + if (debug_show_raw_values) generic_print_float_as_hex (frtp); + printf (" %e", frtp); + } + } + } +} + +/* implementation detail.. FRS and FRB use the same set of regs. */ +void print_frs_or_frb () { + unsigned long long vsrvalue1, vsrvalue3; + if (debug_show_labels) { + if (has_frs) printf (" frs%s:", has_frsp?"p":"" ); + if (has_frb) printf (" frb%s:", has_frbp?"p":"" ); + } + if (uses_dfp128_input) { + if (verbose) print_vsr (26); + if (verbose) print_vsr (27); + vsrvalue1 = get_vsrhd_vs26 (); vsrvalue3 = get_vsrhd_vs27 (); + dissect_dfp128_float (vsrvalue1, vsrvalu... [truncated message content] |
|
From: Carl L. <ca...@so...> - 2020-09-22 16:49:31
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=459d52ec1f744006dea8d695ea3e6968b04bff22 commit 459d52ec1f744006dea8d695ea3e6968b04bff22 Author: Carl Love <ca...@us...> Date: Tue Jul 28 13:17:18 2020 -0500 Add prefixed support for the following word instructions. addi Add Immediate lbz Load Byte & Zero ld Load Doubleword lfd Load Floating Double lfs Load Floating Single lha Load Halfword Algebraic lhz Load Halfword & Zero lq Load Quadword lwa Load Word Algebraic lwz Load Word & Zero lxsd Load VSX Scalar Doubleword lxssp Load VSX Scalar Single-Precision lxv Load VSX Vector stb Store Byte std Store Doubleword stfd Store Floating Double stfs Store Floating Single sth Store Halfword stq Store Quadword stw Store Word stxsd Store VSX Scalar Doubleword stxssp Store VSX Scalar Single-Precision stxv Store VSX Vector Diff: --- VEX/priv/guest_ppc_toIR.c | 1582 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 1216 insertions(+), 366 deletions(-) diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index c5016faee6..14e78aa8db 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -372,6 +372,11 @@ static UInt ifieldOPClo8 ( UInt instr) { return IFIELD( instr, 1, 8 ); } +/* Extract 4-bit secondary opcode, instr[5:1] */ +static UInt ifieldOPClo4 ( UInt instr) { + return IFIELD( instr, 0, 4 ); +} + /* Extract 5-bit secondary opcode, instr[5:1] */ static UInt ifieldOPClo5 ( UInt instr) { return IFIELD( instr, 1, 5 ); @@ -387,6 +392,15 @@ static UChar ifieldRegDS( UInt instr ) { return toUChar( IFIELD( instr, 21, 5 ) ); } +/* Extract XTp (destination register) field, instr[25:22, 21] */ +static UChar ifieldRegXTp ( UInt instr ) +{ + UChar TX = toUChar (IFIELD (instr, 21, 1)); + UChar Tp = toUChar (IFIELD (instr, 22, 4)); + /* XTp = 32 * TX + 2* Tp; Only even values of XTp can be encoded. */ + return (TX << 5) | (Tp << 1); +} + /* Extract XT (destination register) field, instr[0,25:21] */ static UChar ifieldRegXT ( UInt instr ) { @@ -3056,6 +3070,12 @@ static void set_XER_OV_OV32_ADDEX ( IRType ty, IRExpr* res, /*-----------------------------------------------------------*/ /*--- Prefix instruction helpers ---*/ /*-----------------------------------------------------------*/ +#define DFORM_IMMASK 0xffffffff +#define DSFORM_IMMASK 0xfffffffc +#define DQFORM_IMMASK 0xfffffff0 + +#define ISA_3_1_PREFIX_CHECK if (prefix) {if (!allow_isa_3_1) goto decode_noIsa3_1;} + /* ENABLE_PREFIX_CHECK is for development purposes. Turn off for production releases to improve performance. */ #define ENABLE_PREFIX_CHECK 0 @@ -3081,6 +3101,50 @@ static void set_XER_OV_OV32_ADDEX ( IRType ty, IRExpr* res, #define pType2 2 /* Modified Load/Store Instructions */ #define pType3 3 /* Modified Register-to-Register Instructions */ +/* Extract unsigned from prefix instr[17:0] */ +static UInt ifieldUIMM18 ( UInt instr ) { + return instr & 0x3FFFF; +} + +static ULong extend_s_34to64 ( UInt x ) +{ + return (ULong)((((Long)x) << 30) >> 30); +} + +static UChar PrefixType( UInt instr ) { + return toUChar( IFIELD( instr, 24, 2 ) ); +} + +static UChar ifieldR( UInt instr ) { + return toUChar( IFIELD( instr, 20, 1 ) ); +} + +/* Sign extend imm34 -> IRExpr* */ +static IRExpr* mkSzExtendS34 ( UInt imm64 ) +{ + return ( mkU64(extend_s_34to64(imm64))); +} + +/* Prefix instruction effective address calc: (rA + simm) */ +static IRExpr* ea_rA_simm34 ( UInt rA, UInt simm34 ) +{ + vassert(rA < 32); + vassert(mode64); + return binop(Iop_Add64, getIReg(rA), mkSzExtendS34(simm34)); +} + +/* Standard prefix instruction effective address calc: (rA|0) + simm16 */ +static IRExpr* ea_rAor0_simm34 ( UInt rA, UInt simm34 ) +{ + vassert(rA < 32); + vassert(mode64); + if (rA == 0) { + return mkSzExtendS34(simm34); + } else { + return ea_rA_simm34( rA, simm34 ); + } +} + static int prefix_instruction ( UInt instr ) { /* Format of first 4 bytes of prefix instruction @@ -3092,6 +3156,45 @@ static int prefix_instruction ( UInt instr ) return False; } +/* standard offset calculation, check prefix type */ +static IRExpr* calculate_prefix_EA ( UInt prefix, UInt suffixInstr, + UChar rA_addr, UInt ptype, + UInt immediate_mask, + UInt *immediate_val, + UInt *R ) +{ + IRType ty = Ity_I64; + UInt d0 = ifieldUIMM18(prefix); // Will be zero for word inst + UInt d1 = ifieldUIMM16(suffixInstr) & immediate_mask; + UInt D = CONCAT( d0, d1, 16 ); + Bool is_prefix = prefix_instruction( prefix ); + IRTemp tmp = newTemp(ty); + + if ( !is_prefix ) { + *immediate_val = extend_s_16to32( d1 ); + assign( tmp, ea_rAor0_simm( rA_addr, d1 ) ); + *R = 0; + + } else { + vassert( ty == Ity_I64 ); // prefix instructions must be 64-bit + vassert( (ptype == pType0) || (ptype == pType2) ); + *R = ifieldR( prefix ); + *immediate_val = extend_s_32to64( D ); + assign( tmp, ea_rAor0_simm34( rA_addr, D ) ); + } + + /* Get the EA */ + if ( *R == 0 ) + return mkexpr ( tmp ); + + /* Add immediate value from instruction to the current instruction + address. guest_CIA_curr_instr is pointing at the prefix, use address + of the instruction prefix. */ + return binop( Iop_Add64, + mkexpr ( tmp ), + mkU64( guest_CIA_curr_instr ) ); +} + /*------------------------------------------------------------*/ /*--- Read/write to guest-state --- */ /*------------------------------------------------------------*/ @@ -5273,6 +5376,77 @@ static Bool dis_int_mult_add ( UInt prefix, UInt theInstr ) return True; } +static Bool dis_int_arith_prefix ( UInt prefix, UInt theInstr ) +{ + + UChar opc1 = ifieldOPC(theInstr); + UChar rT_addr = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp rA = newTemp(ty); + IRTemp rT = newTemp(ty); + IRTemp tmp = newTemp(ty); + IRTemp value = newTemp(ty); + UInt si0 = ifieldUIMM18(prefix); + UInt si1 = ifieldUIMM16(theInstr); // AKA, SI + UInt ptype = PrefixType(prefix); + Long simm16 = extend_s_16to64(si1); + Bool is_prefix = prefix_instruction( prefix ); + UInt R = 0; // must be zero for word instruction + + if ( !is_prefix ) { + assign( value, mkSzExtendS16( ty, si1 )); + + } else { + vassert( ty == Ity_I64 ); // prefix instructions must be 64-bit + vassert( ptype == pType2 ); + + R = ifieldR(prefix); + assign( value, mkSzExtendS34( CONCAT( si0, si1, 16 ))); + } + + assign( rA, getIReg(rA_addr) ); + + switch (opc1) { + /* D-Form */ + + case 0x0E: // addi (Add Immediate, PPC32 p350) + // li rD,val == addi rD,0,val + // la disp(rA) == addi rD,rA,disp + + if ( rA_addr == 0 ) { + pDIP(is_prefix, "li r%u,%d", rT_addr, (Int)simm16); + DIPn(is_prefix); + assign( tmp, mkexpr( value ) ); + + } else { + pDIP(is_prefix, "addi r%u,r%u,%d", rT_addr, rA_addr, (Int)simm16); + DIPp(is_prefix, ",%u", R); + assign( tmp, binop( mkSzOp(ty, Iop_Add8), mkexpr( rA ), mkexpr( value ) ) ); + } + + if ( R == 0 ) + assign( rT, mkexpr( tmp ) ); + else + /* Add immediate value from instruction to the current instruction addr. + guest_CIA_curr_instr is pointing at the prefix, use address of the + instruction prefix. */ + assign( rT, binop( Iop_Add64, + mkU64( mkSzAddr( Ity_I64, guest_CIA_curr_instr ) ), + mkexpr( tmp ) ) ); + + break; + + default: + vex_printf("dis_int_arith_prefix(ppc)(opc1)\n"); + return False; + } + + putIReg( rT_addr, mkexpr(rT) ); + + return True; +} + static Bool dis_int_arith ( UInt prefix, UInt theInstr ) { /* D-Form, XO-Form */ @@ -7440,6 +7614,225 @@ static Bool dis_int_rot ( UInt prefix, UInt theInstr ) /* Integer Load Instructions */ +static Bool dis_int_load_ds_form_prefix ( UInt prefix, + UInt theInstr ) +{ + /* DS-Form Prefixed versions */ + UChar opc1 = ifieldOPC(theInstr); + UChar rT_addr = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + IRType ty = mode64 ? Ity_I64 : Ity_I32; + UChar b0 = ifieldBIT0(theInstr); + UChar b1 = ifieldBIT1(theInstr); + IRTemp EA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt immediate_val = 0; + UInt R = 0; + + /* Some of these instructions have different encodings for their word + versions and their prefix versions. */ + + if (opc1 == 0x29) { //plwa + pDIP( is_prefix, "lwa r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + + putIReg( rT_addr, + unop(Iop_32Sto64, load( Ity_I32, mkexpr( EA ) ) ) ); + return True; + + } else if (opc1 == 0x39) { // pld + pDIP( is_prefix, "ld r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPn( is_prefix); + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + + putIReg( rT_addr, load( Ity_I64, mkexpr( EA ) ) ); + return True; + + } else if (opc1 == 0x3A) { + /* Word version DS Form - 64bit Loads. In each case EA will have been + formed with the lowest 2 bits masked off the immediate offset. */ + UInt uimm16 = ifieldUIMM16(theInstr); + Int simm16 = extend_s_16to32(uimm16); + + simm16 = simm16 & 0xFFFFFFFC; + assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); + + switch ((b1<<1) | b0) { + case 0x0: // ld (Load DWord, PPC64 p472) + pDIP( is_prefix, "ld r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + putIReg( rT_addr, load( Ity_I64, mkexpr( EA ) ) ); + break; + + case 0x1: // ldu (Load DWord, Update, PPC64 p474) + /* There is no prefixed version of these instructions. */ + if (rA_addr == 0 || rA_addr == rT_addr) { + vex_printf("dis_int_load(ppc)(ldu,rA_addr|rT_addr)\n"); + return False; + } + DIP("ldu r%u,%u(r%u)\n", rT_addr, immediate_val, rA_addr); + + putIReg( rT_addr, load( Ity_I64, mkexpr( EA ) ) ); + putIReg( rA_addr, mkexpr( EA ) ); + break; + + case 0x2: // lwa (Load Word Alg, PPC64 p499) + pDIP( is_prefix, "lwa r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + + putIReg( rT_addr, + unop(Iop_32Sto64, load( Ity_I32, mkexpr( EA ) ) ) ); + break; + + default: + vex_printf("dis_int_load_ds_form_prefix(ppc)(0x3A, opc2)\n"); + return False; + } + return True; + } + return False; +} + +static Bool dis_int_load_prefix ( UInt prefix, UInt theInstr ) +{ + /* D-Form, X-Form, Prefixed versions */ + UChar opc1 = ifieldOPC(theInstr); + UChar rT_addr = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp EA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt size = 0; + UInt immediate_val = 0; + UInt R = 0; + IRExpr* val; + + if (opc1 == 0x22) { + // byte loads + size = Ity_I8; + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + } else if (( opc1 == 0x28 ) || ( opc1 == 0x2A )) { + // half word loads lwz, plwz, lha, plha + size = Ity_I16; + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + } else if (opc1 == 0x20 ) { + // word load + size = Ity_I32; + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + } else if (opc1 == 0x38 ) { // lq, plq + // word load + size = Ity_I64; + + if (!is_prefix) + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DQFORM_IMMASK, + &immediate_val, &R ) ); + + else + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + } + + val = load( size, mkexpr( EA ) ); + + /* Store the load value in the destination and print the instruction + details. */ + switch (opc1) { + case 0x20: // lwz (Load W & Zero, PPC32 p460) + pDIP( is_prefix, "lwz r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + + putIReg( rT_addr, mkWidenFrom32(ty, val, False) ); + break; + + case 0x22: // lbz (Load B & Zero, PPC32 p433) + pDIP( is_prefix, "lbz r%u,%u(r%u)", rT_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + putIReg( rT_addr, mkWidenFrom8( ty, val, False ) ); + break; + + case 0x28: // lhz (Load HW & Zero, PPC32 p450) + pDIP( is_prefix, "lhz r%u,%u(r%u)", rT_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + putIReg( rT_addr, mkWidenFrom16( ty, val, False ) ); + break; + + case 0x2A: // lha (Load HW Alg, PPC32 p445) + pDIP( is_prefix, "lha r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + putIReg( rT_addr, mkWidenFrom16(ty, val, True) ); + break; + + case 0x38: { // lq, plq + IRTemp high = newTemp(ty); + IRTemp low = newTemp(ty); + /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ + pDIP( is_prefix, "lq r%u,%u(r%u)", rT_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + /* NOTE: there are some changes to XER[41:42] that have not been + * implemented. + */ + //trap if EA misaligned on 16 byte address + if (mode64) { + if (host_endness == VexEndnessBE) { + assign(high, load(ty, mkexpr( EA ) ) ); + assign(low, load(ty, binop( Iop_Add64, + mkexpr( EA ), + mkU64( 8 ) ) ) ); + } else { + assign(low, load(ty, mkexpr( EA ) ) ); + assign(high, load(ty, binop( Iop_Add64, + mkexpr( EA ), + mkU64( 8 ) ) ) ); + } + } else { + assign(high, load(ty, binop( Iop_Add32, + mkexpr( EA ), + mkU32( 4 ) ) ) ); + assign(low, load(ty, binop( Iop_Add32, + mkexpr( EA ), + mkU32( 12 ) ) ) ); + } + + /* Note, the load order for lq is the same for BE and LE. However, + plq does an endian aware load. */ + if (is_prefix &&( host_endness == VexEndnessLE )) { + putIReg( rT_addr, mkexpr( low) ); + putIReg( rT_addr+1, mkexpr( high) ); + } else { + putIReg( rT_addr, mkexpr( high) ); + putIReg( rT_addr+1, mkexpr( low) ); + } + break; + } + + default: + vex_printf("dis_int_load_prefix(ppc)(opc1)\n"); + return False; + } + return True; +} + static Bool dis_int_load ( UInt prefix, UInt theInstr ) { /* D-Form, X-Form, DS-Form */ @@ -7449,7 +7842,6 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) UInt uimm16 = ifieldUIMM16(theInstr); UChar rB_addr = ifieldRegB(theInstr); UInt opc2 = ifieldOPClo10(theInstr); - UChar b1 = ifieldBIT1(theInstr); UChar b0 = ifieldBIT0(theInstr); Int simm16 = extend_s_16to32(uimm16); @@ -7469,23 +7861,12 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) simm16 = simm16 & 0xFFFFFFF0; assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); break; - case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off - // lowest 2 bits of immediate before forming EA - simm16 = simm16 & 0xFFFFFFFC; - assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); - break; default: // immediate offset assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); break; } switch (opc1) { - case 0x22: // lbz (Load B & Zero, PPC32 p433) - DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); - val = load(Ity_I8, mkexpr(EA)); - putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); - break; - case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) if (rA_addr == 0 || rA_addr == rD_addr) { vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); @@ -7497,12 +7878,6 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) putIReg( rA_addr, mkexpr(EA) ); break; - case 0x2A: // lha (Load HW Alg, PPC32 p445) - DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); - val = load(Ity_I16, mkexpr(EA)); - putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); - break; - case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) if (rA_addr == 0 || rA_addr == rD_addr) { vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); @@ -7514,12 +7889,6 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) putIReg( rA_addr, mkexpr(EA) ); break; - case 0x28: // lhz (Load HW & Zero, PPC32 p450) - DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); - val = load(Ity_I16, mkexpr(EA)); - putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); - break; - case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) if (rA_addr == 0 || rA_addr == rD_addr) { vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); @@ -7531,12 +7900,6 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) putIReg( rA_addr, mkexpr(EA) ); break; - case 0x20: // lwz (Load W & Zero, PPC32 p460) - DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); - val = load(Ity_I32, mkexpr(EA)); - putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); - break; - case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) if (rA_addr == 0 || rA_addr == rD_addr) { vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); @@ -7664,71 +8027,6 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) } break; - /* DS Form - 64bit Loads. In each case EA will have been formed - with the lowest 2 bits masked off the immediate offset. */ - case 0x3A: - switch ((b1<<1) | b0) { - case 0x0: // ld (Load DWord, PPC64 p472) - DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); - putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); - break; - - case 0x1: // ldu (Load DWord, Update, PPC64 p474) - if (rA_addr == 0 || rA_addr == rD_addr) { - vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); - return False; - } - DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); - putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); - putIReg( rA_addr, mkexpr(EA) ); - break; - - case 0x2: // lwa (Load Word Alg, PPC64 p499) - DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); - putIReg( rD_addr, - unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); - break; - - default: - vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); - return False; - } - break; - - case 0x38: { - IRTemp high = newTemp(ty); - IRTemp low = newTemp(ty); - /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ - DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); - /* NOTE: there are some changes to XER[41:42] that have not been - * implemented. - */ - // trap if EA misaligned on 16 byte address - if (mode64) { - if (host_endness == VexEndnessBE) { - assign(high, load(ty, mkexpr( EA ) ) ); - assign(low, load(ty, binop( Iop_Add64, - mkexpr( EA ), - mkU64( 8 ) ) ) ); - } else { - assign(low, load(ty, mkexpr( EA ) ) ); - assign(high, load(ty, binop( Iop_Add64, - mkexpr( EA ), - mkU64( 8 ) ) ) ); - } - } else { - assign(high, load(ty, binop( Iop_Add32, - mkexpr( EA ), - mkU32( 4 ) ) ) ); - assign(low, load(ty, binop( Iop_Add32, - mkexpr( EA ), - mkU32( 12 ) ) ) ); - } - gen_SIGBUS_if_misaligned( EA, 16 ); - putIReg( rD_addr, mkexpr( high) ); - putIReg( rD_addr+1, mkexpr( low) ); - break; - } default: vex_printf("dis_int_load(ppc)(opc1)\n"); return False; @@ -7741,24 +8039,190 @@ static Bool dis_int_load ( UInt prefix, UInt theInstr ) /* Integer Store Instructions */ -static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) +static Bool dis_int_store_ds_prefix ( UInt prefix, + UInt theInstr, const VexAbiInfo* vbi) { - /* D-Form, X-Form, DS-Form */ UChar opc1 = ifieldOPC(theInstr); UInt rS_addr = ifieldRegDS(theInstr); UInt rA_addr = ifieldRegA(theInstr); - UInt uimm16 = ifieldUIMM16(theInstr); - UInt rB_addr = ifieldRegB(theInstr); - UInt opc2 = ifieldOPClo10(theInstr); - UChar b1 = ifieldBIT1(theInstr); UChar b0 = ifieldBIT0(theInstr); - + UChar b1 = ifieldBIT1(theInstr); + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp rS = newTemp(ty); + IRTemp EA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt R = 0; // must be zero for word instruction + UInt immediate_val = 0; + Int simm16 = extend_s_16to32(ifieldUIMM16(theInstr)); + + if (opc1 == 0x3C) { + // force opc2 to 2 to map pstq to stq inst + b0 = 0; + b1 = 1; + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + } else if (opc1 == 0x3D) { + // force opc2 to 0 to map pstd to std inst + b0 = 0; + b1 = 0; + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + + } else if ( opc1 == 0x3 ) { + + assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); + + } else if ( opc1 == 0x3E ) { + // lowest 2 bits of immediate before forming EA + immediate_val = simm16 & 0xFFFFFFFC; + assign( EA, ea_rAor0_simm( rA_addr, immediate_val ) ); + + } else { + return False; + } + + assign( rS, getIReg(rS_addr) ); + + /* DS Form - 64bit Stores. In each case EA will have been formed + with the lowest 2 bits masked off the immediate offset. */ + switch ((b1<<1) | b0) { + case 0x0: // std (Store DWord, PPC64 p580) + if (!mode64) + return False; + + pDIP( is_prefix,"std r%u,%u(r%u)", rS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + store( mkexpr(EA), mkexpr(rS) ); + break; + + case 0x1: // stdu (Store DWord, Update, PPC64 p583) + /* Note this instruction is handled here but it isn't actually a + prefix instruction. Just makes the parsing easier to handle it + here. */ + if (!mode64) + return False; + + DIP("stdu r%u,%u(r%u)\n", rS_addr, immediate_val, rA_addr); + putIReg( rA_addr, mkexpr(EA) ); + store( mkexpr(EA), mkexpr(rS) ); + break; + + case 0x2: // stq, pstq (Store QuadWord, Update, PPC64 p583) + { + IRTemp EA_hi = newTemp(ty); + IRTemp EA_lo = newTemp(ty); + + pDIP( is_prefix, "stq r%u,%u(r%u)", rS_addr, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + + if (mode64) { + if (host_endness == VexEndnessBE) { + + /* upper 64-bits */ + assign( EA_hi, ea_rAor0_simm( rA_addr, immediate_val ) ); + + /* lower 64-bits */ + assign( EA_lo, ea_rAor0_simm( rA_addr, immediate_val+8 ) ); + } else { + /* upper 64-bits */ + assign( EA_hi, ea_rAor0_simm( rA_addr, immediate_val+8 ) ); + + /* lower 64-bits */ + assign( EA_lo, ea_rAor0_simm( rA_addr, immediate_val ) ); + } + } else { + /* upper half of upper 64-bits */ + assign( EA_hi, ea_rAor0_simm( rA_addr, immediate_val+4 ) ); + + /* lower half of upper 64-bits */ + assign( EA_lo, ea_rAor0_simm( rA_addr, immediate_val+12 ) ); + } + + /* Note, the store order for stq instruction is the same for BE + and LE. The store order for the pstq instruction is endian aware + store. */ + if (is_prefix &&( host_endness == VexEndnessLE )) { + // LE and pstq + store( mkexpr(EA_hi), getIReg( rS_addr+1 ) ); + store( mkexpr(EA_lo), mkexpr(rS) ); + } else { + store( mkexpr(EA_hi), mkexpr(rS) ); + store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); + } + break; + } + default: + vex_printf("dis_int_store_ds_prefix(ppc)(opc1)\n"); + return False; + } + return True; +} + +static Bool dis_int_store_prefix ( UInt prefix, + UInt theInstr, const VexAbiInfo* vbi) +{ + UChar opc1 = ifieldOPC(theInstr); + UInt rS_addr = ifieldRegDS(theInstr); + UInt rA_addr = ifieldRegA(theInstr); + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp rS = newTemp(ty); + IRTemp EA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt immediate_val = 0; + UInt R = 0; // must be zero for word instruction + + assign( rS, getIReg(rS_addr) ); + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + switch (opc1) { + case 0x24: // stw (Store W, PPC32 p530) + pDIP( is_prefix, "stw r%u,%u(r%u)\n", rS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); + break; + + case 0x26: // stb (Store B, PPC32 p509) + pDIP( is_prefix, "stb r%u,%u(r%u)", rS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); + break; + + case 0x2C: // sth (Store HW, PPC32 p522) + pDIP( is_prefix, "sth r%u,%u(r%u)", rS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); + break; + + default: + vex_printf("dis_int_store_prefix(ppc)(opc1)\n"); + return False; + } + return True; +} + +static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) +{ + /* D-Form, X-Form, DS-Form */ + UChar opc1 = ifieldOPC(theInstr); + UInt rS_addr = ifieldRegDS(theInstr); + UInt rA_addr = ifieldRegA(theInstr); + UInt uimm16 = ifieldUIMM16(theInstr); + UInt rB_addr = ifieldRegB(theInstr); + UInt opc2 = ifieldOPClo10(theInstr); + UChar b0 = ifieldBIT0(theInstr); + Int simm16 = extend_s_16to32(uimm16); IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp rS = newTemp(ty); IRTemp rB = newTemp(ty); IRTemp EA = newTemp(ty); - + /* There is no prefixed version of these instructions. */ PREFIX_CHECK @@ -7769,9 +8233,7 @@ static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) case 0x1F: // register offset assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); break; - case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off - // lowest 2 bits of immediate before forming EA - simm16 = simm16 & 0xFFFFFFFC; + /* fallthrough */ default: // immediate offset assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); @@ -7779,11 +8241,6 @@ static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) } switch (opc1) { - case 0x26: // stb (Store B, PPC32 p509) - DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); - store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); - break; - case 0x27: // stbu (Store B, Update, PPC32 p510) if (rA_addr == 0 ) { vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); @@ -7794,11 +8251,6 @@ static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); break; - case 0x2C: // sth (Store HW, PPC32 p522) - DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); - store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); - break; - case 0x2D: // sthu (Store HW, Update, PPC32 p524) if (rA_addr == 0) { vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); @@ -7900,64 +8352,6 @@ static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) } break; - /* DS Form - 64bit Stores. In each case EA will have been formed - with the lowest 2 bits masked off the immediate offset. */ - case 0x3E: - switch ((b1<<1) | b0) { - case 0x0: // std (Store DWord, PPC64 p580) - if (!mode64) - return False; - - DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); - store( mkexpr(EA), mkexpr(rS) ); - break; - - case 0x1: // stdu (Store DWord, Update, PPC64 p583) - if (!mode64) - return False; - - DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); - putIReg( rA_addr, mkexpr(EA) ); - store( mkexpr(EA), mkexpr(rS) ); - break; - - case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) - IRTemp EA_hi = newTemp(ty); - IRTemp EA_lo = newTemp(ty); - DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); - - if (mode64) { - if (host_endness == VexEndnessBE) { - - /* upper 64-bits */ - assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); - - /* lower 64-bits */ - assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); - } else { - /* upper 64-bits */ - assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); - - /* lower 64-bits */ - assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); - } - } else { - /* upper half of upper 64-bits */ - assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); - - /* lower half of upper 64-bits */ - assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); - } - store( mkexpr(EA_hi), mkexpr(rS) ); - store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); - break; - } - default: - vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); - return False; - } - break; - default: vex_printf("dis_int_store(ppc)(opc1)\n"); return False; @@ -10482,6 +10876,47 @@ static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) /* Floating Point Load Instructions */ +static Bool dis_fp_load_prefix ( UInt prefix, UInt theInstr ) +{ + /* X-Form, D-Form */ + UChar opc1 = ifieldOPC(theInstr); + UChar frT_addr = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp EA = newTemp(ty); + IRTemp rA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt R = 0; // must be zero for word instruction + UInt immediate_val = 0; + + assign( rA, getIReg(rA_addr) ); + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + switch (opc1) { + case 0x30: // lfs (Load Float Single, PPC32 p441) + pDIP( is_prefix, "lfs fr%u,%u(r%u)\n", frT_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + putFReg( frT_addr, + unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); + break; + + case 0x32: // lfd (Load Float Double, PPC32 p437) + pDIP( is_prefix, "lfd fr%u,%u(r%u)\n", frT_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + putFReg( frT_addr, load(Ity_F64, mkexpr(EA)) ); + break; + + default: + vex_printf("dis_fp_load_prefix(ppc)(opc1)\n"); + return False; + } + return True; +} + static Bool dis_fp_load ( UInt prefix, UInt theInstr ) { /* X-Form, D-Form */ @@ -10623,6 +11058,57 @@ static Bool dis_fp_load ( UInt prefix, UInt theInstr ) /* Floating Point Store Instructions */ +static Bool dis_fp_store_prefix ( UInt prefix, UInt theInstr ) +{ + /* X-Form, D-Form */ + UChar opc1 = ifieldOPC(theInstr); + UChar frS_addr = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp frS = newTemp(Ity_F64); + IRTemp EA = newTemp(ty); + IRTemp rA = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt R = 0; // must be zero for word instruction + UInt immediate_val = 0; + + assign( frS, getFReg( frS_addr ) ); + assign( rA, getIReg( rA_addr ) ); + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DFORM_IMMASK, + &immediate_val, &R ) ); + + /* These are straightforward from a status bits perspective: no + funny status or CR bits affected. For single precision stores, + the values are truncated and denormalised (not rounded) to turn + them into single precision values. */ + + switch (opc1) { + + case 0x34: // stfs (Store Float Single, PPC32 p518) + pDIP( is_prefix, "stfs fr%u,%u(r%u)\n", frS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + /* Use Iop_TruncF64asF32 to truncate and possible denormalise + the value to be stored in the correct way, without any + rounding. */ + store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); + break; + + case 0x36: // stfd (Store Float Double, PPC32 p513) + pDIP( is_prefix, "stfd fr%u,%u(r%u)", frS_addr, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + store( mkexpr(EA), mkexpr(frS) ); + break; + + default: + vex_printf("dis_fp_store_prefix(ppc)(opc1)\n"); + return False; + } + return True; +} + static Bool dis_fp_store ( UInt prefix, UInt theInstr ) { /* X-Form, D-Form */ @@ -10654,16 +11140,6 @@ static Bool dis_fp_store ( UInt prefix, UInt theInstr ) them into single precision values. */ switch (opc1) { - - case 0x34: // stfs (Store Float Single, PPC32 p518) - DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); - assign( EA, ea_rAor0_simm(rA_addr, simm16) ); - /* Use Iop_TruncF64asF32 to truncate and possible denormalise - the value to be stored in the correct way, without any - rounding. */ - store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); - break; - case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) if (rA_addr == 0) return False; @@ -10673,13 +11149,6 @@ static Bool dis_fp_store ( UInt prefix, UInt theInstr ) store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); putIReg( rA_addr, mkexpr(EA) ); break; - - case 0x36: // stfd (Store Float Double, PPC32 p513) - DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); - assign( EA, ea_rAor0_simm(rA_addr, simm16) ); - store( mkexpr(EA), mkexpr(frS) ); - break; - case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) if (rA_addr == 0) return False; @@ -11725,6 +12194,7 @@ static Bool dis_fp_round ( UInt prefix, UInt theInstr ) assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); goto putFR; } + return True; } @@ -11864,29 +12334,318 @@ static Bool dis_fp_round ( UInt prefix, UInt theInstr ) )); break; - default: - vex_printf("dis_fp_round(ppc)(opc2)\n"); - return False; - } -putFR: - putFReg( frD_addr, mkexpr(frD) ); + default: + vex_printf("dis_fp_round(ppc)(opc2)\n"); + return False; + } +putFR: + putFReg( frD_addr, mkexpr(frD) ); + + if (set_FPRF) { + // XXX XXX XXX FIXME + // set FPRF from frD + } + + if (flag_rC && clear_CR1) { + putCR321( 1, mkU8(0) ); + putCR0( 1, mkU8(0) ); + } + + return True; +} + +/* + Floating Point Pair Instructions +*/ +static Bool dis_fp_pair_prefix ( UInt prefix, UInt theInstr ) +{ + /* X-Form/DS-Form */ + UChar opc1 = ifieldOPC(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + IRType ty = mode64 ? Ity_I64 : Ity_I32; + IRTemp EA = newTemp(ty); + IRTemp EA_16 = newTemp(ty); + UInt ptype = PrefixType(prefix); + Bool is_prefix = prefix_instruction( prefix ); + UInt R = 0; + UInt immediate_val = 0; + UInt opc2; + + switch (opc1) { + case 0x6: + { + UChar XTp = ifieldRegXTp(theInstr); + opc2 = ifieldOPClo4(theInstr); + + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DQFORM_IMMASK, + &immediate_val, &R ) ); + + switch (opc2) { + + case 0: + { + /* Endian aware load */ + pDIP( is_prefix, "lxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + if (is_prefix && (R == 1) ) { + vex_printf("Illegal instruction R = 1; plxvp %u,%u(%u)\n", + XTp, immediate_val, rA_addr ); + return False; + } + + // address of next 128bits + assign( EA_16, binop( Iop_Add64, mkU64( 16), mkexpr( EA ) ) ); + if (host_endness == VexEndnessLE) { + putVSReg( XTp, load( Ity_V128, mkexpr( EA ) ) ); + putVSReg( XTp+1, load( Ity_V128, mkexpr( EA_16 ) ) ); + } else { + putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) ); + putVSReg( XTp, load( Ity_V128, mkexpr( EA_16 ) ) ); + } + break; + } + + case 1: + { + IRTemp EA_8 = newTemp(ty); + IRTemp EA_24 = newTemp(ty); + /* Endian aware store */ + pDIP( is_prefix, "stxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + if ( is_prefix && ( R == 1 ) ) { + vex_printf("Illegal instruction R = 1; pstxvp %u,%u(%u)\n", + XTp, immediate_val, rA_addr ); + return False; + } + + // address of next 128bits + assign( EA_8, binop( Iop_Add64, mkU64( 8 ), mkexpr( EA ) ) ); + assign( EA_16, binop( Iop_Add64, mkU64( 16 ), mkexpr( EA ) ) ); + assign( EA_24, binop( Iop_Add64, mkU64( 24 ), mkexpr( EA ) ) ); + + if (host_endness == VexEndnessBE) { + store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp ) ) ); + store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) ); + store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) ); + store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) ); + } else { + store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) ); + store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) ); + store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp ) ) ); + store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) ); + } + break; + } + + default: + vex_printf("dis_fp_pair_prefix\n"); + return False; + } + return True; + } + break; + + case 0x2A: // plxsd + case 0x2B: // plxssp + case 0x39: // lxsd, lxssp + { + UChar vRT = ifieldRegDS(theInstr); + opc2 = ifieldOPC0o2(theInstr); + if (opc1 == 0x2A) + opc2 = 0x2; // map plxsd to lxsd inst + + if (opc1 == 0x2B) + opc2 = 0x3; // map plxssp to lxssp inst + + /* The word version uses the DS-form. */ + assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr, + ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + + switch(opc2) { + case 0x2: // lxsd (Load VSX Scalar Doubleword) + pDIP( is_prefix, "lxsd v%u,%u(r%u)\n", vRT, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + putVSReg( vRT+32, binop( Iop_64HLtoV128, + load( Ity_I64, mkexpr( EA ) ), + mkU64( 0 ) ) ); + return True; + + case 0x3: // lxssp (Load VSX Scalar Single from memory, + // store as double in register) + pDIP( is_prefix, "lxssp v%u,%u(r%u)\n", vRT, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + putVSReg( vRT+32, + binop( Iop_64HLtoV128, + unop( Iop_ReinterpF64asI64, + unop( Iop_F32toF64, + unop( Iop_ReinterpI32asF32, + load( Ity_I32, mkexpr( EA ) ) + ) ) ), + mkU64( 0 ) ) ); + return True; + + default: + vex_printf("dis_fp_pair_prefix(ppc) : DS-form wrong opc2\n"); + return False; + } + break; + } + + case 0x2E: // pstxsd + case 0x2F: // pstxssp + case 0x3d: // lxv, stxv, stxsd, stxssp, pstd + case 0x32: // plxv (TX=0) + case 0x33: // plxv (TX=1) + case 0x36: // pstxv + { + UChar vRS = ifieldRegDS(theInstr); + UInt TX = IFIELD( theInstr, 3, 1); // default TX or SX bit field + + opc2 = IFIELD(theInstr, 0, 3); + + if ((opc1 == 0x32) || (opc1 == 0x33)) { + TX = IFIELD( theInstr, 26, 1); // TX special case + opc2 = 1; // Force plxv to match lxv case + } + if (opc1 == 0x2E) opc2 = 2; // Map pstxsd inst to stxsd + if (opc1 == 0x2F) opc2 = 3; // Map pstxssp inst to stxssp + if (opc1 == 0x36) { + opc2 = 5; // Map pstxv inst to stxv + TX = IFIELD( theInstr, 26, 1); // Actually SX in the ISA + } + if ((opc2 == 0x1) || (opc2 == 0x5)) { // lxv, stxv, stxsd + UInt ea_off = 8; + IRTemp word[2]; + IRExpr* irx_addr; + UInt T = IFIELD( theInstr, 21, 5); // T or S depending on inst + + /* Effective address calculation */ + if (opc1 == 0x3D) { + UInt uimm16 = ifieldUIMM16(theInstr); + Int simm16 = extend_s_16to32(uimm16); + + simm16 = simm16 & DQFORM_IMMASK; + assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); + + } else { + assign( EA, + calculate_prefix_EA( prefix, theInstr, rA_addr, ptype, + DFORM_IMMASK, &immediate_val, &R ) ); + } + + word[0] = newTemp(Ity_I64); + word[1] = newTemp(Ity_I64); + + if ( opc2 == 1) { + // lxv (Load VSX Vector) + pDIP( is_prefix, "lxv v%u,%u(r%u)\n", vRS, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + assign( word[0], load( Ity_I64, mkexpr( EA ) ) ); + + irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), + ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); + + assign( word[1], load( Ity_I64, irx_addr ) ); + + if (host_endness == VexEndnessBE) + putVSReg( TX*32+T, binop( Iop_64HLtoV128, + mkexpr( word[0] ), + mkexpr( word[1] ) ) ); + else + putVSReg( TX*32+T, binop( Iop_64HLtoV128, + mkexpr( word[1] ), + mkexpr( word[0] ) ) ); + return True; + + } else if ( opc2 == 5) { + // stxv (Store VSX Vector) + pDIP( is_prefix, "stxv v%u,%u(r%u)\n", vRS, immediate_val, rA_addr ); + DIPp( is_prefix, ",%u", R ); + + if (host_endness == VexEndnessBE) { + store( mkexpr(EA), unop( Iop_V128HIto64, + getVSReg( TX*32+T ) ) ); + irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), + ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); + store( irx_addr, unop( Iop_V128to64, + getVSReg( TX*32+T ) ) ); + } else { + store( mkexpr(EA), unop( Iop_V128to64, + getVSReg( TX*32+T ) ) ); + irx_addr + = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), + ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); + store( irx_addr, unop( Iop_V128HIto64, + getVSReg( TX*32+T ) ) ); + } + return True; + + } else + return False; + + break; + + } else if ((opc2 & 0x3) == 0x2) { + // stxsd (Store VSX Scalar Doubleword) + pDIP( is_prefix, "stxsd v%u,%u(r%u)\n", vRS, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + store( mkexpr(EA), unop( Iop_V128HIto64, + getVSReg( vRS+32 ) ) ); + /* HW is clearing vector element 1. Don't see that in the ISA but + * matching the HW. + */ + putVSReg( vRS+32, binop( Iop_64HLtoV128, + unop( Iop_V128HIto64, + getVSReg( vRS+32 ) ), + mkU64( 0 ) ) ); + return True; + + } else if ((opc2 & 0x3) == 0x3) { + // stxssp (Store VSX Scalar Single - store double precision + // value from register into memory in single precision format) + IRTemp high64 = newTemp(Ity_F64); + IRTemp val32 = newTemp(Ity_I32); + + pDIP( is_prefix, "stxssp v%u,%u(r%u)\n", vRS, immediate_val, rA_addr); + DIPp( is_prefix, ",%u", R ); + + assign( EA, calculate_prefix_EA( prefix, theInstr, + rA_addr, ptype, DSFORM_IMMASK, + &immediate_val, &R ) ); + assign(high64, unop( Iop_ReinterpI64asF64, + unop( Iop_V128HIto64, getVSReg( vRS+32 ) ) ) ); + + assign(val32, unop( Iop_ReinterpF32asI32, + unop( Iop_TruncF64asF32, + mkexpr(high64) ) ) ); + store( mkexpr(EA), mkexpr( val32 ) ); - if (set_FPRF) { - // XXX XXX XXX FIXME - // set FPRF from frD - } + return True; - if (flag_rC && clear_CR1) { - putCR321( 1, mkU8(0) ); - putCR0( 1, mkU8(0) ); + } else { + vex_printf("dis_fp_pair_prefix(ppc) : DS-form wrong opc2\n"); + return False; + } + break; } - return True; + default: + vex_printf("dis_fp_pair_prefix(ppc)(instr)\n"); + return False; + } + return False; } -/* - Floating Point Pair Instructions -*/ static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) { /* X-Form/DS-Form */ @@ -11940,10 +12699,6 @@ static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) break; case 0x39: { - UInt DS = IFIELD( theInstr, 2, 14); - UChar vRT = ifieldRegDS(theInstr); - IRTemp EA = newTemp( ty ); - opc2 = ifieldOPC0o2(theInstr); switch(opc2) { @@ -11961,31 +12716,6 @@ static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) is_load = 1; break; - case 0x2: // lxsd (Load VSX Scalar Doubleword) - DIP("lxsd v%u,%u(r%u)\n", vRT, DS, rA_addr); - - assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); - - putVSReg( vRT+32, binop( Iop_64HLtoV128, - load( Ity_I64, mkexpr( EA ) ), - mkU64( 0 ) ) ); - return True; - - case 0x3: // lxssp (Load VSX Scalar Single from memory, - // store as double in register) - DIP("lxssp v%u,%u(r%u)\n", vRT, DS, rA_addr); - - assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); - - putVSReg( vRT+32, - binop( Iop_64HLtoV128, - unop( Iop_ReinterpF64asI64, - unop( Iop_F32toF64, - unop( Iop_ReinterpI32asF32, - load( Ity_I32, mkexpr( EA ) ) ) ) ), - mkU64( 0 ) ) ); - return True; - default: vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); return False; @@ -11994,10 +12724,6 @@ static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) } case 0x3d: { - UInt DS = IFIELD( theInstr, 2, 14); - UChar vRS = ifieldRegDS(theInstr); - IRTemp EA = newTemp( ty ); - opc2 = ifieldOPC0o2(theInstr); switch(opc2) { @@ -12015,104 +12741,6 @@ static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); break; - case 0x1: - { - UInt ea_off = 8; - IRTemp word[2]; - IRExpr* irx_addr; - UInt T = IFIELD( theInstr, 21, 5); // T or S depending on inst - UInt TX = IFIELD( theInstr, 3, 1); // TX or SX field - - word[0] = newTemp(Ity_I64); - word[1] = newTemp(Ity_I64); - DS = IFIELD( theInstr, 4, 12); // DQ in the instruction definition - assign( EA, ea_rAor0_simm( rA_addr, DS<<4 ) ); - - if ( IFIELD( theInstr, 0, 3) == 1) { - // lxv (Load VSX Vector) - DIP("lxv v%u,%u(r%u)\n", vRS, DS, rA_addr); - - assign( word[0], load( Ity_I64, mkexpr( EA ) ) ); - - irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), - ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); - - assign( word[1], load( Ity_I64, irx_addr ) ); - - if (host_endness == VexEndnessBE) - putVSReg( TX*32+T, binop( Iop_64HLtoV128, - mkexpr( word[0] ), - mkexpr( word[1] ) ) ); - else - putVSReg( TX*32+T, binop( Iop_64HLtoV128, - mkexpr( word[1] ), - mkexpr( word[0] ) ) ); - return True; - - } else if ( IFIELD( theInstr, 0, 3) == 5) { - // stxv (Store VSX Vector) - DIP("stxv v%u,%u(r%u)\n", vRS, DS, rA_addr); - - if (host_endness == VexEndnessBE) { - store( mkexpr(EA), unop( Iop_V128HIto64, - getVSReg( TX*32+T ) ) ); - irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), - ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); - store( irx_addr, unop( Iop_V128to64, - getVSReg( TX*32+T ) ) ); - } else { - store( mkexpr(EA), unop( Iop_V128to64, - getVSReg( TX*32+T ) ) ); - irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), - ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); - store( irx_addr, unop( Iop_V128HIto64, - getVSReg( TX*32+T ) ) ); - } - return True; - - } else { - vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n"); - return False; - } - break; - } - case 0x2: - // stxsd (Store VSX Scalar Doubleword) - DIP("stxsd v%u,%u(r%u)\n", vRS, DS, rA_addr); - - assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); - - store( mkexpr(EA), unop( Iop_V128HIto64, - getVSReg( vRS+32 ) ) ); - /* HW is clearing vector element 1. Don't see that in the ISA but - * matching the HW. - */ - putVSReg( vRS+32, binop( Iop_64HLtoV128, - unop( Iop_V128HIto64, - getVSReg( vRS+32 ) ), - mkU64( 0 ) ) ); - return True; - - case 0x3: - { - // stxssp (Store VSX Scalar Single - store double precision - // value from register into memory in single precision format) - IRTemp high64 = newTemp(Ity_F64); - IRTemp val32 = newTemp(Ity_I32); - - DIP("stxssp v%u,%u(r%u)\n", vRS, DS, rA_addr); - - assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); - assign(high64, unop( Iop_ReinterpI64asF64, - unop( Iop_V128HIto64, getVSReg( vRS+32 ) ) ) ); - - assign(val32, unop( Iop_ReinterpF32asI32, - unop( Iop_TruncF64asF32, - mkexpr(high64) ) ) ); - store( mkexpr(EA), mkexpr( val32 ) ); - - return True; - } default: vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); return False; @@ -29042,7 +29670,12 @@ DisResult disInstr_PPC_WRK ( switch (opc1) { /* Integer Arithmetic Instructions */ - case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi + case 0x0E: // addi + ISA_3_1_PREFIX_CHECK + if (dis_int_arith_prefix( prefix, theInstr )) goto decode_success; + goto decode_failure; + + case 0x0C: case 0x0D: // addic, addic. case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic if (dis_int_arith( prefix, theInstr )) goto decode_success; goto decode_failure; @@ -29054,10 +29687,15 @@ DisResult disInstr_PPC_WRK ( /* Integer Logical Instructions */ case 0x1C: case 0x1D: case 0x18: // andi., andis., ori - case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris + case 0x1A: case 0x1B: // xori, xoris if (dis_int_logic( prefix, theInstr )) goto decode_success; goto decode_failure; + case 0x19: // oris + if (dis_int_logic( prefix, theInstr )) //oris + goto decode_success; + goto decode_failure; + /* Integer Rotate Instructions */ case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm if (dis_int_rot( prefix, theInstr )) goto decode_success; @@ -29070,21 +29708,94 @@ DisResult disInstr_PPC_WRK ( goto decode_failure; /* Integer Load Instructions */ - case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha - case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu - case 0x20: case 0x21: // lwz, lwzu + case 0x20: // lwz + case 0x22: // lbz + ISA_3_1_PREFIX_CHECK + if (dis_int_load_prefix( prefix, theInstr )) + goto decode_success; + goto decode_failure; + + case 0x21: case 0x23: // lwzu, lbzu if (dis_int_load( prefix, theInstr )) goto decode_success; goto decode_failure; /* Integer Store Instructions */ - case 0x26: case 0x27: case 0x2C: // stb, stbu, sth - case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu + case 0x26: case 0x2C: case 0x24: // stb, sth, stw + ISA_3_1_PREFIX_CHECK + if (dis_int_store_prefix( prefix, theInstr, abiinfo )) + goto decode_success; + goto decode_failure; + + case 0x27: case 0x2D: case 0x25: // stbu, sthu, stwu if (dis_int_store( prefix, theInstr, abiinfo )) goto decode_success; goto decode_failure; + case 0x28: // lhz + ISA_3_1_PREFIX_CHECK + if (dis_int_load_prefix( prefix, theInstr )) + goto decode_success; + goto decode_failure; + + case 0x29: // lhzu, plwa + if (prefix_instruction( prefix)) { + if ( !(allow_isa_3_1) ) goto decode_noIsa3_1; + // prefix inst: plwa + if (dis_int_load_ds_form_prefix( prefix, theInstr )) + goto decode_success; + } else { + // lhzu + if (dis_int_load( prefix, theInstr )) goto decode_success; + } + goto decode_failure; + + case 0x2A: // lha, plha, plxsd + { + if (prefix_instruction( prefix )) { + UInt ptype = PrefixType(prefix); + if ( !(allow_isa_3_1) ) goto decode_noIsa3_1; + if (ptype == pType0) { + if (dis_fp_pair_prefix( prefix, theInstr )) // plxsd + goto decode_success; + } else if (ptype == pType2) { + if (dis_int_load_prefix( prefix, theInstr )) // plha + goto decode_success; + } + } else { + if (dis_int_load_prefix( prefix, theInstr )) // lha + goto decode_success; + } + } + goto decode_failure; + + case 0x2B: // lhau, plxssp + if (prefix_instruction( prefix)) { + if ( !(allow_isa_3_1) ) goto decode_noIsa3_1; + if (dis_fp_pair_prefix( prefix, theInstr )) // plxssp + goto decode_success; + } else { + if (dis_int_load( prefix, theInstr )) + goto decode_success; + } + goto decode_failure; + /* Integer Load and Store Multiple Instructions */ - case 0x2E: case 0x2F: // lmw, stmw - if (dis_int_ldst_mult( prefix, theInstr )) goto decode_success; + case 0x2E: + if (prefix_instruction( prefix )) { // pstxsd + if ( !(allow_isa_3_1) ) goto decode_noIsa3_1; + if (dis_fp_pair_prefix( prefix, theInstr )) goto decode_success; + } else { // lmw, + if (dis_int_ldst_mult( prefix, theInstr )) goto decode_success; + } + goto decode_failure; + + case 0x2F: + if (prefix_instruction( prefix )) { // pstxssp + if ( !(allow_isa_3_1) ) goto decode_noIsa3_1; + if (dis_fp_pair_prefix( prefix, theInstr )) goto decode_success; + } else { // stmw + if (dis_int_ldst_mult( prefix, th... [truncated message content] |
|
From: Carl L. <ca...@so...> - 2020-09-22 16:49:17
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=ad293d5168c7966329681da62a952183b61d5a05 commit ad293d5168c7966329681da62a952183b61d5a05 Author: Carl Love <ce...@us...> Date: Wed May 6 15:27:32 2020 -0500 Instruction Prefix Support Diff: --- VEX/priv/guest_ppc_toIR.c | 986 +++++++++++++++++++++++++++++++++------------- VEX/pub/libvex.h | 1 + 2 files changed, 718 insertions(+), 269 deletions(-) diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 96217fb054..c5016faee6 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -274,11 +274,30 @@ static Bool OV32_CA32_supported = False; #define SIGN_BIT32 0x80000000 #define SIGN_MASK32 0x7fffffff +/* The instruction size can be either 4 byte (word instruction) or 8 bytes + (prefix instruction) starting with ISA 3.1 */ +#define WORD_INST_SIZE 4 +#define PREFIX_INST_SIZE 8 /*------------------------------------------------------------*/ /*--- Debugging output ---*/ /*------------------------------------------------------------*/ +/* Pre DIP macro for prefix instruction printing. */ +#define pDIP(flag,format, args...) \ + if (vex_traceflags & VEX_TRACE_FE){ \ + if (flag) {vex_printf("p"); vex_printf(format, ## args);} \ + else {vex_printf(format, ## args); vex_printf("\n");}} + +/* Post DIP macro to print additional args for prefix instruction printing. */ +#define DIPp(flag,format, args...) \ + if (vex_traceflags & VEX_TRACE_FE) { \ + if (flag) {vex_printf(format, ## args); vex_printf("\n");}} + +/* Post DIP macro with no additional args for prefix instruction printing. */ +#define DIPn(flag) \ + if (vex_traceflags & VEX_TRACE_FE) {if (flag) vex_printf("\n");} + #define DIP(format, args...) \ if (vex_traceflags & VEX_TRACE_FE) \ vex_printf(format, ## args) @@ -532,7 +551,11 @@ static ULong MASK64( UInt begin, UInt end ) static Addr64 nextInsnAddr( void ) { - return guest_CIA_curr_instr + 4; + /* Note in the case of a prefix instruction, delta has already been + incremented by WORD_INST_SIZE to move past the prefix part of the + instruction. So only need to increment by WORD_INST_SIZE to get to + the start of the next instruction. */ + return guest_CIA_curr_instr + WORD_INST_SIZE; } @@ -1602,6 +1625,9 @@ typedef enum { DWORD } _popcount_data_type; +/*-----------------------------------------------------------*/ +/*--- IR popcount helpers ---*/ +/*-----------------------------------------------------------*/ /* Generate an IR sequence to do a popcount operation on the supplied IRTemp, and return a new IRTemp holding the result. 'ty' may be Ity_I32 or Ity_I64 only. */ @@ -3027,7 +3053,44 @@ static void set_XER_OV_OV32_ADDEX ( IRType ty, IRExpr* res, } } +/*-----------------------------------------------------------*/ +/*--- Prefix instruction helpers ---*/ +/*-----------------------------------------------------------*/ +/* ENABLE_PREFIX_CHECK is for development purposes. Turn off for production + releases to improve performance. */ +#define ENABLE_PREFIX_CHECK 0 + +#if ENABLE_PREFIX_CHECK +#define PREFIX_CHECK { vassert( !prefix_instruction( prefix ) ); } +#else +#define PREFIX_CHECK { } +#endif + +/* Bits 0:5 of all prefix instructions are assigned the primary opcode + value 0b000001. 0b000001 is not available for use as a primary opcode for + either word instructions or suffixes of prefixed instructions. */ + +#define PREFIX_INST 0x1 +#define PREFIX_NOP_INVALID -1 + +#define CONCAT(_aa,_bb,_cc) ((_aa) << (_cc) | (_bb)) +/* The codes for the prefix types */ +#define pType0 0 /* Eight-Byte Load/Store Instructions */ +#define pType1 1 /* Eight-Byte Register-to-Register Instructions */ +#define pType2 2 /* Modified Load/Store Instructions */ +#define pType3 3 /* Modified Register-to-Register Instructions */ + +static int prefix_instruction ( UInt instr ) +{ + /* Format of first 4 bytes of prefix instruction + bits [0:5] - must be 0x1 identifying this as a prefix inst + bits [6:7] - prefix instruction type. */ + UChar opcode = IFIELD( instr, 26, 6); + + if (opcode == PREFIX_INST) return True; + return False; +} /*------------------------------------------------------------*/ /*--- Read/write to guest-state --- */ @@ -5107,7 +5170,7 @@ static void storeTMfailure( Addr64 err_address, ULong tm_reason, /* Integer Arithmetic Instructions */ -static Bool dis_int_mult_add ( UInt theInstr ) +static Bool dis_int_mult_add ( UInt prefix, UInt theInstr ) { /* VA-Form */ UChar rD_addr = ifieldRegDS( theInstr ); @@ -5131,6 +5194,9 @@ static Bool dis_int_mult_add ( UInt theInstr ) assign( rB, getIReg( rB_addr ) ); assign( rC, getIReg( rC_addr ) ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc2) { case 0x30: // maddhd multiply-add High doubleword signed DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); @@ -5207,7 +5273,7 @@ static Bool dis_int_mult_add ( UInt theInstr ) return True; } -static Bool dis_int_arith ( UInt theInstr ) +static Bool dis_int_arith ( UInt prefix, UInt theInstr ) { /* D-Form, XO-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -5227,6 +5293,9 @@ static Bool dis_int_arith ( UInt theInstr ) Bool do_rc = False; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rA, getIReg(rA_addr) ); assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB @@ -5876,7 +5945,7 @@ static Bool dis_int_arith ( UInt theInstr ) return True; } -static Bool dis_modulo_int ( UInt theInstr ) +static Bool dis_modulo_int ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -5887,6 +5956,9 @@ static Bool dis_modulo_int ( UInt theInstr ) IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp rD = newTemp( ty ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc1) { /* X-Form */ case 0x1F: @@ -6258,7 +6330,7 @@ static Bool dis_modulo_int ( UInt theInstr ) /* Byte Compare Instructions */ -static Bool dis_byte_cmp ( UInt theInstr ) +static Bool dis_byte_cmp ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -6270,6 +6342,9 @@ static Bool dis_byte_cmp ( UInt theInstr ) UChar L = toUChar( IFIELD( theInstr, 21, 1 ) ); UChar BF = toUChar( IFIELD( theInstr, 23, 3 ) ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rA, getIReg(rA_addr) ); assign( rB, getIReg(rB_addr) ); @@ -6376,12 +6451,15 @@ static Bool dis_byte_cmp ( UInt theInstr ) /* * Integer Miscellaneous instructions */ -static Bool dis_int_misc ( UInt theInstr ) +static Bool dis_int_misc ( UInt prefix, UInt theInstr ) { Int wc = IFIELD(theInstr, 21, 2); UChar opc1 = ifieldOPC(theInstr); UInt opc2 = ifieldOPClo10(theInstr); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if ( opc1 != 0x1F ) { vex_printf("dis_modulo_int(ppc)(opc1)\n"); return False; @@ -6416,7 +6494,7 @@ static Bool dis_int_misc ( UInt theInstr ) /* Integer Compare Instructions */ -static Bool dis_int_cmp ( UInt theInstr ) +static Bool dis_int_cmp ( UInt prefix, UInt theInstr ) { /* D-Form, X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -6433,6 +6511,9 @@ static Bool dis_int_cmp ( UInt theInstr ) IRExpr *a = getIReg(rA_addr); IRExpr *b; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. vex_printf("dis_int_cmp(ppc)(flag_L)\n"); return False; @@ -6580,7 +6661,7 @@ static Bool dis_int_cmp ( UInt theInstr ) /* Integer Logical Instructions */ -static Bool dis_int_logic ( UInt theInstr ) +static Bool dis_int_logic ( UInt prefix, UInt theInstr ) { /* D-Form, X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -6597,6 +6678,9 @@ static Bool dis_int_logic ( UInt theInstr ) IRTemp rB = newTemp(ty); Bool do_rc = False; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rS, getIReg(rS_addr) ); assign( rB, getIReg(rB_addr) ); @@ -6971,7 +7055,7 @@ static Bool dis_int_logic ( UInt theInstr ) /* Integer Parity Instructions */ -static Bool dis_int_parity ( UInt theInstr ) +static Bool dis_int_parity ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -7004,6 +7088,9 @@ static Bool dis_int_parity ( UInt theInstr ) IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1f || rB_addr || b0) { vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); return False; @@ -7100,7 +7187,7 @@ static Bool dis_int_parity ( UInt theInstr ) /* Integer Rotate Instructions */ -static Bool dis_int_rot ( UInt theInstr ) +static Bool dis_int_rot ( UInt prefix, UInt theInstr ) { /* M-Form, MDS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -7124,6 +7211,9 @@ static Bool dis_int_rot ( UInt theInstr ) UInt mask32; ULong mask64; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rS, getIReg(rS_addr) ); assign( rB, getIReg(rB_addr) ); @@ -7350,7 +7440,7 @@ static Bool dis_int_rot ( UInt theInstr ) /* Integer Load Instructions */ -static Bool dis_int_load ( UInt theInstr ) +static Bool dis_int_load ( UInt prefix, UInt theInstr ) { /* D-Form, X-Form, DS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -7367,6 +7457,9 @@ static Bool dis_int_load ( UInt theInstr ) IRTemp EA = newTemp(ty); IRExpr* val; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc1) { case 0x1F: // register offset assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); @@ -7648,7 +7741,7 @@ static Bool dis_int_load ( UInt theInstr ) /* Integer Store Instructions */ -static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) +static Bool dis_int_store ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) { /* D-Form, X-Form, DS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -7666,6 +7759,9 @@ static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) IRTemp rB = newTemp(ty); IRTemp EA = newTemp(ty); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rB, getIReg(rB_addr) ); assign( rS, getIReg(rS_addr) ); @@ -7874,7 +7970,7 @@ static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) /* Integer Load/Store Multiple Instructions */ -static Bool dis_int_ldst_mult ( UInt theInstr ) +static Bool dis_int_ldst_mult ( UInt prefix, UInt theInstr ) { /* D-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -7891,6 +7987,9 @@ static Bool dis_int_ldst_mult ( UInt theInstr ) UInt ea_off = 0; IRExpr* irx_addr; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); switch (opc1) { @@ -8018,7 +8117,7 @@ void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 } } -static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) +static Bool dis_int_ldst_str ( UInt prefix, UInt theInstr, /*OUT*/Bool* stopHere ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -8034,6 +8133,9 @@ static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) IRTemp t_EA = newTemp(ty); IRTemp t_nbytes = IRTemp_INVALID; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + *stopHere = False; if (opc1 != 0x1F || b0 != 0) { @@ -8186,7 +8288,7 @@ static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) /* Integer Branch Instructions */ -static Bool dis_branch ( UInt theInstr, +static Bool dis_branch ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi, /*OUT*/DisResult* dres ) { @@ -8210,6 +8312,9 @@ static Bool dis_branch ( UInt theInstr, IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); IRTemp lr_old = newTemp(ty); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + /* Hack to pass through code that just wants to read the PC */ if (theInstr == 0x429F0005) { DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); @@ -8390,7 +8495,7 @@ static Bool dis_branch ( UInt theInstr, /* * PC relative instruction */ -static Bool dis_pc_relative ( UInt theInstr ) +static Bool dis_pc_relative ( UInt prefix, UInt theInstr ) { /* DX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -8402,6 +8507,9 @@ static Bool dis_pc_relative ( UInt theInstr ) UInt opc2 = ifieldOPClo5(theInstr); IRType ty = mode64 ? Ity_I64 : Ity_I32; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if ( opc1 != 0x13) { vex_printf("dis_pc_relative(ppc)(opc1)\n"); return False; @@ -8441,7 +8549,7 @@ static Bool dis_pc_relative ( UInt theInstr ) /* Condition Register Logical Instructions */ -static Bool dis_cond_logic ( UInt theInstr ) +static Bool dis_cond_logic ( UInt prefix, UInt theInstr ) { /* XL-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -8457,6 +8565,9 @@ static Bool dis_cond_logic ( UInt theInstr ) IRTemp crbA = newTemp(Ity_I32); IRTemp crbB = newTemp(Ity_I32); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 19 || b0 != 0) { vex_printf("dis_cond_logic(ppc)(opc1)\n"); return False; @@ -8625,7 +8736,7 @@ static Bool do_trap ( UChar TO, return False; /* not an unconditional trap */ } -static Bool dis_trapi ( UInt theInstr, +static Bool dis_trapi ( UInt prefix, UInt theInstr, /*OUT*/DisResult* dres ) { /* D-Form */ @@ -8638,6 +8749,9 @@ static Bool dis_trapi ( UInt theInstr, IRType ty = mode64 ? Ity_I64 : Ity_I32; Bool uncond = False; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc1) { case 0x03: // twi (Trap Word Immediate, PPC32 p548) uncond = do_trap( TO, @@ -8676,7 +8790,7 @@ static Bool dis_trapi ( UInt theInstr, return True; } -static Bool dis_trap ( UInt theInstr, +static Bool dis_trap ( UInt prefix, UInt theInstr, /*OUT*/DisResult* dres ) { /* X-Form */ @@ -8688,6 +8802,9 @@ static Bool dis_trap ( UInt theInstr, IRType ty = mode64 ? Ity_I64 : Ity_I32; Bool uncond = False; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (ifieldBIT0(theInstr) != 0) return False; @@ -8734,11 +8851,14 @@ static Bool dis_trap ( UInt theInstr, /* System Linkage Instructions */ -static Bool dis_syslink ( UInt theInstr, +static Bool dis_syslink ( UInt prefix, UInt theInstr, const VexAbiInfo* abiinfo, DisResult* dres ) { IRType ty = mode64 ? Ity_I64 : Ity_I32; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (theInstr != 0x44000002) { vex_printf("dis_syslink(ppc)(theInstr)\n"); return False; @@ -8772,7 +8892,7 @@ static Bool dis_syslink ( UInt theInstr, check any stores it does. Instead, the reservation is cancelled when the scheduler switches to another thread (run_thread_for_a_while()). */ -static Bool dis_memsync ( UInt theInstr ) +static Bool dis_memsync ( UInt prefix, UInt theInstr ) { /* X-Form, XL-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -8790,6 +8910,9 @@ static Bool dis_memsync ( UInt theInstr ) IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp EA = newTemp(ty); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); switch (opc1) { @@ -9182,7 +9305,7 @@ static Bool dis_memsync ( UInt theInstr ) /* Integer Shift Instructions */ -static Bool dis_int_shift ( UInt theInstr ) +static Bool dis_int_shift ( UInt prefix, UInt theInstr ) { /* X-Form, XS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -9203,6 +9326,9 @@ static Bool dis_int_shift ( UInt theInstr ) IRTemp rB_lo32 = newTemp(Ity_I32); IRExpr* e_tmp; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rS, getIReg(rS_addr) ); assign( rB, getIReg(rB_addr) ); assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); @@ -9437,7 +9563,7 @@ static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) ); } -static Bool dis_int_ldst_rev ( UInt theInstr ) +static Bool dis_int_ldst_rev ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -9453,6 +9579,9 @@ static Bool dis_int_ldst_rev ( UInt theInstr ) IRTemp w1 = newTemp(Ity_I32); IRTemp w2 = newTemp(Ity_I32); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F || b0 != 0) { vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); return False; @@ -9544,7 +9673,7 @@ static Bool dis_int_ldst_rev ( UInt theInstr ) /* Processor Control Instructions */ -static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) +static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt prefix, UInt theInstr ) { UChar opc1 = ifieldOPC(theInstr); @@ -9567,6 +9696,10 @@ static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp rS = newTemp(ty); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rS, getIReg(rS_addr) ); /* Reorder SPR field as per PPC32 p470 */ @@ -10021,7 +10154,7 @@ static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) /* Cache Management Instructions */ -static Bool dis_cache_manage ( UInt theInstr, +static Bool dis_cache_manage ( UInt prefix, UInt theInstr, DisResult* dres, const VexArchInfo* guest_archinfo ) { @@ -10037,6 +10170,9 @@ static Bool dis_cache_manage ( UInt theInstr, IRType ty = mode64 ? Ity_I64 : Ity_I32; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + // Check for valid hint values for dcbt and dcbtst as currently described in // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no // means of modeling the hint anyway. @@ -10346,7 +10482,7 @@ static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) /* Floating Point Load Instructions */ -static Bool dis_fp_load ( UInt theInstr ) +static Bool dis_fp_load ( UInt prefix, UInt theInstr ) { /* X-Form, D-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -10365,6 +10501,9 @@ static Bool dis_fp_load ( UInt theInstr ) IRTemp iHi = newTemp(Ity_I32); IRTemp iLo = newTemp(Ity_I32); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( rA, getIReg(rA_addr) ); assign( rB, getIReg(rB_addr) ); @@ -10484,7 +10623,7 @@ static Bool dis_fp_load ( UInt theInstr ) /* Floating Point Store Instructions */ -static Bool dis_fp_store ( UInt theInstr ) +static Bool dis_fp_store ( UInt prefix, UInt theInstr ) { /* X-Form, D-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -10502,6 +10641,9 @@ static Bool dis_fp_store ( UInt theInstr ) IRTemp rA = newTemp(ty); IRTemp rB = newTemp(ty); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frS, getFReg(frS_addr) ); assign( rA, getIReg(rA_addr) ); assign( rB, getIReg(rB_addr) ); @@ -10612,7 +10754,7 @@ static Bool dis_fp_store ( UInt theInstr ) /* Floating Point Arith Instructions */ -static Bool dis_fp_arith ( UInt theInstr ) +static Bool dis_fp_arith ( UInt prefix, UInt theInstr ) { /* A-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -10640,6 +10782,9 @@ static Bool dis_fp_arith ( UInt theInstr ) zero. Hence cr1 should be cleared if this is a . form insn. */ Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getFReg(frA_addr)); assign( frB, getFReg(frB_addr)); assign( frC, getFReg(frC_addr)); @@ -10850,7 +10995,7 @@ static Bool dis_fp_arith ( UInt theInstr ) /* Floating Point Mult-Add Instructions */ -static Bool dis_fp_multadd ( UInt theInstr ) +static Bool dis_fp_multadd ( UInt prefix, UInt theInstr ) { /* A-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -10882,6 +11027,9 @@ static Bool dis_fp_multadd ( UInt theInstr ) zero. Hence cr1 should be cleared if this is a . form insn. */ Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + /* Bind the rounding mode expression to a temp; there's no point in creating gratuitous CSEs, as we know we'll need to use it twice. */ @@ -11352,7 +11500,7 @@ static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); } -static Bool dis_fp_tests ( UInt theInstr ) +static Bool dis_fp_tests ( UInt prefix, UInt theInstr ) { UChar opc1 = ifieldOPC(theInstr); UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); @@ -11361,6 +11509,9 @@ static Bool dis_fp_tests ( UInt theInstr ) UInt opc2 = ifieldOPClo10(theInstr); IRTemp frB_I64 = newTemp(Ity_I64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3F || b0 != 0 ){ vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); return False; @@ -11419,7 +11570,7 @@ static Bool dis_fp_tests ( UInt theInstr ) /* Floating Point Compare Instructions */ -static Bool dis_fp_cmp ( UInt theInstr ) +static Bool dis_fp_cmp ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -11436,6 +11587,9 @@ static Bool dis_fp_cmp ( UInt theInstr ) IRTemp frA = newTemp(Ity_F64); IRTemp frB = newTemp(Ity_F64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { vex_printf("dis_fp_cmp(ppc)(instr)\n"); return False; @@ -11516,7 +11670,7 @@ static Bool dis_fp_cmp ( UInt theInstr ) /* Floating Point Rounding/Conversion Instructions */ -static Bool dis_fp_round ( UInt theInstr ) +static Bool dis_fp_round ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -11542,6 +11696,10 @@ static Bool dis_fp_round ( UInt theInstr ) simulating exceptions, the exception status will appear to be zero. Hence cr1 should be cleared if this is a . form insn. */ Bool clear_CR1 = True; + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { vex_printf("dis_fp_round(ppc)(instr)\n"); return False; @@ -11729,7 +11887,7 @@ putFR: /* Floating Point Pair Instructions */ -static Bool dis_fp_pair ( UInt theInstr ) +static Bool dis_fp_pair ( UInt prefix, UInt theInstr ) { /* X-Form/DS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -11748,6 +11906,9 @@ static Bool dis_fp_pair ( UInt theInstr ) UChar b0 = ifieldBIT0(theInstr); Bool is_load = 0; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc1) { case 0x1F: // register offset /* These instructions work on a pair of registers. The specified @@ -11986,7 +12147,7 @@ static Bool dis_fp_pair ( UInt theInstr ) /* Floating Point Merge Instructions */ -static Bool dis_fp_merge ( UInt theInstr ) +static Bool dis_fp_merge ( UInt prefix, UInt theInstr ) { /* X-Form */ UInt opc2 = ifieldOPClo10(theInstr); @@ -11998,6 +12159,9 @@ static Bool dis_fp_merge ( UInt theInstr ) IRTemp frA = newTemp(Ity_F64); IRTemp frB = newTemp(Ity_F64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getFReg(frA_addr)); assign( frB, getFReg(frB_addr)); @@ -12040,7 +12204,7 @@ static Bool dis_fp_merge ( UInt theInstr ) /* Floating Point Move Instructions */ -static Bool dis_fp_move ( UInt theInstr ) +static Bool dis_fp_move ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -12057,6 +12221,9 @@ static Bool dis_fp_move ( UInt theInstr ) IRTemp signA; IRTemp hiD; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { vex_printf("dis_fp_move(ppc)(instr)\n"); return False; @@ -12141,13 +12308,16 @@ static Bool dis_fp_move ( UInt theInstr ) /* Floating Point Status/Control Register Instructions */ -static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) +static Bool dis_fp_scr ( UInt prefix, UInt theInstr, Bool GX_level ) { /* Many forms - see each switch case */ UChar opc1 = ifieldOPC(theInstr); UInt opc2 = ifieldOPClo10(theInstr); UChar flag_rC = ifieldBIT0(theInstr); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3F) { vex_printf("dis_fp_scr(ppc)(instr)\n"); return False; @@ -13078,7 +13248,7 @@ static IRExpr * Check_unordered(IRExpr * val) /*------------------------------------------------------------*/ /* DFP Arithmetic instructions */ -static Bool dis_dfp_arith(UInt theInstr) +static Bool dis_dfp_arith( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); @@ -13099,6 +13269,9 @@ static Bool dis_dfp_arith(UInt theInstr) */ Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getDReg( frA_addr ) ); assign( frB, getDReg( frB_addr ) ); @@ -13136,7 +13309,7 @@ static Bool dis_dfp_arith(UInt theInstr) } /* Quad DFP Arithmetic instructions */ -static Bool dis_dfp_arithq(UInt theInstr) +static Bool dis_dfp_arithq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); @@ -13157,6 +13330,9 @@ static Bool dis_dfp_arithq(UInt theInstr) */ Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getDReg_pair( frA_addr ) ); assign( frB, getDReg_pair( frB_addr ) ); @@ -13194,7 +13370,7 @@ static Bool dis_dfp_arithq(UInt theInstr) } /* DFP 64-bit logical shift instructions */ -static Bool dis_dfp_shift(UInt theInstr) { +static Bool dis_dfp_shift( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo9( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13205,6 +13381,9 @@ static Bool dis_dfp_shift(UInt theInstr) { IRTemp frS = newTemp( Ity_D64 ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getDReg( frA_addr ) ); switch (opc2) { @@ -13231,7 +13410,7 @@ static Bool dis_dfp_shift(UInt theInstr) { } /* Quad DFP logical shift instructions */ -static Bool dis_dfp_shiftq(UInt theInstr) { +static Bool dis_dfp_shiftq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo9( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13242,6 +13421,9 @@ static Bool dis_dfp_shiftq(UInt theInstr) { IRTemp frS = newTemp( Ity_D128 ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getDReg_pair( frA_addr ) ); switch (opc2) { @@ -13268,7 +13450,7 @@ static Bool dis_dfp_shiftq(UInt theInstr) { } /* DFP 64-bit format conversion instructions */ -static Bool dis_dfp_fmt_conv(UInt theInstr) { +static Bool dis_dfp_fmt_conv( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frB_addr = ifieldRegB( theInstr ); @@ -13278,6 +13460,9 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) { IRTemp frS; Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc2) { case 0x102: //dctdp DIP( "dctdp%s fr%u,fr%u\n", @@ -13334,7 +13519,7 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) { } /* Quad DFP format conversion instructions */ -static Bool dis_dfp_fmt_convq(UInt theInstr) { +static Bool dis_dfp_fmt_convq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frB_addr = ifieldRegB( theInstr ); @@ -13346,6 +13531,9 @@ static Bool dis_dfp_fmt_convq(UInt theInstr) { UChar flag_rC = ifieldBIT0( theInstr ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc2) { case 0x102: // dctqpq DIP( "dctqpq%s fr%u,fr%u\n", @@ -13398,7 +13586,7 @@ static Bool dis_dfp_fmt_convq(UInt theInstr) { return True; } -static Bool dis_dfp_round( UInt theInstr ) { +static Bool dis_dfp_round( UInt prefix, UInt theInstr ) { UChar frS_addr = ifieldRegDS(theInstr); UChar R = IFIELD(theInstr, 16, 1); UChar RMC = IFIELD(theInstr, 9, 2); @@ -13409,6 +13597,9 @@ static Bool dis_dfp_round( UInt theInstr ) { UInt opc2 = ifieldOPClo8( theInstr ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc2) { /* drintn, is the same as drintx. The only difference is this * instruction does not generate an exception for an inexact operation. @@ -13443,7 +13634,7 @@ static Bool dis_dfp_round( UInt theInstr ) { return True; } -static Bool dis_dfp_roundq(UInt theInstr) { +static Bool dis_dfp_roundq( UInt prefix, UInt theInstr ) { UChar frS_addr = ifieldRegDS( theInstr ); UChar frB_addr = ifieldRegB( theInstr ); UChar R = IFIELD(theInstr, 16, 1); @@ -13454,6 +13645,9 @@ static Bool dis_dfp_roundq(UInt theInstr) { Bool clear_CR1 = True; UInt opc2 = ifieldOPClo8( theInstr ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + switch (opc2) { /* drintnq, is the same as drintxq. The only difference is this * instruction does not generate an exception for an inexact operation. @@ -13484,7 +13678,7 @@ static Bool dis_dfp_roundq(UInt theInstr) { return True; } -static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { +static Bool dis_dfp_quantize_sig_rrnd( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo8( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13498,6 +13692,9 @@ static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { IRTemp frS = newTemp( Ity_D64 ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frB, getDReg( frB_addr ) ); switch (opc2) { @@ -13578,7 +13775,7 @@ static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { return True; } -static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { +static Bool dis_dfp_quantize_sig_rrndq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo8( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13592,6 +13789,9 @@ static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { IRTemp frS = newTemp( Ity_D128 ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frB, getDReg_pair( frB_addr ) ); switch (opc2) { @@ -13673,7 +13873,7 @@ static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { return True; } -static Bool dis_dfp_extract_insert(UInt theInstr) { +static Bool dis_dfp_extract_insert( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13686,6 +13886,9 @@ static Bool dis_dfp_extract_insert(UInt theInstr) { IRTemp frS = newTemp( Ity_D64 ); IRTemp tmp = newTemp( Ity_I64 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frA, getDReg( frA_addr ) ); assign( frB, getDReg( frB_addr ) ); @@ -13719,7 +13922,7 @@ static Bool dis_dfp_extract_insert(UInt theInstr) { return True; } -static Bool dis_dfp_extract_insertq(UInt theInstr) { +static Bool dis_dfp_extract_insertq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); UChar frS_addr = ifieldRegDS( theInstr ); UChar frA_addr = ifieldRegA( theInstr ); @@ -13733,6 +13936,9 @@ static Bool dis_dfp_extract_insertq(UInt theInstr) { IRTemp tmp = newTemp( Ity_I64 ); Bool clear_CR1 = True; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frB, getDReg_pair( frB_addr ) ); switch (opc2) { @@ -13770,7 +13976,7 @@ static Bool dis_dfp_extract_insertq(UInt theInstr) { } /* DFP 64-bit comparison instructions */ -static Bool dis_dfp_compare(UInt theInstr) { +static Bool dis_dfp_compare( UInt prefix, UInt theInstr ) { /* X-Form */ UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF UChar frA_addr = ifieldRegA( theInstr ); @@ -13782,6 +13988,8 @@ static Bool dis_dfp_compare(UInt theInstr) { IRTemp ccIR = newTemp( Ity_I32 ); IRTemp ccPPC32 = newTemp( Ity_I32 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK /* Note: Differences between dcmpu and dcmpo are only in exception flag settings, which aren't supported anyway. */ @@ -13845,7 +14053,7 @@ static Bool dis_dfp_compare(UInt theInstr) { } /* Test class/group/exponent/significance instructions. */ -static Bool dis_dfp_exponent_test ( UInt theInstr ) +static Bool dis_dfp_exponent_test ( UInt prefix, UInt theInstr ) { UChar frA_addr = ifieldRegA( theInstr ); UChar frB_addr = ifieldRegB( theInstr ); @@ -13872,6 +14080,9 @@ static Bool dis_dfp_exponent_test ( UInt theInstr ) IRTemp cc3 = newTemp( Ity_I32 ); IRTemp cc = newTemp( Ity_I32 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + /* The dtstex and dtstexg instructions only differ in the size of the * exponent field. The following switch statement takes care of the size * specific setup. Once the value of the exponents, the G-field shift @@ -14038,7 +14249,7 @@ static Bool dis_dfp_exponent_test ( UInt theInstr ) } /* Test class/group/exponent/significance instructions. */ -static Bool dis_dfp_class_test ( UInt theInstr ) +static Bool dis_dfp_class_test ( UInt prefix, UInt theInstr ) { UChar frA_addr = ifieldRegA( theInstr ); IRTemp frA = newTemp( Ity_D64 ); @@ -14084,6 +14295,9 @@ static Bool dis_dfp_class_test ( UInt theInstr ) IRTemp dcm4 = newTemp( Ity_I32 ); IRTemp dcm5 = newTemp( Ity_I32 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + /* The only difference between the dtstdc and dtstdcq instructions is * size of the T and G fields. The calculation of the 4 bit field * is the same. Setup the parameters and values that are DFP size @@ -14482,7 +14696,7 @@ static Bool dis_dfp_class_test ( UInt theInstr ) return True; } -static Bool dis_dfp_bcd(UInt theInstr) { +static Bool dis_dfp_bcd( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); ULong sp = IFIELD(theInstr, 19, 2); ULong s = IFIELD(theInstr, 20, 1); @@ -14499,6 +14713,9 @@ static Bool dis_dfp_bcd(UInt theInstr) { IRTemp dbcd_l = newTemp( Ity_I32 ); IRTemp lmd = newTemp( Ity_I32 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frB, getDReg( frB_addr ) ); assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); @@ -14742,7 +14959,7 @@ static Bool dis_dfp_bcd(UInt theInstr) { return True; } -static Bool dis_dfp_bcdq( UInt theInstr ) +static Bool dis_dfp_bcdq( UInt prefix, UInt theInstr ) { UInt opc2 = ifieldOPClo10( theInstr ); ULong sp = IFIELD(theInstr, 19, 2); @@ -14758,6 +14975,9 @@ static Bool dis_dfp_bcdq( UInt theInstr ) IRTemp result_hi = newTemp( Ity_I64 ); IRTemp result_lo = newTemp( Ity_I64 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( frB_hi, getDReg( frB_addr ) ); assign( frB_lo, getDReg( frB_addr + 1 ) ); assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); @@ -15151,7 +15371,7 @@ static Bool dis_dfp_bcdq( UInt theInstr ) return True; } -static Bool dis_dfp_significant_digits( UInt theInstr ) +static Bool dis_dfp_significant_digits( UInt prefix, UInt theInstr ) { UInt opc1 = ifieldOPC( theInstr ); UInt opc2 = ifieldOPClo10(theInstr); @@ -15173,6 +15393,9 @@ static Bool dis_dfp_significant_digits( UInt theInstr ) UChar UIM = toUChar( IFIELD( theInstr, 16, 6 ) ); IRTemp BCD_valid = newTemp( Ity_I32 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc2 == 0x2A2) { // dtstsf DFP Test Significance // dtstsfq DFP Test Significance Quad /* Get the reference singificance stored in frA */ @@ -15403,7 +15626,7 @@ static Bool dis_dfp_significant_digits( UInt theInstr ) /* Altivec Cache Control Instructions (Data Streams) */ -static Bool dis_av_datastream ( UInt theInstr ) +static Bool dis_av_datastream ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -15416,6 +15639,9 @@ static Bool dis_av_datastream ( UInt theInstr ) UInt opc2 = ifieldOPClo10(theInstr); UChar b0 = ifieldBIT0(theInstr); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { vex_printf("dis_av_datastream(ppc)(instr)\n"); return False; @@ -15454,7 +15680,7 @@ static Bool dis_av_datastream ( UInt theInstr ) /* AltiVec Processor Control Instructions */ -static Bool dis_av_procctl ( UInt theInstr ) +static Bool dis_av_procctl ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -15463,6 +15689,9 @@ static Bool dis_av_procctl ( UInt theInstr ) UChar vB_addr = ifieldRegB(theInstr); UInt opc2 = IFIELD( theInstr, 0, 11 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x4) { vex_printf("dis_av_procctl(ppc)(instr)\n"); return False; @@ -15499,7 +15728,8 @@ static Bool dis_av_procctl ( UInt theInstr ) /* Vector Extend Sign Instructions */ -static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 ) +static Bool dis_av_extend_sign_count_zero ( UInt prefix, UInt theInstr, + UInt allow_isa_3_0 ) { /* VX-Form, sort of, the A register field is used to select the specific * sign extension instruction or count leading/trailing zero LSB @@ -15515,6 +15745,9 @@ static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 ) IRTemp vB = newTemp( Ity_V128 ); IRTemp vT = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getVReg ( vB_addr ) ); if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) ) { @@ -15841,7 +16074,7 @@ static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 ) /* Vector Rotate Instructions */ -static Bool dis_av_rotate ( UInt theInstr ) +static Bool dis_av_rotate ( UInt prefix, UInt theInstr ) { /* VX-Form */ @@ -15872,6 +16105,9 @@ static Bool dis_av_rotate ( UInt theInstr ) UInt word_size; unsigned long long word_mask; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if ( opc1 != 0x4 ) { vex_printf("dis_av_rotate(ppc)(instr)\n"); return False; @@ -16106,7 +16342,7 @@ static Bool dis_av_rotate ( UInt theInstr ) /* AltiVec Vector Extract Element Instructions */ -static Bool dis_av_extract_element ( UInt theInstr ) +static Bool dis_av_extract_element ( UInt prefix, UInt theInstr ) { /* VX-Form, * sorta destination and first source are GPR not vector registers @@ -16122,6 +16358,9 @@ static Bool dis_av_extract_element ( UInt theInstr ) IRTemp rA = newTemp( Ity_I64 ); IRTemp rT = newTemp( Ity_I64 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getVReg( vB_addr ) ); assign( rA, getIReg( rA_addr ) ); @@ -16192,7 +16431,7 @@ static Bool dis_av_extract_element ( UInt theInstr ) * VSX scalar and vector convert instructions */ static Bool -dis_vx_conv ( UInt theInstr, UInt opc2 ) +dis_vx_conv ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX2-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -16200,6 +16439,10 @@ dis_vx_conv ( UInt theInstr, UInt opc2 ) UChar XB = ifieldRegXB( theInstr ); IRTemp xB, xB2; IRTemp b3, b2, b1, b0; + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + xB = xB2 = IRTemp_INVALID; if (opc1 != 0x3C) { @@ -16854,7 +17097,7 @@ dis_vx_conv ( UInt theInstr, UInt opc2 ) * VSX vector Double Precision Floating Point Arithmetic Instructions */ static Bool -dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) +dis_vxv_dp_arith ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -16867,6 +17110,9 @@ dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) IRTemp frA2 = newTemp(Ity_F64); IRTemp frB2 = newTemp(Ity_F64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); return False; @@ -17097,7 +17343,7 @@ dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) * VSX vector Single Precision Floating Point Arithmetic Instructions */ static Bool -dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) +dis_vxv_sp_arith ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -17112,6 +17358,9 @@ dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) IRTemp res2 = newTemp(Ity_I32); IRTemp res3 = newTemp(Ity_I32); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + a3 = a2 = a1 = a0 = IRTemp_INVALID; b3 = b2 = b1 = b0 = IRTemp_INVALID; @@ -17423,12 +17672,16 @@ dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) * Vector Population Count/bit matrix transpose */ static Bool -dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) +dis_av_count_bitTranspose ( UInt prefix, UInt theInstr, UInt opc2 ) { UChar vRB_addr = ifieldRegB(theInstr); UChar vRT_addr = ifieldRegDS(theInstr); UChar opc1 = ifieldOPC( theInstr ); IRTemp vB = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getVReg(vRB_addr)); if (opc1 != 0x4) { @@ -18007,13 +18260,16 @@ static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) * Miscellaneous VSX vector instructions */ static Bool -dis_vxv_misc ( UInt theInstr, UInt opc2 ) +dis_vxv_misc ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); UChar XT = ifieldRegXT( theInstr ); UChar XB = ifieldRegXB( theInstr ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); return False; @@ -18504,7 +18760,7 @@ dis_vxv_misc ( UInt theInstr, UInt opc2 ) * VSX Scalar Floating Point Arithmetic Instructions */ static Bool -dis_vxs_arith ( UInt theInstr, UInt opc2 ) +dis_vxs_arith ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -18515,6 +18771,9 @@ dis_vxs_arith ( UInt theInstr, UInt opc2 ) IRTemp frA = newTemp(Ity_F64); IRTemp frB = newTemp(Ity_F64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); return False; @@ -18833,7 +19092,7 @@ dis_vxs_arith ( UInt theInstr, UInt opc2 ) * VSX Floating Point Compare Instructions */ static Bool -dis_vx_cmp( UInt theInstr, UInt opc2 ) +dis_vx_cmp( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form and XX2-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -18844,6 +19103,9 @@ dis_vx_cmp( UInt theInstr, UInt opc2 ) IRTemp frA = newTemp(Ity_F64); IRTemp frB = newTemp(Ity_F64); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); return False; @@ -18958,7 +19220,7 @@ do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, * VSX Vector Compare Instructions */ static Bool -dis_vvec_cmp( UInt theInstr, UInt opc2 ) +dis_vvec_cmp( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -18969,6 +19231,9 @@ dis_vvec_cmp( UInt theInstr, UInt opc2 ) IRTemp vA = newTemp( Ity_V128 ); IRTemp vB = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); return False; @@ -19054,7 +19319,7 @@ dis_vvec_cmp( UInt theInstr, UInt opc2 ) * Miscellaneous VSX Scalar Instructions */ static Bool -dis_vxs_misc( UInt theInstr, const VexAbiInfo* vbi, UInt opc2, +dis_vxs_misc( UInt prefix, UInt theInstr, const VexAbiInfo* vbi, UInt opc2, int allow_isa_3_0 ) { #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL @@ -19066,6 +19331,9 @@ dis_vxs_misc( UInt theInstr, const VexAbiInfo* vbi, UInt opc2, IRTemp vA = newTemp( Ity_V128 ); IRTemp vB = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); return False; @@ -20320,7 +20588,7 @@ dis_vxs_misc( UInt theInstr, const VexAbiInfo* vbi, UInt opc2, */ static Bool -dis_vx_misc ( UInt theInstr, UInt opc2 ) +dis_vx_misc ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar XT = ifieldRegXT ( theInstr ); @@ -20340,6 +20608,9 @@ dis_vx_misc ( UInt theInstr, UInt opc2 ) IRTemp nan_cmp_value = newTemp(Ity_I64); UInt trap_enabled = 0; /* 0 - trap enabled is False */ + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVSReg( XA ) ); assign( vB, getVSReg( XB ) ); assign( xT, getVSReg( XT ) ); @@ -20554,7 +20825,7 @@ dis_vx_misc ( UInt theInstr, UInt opc2 ) * VSX Logical Instructions */ static Bool -dis_vx_logic ( UInt theInstr, UInt opc2 ) +dis_vx_logic ( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -20564,6 +20835,9 @@ dis_vx_logic ( UInt theInstr, UInt opc2 ) IRTemp vA = newTemp( Ity_V128 ); IRTemp vB = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vx_logic(ppc)(instr)\n" ); return False; @@ -20625,7 +20899,7 @@ dis_vx_logic ( UInt theInstr, UInt opc2 ) * NOTE: VSX supports word-aligned storage access. */ static Bool -dis_vx_load ( UInt theInstr ) +dis_vx_load ( UInt prefix, UInt theInstr ) { /* XX1-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -20637,6 +20911,9 @@ dis_vx_load ( UInt theInstr ) IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp EA = newTemp( ty ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F) { vex_printf( "dis_vx_load(ppc)(instr)\n" ); return False; @@ -21261,7 +21538,7 @@ dis_vx_load ( UInt theInstr ) * VSX Move Instructions */ static Bool -dis_vx_move ( UInt theInstr ) +dis_vx_move ( UInt prefix, UInt theInstr ) { /* XX1-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -21272,6 +21549,9 @@ dis_vx_move ( UInt theInstr ) UInt opc2 = ifieldOPClo10( theInstr ); IRType ty = Ity_I64; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if ( opc1 != 0x1F ) { vex_printf( "dis_vx_move(ppc)(instr)\n" ); return False; @@ -21334,7 +21614,7 @@ dis_vx_move ( UInt theInstr ) * NOTE: VSX supports word-aligned storage access. */ static Bool -dis_vx_store ( UInt theInstr ) +dis_vx_store ( UInt prefix, UInt theInstr ) { /* XX1-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -21347,6 +21627,9 @@ dis_vx_store ( UInt theInstr ) IRType ty = mode64 ? Ity_I64 : Ity_I32; IRTemp EA = newTemp( ty ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F) { vex_printf( "dis_vx_store(ppc)(instr)\n" ); return False; @@ -22177,7 +22460,8 @@ dis_vx_store ( UInt theInstr ) } static Bool -dis_vx_Scalar_Round_to_quad_integer( UInt theInstr, const VexAbiInfo* vbi ) +dis_vx_Scalar_Round_to_quad_integer( UInt prefix, UInt theInstr, + const VexAbiInfo* vbi ) { /* The ISA 3.0 instructions supported in this function require * the underlying hardware platform that supports the ISA3.0 @@ -22192,6 +22476,9 @@ dis_vx_Scalar_Round_to_quad_integer( UInt theInstr, const VexAbiInfo* vbi ) IRTemp vT = newTemp( Ity_F128 ); UChar EX = IFIELD( theInstr, 0, 1 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getF128Reg( vB_addr ) ); if (opc1 != 0x3F) { vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" ); @@ -22244,7 +22531,7 @@ dis_vx_Scalar_Round_to_quad_integer( UInt theInstr, const VexAbiInfo* vbi ) } static Bool -dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr, +dis_vx_Floating_Point_Arithmetic_quad_precision( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) { /* The ISA 3.0 instructions supported in this function require @@ -22263,6 +22550,9 @@ dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr, IRExpr* rm = get_IR_roundingmode(); UChar R0 = IFIELD( theInstr, 0, 1 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getF128Reg( vB_addr ) ); if ( opc1 != 0x3F ) { @@ -22596,7 +22886,7 @@ dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr, /* VSX Scalar Quad-Precision instructions */ static Bool -dis_vx_scalar_quad_precision ( UInt theInstr ) +dis_vx_scalar_quad_precision ( UInt prefix, UInt theInstr ) { /* This function emulates the 128-bit floating point instructions * using existing 128-bit vector instructions (Iops). The 128-bit @@ -22613,6 +22903,9 @@ dis_vx_scalar_quad_precision ( UInt theInstr ) IRTemp vB = newTemp( Ity_V128 ); IRTemp vT = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vB, getVSReg( vB_addr ) ); if (opc1 != 0x3F) { @@ -23006,7 +23299,7 @@ dis_vx_scalar_quad_precision ( UInt theInstr ) * VSX permute and other miscealleous instructions */ static Bool -dis_vx_permute_misc( UInt theInstr, UInt opc2 ) +dis_vx_permute_misc( UInt prefix, UInt theInstr, UInt opc2 ) { /* XX3-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -23017,6 +23310,9 @@ dis_vx_permute_misc( UInt theInstr, UInt opc2 ) IRTemp vA = newTemp( Ity_V128 ); IRTemp vB = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x3C) { vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); return False; @@ -23186,7 +23482,7 @@ dis_vx_permute_misc( UInt theInstr, UInt opc2 ) /* AltiVec Load Instructions */ -static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) +static Bool dis_av_load ( const VexAbiInfo* vbi, UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -23200,6 +23496,9 @@ static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) IRTemp EA = newTemp(ty); IRTemp EA_align16 = newTemp(ty); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F || b0 != 0) { vex_printf("dis_av_load(ppc)(instr)\n"); return False; @@ -23349,7 +23648,7 @@ static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) /* AltiVec Store Instructions */ -static Bool dis_av_store ( UInt theInstr ) +static Bool dis_av_store ( UInt prefix, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -23366,6 +23665,9 @@ static Bool dis_av_store ( UInt theInstr ) IRTemp eb = newTemp(Ity_I8); IRTemp idx = newTemp(Ity_I8); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x1F || b0 != 0) { vex_printf("dis_av_store(ppc)(instr)\n"); return False; @@ -23447,7 +23749,7 @@ static Bool dis_av_store ( UInt theInstr ) /* AltiVec Arithmetic Instructions */ -static Bool dis_av_arith ( UInt theInstr ) +static Bool dis_av_arith ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -23467,6 +23769,9 @@ static Bool dis_av_arith ( UInt theInstr ) IRTemp a7, a6, a5, a4, a3, a2, a1, a0; IRTemp b3, b2, b1, b0; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + aEvn = aOdd = IRTemp_INVALID; a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; @@ -23954,7 +24259,7 @@ static Bool dis_av_arith ( UInt theInstr ) /* AltiVec Logic Instructions */ -static Bool dis_av_logic ( UInt theInstr ) +static Bool dis_av_logic ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -23968,6 +24273,9 @@ static Bool dis_av_logic ( UInt theInstr ) assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + if (opc1 != 0x4) { vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); return False; @@ -24032,7 +24340,7 @@ static Bool dis_av_logic ( UInt theInstr ) /* AltiVec Compare Instructions */ -static Bool dis_av_cmp ( UInt theInstr ) +static Bool dis_av_cmp ( UInt prefix, UInt theInstr ) { /* VXR-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -24045,6 +24353,10 @@ static Bool dis_av_cmp ( UInt theInstr ) IRTemp vA = newTemp(Ity_V128); IRTemp vB = newTemp(Ity_V128); IRTemp vD = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); @@ -24234,7 +24546,7 @@ static Bool dis_av_cmp ( UInt theInstr ) /* AltiVec Multiply-Sum Instructions */ -static Bool dis_av_multarith ( UInt theInstr ) +static Bool dis_av_multarith ( UInt prefix, UInt theInstr ) { /* VA-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -24265,6 +24577,9 @@ static Bool dis_av_multarith ( UInt theInstr ) IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; IRTemp c3, c2, c1, c0; + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; c3 = c2 = c1 = c0 = IRTemp_INVALID; @@ -24627,7 +24942,7 @@ static Bool dis_av_multarith ( UInt theInstr ) /* AltiVec Polynomial Multiply-Sum Instructions */ -static Bool dis_av_polymultarith ( UInt theInstr ) +static Bool dis_av_polymultarith ( UInt prefix, UInt theInstr ) { /* VA-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -24640,6 +24955,9 @@ static Bool dis_av_polymultarith ( UInt theInstr ) IRTemp vB = newTemp(Ity_V128); IRTemp vC = newTemp(Ity_V128); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); assign( vC, getVReg(vC_addr)); @@ -24681,7 +24999,7 @@ static Bool dis_av_polymultarith ( UInt theInstr ) /* AltiVec Shift/Rotate Instructions */ -static Bool dis_av_shift ( UInt theInstr ) +static Bool dis_av_shift ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -24692,6 +25010,10 @@ static Bool dis_av_shift ( UInt theInstr ) IRTemp vA = newTemp(Ity_V128); IRTemp vB = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); @@ -24839,7 +25161,7 @@ static Bool dis_av_shift ( UInt theInstr ) /* AltiVec Permute Instructions */ -static Bool dis_av_permute ( UInt theInstr ) +static Bool dis_av_permute ( UInt prefix, UInt theInstr ) { /* VA-Form, VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -24857,6 +25179,10 @@ static Bool dis_av_permute ( UInt theInstr ) IRTemp vA = newTemp(Ity_V128); IRTemp vB = newTemp(Ity_V128); IRTemp vC = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); assign( vC, getVReg(vC_addr)); @@ -25337,7 +25663,7 @@ static Bool dis_av_permute ( UInt theInstr ) /* Vector Integer Absolute Difference */ -static Bool dis_abs_diff ( UInt theInstr ) +static Bool dis_abs_diff ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC( theInstr ); @@ -25354,6 +25680,9 @@ static Bool dis_abs_diff ( UInt theInstr ) IRTemp vBminusA = newTemp( Ity_V128 ); IRTemp vMask = newTemp( Ity_V128 ); + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg( vA_addr ) ); assign( vB, getVReg( vB_addr ) ); @@ -25450,7 +25779,7 @@ static Bool dis_abs_diff ( UInt theInstr ) /* AltiVec 128 bit integer multiply by 10 Instructions */ -static Bool dis_av_mult10 ( UInt theInstr ) +static Bool dis_av_mult10 ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -25460,6 +25789,10 @@ static Bool dis_av_mult10 ( UInt theInstr ) UInt opc2 = IFIELD( theInstr, 0, 11 ); IRTemp vA = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); if (opc1 != 0x4) { @@ -25507,7 +25840,7 @@ static Bool dis_av_mult10 ( UInt theInstr ) /* AltiVec Pack/Unpack Instructions */ -static Bool dis_av_pack ( UInt theInstr ) +static Bool dis_av_pack ( UInt prefix, UInt theInstr ) { /* VX-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -25520,6 +25853,10 @@ static Bool dis_av_pack ( UInt theInstr ) IRTemp zeros = IRTemp_INVALID; IRTemp vA = newTemp(Ity_V128); IRTemp vB = newTemp(Ity_V128); + + /* There is no prefixed version of these instructions. */ + PREFIX_CHECK + assign( vA, getVReg(vA_addr)); assign( vB, getVReg(vB_addr)); @@ -25827,7 +26164,7 @@ static Bool dis_av_pack ( UInt theInstr ) /* AltiVec Cipher Instructions */ -static Bool dis_av_cipher ( UInt theInstr ) +static Bool dis_... [truncated message content] |
|
From: Carl L. <ca...@so...> - 2020-09-22 16:49:05
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=ebcf62b047843bfb0a8c9141b7e272f693c3df28 commit ebcf62b047843bfb0a8c9141b7e272f693c3df28 Author: Carl Love <ce...@us...> Date: Wed May 6 15:13:42 2020 -0500 Add check for isa 3.1 support Diff: --- VEX/priv/guest_ppc_toIR.c | 6 +++++- VEX/priv/host_ppc_isel.c | 5 +++-- VEX/priv/main_main.c | 23 +++++++++++++++++++++++ VEX/pub/libvex.h | 2 ++ coregrind/m_initimg/initimg-linux.c | 23 +++++++++++++++++++++-- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index c4965a19ef..96217fb054 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -28431,6 +28431,7 @@ DisResult disInstr_PPC_WRK ( Bool allow_DFP = False; Bool allow_isa_2_07 = False; Bool allow_isa_3_0 = False; + Bool allow_isa_3_1 = False; /* What insn variants are we supporting today? */ if (mode64) { @@ -28442,6 +28443,7 @@ DisResult disInstr_PPC_WRK ( allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07)); allow_isa_3_0 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_0)); + allow_isa_3_1 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_1)); } else { allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); @@ -28451,6 +28453,7 @@ DisResult disInstr_PPC_WRK ( allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07)); allow_isa_3_0 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_0)); + allow_isa_3_1 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_1)); } /* Enable writting the OV32 and CA32 bits added with ISA3.0 */ @@ -30192,7 +30195,8 @@ DisResult disInstr_PPC ( IRSB* irsb_IN, mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP - | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0; + | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0 + | VEX_HWCAPS_PPC64_ISA3_1; if (mode64) { vassert((hwcaps_guest & mask32) == 0); diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c index 10dbd65976..93d0625800 100644 --- a/VEX/priv/host_ppc_isel.c +++ b/VEX/priv/host_ppc_isel.c @@ -7053,7 +7053,7 @@ HInstrArray* iselSB_PPC ( const IRSB* bb, mode64 = arch_host == VexArchPPC64; /* do some sanity checks, - * Note: no 32-bit support for ISA 3.0 + * Note: no 32-bit support for ISA 3.0, ISA 3.1 */ mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX @@ -7061,7 +7061,8 @@ HInstrArray* iselSB_PPC ( const IRSB* bb, mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP - | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0; + | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0 + | VEX_HWCAPS_PPC64_ISA3_1; if (mode64) { vassert((hwcaps_host & mask32) == 0); diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index 3e788d5240..72f4199886 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -1684,6 +1684,7 @@ static const HChar* show_hwcaps_ppc32 ( UInt hwcaps ) { VEX_HWCAPS_PPC32_DFP, "DFP" }, { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" }, { VEX_HWCAPS_PPC32_ISA3_0, "ISA3_0" }, + { VEX_HWCAPS_PPC32_ISA3_1, "ISA3_1" }, }; /* Allocate a large enough buffer */ static HChar buf[sizeof prefix + @@ -1715,6 +1716,7 @@ static const HChar* show_hwcaps_ppc64 ( UInt hwcaps ) { VEX_HWCAPS_PPC64_DFP, "DFP" }, { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" }, { VEX_HWCAPS_PPC64_ISA3_0, "ISA3_0" }, + { VEX_HWCAPS_PPC64_ISA3_1, "ISA3_1" }, }; /* Allocate a large enough buffer */ static HChar buf[sizeof prefix + @@ -2075,6 +2077,27 @@ static void check_hwcaps ( VexArch arch, UInt hwcaps ) invalid_hwcaps(arch, hwcaps, "ISA3_0 requires DFP capabilities\n"); } + + /* ISA3_1 requires everything else */ + if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_1) != 0) { + if ( !((hwcaps + & VEX_HWCAPS_PPC64_ISA3_0) == VEX_HWCAPS_PPC64_ISA3_0)) + invalid_hwcaps(arch, hwcaps, + "ISA3_1 requires ISA3_0 capabilities\n"); + if ( !((hwcaps + & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07)) + invalid_hwcaps(arch, hwcaps, + "ISA3_1 requires ISA2_07 capabilities\n"); + if ( !has_v_fx_gx) + invalid_hwcaps(arch, hwcaps, + "ISA3_1 requires VMX and FX and GX capabilities\n"); + if ( !(hwcaps & VEX_HWCAPS_PPC64_VX)) + invalid_hwcaps(arch, hwcaps, + "ISA3_1 requires VX capabilities\n"); + if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP)) + invalid_hwcaps(arch, hwcaps, + "ISA3_1 requires DFP capabilities\n"); + } return; } diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 4eb97162fa..490ba06b5e 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -112,6 +112,7 @@ typedef #define VEX_HWCAPS_PPC32_DFP (1<<17) /* Decimal Floating Point (DFP) -- e.g., dadd */ #define VEX_HWCAPS_PPC32_ISA2_07 (1<<19) /* ISA 2.07 -- e.g., mtvsrd */ #define VEX_HWCAPS_PPC32_ISA3_0 (1<<21) /* ISA 3.0 -- e.g., cnttzw */ +#define VEX_HWCAPS_PPC32_ISA3_1 (1<<22) /* ISA 3.1 -- e.g., brh */ /* ppc64: baseline capability is integer and basic FP insns */ #define VEX_HWCAPS_PPC64_V (1<<13) /* Altivec (VMX) */ @@ -122,6 +123,7 @@ typedef #define VEX_HWCAPS_PPC64_DFP (1<<18) /* Decimal Floating Point (DFP) -- e.g., dadd */ #define VEX_HWCAPS_PPC64_ISA2_07 (1<<20) /* ISA 2.07 -- e.g., mtvsrd */ #define VEX_HWCAPS_PPC64_ISA3_0 (1<<22) /* ISA 3.0 -- e.g., cnttzw */ +#define VEX_HWCAPS_PPC64_ISA3_1 (1<<23) /* ISA 3.1 -- e.g., brh */ /* s390x: Hardware capability encoding diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index e811ff667d..365942c4f7 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -721,6 +721,7 @@ Addr setup_client_stack( void* init_sp, case AT_HWCAP2: { Bool auxv_2_07, hw_caps_2_07; Bool auxv_3_0, hw_caps_3_0; + Bool auxv_3_1, hw_caps_3_1; /* The HWCAP2 field may contain an arch_2_07 entry that indicates * if the processor is compliant with the 2.07 ISA. (i.e. Power 8 @@ -771,9 +772,27 @@ Addr setup_client_stack( void* init_sp, == VEX_HWCAPS_PPC64_ISA3_0; /* Verify the PPC_FEATURE2_ARCH_3_00 setting in HWCAP2 - * matches the setting in VEX HWCAPS. - */ + * matches the setting in VEX HWCAPS. + */ vg_assert(auxv_3_0 == hw_caps_3_0); + + /* Power ISA version 3.1 + https://ibm.ent.box.com/s/hhjfw0x0lrbtyzmiaffnbxh2fuo0fog0 + + 64-bit ELF V? ABI specification for Power. HWCAP2 bit pattern + for ISA 3.0, page ?. + + ADD PUBLIC LINK WHEN AVAILABLE + */ + /* ISA 3.1 */ + auxv_3_1 = (auxv->u.a_val & 0x00040000ULL) == 0x00040000ULL; + hw_caps_3_1 = (vex_archinfo->hwcaps & VEX_HWCAPS_PPC64_ISA3_1) + == VEX_HWCAPS_PPC64_ISA3_1; + + /* Verify the PPC_FEATURE2_ARCH_3_1 setting in HWCAP2 + * matches the setting in VEX HWCAPS. + */ + vg_assert(auxv_3_1 == hw_caps_3_1); } break; |