|
From: <sv...@va...> - 2015-04-10 12:27:53
|
Author: sewardj
Date: Fri Apr 10 13:27:40 2015
New Revision: 3124
Log:
Add a port to Linux/TileGx. Zhi-Gang Liu (zl...@ti...)
VEX aspects.
See bug 339778 - Linux/TileGx platform support to Valgrind
Added:
trunk/priv/guest_tilegx_defs.h
trunk/priv/guest_tilegx_helpers.c
trunk/priv/guest_tilegx_toIR.c
trunk/priv/host_tilegx_defs.c
trunk/priv/host_tilegx_defs.h
trunk/priv/host_tilegx_isel.c
trunk/priv/tilegx_disasm.c
trunk/priv/tilegx_disasm.h
trunk/pub/libvex_guest_tilegx.h
Modified:
trunk/auxprogs/genoffsets.c
trunk/priv/guest_generic_bb_to_IR.c
trunk/priv/ir_defs.c
trunk/priv/main_main.c
trunk/pub/libvex.h
trunk/pub/libvex_basictypes.h
Modified: trunk/auxprogs/genoffsets.c
==============================================================================
--- trunk/auxprogs/genoffsets.c (original)
+++ trunk/auxprogs/genoffsets.c Fri Apr 10 13:27:40 2015
@@ -55,6 +55,7 @@
#include "../pub/libvex_guest_s390x.h"
#include "../pub/libvex_guest_mips32.h"
#include "../pub/libvex_guest_mips64.h"
+#include "../pub/libvex_guest_tilegx.h"
#define VG_STRINGIFZ(__str) #__str
#define VG_STRINGIFY(__str) VG_STRINGIFZ(__str)
@@ -263,6 +264,68 @@
GENOFFSET(MIPS64,mips64,PC);
GENOFFSET(MIPS64,mips64,HI);
GENOFFSET(MIPS64,mips64,LO);
+
+ // Tilegx
+ GENOFFSET(TILEGX,tilegx,r0);
+ GENOFFSET(TILEGX,tilegx,r1);
+ GENOFFSET(TILEGX,tilegx,r2);
+ GENOFFSET(TILEGX,tilegx,r3);
+ GENOFFSET(TILEGX,tilegx,r4);
+ GENOFFSET(TILEGX,tilegx,r5);
+ GENOFFSET(TILEGX,tilegx,r6);
+ GENOFFSET(TILEGX,tilegx,r7);
+ GENOFFSET(TILEGX,tilegx,r8);
+ GENOFFSET(TILEGX,tilegx,r9);
+ GENOFFSET(TILEGX,tilegx,r10);
+ GENOFFSET(TILEGX,tilegx,r11);
+ GENOFFSET(TILEGX,tilegx,r12);
+ GENOFFSET(TILEGX,tilegx,r13);
+ GENOFFSET(TILEGX,tilegx,r14);
+ GENOFFSET(TILEGX,tilegx,r15);
+ GENOFFSET(TILEGX,tilegx,r16);
+ GENOFFSET(TILEGX,tilegx,r17);
+ GENOFFSET(TILEGX,tilegx,r18);
+ GENOFFSET(TILEGX,tilegx,r19);
+ GENOFFSET(TILEGX,tilegx,r20);
+ GENOFFSET(TILEGX,tilegx,r21);
+ GENOFFSET(TILEGX,tilegx,r22);
+ GENOFFSET(TILEGX,tilegx,r23);
+ GENOFFSET(TILEGX,tilegx,r24);
+ GENOFFSET(TILEGX,tilegx,r25);
+ GENOFFSET(TILEGX,tilegx,r26);
+ GENOFFSET(TILEGX,tilegx,r27);
+ GENOFFSET(TILEGX,tilegx,r28);
+ GENOFFSET(TILEGX,tilegx,r29);
+ GENOFFSET(TILEGX,tilegx,r30);
+ GENOFFSET(TILEGX,tilegx,r31);
+ GENOFFSET(TILEGX,tilegx,r32);
+ GENOFFSET(TILEGX,tilegx,r33);
+ GENOFFSET(TILEGX,tilegx,r34);
+ GENOFFSET(TILEGX,tilegx,r35);
+ GENOFFSET(TILEGX,tilegx,r36);
+ GENOFFSET(TILEGX,tilegx,r37);
+ GENOFFSET(TILEGX,tilegx,r38);
+ GENOFFSET(TILEGX,tilegx,r39);
+ GENOFFSET(TILEGX,tilegx,r40);
+ GENOFFSET(TILEGX,tilegx,r41);
+ GENOFFSET(TILEGX,tilegx,r42);
+ GENOFFSET(TILEGX,tilegx,r43);
+ GENOFFSET(TILEGX,tilegx,r44);
+ GENOFFSET(TILEGX,tilegx,r45);
+ GENOFFSET(TILEGX,tilegx,r46);
+ GENOFFSET(TILEGX,tilegx,r47);
+ GENOFFSET(TILEGX,tilegx,r48);
+ GENOFFSET(TILEGX,tilegx,r49);
+ GENOFFSET(TILEGX,tilegx,r50);
+ GENOFFSET(TILEGX,tilegx,r51);
+ GENOFFSET(TILEGX,tilegx,r52);
+ GENOFFSET(TILEGX,tilegx,r53);
+ GENOFFSET(TILEGX,tilegx,r54);
+ GENOFFSET(TILEGX,tilegx,r55);
+ GENOFFSET(TILEGX,tilegx,pc);
+ GENOFFSET(TILEGX,tilegx,EMNOTE);
+ GENOFFSET(TILEGX,tilegx,CMSTART);
+ GENOFFSET(TILEGX,tilegx,NRADDR);
}
/*--------------------------------------------------------------------*/
Modified: trunk/priv/guest_generic_bb_to_IR.c
==============================================================================
--- trunk/priv/guest_generic_bb_to_IR.c (original)
+++ trunk/priv/guest_generic_bb_to_IR.c Fri Apr 10 13:27:40 2015
@@ -374,7 +374,7 @@
|| dres.whatNext == Dis_ResteerU
|| dres.whatNext == Dis_ResteerC);
/* ... disassembled insn length is sane ... */
- vassert(dres.len >= 0 && dres.len <= 20);
+ vassert(dres.len >= 0 && dres.len <= 24);
/* ... continueAt is zero if no resteer requested ... */
if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC)
vassert(dres.continueAt == 0);
Added: trunk/priv/guest_tilegx_defs.h
==============================================================================
--- trunk/priv/guest_tilegx_defs.h (added)
+++ trunk/priv/guest_tilegx_defs.h Fri Apr 10 13:27:40 2015
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------*/
+/*--- begin guest_tilegx_defs.h ---*/
+/*---------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2010-2013 Tilera Corp.
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+ /* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
+
+#ifndef __VEX_GUEST_TILEGX_DEFS_H
+#define __VEX_GUEST_TILEGX_DEFS_H
+
+#ifdef __tilegx__
+#include "tilegx_disasm.h"
+#endif
+
+/*---------------------------------------------------------*/
+/*--- tilegx to IR conversion ---*/
+/*---------------------------------------------------------*/
+
+/* Convert one TILEGX insn to IR. See the type DisOneInstrFn in
+ bb_to_IR.h. */
+extern DisResult disInstr_TILEGX ( IRSB* irbb,
+ Bool (*resteerOkFn) ( void *, Addr ),
+ Bool resteerCisOk,
+ void* callback_opaque,
+ const UChar* guest_code,
+ Long delta,
+ Addr guest_IP,
+ VexArch guest_arch,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo,
+ VexEndness host_endness_IN,
+ Bool sigill_diag_IN );
+
+/* Used by the optimiser to specialise calls to helpers. */
+extern IRExpr *guest_tilegx_spechelper ( const HChar * function_name,
+ IRExpr ** args,
+ IRStmt ** precedingStmts,
+ Int n_precedingStmts );
+
+/* Describes to the optimser which part of the guest state require
+ precise memory exceptions. This is logically part of the guest
+ state description. */
+extern Bool guest_tilegx_state_requires_precise_mem_exns (
+ Int, Int, VexRegisterUpdates );
+
+extern VexGuestLayout tilegxGuest_layout;
+
+/*---------------------------------------------------------*/
+/*--- tilegx guest helpers ---*/
+/*---------------------------------------------------------*/
+
+extern ULong tilegx_dirtyhelper_gen ( ULong opc,
+ ULong rd0,
+ ULong rd1,
+ ULong rd2,
+ ULong rd3 );
+
+/*---------------------------------------------------------*/
+/*--- Condition code stuff ---*/
+/*---------------------------------------------------------*/
+
+/* Defines conditions which we can ask for TILEGX */
+
+typedef enum {
+ TILEGXCondEQ = 0, /* equal : Z=1 */
+ TILEGXCondNE = 1, /* not equal : Z=0 */
+ TILEGXCondHS = 2, /* >=u (higher or same) : C=1 */
+ TILEGXCondLO = 3, /* <u (lower) : C=0 */
+ TILEGXCondMI = 4, /* minus (negative) : N=1 */
+ TILEGXCondPL = 5, /* plus (zero or +ve) : N=0 */
+ TILEGXCondVS = 6, /* overflow : V=1 */
+ TILEGXCondVC = 7, /* no overflow : V=0 */
+ TILEGXCondHI = 8, /* >u (higher) : C=1 && Z=0 */
+ TILEGXCondLS = 9, /* <=u (lower or same) : C=0 || Z=1 */
+ TILEGXCondGE = 10, /* >=s (signed greater or equal) : N=V */
+ TILEGXCondLT = 11, /* <s (signed less than) : N!=V */
+ TILEGXCondGT = 12, /* >s (signed greater) : Z=0 && N=V */
+ TILEGXCondLE = 13, /* <=s (signed less or equal) : Z=1 || N!=V */
+ TILEGXCondAL = 14, /* always (unconditional) : 1 */
+ TILEGXCondNV = 15 /* never (unconditional): : 0 */
+} TILEGXCondcode;
+
+#endif /* __VEX_GUEST_TILEGX_DEFS_H */
+
+/*---------------------------------------------------------------*/
+/*--- end guest_tilegx_defs.h ---*/
+/*---------------------------------------------------------------*/
Added: trunk/priv/guest_tilegx_helpers.c
==============================================================================
--- trunk/priv/guest_tilegx_helpers.c (added)
+++ trunk/priv/guest_tilegx_helpers.c Fri Apr 10 13:27:40 2015
@@ -0,0 +1,1112 @@
+/*---------------------------------------------------------------*/
+/*--- begin guest_tilegx_helpers.c ---*/
+/*---------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2010-2013 Tilera Corp.
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
+
+#include "libvex_basictypes.h"
+#include "libvex_emnote.h"
+#include "libvex_guest_tilegx.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+
+#include "main_util.h"
+#include "guest_generic_bb_to_IR.h"
+#include "guest_tilegx_defs.h"
+
+/* This file contains helper functions for tilegx guest code. Calls to
+ these functions are generated by the back end.
+*/
+
+#define ALWAYSDEFD(field) \
+ { offsetof(VexGuestTILEGXState, field), \
+ (sizeof ((VexGuestTILEGXState*)0)->field) }
+
+/* generalised left-shifter */
+static inline UInt lshift ( UInt x, Int n )
+{
+ if (n >= 0)
+ return x << n;
+ else
+ return x >> (-n);
+}
+
+IRExpr *guest_tilegx_spechelper ( const HChar * function_name, IRExpr ** args,
+ IRStmt ** precedingStmts, Int n_precedingStmts)
+{
+ return NULL;
+}
+
+/* VISIBLE TO LIBVEX CLIENT */
+void LibVEX_GuestTILEGX_initialise ( VexGuestTILEGXState * vex_state )
+{
+ vex_state->guest_r0 = 0;
+ vex_state->guest_r1 = 0;
+ vex_state->guest_r2 = 0;
+ vex_state->guest_r3 = 0;
+ vex_state->guest_r4 = 0;
+ vex_state->guest_r5 = 0;
+ vex_state->guest_r6 = 0;
+ vex_state->guest_r7 = 0;
+ vex_state->guest_r8 = 0;
+ vex_state->guest_r9 = 0;
+ vex_state->guest_r10 = 0;
+ vex_state->guest_r11 = 0;
+ vex_state->guest_r12 = 0;
+ vex_state->guest_r13 = 0;
+ vex_state->guest_r14 = 0;
+ vex_state->guest_r15 = 0;
+ vex_state->guest_r16 = 0;
+ vex_state->guest_r17 = 0;
+ vex_state->guest_r18 = 0;
+ vex_state->guest_r19 = 0;
+ vex_state->guest_r20 = 0;
+ vex_state->guest_r21 = 0;
+ vex_state->guest_r22 = 0;
+ vex_state->guest_r23 = 0;
+ vex_state->guest_r24 = 0;
+ vex_state->guest_r25 = 0;
+ vex_state->guest_r26 = 0;
+ vex_state->guest_r27 = 0;
+ vex_state->guest_r28 = 0;
+ vex_state->guest_r29 = 0;
+ vex_state->guest_r30 = 0;
+ vex_state->guest_r31 = 0;
+ vex_state->guest_r32 = 0;
+ vex_state->guest_r33 = 0;
+ vex_state->guest_r34 = 0;
+ vex_state->guest_r35 = 0;
+ vex_state->guest_r36 = 0;
+ vex_state->guest_r37 = 0;
+ vex_state->guest_r38 = 0;
+ vex_state->guest_r39 = 0;
+ vex_state->guest_r40 = 0;
+ vex_state->guest_r41 = 0;
+ vex_state->guest_r42 = 0;
+ vex_state->guest_r43 = 0;
+ vex_state->guest_r44 = 0;
+ vex_state->guest_r45 = 0;
+ vex_state->guest_r46 = 0;
+ vex_state->guest_r47 = 0;
+ vex_state->guest_r48 = 0;
+ vex_state->guest_r49 = 0;
+ vex_state->guest_r50 = 0;
+ vex_state->guest_r51 = 0;
+ vex_state->guest_r52 = 0;
+ vex_state->guest_r53 = 0;
+ vex_state->guest_r54 = 0;
+ vex_state->guest_r55 = 0;
+
+ vex_state->guest_pc = 0; /* Program counter */
+
+ vex_state->guest_EMNOTE = 0;
+ vex_state->guest_CMSTART = 0;
+
+ /* For clflush: record start and length of area to invalidate */
+ vex_state->guest_CMSTART = 0;
+ vex_state->guest_CMLEN = 0;
+
+ /* Used to record the unredirected guest address at the start of
+ a translation whose start has been redirected. By reading
+ this pseudo-register shortly afterwards, the translation can
+ find out what the corresponding no-redirection address was.
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ vex_state->guest_NRADDR = 0;
+}
+
+/*-----------------------------------------------------------*/
+/*--- Describing the tilegx guest state, for the benefit ---*/
+/*--- of iropt and instrumenters. ---*/
+/*-----------------------------------------------------------*/
+
+/* Figure out if any part of the guest state contained in minoff
+ .. maxoff requires precise memory exceptions. If in doubt return
+ True (but this is generates significantly slower code).
+
+ We enforce precise exns for guest SP, PC.
+*/
+Bool guest_tilegx_state_requires_precise_mem_exns (
+ Int minoff, Int maxoff,
+ VexRegisterUpdates pxControl)
+{
+ Int sp_min = offsetof(VexGuestTILEGXState, guest_r54);
+ Int sp_max = sp_min + 8 - 1;
+ Int pc_min = offsetof(VexGuestTILEGXState, guest_pc);
+ Int pc_max = pc_min + 8 - 1;
+
+ if (maxoff < sp_min || minoff > sp_max) {
+ /* no overlap with sp */
+ if (pxControl == VexRegUpdSpAtMemAccess)
+ return False; /* We only need to check stack pointer. */
+ } else {
+ return True;
+ }
+
+ if (maxoff < pc_min || minoff > pc_max) {
+ /* no overlap with pc */
+ } else {
+ return True;
+ }
+
+ /* We appear to need precise updates of R52 in order to get proper
+ stacktraces from non-optimised code. */
+ Int fp_min = offsetof(VexGuestTILEGXState, guest_r52);
+ Int fp_max = fp_min + 8 - 1;
+
+ if (maxoff < fp_min || minoff > fp_max) {
+ /* no overlap with fp */
+ } else {
+ return True;
+ }
+
+ return False;
+}
+
+VexGuestLayout tilegxGuest_layout = {
+ /* Total size of the guest state, in bytes. */
+ .total_sizeB = sizeof(VexGuestTILEGXState),
+ /* Describe the stack pointer. */
+ .offset_SP = offsetof(VexGuestTILEGXState, guest_r54),
+ .sizeof_SP = 8,
+ /* Describe the frame pointer. */
+ .offset_FP = offsetof(VexGuestTILEGXState, guest_r52),
+ .sizeof_FP = 8,
+ /* Describe the instruction pointer. */
+ .offset_IP = offsetof(VexGuestTILEGXState, guest_pc),
+ .sizeof_IP = 8,
+ /* Describe any sections to be regarded by Memcheck as
+ 'always-defined'. */
+ .n_alwaysDefd = 8,
+ /* ? :( */
+ .alwaysDefd = {
+ /* 0 */ ALWAYSDEFD(guest_r0),
+ /* 1 */ ALWAYSDEFD(guest_r1),
+ /* 2 */ ALWAYSDEFD(guest_EMNOTE),
+ /* 3 */ ALWAYSDEFD(guest_CMSTART),
+ /* 4 */ ALWAYSDEFD(guest_CMLEN),
+ /* 5 */ ALWAYSDEFD(guest_r52),
+ /* 6 */ ALWAYSDEFD(guest_r55),
+ /* 7 */ ALWAYSDEFD(guest_pc),
+ }
+};
+
+#ifdef __tilegx__
+ULong tilegx_dirtyhelper_gen ( ULong opc,
+ ULong rd0, ULong rd1,
+ ULong rd2, ULong rd3)
+{
+ switch (opc)
+ {
+ case 0:
+ {
+ /* break point */
+ switch (rd0) {
+ case 0x286a44ae90048fffULL:
+ asm (" bpt ");
+ break;
+ default:
+ vex_printf("unhandled \"bpt\": cins=%016llx\n", rd0);
+
+ vassert(0);
+ return 0;
+ }
+ }
+ break;
+ case 28:
+ {
+ return __insn_addxsc(rd1, rd2);
+ }
+ break;
+
+ case 150:
+ {
+ __insn_mf();
+ return 0;
+ }
+ break;
+
+ case 152: /* mm rd, ra, imm0, imm1 */
+ {
+ ULong mask;
+
+ if( rd2 <= rd3)
+ mask = (-1ULL << rd2) ^ ((-1ULL << rd3) << 1);
+ else
+ mask = (-1ULL << rd2) | (-1ULL >> (63 - rd3));
+
+ return (rd0 & mask) | (rd1 & (-1ULL ^ mask));
+ }
+ break;
+ case 154: /* mtspr imm, ra */
+ {
+ switch(rd0)
+ {
+ case 0x2785:
+ __insn_mtspr(0x2785, rd1);
+ break;
+ case 0x2780:
+ __insn_mtspr(0x2780, rd1);
+ break;
+ case 0x2708:
+ __insn_mtspr(0x2708, rd1);
+ break;
+ case 0x2580:
+ __insn_mtspr(0x2580, rd1);
+ break;
+ case 0x2581:
+ __insn_mtspr(0x2581, rd1);
+ break;
+ case 0x2709: // PASS
+ __insn_mtspr(0x2709, rd1);
+ break;
+ case 0x2707: // FAIL
+ __insn_mtspr(0x2707, rd1);
+ break;
+ case 0x2705: // DONE
+ __insn_mtspr(0x2705, rd1);
+ break;
+
+ case 0x2870: //
+
+ default:
+ vex_printf("opc=%d rd0=%llx rd1=%llx\n",
+ (int)opc, rd0, rd1);
+ vassert(0);
+ }
+ }
+ break;
+
+ case 151: /* mfspr rd, imm */
+ {
+ switch(rd1)
+ {
+ case 0x2785: // SIM_CTRL
+ return __insn_mfspr(0x2785);
+ break;
+
+ case 0x2708: // ICS
+ return __insn_mfspr(0x2708);
+ break;
+
+ case 0x2780: // CMPEXCH_VALUE
+ return __insn_mfspr(0x2780);
+ break;
+
+ case 0x2781: // CYCLE
+ return __insn_mfspr(0x2781);
+ break;
+
+ case 0x2709: // PASS
+ return __insn_mfspr(0x2709);
+ break;
+
+ case 0x2707: // FAIL
+ return __insn_mfspr(0x2707);
+ break;
+
+ case 0x2705: // DONE
+ return __insn_mfspr(0x2705);
+ break;
+
+ case 0x2580: // EX_CONTEXT_0
+ return __insn_mfspr(0x2580);
+ break;
+
+ case 0x2581: // EX_CONTEXT_1
+ return __insn_mfspr(0x2581);
+ break;
+
+ default:
+ vex_printf("opc=%d rd0=%llx rd1=%llx\n",
+ (int)opc, rd0, rd1);
+ vassert(0);
+ }
+ }
+ break;
+ case 183:
+ {
+ return __insn_pcnt(rd1);
+ }
+ break;
+ case 184:
+ {
+ return __insn_revbits(rd1);
+ }
+ break;
+ case 185: /* revbytes rd, ra */
+ {
+ return __insn_revbytes(rd1);
+ }
+ break;
+
+ case 102:
+ return __insn_fsingle_add1(rd1, rd2);
+ break;
+
+ case 103:
+ return __insn_fsingle_addsub2(rd0, rd1, rd2);
+ break;
+
+ case 104:
+ return __insn_fsingle_mul1(rd1, rd2);
+ break;
+
+ case 105:
+ return __insn_fsingle_mul2(rd1, rd2);
+ break;
+
+ case 106:
+ return __insn_fsingle_pack1(rd1);
+ break;
+
+ case 107:
+ return __insn_fsingle_pack2(rd1, rd2);
+ break;
+
+ case 108:
+ return __insn_fsingle_sub1(rd1, rd2);
+ break;
+
+ case 21:
+ switch (rd0) {
+ case 0x286a44ae90048fffULL:
+ asm ("{ moveli zero, 72 ; raise }");
+ break;
+ default:
+ vex_printf("unhandled \"raise\": cins=%016llx\n", rd0);
+ __insn_ill();
+ return 0;
+ }
+ break;
+
+ case 64:
+ {
+ return __insn_cmul(rd1, rd2);
+ }
+ break;
+ case 65:
+ {
+ return __insn_cmula(rd0, rd1, rd2);
+ }
+ break;
+ case 66:
+ {
+ return __insn_cmulaf(rd0, rd1, rd2);
+ }
+ break;
+ case 67:
+ {
+ return __insn_cmulf(rd1, rd2);
+ }
+ break;
+ case 68:
+ {
+ return __insn_cmulfr(rd1, rd2);
+ }
+ break;
+ case 69:
+ {
+ return __insn_cmulh(rd1, rd2);
+ }
+ break;
+ case 70:
+ {
+ return __insn_cmulhr(rd1, rd2);
+ }
+ break;
+ case 71:
+ {
+ return __insn_crc32_32(rd1, rd2);
+ }
+ break;
+ case 72:
+ {
+ return __insn_crc32_8(rd1, rd2);
+ }
+ break;
+ case 75:
+ {
+ return __insn_dblalign2(rd1, rd2);
+ }
+ break;
+ case 76:
+ {
+ return __insn_dblalign4(rd1, rd2);
+ }
+ break;
+ case 77:
+ {
+ return __insn_dblalign6(rd1, rd2);
+ }
+ break;
+ case 78:
+ {
+ __insn_drain();
+ return 0;
+ }
+ break;
+ case 79:
+ {
+ __insn_dtlbpr(rd0);
+ return 0;
+ }
+ break;
+ case 82:
+ {
+ return __insn_fdouble_add_flags(rd1, rd2);
+ }
+ break;
+ case 83:
+ {
+ return __insn_fdouble_addsub(rd0, rd1, rd2);
+ }
+ break;
+ case 84:
+ {
+ return __insn_fdouble_mul_flags(rd1, rd2);
+ }
+ break;
+ case 85:
+ {
+ return __insn_fdouble_pack1(rd1, rd2);
+ }
+ break;
+ case 86:
+ {
+ return __insn_fdouble_pack2(rd0, rd1, rd2);
+ }
+ break;
+ case 87:
+ {
+ return __insn_fdouble_sub_flags(rd1, rd2);
+ }
+ break;
+ case 88:
+ {
+ return __insn_fdouble_unpack_max(rd1, rd2);
+ }
+ break;
+ case 89:
+ {
+ return __insn_fdouble_unpack_min(rd1, rd2);
+ }
+ break;
+
+ case 98:
+ {
+ __insn_finv(rd0);
+ return 0;
+ }
+ break;
+ case 99:
+ {
+ __insn_flush(rd0);
+ return 0;
+ }
+ break;
+ case 100:
+ {
+ __insn_flushwb();
+ return 0;
+ }
+ break;
+
+ case 109:
+ {
+ __insn_icoh((ULong *)rd0);
+ return 0;
+ }
+ break;
+ case 110:
+ {
+ __insn_ill();
+ }
+ break;
+ case 111:
+ {
+ __insn_inv((ULong *)rd0);
+ return 0;
+ }
+ break;
+
+ case 169:
+ {
+ return __insn_mula_hu_hu(rd0, rd1, rd2);
+ }
+ break;
+ case 170:
+ {
+ return __insn_mula_hu_ls(rd0, rd1, rd2);
+ }
+ break;
+ case 205:
+ {
+ return __insn_shufflebytes(rd0, rd1, rd2);
+ }
+ break;
+ case 224:
+ {
+ return __insn_subxsc(rd1, rd2);
+ }
+ break;
+ case 229:
+ {
+ return __insn_tblidxb0(rd0, rd1);
+ }
+ break;
+ case 230:
+ {
+ return __insn_tblidxb1(rd0, rd1);
+ }
+ break;
+ case 231:
+ {
+ return __insn_tblidxb2(rd0, rd1);
+ }
+ break;
+ case 232:
+ {
+ return __insn_tblidxb3(rd0, rd1);
+ }
+ break;
+ case 233:
+ {
+ return __insn_v1add(rd1, rd2);
+ }
+ break;
+ case 234:
+ {
+ return __insn_v1add(rd1, rd2);
+ }
+ break;
+ case 235:
+ {
+ return __insn_v1adduc(rd1, rd2);
+ }
+ break;
+ case 236:
+ {
+ return __insn_v1adiffu(rd1, rd2);
+ }
+ break;
+ case 237:
+ {
+ return __insn_v1avgu(rd1, rd2);
+ }
+ break;
+
+ case 238:
+ {
+ return __insn_v1cmpeq(rd1, rd2);
+ }
+ break;
+ case 239:
+ {
+ return __insn_v1cmpeq(rd1, rd2);
+ }
+ break;
+ case 240:
+ {
+ return __insn_v1cmples(rd1, rd2);
+ }
+ break;
+ case 241:
+ {
+ return __insn_v1cmpleu(rd1, rd2);
+ }
+ break;
+ case 242:
+ {
+ return __insn_v1cmplts(rd1, rd2);
+ }
+ break;
+ case 243:
+ {
+ return __insn_v1cmplts(rd1, rd2);
+ }
+ break;
+ case 244:
+ {
+ return __insn_v1cmpltu(rd1, rd2);
+ }
+ break;
+ case 245:
+ {
+ return __insn_v1cmpltu(rd1, rd2);
+ }
+ break;
+ case 246:
+ {
+ return __insn_v1cmpne(rd1, rd2);
+ }
+ break;
+ case 247:
+ {
+ return __insn_v1ddotpu(rd1, rd2);
+ }
+ break;
+ case 248:
+ {
+ return __insn_v1ddotpua(rd0, rd1, rd2);
+ }
+ break;
+ case 249:
+ {
+ return __insn_v1ddotpus(rd1, rd2);
+ }
+ break;
+ case 250:
+ {
+ return __insn_v1ddotpusa(rd0, rd1, rd2);
+ }
+ break;
+ case 251:
+ {
+ return __insn_v1dotp(rd1, rd2);
+ }
+ break;
+ case 252:
+ {
+ return __insn_v1dotpa(rd0, rd1, rd2);
+ }
+ break;
+ case 253:
+ {
+ return __insn_v1dotpu(rd1, rd2);
+ }
+ break;
+ case 254:
+ {
+ return __insn_v1dotpua(rd0, rd1, rd2);
+ }
+ break;
+ case 255:
+ {
+ return __insn_v1dotpus(rd1, rd2);
+ }
+ break;
+ case 256:
+ {
+ return __insn_v1dotpusa(rd0, rd1, rd2);
+ }
+ break;
+ case 257:
+ {
+ return __insn_v1int_h(rd1, rd2);
+ }
+ break;
+ case 258:
+ {
+ return __insn_v1int_l(rd1, rd2);
+ }
+ break;
+ case 259:
+ {
+ return __insn_v1maxu(rd1, rd2);
+ }
+ break;
+ case 260:
+ {
+ return __insn_v1maxu(rd1, rd2);
+ }
+ break;
+ case 261:
+ {
+ return __insn_v1minu(rd1, rd2);
+ }
+ break;
+ case 262:
+ {
+ return __insn_v1minu(rd1, rd2);
+ }
+ break;
+ case 263:
+ {
+ return __insn_v1mnz(rd1, rd2);
+ }
+ break;
+ case 264:
+ {
+ return __insn_v1multu(rd1, rd2);
+ }
+ break;
+ case 265:
+ {
+ return __insn_v1mulu(rd1, rd2);
+ }
+ break;
+ case 266:
+ {
+ return __insn_v1mulus(rd1, rd2);
+ }
+ break;
+ case 267:
+ {
+ return __insn_v1mz(rd1, rd2);
+ }
+ break;
+ case 268:
+ {
+ return __insn_v1sadau(rd0, rd1, rd2);
+ }
+ break;
+ case 269:
+ {
+ return __insn_v1sadu(rd1, rd2);
+ }
+ break;
+ case 270:
+ {
+ return __insn_v1shl(rd1, rd2);
+ }
+ break;
+ case 271:
+ {
+ return __insn_v1shli(rd1, rd2);
+ }
+ break;
+ case 272:
+ {
+ return __insn_v1shrs(rd1, rd2);
+ }
+ break;
+ case 273:
+ {
+ return __insn_v1shrsi(rd1, rd2);
+ }
+ break;
+ case 274:
+ {
+ return __insn_v1shru(rd1, rd2);
+ }
+ break;
+ case 275:
+ {
+ return __insn_v1shrui(rd1, rd2);
+ }
+ break;
+ case 276:
+ {
+ return __insn_v1sub(rd1, rd2);
+ }
+ break;
+ case 277:
+ {
+ return __insn_v1subuc(rd1, rd2);
+ }
+ break;
+ case 278:
+ {
+ return __insn_v2add(rd1, rd2);
+ }
+ break;
+ case 279:
+ {
+ return __insn_v2add(rd1, rd2);
+ }
+ break;
+ case 280:
+ {
+ return __insn_v2addsc(rd1, rd2);
+ }
+ break;
+ case 281:
+ {
+ return __insn_v2adiffs(rd1, rd2);
+ }
+ break;
+ case 282:
+ {
+ return __insn_v2avgs(rd1, rd2);
+ }
+ break;
+ case 283:
+ {
+ return __insn_v2cmpeq(rd1, rd2);
+ }
+ break;
+ case 284:
+ {
+ return __insn_v2cmpeq(rd1, rd2);
+ }
+ break;
+ case 285:
+ {
+ return __insn_v2cmples(rd1, rd2);
+ }
+ break;
+ case 286:
+ {
+ return __insn_v2cmpleu(rd1, rd2);
+ }
+ break;
+ case 287:
+ {
+ return __insn_v2cmplts(rd1, rd2);
+ }
+ break;
+ case 288:
+ {
+ return __insn_v2cmplts(rd1, rd2);
+ }
+ break;
+ case 289:
+ {
+ return __insn_v2cmpltu(rd1, rd2);
+ }
+ break;
+ case 290:
+ {
+ return __insn_v2cmpltu(rd1, rd2);
+ }
+ break;
+ case 291:
+ {
+ return __insn_v2cmpne(rd1, rd2);
+ }
+ break;
+ case 292:
+ {
+ return __insn_v2dotp(rd1, rd2);
+ }
+ break;
+ case 293:
+ {
+ return __insn_v2dotpa(rd0, rd1, rd2);
+ }
+ break;
+ case 294:
+ {
+ return __insn_v2int_h(rd1, rd2);
+ }
+ break;
+ case 295:
+ {
+ return __insn_v2int_l(rd1, rd2);
+ }
+ break;
+ case 296:
+ {
+ return __insn_v2maxs(rd1, rd2);
+ }
+ break;
+ case 297:
+ {
+ return __insn_v2maxs(rd1, rd2);
+ }
+ break;
+ case 298:
+ {
+ return __insn_v2mins(rd1, rd2);
+ }
+ break;
+ case 299:
+ {
+ return __insn_v2mins(rd1, rd2);
+ }
+ break;
+ case 300:
+ {
+ return __insn_v2mnz(rd1, rd2);
+ }
+ break;
+ case 301:
+ {
+ return __insn_v2mulfsc(rd1, rd2);
+ }
+ break;
+ case 302:
+ {
+ return __insn_v2muls(rd1, rd2);
+ }
+ break;
+ case 303:
+ {
+ return __insn_v2mults(rd1, rd2);
+ }
+ break;
+ case 304:
+ {
+ return __insn_v2mz(rd1, rd2);
+ }
+ break;
+ case 305:
+ {
+ return __insn_v2packh(rd1, rd2);
+ }
+ break;
+ case 306:
+ {
+ return __insn_v2packl(rd1, rd2);
+ }
+ break;
+ case 307:
+ {
+ return __insn_v2packuc(rd1, rd2);
+ }
+ break;
+ case 308:
+ {
+ return __insn_v2sadas(rd0, rd1, rd2);
+ }
+ break;
+ case 309:
+ {
+ return __insn_v2sadau(rd0, rd1, rd2);
+ }
+ break;
+ case 310:
+ {
+ return __insn_v2sads(rd1, rd2);
+ }
+ break;
+ case 311:
+ {
+ return __insn_v2sadu(rd1, rd2);
+ }
+ break;
+ case 312:
+ {
+ return __insn_v2shl(rd1, rd2);
+ }
+ break;
+ case 313:
+ {
+ return __insn_v2shli(rd1, rd2);
+ }
+ break;
+ case 314:
+ {
+ return __insn_v2shlsc(rd1, rd2);
+ }
+ break;
+ case 315:
+ {
+ return __insn_v2shrs(rd1, rd2);
+ }
+ break;
+ case 316:
+ {
+ return __insn_v2shrsi(rd1, rd2);
+ }
+ break;
+ case 317:
+ {
+ return __insn_v2shru(rd1, rd2);
+ }
+ break;
+ case 318:
+ {
+ return __insn_v2shrui(rd1, rd2);
+ }
+ break;
+ case 319:
+ {
+ return __insn_v2sub(rd1, rd2);
+ }
+ break;
+ case 320:
+ {
+ return __insn_v2subsc(rd1, rd2);
+ }
+ break;
+ case 321:
+ {
+ return __insn_v4add(rd1, rd2);
+ }
+ break;
+ case 322:
+ {
+ return __insn_v4addsc(rd1, rd2);
+ }
+ break;
+ case 323:
+ {
+ return __insn_v4int_h(rd1, rd2);
+ }
+ break;
+ case 324:
+ {
+ return __insn_v4int_l(rd1, rd2);
+ }
+ break;
+ case 325:
+ {
+ return __insn_v4packsc(rd1, rd2);
+ }
+ break;
+ case 326:
+ {
+ return __insn_v4shl(rd1, rd2);
+ }
+ break;
+ case 327:
+ {
+ return __insn_v4shlsc(rd1, rd2);
+ }
+ break;
+ case 328:
+ {
+ return __insn_v4shrs(rd1, rd2);
+ }
+ break;
+ case 329:
+ {
+ return __insn_v4shru(rd1, rd2);
+ }
+ break;
+ case 330:
+ {
+ return __insn_v4sub(rd1, rd2);
+ }
+ break;
+ case 331:
+ {
+ return __insn_v4subsc(rd1, rd2);
+ }
+ break;
+
+ default:
+ vex_printf("opc=%d rd0=%llx rd1=%llx\n",
+ (int)opc, rd0, rd1);
+ vassert(0);
+ }
+}
+#else
+ULong tilegx_dirtyhelper_gen ( ULong opc,
+ ULong rd0, ULong rd1,
+ ULong rd2, ULong rd3 )
+{
+ vex_printf("NOT a TILEGX platform");
+ return 0;
+}
+#endif /* __tilegx__ */
+
+/*---------------------------------------------------------------*/
+/*--- end guest_tilegx_helpers.c ---*/
+/*---------------------------------------------------------------*/
Added: trunk/priv/guest_tilegx_toIR.c
==============================================================================
--- trunk/priv/guest_tilegx_toIR.c (added)
+++ trunk/priv/guest_tilegx_toIR.c Fri Apr 10 13:27:40 2015
@@ -0,0 +1,2518 @@
+
+/*--------------------------------------------------------------------*/
+/*--- begin guest_tilegx_toIR.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2010-2013 Tilera Corp.
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
+
+/* Translates TILEGX code to IR. */
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+#include "libvex_guest_tilegx.h"
+
+#include "main_util.h"
+#include "main_globals.h"
+#include "guest_generic_bb_to_IR.h"
+#include "guest_tilegx_defs.h"
+#include "tilegx_disasm.h"
+
+#if __tilegx__
+/*------------------------------------------------------------*/
+/*--- Globals ---*/
+/*------------------------------------------------------------*/
+
+/* These are set at the start of the translation of a instruction, so
+ that we don't have to pass them around endlessly. CONST means does
+ not change during translation of the instruction.
+*/
+
+/* CONST: is the host bigendian? This has to do with float vs double
+ register accesses on VFP, but it's complex and not properly thought
+ out. */
+static VexEndness host_endness;
+
+/* Pointer to the guest code area. */
+static UChar *guest_code;
+
+/* The guest address corresponding to guest_code[0]. */
+static Addr64 guest_PC_bbstart;
+
+/* CONST: The guest address for the instruction currently being
+ translated. */
+static Addr64 guest_PC_curr_instr;
+
+/* MOD: The IRSB* into which we're generating code. */
+static IRSB *irsb;
+
+/*------------------------------------------------------------*/
+/*--- Debugging output ---*/
+/*------------------------------------------------------------*/
+
+#define DIP(format, args...) \
+ if (vex_traceflags & VEX_TRACE_FE) \
+ vex_printf(format, ## args)
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for deconstructing the ---*/
+/*--- tilegx insn stream. ---*/
+/*------------------------------------------------------------*/
+
+static Int integerGuestRegOffset ( UInt iregNo )
+{
+ return 8 * (iregNo);
+}
+
+/*------------------------------------------------------------*/
+/*--- Field helpers ---*/
+/*------------------------------------------------------------*/
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments. ---*/
+/*------------------------------------------------------------*/
+
+static IRExpr *mkU8 ( UInt i )
+{
+ return IRExpr_Const(IRConst_U8((UChar) i));
+}
+
+/* Create an expression node for a 32-bit integer constant */
+static IRExpr *mkU32 ( UInt i )
+{
+ return IRExpr_Const(IRConst_U32(i));
+}
+
+/* Create an expression node for a 64-bit integer constant */
+static IRExpr *mkU64 ( ULong i )
+{
+ return IRExpr_Const(IRConst_U64(i));
+}
+
+static IRExpr *mkexpr ( IRTemp tmp )
+{
+ return IRExpr_RdTmp(tmp);
+}
+
+static IRExpr *unop ( IROp op, IRExpr * a )
+{
+ return IRExpr_Unop(op, a);
+}
+
+static IRExpr *binop ( IROp op, IRExpr * a1, IRExpr * a2 )
+{
+ return IRExpr_Binop(op, a1, a2);
+}
+
+static IRExpr *load ( IRType ty, IRExpr * addr )
+{
+ IRExpr *load1 = NULL;
+
+ load1 = IRExpr_Load(Iend_LE, ty, addr);
+ return load1;
+}
+
+/* Add a statement to the list held by "irsb". */
+static void stmt ( IRStmt * st )
+{
+ addStmtToIRSB(irsb, st);
+}
+
+#define OFFB_PC offsetof(VexGuestTILEGXState, guest_pc)
+
+static void putPC ( IRExpr * e )
+{
+ stmt(IRStmt_Put(OFFB_PC, e));
+}
+
+static void assign ( IRTemp dst, IRExpr * e )
+{
+ stmt(IRStmt_WrTmp(dst, e));
+}
+
+static void store ( IRExpr * addr, IRExpr * data )
+{
+ stmt(IRStmt_Store(Iend_LE, addr, data));
+}
+
+/* Generate a new temporary of the given type. */
+static IRTemp newTemp ( IRType ty )
+{
+ vassert(isPlausibleIRType(ty));
+ return newIRTemp(irsb->tyenv, ty);
+}
+
+static ULong extend_s_16to64 ( UInt x )
+{
+ return (ULong) ((((Long) x) << 48) >> 48);
+}
+
+static ULong extend_s_8to64 ( UInt x )
+{
+ return (ULong) ((((Long) x) << 56) >> 56);
+}
+
+static IRExpr *getIReg ( UInt iregNo )
+{
+ IRType ty = Ity_I64;
+ if(!(iregNo < 56 || iregNo == 63 ||
+ (iregNo >= 70 && iregNo <= 73))) {
+ vex_printf("iregNo=%d\n", iregNo);
+ vassert(0);
+ }
+ return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
+}
+
+static void putIReg ( UInt archreg, IRExpr * e )
+{
+ IRType ty = Ity_I64;
+ if(!(archreg < 56 || archreg == 63 || archreg == 70 ||
+ archreg == 72 || archreg == 73)) {
+ vex_printf("archreg=%d\n", archreg);
+ vassert(0);
+ }
+ vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+ if (archreg != 63)
+ stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
+}
+
+/* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
+ of these combinations make sense. */
+static IRExpr *narrowTo ( IRType dst_ty, IRExpr * e )
+{
+ IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
+ if (src_ty == dst_ty)
+ return e;
+ if (src_ty == Ity_I32 && dst_ty == Ity_I16)
+ return unop(Iop_32to16, e);
+ if (src_ty == Ity_I32 && dst_ty == Ity_I8)
+ return unop(Iop_32to8, e);
+
+ if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
+ return unop(Iop_64to8, e);
+ }
+ if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
+ return unop(Iop_64to16, e);
+ }
+ if (src_ty == Ity_I64 && dst_ty == Ity_I32) {
+ return unop(Iop_64to32, e);
+ }
+
+ if (vex_traceflags & VEX_TRACE_FE) {
+ vex_printf("\nsrc, dst tys are: ");
+ ppIRType(src_ty);
+ vex_printf(", ");
+ ppIRType(dst_ty);
+ vex_printf("\n");
+ }
+ vpanic("narrowTo(tilegx)");
+ return e;
+}
+
+#define signExtend(_e, _n) \
+ ((_n == 32) ? \
+ unop(Iop_32Sto64, _e) : \
+ ((_n == 16) ? \
+ (Iop_16Sto64, _e) : \
+ (binop(Iop_Sar64, binop(Iop_Shl64, _e, mkU8(63 - (_n))), mkU8(63 - (_n))))))
+
+static IRStmt* dis_branch ( IRExpr* guard, ULong imm )
+{
+ IRTemp t0;
+
+ t0 = newTemp(Ity_I1);
+ assign(t0, guard);
+ return IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U64(imm), OFFB_PC);
+}
+
+#define MARK_REG_WB(_rd, _td) \
+ do { \
+ vassert(rd_wb_index < 6); \
+ rd_wb_temp[rd_wb_index] = _td; \
+ rd_wb_reg[rd_wb_index] = _rd; \
+ rd_wb_index++; \
+ } while(0)
+
+/*------------------------------------------------------------*/
+/*--- Disassemble a single instruction ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction bundle into IR. The bundle is
+ located in host memory at guest_instr, and has guest IP of
+ guest_PC_curr_instr, which will have been set before the call
+ here. */
+static DisResult disInstr_TILEGX_WRK ( Bool(*resteerOkFn) (void *, Addr),
+ Bool resteerCisOk,
+ void *callback_opaque,
+ Long delta64,
+ const VexArchInfo * archinfo,
+ const VexAbiInfo * abiinfo,
+ Bool sigill_diag )
+{
+ struct tilegx_decoded_instruction
+ decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
+ ULong cins, opcode, rd, ra, rb, imm;
+ ULong opd[4];
+ ULong opd_src_map, opd_dst_map, opd_imm_map;
+ Int use_dirty_helper;
+ IRTemp t0, t1, t2, t3, t4;
+ IRTemp tb[4];
+ IRTemp rd_wb_temp[6];
+ ULong rd_wb_reg[6];
+ /* Tilegx is a VLIW processor, we have to commit register write after read.*/
+ Int rd_wb_index;
+ Int n, nr_insn;
+ DisResult dres;
+ Int stmts_used;
+
+ /* The running delta */
+ Long delta = delta64;
+
+ /* Holds pc at the start of the insn, so that we can print
+ consistent error messages for unimplemented insns. */
+ //Long delta_start = delta;
+
+ UChar *code = (UChar *) (guest_code + delta);
+
+ IRStmt *bstmt = NULL; /* Branch statement. */
+ IRExpr *next = NULL; /* Next bundle expr. */
+ ULong jumpkind = Ijk_Boring;
+ ULong steering_pc;
+
+ /* Set result defaults. */
+ dres.whatNext = Dis_Continue;
+ dres.len = 0;
+ dres.continueAt = 0;
+ dres.jk_StopHere = Ijk_INVALID;
+
+ /* Verify the code addr is 8-byte aligned. */
+ vassert((((ULong)code) & 7) == 0);
+
+ /* Get the instruction bundle. */
+ cins = *((ULong *)(Addr) code);
+
+ /* "Special" instructions. */
+ /* Spot the 16-byte preamble: ****tilegx****
+ 0:02b3c7ff91234fff { moveli zero, 4660 ; moveli zero, 22136 }
+ 8:0091a7ff95678fff { moveli zero, 22136 ; moveli zero, 4660 }
+ */
+#define CL_W0 0x02b3c7ff91234fffULL
+#define CL_W1 0x0091a7ff95678fffULL
+
+ if (*((ULong*)(Addr)(code)) == CL_W0 &&
+ *((ULong*)(Addr)(code + 8)) == CL_W1) {
+ /* Got a "Special" instruction preamble. Which one is it? */
+ if (*((ULong*)(Addr)(code + 16)) ==
+ 0x283a69a6d1483000ULL /* or r13, r13, r13 */ ) {
+ /* r0 = client_request ( r12 ) */
+ DIP("r0 = client_request ( r12 )\n");
+
+ putPC(mkU64(guest_PC_curr_instr + 24));
+
+ dres.jk_StopHere = Ijk_ClientReq;
+ dres.whatNext = Dis_StopHere;
+ dres.len = 24;
+ goto decode_success;
+
+ } else if (*((ULong*)(Addr)(code + 16)) ==
+ 0x283a71c751483000ULL /* or r14, r14, r14 */ ) {
+ /* r11 = guest_NRADDR */
+ DIP("r11 = guest_NRADDR\n");
+ dres.len = 24;
+ putIReg(11, IRExpr_Get(offsetof(VexGuestTILEGXState, guest_NRADDR),
+ Ity_I64));
+ putPC(mkU64(guest_PC_curr_instr + 8));
+ goto decode_success;
+
+ } else if (*((ULong*)(Addr)(code + 16)) ==
+ 0x283a79e7d1483000ULL /* or r15, r15, r15 */ ) {
+ /* branch-and-link-to-noredir r12 */
+ DIP("branch-and-link-to-noredir r12\n");
+ dres.len = 24;
+ putIReg(55, mkU64(guest_PC_curr_instr + 24));
+
+ putPC(getIReg(12));
+
+ dres.jk_StopHere = Ijk_NoRedir;
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+
+ } else if (*((ULong*)(Addr)(code + 16)) ==
+ 0x283a5965d1483000ULL /* or r11, r11, r11 */ ) {
+ /* vex-inject-ir */
+ DIP("vex-inject-ir\n");
+ dres.len = 24;
+
+ vex_inject_ir(irsb, Iend_LE);
+
+ stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_CMSTART),
+ mkU64(guest_PC_curr_instr)));
+ stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_CMLEN),
+ mkU64(24)));
+
+ /* 2 + 1 = 3 bundles. 24 bytes. */
+ putPC(mkU64(guest_PC_curr_instr + 24));
+
+ dres.jk_StopHere = Ijk_InvalICache;
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+
+ /* We don't expect this. */
+ vex_printf("%s: unexpect special bundles at %lx\n",
+ __func__, (Addr)guest_PC_curr_instr);
+ delta += 16;
+ goto decode_failure;
+ /*NOTREACHED*/
+ }
+
+ /* To decode the given instruction bundle. */
+ nr_insn = parse_insn_tilegx((tilegx_bundle_bits)cins,
+ (ULong)code,
+ decoded);
+
+ if (vex_traceflags & VEX_TRACE_FE)
+ decode_and_display(&cins, 1, (ULong)code);
+
+ /* Init. rb_wb_index */
+ rd_wb_index = 0;
+
+ steering_pc = -1ULL;
+
+ // Save the current stmts_used in case we need rollback.
+ stmts_used = irsb->stmts_used;
+
+ for (n = 0; n < nr_insn; n++) {
+ opcode = decoded[n].opcode->mnemonic;
+ Int opi;
+
+ rd = ra = rb = -1;
+ opd[0] = opd[1] = opd[2] = opd[3] = -1;
+ opd_dst_map = 0;
+ opd_src_map = 0;
+ opd_imm_map = 0;
+
+ for (opi = 0; opi < decoded[n].opcode->num_operands; opi++) {
+ const struct tilegx_operand *op = decoded[n].operands[opi];
+ opd[opi] = decoded[n].operand_values[opi];
+
+ /* Set the operands. rd, ra, rb and imm. */
+ if (opi < 3) {
+ if (op->is_dest_reg) {
+ if (rd == -1)
+ rd = decoded[n].operand_values[opi];
+ else if (ra == -1)
+ ra = decoded[n].operand_values[opi];
+ } else if (op->is_src_reg) {
+ if (ra == -1) {
+ ra = decoded[n].operand_values[opi];
+ } else if(rb == -1) {
+ rb = decoded[n].operand_values[opi];
+ } else {
+ vassert(0);
+ }
+ } else {
+ imm = decoded[n].operand_values[opi];
+ }
+ }
+
+ /* Build bit maps of used dest, source registers
+ and immediate. */
+ if (op->is_dest_reg) {
+ opd_dst_map |= 1ULL << opi;
+ if(op->is_src_reg)
+ opd_src_map |= 1ULL << opi;
+ } else if(op->is_src_reg) {
+ opd_src_map |= 1ULL << opi;
+ } else {
+ opd_imm_map |= 1ULL << opi;
+ }
+ }
+
+ use_dirty_helper = 0;
+
+ switch (opcode) {
+ case 0: /* "bpt" */ /* "raise" */
+ /* "bpt" pseudo instruction is an illegal instruction */
+ opd_imm_map |= (1 << 0);
+ opd[0] = cins;
+ use_dirty_helper = 1;
+ break;
+ case 1: /* "info" */ /* Ignore this instruction. */
+ break;
+ case 2: /* "infol" */ /* Ignore this instruction. */
+ break;
+ case 3: /* "ld4s_tls" */ /* Ignore this instruction. */
+ break;
+ case 4: /* "ld_tls" */ /* Ignore this instruction. */
+ break;
+ case 5: /* "move" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, getIReg(ra));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 6: /* "movei" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, mkU64(extend_s_8to64(imm)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 7: /* "moveli" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, mkU64(extend_s_16to64(imm)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 8: /* "prefetch" */ /* Ignore. */
+ break;
+ case 9: /* "prefetch_add_l1" */ /* Ignore. */
+ break;
+ case 10: /* "prefetch_add_l1_fault" */ /* Ignore. */
+ break;
+ case 11: /* "prefetch_add_l2" */ /* Ignore. */
+ break;
+ case 12: /* "prefetch_add_l2_fault" */ /* Ignore. */
+ break;
+ case 13: /* "prefetch_add_l3" */ /* Ignore. */
+ break;
+ case 14: /* "prefetch_add_l3_fault" */ /* Ignore. */
+ break;
+ case 15: /* "prefetch_l1" */ /* Ignore. */
+ break;
+ case 16: /* "prefetch_l1_fault" */ /* Ignore. */
+ break;
+ case 17: /* "prefetch_l2" */ /* Ignore. */
+ break;
+ case 18: /* "prefetch_l2_fault" */ /* Ignore. */
+ break;
+ case 19: /* "prefetch_l3" */ /* Ignore. */
+ break;
+ case 20: /* "prefetch_l3_fault" */ /* Ignore. */
+ break;
+ case 21: /* "raise" */
+ /* "raise" pseudo instruction is an illegal instruction plusing
+ a "moveli zero, <sig>", so we need save whole bundle in the
+ opd[0], which will be used in the dirty helper. */
+ opd_imm_map |= (1 << 0);
+ opd[0] = cins;
+ use_dirty_helper = 1;
+ break;
+ case 22: /* "add" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_Add64, getIReg(ra), getIReg(rb)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 23: /* "addi" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_Add64, getIReg(ra),
+ mkU64(extend_s_8to64(imm))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 24: /* "addli" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_Add64, getIReg(ra),
+ mkU64(extend_s_16to64(imm))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 25: /* "addx" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, signExtend(binop(Iop_Add32,
+ narrowTo(Ity_I32, getIReg(ra)),
+ narrowTo(Ity_I32, getIReg(rb))),
+ 32));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 26: /* "addxi" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, signExtend(binop(Iop_Add32,
+ narrowTo(Ity_I32, getIReg(ra)),
+ mkU32(imm)), 32));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 27: /* "addxli" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, signExtend(binop(Iop_Add32,
+ narrowTo(Ity_I32, getIReg(ra)),
+ mkU32(imm)), 32));
+
+ MARK_REG_WB(rd, t2);
+ break;
+ case 28: /* "addxsc" */
+ use_dirty_helper = 1;
+ break;
+ case 29: /* "and" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, getIReg(ra), getIReg(rb)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 30: /* "andi" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, getIReg(ra),
+ mkU64(extend_s_8to64(imm))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 31: /* "beqz" */
+ /* Fall-through */
+ case 32:
+ /* "beqzt" */
+ bstmt = dis_branch(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)),
+ imm);
+ break;
+ case 33: /* "bfexts" */
+ {
+ ULong imm0 = decoded[n].operand_values[3];
+ ULong mask = ((-1ULL) ^ ((-1ULL << ((imm0 - imm) & 63)) << 1));
+ t0 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t0, binop(Iop_Xor64,
+ binop(Iop_Sub64,
+ binop(Iop_And64,
+ binop(Iop_Shr64,
+ getIReg(ra),
+ mkU8(imm0)),
+ mkU64(1)),
+ mkU64(1)),
+ mkU64(-1ULL)));
+ assign(t2,
+ binop(Iop_Or64,
+ binop(Iop_And64,
+ binop(Iop_Or64,
+ binop(Iop_Shr64,
+ getIReg(ra),
+ mkU8(imm)),
+ binop(Iop_Shl64,
+ getIReg(ra),
+ mkU8(64 - imm))),
+ mkU64(mask)),
+ binop(Iop_And64,
+ mkexpr(t0),
+ mkU64(~mask))));
+
+ MARK_REG_WB(rd, t2);
+ }
+ break;
+ case 34: /* "bfextu" */
+ {
+ ULong imm0 = decoded[n].operand_values[3];
+ ULong mask = 0;
+ t2 = newTemp(Ity_I64);
+ mask = ((-1ULL) ^ ((-1ULL << ((imm0 - imm) & 63)) << 1));
+
+ assign(t2,
+ binop(Iop_And64,
+ binop(Iop_Or64,
+ binop(Iop_Shr64,
+ getIReg(ra),
+ mkU8(imm)),
+ binop(Iop_Shl64,
+ getIReg(ra),
+ mkU8(64 - imm))),
+ mkU64(mask)));
+ MARK_REG_WB(rd, t2);
+ }
+ break;
+ case 35: /* "bfins" */
+ {
+ ULong mask;
+ ULong imm0 = decoded[n].operand_values[3];
+ t0 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ if (imm <= imm0)
+ {
+ mask = ((-1ULL << imm) ^ ((-1ULL << imm0) << 1));
+ }
+ else
+ {
+ mask = ((-1ULL << imm) | (-1ULL >> (63 - imm0)));
+ }
+
+ assign(t0, binop(Iop_Or64,
+ binop(Iop_Shl64,
+ getIReg(ra),
+ mkU8(imm)),
+ binop(Iop_Shr64,
+ getIReg(ra),
+ mkU8(64 - imm))));
+
+ assign(t2, binop(Iop_Or64,
+ binop(Iop_And64,
+ mkexpr(t0),
+ mkU64(mask)),
+ binop(Iop_And64,
+ getIReg(rd),
+ mkU64(~mask))));
+
+ MARK_REG_WB(rd, t2);
+ }
+ break;
+ case 36: /* "bgez" */
+ /* Fall-through */
+ case 37: /* "bgezt" */
+ bstmt = dis_branch(binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ getIReg(ra),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x0)),
+ imm);
+ break;
+ case 38: /* "bgtz" */
+ /* Fall-through */
+ case 39:
+ /* "bgtzt" */
+ bstmt = dis_branch(unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ getIReg(ra),
+ mkU64(0))),
+ imm);
+ break;
+ case 40: /* "blbc" */
+ /* Fall-through */
+ case 41: /* "blbct" */
+ bstmt = dis_branch(unop(Iop_64to1,
+ unop(Iop_Not64, getIReg(ra))),
+ imm);
+
+ break;
+ case 42: /* "blbs" */
+ /* Fall-through */
+ case 43:
+ /* "blbst" */
+ bstmt = dis_branch(unop(Iop_64to1,
+ getIReg(ra)),
+ imm);
+ break;
+ case 44: /* "blez" */
+ bstmt = dis_branch(binop(Iop_CmpLE64S, getIReg(ra),
+ mkU64(0)),
+ imm);
+ break;
+ case 45: /* "blezt" */
+ bstmt = dis_branch(binop(Iop_CmpLE64S, getIReg(ra),
+ mkU64(0)),
+ imm);
+ break;
+ case 46: /* "bltz" */
+ bstmt = dis_branch(binop(Iop_CmpLT64S, getIReg(ra),
+ mkU64(0)),
+ imm);
+ break;
+ case 47: /* "bltzt" */
+ bstmt = dis_branch(binop(Iop_CmpLT64S, getIReg(ra),
+ mkU64(0)),
+ imm);
+ break;
+ case 48: /* "bnez" */
+ /* Fall-through */
+ case 49:
+ /* "bnezt" */
+ bstmt = dis_branch(binop(Iop_CmpNE64, getIReg(ra),
+ mkU64(0)),
+ imm);
+ break;
+ case 50: /* "clz" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_Clz64, getIReg(ra)));
+
+ MARK_REG_WB(rd, t2);
+ break;
+ case 51: /* "cmoveqz rd, ra, rb" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, IRExpr_ITE(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)),
+ getIReg(rb), getIReg(rd)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 52: /* "cmovnez" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, IRExpr_ITE(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)),
+ getIReg(rd), getIReg(rb)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 53: /* "cmpeq" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64, binop(Iop_CmpEQ64,
+ getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+ break;
+
+ case 54: /* "cmpeqi" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64, binop(Iop_CmpEQ64,
+ getIReg(ra),
+ mkU64(extend_s_8to64(imm)))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 55: /* "cmpexch" */
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+
+ assign(t1, getIReg(rb));
+ stmt( IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t2, Iend_LE,
+ getIReg(ra),
+ NULL, binop(Iop_Add64,
+ getIReg(70),
+ getIReg(71)),
+ NULL, mkexpr(t1))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 56: /* "cmpexch4" */
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I32);
+
+ assign(t1, narrowTo(Ity_I32, getIReg(rb)));
+ stmt( IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t3, Iend_LE,
+ getIReg(ra),
+ NULL,
+ narrowTo(Ity_I32, binop(Iop_Add64,
+ getIReg(70),
+ getIReg(71))),
+ NULL,
+ mkexpr(t1))));
+ assign(t2, unop(Iop_32Uto64, mkexpr(t3)));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 57: /* "cmples" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLE64S, getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 58: /* "cmpleu" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLE64U, getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 59: /* "cmplts" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLT64S, getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 60: /* "cmpltsi" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLT64S,
+ getIReg(ra),
+ mkU64(extend_s_8to64(imm)))));
+ MARK_REG_WB(rd, t2);
+ break;
+ case 61:
+
+ /* "cmpltu" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLT64U, getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+
+
+ break;
+ case 62: /* "cmpltui" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpLT64U,
+ getIReg(ra),
+ mkU64(imm))));
+ MARK_REG_WB(rd, t2);
+
+
+ break;
+ case 63: /* "cmpne" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpNE64, getIReg(ra), getIReg(rb))));
+ MARK_REG_WB(rd, t2);
+
+
+ break;
+ case 64:
+ /* Fall-through */
+ case 65:
+ /* Fall-through */
+ case 66:
+ /* Fall-through */
+ case 67:
+ /* Fall-through */
+ case 68:
+ /* Fall-through */
+ case 69:
+ /* Fall-through */
+ case 70:
+ /* Fall-through */
+ case 71:
+ /* Fall-through */
+ case 72:
+ use_dirty_helper = 1;
+ break;
+ case 73: /* "ctz" */
+ t2 = newTemp(Ity_I64);
+ assign(t2, unop(Iop_Ctz64, getIReg(ra)));
+
+ MARK_REG_WB(rd, t2);
+
+
+ break;
+ case 74: /* "dblalign" */
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+
+ /* t0 is the bit shift amount */
+ assign(t0, binop(Iop_Shl64,
+ binop(Iop_And64,
+ getIReg(rb),
+ mkU64(7)),
+ mkU8(3)));
+ assign(t1, binop(Iop_Sub64,
+ mkU64(64),
+ mkexpr(t0)));
+
+ assign(t2, binop(Iop_Or64,
+ binop(Iop_Shl64,
+ getIReg(ra),
+ unop(Iop_64to8, mkexpr(t1))),
+ binop(Iop_Shr64,
+ ...
[truncated message content] |