/* Support code for various pieces of CGEN simulators.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
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, or (at your option)
-any later version.
+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, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "bfd.h"
#include "sim-main.h"
#include "dis-asm.h"
-#include "cpu-opc.h"
#define MEMOPS_DEFINE_INLINE
#include "cgen-mem.h"
#define SEMOPS_DEFINE_INLINE
#include "cgen-ops.h"
+#undef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
const char *mode_names[] = {
- "VM",
+ "VOID",
"BI",
"QI",
"HI",
"SI",
"DI",
- "UBI",
"UQI",
"UHI",
"USI",
"DF",
"XF",
"TF",
+ 0, /* MODE_TARGET_MAX */
+ "INT",
+ "UINT",
+ "PTR"
+};
+
+/* Opcode table for virtual insns used by the simulator. */
+
+#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
+
+static const CGEN_IBASE virtual_insn_entries[] =
+{
+ {
+ VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } }
+ },
+ {
+ VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } }
+ },
+ {
+ VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } }
+ },
+ {
+ VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } }
+ },
+ {
+ VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } }
+ },
+ {
+ VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } }
+ }
+};
+
+#undef V
+
+const CGEN_INSN cgen_virtual_insn_table[] =
+{
+ { & virtual_insn_entries[0] },
+ { & virtual_insn_entries[1] },
+ { & virtual_insn_entries[2] },
+ { & virtual_insn_entries[3] },
+ { & virtual_insn_entries[4] },
+ { & virtual_insn_entries[5] }
};
/* Initialize cgen things.
cgen_init (SIM_DESC sd)
{
int i, c;
- int run_fast_p = 1;
/* If no profiling or tracing has been enabled, run in fast mode. */
- for (c = 0; c < MAX_NR_PROCESSORS; ++c)
- {
- sim_cpu *cpu = STATE_CPU (sd, c);
-
- for (i = 0; i < MAX_PROFILE_VALUES; ++i)
- if (CPU_PROFILE_FLAGS (cpu) [i])
- {
- run_fast_p = 0;
- break;
- }
- for (i = 0; i < MAX_TRACE_VALUES; ++i)
- if (CPU_TRACE_FLAGS (cpu) [i])
- {
- run_fast_p = 0;
- break;
- }
- if (! run_fast_p)
- break;
- }
- STATE_RUN_FAST_P (sd) = run_fast_p;
-}
-\f
-/* Disassembly support.
- ??? While executing an instruction, the insn has been decoded and all its
- fields have been extracted. It is certainly possible to do the disassembly
- with that data. This seems simpler, but maybe in the future the already
- extracted fields will be used. */
-
-/* Pseudo FILE object for strings. */
-typedef struct {
- char *buffer;
- char *current;
-} SFILE;
-
-/* sprintf to a "stream" */
-
-static int
-disasm_sprintf VPARAMS ((SFILE *f, const char *format, ...))
-{
-#ifndef __STDC__
- SFILE *f;
- const char *format;
-#endif
- int n;
- va_list args;
-
- VA_START (args, format);
-#ifndef __STDC__
- f = va_arg (args, SFILE *);
- format = va_arg (args, char *);
-#endif
- vsprintf (f->current, format, args);
- f->current += n = strlen (f->current);
- va_end (args);
- return n;
+ {
+ int run_fast_p = 1;
+
+ for (c = 0; c < MAX_NR_PROCESSORS; ++c)
+ {
+ SIM_CPU *cpu = STATE_CPU (sd, c);
+
+ for (i = 0; i < MAX_PROFILE_VALUES; ++i)
+ if (CPU_PROFILE_FLAGS (cpu) [i])
+ {
+ run_fast_p = 0;
+ break;
+ }
+ for (i = 0; i < MAX_TRACE_VALUES; ++i)
+ if (CPU_TRACE_FLAGS (cpu) [i])
+ {
+ run_fast_p = 0;
+ break;
+ }
+ if (! run_fast_p)
+ break;
+ }
+ STATE_RUN_FAST_P (sd) = run_fast_p;
+ }
}
-void
-sim_disassemble_insn (SIM_CPU *cpu, const struct cgen_insn *insn,
- const struct argbuf *abuf, PCADDR pc, char *buf)
-{
- unsigned int length;
- unsigned long insn_value;
- struct disassemble_info disasm_info;
- struct cgen_fields fields;
- SFILE sfile;
- union {
- unsigned8 bytes[16];
- unsigned16 shorts[8];
- unsigned32 words[4];
- } insn_buf;
- SIM_DESC sd = CPU_STATE (cpu);
+/* Return the name of insn number I. */
- sfile.buffer = sfile.current = buf;
- INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
- (fprintf_ftype) disasm_sprintf);
- disasm_info.endian =
- (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG
- : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE
- : BFD_ENDIAN_UNKNOWN);
+const char *
+cgen_insn_name (SIM_CPU *cpu, int i)
+{
+ return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
+}
- length = sim_core_read_buffer (sd, cpu, sim_core_read_map, &insn_buf, pc,
- CGEN_INSN_BITSIZE (insn) / 8);
+/* Return the maximum number of extra bytes required for a SIM_CPU struct. */
- switch (length)
- {
- case 1 : insn_value = insn_buf.bytes[0]; break;
- case 2 : insn_value = T2H_2 (insn_buf.shorts[0]); break;
- case 4 : insn_value = T2H_4 (insn_buf.words[0]); break;
- default: abort ();
- }
+int
+cgen_cpu_max_extra_bytes (void)
+{
+ int i;
+ int extra = 0;
- length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
- /* Result of extract fn is in bits. */
- /* ??? This assumes that each instruction has a fixed length (and thus
- for insns with multiple versions of variable lengths they would each
- have their own table entry). */
- if (length == CGEN_INSN_BITSIZE (insn))
+ for (i = 0; sim_machs[i] != 0; ++i)
{
- (*CGEN_PRINT_FN (insn)) (&disasm_info, insn, &fields, pc, length);
- }
- else
- {
- /* This shouldn't happen, but aborting is too drastic. */
- strcpy (buf, "***unknown***");
+ int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
+ if (size > extra)
+ extra = size;
}
+ return extra;
}
\f
#ifdef DI_FN_SUPPORT
}
#endif /* DI_FN_SUPPORT */
+\f
+QI
+RORQI (val, shift)
+ QI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 8 - shift;
+ int mask = (1 << shift) - 1;
+ QI result = (val & mask) << remain;
+ mask = (1 << remain) - 1;
+ result |= (val >> shift) & mask;
+ return result;
+ }
+ return val;
+}
+
+QI
+ROLQI (val, shift)
+ QI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 8 - shift;
+ int mask = (1 << remain) - 1;
+ QI result = (val & mask) << shift;
+ mask = (1 << shift) - 1;
+ result |= (val >> remain) & mask;
+ return result;
+ }
+ return val;
+}
+
+HI
+RORHI (val, shift)
+ HI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 16 - shift;
+ int mask = (1 << shift) - 1;
+ HI result = (val & mask) << remain;
+ mask = (1 << remain) - 1;
+ result |= (val >> shift) & mask;
+ return result;
+ }
+ return val;
+}
+
+HI
+ROLHI (val, shift)
+ HI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 16 - shift;
+ int mask = (1 << remain) - 1;
+ HI result = (val & mask) << shift;
+ mask = (1 << shift) - 1;
+ result |= (val >> remain) & mask;
+ return result;
+ }
+ return val;
+}
+
+SI
+RORSI (val, shift)
+ SI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 32 - shift;
+ int mask = (1 << shift) - 1;
+ SI result = (val & mask) << remain;
+ mask = (1 << remain) - 1;
+ result |= (val >> shift) & mask;
+ return result;
+ }
+ return val;
+}
+
+SI
+ROLSI (val, shift)
+ SI val;
+ int shift;
+{
+ if (shift != 0)
+ {
+ int remain = 32 - shift;
+ int mask = (1 << remain) - 1;
+ SI result = (val & mask) << shift;
+ mask = (1 << shift) - 1;
+ result |= (val >> remain) & mask;
+ return result;
+ }
+
+ return val;
+}
+
+/* Emit an error message from CGEN RTL. */
+
+void
+cgen_rtx_error (SIM_CPU *cpu, const char * msg)
+{
+ SIM_DESC sd = CPU_STATE (cpu);
+
+ sim_io_printf (sd, msg);
+ sim_io_printf (sd, "\n");
+
+ sim_engine_halt (sd, cpu, NULL, CIA_GET (cpu), sim_stopped, SIM_SIGTRAP);
+}