Add support for instruction level tracing to the ARM simulator.

* wrapper.c (op_print): New function.
	(sim_dis_read): New function.
	(print_insn): New function - disassembles the given instruction.
	(sim_trace): Note that tracing is now allowed.
	(sim_create_inferior): Default to emulating v6.
	Initialise the disassembler machinery.
	(sim_target_parse_command_line): Add support for -t -d and -z
	options.
	(sim_target_display_usage): Note existence of -d and -z options.
	(sim_open): Parse -t -d and -z options.
	* armemu.h: Add exports of trace, disas and trace_funcs.
	Add prototype for print_insn.
	* armemu.c (ARMul_Emulate26): Add tracing code.
	Delete unused variables.
	* thumbemu (handle_v6_thumb_insn): Delete unused variable Rd.
	Move Rm variable into switch cases.
	Add tracing code.

	* armcopro.c (XScale_cp15_init): Add a return value.
	(XScale_cp13_init): Likewise.
	(XScale_cp14_init): Likewise.
	(XScale_cp15_LDC): Delete unused function.
	(XScale_cp15_STC): Likewise.
	* maverick.c: Delete comment inside comment.
	(DSPInit): Delete unused function.
	(DSPMCR4): Fix compile time warning about missing parenthesis.
	(DSPMCR5): Likewise.
	(DSPCDP6): Delete unused variable opcode2.
This commit is contained in:
Nick Clifton 2014-03-14 15:21:23 +00:00
parent b9366cf395
commit 8d05292667
7 changed files with 245 additions and 94 deletions

View File

@ -1,3 +1,34 @@
2014-03-14 Nick Clifton <nickc@redhat.com>
* wrapper.c (op_print): New function.
(sim_dis_read): New function.
(print_insn): New function - disassembles the given instruction.
(sim_trace): Note that tracing is now allowed.
(sim_create_inferior): Default to emulating v6.
Initialise the disassembler machinery.
(sim_target_parse_command_line): Add support for -t -d and -z
options.
(sim_target_display_usage): Note existence of -d and -z options.
(sim_open): Parse -t -d and -z options.
* armemu.h: Add exports of trace, disas and trace_funcs.
Add prototype for print_insn.
* armemu.c (ARMul_Emulate26): Add tracing code.
Delete unused variables.
* thumbemu (handle_v6_thumb_insn): Delete unused variable Rd.
Move Rm variable into switch cases.
Add tracing code.
* armcopro.c (XScale_cp15_init): Add a return value.
(XScale_cp13_init): Likewise.
(XScale_cp14_init): Likewise.
(XScale_cp15_LDC): Delete unused function.
(XScale_cp15_STC): Likewise.
* maverick.c: Delete comment inside comment.
(DSPInit): Delete unused function.
(DSPMCR4): Fix compile time warning about missing parenthesis.
(DSPMCR5): Likewise.
(DSPCDP6): Delete unused variable opcode2.
2014-03-14 David McQuillan <dmcq@tao-group.com>
PR sim/8388

View File

@ -85,6 +85,8 @@ XScale_cp15_init (ARMul_State * state ATTRIBUTE_UNUSED)
/* Initialise the ARM Control Register. */
XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
return TRUE;
}
/* Check an access to a register. */
@ -370,34 +372,6 @@ read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm)
return 0;
}
static unsigned
XScale_cp15_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
{
unsigned reg = BITS (12, 15);
unsigned result;
result = check_cp15_access (state, reg, 0, 0, 0);
if (result == ARMul_DONE && type == ARMul_DATA)
write_cp15_reg (state, reg, 0, 0, data);
return result;
}
static unsigned
XScale_cp15_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
{
unsigned reg = BITS (12, 15);
unsigned result;
result = check_cp15_access (state, reg, 0, 0, 0);
if (result == ARMul_DONE && type == ARMul_DATA)
* data = read_cp15_reg (reg, 0, 0);
return result;
}
static unsigned
XScale_cp15_MRC (ARMul_State * state,
unsigned type ATTRIBUTE_UNUSED,
@ -582,6 +556,8 @@ XScale_cp13_init (ARMul_State * state ATTRIBUTE_UNUSED)
XScale_cp13_CR0_Regs[i] = 0;
XScale_cp13_CR1_Regs[i] = 0;
}
return TRUE;
}
/* Check an access to a register. */
@ -812,6 +788,8 @@ XScale_cp14_init (ARMul_State * state ATTRIBUTE_UNUSED)
for (i = 16; i--;)
XScale_cp14_Regs[i] = 0;
return TRUE;
}
/* Check an access to a register. */

View File

