binutils-gdb/sim/cr16/cr16_sim.h
Joel Brobecker 61baf725ec update copyright year range in GDB files
This applies the second part of GDB's End of Year Procedure, which
updates the copyright year range in all of GDB's files.

gdb/ChangeLog:

        Update copyright year range in all GDB files.
2017-01-01 10:52:34 +04:00

430 lines
12 KiB
C

/* Simulation code for the CR16 processor.
Copyright (C) 2008-2017 Free Software Foundation, Inc.
Contributed by M Ranga Swami Reddy <MR.Swami.Reddy@nsc.com>
This file is part of GDB, the GNU debugger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include "ansidecl.h"
#include "gdb/callback.h"
#include "opcode/cr16.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 cr16_debug;
#include "gdb/remote-sim.h"
#include "sim-config.h"
#include "sim-types.h"
typedef unsigned8 uint8;
typedef signed8 int8;
typedef unsigned16 uint16;
typedef signed16 int16;
typedef unsigned32 uint32;
typedef signed32 int32;
typedef unsigned64 uint64;
typedef signed64 int64;
/* FIXME: CR16 defines */
typedef uint16 reg_t;
typedef uint32 creg_t;
struct simops
{
char mnimonic[12];
uint32 size;
uint32 mask;
uint32 opcode;
int format;
char fname[12];
void (*func)(SIM_DESC, SIM_CPU *);
int numops;
operand_desc operands[4];
};
enum _ins_type
{
INS_UNKNOWN, /* unknown instruction */
INS_NO_TYPE_INS,
INS_ARITH_INS,
INS_LD_STOR_INS,
INS_BRANCH_INS,
INS_ARITH_BYTE_INS,
INS_SHIFT_INS,
INS_BRANCH_NEQ_INS,
INS_STOR_IMM_INS,
INS_CSTBIT_INS,
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;
};
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; \
} \
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; \
} \
} \
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)
struct _state
{
creg_t regs[16]; /* general-purpose registers */
#define GPR(N) (State.regs[(N)] + 0)
#define SET_GPR(N,VAL) (State.regs[(N)] = (VAL))
#define GPR32(N) \
(N < 12) ? \
((((uint16) State.regs[(N) + 1]) << 16) | (uint16) State.regs[(N)]) \
: GPR (N)
#define SET_GPR32(N,VAL) do { \
if (N < 11) \
{ SET_GPR (N + 1, (VAL) >> 16); SET_GPR (N, ((VAL) & 0xffff));} \
else { if ( N == 11) \
{ SET_GPR (N + 1, ((GPR32 (12)) & 0xffff0000)|((VAL) >> 16)); \
SET_GPR (N, ((VAL) & 0xffff));} \
else SET_GPR (N, (VAL));} \
} while (0)
creg_t cregs[16]; /* control registers */
#define CREG(N) (State.cregs[(N)] + 0)
#define SET_CREG(N,VAL) move_to_cr (sd, cpu, (N), 0, (VAL), 0)
#define SET_HW_CREG(N,VAL) move_to_cr (sd, cpu, (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))
/* writeback info */
struct slot slot[NR_SLOTS];
int slot_nr;
/* trace data */
struct {
uint16 psw;
} trace;
int pc_changed;
/* NOTE: everything below this line is not reset by
sim_create_inferior() */
enum _ins_type ins_type;
} State;
extern uint32 OP[4];
extern uint32 sign_flag;
extern struct simops Simops[];
enum
{
PC_CR = 0,
BDS_CR = 1,
BSR_CR = 2,
DCR_CR = 3,
CAR0_CR = 5,
CAR1_CR = 7,
CFG_CR = 9,
PSR_CR = 10,
INTBASE_CR = 11,
ISP_CR = 13,
USP_CR = 15
};
enum
{
PSR_I_BIT = 0x0800,
PSR_P_BIT = 0x0400,
PSR_E_BIT = 0x0200,
PSR_N_BIT = 0x0080,
PSR_Z_BIT = 0x0040,
PSR_F_BIT = 0x0020,
PSR_U_BIT = 0x0008,
PSR_L_BIT = 0x0004,
PSR_T_BIT = 0x0002,
PSR_C_BIT = 0x0001
};
#define PSR CREG (PSR_CR)
#define SET_PSR(VAL) SET_CREG (PSR_CR, (VAL))
#define SET_HW_PSR(VAL) SET_HW_CREG (PSR_CR, (VAL))
#define SET_PSR_BIT(MASK,VAL) move_to_cr (sd, cpu, PSR_CR, ~((creg_t) MASK), (VAL) ? (MASK) : 0, 1)
#define PSR_SM ((PSR & PSR_SM_BIT) != 0)
#define SET_PSR_SM(VAL) SET_PSR_BIT (PSR_SM_BIT, (VAL))
#define PSR_I ((PSR & PSR_I_BIT) != 0)
#define SET_PSR_I(VAL) SET_PSR_BIT (PSR_I_BIT, (VAL))
#define PSR_DB ((PSR & PSR_DB_BIT) != 0)
#define SET_PSR_DB(VAL) SET_PSR_BIT (PSR_DB_BIT, (VAL))
#define PSR_P ((PSR & PSR_P_BIT) != 0)
#define SET_PSR_P(VAL) SET_PSR_BIT (PSR_P_BIT, (VAL))
#define PSR_E ((PSR & PSR_E_BIT) != 0)
#define SET_PSR_E(VAL) SET_PSR_BIT (PSR_E_BIT, (VAL))
#define PSR_N ((PSR & PSR_N_BIT) != 0)
#define SET_PSR_N(VAL) SET_PSR_BIT (PSR_N_BIT, (VAL))
#define PSR_Z ((PSR & PSR_Z_BIT) != 0)
#define SET_PSR_Z(VAL) SET_PSR_BIT (PSR_Z_BIT, (VAL))
#define PSR_F ((PSR & PSR_F_BIT) != 0)
#define SET_PSR_F(VAL) SET_PSR_BIT (PSR_F_BIT, (VAL))
#define PSR_U ((PSR & PSR_U_BIT) != 0)
#define SET_PSR_U(VAL) SET_PSR_BIT (PSR_U_BIT, (VAL))
#define PSR_L ((PSR & PSR_L_BIT) != 0)
#define SET_PSR_L(VAL) SET_PSR_BIT (PSR_L_BIT, (VAL))
#define PSR_T ((PSR & PSR_T_BIT) != 0)
#define SET_PSR_T(VAL) SET_PSR_BIT (PSR_T_BIT, (VAL))
#define PSR_C ((PSR & PSR_C_BIT) != 0)
#define SET_PSR_C(VAL) SET_PSR_BIT (PSR_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 SET_PC(VAL) (State.cregs[PC_CR] = (VAL))
#define BPSR CREG (BPSR_CR)
#define SET_BPSR(VAL) SET_CREG (BPSR_CR, (VAL))
#define BPC CREG (BPC_CR)
#define SET_BPC(VAL) SET_CREG (BPC_CR, (VAL))
#define DPSR CREG (DPSR_CR)
#define SET_DPSR(VAL) SET_CREG (DPSR_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_CR16_STOP -1
#define SIG_CR16_EXIT -2
#define SIG_CR16_BUS -3
#define SIG_CR16_IAD -4
/* TODO: Resolve conflicts with common headers. */
#undef SEXT8
#undef SEXT16
#undef SEXT32
#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 24-bit number */
#define SEXT24(x) ((((x)&0xffffff)^(~0x7fffff))+0x800000)
/* sign-extend a 32-bit number */
#define SEXT32(x) ((((x)&0xffffffff)^(~0x7fffffff))+0x80000000)
#define SB(addr, data) sim_core_write_1 (cpu, PC, read_map, addr, data)
#define RB(addr) sim_core_read_1 (cpu, PC, read_map, addr)
#define SW(addr, data) sim_core_write_unaligned_2 (cpu, PC, read_map, addr, data)
#define RW(addr) sim_core_read_unaligned_2 (cpu, PC, read_map, addr)
#define SLW(addr, data) sim_core_write_unaligned_4 (cpu, PC, read_map, addr, data)
/* Yes, this is as whacked as it looks. The sim currently reads little endian
for 16 bits, but then merge them like big endian to get 32 bits. */
static inline uint32 get_longword (SIM_CPU *cpu, address_word addr)
{
return (RW (addr) << 16) | RW (addr + 2);
}
#define RLW(addr) get_longword (cpu, addr)
#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
#define INT_VECTOR_START 0xFFFE00 /*maskable interrupt - mapped to ICU */
#define NMI_VECTOR_START 0xFFFF00 /*non-maskable interrupt;for observability*/
#define ISE_VECTOR_START 0xFFFC00 /*in-system emulation trap */
#define ADBG_VECTOR_START 0xFFFC02 /*alternate debug trap */
#define ATRC_VECTOR_START 0xFFFC0C /*alternate trace trap */
#define ABPT_VECTOR_START 0xFFFC0E /*alternate break point trap */
/* 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 PSR_HW_P, a VAL intended for
PSR is masked for zero bits. */
extern creg_t move_to_cr (SIM_DESC, SIM_CPU *, int cr, creg_t mask, creg_t val, int psw_hw_p);
#ifndef SIGTRAP
#define SIGTRAP 5
#endif
/* Special purpose trap */
#define TRAP_BREAKPOINT 8