OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/tags/gdb/gdb-6.8/gdb-6.8.openrisc-2.1/sim/d10v
    from Rev 24 to Rev 33
    Reverse comparison

Rev 24 → Rev 33

/endian.c
0,0 → 1,137
/* If we're being compiled as a .c file, rather than being included in
d10v_sim.h, then ENDIAN_INLINE won't be defined yet. */
 
#ifndef ENDIAN_INLINE
#define NO_ENDIAN_INLINE
#include "d10v_sim.h"
#define ENDIAN_INLINE
#endif
 
ENDIAN_INLINE uint16
get_word (x)
uint8 *x;
{
#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__)
 
unsigned short word = *(unsigned short *)x;
__asm__ ("xchgb %b0,%h0" : "=q" (word) : "0" (word));
return word;
 
#elif defined(WORDS_BIGENDIAN)
/* It is safe to do this on big endian hosts, since the d10v requires that words be
aligned on 16-bit boundaries. */
return *(uint16 *)x;
 
#else
return ((uint16)x[0]<<8) + x[1];
#endif
}
 
ENDIAN_INLINE uint32
get_longword (x)
uint8 *x;
{
#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP)
 
unsigned int long_word = *(unsigned *)x;
__asm__ ("bswap %0" : "=r" (long_word) : "0" (long_word));
return long_word;
 
#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__)
 
unsigned int long_word = *(unsigned *)x;
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (long_word)
: "0" (long_word));
 
return long_word;
 
#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__))
/* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */
return *(uint32 *)x;
 
#elif defined(WORDS_BIGENDIAN)
/* long words must be aligned on at least 16-bit boundaries, so this should be safe. */
return (((uint32) *(uint16 *)x)<<16) | ((uint32) *(uint16 *)(x+2));
 
#else
return ((uint32)x[0]<<24) + ((uint32)x[1]<<16) + ((uint32)x[2]<<8) + ((uint32)x[3]);
#endif
}
 
ENDIAN_INLINE int64
get_longlong (x)
uint8 *x;
{
uint32 top = get_longword (x);
uint32 bottom = get_longword (x+4);
return (((int64)top)<<32) | (int64)bottom;
}
 
ENDIAN_INLINE void
write_word (addr, data)
uint8 *addr;
uint16 data;
{
#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__)
 
__asm__ ("xchgb %b0,%h0" : "=q" (data) : "0" (data));
*(uint16 *)addr = data;
 
#elif defined(WORDS_BIGENDIAN)
/* It is safe to do this on big endian hosts, since the d10v requires that words be
aligned on 16-bit boundaries. */
*(uint16 *)addr = data;
 
#else
addr[0] = (data >> 8) & 0xff;
addr[1] = data & 0xff;
#endif
}
 
ENDIAN_INLINE void
write_longword (addr, data)
uint8 *addr;
uint32 data;
{
#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP)
 
__asm__ ("bswap %0" : "=r" (data) : "0" (data));
*(uint32 *)addr = data;
 
#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__)
 
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (data)
: "0" (data));
 
*(uint32 *)addr = data;
 
#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__))
/* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */
*(uint32 *)addr = data;
 
#elif defined(WORDS_BIGENDIAN)
*(uint16 *)addr = (uint16)(data >> 16);
*(uint16 *)(addr + 2) = (uint16)data;
 
#else
addr[0] = (data >> 24) & 0xff;
addr[1] = (data >> 16) & 0xff;
addr[2] = (data >> 8) & 0xff;
addr[3] = data & 0xff;
#endif
}
 