@ -1,7 +1,7 @@
/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
Modifications to add arch. v4 support by <jsmith@cygnus.com>.
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 3 of the License, or
@ -314,7 +314,7 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
{
ARMword Rm;
int ror = -1;
switch (BITS (4, 11))
{
case 0x07: ror = 0; break;
@ -580,11 +580,20 @@ ARMul_Emulate26 (ARMul_State * state)
if (state->EventSet)
ARMul_EnvokeEvent (state);
#if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */
fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
if (instr == 0)
abort ();
#endif
if (! TFLAG && trace)
{
fprintf (stderr, "pc: %x, ", pc & ~1);
if (! disas)
fprintf (stderr, "instr: %x\n", instr);
}
if (instr == 0 || pc < 0x10)
{
ARMul_Abort (state, ARMUndefinedInstrV);
state->Emulate = FALSE;
}
#if 0 /* Enable this code to help track down stack alignment bugs. */
{
static ARMword old_sp = -1;
@ -628,8 +637,8 @@ ARMul_Emulate26 (ARMul_State * state)
}
if (state->Debug)
{
fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
state->Mode);
fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n",
(long) pc, (long) instr, (long) state->Mode);
(void) fgetc (stdin);
}
}
@ -667,6 +676,14 @@ ARMul_Emulate26 (ARMul_State * state)
case t_decoded:
/* ARM instruction available. */
if (disas || trace)
{
fprintf (stderr, " emulate as: ");
if (trace)
fprintf (stderr, "%08x ", new);
if (! disas)
fprintf (stderr, "\n");
}
instr = new;
/* So continue instruction decoding. */
break;
@ -675,6 +692,8 @@ ARMul_Emulate26 (ARMul_State * state)
}
}
#endif
if (disas)
print_insn (instr);
/* Check the condition codes. */
if ((temp = TOPBITS (28)) == AL)
@ -1654,7 +1673,6 @@ check_PMUintr:
{
if (BITS (4, 7) == 0x7)
{
ARMword value;
extern int SWI_vector_installed;
/* Hardware is allowed to optionally override this
@ -1736,7 +1754,6 @@ check_PMUintr:
ARMdword op1 = state->Reg[BITS (0, 3)];
ARMdword op2 = state->Reg[BITS (8, 11)];
ARMdword dest;
ARMdword result;
if (BIT (5))
op1 >>= 16;
@ -1877,7 +1894,6 @@ check_PMUintr:
/* ElSegundo SMULxy insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (8, 11)];
ARMword Rn = state->Reg[BITS (12, 15)];
if (BIT (5))
op1 >>= 16;
@ -3459,7 +3475,6 @@ check_PMUintr:
FLUSHPIPE;
break;
/* Branch and Link forward. */
case 0xb0:
case 0xb1:
@ -3477,9 +3492,10 @@ check_PMUintr:
#endif
state->Reg[15] = pc + 8 + POSBRANCH;
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
break;
/* Branch and Link backward. */
case 0xb8:
case 0xb9:
@ -3497,9 +3513,10 @@ check_PMUintr:
#endif
state->Reg[15] = pc + 8 + NEGBRANCH;
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
break;
/* Co-Processor Data Transfers. */
case 0xc4:
if (state->is_v5)
@ -4150,6 +4167,8 @@ WriteR15 (ARMul_State * state, ARMword src)
#endif
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
}
/* This routine handles writes to register 15 when the S bit is set. */
@ -4187,6 +4206,8 @@ WriteSR15 (ARMul_State * state, ARMword src)
ARMul_R15Altered (state);
#endif
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
}
/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
@ -4208,6 +4229,8 @@ WriteR15Branch (ARMul_State * state, ARMword src)
state->Reg[15] = src & 0xfffffffc;
}
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
#else
WriteR15 (state, src);
#endif

View File

@ -15,6 +15,10 @@
along with this program; if not, see <http://www.gnu.org/licenses/>. */
extern ARMword isize;
extern int trace;
extern int disas;
extern int trace_funcs;
extern void print_insn (ARMword);
/* Condition code values. */
#define EQ 0
@ -46,6 +50,10 @@ extern ARMword isize;
#define CBIT (1L << 29)
#define VBIT (1L << 28)
#define SBIT (1L << 27)
#define GE0 (1L << 16)
#define GE1 (1L << 17)
#define GE2 (1L << 18)
#define GE3 (1L << 19)
#define IBIT (1L << 7)
#define FBIT (1L << 6)
#define IFBITS (3L << 6)

View File

