/* Simulation code for the CR16 processor.
Copyright (C) 2008-2014 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 <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "cr16_sim.h"
#include "simops.h"
#include "targ-vals.h"
extern char *strrchr ();
enum op_types {
OP_VOID,
OP_CONSTANT3,
OP_UCONSTANT3,
OP_CONSTANT4,
OP_CONSTANT4_1,
OP_CONSTANT5,
OP_CONSTANT6,
OP_CONSTANT16,
OP_UCONSTANT16,
OP_CONSTANT20,
OP_UCONSTANT20,
OP_CONSTANT32,
OP_UCONSTANT32,
OP_MEMREF,
OP_MEMREF2,
OP_MEMREF3,
OP_DISP5,
OP_DISP17,
OP_DISP25,
OP_DISPE9,
//OP_ABS20,
OP_ABS20_OUTPUT,
//OP_ABS24,
OP_ABS24_OUTPUT,
OP_R_BASE_DISPS16,
OP_R_BASE_DISP20,
OP_R_BASE_DISPS20,
OP_R_BASE_DISPE20,
OP_RP_BASE_DISPE0,
OP_RP_BASE_DISP4,
OP_RP_BASE_DISPE4,
OP_RP_BASE_DISP14,
OP_RP_BASE_DISP16,
OP_RP_BASE_DISP20,
OP_RP_BASE_DISPS20,
OP_RP_BASE_DISPE20,
OP_R_INDEX7_ABS20,
OP_R_INDEX8_ABS20,
OP_RP_INDEX_DISP0,
OP_RP_INDEX_DISP14,
OP_RP_INDEX_DISP20,
OP_RP_INDEX_DISPS20,
OP_REG,
OP_REGP,
OP_PROC_REG,
OP_PROC_REGP,
OP_COND,
OP_RA
};
enum {
PSR_MASK = (PSR_I_BIT
| PSR_P_BIT
| PSR_E_BIT
| PSR_N_BIT
| PSR_Z_BIT
| PSR_F_BIT
| PSR_U_BIT
| PSR_L_BIT
| PSR_T_BIT
| PSR_C_BIT),
/* The following bits in the PSR _can't_ be set by instructions such
as mvtc. */
PSR_HW_MASK = (PSR_MASK)
};
/* cond Code Condition True State
* EQ Equal Z flag is 1
* NE Not Equal Z flag is 0
* CS Carry Set C flag is 1
* CC Carry Clear C flag is 0
* HI Higher L flag is 1
* LS Lower or Same L flag is 0
* GT Greater Than N flag is 1
* LE Less Than or Equal To N flag is 0
* FS Flag Set F flag is 1
* FC Flag Clear F flag is 0
* LO Lower Z and L flags are 0
* HS Higher or Same Z or L flag is 1
* LT Less Than Z and N flags are 0
* GE Greater Than or Equal To Z or N flag is 1. */
int cond_stat(int cc)
{
switch (cc)
{
case 0: return PSR_Z; break;
case 1: return !PSR_Z; break;
case 2: return PSR_C; break;
case 3: return !PSR_C; break;
case 4: return PSR_L; break;
case 5: return !PSR_L; break;
case 6: return PSR_N; break;
case 7: return !PSR_N; break;
case 8: return PSR_F; break;
case 9: return !PSR_F; break;
case 10: return !PSR_Z && !PSR_L; break;
case 11: return PSR_Z || PSR_L; break;
case 12: return !PSR_Z && !PSR_N; break;
case 13: return PSR_Z || PSR_N; break;
case 14: return 1; break; /*ALWAYS. */
default:
// case NEVER: return false; break;
//case NO_COND_CODE:
//panic("Shouldn't have NO_COND_CODE in an actual instruction!");
return 0; break;
}
return 0;
}
creg_t
move_to_cr (int cr, creg_t mask, creg_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 PSR_CR:
if (psw_hw_p)
val &= PSR_HW_MASK;
#if 0
else
val &= PSR_MASK;
(*cr16_callback->printf_filtered)
(cr16_callback,
"ERROR at PC 0x%x: ST can only be set when FX is set.\n", PC);
State.exception = SIGILL;
#endif
/* keep an up-to-date psw around for tracing. */
State.trace.psw = (State.trace.psw & mask) | val;
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;
}
|