ENDIAN_INLINE void
write_longlong (addr, data)
uint8 *addr;
int64 data;
{
write_longword (addr, (uint32)(data >> 32));
write_longword (addr+4, (uint32)data);
}
endian.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: interp.c =================================================================== --- interp.c (nonexistent) +++ interp.c (revision 33) @@ -0,0 +1,1499 @@ +#include +#include "sysdep.h" +#include "bfd.h" +#include "gdb/callback.h" +#include "gdb/remote-sim.h" + +#include "d10v_sim.h" +#include "gdb/sim-d10v.h" +#include "gdb/signals.h" + +enum _leftright { LEFT_FIRST, RIGHT_FIRST }; + +static char *myname; +static SIM_OPEN_KIND sim_kind; +int d10v_debug; + +/* Set this to true to get the previous segment layout. */ + +int old_segment_mapping; + +host_callback *d10v_callback; +unsigned long ins_type_counters[ (int)INS_MAX ]; + +uint16 OP[4]; + +static int init_text_p = 0; +/* non-zero if we opened prog_bfd */ +static int prog_bfd_was_opened_p; +bfd *prog_bfd; +asection *text; +bfd_vma text_start; +bfd_vma text_end; + +static long hash PARAMS ((long insn, int format)); +static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); +static void get_operands PARAMS ((struct simops *s, uint32 ins)); +static void do_long PARAMS ((uint32 ins)); +static void do_2_short PARAMS ((uint16 ins1, uint16 ins2, enum _leftright leftright)); +static void do_parallel PARAMS ((uint16 ins1, uint16 ins2)); +static char *add_commas PARAMS ((char *buf, int sizeof_buf, unsigned long value)); +extern void sim_set_profile PARAMS ((int n)); +extern void sim_set_profile_size PARAMS ((int n)); +static INLINE uint8 *map_memory (unsigned phys_addr); + +#ifdef NEED_UI_LOOP_HOOK +/* How often to run the ui_loop update, when in use */ +#define UI_LOOP_POLL_INTERVAL 0x14000 + +/* Counter for the ui_loop_hook update */ +static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; + +/* Actual hook to call to run through gdb's gui event loop */ +extern int (*deprecated_ui_loop_hook) PARAMS ((int signo)); +#endif /* NEED_UI_LOOP_HOOK */ + +#ifndef INLINE +#if defined(__GNUC__) && defined(__OPTIMIZE__) +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +#define MAX_HASH 63 +struct hash_entry +{ + struct hash_entry *next; + uint32 opcode; + uint32 mask; + int size; + struct simops *ops; +}; + +struct hash_entry hash_table[MAX_HASH+1]; + +INLINE static long +hash(insn, format) + long insn; + int format; +{ + if (format & LONG_OPCODE) + return ((insn & 0x3F000000) >> 24); + else + return((insn & 0x7E00) >> 9); +} + +INLINE static struct hash_entry * +lookup_hash (ins, size) + uint32 ins; + int size; +{ + struct hash_entry *h; + + if (size) + h = &hash_table[(ins & 0x3F000000) >> 24]; + else + h = &hash_table[(ins & 0x7E00) >> 9]; + + while ((ins & h->mask) != h->opcode || h->size != size) + { + if (h->next == NULL) + { + State.exception = SIGILL; + State.pc_changed = 1; /* Don't increment the PC. */ + return NULL; + } + h = h->next; + } + return (h); +} + +INLINE static void +get_operands (struct simops *s, uint32 ins) +{ + int i, shift, bits, flags; + uint32 mask; + for (i=0; i < s->numops; i++) + { + shift = s->operands[3*i]; + bits = s->operands[3*i+1]; + flags = s->operands[3*i+2]; + mask = 0x7FFFFFFF >> (31 - bits); + OP[i] = (ins >> shift) & mask; + } + /* FIXME: for tracing, update values that need to be updated each + instruction decode cycle */ + State.trace.psw = PSW; +} + +bfd_vma +decode_pc () +{ + asection *s; + if (!init_text_p && prog_bfd != NULL) + { + init_text_p = 1; + for (s = prog_bfd->sections; s; s = s->next) + if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) + { + text = s; + text_start = bfd_get_section_vma (prog_bfd, s); + text_end = text_start + bfd_section_size (prog_bfd, s); + break; + } + } + + return (PC << 2) + text_start; +} + +static void +do_long (ins) + uint32 ins; +{ + struct hash_entry *h; +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins); +#endif + h = lookup_hash (ins, 1); + if (h == NULL) + return; + get_operands (h->ops, ins); + State.ins_type = INS_LONG; + ins_type_counters[ (int)State.ins_type ]++; + (h->ops->func)(); +} + +static void +do_2_short (ins1, ins2, leftright) + uint16 ins1, ins2; + enum _leftright leftright; +{ + struct hash_entry *h; + enum _ins_type first, second; + +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n", + ins1, (leftright) ? "left" : "right", ins2); +#endif + + if (leftright == LEFT_FIRST) + { + first = INS_LEFT; + second = INS_RIGHT; + ins_type_counters[ (int)INS_LEFTRIGHT ]++; + } + else + { + first = INS_RIGHT; + second = INS_LEFT; + ins_type_counters[ (int)INS_RIGHTLEFT ]++; + } + + /* Issue the first instruction */ + h = lookup_hash (ins1, 0); + if (h == NULL) + return; + get_operands (h->ops, ins1); + State.ins_type = first; + ins_type_counters[ (int)State.ins_type ]++; + (h->ops->func)(); + + /* Issue the second instruction (if the PC hasn't changed) */ + if (!State.pc_changed && !State.exception) + { + /* finish any existing instructions */ + SLOT_FLUSH (); + h = lookup_hash (ins2, 0); + if (h == NULL) + return; + get_operands (h->ops, ins2); + State.ins_type = second; + ins_type_counters[ (int)State.ins_type ]++; + ins_type_counters[ (int)INS_CYCLES ]++; + (h->ops->func)(); + } + else if (!State.exception) + ins_type_counters[ (int)INS_COND_JUMP ]++; +} + +static void +do_parallel (ins1, ins2) + uint16 ins1, ins2; +{ + struct hash_entry *h1, *h2; +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2); +#endif + ins_type_counters[ (int)INS_PARALLEL ]++; + h1 = lookup_hash (ins1, 0); + if (h1 == NULL) + return; + h2 = lookup_hash (ins2, 0); + if (h2 == NULL) + return; + + if (h1->ops->exec_type == PARONLY) + { + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_COND_TEST; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + if (State.exe) + { + ins_type_counters[ (int)INS_COND_TRUE ]++; + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; + } + else if (h2->ops->exec_type == PARONLY) + { + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_COND_TEST; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + if (State.exe) + { + ins_type_counters[ (int)INS_COND_TRUE ]++; + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; + } + else + { + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_PARALLEL; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + if (!State.exception) + { + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_PARALLEL; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + } + } +} + +static char * +add_commas(buf, sizeof_buf, value) + char *buf; + int sizeof_buf; + unsigned long value; +{ + int comma = 3; + char *endbuf = buf + sizeof_buf - 1; + + *--endbuf = '\0'; + do { + if (comma-- == 0) + { + *--endbuf = ','; + comma = 2; + } + + *--endbuf = (value % 10) + '0'; + } while ((value /= 10) != 0); + + return endbuf; +} + +void +sim_size (power) + int power; + +{ + int i; + for (i = 0; i < IMEM_SEGMENTS; i++) + { + if (State.mem.insn[i]) + free (State.mem.insn[i]); + } + for (i = 0; i < DMEM_SEGMENTS; i++) + { + if (State.mem.data[i]) + free (State.mem.data[i]); + } + for (i = 0; i < UMEM_SEGMENTS; i++) + { + if (State.mem.unif[i]) + free (State.mem.unif[i]); + } + /* Always allocate dmem segment 0. This contains the IMAP and DMAP + registers. */ + State.mem.data[0] = calloc (1, SEGMENT_SIZE); +} + +/* For tracing - leave info on last access around. */ +static char *last_segname = "invalid"; +static char *last_from = "invalid"; +static char *last_to = "invalid"; + +enum + { + IMAP0_OFFSET = 0xff00, + DMAP0_OFFSET = 0xff08, + DMAP2_SHADDOW = 0xff04, + DMAP2_OFFSET = 0xff0c + }; + +static void +set_dmap_register (int reg_nr, unsigned long value) +{ + uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + + DMAP0_OFFSET + 2 * reg_nr); + WRITE_16 (raw, value); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, "mem: dmap%d=0x%04lx\n", reg_nr, value); + } +#endif +} + +static unsigned long +dmap_register (void *regcache, int reg_nr) +{ + uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + + DMAP0_OFFSET + 2 * reg_nr); + return READ_16 (raw); +} + +static void +set_imap_register (int reg_nr, unsigned long value) +{ + uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + + IMAP0_OFFSET + 2 * reg_nr); + WRITE_16 (raw, value); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, "mem: imap%d=0x%04lx\n", reg_nr, value); + } +#endif +} + +static unsigned long +imap_register (void *regcache, int reg_nr) +{ + uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + + IMAP0_OFFSET + 2 * reg_nr); + return READ_16 (raw); +} + +enum + { + HELD_SPI_IDX = 0, + HELD_SPU_IDX = 1 + }; + +static unsigned long +spu_register (void) +{ + if (PSW_SM) + return GPR (SP_IDX); + else + return HELD_SP (HELD_SPU_IDX); +} + +static unsigned long +spi_register (void) +{ + if (!PSW_SM) + return GPR (SP_IDX); + else + return HELD_SP (HELD_SPI_IDX); +} + +static void +set_spi_register (unsigned long value) +{ + if (!PSW_SM) + SET_GPR (SP_IDX, value); + SET_HELD_SP (HELD_SPI_IDX, value); +} + +static void +set_spu_register (unsigned long value) +{ + if (PSW_SM) + SET_GPR (SP_IDX, value); + SET_HELD_SP (HELD_SPU_IDX, value); +} + +/* Given a virtual address in the DMAP address space, translate it + into a physical address. */ + +unsigned long +sim_d10v_translate_dmap_addr (unsigned long offset, + int nr_bytes, + unsigned long *phys, + void *regcache, + unsigned long (*dmap_register) (void *regcache, + int reg_nr)) +{ + short map; + int regno; + last_from = "logical-data"; + if (offset >= DMAP_BLOCK_SIZE * SIM_D10V_NR_DMAP_REGS) + { + /* Logical address out side of data segments, not supported */ + return 0; + } + regno = (offset / DMAP_BLOCK_SIZE); + offset = (offset % DMAP_BLOCK_SIZE); + if ((offset % DMAP_BLOCK_SIZE) + nr_bytes > DMAP_BLOCK_SIZE) + { + /* Don't cross a BLOCK boundary */ + nr_bytes = DMAP_BLOCK_SIZE - (offset % DMAP_BLOCK_SIZE); + } + map = dmap_register (regcache, regno); + if (regno == 3) + { + /* Always maps to data memory */ + int iospi = (offset / 0x1000) % 4; + int iosp = (map >> (4 * (3 - iospi))) % 0x10; + last_to = "io-space"; + *phys = (SIM_D10V_MEMORY_DATA + (iosp * 0x10000) + 0xc000 + offset); + } + else + { + int sp = ((map & 0x3000) >> 12); + int segno = (map & 0x3ff); + switch (sp) + { + case 0: /* 00: Unified memory */ + *phys = SIM_D10V_MEMORY_UNIFIED + (segno * DMAP_BLOCK_SIZE) + offset; + last_to = "unified"; + break; + case 1: /* 01: Instruction Memory */ + *phys = SIM_D10V_MEMORY_INSN + (segno * DMAP_BLOCK_SIZE) + offset; + last_to = "chip-insn"; + break; + case 2: /* 10: Internal data memory */ + *phys = SIM_D10V_MEMORY_DATA + (segno << 16) + (regno * DMAP_BLOCK_SIZE) + offset; + last_to = "chip-data"; + break; + case 3: /* 11: Reserved */ + return 0; + } + } + return nr_bytes; +} + +/* Given a virtual address in the IMAP address space, translate it + into a physical address. */ + +unsigned long +sim_d10v_translate_imap_addr (unsigned long offset, + int nr_bytes, + unsigned long *phys, + void *regcache, + unsigned long (*imap_register) (void *regcache, + int reg_nr)) +{ + short map; + int regno; + int sp; + int segno; + last_from = "logical-insn"; + if (offset >= (IMAP_BLOCK_SIZE * SIM_D10V_NR_IMAP_REGS)) + { + /* Logical address outside of IMAP segments, not supported */ + return 0; + } + regno = (offset / IMAP_BLOCK_SIZE); + offset = (offset % IMAP_BLOCK_SIZE); + if (offset + nr_bytes > IMAP_BLOCK_SIZE) + { + /* Don't cross a BLOCK boundary */ + nr_bytes = IMAP_BLOCK_SIZE - offset; + } + map = imap_register (regcache, regno); + sp = (map & 0x3000) >> 12; + segno = (map & 0x007f); + switch (sp) + { + case 0: /* 00: unified memory */ + *phys = SIM_D10V_MEMORY_UNIFIED + (segno << 17) + offset; + last_to = "unified"; + break; + case 1: /* 01: instruction memory */ + *phys = SIM_D10V_MEMORY_INSN + (IMAP_BLOCK_SIZE * regno) + offset; + last_to = "chip-insn"; + break; + case 2: /*10*/ + /* Reserved. */ + return 0; + case 3: /* 11: for testing - instruction memory */ + offset = (offset % 0x800); + *phys = SIM_D10V_MEMORY_INSN + offset; + if (offset + nr_bytes > 0x800) + /* don't cross VM boundary */ + nr_bytes = 0x800 - offset; + last_to = "test-insn"; + break; + } + return nr_bytes; +} + +unsigned long +sim_d10v_translate_addr (unsigned long memaddr, + int nr_bytes, + unsigned long *targ_addr, + void *regcache, + unsigned long (*dmap_register) (void *regcache, + int reg_nr), + unsigned long (*imap_register) (void *regcache, + int reg_nr)) +{ + unsigned long phys; + unsigned long seg; + unsigned long off; + + last_from = "unknown"; + last_to = "unknown"; + + seg = (memaddr >> 24); + off = (memaddr & 0xffffffL); + + /* However, if we've asked to use the previous generation of segment + mapping, rearrange the segments as follows. */ + + if (old_segment_mapping) + { + switch (seg) + { + case 0x00: /* DMAP translated memory */ + seg = 0x10; + break; + case 0x01: /* IMAP translated memory */ + seg = 0x11; + break; + case 0x10: /* On-chip data memory */ + seg = 0x02; + break; + case 0x11: /* On-chip insn memory */ + seg = 0x01; + break; + case 0x12: /* Unified memory */ + seg = 0x00; + break; + } + } + + switch (seg) + { + case 0x00: /* Physical unified memory */ + last_from = "phys-unified"; + last_to = "unified"; + phys = SIM_D10V_MEMORY_UNIFIED + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x01: /* Physical instruction memory */ + last_from = "phys-insn"; + last_to = "chip-insn"; + phys = SIM_D10V_MEMORY_INSN + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x02: /* Physical data memory segment */ + last_from = "phys-data"; + last_to = "chip-data"; + phys = SIM_D10V_MEMORY_DATA + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x10: /* in logical data address segment */ + nr_bytes = sim_d10v_translate_dmap_addr (off, nr_bytes, &phys, regcache, + dmap_register); + break; + + case 0x11: /* in logical instruction address segment */ + nr_bytes = sim_d10v_translate_imap_addr (off, nr_bytes, &phys, regcache, + imap_register); + break; + + default: + return 0; + } + + *targ_addr = phys; + return nr_bytes; +} + +/* Return a pointer into the raw buffer designated by phys_addr. It + is assumed that the client has already ensured that the access + isn't going to cross a segment boundary. */ + +uint8 * +map_memory (unsigned phys_addr) +{ + uint8 **memory; + uint8 *raw; + unsigned offset; + int segment = ((phys_addr >> 24) & 0xff); + + switch (segment) + { + + case 0x00: /* Unified memory */ + { + memory = &State.mem.unif[(phys_addr / SEGMENT_SIZE) % UMEM_SEGMENTS]; + last_segname = "umem"; + break; + } + + case 0x01: /* On-chip insn memory */ + { + memory = &State.mem.insn[(phys_addr / SEGMENT_SIZE) % IMEM_SEGMENTS]; + last_segname = "imem"; + break; + } + + case 0x02: /* On-chip data memory */ + { + if ((phys_addr & 0xff00) == 0xff00) + { + phys_addr = (phys_addr & 0xffff); + if (phys_addr == DMAP2_SHADDOW) + { + phys_addr = DMAP2_OFFSET; + last_segname = "dmap"; + } + else + last_segname = "reg"; + } + else + last_segname = "dmem"; + memory = &State.mem.data[(phys_addr / SEGMENT_SIZE) % DMEM_SEGMENTS]; + break; + } + + default: + /* OOPS! */ + last_segname = "scrap"; + return State.mem.fault; + } + + if (*memory == NULL) + { + *memory = calloc (1, SEGMENT_SIZE); + if (*memory == NULL) + { + (*d10v_callback->printf_filtered) (d10v_callback, "Malloc failed.\n"); + return State.mem.fault; + } + } + + offset = (phys_addr % SEGMENT_SIZE); + raw = *memory + offset; + return raw; +} + +/* Transfer data to/from simulated memory. Since a bug in either the + simulated program or in gdb or the simulator itself may cause a + bogus address to be passed in, we need to do some sanity checking + on addresses to make sure they are within bounds. When an address + fails the bounds check, treat it as a zero length read/write rather + than aborting the entire run. */ + +static int +xfer_mem (SIM_ADDR virt, + unsigned char *buffer, + int size, + int write_p) +{ + uint8 *memory; + unsigned long phys; + int phys_size; + phys_size = sim_d10v_translate_addr (virt, size, &phys, NULL, + dmap_register, imap_register); + if (phys_size == 0) + return 0; + + memory = map_memory (phys); + +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "sim_%s %d bytes: 0x%08lx (%s) -> 0x%08lx (%s) -> 0x%08lx (%s)\n", + (write_p ? "write" : "read"), + phys_size, virt, last_from, + phys, last_to, + (long) memory, last_segname); + } +#endif + + if (write_p) + { + memcpy (memory, buffer, phys_size); + } + else + { + memcpy (buffer, memory, phys_size); + } + + return phys_size; +} + + +int +sim_write (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem( addr, buffer, size, 1); +} + +int +sim_read (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem( addr, buffer, size, 0); +} + + +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *callback; + struct bfd *abfd; + char **argv; +{ + struct simops *s; + struct hash_entry *h; + static int init_p = 0; + char **p; + + sim_kind = kind; + d10v_callback = callback; + myname = argv[0]; + old_segment_mapping = 0; + + /* NOTE: This argument parsing is only effective when this function + is called by GDB. Standalone argument parsing is handled by + sim/common/run.c. */ + for (p = argv + 1; *p; ++p) + { + if (strcmp (*p, "-oldseg") == 0) + old_segment_mapping = 1; +#ifdef DEBUG + else if (strcmp (*p, "-t") == 0) + d10v_debug = DEBUG; + else if (strncmp (*p, "-t", 2) == 0) + d10v_debug = atoi (*p + 2); +#endif + else + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",*p); + } + + /* put all the opcodes in the hash table */ + if (!init_p++) + { + for (s = Simops; s->func; s++) + { + h = &hash_table[hash(s->opcode,s->format)]; + + /* go to the last entry in the chain */ + while (h->next) + h = h->next; + + if (h->ops) + { + h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry)); + if (!h->next) + perror ("malloc failure"); + + h = h->next; + } + h->ops = s; + h->mask = s->mask; + h->opcode = s->opcode; + h->size = s->is_long; + } + } + + /* reset the processor state */ + if (!State.mem.data[0]) + sim_size (1); + sim_create_inferior ((SIM_DESC) 1, NULL, NULL, NULL); + + /* Fudge our descriptor. */ + return (SIM_DESC) 1; +} + + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ + if (prog_bfd != NULL && prog_bfd_was_opened_p) + { + bfd_close (prog_bfd); + prog_bfd = NULL; + prog_bfd_was_opened_p = 0; + } +} + +void +sim_set_profile (n) + int n; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n); +} + +void +sim_set_profile_size (n) + int n; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n); +} + +uint8 * +dmem_addr (uint16 offset) +{ + unsigned long phys; + uint8 *mem; + int phys_size; + + /* Note: DMEM address range is 0..0x10000. Calling code can compute + things like ``0xfffe + 0x0e60 == 0x10e5d''. Since offset's type + is uint16 this is modulo'ed onto 0x0e5d. */ + + phys_size = sim_d10v_translate_dmap_addr (offset, 1, &phys, NULL, + dmap_register); + if (phys_size == 0) + { + mem = State.mem.fault; + } + else + mem = map_memory (phys); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n", + offset, last_from, + phys, phys_size, last_to, + (long) mem, last_segname); + } +#endif + return mem; +} + +uint8 * +imem_addr (uint32 offset) +{ + unsigned long phys; + uint8 *mem; + int phys_size = sim_d10v_translate_imap_addr (offset, 1, &phys, NULL, + imap_register); + if (phys_size == 0) + { + return State.mem.fault; + } + mem = map_memory (phys); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n", + offset, last_from, + phys, phys_size, last_to, + (long) mem, last_segname); + } +#endif + return mem; +} + +static int stop_simulator = 0; + +int +sim_stop (sd) + SIM_DESC sd; +{ + stop_simulator = 1; + return 1; +} + + +/* Run (or resume) the program. */ +void +sim_resume (sd, step, siggnal) + SIM_DESC sd; + int step, siggnal; +{ + uint32 inst; + uint8 *iaddr; + +/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */ + State.exception = 0; + if (step) + sim_stop (sd); + + switch (siggnal) + { + case 0: + break; +#ifdef SIGBUS + case SIGBUS: +#endif + case SIGSEGV: + SET_BPC (PC); + SET_BPSW (PSW); + SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (AE_VECTOR_START); + SLOT_FLUSH (); + break; + case SIGILL: + SET_BPC (PC); + SET_BPSW (PSW); + SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (RIE_VECTOR_START); + SLOT_FLUSH (); + break; + default: + /* just ignore it */ + break; + } + + do + { + iaddr = imem_addr ((uint32)PC << 2); + if (iaddr == State.mem.fault) + { + State.exception = SIGBUS; + break; + } + + inst = get_longword( iaddr ); + + State.pc_changed = 0; + ins_type_counters[ (int)INS_CYCLES ]++; + + switch (inst & 0xC0000000) + { + case 0xC0000000: + /* long instruction */ + do_long (inst & 0x3FFFFFFF); + break; + case 0x80000000: + /* R -> L */ + do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST); + break; + case 0x40000000: + /* L -> R */ + do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST); + break; + case 0: + do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); + break; + } + + /* If the PC of the current instruction matches RPT_E then + schedule a branch to the loop start. If one of those + instructions happens to be a branch, than that instruction + will be ignored */ + if (!State.pc_changed) + { + if (PSW_RP && PC == RPT_E) + { + /* Note: The behavour of a branch instruction at RPT_E + is implementation dependant, this simulator takes the + branch. Branching to RPT_E is valid, the instruction + must be executed before the loop is taken. */ + if (RPT_C == 1) + { + SET_PSW_RP (0); + SET_RPT_C (0); + SET_PC (PC + 1); + } + else + { + SET_RPT_C (RPT_C - 1); + SET_PC (RPT_S); + } + } + else + SET_PC (PC + 1); + } + + /* Check for a breakpoint trap on this instruction. This + overrides any pending branches or loops */ + if (PSW_DB && PC == IBA) + { + SET_BPC (PC); + SET_BPSW (PSW); + SET_PSW (PSW & PSW_SM_BIT); + SET_PC (SDBT_VECTOR_START); + } + + /* Writeback all the DATA / PC changes */ + SLOT_FLUSH (); + +#ifdef NEED_UI_LOOP_HOOK + if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0) + { + ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; + deprecated_ui_loop_hook (0); + } +#endif /* NEED_UI_LOOP_HOOK */ + } + while ( !State.exception && !stop_simulator); + + if (step && !State.exception) + State.exception = SIGTRAP; +} + +void +sim_set_trace (void) +{ +#ifdef DEBUG + d10v_debug = DEBUG; +#endif +} + +void +sim_info (sd, verbose) + SIM_DESC sd; + int verbose; +{ + char buf1[40]; + char buf2[40]; + char buf3[40]; + char buf4[40]; + char buf5[40]; + unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ]; + unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ]; + unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ]; + unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ]; + unsigned long left_total = left + left_parallel + left_cond + left_nops; + + unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ]; + unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ]; + unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ]; + unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ]; + unsigned long right_total = right + right_parallel + right_cond + right_nops; + + unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ]; + unsigned long ins_long = ins_type_counters[ (int)INS_LONG ]; + unsigned long parallel = ins_type_counters[ (int)INS_PARALLEL ]; + unsigned long leftright = ins_type_counters[ (int)INS_LEFTRIGHT ]; + unsigned long rightleft = ins_type_counters[ (int)INS_RIGHTLEFT ]; + unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ]; + unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ]; + unsigned long cond_jump = ins_type_counters[ (int)INS_COND_JUMP ]; + unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ]; + unsigned long total = (unknown + left_total + right_total + ins_long); + + int size = strlen (add_commas (buf1, sizeof (buf1), total)); + int parallel_size = strlen (add_commas (buf1, sizeof (buf1), + (left_parallel > right_parallel) ? left_parallel : right_parallel)); + int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond)); + int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops)); + int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s left instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), left_total), + normal_size, add_commas (buf2, sizeof (buf2), left), + parallel_size, add_commas (buf3, sizeof (buf3), left_parallel), + cond_size, add_commas (buf4, sizeof (buf4), left_cond), + nop_size, add_commas (buf5, sizeof (buf5), left_nops)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s right instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), right_total), + normal_size, add_commas (buf2, sizeof (buf2), right), + parallel_size, add_commas (buf3, sizeof (buf3), right_parallel), + cond_size, add_commas (buf4, sizeof (buf4), right_cond), + nop_size, add_commas (buf5, sizeof (buf5), right_nops)); + + if (ins_long) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s long instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), ins_long)); + + if (parallel) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s parallel instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), parallel)); + + if (leftright) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) encoded L->R\n", + size, add_commas (buf1, sizeof (buf1), leftright)); + + if (rightleft) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) encoded R->L\n", + size, add_commas (buf1, sizeof (buf1), rightleft)); + + if (unknown) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s unknown instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), unknown)); + + if (cond_true) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) due to EXExxx condition being true\n", + size, add_commas (buf1, sizeof (buf1), cond_true)); + + if (cond_false) + (*d10v_callback->printf_filtered) (d10v_callback, + "skipped %*s instruction(s) due to EXExxx condition being false\n", + size, add_commas (buf1, sizeof (buf1), cond_false)); + + if (cond_jump) + (*d10v_callback->printf_filtered) (d10v_callback, + "skipped %*s instruction(s) due to conditional branch succeeding\n", + size, add_commas (buf1, sizeof (buf1), cond_jump)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s cycle(s)\n", + size, add_commas (buf1, sizeof (buf1), cycles)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s total instructions\n", + size, add_commas (buf1, sizeof (buf1), total)); +} + +SIM_RC +sim_create_inferior (sd, abfd, argv, env) + SIM_DESC sd; + struct bfd *abfd; + char **argv; + char **env; +{ + bfd_vma start_address; + + /* reset all state information */ + memset (&State.regs, 0, (int)&State.mem - (int)&State.regs); + + /* There was a hack here to copy the values of argc and argv into r0 + and r1. The values were also saved into some high memory that + won't be overwritten by the stack (0x7C00). The reason for doing + this was to allow the 'run' program to accept arguments. Without + the hack, this is not possible anymore. If the simulator is run + from the debugger, arguments cannot be passed in, so this makes + no difference. */ + + /* set PC */ + if (abfd != NULL) + start_address = bfd_get_start_address (abfd); + else + start_address = 0xffc0 << 2; +#ifdef DEBUG + if (d10v_debug) + (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%lx\n", (long) start_address); +#endif + SET_CREG (PC_CR, start_address >> 2); + + /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board + initializes imap0 and imap1 to 0x1000 as part of its ROM + initialization. */ + if (old_segment_mapping) + { + /* External memory startup. This is the HARD reset state. */ + set_imap_register (0, 0x0000); + set_imap_register (1, 0x007f); + set_dmap_register (0, 0x2000); + set_dmap_register (1, 0x2000); + set_dmap_register (2, 0x0000); /* Old DMAP */ + set_dmap_register (3, 0x0000); + } + else + { + /* Internal memory startup. This is the ROM intialized state. */ + set_imap_register (0, 0x1000); + set_imap_register (1, 0x1000); + set_dmap_register (0, 0x2000); + set_dmap_register (1, 0x2000); + set_dmap_register (2, 0x2000); /* DMAP2 initial internal value is + 0x2000 on the new board. */ + set_dmap_register (3, 0x0000); + } + + SLOT_FLUSH (); + return SIM_RC_OK; +} + + +void +sim_set_callbacks (p) + host_callback *p; +{ + d10v_callback = p; +} + +void +sim_stop_reason (sd, reason, sigrc) + SIM_DESC sd; + enum sim_stop *reason; + int *sigrc; +{ +/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */ + + switch (State.exception) + { + case SIG_D10V_STOP: /* stop instruction */ + *reason = sim_exited; + *sigrc = 0; + break; + + case SIG_D10V_EXIT: /* exit trap */ + *reason = sim_exited; + *sigrc = GPR (0); + break; + + case SIG_D10V_BUS: + *reason = sim_stopped; + *sigrc = TARGET_SIGNAL_BUS; + break; + + default: /* some signal */ + *reason = sim_stopped; + if (stop_simulator && !State.exception) + *sigrc = TARGET_SIGNAL_INT; + else + *sigrc = State.exception; + break; + } + + stop_simulator = 0; +} + +int +sim_fetch_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + int size; + switch ((enum sim_d10v_regs) rn) + { + case SIM_D10V_R0_REGNUM: + case SIM_D10V_R1_REGNUM: + case SIM_D10V_R2_REGNUM: + case SIM_D10V_R3_REGNUM: + case SIM_D10V_R4_REGNUM: + case SIM_D10V_R5_REGNUM: + case SIM_D10V_R6_REGNUM: + case SIM_D10V_R7_REGNUM: + case SIM_D10V_R8_REGNUM: + case SIM_D10V_R9_REGNUM: + case SIM_D10V_R10_REGNUM: + case SIM_D10V_R11_REGNUM: + case SIM_D10V_R12_REGNUM: + case SIM_D10V_R13_REGNUM: + case SIM_D10V_R14_REGNUM: + case SIM_D10V_R15_REGNUM: + WRITE_16 (memory, GPR (rn - SIM_D10V_R0_REGNUM)); + size = 2; + break; + case SIM_D10V_CR0_REGNUM: + case SIM_D10V_CR1_REGNUM: + case SIM_D10V_CR2_REGNUM: + case SIM_D10V_CR3_REGNUM: + case SIM_D10V_CR4_REGNUM: + case SIM_D10V_CR5_REGNUM: + case SIM_D10V_CR6_REGNUM: + case SIM_D10V_CR7_REGNUM: + case SIM_D10V_CR8_REGNUM: + case SIM_D10V_CR9_REGNUM: + case SIM_D10V_CR10_REGNUM: + case SIM_D10V_CR11_REGNUM: + case SIM_D10V_CR12_REGNUM: + case SIM_D10V_CR13_REGNUM: + case SIM_D10V_CR14_REGNUM: + case SIM_D10V_CR15_REGNUM: + WRITE_16 (memory, CREG (rn - SIM_D10V_CR0_REGNUM)); + size = 2; + break; + case SIM_D10V_A0_REGNUM: + case SIM_D10V_A1_REGNUM: + WRITE_64 (memory, ACC (rn - SIM_D10V_A0_REGNUM)); + size = 8; + break; + case SIM_D10V_SPI_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + WRITE_16 (memory, spi_register ()); + size = 2; + break; + case SIM_D10V_SPU_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + WRITE_16 (memory, spu_register ()); + size = 2; + break; + case SIM_D10V_IMAP0_REGNUM: + case SIM_D10V_IMAP1_REGNUM: + WRITE_16 (memory, imap_register (NULL, rn - SIM_D10V_IMAP0_REGNUM)); + size = 2; + break; + case SIM_D10V_DMAP0_REGNUM: + case SIM_D10V_DMAP1_REGNUM: + case SIM_D10V_DMAP2_REGNUM: + case SIM_D10V_DMAP3_REGNUM: + WRITE_16 (memory, dmap_register (NULL, rn - SIM_D10V_DMAP0_REGNUM)); + size = 2; + break; + case SIM_D10V_TS2_DMAP_REGNUM: + size = 0; + break; + default: + size = 0; + break; + } + return size; +} + +int +sim_store_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + int size; + switch ((enum sim_d10v_regs) rn) + { + case SIM_D10V_R0_REGNUM: + case SIM_D10V_R1_REGNUM: + case SIM_D10V_R2_REGNUM: + case SIM_D10V_R3_REGNUM: + case SIM_D10V_R4_REGNUM: + case SIM_D10V_R5_REGNUM: + case SIM_D10V_R6_REGNUM: + case SIM_D10V_R7_REGNUM: + case SIM_D10V_R8_REGNUM: + case SIM_D10V_R9_REGNUM: + case SIM_D10V_R10_REGNUM: + case SIM_D10V_R11_REGNUM: + case SIM_D10V_R12_REGNUM: + case SIM_D10V_R13_REGNUM: + case SIM_D10V_R14_REGNUM: + case SIM_D10V_R15_REGNUM: + SET_GPR (rn - SIM_D10V_R0_REGNUM, READ_16 (memory)); + size = 2; + break; + case SIM_D10V_CR0_REGNUM: + case SIM_D10V_CR1_REGNUM: + case SIM_D10V_CR2_REGNUM: + case SIM_D10V_CR3_REGNUM: + case SIM_D10V_CR4_REGNUM: + case SIM_D10V_CR5_REGNUM: + case SIM_D10V_CR6_REGNUM: + case SIM_D10V_CR7_REGNUM: + case SIM_D10V_CR8_REGNUM: + case SIM_D10V_CR9_REGNUM: + case SIM_D10V_CR10_REGNUM: + case SIM_D10V_CR11_REGNUM: + case SIM_D10V_CR12_REGNUM: + case SIM_D10V_CR13_REGNUM: + case SIM_D10V_CR14_REGNUM: + case SIM_D10V_CR15_REGNUM: + SET_CREG (rn - SIM_D10V_CR0_REGNUM, READ_16 (memory)); + size = 2; + break; + case SIM_D10V_A0_REGNUM: + case SIM_D10V_A1_REGNUM: + SET_ACC (rn - SIM_D10V_A0_REGNUM, READ_64 (memory) & MASK40); + size = 8; + break; + case SIM_D10V_SPI_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + set_spi_register (READ_16 (memory)); + size = 2; + break; + case SIM_D10V_SPU_REGNUM: + set_spu_register (READ_16 (memory)); + size = 2; + break; + case SIM_D10V_IMAP0_REGNUM: + case SIM_D10V_IMAP1_REGNUM: + set_imap_register (rn - SIM_D10V_IMAP0_REGNUM, READ_16(memory)); + size = 2; + break; + case SIM_D10V_DMAP0_REGNUM: + case SIM_D10V_DMAP1_REGNUM: + case SIM_D10V_DMAP2_REGNUM: + case SIM_D10V_DMAP3_REGNUM: + set_dmap_register (rn - SIM_D10V_DMAP0_REGNUM, READ_16(memory)); + size = 2; + break; + case SIM_D10V_TS2_DMAP_REGNUM: + size = 0; + break; + default: + size = 0; + break; + } + SLOT_FLUSH (); + return size; +} + + +void +sim_do_command (sd, cmd) + SIM_DESC sd; + char *cmd; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd); +} + +SIM_RC +sim_load (sd, prog, abfd, from_tty) + SIM_DESC sd; + char *prog; + bfd *abfd; + int from_tty; +{ + extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ + + if (prog_bfd != NULL && prog_bfd_was_opened_p) + { + bfd_close (prog_bfd); + prog_bfd_was_opened_p = 0; + } + prog_bfd = sim_load_file (sd, myname, d10v_callback, prog, abfd, + sim_kind == SIM_OPEN_DEBUG, + 1/*LMA*/, sim_write); + if (prog_bfd == NULL) + return SIM_RC_FAIL; + prog_bfd_was_opened_p = abfd == NULL; + return SIM_RC_OK; +}
interp.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: configure.ac =================================================================== --- configure.ac (nonexistent) +++ configure.ac (revision 33) @@ -0,0 +1,17 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59)dnl +AC_INIT(Makefile.in) +AC_CONFIG_HEADER(config.h:config.in) + +sinclude(../common/aclocal.m4) + +# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around +# it by inlining the macro's contents. +sinclude(../common/common.m4) + +SIM_AC_OPTION_WARNINGS + +AC_CHECK_HEADERS(unistd.h) + + +SIM_AC_OUTPUT
configure.ac Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: gencode.c =================================================================== --- gencode.c (nonexistent) +++ gencode.c (revision 33) @@ -0,0 +1,155 @@ +#include "config.h" +#include +#include +#include +#include "ansidecl.h" +#include "opcode/d10v.h" + +static void write_header PARAMS ((void)); +static void write_opcodes PARAMS ((void)); +static void write_template PARAMS ((void)); + +int +main (argc, argv) + int argc; + char *argv[]; +{ + if ((argc > 1) && (strcmp (argv[1],"-h") == 0)) + write_header(); + else if ((argc > 1) && (strcmp (argv[1],"-t") == 0)) + write_template (); + else + write_opcodes(); + return 0; +} + + +static void +write_header () +{ + struct d10v_opcode *opcode; + + for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++) + if (opcode->format != OPCODE_FAKE) + printf("void OP_%X PARAMS ((void));\t\t/* %s */\n",opcode->opcode, opcode->name); +} + + +/* write_template creates a file all required functions, ready */ +/* to be filled out */ + +static void +write_template () +{ + struct d10v_opcode *opcode; + int i,j; + + printf ("#include \"d10v_sim.h\"\n"); + printf ("#include \"simops.h\"\n"); + + for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++) + { + if (opcode->format != OPCODE_FAKE) + { + printf("/* %s */\nvoid\nOP_%X ()\n{\n",opcode->name,opcode->opcode); + + /* count operands */ + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM) || (flags & OPERAND_ADDR)) + j++; + } + switch (j) + { + case 0: + printf ("printf(\" %s\\n\");\n",opcode->name); + break; + case 1: + printf ("printf(\" %s\\t%%x\\n\",OP[0]);\n",opcode->name); + break; + case 2: + printf ("printf(\" %s\\t%%x,%%x\\n\",OP[0],OP[1]);\n",opcode->name); + break; + case 3: + printf ("printf(\" %s\\t%%x,%%x,%%x\\n\",OP[0],OP[1],OP[2]);\n",opcode->name); + break; + default: + fprintf (stderr,"Too many operands: %d\n",j); + } + printf ("}\n\n"); + } + } +} + + +long Opcodes[512]; +static int curop=0; + +check_opcodes( long op) +{ + int i; + + for (i=0;iname; opcode++) + { + if (opcode->format != OPCODE_FAKE) + { + printf (" { %ld,%d,%ld,%d,%d,%d,%d,OP_%X,", opcode->opcode, + (opcode->format & LONG_OPCODE) ? 1 : 0, opcode->mask, opcode->format, + opcode->cycles, opcode->unit, opcode->exec_type, opcode->opcode); + + /* REMOVE ME */ + check_opcodes (opcode->opcode); + Opcodes[curop++] = opcode->opcode; + + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM) || (flags & OPERAND_ADDR)) + j++; + } + printf ("%d,",j); + + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + int shift = d10v_operands[opcode->operands[i]].shift; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM)|| (flags & OPERAND_ADDR)) + { + if (j == 0) + printf ("{"); + else + printf (", "); + if ((flags & OPERAND_REG) && (opcode->format == LONG_L)) + shift += 15; + printf ("%d,%d,%d",shift,d10v_operands[opcode->operands[i]].bits,flags); + j = 1; + } + } + if (j) + printf ("}"); + printf ("},\n"); + } + } + printf ("{ 0,0,0,0,0,0,0,(void (*)(void))0,0,{0,0,0}},\n};\n"); +}
gencode.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: ChangeLog =================================================================== --- ChangeLog (nonexistent) +++ ChangeLog (revision 33) @@ -0,0 +1,1333 @@ +2006-12-21 Hans-Peter Nilsson + + * acconfig.h: Remove. + * config.in: Regenerate. + +2006-06-13 Richard Earnshaw + + * configure: Regenerated. + +2006-06-05 Daniel Jacobowitz + + * configure: Regenerated. + +2006-05-31 Daniel Jacobowitz + + * configure: Regenerated. + +2006-04-18 Nick Clifton + + * interp.c (sim_stop_reason): Fix typo. + +2005-11-28 Mark Mitchell + + * interp.c (gdb/signals.h): Include it. + (sim_stop_reason): Use TARGET_SIGNAL_*. + +2005-03-23 Mark Kettenis + + * configure: Regenerate. + +2005-01-14 Andrew Cagney + + * configure.ac: Sinclude aclocal.m4 before common.m4. Add + explicit call to AC_CONFIG_HEADER. + * configure: Regenerate. + +2005-01-12 Andrew Cagney + + * configure.ac: Update to use ../common/common.m4. + * configure: Re-generate. + +2005-01-11 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +2005-01-07 Andrew Cagney + + * configure.ac: Rename configure.in, require autoconf 2.59. + * configure: Re-generate. + +2004-12-08 Hans-Peter Nilsson + + * configure: Regenerate for ../common/aclocal.m4 update. + +2004-06-28 Andrew Cagney + + * interp.c (sim_resume): Rename ui_loop_hook to + deprecated_ui_loop_hook. + +2003-10-30 Andrew Cagney + + * simops.c: Replace "struct symbol_cache_entry" with "struct + bfd_symbol". + +2003-06-22 Andrew Cagney + + * interp.c (xfer_mem): Simplify. Only do a single partial + transfer. Problem reported by Tom Rix. + +2003-05-07 Andrew Cagney + + * interp.c (sim_d10v_translate_addr): Add "regcache" parameter. + (sim_d10v_translate_imap_addr): Ditto. + (sim_d10v_translate_dmap_addr): Ditto. + (xfer_mem): Pass NULL regcache to sim_d10v_translate_addr. + (dmem_addr): Pass NULL regcache to sim_d10v_translate_dmap_addr. + (dmap_register, imap_register): Add "regcache" parameter. + (imem_addr): Pass NULL regcache to sim_d10v_translate_imap_addr. + (sim_fetch_register): Pass NULL regcache to imap_register and + dmap_register. + +2003-02-27 Andrew Cagney + + * interp.c (sim_open, sim_create_inferior): Rename _bfd to bfd. + +2002-11-13 Andrew Cagney + + * simops.c: Include . + +2002-06-17 Andrew Cagney + + * d10v_sim.h (SET_PSW_BIT): Add cast to avoid inverting an enum. + +2002-06-16 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +2002-06-13 Tom Rix + + * interp.c (xfer_mem): Fix transfers across multiple segments. + +2002-06-09 Andrew Cagney + + * Makefile.in (INCLUDE): Update path to callback.h. + * gencode.c: Do not include "callback.h". + * d10v_sim.h: Include "gdb/callback.h" and "gdb/remote-sim.h". + * interp.c: Ditto. + +2002-06-08 Andrew Cagney + + * interp.c (sim_fetch_register): Fix name of enum used in cast. + (sim_store_register): Ditto. + +2002-06-02 Elena Zannoni + + From Jason Eckhardt + * d10v_sim.h (INC_ADDR): Correctly handle the case where MOD_E is + less than MOD_S (post-decrement). + +2002-06-01 Andrew Cagney + + * interp.c (sim_fetch_register, sim_store_register): Use a switch + statement and enums from "sim-d10v.h". + +2002-05-28 Elena Zannoni + + * interp.c (sim_create_inferior): Add comment. + + From Alan Matsuoka : + From 2001-04-27 Jason Eckhardt : + * simops.c (OP_4400): Output "mvf0f" instead of "mf0f". + (OP_4401): Output "mvf0t" instead of "mf0t". + (OP_460B): Do not output a flag register. + (OP_4609): Do not output a flag register. + +2002-05-23 Andrew Cagney + + * Makefile.in (INCLUDE): Add "gdb/sim-d10v.h". + * interp.c: Include "gdb/sim-d10v.h" instead of "sim-d10v.h". + +2001-08-01 John R. Moore + + * interp.c (sim_create_inferior): Removed a hack that stated + it was setting r0/r1 with argc/argv. + +2001-04-15 J.T. Conklin + + * Makefile.in (simops.o): Add simops.h to dependency list. + +Tue May 23 21:39:23 2000 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Apr 18 16:26:41 2000 Andrew Cagney + + * interp.c (sim_resume): Deliver SIGILL. + (lookup_hash): Do not print SIGILL message. + +Tue Feb 22 18:24:56 2000 Andrew Cagney + + * Makefile.in (SIM_EXTRA_CFLAGS): Define SIM_HAVE_ENVIRONMENT. + * interp.c (sim_set_trace): Replace sim_trace. Enable tracing. + +Tue Feb 8 17:41:12 2000 Andrew Cagney + + * d10v_sim.h (SIG_D10V_BUS): Define. + + * simops.c (address_exception): Delete function. + (OP_30000000, OP_6401, OP_6001, OP_6000, OP_32010000, OP_31000000, + OP_6601, OP_6201, OP_6200, OP_33010000, OP_34000000, OP_6800, + OP_6C1F, OP_6801, OP_6C01, OP_36010000, OP_35000000, OP_6A00, + OP_6E1F, OP_6A01, OP_6E01, OP_37010000): Replace call to + address_exception with code that sets SIG_D10V_BUS. + + * interp.c (sim_resume): When SIGBUS or SIGSEGV, deliver a bus + error to the simulator before resuming execution. + (sim_trace): Check stop reason and use that to determine sim_trace + return value. + (sim_stop_reason): For SIG_D10V_BUS return a SIGBUS / SIGSEGV + sigrc. + +Tue Jan 18 16:07:42 MST 2000 Diego Novillo + + * interp.c (sim_create_inferior): Change internal initial value for + DMAP2 to 0x2000. + +Mon Jan 3 02:06:07 2000 Andrew Cagney + + * interp.c (lookup_hash): Stop the update of the PC when there was + an illegal instruction exception. + +Mon Jan 3 00:14:33 2000 Andrew Cagney + + * simops.c (address_exception): New function. + (OP_30000000, OP_6401, OP_6001, OP_6000, OP_32010000, OP_31000000, + OP_6601, OP_6201, OP_6200, OP_33010000, OP_34000000, OP_6800, + OP_6C1F, OP_6801, OP_6C01, OP_36010000, OP_35000000, OP_6A00, + OP_6E1F, OP_6A01, OP_6E01, OP_37010000): For "ld", "ld2w", "st" + and "st2w" check that the address is aligned. + +1999-12-30 Chandra Chavva + + * d10v_sim.h (INC_ADDR): Added code to assign + proper address for loads with predec operations. + +1999-11-25 Nick Clifton + + * simops.c (OP_4E0F): New function: Simulate new bit pattern for + cpfg instruction. + +Fri Oct 29 18:34:28 1999 Andrew Cagney + + * simops.c (move_to_cr): Don't allow user to set PSW.DM in either + DPSW and BPSW. + +Thu Oct 28 01:26:18 1999 Andrew Cagney + + * simops.c (OP_5F20): Use SET_HW_PSW when updating PSW. + (PSW_HW_MASK): Declare. + + * d10v_sim.h (move_to_cr): Add ``psw_hw_p'' parameter. + (SET_CREG, SET_PSW_BIT): Update. + (SET_HW_CREG, SET_HW_PSW): Define. + +Sun Oct 24 21:38:04 1999 Andrew Cagney + + * interp.c (sim_d10v_translate_dmap_addr): Fix extraction of IOSP + for DMAP3. + +Sun Oct 24 16:04:16 1999 Andrew Cagney + + * interp.c (sim_d10v_translate_addr): New function. + (xfer_mem): Rewrite. Use sim_d10v_translate_addr. + (map_memory): Make INLINE. + +Sun Oct 24 13:45:19 1999 Andrew Cagney + + * interp.c (sim_d10v_translate_dmap_addr): New function. + (dmem_addr): Rewrite. Use sim_d10v_translate_dmap_addr. Change + offset parameter to type uint16. + * d10v_sim.h (dmem_addr): Update declaration. + +Sun Oct 24 13:07:31 1999 Andrew Cagney + + * interp.c (imap_register, set_imap_register, dmap_register, + set_imap_register): Use map_memory. + (DMAP): Update. + (sim_create_inferior): Initialize all DMAP registers. NOTE that + DMAP2, in internal memory mode, is set to 0x0000 and NOT + 0x2000. This is consistent with the older d10v boards. + +Sun Oct 24 11:22:12 1999 Andrew Cagney + + * interp.c (sim_d10v_translate_imap_addr): New function. + (imem_addr): Rewrite. Use sim_d10v_translate_imap_addr. + (last_from, last_to): Declare. + +Sun Oct 24 01:21:56 1999 Andrew Cagney + + * d10v_sim.h (struct d10v_memory): Define. Support very long + memories. + (struct _state): Replace imem, dmem and umem by mem. + (IMAP_BLOCK_SIZE, DMAP_BLOCK_SIZE, SEGMENT_SIZE, IMEM_SEGMENTS, + DMEM_SEGMENTS, UMEM_SEGMENTS): Define. + + * interp.c (map_memory): New function. + (sim_size, xfer_memory, imem_addr, dmem_addr): Update. + (UMEM_SEGMENTS): Moveed to "d10v_sim.h". + (IMEM_SIZEDMEM_SIZE): Delete. + +Sat Oct 23 20:06:58 1999 Andrew Cagney + + * interp.c: Include "sim-d10v.h". + (imap_register, set_imap_register, dmap_register, + set_dmap_register, spi_register, spu_register, set_spi_register, + set_spu_register): New functions. + (sim_create_inferior): Update. + (sim_fetch_register, sim_store_register): Rewrite. Use enums + defined in sim-d10v.h. + + * d10v_sim.h (DEBUG_MEMORY): Define. + (IMAP0, IMAP1, DMAP, SET_IMAP0, SET_IMAP1, SET_DMAP): Delete. + +Sat Oct 23 18:41:18 1999 Andrew Cagney + + * interp.c (sim_open): Allow a debug value to be passed to the -t + option. + (lookup_hash): Don't exit on an illegal instruction. + (do_long, do_2_short, do_parallel): Check for failed instruction + lookup. + +Mon Oct 18 18:03:24 MDT 1999 Diego Novillo + + * simops.c (OP_3220): Fix trace output for illegal accumulator + message. + +1999-09-14 Nick Clifton + + * simops.c: Disable setting of DM bit in PSW. + +Wed Sep 8 19:34:55 MDT 1999 Diego Novillo + + * simops.c (op_types): Added new memory indirect type OP_MEMREF3. + (trace_input_func): Added support for OP_MEMREF3. + (OP_32010000): New instruction ld. + (OP_33010000): New instruction ld2w. + (OP_5209): New instruction sac. + (OP_4209): New instruction sachi. + (OP_3220): New instruction slae. + (OP_36010000): New instruction st. + (OP_37010000): New instruction st2w. + +1999-09-09 Stan Shebs + + * interp.c (old_segment_mapping): New global. + (xfer_mem): Change the default segment mapping to be the way + that Mitsubishi prefers, but use the previous mapping if + old_segment_mapping is true. + (sim_open): Add an option -oldseg to get the old mapping. + (sim_create_inferior): Init mapping registers based on the + value of old_segment_mapping. + +1999-09-07 Nick Clifton + + * simops.c (OP_6601): Do not write back decremented address if + either of the destination registers was the same as the address + register. + (OP_6201): Do not write back incremented address if either of the + destination registers was the same as the address register. + +Thu Sep 2 18:15:53 1999 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +1999-05-08 Felix Lee + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +1999-04-02 Keith Seitz + + * interp.c (ui_loop_hook_counter): New global (when NEED_UI_LOOP_HOOK + defined). + (sim_resume): If the counter has expired, call the ui_loop_hook, + if defined. + (UI_LOOP_POLL_INTERVAL): Define. Used to tweak the frequency of + ui_loop_hook calls. + * Makefile.in (SIM_EXTRA_CFLAGS): Include NEED_UI_LOOP_HOOK. + +Wed Mar 10 19:32:13 1999 Nick Clifton + + * simops.c: If load instruction with auto increment/decrement + addressing is used when the destination register is the same as + the address register, then ignore the auto increment/decrement. + +Wed Mar 10 19:32:13 1999 Martin M. Hunt + + * simops.c (OP_5F00): Ifdef SYS_stat case because + not all systems have it defined. + +1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_5607): Correct saturation comparison/assignment. + (OP_1201, OP_1203, OP_17001200, OP_17001202, + OP_2A00, OP_2800, OP_2C00, OP_3200, OP_3201, + OP_1001, OP_1003, OP_17001000, OP_17001002): Ditto. + +1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_5605): Sign extend MIN32 and MAX32 before saturation + comparison. + (OP_5607): Ditto. + (OP_2A00): Ditto. + (OP_2800): Ditto. + +1999-01-13 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_1223): Sign extend MIN32 and MAX32 before saturation + comparison. + +Tue Nov 24 17:04:43 1998 Andrew Cagney + + * simops.c (sys/syscall.h): Include targ-vals.h instead. + (SYS_*): Replace with TARGET_SYS_*. + + * Makefile.in: Add dependency on targ-vals.h. + (NL_TARGET): Define as NL_TARGET_d10v. + +Wed Sep 30 00:06:32 1998 Andrew Cagney + + * interp.c (xfer_mem): Missing break, instruction memory case + flowed into unified memory case. + +Wed Sep 30 10:14:18 1998 Nick Clifton + + * simops.c: If load instruction with auto increment/decrement + addressing is used when the destination register is the same as + the address register, then ignore the auto increment/decrement. + +Tue Apr 28 18:33:31 1998 Geoffrey Noer + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Apr 26 15:31:55 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Sun Apr 26 15:20:23 1998 Tom Tromey + + * acconfig.h: New file. + * configure.in: Reverted change of Apr 24; use sinclude again. + +Fri Apr 24 14:16:40 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Fri Apr 24 11:20:06 1998 Tom Tromey + + * configure.in: Don't call sinclude. + +Fri Apr 24 11:04:46 1998 Andrew Cagney + + * interp.c (struct hash_entry): OPCODE and MASK are unsigned. + + * d10v_sim.h (remote-sim.h, sim-config.h): Include. + +Sat Apr 4 20:36:25 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 1 12:59:17 1998 Andrew Cagney + + * simops.c (trace_input_func): Use move_from_cr / CREGS to obtain + up-to-date CR value. + (OP_OP_1000000, add3): Trace inputs before performing add. + (OP_5F00, <*>): Trace input registers before making system call. + (OP_5F00, ): Trace R0, R1 not REGn. + (OP_5F00, ): Always return 47. + + * d10v_sim.h (SLOT, SLOT_NR, SLOT_PEND_MASK, SLOT_PEND, + SLOT_DISCARD, SLOT_FLUSH): Define. An implementation of write + back slots. + (struct _state): Add struct slot slot to global state variable. + (struct _state): Delete fields SM, EA, DB, DM, IE, RP, MD, FX, ST, + F0, F1, C from global State variable. + (struct _state): Add struct trace to global State variable. + (GPR, SET_GPR): Define. SET_GPR uses SLOT_PEND. + (PSW*, SET_PSW*): Define. SET_PSW* uses SET_CREG. + (CREG, SET_CREG, SET_*): Define. SET_CREG uses func move_to_cr. + (INC_ADDR): Re-implement. Use SET_GPR to update registers. + (JMP): Re-implement. Use SET_* to update registers. + + * interp.c: Use new SET_* et.al. macros to fetch / store + registers. + (get_operands): Squirrel away trace values at start of each + operand decode. + (do_2_short): Flush pending writes before issuing second + instruction. + (sim_resume): Flush pending writes at end of instruction cycle. + (sim_fetch_register, sim_store_register, sim_create_inferior): + After scheduling updates to registers using SET_*, flush updates. + (sim_resume): Re-order handling of RPT/repeat and IBA/hbreak so + that each sets pc using SET_* and last SET_* eventually winds out. + + * simops.c: Use new SET_* et.al. macros to fetch / store + registers. + (move_to_cr): Add MASK argument for selective update of CREG bits. + Re-implement using new SET_* macros. + (trace_output_func, trace_output): Delete. Replace with. + (do_trace_output_flush, trace_output_finish, trace_output_40, + trace_output_32, trace_output_16, trace_output_void, + trace_output_flag): New functions. Handle specific trace cases. + (OP_*): Re-write tracing to use new trace_output_* functions. + (OP_*): Re-write to use new SET_* et.al. macros. + (FUNC, PARM[1-4], RETVAL, RETVAL32): Redo definition. + (RETVAL_HIGH, RETVAL_LOW): Delete, use RETVAL32. + +Wed Apr 1 12:55:18 1998 Andrew Cagney + + * configure.in (SIM_AC_OPTION_WARNINGS): Add. + configure: Re-generate. + +Fri Mar 27 16:15:52 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 25 12:35:29 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 18 12:38:12 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Feb 17 12:38:42 1998 Andrew Cagney + + * interp.c (sim_store_register, sim_fetch_register): Pass in + length parameter. Return -1. + +Mon Oct 27 14:43:33 1997 Fred Fish + + * (dmem_addr): If address is illegal or in I/O space, signal a bus + error. Allocate unified memory on demand. Fix DMEM address + calculations. + +Mon Feb 16 10:27:53 1998 Andrew Cagney + + * simops.c (OP_5F20): Implement "dbt". + (OP_5F60): Implement "rtd". + + * d10v_sim.h (DPC_CR): Define enum. + (DBT_VECTOR_START): Define + (DPSW, DPC): Define. + +Fri Feb 13 15:15:58 1998 Andrew Cagney + + * simops.c (move_to_cr): Sync regs[SP_IDX] with State.sp according + to PSW:SM. + + * d10v_sim.h (struct _state): Add sp, as holding area for SPI/SPU. + (SP_IDX): Define. + +Wed Feb 11 16:53:49 1998 Andrew Cagney + + * simops.c (OP_5F00): Call error instead of abort for unknown + syscalls. + + * d10v_sim.h (enum): Define DPSW_CR. + + * simops.c (move_to_cr): Mask out hardwired zero bits in DPSW. + +Tue Feb 10 18:28:38 1998 Andrew Cagney + + * interp.c (sim_write_phys): Delete. + (sim_load): Call sim_load_file with sim_write and LMA. + +Mon Feb 9 12:05:01 1998 Andrew Cagney + + * interp.c: Rewrite xfer_mem so that it translates addresses as - + 0x00... - DMAP translated memory, 0x01... IMAP translated memory, + 0x10... - on-chip data, 0x11... - on-chip insn, 0x12... - unified + memory. + (pc_addr): Delete. + (imem_addr): New function - translate IMEM address. + (sim_resume): Use imem_addr to translate insn address, abort if + translation failed. + (sim_create_inferior): Write ARGV to memory using sim_write. Pass + argc/argv using r0/r1 not r2/r3. + (sim_size): Do not initialize IMAP/DMAP here. + (sim_open): Call sim_create_inferior and sim_size to initialize + the system. + (sim_create_inferior): Initialize IMAP/DMAP to hardware reset + defaults. + (init_system): Delete. + (xfer_mem, sim_fetch_register, sim_store_register): Do not call + init_system. + (decode_pc): Check prog_bfd is defined before looking up .text + section. + +Sun Feb 1 16:47:51 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Jan 31 18:15:41 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Jan 25 22:23:01 1998 Michael Meissner + + * interp.c (sim_stop_reason): Exit status is now in r0, not r2. + +Sat Jan 24 19:00:30 1998 Michael Meissner + + * d10v_sim.h (DEBUG_TRAP): New debug flag. + + * simops.c (OP_5F00): If DEBUG_TRAP is on, turn traps 0-14 into + printing the registers. + +Thu Jan 22 17:54:01 1998 Michael Meissner + + * simops.c (op_types): New ABI, args are r0..r3, system call # is + in r4. + (trace_{in,out}put_func): Ditto. + (OP_4900): Ditto. + (OP_24800000): Ditto. + (OP_4D00): Ditto. + (OP_5F00): Ditto. + +Thu Jan 22 14:30:36 1998 Fred Fish + + * interp.c (UMEM_SEGMENTS): New define, set to 128. + (sim_size): Use UMEM_SEGMENTS rather than hardwired constant. + (sim_close): Reset prog_bfd to NULL after closing it. Also + reset prog_bfd_was_opened_p after closing prog_bfd. + (sim_load): Reset prog_bfd_was_opened_p after closing prog_bfd. + (sim_create_inferior): Get start address from abfd not prog_bfd. + (xfer_mem): Do bounds checking on addresses and return zero length + read/write on bad addresses, rather than aborting. Prepare to + be able to handle xfers that cross segment boundaries, but not + yet implemented. Only emit debug message when d10v_debug is + set as well as DEBUG being defined. + +Mon Jan 19 22:26:29 1998 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Dec 15 23:17:11 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Dec 9 10:28:31 1997 Andrew Cagney + + * d10v_sim.h (RPT_S): Index cregs with RPT_S_CR not RPT_E_CR. + (BPSW): Ditto for BPSW_CR and not PSW_CR. + + * simops.c (OP_5F40): JMP to BPC instead of assigning PC directly. + +Mon Dec 8 12:58:33 1997 Andrew Cagney + + * simops.c (OP_5F00): From Martin Hunt . Change + reserved trap from 0 to 15. Add trap emulation code for 0-14. + + * interp.c (sim_resume): From Martin Hunt . Check + IBA for SDBT. + + * d10v_sim.h (AE_VECTOR_START, RIE_VECTOR_START, + SDBT_VECTOR_START, TRAP_VECTOR_START): Define. + + * simops.c (OP_5F00): For "trap", mask out all but SM bit in PSW, + use move_to_cr. + (OP_5F00): For "trap", update BPSW with move_to_cr. + +Fri Dec 5 15:31:17 1997 Andrew Cagney + + * d10v_sim.h (enum): Enumerate CR register names. + (enum): Enumerate PSW bit values. + (PSW): Obtain value uing move_from_cr. + (MOD_S, MOD_E, BPSW): Make r-values. + (move_from_cr, move_to_cr): Declare functions. + + * interp.c (sim_fetch_register, sim_store_register): Use + move_from_cr and move_to_cr for CR register transfers. + + * simops.c (move_from_cr, move_to_cr): New functions. + (OP_5F40): Move BPSW to PSW using move_to_cr and move_from_cr. + (OP_5600): For "mvtc", use function move_to_cr. + (OP_5200): For "mvfc", use function move_from_cr. + +Fri Dec 5 13:33:14 1997 Andrew Cagney + + * simops.c (OP_5600): For "mvtc" MOD_E and MOD_S, ensure that the + LSbit is zero. + +Thu Dec 4 09:21:05 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Thu Dec 4 16:51:02 1997 Andrew Cagney + + * d10v_sim.h (struct _state): Add DM - PSW debug mask. + + * simops.c (OP_5600): For "mvtc", save PSW.DM. + (OP_5200): Ditto for "mvfc". + +Wed Dec 3 17:27:06 1997 Andrew Cagney + + * d10v_sim.h (SEXT56): Define. + + * simops.c (OP_4201): For "rac", sign extend 56 bit value before + it is shifted. + + * d10v_sim.h (MAX32, MIN32, MASK32, MASK40): Re-define using + SIGNED64 macro. + +Tue Dec 2 15:38:34 1997 Fred Fish + + * interp.c (sim_resume): Call do_2_short with LEFT_FIRST or + RIGHT_FIRST, as appropriate, instead of hardcoded ints that + don't match enum values. + +Tue Dec 2 15:01:08 1997 Andrew Cagney + + * simops.c (OP_3A00): For "macu", perform multiply stage using 32 + bit rather than 16 bit precision. + (OP_3C00): For "mulxu", store unsigned product in ACC. + (OP_3800): For "msbu", subtract unsigned product from ACC, + (OP_0): For "sub", compute carry by comparing inputs. + +Tue Dec 2 11:04:37 1997 Andrew Cagney + + * simops.c (OP_1000): For "sub2w", compute carry by comparing + inputs. + +Mon Nov 17 20:57:21 1997 Andrew Cagney + + * simops.c (OP_1): Use 32 bit unsigned arithmetic for subtract, + carry indicated by value > 0xffff. + +Fri Nov 14 12:51:20 1997 Andrew Cagney + + * interp.c (sim_resume): Don't set up SIGINT handler using signal, + handled by client. + (sim_resume): Fix race condition of a direct assignment to + stop_simulator, conditionally call sim_stop. + (sim_stop_reason): Check stop_simulator returning SIGINT. Clear + stop_simulator ready for next sim_resume call. + (sim_ctrl_c): Delete function. + +Thu Nov 13 19:29:34 1997 Andrew Cagney + + * interp.c (sim_resume): For "REP", only check/update the PC when + a branch instruction has not been executed. + +Mon Nov 10 17:50:18 1997 Andrew Cagney + + * simops.c (OP_4201): "rachi". Sign extend bit 40 of ACC. Sign + extend bit 44 all constants. + (OP_4201): Replace GCC specific 0x..LL with SIGNED64 macro. + +Fri Oct 24 10:26:29 1997 Andrew Cagney + + * d10v_sim.h: Include sim-types.h. + (uint8, in816, uiny16, int32, uint32, int64, uint64): Typedef + using unsigned8 et.al. from sim-types.h. + (SEXT32, SEXT40, SEXT44, SEXT60): Replace GCC specific 0x..LL with + SIGNED64 macro. + +Wed Oct 22 14:43:00 1997 Andrew Cagney + + * interp.c (sim_write_phys): New function, write to physical + instead of virtual memory. + + * interp.c (sim_load): Pass lma_p and sim_write_phys to + sim_load_file. + +Mon Oct 13 10:55:07 1997 Fred Fish + + * simops.c (OP_6A01): Change OP_POSTDEC to OP_POSTINC and move + exception generation code to OP_6E01. + (OP_6E01): Change OP_POSTINC to OP_POSTDEC and insert exception + generation code. + +Sat Oct 11 09:02:08 1997 Fred Fish + + * simops.c (OP_6401): postdecrement on r15 is OK, remove exception. + (OP_6601): Ditto. + +Fri Oct 3 09:28:00 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Sep 27 12:51:34 1997 Fred Fish + + * interp.c (pc_addr): Discard upper bit(s) of PC in case + IMAP1 selects unified memory. + * d10v_sim.h (INC_ADDR): Align MOD_E to increment before testing + for end condition. + +Wed Sep 24 17:38:57 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Sep 23 11:04:38 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 22 11:46:20 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 19 17:45:25 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 15 17:36:15 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Sep 10 22:30:24 1997 Martin M. Hunt + + * interp.c (sim_resume): Increment PC at end of rep + loop. + + * simops.c (OP_4201): Fix rachi instruction. + +Thu Sep 4 17:21:23 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Aug 27 18:13:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Aug 26 10:37:49 1997 Andrew Cagney + + * interp.c (sim_kill): Delete. + (sim_create_inferior): Add ABFD argument. + (sim_load): Move setting of PC from here. + (sim_create_inferior): To here. + (start_address): Delete variable. + +Mon Aug 25 17:50:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Aug 25 15:39:29 1997 Andrew Cagney + + * interp.c (sim_open): Add ABFD argument. + +Tue May 20 10:14:45 1997 Andrew Cagney + + * interp.c (sim_open): Add callback argument. + (sim_set_callbacks): Remove SIM_DESC argument. + +Thu Apr 24 00:39:51 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Apr 22 10:29:23 1997 Doug Evans + + * interp.c (sim_open): Undo patch to add -E support. + +Fri Apr 18 13:39:01 1997 Andrew Cagney + + * interp.c (sim_stop): New function. + +Thu Apr 17 02:42:00 1997 Doug Evans + + * Makefile.in (SIM_OBJS): Add sim-load.o. + * d10v_sim.h (exec_bfd): Rename to prog_bfd. + * interp.c: #include bfd.h. + (myname, sim_kind, start_address): New static locals. + (prog_bfd_was_opened_p, prog_bfd): New static locals. + (decode_pc): Update to use prog_bfd. + (sim_open): Set sim_kind, myname. Ignore -E arg. + (sim_close): Close prog_bfd if simulator opened it. + (sim_create_inferior): Return SIM_RC. Delete arg start_address. + (sim_load): Return SIM_RC. New arg abfd. Set start address from bfd. + Call sim_load_file to load file into simulator. + * simops.c (trace_input_func): exec_bfd renamed to prog_bfd. + +Wed Apr 16 16:12:03 1997 Andrew Cagney + + * simops.c (OP_5F00): Only provide system calls SYS_execv, + SYS_wait, SYS_wait, SYS_utime, SYS_time if defined by the host. + +Mon Apr 7 15:45:02 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Apr 2 15:06:28 1997 Doug Evans + + * interp.c (sim_open): New arg `kind'. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 14:34:19 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 17 15:10:07 1997 Andrew Cagney + + * configure: Re-generate. + +Fri Mar 14 10:34:11 1997 Michael Meissner + + * configure: Regenerate to track ../common/aclocal.m4 changes. + + * simops.c (OP_5F00): Remove old traps 1-3. Make trap 15 the same + as trap 0, which will be deprecated. Only set errno, if an error + in fact was returned. + +Thu Mar 13 12:41:20 1997 Doug Evans + + * interp.c: Delete redundant prototypes of sim_foo fns. + (sim_open): New SIM_DESC result. Argument is now in argv form. + (other sim_*): New SIM_DESC argument. + +Thu Mar 13 10:29:04 1997 Michael Meissner + + * simops.c (trace_{input,output}_func): Call flush_stdout from the + callback functions. + (OP_5F00): Ditto. + (OP_6{4,6,C,A}01): Test for post decrement on the stack pointer. + (OP_{1200,1000000,201,5FE0,1003,17001002}): Fix problems in + setting the carry bit after an add or a subtract. + +Wed Feb 12 16:04:15 1997 Michael Meissner + + * simops.c (OP_{1403,15002A02,3{0,4}0{0,1}}): Only use the bottom + 40 bits of accumulators. Sign/zero extend as appropriate. + +Tue Feb 4 13:33:30 1997 Doug Evans + + * Makefile.in (@COMMON_MAKEFILE_FRAG): Use + COMMON_{PRE,POST}_CONFIG_FRAG instead. + * configure.in: sinclude ../common/aclocal.m4. + * configure: Regenerated. + +Thu Jan 23 11:46:23 1997 Stu Grossman (grossman@critters.cygnus.com) + + * configure configure.in Makefile.in: Update to new configure + scheme which is more compatible with WinGDB builds. + * configure.in: Improve comment on how to run autoconf. + * configure: Re-run autoconf to get new ../common/aclocal.m4. + * Makefile.in: Use autoconf substitution to install common + makefile fragment. + +Fri Dec 27 22:54:05 1996 Angela Marie Thomas (angela@cygnus.com) + + * gencode.c: patch to not #include "d10v_sim.h" which + unecessarily includes bfd.h and causes wingdb configure + to fail. + +Mon Dec 16 13:39:03 1996 Martin M. Hunt + + * interp.c (xfer_mem): Change unified memory to 0x0. + +Thu Nov 28 20:42:56 1996 Michael Meissner + + * simops.c (OP_3E01): Fix tracing information. + (OP_300{0,1}): Do not propigate sign. + +Mon Nov 25 19:47:40 1996 Doug Evans + + * config.in (WORDS_BIGENDIAN): Add. + * configure: Regenerated. + * d10v_sim.h: #include "config.h" + +Sat Nov 23 09:34:50 1996 Michael Meissner + + * gencode.c (write_opcodes): Eliminate warnings when generated + table.c is compiled. + +Wed Nov 20 19:41:40 1996 Michael Meissner + + * interp.c (sim_open): Cast result of calloc, and make sure NULL + was not returned. + (dmem_addr): If address is illegal or in I/O space, signal a bus + error. + (pc_addr): Signal bus error, not illegal instruction for bogus + pc. + +Wed Nov 20 01:23:03 1996 Doug Evans + + * Makefile.in: Delete all stuff moved to ../common/Make-common.in. + (SIM_OBJS,SIM_EXTRA_CFLAGS,SIM_EXTRA_CLEAN): Define. + * configure.in: Simplify using macros in ../common/aclocal.m4. + Call AC_CHECK_HEADERS(unistd.h). + * configure: Regenerated. + * config.in: New file. + * interp.c: #include "callback.h". + * simops.c: #include "config.h". #include if present. + +Fri Nov 8 16:19:55 1996 Martin M. Hunt + + * d10v-sim.h (simops): Add flag is_long. + (State): Add pc_changed. Instructions which update the PC should + use the JMP macro which sets this. + (JMP): New macro. Sets the PC and the pc_changed flag. + + * gencode.c (write_opcodes): Add is_long field. + + * interp.c (lookup_hash): If we blindly apply a short opcode's mask + to a long opcode we could get a false match. Check the opcode size. + (hash): Add a size field to the hash table. + (sim_open): Initialize size field in hash table. + (sim_resume): Change to logic for setting the PC. Used to increment the + PC if it had not been changed. This didn't allow single-instruction loops. + Now checks the flag State.pc_changed. Also now stops when ^C is received. + (dmem_addr): Fix translation of data segments to unified memory. + (sim_ctrl_c): New function. When ^C is received, set stop_simulator flag. + + * simops.c: Changed all branch and jump instructions to use new JMP macro. + (OP_20000000): Corrected trace information to show this is a ldi.l, not + a ldi.s instruction. + +Thu Oct 31 19:13:55 1996 Martin M. Hunt + + * interp.c (sim_fetch_register, sim_store_register): Fix bug where + updating the accumulators was overwriting other parts of the global + State variable. + +Wed Oct 30 17:35:14 1996 Michael Meissner + + * interp.c (bfd.h) Don't include it here any more. + (text{,_start,_end}): Move here from simops.c and make extern. + (decode_pc): New function to return the PC as an address that the + debugger can use. + (dmem_addr): Print decoded PC in error message. + (pc_addr): Ditto. + + * simops.c (bfd.h) Don't include it here any more. + (text{,_start,_end}): Move to simops.c. + (trace_input_func): Move decoding of PC, and looking up .text + start to decode_pc. + + * d10v_sim.h (bfd.h): Include it here. + (text{,_start,_end}): Add external declarations. + (exec_bfd): Ditto. + (decode_pc): Ditto. + +Tue Oct 29 12:13:52 1996 Martin M. Hunt + + * interp.c (sim_size): Now allocates unified memory for imap segments + 0,1,2, and 127. Initializes imap0 and imap1 to 0x1000. Initializes dmap to 0. + (sim_write): Just call xfer_mem(). + (sim_read): Just call xfer_mem(). + (xfer_mem): New function. Does appropriate memory mapping and copies bytes. + (dmem_addr): New function. Reads dmap register and translates data + addresses to local addresses. + (pc_addr): New function. Reads imap register and computes local address + corresponding to contents of the PC. + (sim_resume): Change to use pc_addr(). + (sim_create_inferior): Change reinitialization code. Also reinitializes + imap[01] and dmap. + (sim_fetch_register): Add fake registers 32,33,34 for imap0, imap1, and dmap. + (sim_store_register): Add fake registers 32,33,34 for imap0, imap1, and dmap. + + * simops.c (MEMPTR): Redefine to use dmem_addr(). + (OP_5F00): Replace references to STate.imem with dmem_addr(). + + * d10v-sim.h (State): Remove mem_min and mem_max. Add umem[128]. + (RB,SW,RW,SLW,RLW): Redefine to use dmem_addr(). + (IMAP0,IMAP1,DMAP,SET_IMAP,SET_IMAP1,SET_DMAP): Define. + +Tue Oct 22 15:22:33 1996 Michael Meissner + + * d10v_sim.h (_ins_type): Reorganize, so that we can provide + better statistics, like not counting NOPS as parallel + instructions, and printing total cycles. + (ins_type_counters): Make unsigned long. + (left_nops,right_nops): Fold into ins_type_counters. + + * simops.c (trace_input_func): Print new instruction types. + Handle OP_R2R3 as input types. + (OP_{38000000,7000}): Correctly sign extend bytes. + (OP_5E00): Don't count NOPs as parallel instructions. + (OP_460B): Remove unused variable. + (OP_5F00): Ditto. + + * interp.c (ins_type_counters): Make unsigned long. + (left_nops,right_nops): Delete. + (most functions): Add prototypes. + (INLINE): If GCC and optimize define as __inline__. + ({,lookup_}hash,get_operands): Declare as INLINE. + (do_parallel): Count conditional operations. + (add_commas): New function, to add commas every 3 digits. + (sim_size): Call add_commas to print numbers. + (sim_{open,resume}): Delete unused variables. + (sim_info): Provide better statistics. + (sim_read): Add int return type. + +Mon Oct 21 16:16:26 1996 Martin M. Hunt + + * interp.c (sim_resume): Change the way single-stepping and exceptions + are handled so single-stepping works again. + +Thu Oct 17 12:24:16 1996 Michael Meissner + + * endian.c: Optimize simulated loads/stores on x86, AIX, and big + endian hosts. + + * configure.in (--enable-sim-bswap): New switch to enable using + the BSWAP instruction on x86's. + * configure: Regenerate. + + * Makefile.in ({SWAP,CONFIG}_CFLAGS): Add --enable-sim-bswap + support. + +Wed Oct 16 13:50:06 1996 Michael Meissner + + * endian.c: New file. Move endian functions here from interp.c. + Optimize code, and make it work as either inline functions or as a + separate file. + + * interp.c: Move endian functions from here to endian.c. + + * Makefile.in (INCLUDE): Add endian.c. + (run,libsim.a): Add dependency on endian.o. + (endian.o): Add dependency. + + * d10v_sim.h (read/write support): Always go through the machine + independent endian functions. If compiling with GCC and + optimizing, include endian.c so the endian functions are inlined. + + * simops.c (OP_5F00): Correct tracing of accumulators. + +Tue Oct 15 10:57:50 1996 Michael Meissner + + * simops.c (OP_5F00): Add support for getpid, kill system calls. + + * interp.c (do_{2_short,parallel}): If an exception is raised, + don't execute the second instruction. + +Sat Oct 12 22:17:43 1996 Michael Meissner + + * simops.c (OP_{31000000,6601,6201,6200}): Store address in a + temporary in case the register is overriden when loading. + (OP_6200): Output type is OP_DREG for tracing. + +Fri Oct 4 23:46:18 1996 Michael Meissner + + * d10v_sim.h (struct _state): Add mem_{min,max} fields. + + * interp.c (sim_size): Initialize mem_{min,max} fields. + (sim_write): Update mem_{min,max} fields. + (sim_resume): If PC is not in the minimum/maximum memory range, + abort. + (sim_create_inferior): Preserve mem_{min,max} fields. + +Fri Sep 27 13:11:58 1996 Mark Alexander + + * simops.c (OP_5F00): Add support for time() system call. + +Wed Sep 25 16:31:41 1996 Michael Meissner + + * simops.c (OP_{6E01,6A01,6E1F,6A00}): Print both words being + stored if tracing. + (OP_5F00,trace_{in,out}put_func): Add finer grain tracing for + system calls. + +Mon Sep 23 17:55:30 1996 Michael Meissner + + * simops.c (op_types): Add OP_{CONSTANT8,R2,R3}. + (trace_input_func): Add support for OP_{CONSTANT8,R2,R3}. + (OP_{4900,24800000,4800,4A00,4B00,4D00,4C00}): Add OP_R2 and OP_R3 + to call/subroutine returns to trace the first two arguments and + the return value. For small jumps, use CONSTANT8, not CONSTANT16. + +Fri Sep 20 15:36:45 1996 Martin M. Hunt + + * interp.c (sim_create_inferior): Reinitialize State every time + sim_create_inferior() is called. + +Thu Sep 19 21:38:20 1996 Michael Meissner + + * simops.c (OP_{401,2000000,601,3000000,23000000}): Get sign right + on comparisons. + (OP_401): Fix tracing information. + +Thu Sep 19 10:30:22 1996 Michael Meissner + + * simops.c (SIZE_{PC,LINE_NUMBER}): New default sizes for output. + (trace_input_func): Use them. + (trace_input_func): Make sure there is a trailing space after the + instruction. + (OP_6200): Fix tracing info. + + * Makefile.in (run): Add dependencies on libbfd.a and + libiberity.a. + +Wed Sep 18 09:13:25 1996 Michael Meissner + + * d10v_sim.h (DEBUG_INSTRUCTION): New debug value to include line + numbers and function names in debug trace. + (DEBUG): If not defined, set to DEBUG_TRACE, DEBUG_VALUES, and + DEBUG_LINE_NUMBER. + (SIG_D10V_{STOP,EXIT}): Values to represent the stop instruction + and exit system call trap being executed. + + * interp.c (sim_stop_reason): Set exit code correctly for stop + instruction and exit system call trap. + + * configure.in (--enable-sim-cflags): Remove trace case. + (--enable-sim-debug): New switch to set the debug values. + * configure: Regenerate. + + * simops.c (trace_{input,output}_func): Rename from + trace_{input,output}. + (trace_{input,output}): Call trace_{input,output}_func if + d10v_debug is non-zero. + (SIZE_INSTRUCTION): Cut down to 8. + (SIZE_OPERANDS): Cut down to 18. + (SIZE_LOCATION): New value for size of line number, function name + field. + (init_text_p,text{,_start,_end}): New static variables for + printing line number and function name. + (exec_bfd): New external that run.c sets. + (trace_input_func): Print line number and function name if + available and if desired. + (OP_4E09): Don't print out DBT message. + (OP_5FE0): Set exception field to SIG_D10V_STOP. + (OP_5F00): Set exception field to SIG_D10V_EXIT. + +Sat Sep 14 22:18:43 1996 Michael Meissner + + * interp.c (do_2_short): If the instruction encodes jump->ins, + don't do the second instruction if the jump succeeds. + +Fri Sep 13 22:35:19 1996 Michael Meissner + + * simops.c (OP_5F00): Use unknown traps to print all GPRs, + accumulators, PC, and F0/F1/C flags. + +Thu Sep 12 12:50:11 1996 Mark Alexander + + * simops.c (OP_5F00): Fix problems with system calls. + +Thu Sep 12 12:19:28 1996 Michael Meissner + + * simops.c (OP_5F00): Correct tracing information for trap. + +Wed Sep 11 18:55:50 1996 Michael Meissner + + * Makefile.in (CSEARCH): Correctly find opcodes directory. + +Mon Sep 9 13:27:26 1996 Michael Meissner + + * simops.c (trace_output): Properly align accumulator output. + (OP_3{0,2,4}00): Properly parenthesize test expression. Add error + if shift count is too high. + (OP_4E{00,02,04,20,22,40,42}): Make tests agree with book. + (OP_4E09): Make cpfg properly trace the input flags. + (op_types): Add OP_FLAG_OUTPUT. + (trace_{input,output}): Support OP_FLAG_OUTPUT. + (OP_31000000): This ld2w varient is a 16-bit memory reference, not + an 8-bit memory reference instruction for tracing purposes. + (OP_201): Addi needs to set the carry. + +Fri Sep 6 17:56:17 1996 Martin M. Hunt + + * simops.c (OP_2600, OP_2601): Changed min and max comparisons + to use signed register values. + +Wed Sep 4 11:35:17 1996 Michael Meissner + + * d10v_sim.h (DEBUG_*): Add bit flags for controlling debug + output. + (_ins_type): New enumeration to specify which container an + instruction is in, and whether it is part of a parallel operation. + (_state): Add ins_type field. + ({,u}int{8,16,32,64}): Use limits.h to size the appropriate types. + (ins_type_counters): Counters for the various instruction types. + ({left,right}_nops): Counters for the number of nops in each + container. + (d10v_debug): New variable to indicate whether debugging is turned + on. + + * simops.c: (all functions): Change all #ifdef DEBUG code so that + the input and output values can be traced, along with the + instruction type. Make the -t option enable tracing. + (all functions): Change printf calls to use the printf_filtered + function in the callback table. + + * interp.c (_leftright): New enumeration to say whether 2 short + instructions are done left first or right first. + (do_{long,2_short,parallel}): Indicate in the machine state which + type of instruction this is. Count each of the types of + instructions executed. + (sim_size): Only print the memory sizes if DEBUG_MEMSIZE debug + flag is set. + (sim_resume): Pass left/right indication to do_2_short. + (all functions): Change printf calls to use the printf_filtered + function in the callback table. + (sim_trace): Turn on debug flag if DEBUG was defined, and call + sim_resume. + (sim_info): Print out statistics on instructions. + (sim_{trace,create_inferior}): Eliminate extraneous output unless + debugging. + (sim_open): If args == -t and DEBUG was defined, set d10v_debug. + Only initialize the hash table the first time sim_open is called. + + * Makefile.in: Make objects depend on d10v_sim.h. + ({,SIM_}CFLAGS): Include configure dependent switches. Setting + CFLAGS does not override host/target defines or SIM_CFLAGS. + (CC_FOR_BUILD,gencode): Use CC_FOR_BUILD to compile gencode. + (run): By default, the math library is not needed to be linked + in. + ({BFD,LIBIBERTY}_LIB): Define as variables so they can be + overridden. + (VPATH): Don't set to anything but @srcdir@ to work with non-GNU + makes. + ({run,callback}.o): Provide explicit paths to their appropriate + source directories. + (gencode{,.o},d10v-opc.o): Split compilation into creating object + and linking. Instead of linking in libopcodes.a, just compile + d10v-opc.o directly to handle canadian cross. + (CSEARCH): Add opcodes directory. + + * configure.in (--enable-sim-cflags): New switch to allow user to + set the defaults. + (CC_FOR_BUILD): Deal with canadian crosses. + * configure: Regenerate. + +Wed Sep 04 04:45:34 1996 Mark Alexander + + * simops.c: Include correct syscall.h for d10v, not host's. + Fix #ifdef SYS_stat. + +Tue Sep 3 14:00:04 1996 Michael Meissner + + * simops.c (OP_5F00): Wrap all SYS_xxx traps with #ifdef. + Add trap 2 to be printf and trap 3 to be putchar. + +Wed Aug 28 21:42:34 1996 Mark Alexander + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Add support + for low-level system calls. + +Wed Aug 28 17:33:19 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c: Fix byte-order problems. + +Mon Aug 26 18:30:28 1996 Martin M. Hunt + + * d10v_sim.h (SEXT32): Added. + * interp.c: Commented out printfs. + * simops.c: Fixed error in sb and st2w. + +Thu Aug 15 13:30:03 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Added remaining + DSP instructions. Added modulo addressing. + +Sun Aug 11 12:57:15 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Snapshot. + +Fri Aug 2 17:44:24 1996 Martin M. Hunt + + * d10v_sim.h, simops.c: Snapshot. + +Thu Aug 1 17:05:24 1996 Martin M. Hunt + + * ChangeLog, Makefile.in, configure, configure.in, d10v_sim.h, + gencode.c, interp.c, simops.c: Created. +
ChangeLog Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: d10v_sim.h =================================================================== --- d10v_sim.h (nonexistent) +++ d10v_sim.h (revision 33) @@ -0,0 +1,487 @@ +#include "config.h" +#include +#include +#include +#include "ansidecl.h" +#include "gdb/callback.h" +#include "opcode/d10v.h" +#include "bfd.h" + +#define DEBUG_TRACE 0x00000001 +#define DEBUG_VALUES 0x00000002 +#define DEBUG_LINE_NUMBER 0x00000004 +#define DEBUG_MEMSIZE 0x00000008 +#define DEBUG_INSTRUCTION 0x00000010 +#define DEBUG_TRAP 0x00000020 +#define DEBUG_MEMORY 0x00000040 + +#ifndef DEBUG +#define DEBUG (DEBUG_TRACE | DEBUG_VALUES | DEBUG_LINE_NUMBER) +#endif + +extern int d10v_debug; + +#include "gdb/remote-sim.h" +#include "sim-config.h" +#include "sim-types.h" + +typedef unsigned8 uint8; +typedef unsigned16 uint16; +typedef signed16 int16; +typedef unsigned32 uint32; +typedef signed32 int32; +typedef unsigned64 uint64; +typedef signed64 int64; + +/* FIXME: D10V defines */ +typedef uint16 reg_t; + +struct simops +{ + long opcode; + int is_long; + long mask; + int format; + int cycles; + int unit; + int exec_type; + void (*func)(); + int numops; + int operands[9]; +}; + +enum _ins_type +{ + INS_UNKNOWN, /* unknown instruction */ + INS_COND_TRUE, /* # times EXExxx executed other instruction */ + INS_COND_FALSE, /* # times EXExxx did not execute other instruction */ + INS_COND_JUMP, /* # times JUMP skipped other instruction */ + INS_CYCLES, /* # cycles */ + INS_LONG, /* long instruction (both containers, ie FM == 11) */ + INS_LEFTRIGHT, /* # times instruction encoded as L -> R (ie, FM == 01) */ + INS_RIGHTLEFT, /* # times instruction encoded as L <- R (ie, FM == 10) */ + INS_PARALLEL, /* # times instruction encoded as L || R (ie, RM == 00) */ + + INS_LEFT, /* normal left instructions */ + INS_LEFT_PARALLEL, /* left side of || */ + INS_LEFT_COND_TEST, /* EXExx test on left side */ + INS_LEFT_COND_EXE, /* execution after EXExxx test on right side succeeded */ + INS_LEFT_NOPS, /* NOP on left side */ + + INS_RIGHT, /* normal right instructions */ + INS_RIGHT_PARALLEL, /* right side of || */ + INS_RIGHT_COND_TEST, /* EXExx test on right side */ + INS_RIGHT_COND_EXE, /* execution after EXExxx test on left side succeeded */ + INS_RIGHT_NOPS, /* NOP on right side */ + + INS_MAX +}; + +extern unsigned long ins_type_counters[ (int)INS_MAX ]; + +enum { + SP_IDX = 15, +}; + +/* Write-back slots */ +union slot_data { + unsigned_1 _1; + unsigned_2 _2; + unsigned_4 _4; + unsigned_8 _8; +}; +struct slot { + void *dest; + int size; + union slot_data data; + union slot_data mask; +}; +enum { + NR_SLOTS = 16, +}; +#define SLOT (State.slot) +#define SLOT_NR (State.slot_nr) +#define SLOT_PEND_MASK(DEST, MSK, VAL) \ + do \ + { \ + SLOT[SLOT_NR].dest = &(DEST); \ + SLOT[SLOT_NR].size = sizeof (DEST); \ + switch (sizeof (DEST)) \ + { \ + case 1: \ + SLOT[SLOT_NR].data._1 = (unsigned_1) (VAL); \ + SLOT[SLOT_NR].mask._1 = (unsigned_1) (MSK); \ + break; \ + case 2: \ + SLOT[SLOT_NR].data._2 = (unsigned_2) (VAL); \ + SLOT[SLOT_NR].mask._2 = (unsigned_2) (MSK); \ + break; \ + case 4: \ + SLOT[SLOT_NR].data._4 = (unsigned_4) (VAL); \ + SLOT[SLOT_NR].mask._4 = (unsigned_4) (MSK); \ + break; \ + case 8: \ + SLOT[SLOT_NR].data._8 = (unsigned_8) (VAL); \ + SLOT[SLOT_NR].mask._8 = (unsigned_8) (MSK); \ + break; \ + } \ + SLOT_NR = (SLOT_NR + 1); \ + } \ + while (0) +#define SLOT_PEND(DEST, VAL) SLOT_PEND_MASK(DEST, 0, VAL) +#define SLOT_DISCARD() (SLOT_NR = 0) +#define SLOT_FLUSH() \ + do \ + { \ + int i; \ + for (i = 0; i < SLOT_NR; i++) \ + { \ + switch (SLOT[i].size) \ + { \ + case 1: \ + *(unsigned_1*) SLOT[i].dest &= SLOT[i].mask._1; \ + *(unsigned_1*) SLOT[i].dest |= SLOT[i].data._1; \ + break; \ + case 2: \ + *(unsigned_2*) SLOT[i].dest &= SLOT[i].mask._2; \ + *(unsigned_2*) SLOT[i].dest |= SLOT[i].data._2; \ + break; \ + case 4: \ + *(unsigned_4*) SLOT[i].dest &= SLOT[i].mask._4; \ + *(unsigned_4*) SLOT[i].dest |= SLOT[i].data._4; \ + break; \ + case 8: \ + *(unsigned_8*) SLOT[i].dest &= SLOT[i].mask._8; \ + *(unsigned_8*) SLOT[i].dest |= SLOT[i].data._8; \ + break; \ + } \ + } \ + SLOT_NR = 0; \ + } \ + while (0) +#define SLOT_DUMP() \ + do \ + { \ + int i; \ + for (i = 0; i < SLOT_NR; i++) \ + { \ + switch (SLOT[i].size) \ + { \ + case 1: \ + printf ("SLOT %d *0x%08lx & 0x%02x | 0x%02x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._1, \ + (unsigned) SLOT[i].data._1); \ + break; \ + case 2: \ + printf ("SLOT %d *0x%08lx & 0x%04x | 0x%04x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._2, \ + (unsigned) SLOT[i].data._2); \ + break; \ + case 4: \ + printf ("SLOT %d *0x%08lx & 0x%08x | 0x%08x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._4, \ + (unsigned) SLOT[i].data._4); \ + break; \ + case 8: \ + printf ("SLOT %d *0x%08lx & 0x%08x%08x | 0x%08x%08x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) (SLOT[i].mask._8 >> 32), \ + (unsigned) SLOT[i].mask._8, \ + (unsigned) (SLOT[i].data._8 >> 32), \ + (unsigned) SLOT[i].data._8); \ + break; \ + } \ + } \ + } \ + while (0) + +/* d10v memory: There are three separate d10v memory regions IMEM, + UMEM and DMEM. The IMEM and DMEM are further broken down into + blocks (very like VM pages). */ + +enum +{ + IMAP_BLOCK_SIZE = 0x20000, + DMAP_BLOCK_SIZE = 0x4000, +}; + +/* Implement the three memory regions using sparse arrays. Allocate + memory using ``segments''. A segment must be at least as large as + a BLOCK - ensures that an access that doesn't cross a block + boundary can't cross a segment boundary */ + +enum +{ + SEGMENT_SIZE = 0x20000, /* 128KB - MAX(IMAP_BLOCK_SIZE,DMAP_BLOCK_SIZE) */ + IMEM_SEGMENTS = 8, /* 1MB */ + DMEM_SEGMENTS = 8, /* 1MB */ + UMEM_SEGMENTS = 128 /* 16MB */ +}; + +struct d10v_memory +{ + uint8 *insn[IMEM_SEGMENTS]; + uint8 *data[DMEM_SEGMENTS]; + uint8 *unif[UMEM_SEGMENTS]; + uint8 fault[16]; +}; + +struct _state +{ + reg_t regs[16]; /* general-purpose registers */ +#define GPR(N) (State.regs[(N)] + 0) +#define SET_GPR(N,VAL) SLOT_PEND (State.regs[(N)], (VAL)) + +#define GPR32(N) ((((uint32) State.regs[(N) + 0]) << 16) \ + | (uint16) State.regs[(N) + 1]) +#define SET_GPR32(N,VAL) do { SET_GPR (OP[0] + 0, (VAL) >> 16); SET_GPR (OP[0] + 1, (VAL)); } while (0) + + reg_t cregs[16]; /* control registers */ +#define CREG(N) (State.cregs[(N)] + 0) +#define SET_CREG(N,VAL) move_to_cr ((N), 0, (VAL), 0) +#define SET_HW_CREG(N,VAL) move_to_cr ((N), 0, (VAL), 1) + + reg_t sp[2]; /* holding area for SPI(0)/SPU(1) */ +#define HELD_SP(N) (State.sp[(N)] + 0) +#define SET_HELD_SP(N,VAL) SLOT_PEND (State.sp[(N)], (VAL)) + + int64 a[2]; /* accumulators */ +#define ACC(N) (State.a[(N)] + 0) +#define SET_ACC(N,VAL) SLOT_PEND (State.a[(N)], (VAL) & MASK40) + + /* writeback info */ + struct slot slot[NR_SLOTS]; + int slot_nr; + + /* trace data */ + struct { + uint16 psw; + } trace; + + uint8 exe; + int exception; + int pc_changed; + + /* NOTE: everything below this line is not reset by + sim_create_inferior() */ + + struct d10v_memory mem; + + enum _ins_type ins_type; + +} State; + + +extern host_callback *d10v_callback; +extern uint16 OP[4]; +extern struct simops Simops[]; +extern asection *text; +extern bfd_vma text_start; +extern bfd_vma text_end; +extern bfd *prog_bfd; + +enum +{ + PSW_CR = 0, + BPSW_CR = 1, + PC_CR = 2, + BPC_CR = 3, + DPSW_CR = 4, + DPC_CR = 5, + RPT_C_CR = 7, + RPT_S_CR = 8, + RPT_E_CR = 9, + MOD_S_CR = 10, + MOD_E_CR = 11, + IBA_CR = 14, +}; + +enum +{ + PSW_SM_BIT = 0x8000, + PSW_EA_BIT = 0x2000, + PSW_DB_BIT = 0x1000, + PSW_DM_BIT = 0x0800, + PSW_IE_BIT = 0x0400, + PSW_RP_BIT = 0x0200, + PSW_MD_BIT = 0x0100, + PSW_FX_BIT = 0x0080, + PSW_ST_BIT = 0x0040, + PSW_F0_BIT = 0x0008, + PSW_F1_BIT = 0x0004, + PSW_C_BIT = 0x0001, +}; + +#define PSW CREG (PSW_CR) +#define SET_PSW(VAL) SET_CREG (PSW_CR, (VAL)) +#define SET_HW_PSW(VAL) SET_HW_CREG (PSW_CR, (VAL)) +#define SET_PSW_BIT(MASK,VAL) move_to_cr (PSW_CR, ~((reg_t) MASK), (VAL) ? (MASK) : 0, 1) + +#define PSW_SM ((PSW & PSW_SM_BIT) != 0) +#define SET_PSW_SM(VAL) SET_PSW_BIT (PSW_SM_BIT, (VAL)) + +#define PSW_EA ((PSW & PSW_EA_BIT) != 0) +#define SET_PSW_EA(VAL) SET_PSW_BIT (PSW_EA_BIT, (VAL)) + +#define PSW_DB ((PSW & PSW_DB_BIT) != 0) +#define SET_PSW_DB(VAL) SET_PSW_BIT (PSW_DB_BIT, (VAL)) + +#define PSW_DM ((PSW & PSW_DM_BIT) != 0) +#define SET_PSW_DM(VAL) SET_PSW_BIT (PSW_DM_BIT, (VAL)) + +#define PSW_IE ((PSW & PSW_IE_BIT) != 0) +#define SET_PSW_IE(VAL) SET_PSW_BIT (PSW_IE_BIT, (VAL)) + +#define PSW_RP ((PSW & PSW_RP_BIT) != 0) +#define SET_PSW_RP(VAL) SET_PSW_BIT (PSW_RP_BIT, (VAL)) + +#define PSW_MD ((PSW & PSW_MD_BIT) != 0) +#define SET_PSW_MD(VAL) SET_PSW_BIT (PSW_MD_BIT, (VAL)) + +#define PSW_FX ((PSW & PSW_FX_BIT) != 0) +#define SET_PSW_FX(VAL) SET_PSW_BIT (PSW_FX_BIT, (VAL)) + +#define PSW_ST ((PSW & PSW_ST_BIT) != 0) +#define SET_PSW_ST(VAL) SET_PSW_BIT (PSW_ST_BIT, (VAL)) + +#define PSW_F0 ((PSW & PSW_F0_BIT) != 0) +#define SET_PSW_F0(VAL) SET_PSW_BIT (PSW_F0_BIT, (VAL)) + +#define PSW_F1 ((PSW & PSW_F1_BIT) != 0) +#define SET_PSW_F1(VAL) SET_PSW_BIT (PSW_F1_BIT, (VAL)) + +#define PSW_C ((PSW & PSW_C_BIT) != 0) +#define SET_PSW_C(VAL) SET_PSW_BIT (PSW_C_BIT, (VAL)) + +/* See simopsc.:move_to_cr() for registers that can not be read-from + or assigned-to directly */ + +#define PC CREG (PC_CR) +#define SET_PC(VAL) SET_CREG (PC_CR, (VAL)) + +#define BPSW CREG (BPSW_CR) +#define SET_BPSW(VAL) SET_CREG (BPSW_CR, (VAL)) + +#define BPC CREG (BPC_CR) +#define SET_BPC(VAL) SET_CREG (BPC_CR, (VAL)) + +#define DPSW CREG (DPSW_CR) +#define SET_DPSW(VAL) SET_CREG (DPSW_CR, (VAL)) + +#define DPC CREG (DPC_CR) +#define SET_DPC(VAL) SET_CREG (DPC_CR, (VAL)) + +#define RPT_C CREG (RPT_C_CR) +#define SET_RPT_C(VAL) SET_CREG (RPT_C_CR, (VAL)) + +#define RPT_S CREG (RPT_S_CR) +#define SET_RPT_S(VAL) SET_CREG (RPT_S_CR, (VAL)) + +#define RPT_E CREG (RPT_E_CR) +#define SET_RPT_E(VAL) SET_CREG (RPT_E_CR, (VAL)) + +#define MOD_S CREG (MOD_S_CR) +#define SET_MOD_S(VAL) SET_CREG (MOD_S_CR, (VAL)) + +#define MOD_E CREG (MOD_E_CR) +#define SET_MOD_E(VAL) SET_CREG (MOD_E_CR, (VAL)) + +#define IBA CREG (IBA_CR) +#define SET_IBA(VAL) SET_CREG (IBA_CR, (VAL)) + + +#define SIG_D10V_STOP -1 +#define SIG_D10V_EXIT -2 +#define SIG_D10V_BUS -3 + +#define SEXT3(x) ((((x)&0x7)^(~3))+4) + +/* sign-extend a 4-bit number */ +#define SEXT4(x) ((((x)&0xf)^(~7))+8) + +/* sign-extend an 8-bit number */ +#define SEXT8(x) ((((x)&0xff)^(~0x7f))+0x80) + +/* sign-extend a 16-bit number */ +#define SEXT16(x) ((((x)&0xffff)^(~0x7fff))+0x8000) + +/* sign-extend a 32-bit number */ +#define SEXT32(x) ((((x)&SIGNED64(0xffffffff))^(~SIGNED64(0x7fffffff)))+SIGNED64(0x80000000)) + +/* sign extend a 40 bit number */ +#define SEXT40(x) ((((x)&SIGNED64(0xffffffffff))^(~SIGNED64(0x7fffffffff)))+SIGNED64(0x8000000000)) + +/* sign extend a 44 bit number */ +#define SEXT44(x) ((((x)&SIGNED64(0xfffffffffff))^(~SIGNED64(0x7ffffffffff)))+SIGNED64(0x80000000000)) + +/* sign extend a 56 bit number */ +#define SEXT56(x) ((((x)&SIGNED64(0xffffffffffffff))^(~SIGNED64(0x7fffffffffffff)))+SIGNED64(0x80000000000000)) + +/* sign extend a 60 bit number */ +#define SEXT60(x) ((((x)&SIGNED64(0xfffffffffffffff))^(~SIGNED64(0x7ffffffffffffff)))+SIGNED64(0x800000000000000)) + +#define MAX32 SIGNED64(0x7fffffff) +#define MIN32 SIGNED64(0xff80000000) +#define MASK32 SIGNED64(0xffffffff) +#define MASK40 SIGNED64(0xffffffffff) + +/* The alignment of MOD_E in the following macro depends upon "i" + always being a power of 2. */ +#define INC_ADDR(x,i) \ +do \ + { \ + int test_i = i < 0 ? i : ~((i) - 1); \ + if (PSW_MD && GPR (x) == (MOD_E & test_i)) \ + SET_GPR (x, MOD_S & test_i); \ + else \ + SET_GPR (x, GPR (x) + (i)); \ + } \ +while (0) + +extern uint8 *dmem_addr (uint16 offset); +extern uint8 *imem_addr PARAMS ((uint32)); +extern bfd_vma decode_pc PARAMS ((void)); + +#define RB(x) (*(dmem_addr(x))) +#define SB(addr,data) ( RB(addr) = (data & 0xff)) + +#if defined(__GNUC__) && defined(__OPTIMIZE__) && !defined(NO_ENDIAN_INLINE) +#define ENDIAN_INLINE static __inline__ +#include "endian.c" +#undef ENDIAN_INLINE + +#else +extern uint32 get_longword PARAMS ((uint8 *)); +extern uint16 get_word PARAMS ((uint8 *)); +extern int64 get_longlong PARAMS ((uint8 *)); +extern void write_word PARAMS ((uint8 *addr, uint16 data)); +extern void write_longword PARAMS ((uint8 *addr, uint32 data)); +extern void write_longlong PARAMS ((uint8 *addr, int64 data)); +#endif + +#define SW(addr,data) write_word(dmem_addr(addr),data) +#define RW(x) get_word(dmem_addr(x)) +#define SLW(addr,data) write_longword(dmem_addr(addr),data) +#define RLW(x) get_longword(dmem_addr(x)) +#define READ_16(x) get_word(x) +#define WRITE_16(addr,data) write_word(addr,data) +#define READ_64(x) get_longlong(x) +#define WRITE_64(addr,data) write_longlong(addr,data) + +#define JMP(x) do { SET_PC (x); State.pc_changed = 1; } while (0) + +#define RIE_VECTOR_START 0xffc2 +#define AE_VECTOR_START 0xffc3 +#define TRAP_VECTOR_START 0xffc4 /* vector for trap 0 */ +#define DBT_VECTOR_START 0xffd4 +#define SDBT_VECTOR_START 0xffd5 + +/* Scedule a store of VAL into cr[CR]. MASK indicates the bits in + cr[CR] that should not be modified (i.e. cr[CR] = (cr[CR] & MASK) | + (VAL & ~MASK)). In addition, unless PSW_HW_P, a VAL intended for + PSW is masked for zero bits. */ + +extern reg_t move_to_cr (int cr, reg_t mask, reg_t val, int psw_hw_p);
d10v_sim.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: config.in =================================================================== --- config.in (nonexistent) +++ config.in (revision 33) @@ -0,0 +1,92 @@ +/* config.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the `time' function. */ +#undef HAVE_TIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `__setfpucw' function. */ +#undef HAVE___SETFPUCW + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS Index: simops.c =================================================================== --- simops.c (nonexistent) +++ simops.c (revision 33) @@ -0,0 +1,3631 @@ +#include "config.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "d10v_sim.h" +#include "simops.h" +#include "targ-vals.h" + +extern char *strrchr (); + +enum op_types { + OP_VOID, + OP_REG, + OP_REG_OUTPUT, + OP_DREG, + OP_DREG_OUTPUT, + OP_ACCUM, + OP_ACCUM_OUTPUT, + OP_ACCUM_REVERSE, + OP_CR, + OP_CR_OUTPUT, + OP_CR_REVERSE, + OP_FLAG, + OP_FLAG_OUTPUT, + OP_CONSTANT16, + OP_CONSTANT8, + OP_CONSTANT3, + OP_CONSTANT4, + OP_MEMREF, + OP_MEMREF2, + OP_MEMREF3, + OP_POSTDEC, + OP_POSTINC, + OP_PREDEC, + OP_R0, + OP_R1, + OP_R2, +}; + + +enum { + PSW_MASK = (PSW_SM_BIT + | PSW_EA_BIT + | PSW_DB_BIT + | PSW_IE_BIT + | PSW_RP_BIT + | PSW_MD_BIT + | PSW_FX_BIT + | PSW_ST_BIT + | PSW_F0_BIT + | PSW_F1_BIT + | PSW_C_BIT), + /* The following bits in the PSW _can't_ be set by instructions such + as mvtc. */ + PSW_HW_MASK = (PSW_MASK | PSW_DM_BIT) +}; + +reg_t +move_to_cr (int cr, reg_t mask, reg_t val, int psw_hw_p) +{ + /* A MASK bit is set when the corresponding bit in the CR should + be left alone */ + /* This assumes that (VAL & MASK) == 0 */ + switch (cr) + { + case PSW_CR: + if (psw_hw_p) + val &= PSW_HW_MASK; + else + val &= PSW_MASK; + if ((mask & PSW_SM_BIT) == 0) + { + int new_psw_sm = (val & PSW_SM_BIT) != 0; + /* save old SP */ + SET_HELD_SP (PSW_SM, GPR (SP_IDX)); + if (PSW_SM != new_psw_sm) + /* restore new SP */ + SET_GPR (SP_IDX, HELD_SP (new_psw_sm)); + } + if ((mask & (PSW_ST_BIT | PSW_FX_BIT)) == 0) + { + if (val & PSW_ST_BIT && !(val & PSW_FX_BIT)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "ERROR at PC 0x%x: ST can only be set when FX is set.\n", + PC<<2); + State.exception = SIGILL; + } + } + /* keep an up-to-date psw around for tracing */ + State.trace.psw = (State.trace.psw & mask) | val; + break; + case BPSW_CR: + case DPSW_CR: + /* Just like PSW, mask things like DM out. */ + if (psw_hw_p) + val &= PSW_HW_MASK; + else + val &= PSW_MASK; + break; + case MOD_S_CR: + case MOD_E_CR: + val &= ~1; + break; + default: + break; + } + /* only issue an update if the register is being changed */ + if ((State.cregs[cr] & ~mask) != val) + SLOT_PEND_MASK (State.cregs[cr], mask, val); + return val; +} + +#ifdef DEBUG +static void trace_input_func PARAMS ((char *name, + enum op_types in1, + enum op_types in2, + enum op_types in3)); + +#define trace_input(name, in1, in2, in3) do { if (d10v_debug) trace_input_func (name, in1, in2, in3); } while (0) + +#ifndef SIZE_INSTRUCTION +#define SIZE_INSTRUCTION 8 +#endif + +#ifndef SIZE_OPERANDS +#define SIZE_OPERANDS 18 +#endif + +#ifndef SIZE_VALUES +#define SIZE_VALUES 13 +#endif + +#ifndef SIZE_LOCATION +#define SIZE_LOCATION 20 +#endif + +#ifndef SIZE_PC +#define SIZE_PC 6 +#endif + +#ifndef SIZE_LINE_NUMBER +#define SIZE_LINE_NUMBER 4 +#endif + +static void +trace_input_func (name, in1, in2, in3) + char *name; + enum op_types in1; + enum op_types in2; + enum op_types in3; +{ + char *comma; + enum op_types in[3]; + int i; + char buf[1024]; + char *p; + long tmp; + char *type; + const char *filename; + const char *functionname; + unsigned int linenumber; + bfd_vma byte_pc; + + if ((d10v_debug & DEBUG_TRACE) == 0) + return; + + switch (State.ins_type) + { + default: + case INS_UNKNOWN: type = " ?"; break; + case INS_LEFT: type = " L"; break; + case INS_RIGHT: type = " R"; break; + case INS_LEFT_PARALLEL: type = "*L"; break; + case INS_RIGHT_PARALLEL: type = "*R"; break; + case INS_LEFT_COND_TEST: type = "?L"; break; + case INS_RIGHT_COND_TEST: type = "?R"; break; + case INS_LEFT_COND_EXE: type = "&L"; break; + case INS_RIGHT_COND_EXE: type = "&R"; break; + case INS_LONG: type = " B"; break; + } + + if ((d10v_debug & DEBUG_LINE_NUMBER) == 0) + (*d10v_callback->printf_filtered) (d10v_callback, + "0x%.*x %s: %-*s ", + SIZE_PC, (unsigned)PC, + type, + SIZE_INSTRUCTION, name); + + else + { + buf[0] = '\0'; + byte_pc = decode_pc (); + if (text && byte_pc >= text_start && byte_pc < text_end) + { + filename = (const char *)0; + functionname = (const char *)0; + linenumber = 0; + if (bfd_find_nearest_line (prog_bfd, text, (struct bfd_symbol **)0, byte_pc - text_start, + &filename, &functionname, &linenumber)) + { + p = buf; + if (linenumber) + { + sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber); + p += strlen (p); + } + else + { + sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); + p += SIZE_LINE_NUMBER+2; + } + + if (functionname) + { + sprintf (p, "%s ", functionname); + p += strlen (p); + } + else if (filename) + { + char *q = strrchr (filename, '/'); + sprintf (p, "%s ", (q) ? q+1 : filename); + p += strlen (p); + } + + if (*p == ' ') + *p = '\0'; + } + } + + (*d10v_callback->printf_filtered) (d10v_callback, + "0x%.*x %s: %-*.*s %-*s ", + SIZE_PC, (unsigned)PC, + type, + SIZE_LOCATION, SIZE_LOCATION, buf, + SIZE_INSTRUCTION, name); + } + + in[0] = in1; + in[1] = in2; + in[2] = in3; + comma = ""; + p = buf; + for (i = 0; i < 3; i++) + { + switch (in[i]) + { + case OP_VOID: + case OP_R0: + case OP_R1: + case OP_R2: + break; + + case OP_REG: + case OP_REG_OUTPUT: + case OP_DREG: + case OP_DREG_OUTPUT: + sprintf (p, "%sr%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CR: + case OP_CR_OUTPUT: + case OP_CR_REVERSE: + sprintf (p, "%scr%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_ACCUM: + case OP_ACCUM_OUTPUT: + case OP_ACCUM_REVERSE: + sprintf (p, "%sa%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT16: + sprintf (p, "%s%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT8: + sprintf (p, "%s%d", comma, SEXT8(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT4: + sprintf (p, "%s%d", comma, SEXT4(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT3: + sprintf (p, "%s%d", comma, SEXT3(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_MEMREF: + sprintf (p, "%s@r%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_MEMREF2: + sprintf (p, "%s@(%d,r%d)", comma, (int16)OP[i], OP[i+1]); + p += strlen (p); + comma = ","; + break; + + case OP_MEMREF3: + sprintf (p, "%s@%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_POSTINC: + sprintf (p, "%s@r%d+", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_POSTDEC: + sprintf (p, "%s@r%d-", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_PREDEC: + sprintf (p, "%s@-r%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_FLAG: + case OP_FLAG_OUTPUT: + if (OP[i] == 0) + sprintf (p, "%sf0", comma); + + else if (OP[i] == 1) + sprintf (p, "%sf1", comma); + + else + sprintf (p, "%sc", comma); + + p += strlen (p); + comma = ","; + break; + } + } + + if ((d10v_debug & DEBUG_VALUES) == 0) + { + *p++ = '\n'; + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%s", buf); + } + else + { + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%-*s", SIZE_OPERANDS, buf); + + p = buf; + for (i = 0; i < 3; i++) + { + buf[0] = '\0'; + switch (in[i]) + { + case OP_VOID: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, ""); + break; + + case OP_REG_OUTPUT: + case OP_DREG_OUTPUT: + case OP_CR_OUTPUT: + case OP_ACCUM_OUTPUT: + case OP_FLAG_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, "---"); + break; + + case OP_REG: + case OP_MEMREF: + case OP_POSTDEC: + case OP_POSTINC: + case OP_PREDEC: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (OP[i])); + break; + + case OP_MEMREF3: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) OP[i]); + break; + + case OP_DREG: + tmp = (long)((((uint32) GPR (OP[i])) << 16) | ((uint32) GPR (OP[i] + 1))); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.8lx", SIZE_VALUES-10, "", tmp); + break; + + case OP_CR: + case OP_CR_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) CREG (OP[i])); + break; + + case OP_ACCUM: + case OP_ACCUM_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.2x%.8lx", SIZE_VALUES-12, "", + ((int)(ACC (OP[i]) >> 32) & 0xff), + ((unsigned long) ACC (OP[i])) & 0xffffffff); + break; + + case OP_CONSTANT16: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + break; + + case OP_CONSTANT4: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT4(OP[i])); + break; + + case OP_CONSTANT8: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT8(OP[i])); + break; + + case OP_CONSTANT3: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT3(OP[i])); + break; + + case OP_FLAG: + if (OP[i] == 0) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF0 = %d", SIZE_VALUES-6, "", + PSW_F0 != 0); + + else if (OP[i] == 1) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF1 = %d", SIZE_VALUES-6, "", + PSW_F1 != 0); + + else + (*d10v_callback->printf_filtered) (d10v_callback, "%*sC = %d", SIZE_VALUES-5, "", + PSW_C != 0); + + break; + + case OP_MEMREF2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)GPR (OP[i + 1])); + i++; + break; + + case OP_R0: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (0)); + break; + + case OP_R1: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (1)); + break; + + case OP_R2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (2)); + break; + + } + } + } + + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +do_trace_output_flush (void) +{ + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +do_trace_output_finish (void) +{ + (*d10v_callback->printf_filtered) (d10v_callback, + " F0=%d F1=%d C=%d\n", + (State.trace.psw & PSW_F0_BIT) != 0, + (State.trace.psw & PSW_F1_BIT) != 0, + (State.trace.psw & PSW_C_BIT) != 0); + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +trace_output_40 (uint64 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.2x%.8lx", + SIZE_VALUES - 12, + "", + ((int)(val >> 32) & 0xff), + ((unsigned long) val) & 0xffffffff); + do_trace_output_finish (); + } +} + +static void +trace_output_32 (uint32 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.8x", + SIZE_VALUES - 10, + "", + (int) val); + do_trace_output_finish (); + } +} + +static void +trace_output_16 (uint16 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.4x", + SIZE_VALUES - 6, + "", + (int) val); + do_trace_output_finish (); + } +} + +static void +trace_output_void () +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, "\n"); + do_trace_output_flush (); + } +} + +static void +trace_output_flag () +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s", + SIZE_VALUES, + ""); + do_trace_output_finish (); + } +} + + + + +#else +#define trace_input(NAME, IN1, IN2, IN3) +#define trace_output(RESULT) +#endif + +/* abs */ +void +OP_4607 () +{ + int16 tmp; + trace_input ("abs", OP_REG, OP_VOID, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = GPR(OP[0]); + if (tmp < 0) + { + tmp = - tmp; + SET_PSW_F0 (1); + } + else + SET_PSW_F0 (0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* abs */ +void +OP_5607 () +{ + int64 tmp; + trace_input ("abs", OP_ACCUM, OP_VOID, OP_VOID); + SET_PSW_F1 (PSW_F0); + + tmp = SEXT40 (ACC (OP[0])); + if (tmp < 0 ) + { + tmp = - tmp; + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = (tmp & MASK40); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add */ +void +OP_200 () +{ + uint16 a = GPR (OP[0]); + uint16 b = GPR (OP[1]); + uint16 tmp = (a + b); + trace_input ("add", OP_REG, OP_REG, OP_VOID); + SET_PSW_C (a > tmp); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* add */ +void +OP_1201 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[0])) + (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1)); + + trace_input ("add", OP_ACCUM, OP_REG, OP_VOID); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add */ +void +OP_1203 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[0])) + SEXT40(ACC (OP[1])); + + trace_input ("add", OP_ACCUM, OP_ACCUM, OP_VOID); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add2w */ +void +OP_1200 () +{ + uint32 tmp; + uint32 a = (GPR (OP[0])) << 16 | GPR (OP[0] + 1); + uint32 b = (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + trace_input ("add2w", OP_DREG, OP_DREG, OP_VOID); + tmp = a + b; + SET_PSW_C (tmp < a); + SET_GPR (OP[0] + 0, (tmp >> 16)); + SET_GPR (OP[0] + 1, (tmp & 0xFFFF)); + trace_output_32 (tmp); +} + +/* add3 */ +void +OP_1000000 () +{ + uint16 a = GPR (OP[1]); + uint16 b = OP[2]; + uint16 tmp = (a + b); + trace_input ("add3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + SET_PSW_C (tmp < a); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* addac3 */ +void +OP_17000200 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[2])) + SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + + trace_input ("addac3", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + SET_GPR (OP[0] + 0, ((tmp >> 16) & 0xffff)); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addac3 */ +void +OP_17000202 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[1])) + SEXT40(ACC (OP[2])); + + trace_input ("addac3", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, tmp & 0xffff); + trace_output_32 (tmp); +} + +/* addac3s */ +void +OP_17001200 () +{ + int64 tmp; + SET_PSW_F1 (PSW_F0); + + trace_input ("addac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + tmp = SEXT40 (ACC (OP[2])) + SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addac3s */ +void +OP_17001202 () +{ + int64 tmp; + SET_PSW_F1 (PSW_F0); + + trace_input ("addac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + tmp = SEXT40(ACC (OP[1])) + SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addi */ +void +OP_201 () +{ + uint16 a = GPR (OP[0]); + uint16 b; + uint16 tmp; + if (OP[1] == 0) + OP[1] = 16; + b = OP[1]; + tmp = (a + b); + trace_input ("addi", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_C (tmp < a); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* and */ +void +OP_C00 () +{ + uint16 tmp = GPR (OP[0]) & GPR (OP[1]); + trace_input ("and", OP_REG, OP_REG, OP_VOID); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* and3 */ +void +OP_6000000 () +{ + uint16 tmp = GPR (OP[1]) & OP[2]; + trace_input ("and3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bclri */ +void +OP_C01 () +{ + int16 tmp; + trace_input ("bclri", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) &~(0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bl.s */ +void +OP_4900 () +{ + trace_input ("bl.s", OP_CONSTANT8, OP_R0, OP_R1); + SET_GPR (13, PC + 1); + JMP( PC + SEXT8 (OP[0])); + trace_output_void (); +} + +/* bl.l */ +void +OP_24800000 () +{ + trace_input ("bl.l", OP_CONSTANT16, OP_R0, OP_R1); + SET_GPR (13, (PC + 1)); + JMP (PC + OP[0]); + trace_output_void (); +} + +/* bnoti */ +void +OP_A01 () +{ + int16 tmp; + trace_input ("bnoti", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) ^ (0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bra.s */ +void +OP_4800 () +{ + trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID); + JMP (PC + SEXT8 (OP[0])); + trace_output_void (); +} + +/* bra.l */ +void +OP_24000000 () +{ + trace_input ("bra.l", OP_CONSTANT16, OP_VOID, OP_VOID); + JMP (PC + OP[0]); + trace_output_void (); +} + +/* brf0f.s */ +void +OP_4A00 () +{ + trace_input ("brf0f.s", OP_CONSTANT8, OP_VOID, OP_VOID); + if (!PSW_F0) + JMP (PC + SEXT8 (OP[0])); + trace_output_flag (); +} + +/* brf0f.l */ +void +OP_25000000 () +{ + trace_input ("brf0f.l", OP_CONSTANT16, OP_VOID, OP_VOID); + if (!PSW_F0) + JMP (PC + OP[0]); + trace_output_flag (); +} + +/* brf0t.s */ +void +OP_4B00 () +{ + trace_input ("brf0t.s", OP_CONSTANT8, OP_VOID, OP_VOID); + if (PSW_F0) + JMP (PC + SEXT8 (OP[0])); + trace_output_flag (); +} + +/* brf0t.l */ +void +OP_25800000 () +{ + trace_input ("brf0t.l", OP_CONSTANT16, OP_VOID, OP_VOID); + if (PSW_F0) + JMP (PC + OP[0]); + trace_output_flag (); +} + +/* bseti */ +void +OP_801 () +{ + int16 tmp; + trace_input ("bseti", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) | (0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* btsti */ +void +OP_E01 () +{ + trace_input ("btsti", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) & (0x8000 >> OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* clrac */ +void +OP_5601 () +{ + trace_input ("clrac", OP_ACCUM_OUTPUT, OP_VOID, OP_VOID); + SET_ACC (OP[0], 0); + trace_output_40 (0); +} + +/* cmp */ +void +OP_600 () +{ + trace_input ("cmp", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)(GPR (OP[1]))) ? 1 : 0); + trace_output_flag (); +} + +/* cmp */ +void +OP_1603 () +{ + trace_input ("cmp", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((SEXT40(ACC (OP[0])) < SEXT40(ACC (OP[1]))) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeq */ +void +OP_400 () +{ + trace_input ("cmpeq", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == GPR (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeq */ +void +OP_1403 () +{ + trace_input ("cmpeq", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((ACC (OP[0]) & MASK40) == (ACC (OP[1]) & MASK40)) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeqi.s */ +void +OP_401 () +{ + trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT4, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == (reg_t) SEXT4 (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeqi.l */ +void +OP_2000000 () +{ + trace_input ("cmpeqi.l", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == (reg_t)OP[1]) ? 1 : 0); + trace_output_flag (); +} + +/* cmpi.s */ +void +OP_601 () +{ + trace_input ("cmpi.s", OP_REG, OP_CONSTANT4, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)SEXT4(OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpi.l */ +void +OP_3000000 () +{ + trace_input ("cmpi.l", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)(OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpu */ +void +OP_4600 () +{ + trace_input ("cmpu", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) < GPR (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpui */ +void +OP_23000000 () +{ + trace_input ("cmpui", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) < (reg_t)OP[1]) ? 1 : 0); + trace_output_flag (); +} + +/* cpfg */ +void +OP_4E09 () +{ + uint8 val; + + trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID); + + if (OP[1] == 0) + val = PSW_F0; + else if (OP[1] == 1) + val = PSW_F1; + else + val = PSW_C; + if (OP[0] == 0) + SET_PSW_F0 (val); + else + SET_PSW_F1 (val); + + trace_output_flag (); +} + +/* cpfg */ +void +OP_4E0F () +{ + uint8 val; + + trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID); + + if (OP[1] == 0) + val = PSW_F0; + else if (OP[1] == 1) + val = PSW_F1; + else + val = PSW_C; + if (OP[0] == 0) + SET_PSW_F0 (val); + else + SET_PSW_F1 (val); + + trace_output_flag (); +} + +/* dbt */ +void +OP_5F20 () +{ + /* d10v_callback->printf_filtered(d10v_callback, "***** DBT ***** PC=%x\n",PC); */ + + /* GDB uses the instruction pair ``dbt || nop'' as a break-point. + The conditional below is for either of the instruction pairs + ``dbt -> XXX'' or ``dbt <- XXX'' and treats them as as cases + where the dbt instruction should be interpreted. + + The module `sim-break' provides a more effective mechanism for + detecting GDB planted breakpoints. The code below may, + eventually, be changed to use that mechanism. */ + + if (State.ins_type == INS_LEFT + || State.ins_type == INS_RIGHT) + { + trace_input ("dbt", OP_VOID, OP_VOID, OP_VOID); + SET_DPC (PC + 1); + SET_DPSW (PSW); + SET_HW_PSW (PSW_DM_BIT | (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (DBT_VECTOR_START); + trace_output_void (); + } + else + { + State.exception = SIGTRAP; + } +} + +/* divs */ +void +OP_14002800 () +{ + uint16 foo, tmp, tmpf; + uint16 hi; + uint16 lo; + + trace_input ("divs", OP_DREG, OP_REG, OP_VOID); + foo = (GPR (OP[0]) << 1) | (GPR (OP[0] + 1) >> 15); + tmp = (int16)foo - (int16)(GPR (OP[1])); + tmpf = (foo >= GPR (OP[1])) ? 1 : 0; + hi = ((tmpf == 1) ? tmp : foo); + lo = ((GPR (OP[0] + 1) << 1) | tmpf); + SET_GPR (OP[0] + 0, hi); + SET_GPR (OP[0] + 1, lo); + trace_output_32 (((uint32) hi << 16) | lo); +} + +/* exef0f */ +void +OP_4E04 () +{ + trace_input ("exef0f", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0); + trace_output_flag (); +} + +/* exef0t */ +void +OP_4E24 () +{ + trace_input ("exef0t", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0); + trace_output_flag (); +} + +/* exef1f */ +void +OP_4E40 () +{ + trace_input ("exef1f", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F1 == 0); + trace_output_flag (); +} + +/* exef1t */ +void +OP_4E42 () +{ + trace_input ("exef1t", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F1 != 0); + trace_output_flag (); +} + +/* exefaf */ +void +OP_4E00 () +{ + trace_input ("exefaf", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0) & (PSW_F1 == 0); + trace_output_flag (); +} + +/* exefat */ +void +OP_4E02 () +{ + trace_input ("exefat", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0) & (PSW_F1 != 0); + trace_output_flag (); +} + +/* exetaf */ +void +OP_4E20 () +{ + trace_input ("exetaf", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0) & (PSW_F1 == 0); + trace_output_flag (); +} + +/* exetat */ +void +OP_4E22 () +{ + trace_input ("exetat", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0) & (PSW_F1 != 0); + trace_output_flag (); +} + +/* exp */ +void +OP_15002A00 () +{ + uint32 tmp, foo; + int i; + + trace_input ("exp", OP_REG_OUTPUT, OP_DREG, OP_VOID); + if (((int16)GPR (OP[1])) >= 0) + tmp = (GPR (OP[1]) << 16) | GPR (OP[1] + 1); + else + tmp = ~((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + + foo = 0x40000000; + for (i=1;i<17;i++) + { + if (tmp & foo) + { + SET_GPR (OP[0], (i - 1)); + trace_output_16 (i - 1); + return; + } + foo >>= 1; + } + SET_GPR (OP[0], 16); + trace_output_16 (16); +} + +/* exp */ +void +OP_15002A02 () +{ + int64 tmp, foo; + int i; + + trace_input ("exp", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[1])); + if (tmp < 0) + tmp = ~tmp & MASK40; + + foo = 0x4000000000LL; + for (i=1;i<25;i++) + { + if (tmp & foo) + { + SET_GPR (OP[0], i - 9); + trace_output_16 (i - 9); + return; + } + foo >>= 1; + } + SET_GPR (OP[0], 16); + trace_output_16 (16); +} + +/* jl */ +void +OP_4D00 () +{ + trace_input ("jl", OP_REG, OP_R0, OP_R1); + SET_GPR (13, PC + 1); + JMP (GPR (OP[0])); + trace_output_void (); +} + +/* jmp */ +void +OP_4C00 () +{ + trace_input ("jmp", OP_REG, + (OP[0] == 13) ? OP_R0 : OP_VOID, + (OP[0] == 13) ? OP_R1 : OP_VOID); + + JMP (GPR (OP[0])); + trace_output_void (); +} + +/* ld */ +void +OP_30000000 () +{ + uint16 tmp; + uint16 addr = OP[1] + GPR (OP[2]); + trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RW (addr); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6401 () +{ + uint16 tmp; + uint16 addr = GPR (OP[1]); + trace_input ("ld", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RW (addr); + SET_GPR (OP[0], tmp); + if (OP[0] != OP[1]) + INC_ADDR (OP[1], -2); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6001 () +{ + uint16 tmp; + uint16 addr = GPR (OP[1]); + trace_input ("ld", OP_REG_OUTPUT, OP_POSTINC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RW (addr); + SET_GPR (OP[0], tmp); + if (OP[0] != OP[1]) + INC_ADDR (OP[1], 2); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6000 () +{ + uint16 tmp; + uint16 addr = GPR (OP[1]); + trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RW (addr); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_32010000 () +{ + uint16 tmp; + uint16 addr = OP[1]; + trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RW (addr); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ld2w */ +void +OP_31000000 () +{ + int32 tmp; + uint16 addr = OP[1] + GPR (OP[2]); + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6601 () +{ + uint16 addr = GPR (OP[1]); + int32 tmp; + trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + if (OP[0] != OP[1] && ((OP[0] + 1) != OP[1])) + INC_ADDR (OP[1], -4); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6201 () +{ + int32 tmp; + uint16 addr = GPR (OP[1]); + trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + if (OP[0] != OP[1] && ((OP[0] + 1) != OP[1])) + INC_ADDR (OP[1], 4); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6200 () +{ + uint16 addr = GPR (OP[1]); + int32 tmp; + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_33010000 () +{ + int32 tmp; + uint16 addr = OP[1]; + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* ldb */ +void +OP_38000000 () +{ + int16 tmp; + trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = SEXT8 (RB (OP[1] + GPR (OP[2]))); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldb */ +void +OP_7000 () +{ + int16 tmp; + trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = SEXT8 (RB (GPR (OP[1]))); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldi.s */ +void +OP_4001 () +{ + int16 tmp; + trace_input ("ldi.s", OP_REG_OUTPUT, OP_CONSTANT4, OP_VOID); + tmp = SEXT4 (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldi.l */ +void +OP_20000000 () +{ + int16 tmp; + trace_input ("ldi.l", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID); + tmp = OP[1]; + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldub */ +void +OP_39000000 () +{ + int16 tmp; + trace_input ("ldub", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = RB (OP[1] + GPR (OP[2])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldub */ +void +OP_7200 () +{ + int16 tmp; + trace_input ("ldub", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = RB (GPR (OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mac */ +void +OP_2A00 () +{ + int64 tmp; + + trace_input ("mac", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40( (tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + + tmp += SEXT40 (ACC (OP[0])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* macsu */ +void +OP_1A00 () +{ + int64 tmp; + + trace_input ("macsu", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16) GPR (OP[1]) * GPR (OP[2])); + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + tmp = ((SEXT40 (ACC (OP[0])) + tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* macu */ +void +OP_3A00 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("macu", OP_ACCUM, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp = (tmp << 1); + tmp = ((ACC (OP[0]) + tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* max */ +void +OP_2600 () +{ + int16 tmp; + trace_input ("max", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + if ((int16) GPR (OP[1]) > (int16)GPR (OP[0])) + { + tmp = GPR (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = GPR (OP[0]); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* max */ +void +OP_3600 () +{ + int64 tmp; + + trace_input ("max", OP_ACCUM, OP_DREG, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + if (tmp > SEXT40 (ACC (OP[0]))) + { + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* max */ +void +OP_3602 () +{ + int64 tmp; + trace_input ("max", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + if (SEXT40 (ACC (OP[1])) > SEXT40 (ACC (OP[0]))) + { + tmp = ACC (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + + +/* min */ +void +OP_2601 () +{ + int16 tmp; + trace_input ("min", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + if ((int16)GPR (OP[1]) < (int16)GPR (OP[0])) + { + tmp = GPR (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = GPR (OP[0]); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* min */ +void +OP_3601 () +{ + int64 tmp; + + trace_input ("min", OP_ACCUM, OP_DREG, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + if (tmp < SEXT40(ACC (OP[0]))) + { + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* min */ +void +OP_3603 () +{ + int64 tmp; + trace_input ("min", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + if (SEXT40(ACC (OP[1])) < SEXT40(ACC (OP[0]))) + { + tmp = ACC (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msb */ +void +OP_2800 () +{ + int64 tmp; + + trace_input ("msb", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + + tmp = SEXT40(ACC (OP[0])) - tmp; + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + { + tmp = (tmp & MASK40); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msbsu */ +void +OP_1800 () +{ + int64 tmp; + + trace_input ("msbsu", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)GPR (OP[1]) * GPR (OP[2])); + if (PSW_FX) + tmp = SEXT40( (tmp << 1) & MASK40); + tmp = ((SEXT40 (ACC (OP[0])) - tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msbu */ +void +OP_3800 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("msbu", OP_ACCUM, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp = (tmp << 1); + tmp = ((ACC (OP[0]) - tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mul */ +void +OP_2E00 () +{ + int16 tmp; + trace_input ("mul", OP_REG, OP_REG, OP_VOID); + tmp = GPR (OP[0]) * GPR (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mulx */ +void +OP_2C00 () +{ + int64 tmp; + + trace_input ("mulx", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mulxsu */ +void +OP_1C00 () +{ + int64 tmp; + + trace_input ("mulxsu", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * GPR (OP[2])); + + if (PSW_FX) + tmp <<= 1; + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mulxu */ +void +OP_3C00 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("mulxu", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp <<= 1; + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mv */ +void +OP_4000 () +{ + int16 tmp; + trace_input ("mv", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mv2w */ +void +OP_5000 () +{ + int32 tmp; + trace_input ("mv2w", OP_DREG_OUTPUT, OP_DREG, OP_VOID); + tmp = GPR32 (OP[1]); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* mv2wfac */ +void +OP_3E00 () +{ + int32 tmp; + trace_input ("mv2wfac", OP_DREG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* mv2wtac */ +void +OP_3E01 () +{ + int64 tmp; + trace_input ("mv2wtac", OP_DREG, OP_ACCUM_OUTPUT, OP_VOID); + tmp = ((SEXT16 (GPR (OP[0])) << 16 | GPR (OP[0] + 1)) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvac */ +void +OP_3E03 () +{ + int64 tmp; + trace_input ("mvac", OP_ACCUM_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mvb */ +void +OP_5400 () +{ + int16 tmp; + trace_input ("mvb", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = SEXT8 (GPR (OP[1]) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvf0f */ +void +OP_4400 () +{ + int16 tmp; + trace_input ("mvf0f", OP_REG_OUTPUT, OP_REG, OP_VOID); + if (PSW_F0 == 0) + { + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + } + else + tmp = GPR (OP[0]); + trace_output_16 (tmp); +} + +/* mvf0t */ +void +OP_4401 () +{ + int16 tmp; + trace_input ("mvf0t", OP_REG_OUTPUT, OP_REG, OP_VOID); + if (PSW_F0) + { + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + } + else + tmp = GPR (OP[0]); + trace_output_16 (tmp); +} + +/* mvfacg */ +void +OP_1E04 () +{ + int16 tmp; + trace_input ("mvfacg", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ((ACC (OP[1]) >> 32) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfachi */ +void +OP_1E00 () +{ + int16 tmp; + trace_input ("mvfachi", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = (ACC (OP[1]) >> 16); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfaclo */ +void +OP_1E02 () +{ + int16 tmp; + trace_input ("mvfaclo", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfc */ +void +OP_5200 () +{ + int16 tmp; + trace_input ("mvfc", OP_REG_OUTPUT, OP_CR, OP_VOID); + tmp = CREG (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvtacg */ +void +OP_1E41 () +{ + int64 tmp; + trace_input ("mvtacg", OP_REG, OP_ACCUM, OP_VOID); + tmp = ((ACC (OP[1]) & MASK32) + | ((int64)(GPR (OP[0]) & 0xff) << 32)); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtachi */ +void +OP_1E01 () +{ + uint64 tmp; + trace_input ("mvtachi", OP_REG, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]) & 0xffff; + tmp = ((SEXT16 (GPR (OP[0])) << 16 | tmp) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtaclo */ +void +OP_1E21 () +{ + int64 tmp; + trace_input ("mvtaclo", OP_REG, OP_ACCUM, OP_VOID); + tmp = ((SEXT16 (GPR (OP[0]))) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtc */ +void +OP_5600 () +{ + int16 tmp; + trace_input ("mvtc", OP_REG, OP_CR_OUTPUT, OP_VOID); + tmp = GPR (OP[0]); + tmp = SET_CREG (OP[1], tmp); + trace_output_16 (tmp); +} + +/* mvub */ +void +OP_5401 () +{ + int16 tmp; + trace_input ("mvub", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = (GPR (OP[1]) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* neg */ +void +OP_4605 () +{ + int16 tmp; + trace_input ("neg", OP_REG, OP_VOID, OP_VOID); + tmp = - GPR (OP[0]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* neg */ +void +OP_5605 () +{ + int64 tmp; + + trace_input ("neg", OP_ACCUM, OP_VOID, OP_VOID); + tmp = -SEXT40(ACC (OP[0])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + + +/* nop */ +void +OP_5E00 () +{ + trace_input ("nop", OP_VOID, OP_VOID, OP_VOID); + + ins_type_counters[ (int)State.ins_type ]--; /* don't count nops as normal instructions */ + switch (State.ins_type) + { + default: + ins_type_counters[ (int)INS_UNKNOWN ]++; + break; + + case INS_LEFT_PARALLEL: + /* Don't count a parallel op that includes a NOP as a true parallel op */ + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]--; + ins_type_counters[ (int)INS_RIGHT ]++; + ins_type_counters[ (int)INS_LEFT_NOPS ]++; + break; + + case INS_LEFT: + case INS_LEFT_COND_EXE: + ins_type_counters[ (int)INS_LEFT_NOPS ]++; + break; + + case INS_RIGHT_PARALLEL: + /* Don't count a parallel op that includes a NOP as a true parallel op */ + ins_type_counters[ (int)INS_LEFT_PARALLEL ]--; + ins_type_counters[ (int)INS_LEFT ]++; + ins_type_counters[ (int)INS_RIGHT_NOPS ]++; + break; + + case INS_RIGHT: + case INS_RIGHT_COND_EXE: + ins_type_counters[ (int)INS_RIGHT_NOPS ]++; + break; + } + + trace_output_void (); +} + +/* not */ +void +OP_4603 () +{ + int16 tmp; + trace_input ("not", OP_REG, OP_VOID, OP_VOID); + tmp = ~GPR (OP[0]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* or */ +void +OP_800 () +{ + int16 tmp; + trace_input ("or", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) | GPR (OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* or3 */ +void +OP_4000000 () +{ + int16 tmp; + trace_input ("or3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + tmp = (GPR (OP[1]) | OP[2]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* rac */ +void +OP_5201 () +{ + int64 tmp; + int shift = SEXT3 (OP[2]); + + trace_input ("rac", OP_DREG_OUTPUT, OP_ACCUM, OP_CONSTANT3); + if (OP[1] != 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, + "ERROR at PC 0x%x: instruction only valid for A0\n", + PC<<2); + State.exception = SIGILL; + } + + SET_PSW_F1 (PSW_F0); + tmp = SEXT56 ((ACC (0) << 16) | (ACC (1) & 0xffff)); + if (shift >=0) + tmp <<= shift; + else + tmp >>= -shift; + tmp += 0x8000; + tmp >>= 16; /* look at bits 0:43 */ + if (tmp > SEXT44 (SIGNED64 (0x0007fffffff))) + { + tmp = 0x7fffffff; + SET_PSW_F0 (1); + } + else if (tmp < SEXT44 (SIGNED64 (0xfff80000000))) + { + tmp = 0x80000000; + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* rachi */ +void +OP_4201 () +{ + signed64 tmp; + int shift = SEXT3 (OP[2]); + + trace_input ("rachi", OP_REG_OUTPUT, OP_ACCUM, OP_CONSTANT3); + SET_PSW_F1 (PSW_F0); + if (shift >=0) + tmp = SEXT40 (ACC (OP[1])) << shift; + else + tmp = SEXT40 (ACC (OP[1])) >> -shift; + tmp += 0x8000; + + if (tmp > SEXT44 (SIGNED64 (0x0007fffffff))) + { + tmp = 0x7fff; + SET_PSW_F0 (1); + } + else if (tmp < SEXT44 (SIGNED64 (0xfff80000000))) + { + tmp = 0x8000; + SET_PSW_F0 (1); + } + else + { + tmp = (tmp >> 16); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* rep */ +void +OP_27000000 () +{ + trace_input ("rep", OP_REG, OP_CONSTANT16, OP_VOID); + SET_RPT_S (PC + 1); + SET_RPT_E (PC + OP[1]); + SET_RPT_C (GPR (OP[0])); + SET_PSW_RP (1); + if (GPR (OP[0]) == 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep with count=0 is illegal.\n"); + State.exception = SIGILL; + } + if (OP[1] < 4) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep must include at least 4 instructions.\n"); + State.exception = SIGILL; + } + trace_output_void (); +} + +/* repi */ +void +OP_2F000000 () +{ + trace_input ("repi", OP_CONSTANT16, OP_CONSTANT16, OP_VOID); + SET_RPT_S (PC + 1); + SET_RPT_E (PC + OP[1]); + SET_RPT_C (OP[0]); + SET_PSW_RP (1); + if (OP[0] == 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi with count=0 is illegal.\n"); + State.exception = SIGILL; + } + if (OP[1] < 4) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi must include at least 4 instructions.\n"); + State.exception = SIGILL; + } + trace_output_void (); +} + +/* rtd */ +void +OP_5F60 () +{ + trace_input ("rtd", OP_VOID, OP_VOID, OP_VOID); + SET_CREG (PSW_CR, DPSW); + JMP(DPC); + trace_output_void (); +} + +/* rte */ +void +OP_5F40 () +{ + trace_input ("rte", OP_VOID, OP_VOID, OP_VOID); + SET_CREG (PSW_CR, BPSW); + JMP(BPC); + trace_output_void (); +} + +/* sac */ +void OP_5209 () +{ + int64 tmp; + + trace_input ("sac", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + + tmp = SEXT40(ACC (OP[1])); + + SET_PSW_F1 (PSW_F0); + + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = 0x80000000; + SET_PSW_F0 (1); + } + else + { + tmp = (tmp & MASK32); + SET_PSW_F0 (0); + } + + SET_GPR32 (OP[0], tmp); + + trace_output_40 (tmp); +} + +/* sachi */ +void +OP_4209 () +{ + int64 tmp; + + trace_input ("sachi", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + + tmp = SEXT40(ACC (OP[1])); + + SET_PSW_F1 (PSW_F0); + + if (tmp > SEXT40(MAX32)) + { + tmp = 0x7fff; + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = 0x8000; + SET_PSW_F0 (1); + } + else + { + tmp >>= 16; + SET_PSW_F0 (0); + } + + SET_GPR (OP[0], tmp); + + trace_output_16 (OP[0]); +} + +/* sadd */ +void +OP_1223 () +{ + int64 tmp; + + trace_input ("sadd", OP_ACCUM, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[0])) + (SEXT40(ACC (OP[1])) >> 16); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* setf0f */ +void +OP_4611 () +{ + int16 tmp; + trace_input ("setf0f", OP_REG_OUTPUT, OP_VOID, OP_VOID); + tmp = ((PSW_F0 == 0) ? 1 : 0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* setf0t */ +void +OP_4613 () +{ + int16 tmp; + trace_input ("setf0t", OP_REG_OUTPUT, OP_VOID, OP_VOID); + tmp = ((PSW_F0 == 1) ? 1 : 0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* slae */ +void +OP_3220 () +{ + int64 tmp; + int16 reg; + + trace_input ("slae", OP_ACCUM, OP_REG, OP_VOID); + + reg = SEXT16 (GPR (OP[1])); + + if (reg >= 17 || reg <= -17) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", reg); + State.exception = SIGILL; + return; + } + + tmp = SEXT40 (ACC (OP[0])); + + if (PSW_ST && (tmp < SEXT40 (MIN32) || tmp > SEXT40 (MAX32))) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: accumulator value 0x%.2x%.8lx out of range\n", ((int)(tmp >> 32) & 0xff), ((unsigned long) tmp) & 0xffffffff); + State.exception = SIGILL; + return; + } + + if (reg >= 0 && reg <= 16) + { + tmp = SEXT56 ((SEXT56 (tmp)) << (GPR (OP[1]))); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + } + else + { + tmp = (SEXT40 (ACC (OP[0]))) >> (-GPR (OP[1])); + } + + SET_ACC(OP[0], tmp); + + trace_output_40(tmp); +} + +/* sleep */ +void +OP_5FC0 () +{ + trace_input ("sleep", OP_VOID, OP_VOID, OP_VOID); + SET_PSW_IE (1); + trace_output_void (); +} + +/* sll */ +void +OP_2200 () +{ + int16 tmp; + trace_input ("sll", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) << (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sll */ +void +OP_3200 () +{ + int64 tmp; + trace_input ("sll", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + tmp = SEXT40 (ACC (OP[0])) << (GPR (OP[1]) & 31); + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } + + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* slli */ +void +OP_2201 () +{ + int16 tmp; + trace_input ("slli", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) << OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* slli */ +void +OP_3201 () +{ + int64 tmp; + + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("slli", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = SEXT40(ACC (OP[0])) << OP[1]; + + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* slx */ +void +OP_460B () +{ + int16 tmp; + trace_input ("slx", OP_REG, OP_VOID, OP_VOID); + tmp = ((GPR (OP[0]) << 1) | PSW_F0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sra */ +void +OP_2400 () +{ + int16 tmp; + trace_input ("sra", OP_REG, OP_REG, OP_VOID); + tmp = (((int16)(GPR (OP[0]))) >> (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sra */ +void +OP_3400 () +{ + trace_input ("sra", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + { + int64 tmp = ((SEXT40(ACC (OP[0])) >> (GPR (OP[1]) & 31)) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); + } + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } +} + +/* srai */ +void +OP_2401 () +{ + int16 tmp; + trace_input ("srai", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (((int16)(GPR (OP[0]))) >> OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srai */ +void +OP_3401 () +{ + int64 tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("srai", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = ((SEXT40(ACC (OP[0])) >> OP[1]) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* srl */ +void +OP_2000 () +{ + int16 tmp; + trace_input ("srl", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) >> (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srl */ +void +OP_3000 () +{ + trace_input ("srl", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + { + int64 tmp = ((uint64)((ACC (OP[0]) & MASK40) >> (GPR (OP[1]) & 31))); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); + } + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } + +} + +/* srli */ +void +OP_2001 () +{ + int16 tmp; + trace_input ("srli", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) >> OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srli */ +void +OP_3001 () +{ + int64 tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("srli", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = ((uint64)(ACC (OP[0]) & MASK40) >> OP[1]); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* srx */ +void +OP_4609 () +{ + uint16 tmp; + trace_input ("srx", OP_REG, OP_VOID, OP_VOID); + tmp = PSW_F0 << 15; + tmp = ((GPR (OP[0]) >> 1) | tmp); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* st */ +void +OP_34000000 () +{ + uint16 addr = OP[1] + GPR (OP[2]); + trace_input ("st", OP_REG, OP_MEMREF2, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + trace_output_void (); +} + +/* st */ +void +OP_6800 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st", OP_REG, OP_MEMREF, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + trace_output_void (); +} + +/* st */ +/* st Rsrc1,@-SP */ +void +OP_6C1F () +{ + uint16 addr = GPR (OP[1]) - 2; + trace_input ("st", OP_REG, OP_PREDEC, OP_VOID); + if (OP[1] != 15) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + State.exception = SIGILL; + return; + } + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + SET_GPR (OP[1], addr); + trace_output_void (); +} + +/* st */ +void +OP_6801 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st", OP_REG, OP_POSTINC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + INC_ADDR (OP[1], 2); + trace_output_void (); +} + +/* st */ +void +OP_6C01 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st", OP_REG, OP_POSTDEC, OP_VOID); + if ( OP[1] == 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n"); + State.exception = SIGILL; + return; + } + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + INC_ADDR (OP[1], -2); + trace_output_void (); +} + +/* st */ +void +OP_36010000 () +{ + uint16 addr = OP[1]; + trace_input ("st", OP_REG, OP_MEMREF3, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr, GPR (OP[0])); + trace_output_void (); +} + +/* st2w */ +void +OP_35000000 () +{ + uint16 addr = GPR (OP[2])+ OP[1]; + trace_input ("st2w", OP_DREG, OP_MEMREF2, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + trace_output_void (); +} + +/* st2w */ +void +OP_6A00 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + trace_output_void (); +} + +/* st2w */ +void +OP_6E1F () +{ + uint16 addr = GPR (OP[1]) - 4; + trace_input ("st2w", OP_DREG, OP_PREDEC, OP_VOID); + if ( OP[1] != 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + State.exception = SIGILL; + return; + } + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + SET_GPR (OP[1], addr); + trace_output_void (); +} + +/* st2w */ +void +OP_6A01 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + INC_ADDR (OP[1], 4); + trace_output_void (); +} + +/* st2w */ +void +OP_6E01 () +{ + uint16 addr = GPR (OP[1]); + trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID); + if ( OP[1] == 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n"); + State.exception = SIGILL; + return; + } + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + INC_ADDR (OP[1], -4); + trace_output_void (); +} + +/* st2w */ +void +OP_37010000 () +{ + uint16 addr = OP[1]; + trace_input ("st2w", OP_DREG, OP_MEMREF3, OP_VOID); + if ((addr & 1)) + { + State.exception = SIG_D10V_BUS; + State.pc_changed = 1; /* Don't increment the PC. */ + trace_output_void (); + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + trace_output_void (); +} + +/* stb */ +void +OP_3C000000 () +{ + trace_input ("stb", OP_REG, OP_MEMREF2, OP_VOID); + SB (GPR (OP[2]) + OP[1], GPR (OP[0])); + trace_output_void (); +} + +/* stb */ +void +OP_7800 () +{ + trace_input ("stb", OP_REG, OP_MEMREF, OP_VOID); + SB (GPR (OP[1]), GPR (OP[0])); + trace_output_void (); +} + +/* stop */ +void +OP_5FE0 () +{ + trace_input ("stop", OP_VOID, OP_VOID, OP_VOID); + State.exception = SIG_D10V_STOP; + trace_output_void (); +} + +/* sub */ +void +OP_0 () +{ + uint16 a = GPR (OP[0]); + uint16 b = GPR (OP[1]); + uint16 tmp = (a - b); + trace_input ("sub", OP_REG, OP_REG, OP_VOID); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits. */ + SET_PSW_C (a >= b); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sub */ +void +OP_1001 () +{ + int64 tmp; + + trace_input ("sub", OP_ACCUM, OP_DREG, OP_VOID); + tmp = SEXT40(ACC (OP[0])) - (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1)); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + + trace_output_40 (tmp); +} + +/* sub */ + +void +OP_1003 () +{ + int64 tmp; + + trace_input ("sub", OP_ACCUM, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[0])) - SEXT40(ACC (OP[1])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + + trace_output_40 (tmp); +} + +/* sub2w */ +void +OP_1000 () +{ + uint32 tmp, a, b; + + trace_input ("sub2w", OP_DREG, OP_DREG, OP_VOID); + a = (uint32)((GPR (OP[0]) << 16) | GPR (OP[0] + 1)); + b = (uint32)((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits */ + tmp = a - b; + SET_PSW_C (a >= b); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3 */ +void +OP_17000000 () +{ + int64 tmp; + + trace_input ("subac3", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + tmp = SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)) - SEXT40 (ACC (OP[2])); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3 */ +void +OP_17000002 () +{ + int64 tmp; + + trace_input ("subac3", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + tmp = SEXT40 (ACC (OP[1])) - SEXT40(ACC (OP[2])); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3s */ +void +OP_17001000 () +{ + int64 tmp; + + trace_input ("subac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + SET_PSW_F1 (PSW_F0); + tmp = SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)) - SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3s */ +void +OP_17001002 () +{ + int64 tmp; + + trace_input ("subac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + SET_PSW_F1 (PSW_F0); + tmp = SEXT40(ACC (OP[1])) - SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subi */ +void +OP_1 () +{ + unsigned tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("subi", OP_REG, OP_CONSTANT16, OP_VOID); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits. */ + /* since OP[1] is never <= 0, -OP[1] == ~OP[1]+1 can never overflow */ + tmp = ((unsigned)(unsigned16) GPR (OP[0]) + + (unsigned)(unsigned16) ( - OP[1])); + SET_PSW_C (tmp >= (1 << 16)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* trap */ +void +OP_5F00 () +{ + trace_input ("trap", OP_CONSTANT4, OP_VOID, OP_VOID); + trace_output_void (); + + switch (OP[0]) + { + default: +#if (DEBUG & DEBUG_TRAP) == 0 + { + uint16 vec = OP[0] + TRAP_VECTOR_START; + SET_BPC (PC + 1); + SET_BPSW (PSW); + SET_PSW (PSW & PSW_SM_BIT); + JMP (vec); + break; + } +#else /* if debugging use trap to print registers */ + { + int i; + static int first_time = 1; + + if (first_time) + { + first_time = 0; + (*d10v_callback->printf_filtered) (d10v_callback, "Trap # PC "); + for (i = 0; i < 16; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %sr%d", (i > 9) ? "" : " ", i); + (*d10v_callback->printf_filtered) (d10v_callback, " a0 a1 f0 f1 c\n"); + } + + (*d10v_callback->printf_filtered) (d10v_callback, "Trap %2d 0x%.4x:", (int)OP[0], (int)PC); + + for (i = 0; i < 16; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %.4x", (int) GPR (i)); + + for (i = 0; i < 2; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %.2x%.8lx", + ((int)(ACC (i) >> 32) & 0xff), + ((unsigned long) ACC (i)) & 0xffffffff); + + (*d10v_callback->printf_filtered) (d10v_callback, " %d %d %d\n", + PSW_F0 != 0, PSW_F1 != 0, PSW_C != 0); + (*d10v_callback->flush_stdout) (d10v_callback); + break; + } +#endif + case 15: /* new system call trap */ + /* Trap 15 is used for simulating low-level I/O */ + { + unsigned32 result = 0; + errno = 0; + +/* Registers passed to trap 0 */ + +#define FUNC GPR (4) /* function number */ +#define PARM1 GPR (0) /* optional parm 1 */ +#define PARM2 GPR (1) /* optional parm 2 */ +#define PARM3 GPR (2) /* optional parm 3 */ +#define PARM4 GPR (3) /* optional parm 3 */ + +/* Registers set by trap 0 */ + +#define RETVAL(X) do { result = (X); SET_GPR (0, result); } while (0) +#define RETVAL32(X) do { result = (X); SET_GPR (0, result >> 16); SET_GPR (1, result); } while (0) +#define RETERR(X) SET_GPR (4, (X)) /* return error code */ + +/* Turn a pointer in a register into a pointer into real memory. */ + +#define MEMPTR(x) ((char *)(dmem_addr(x))) + + switch (FUNC) + { +#if !defined(__GO32__) && !defined(_WIN32) + case TARGET_SYS_fork: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (fork ()); + trace_output_16 (result); + break; + +#define getpid() 47 + case TARGET_SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (getpid ()); + trace_output_16 (result); + break; + + case TARGET_SYS_kill: + trace_input ("", OP_R0, OP_R1, OP_VOID); + if (PARM1 == getpid ()) + { + trace_output_void (); + State.exception = PARM2; + } + else + { + int os_sig = -1; + switch (PARM2) + { +#ifdef SIGHUP + case 1: os_sig = SIGHUP; break; +#endif +#ifdef SIGINT + case 2: os_sig = SIGINT; break; +#endif +#ifdef SIGQUIT + case 3: os_sig = SIGQUIT; break; +#endif +#ifdef SIGILL + case 4: os_sig = SIGILL; break; +#endif +#ifdef SIGTRAP + case 5: os_sig = SIGTRAP; break; +#endif +#ifdef SIGABRT + case 6: os_sig = SIGABRT; break; +#elif defined(SIGIOT) + case 6: os_sig = SIGIOT; break; +#endif +#ifdef SIGEMT + case 7: os_sig = SIGEMT; break; +#endif +#ifdef SIGFPE + case 8: os_sig = SIGFPE; break; +#endif +#ifdef SIGKILL + case 9: os_sig = SIGKILL; break; +#endif +#ifdef SIGBUS + case 10: os_sig = SIGBUS; break; +#endif +#ifdef SIGSEGV + case 11: os_sig = SIGSEGV; break; +#endif +#ifdef SIGSYS + case 12: os_sig = SIGSYS; break; +#endif +#ifdef SIGPIPE + case 13: os_sig = SIGPIPE; break; +#endif +#ifdef SIGALRM + case 14: os_sig = SIGALRM; break; +#endif +#ifdef SIGTERM + case 15: os_sig = SIGTERM; break; +#endif +#ifdef SIGURG + case 16: os_sig = SIGURG; break; +#endif +#ifdef SIGSTOP + case 17: os_sig = SIGSTOP; break; +#endif +#ifdef SIGTSTP + case 18: os_sig = SIGTSTP; break; +#endif +#ifdef SIGCONT + case 19: os_sig = SIGCONT; break; +#endif +#ifdef SIGCHLD + case 20: os_sig = SIGCHLD; break; +#elif defined(SIGCLD) + case 20: os_sig = SIGCLD; break; +#endif +#ifdef SIGTTIN + case 21: os_sig = SIGTTIN; break; +#endif +#ifdef SIGTTOU + case 22: os_sig = SIGTTOU; break; +#endif +#ifdef SIGIO + case 23: os_sig = SIGIO; break; +#elif defined (SIGPOLL) + case 23: os_sig = SIGPOLL; break; +#endif +#ifdef SIGXCPU + case 24: os_sig = SIGXCPU; break; +#endif +#ifdef SIGXFSZ + case 25: os_sig = SIGXFSZ; break; +#endif +#ifdef SIGVTALRM + case 26: os_sig = SIGVTALRM; break; +#endif +#ifdef SIGPROF + case 27: os_sig = SIGPROF; break; +#endif +#ifdef SIGWINCH + case 28: os_sig = SIGWINCH; break; +#endif +#ifdef SIGLOST + case 29: os_sig = SIGLOST; break; +#endif +#ifdef SIGUSR1 + case 30: os_sig = SIGUSR1; break; +#endif +#ifdef SIGUSR2 + case 31: os_sig = SIGUSR2; break; +#endif + } + + if (os_sig == -1) + { + trace_output_void (); + (*d10v_callback->printf_filtered) (d10v_callback, "Unknown signal %d\n", PARM2); + (*d10v_callback->flush_stdout) (d10v_callback); + State.exception = SIGILL; + } + else + { + RETVAL (kill (PARM1, PARM2)); + trace_output_16 (result); + } + } + break; + + case TARGET_SYS_execve: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), + (char **)MEMPTR (PARM3))); + trace_output_16 (result); + break; + +#ifdef TARGET_SYS_execv + case TARGET_SYS_execv: + trace_input ("", OP_R0, OP_R1, OP_VOID); + RETVAL (execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL)); + trace_output_16 (result); + break; +#endif + + case TARGET_SYS_pipe: + { + reg_t buf; + int host_fd[2]; + + trace_input ("", OP_R0, OP_VOID, OP_VOID); + buf = PARM1; + RETVAL (pipe (host_fd)); + SW (buf, host_fd[0]); + buf += sizeof(uint16); + SW (buf, host_fd[1]); + trace_output_16 (result); + } + break; + +#if 0 +#ifdef TARGET_SYS_wait + case TARGET_SYS_wait: + { + int status; + trace_input ("", OP_R0, OP_VOID, OP_VOID); + RETVAL (wait (&status)); + if (PARM1) + SW (PARM1, status); + trace_output_16 (result); + } + break; +#endif +#endif +#else + case TARGET_SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (1); + trace_output_16 (result); + break; + + case TARGET_SYS_kill: + trace_input ("", OP_REG, OP_REG, OP_VOID); + trace_output_void (); + State.exception = PARM2; + break; +#endif + + case TARGET_SYS_read: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2), + PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_write: + trace_input ("", OP_R0, OP_R1, OP_R2); + if (PARM1 == 1) + RETVAL ((int)d10v_callback->write_stdout (d10v_callback, + MEMPTR (PARM2), PARM3)); + else + RETVAL ((int)d10v_callback->write (d10v_callback, PARM1, + MEMPTR (PARM2), PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_lseek: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL32 (d10v_callback->lseek (d10v_callback, PARM1, + ((((unsigned long) PARM2) << 16) + || (unsigned long) PARM3), + PARM4)); + trace_output_32 (result); + break; + + case TARGET_SYS_close: + trace_input ("", OP_R0, OP_VOID, OP_VOID); + RETVAL (d10v_callback->close (d10v_callback, PARM1)); + trace_output_16 (result); + break; + + case TARGET_SYS_open: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2)); + trace_output_16 (result); + break; + + case TARGET_SYS_exit: + trace_input ("", OP_R0, OP_VOID, OP_VOID); + State.exception = SIG_D10V_EXIT; + trace_output_void (); + break; + +#ifdef TARGET_SYS_stat + case TARGET_SYS_stat: + trace_input ("", OP_R0, OP_R1, OP_VOID); + /* stat system call */ + { + struct stat host_stat; + reg_t buf; + + RETVAL (stat (MEMPTR (PARM1), &host_stat)); + + buf = PARM2; + + /* The hard-coded offsets and sizes were determined by using + * the D10V compiler on a test program that used struct stat. + */ + SW (buf, host_stat.st_dev); + SW (buf+2, host_stat.st_ino); + SW (buf+4, host_stat.st_mode); + SW (buf+6, host_stat.st_nlink); + SW (buf+8, host_stat.st_uid); + SW (buf+10, host_stat.st_gid); + SW (buf+12, host_stat.st_rdev); + SLW (buf+16, host_stat.st_size); + SLW (buf+20, host_stat.st_atime); + SLW (buf+28, host_stat.st_mtime); + SLW (buf+36, host_stat.st_ctime); + } + trace_output_16 (result); + break; +#endif + + case TARGET_SYS_chown: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (chown (MEMPTR (PARM1), PARM2, PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_chmod: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (chmod (MEMPTR (PARM1), PARM2)); + trace_output_16 (result); + break; + +#if 0 +#ifdef TARGET_SYS_utime + case TARGET_SYS_utime: + trace_input ("", OP_R0, OP_R1, OP_R2); + /* Cast the second argument to void *, to avoid type mismatch + if a prototype is present. */ + RETVAL (utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2))); + trace_output_16 (result); + break; +#endif +#endif + +#if 0 +#ifdef TARGET_SYS_time + case TARGET_SYS_time: + trace_input ("
simops.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.