@ -20,7 +20,7 @@
#include "ansidecl.h"
#include "armemu.h"
/*#define CIRRUS_DEBUG 1 /**/
/*#define CIRRUS_DEBUG 1 */
#if CIRRUS_DEBUG
# define printfdbg printf
#else
@ -97,13 +97,6 @@ cirrus_not_implemented (char * insn)
exit (1);
}
static unsigned
DSPInit (ARMul_State * state)
{
ARMul_ConsolePrint (state, ", DSP present");
return TRUE;
}
unsigned
DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
unsigned type ATTRIBUTE_UNUSED,
@ -270,8 +263,9 @@ DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
res);
/* carry */
c = (NEG (a) && POS (b) ||
(NEG (a) && POS (res)) || (POS (b) && POS (res)));
c = (NEG (a) && POS (b))
|| (NEG (a) && POS (res))
|| (POS (b) && POS (res));
*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
break;
@ -301,8 +295,9 @@ DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
v = ((NEG64 (a) && POS64 (b) && POS64 (res))
|| (POS64 (a) && NEG64 (b) && NEG64 (res)));
/* carry */
c = (NEG64 (a) && POS64 (b) ||
(NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
c = (NEG64 (a) && POS64 (b))
|| (NEG64 (a) && POS64 (res))
|| (POS64 (b) && POS64 (res));
*value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
break;
@ -1167,10 +1162,6 @@ DSPCDP6 (ARMul_State * state,
unsigned type,
ARMword instr)
{
int opcode2;
opcode2 = BITS (5,7);
switch (BITS (20,21))
{
case 0:

View File

@ -5,12 +5,12 @@
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 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/>. */
@ -38,9 +38,6 @@ handle_v6_thumb_insn (ARMul_State * state,
ARMword tinstr,
tdstate * pvalid)
{
ARMword Rd;
ARMword Rm;
if (! state->is_v6)
{
* pvalid = t_undefined;
@ -56,33 +53,48 @@ handle_v6_thumb_insn (ARMul_State * state,
case 0xba40: /* rev16 */
case 0xbac0: /* revsh */
case 0xb650: /* setend */
default:
default:
printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
* pvalid = t_undefined;
return;
case 0xb200: /* sxth */
Rm = state->Reg [(tinstr & 0x38) >> 3];
if (Rm & 0x8000)
state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
else
state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
break;
{
ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
if (Rm & 0x8000)
state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
else
state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
break;
}
case 0xb240: /* sxtb */
Rm = state->Reg [(tinstr & 0x38) >> 3];
if (Rm & 0x80)
state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
else
state->Reg [(tinstr & 0x7)] = Rm & 0xff;
break;
{
ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
if (Rm & 0x80)
state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
else
state->Reg [(tinstr & 0x7)] = Rm & 0xff;
break;
}
case 0xb280: /* uxth */
Rm = state->Reg [(tinstr & 0x38) >> 3];
state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
break;
{
ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
break;
}
case 0xb2c0: /* uxtb */
Rm = state->Reg [(tinstr & 0x38) >> 3];
state->Reg [(tinstr & 0x7)] = Rm & 0xff;
break;
{
ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
state->Reg [(tinstr & 0x7)] = Rm & 0xff;
break;
}
}
/* Indicate that the instruction has been processed. */
* pvalid = t_branch;
@ -113,6 +125,9 @@ ARMul_ThumbDecode (ARMul_State * state,
tinstr &= 0xFFFF;
}
if (trace)
fprintf (stderr, "pc: %x, Thumb instr: %x", pc & ~1, tinstr);
#if 1 /* debugging to catch non updates */
*ainstr = 0xDEADC0DE;
#endif
@ -413,7 +428,7 @@ ARMul_ThumbDecode (ARMul_State * state,
case 0x0e00:
if (state->is_v5)
{
/* This is normally an undefined instruction. The v5t architecture
/* This is normally an undefined instruction. The v5t architecture
defines this particular pattern as a BKPT instruction, for
hardware assisted debugging. We map onto the arm BKPT
instruction. */
@ -550,6 +565,8 @@ ARMul_ThumbDecode (ARMul_State * state,
state->Reg[14] = (tmp | 1);
valid = t_branch;
FLUSHPIPE;
if (trace_funcs)
fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
break;
}
}
@ -610,5 +627,8 @@ ARMul_ThumbDecode (ARMul_State * state,
break;
}
if (trace && valid != t_decoded)
fprintf (stderr, "\n");
return valid;
}

View File

@ -37,6 +37,7 @@
#include "gdb/sim-arm.h"
#include "gdb/signals.h"
#include "libiberty.h"
#include "iwmmxt.h"
host_callback *sim_callback;
@ -59,6 +60,54 @@ static int big_endian;
int stop_simulator;
#include "dis-asm.h"
int trace = 0;
int disas = 0;
int trace_funcs = 0;
static struct disassemble_info info;
static char opbuf[1000];
static int
op_printf (char *buf, char *fmt, ...)
{
int ret;
va_list ap;
va_start (ap, fmt);
ret = vsprintf (opbuf + strlen (opbuf), fmt, ap);
va_end (ap);
return ret;
}
static int
sim_dis_read (bfd_vma memaddr ATTRIBUTE_UNUSED,
bfd_byte * ptr,
unsigned int length,
struct disassemble_info * info)
{
ARMword val = (ARMword) *((ARMword *) info->application_data);
while (length--)
{
* ptr ++ = val & 0xFF;
val >>= 8;
}
return 0;
}
void
print_insn (ARMword instr)
{
int size;
opbuf[0] = 0;
info.application_data = & instr;
size = print_insn_little_arm (0, & info);
fprintf (stderr, " %*s\n", size, opbuf);
}
/* Cirrus DSP registers.
We need to define these registers outside of maverick.c because
@ -192,10 +241,9 @@ sim_read (sd, addr, buffer, size)
int
sim_trace (sd)
SIM_DESC sd ATTRIBUTE_UNUSED;
{
(*sim_callback->printf_filtered)
(sim_callback,
"This simulator does not support tracing\n");
{
trace = 1;
sim_resume (sd, 0, 0);
return 1;
}
@ -269,9 +317,9 @@ sim_create_inferior (sd, abfd, argv, env)
/* We wouldn't set the machine type with earlier toolchains, so we
explicitly select a processor capable of supporting all ARMs in
32bit mode. */
/* We choose the XScale rather than the iWMMXt, because the iWMMXt
removes the FPE emulator, since it conflicts with its coprocessors.
For the most generic ARM support, we want the FPE emulator in place. */
ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop);
break;
case bfd_mach_arm_XScale:
ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_v6_Prop);
break;
@ -351,6 +399,16 @@ sim_create_inferior (sd, abfd, argv, env)
ARMul_SetCPSR (state, SVC32MODE);
}
memset (& info, 0, sizeof (info));
INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
info.read_memory_func = sim_dis_read;
info.arch = bfd_get_arch (abfd);
info.mach = bfd_get_mach (abfd);
info.endian_code = BFD_ENDIAN_LITTLE;
if (info.mach == 0)
info.arch = bfd_arch_arm;
disassemble_init_for_target (& info);
if (argv != NULL)
{
/* Set up the command line by laboriously stringing together
@ -676,8 +734,6 @@ sim_fetch_register (sd, rn, memory, length)
return length;
}
#ifdef SIM_TARGET_SWITCHES
static void sim_target_parse_arg_array (char **);
typedef struct
@ -718,6 +774,34 @@ sim_target_parse_command_line (argc, argv)
if ((ptr == NULL) || (* ptr != '-'))
break;
if (strcmp (ptr, "-t") == 0)
{
trace = 1;
continue;
}
if (strcmp (ptr, "-z") == 0)
{
/* Remove this option from the argv array. */
for (arg = i; arg < argc; arg ++)
argv[arg] = argv[arg + 1];
argc --;
i --;
trace_funcs = 1;
continue;
}
if (strcmp (ptr, "-d") == 0)
{
/* Remove this option from the argv array. */
for (arg = i; arg < argc; arg ++)
argv[arg] = argv[arg + 1];
argc --;
i --;
disas = 1;
continue;
}
if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
continue;
@ -789,8 +873,9 @@ sim_target_display_usage (help)
fprintf (stream, "%s=<list> Comma seperated list of SWI protocols to supoport.\n\
This list can contain: NONE, DEMON, ANGEL, REDBOOT and/or ALL.\n",
SWI_SWITCH);
fprintf (stream, "-d\t\tEnable disassembly of instructions during tracing.\n");
fprintf (stream, "-z\t\tTrace entering and leaving functions.\n\n");
}
#endif
SIM_DESC
sim_open (kind, ptr, abfd, argv)
@ -853,6 +938,21 @@ sim_open (kind, ptr, abfd, argv)
break;
}
}
else if (argv[i][0] == '-' && argv[i][1] == 't')
{
trace = 1;
break;
}
else if (argv[i][0] == '-' && argv[i][1] == 'z')
{
trace_funcs = 1;
break;
}
else if (argv[i][0] == '-' && argv[i][1] == 'd')
{
disas = 1;
break;
}
else if (argv[i][0] == '-' && argv[i][1] == 'm')
{
if (argv[i][2] != '\0')