This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
RFA: Add support for Cirrus EP9312
- From: Nick Clifton <nickc at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: 10 Feb 2003 12:13:06 +0000
- Subject: RFA: Add support for Cirrus EP9312
Hi Guys,
May I have permission to apply the following patch ?
It adds support for Cirrus's EP9312 chip, an ARM variant with their
own floating point co-processor called the Maverick.
Cheers
Nick
gdb/ChangeLog
2003-02-10 Nick Clifton <nickc@redhat.com>
* Contribute support for Cirrus Maverick ARM co-processor:
2000-06-02 Andrew Cagney <cagney@b1.cygnus.com>
* remote-rdi.c (arm_rdi_fetch_registers): Add #ifdef
COPRO_REGNUM. Only return those registers when COPRO is
defined.
2000-05-30 Jeff Holcomb <jeffh@cygnus.com>
* configure.tgt: Add ep9312-elf target for the Cirrus DSP.
* config/arm/cirrus.mt: New.
* config/arm/tm-cirrus.h: Ditto.
Fri May 12 16:20:51 2000 glen mccready <gkm@pobox.com>
* arm-tdep.c, remote-rdi.c, config/arm/tm-arm.h:
Cirrus DSP coprocessor modifications.
include/gdb/ChangeLog
2003-02-10 Nick Clifton <nickc@redhat.com>
* sim-arm.h (sim_arm_regs): Add Maverick co-processor
registers.
sim/arm/ChangeLog
2003-02-10 Nick Clifton <nickc@redhat.com>
* Contribute support for Cirrus Maverick ARM co-processor,
written by Aldy Hernandez <aldyh@redhat.com> and
Andrew Cagney <cagney@redhat.com>:
* maverick.c: New file: Support for Maverick floating point
co-processor.
* Makefile.in: Add maverick.o target.
* configure.in (COPRO): Add maverick.o.
* configure: Regenerate.
* armcopro.c (ARMul_CoProInit): Only initialise co-processors
available on target processor. Add code to initialse Maverick
co-processor support code.
* armdefs.h (ARMul_state): Add is_ep9312 field.
(ARM_ep9312_Prop): Define.
* armemu.h: Add prototypes for Maverick co-processor
functions.
* arminit.c (ARMul_SelectProcessor): Initialise the
co-processor support once the chip has been selected.
* wrapper.c: Add support for Maverick co-processor.
(init): Do not call ARMul_CoProInit. Delays this until the
chip has been selected.
Index: gdb/arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.98
diff -c -3 -p -w -r1.98 arm-tdep.c
*** gdb/arm-tdep.c 3 Feb 2003 20:03:00 -0000 1.98
--- gdb/arm-tdep.c 10 Feb 2003 11:52:22 -0000
*************** static char * arm_register_name_strings[
*** 115,121 ****
"r12", "sp", "lr", "pc", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
! "fps", "cpsr" }; /* 24 25 */
static char **arm_register_names = arm_register_name_strings;
/* Valid register name flavors. */
--- 115,129 ----
"r12", "sp", "lr", "pc", /* 12 13 14 15 */
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
! "fps", "cpsr", /* 24 25 */
! "cr1", "cr2", "cr3", "cr4", /* 26 27 28 29 */
! "cr5", "cr6", "cr7", "cr8", /* 30 31 32 33 */
! "cr9", "cr10","cr11","cr12", /* 34 35 36 37 */
! "cr13","cr14","cr15","cr16", /* 38 39 40 41 */
! "dspsc" /* 42 */
! /* There are also 4 internal accumulators on the
! chip that could/should be fetchable/settable. */
! };
static char **arm_register_names = arm_register_name_strings;
/* Valid register name flavors. */
*************** set_disassembly_flavor (void)
*** 2613,2618 ****
--- 2621,2630 ----
/* Fill our copy. */
for (j = 0; j < numregs; j++)
arm_register_names[j] = (char *) regnames[j];
+
+ /* GKM - unfortunate that this swapping of names couldn't have included
+ the cirrus dsp registers since they can flip names depending on the
+ opcode and what's stored in them. */
/* Adjust case. */
if (isupper (*regnames[ARM_PC_REGNUM]))
Index: gdb/configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.98
diff -c -3 -p -w -r1.98 configure.tgt
*** gdb/configure.tgt 5 Feb 2003 23:14:47 -0000 1.98
--- gdb/configure.tgt 10 Feb 2003 11:52:22 -0000
*************** arm*-*-* | thumb*-*-* | strongarm*-*-*)
*** 55,60 ****
--- 55,63 ----
gdb_target=embed
configdirs="$configdirs rdi-share"
;;
+ ep9312-*-*) gdb_target=cirrus
+ configdirs="$configdirs rdi-share"
+ ;;
xscale-*-*) gdb_target=embed
configdirs="$configdirs rdi-share"
;;
Index: gdb/remote-rdi.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-rdi.c,v
retrieving revision 1.25
diff -c -3 -p -w -r1.25 remote-rdi.c
*** gdb/remote-rdi.c 2 Nov 2002 14:59:10 -0000 1.25
--- gdb/remote-rdi.c 10 Feb 2003 11:52:24 -0000
*************** arm_rdi_fetch_registers (int regno)
*** 548,553 ****
--- 548,569 ----
store_unsigned_integer (cookedreg, 4, rawregs[15]);
supply_register (ARM_PS_REGNUM, (char *) cookedreg);
arm_rdi_fetch_registers (ARM_PC_REGNUM);
+
+ #ifdef COPRO_REGNUM
+ for (regno = COPRO_REGNUM; regno <= NUM_REGS; regno++)
+ {
+ /* This code has not been tested; we don't have hardware. */
+ char regval[8];
+ unsigned long mask;
+
+ mask = 1 << regno;
+ angel_RDI_CPread (0, mask, (ARMword *) & regval);
+ if (rslt)
+ printf_filtered ("RDI_CPread: %s\n", rdi_error_message (rslt));
+
+ supply_register (regno, (char *) regval);
+ }
+ #endif
}
else
{
*************** arm_rdi_fetch_registers (int regno)
*** 557,562 ****
--- 573,594 ----
rdi_regmask = RDIReg_CPSR;
else if (regno < 0 || regno > 15)
{
+ #ifdef COPRO_REGNUM
+ if (regno >= COPRO_REGNUM && regno <= NUM_REGS)
+ {
+ /* This code has not been tested; we don't have hardware. */
+ char regval[8];
+ unsigned long mask;
+
+ mask = 1 << regno;
+ rslt = angel_RDI_CPread (0, mask, (ARMword *) & regval);
+ if (rslt)
+ printf_filtered ("RDI_CPread: %s\n", rdi_error_message (rslt));
+
+ supply_register (regno, (char *) regval);
+ return;
+ }
+ #endif
rawreg = 0;
supply_register (regno, (char *) &rawreg);
return;
*************** arm_rdi_store_registers (int regno)
*** 598,603 ****
--- 630,652 ----
}
else
{
+ #ifdef COPRO_REGNUM
+ if (regno >= COPRO_REGNUM && regno <= NUM_REGS)
+ {
+ /* This code has not been tested; we don't have hardware. */
+ char regval[8];
+ unsigned long mask;
+
+ mask = 1 << regno;
+ deprecated_read_register_gen (regno, (char *) regval);
+ /* byte ordering? */
+ rslt = angel_RDI_CPwrite (0, mask, (ARMword *) regval);
+ if (rslt)
+ printf_filtered ("RDI_CPwrite: %s\n", rdi_error_message (rslt));
+
+ return;
+ }
+ #endif
deprecated_read_register_gen (regno, (char *) rawreg);
/* RDI manipulates data in host byte order, so convert now. */
store_unsigned_integer (rawerreg, 4, rawreg[0]);
*** /dev/null Sat Oct 19 15:41:17 2002
--- gdb/config/arm/cirrus.mt Sat Feb 8 11:28:47 2003
***************
*** 0 ****
--- 1,7 ----
+ # Target: ARM embedded system
+ TDEPFILES= arm-tdep.o remote-rdp.o remote-rdi.o
+ TDEPLIBS= rdi-share/libangsd.a
+ TM_FILE= tm-cirrus.h
+
+ SIM_OBS = remote-sim.o
+ SIM = ../sim/arm/libsim.a
*** /dev/null Sat Oct 19 15:41:17 2002
--- gdb/config/arm/tm-cirrus.h Sat Feb 8 11:30:04 2003
***************
*** 0 ****
--- 1,89 ----
+ /* Definitions to target GDB for Cirrus
+ Copyright 2003 Free Software Foundation, Inc.
+
+ Contributed by Red Hat.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #ifndef TM_CIRRUS_H
+ #define TM_CIRRUS_H
+
+ #include "arm/tm-embed.h"
+
+ #undef TARGET_DOUBLE_FORMAT
+ #define TARGET_DOUBLE_FORMAT (target_byte_order == BFD_ENDIAN_BIG \
+ ? & floatformat_ieee_double_big \
+ : & floatformat_ieee_double_little)
+
+ /* Co-processors can be used directly with the ARM chips; this should
+ define the size of the copros registers. */
+
+ #define COPRO_REGISTER_SIZE 8
+
+ #define COPRO_REGISTER_TYPE builtin_type_int64
+
+ #define NUM_COPRO_REGS (16 + 1)
+
+ #undef NUM_REGS
+ #define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SREGS + NUM_COPRO_REGS)
+
+ #define COPRO_REGNUM 26 /* Start listing coprocessor registers... */
+ #define DSPSC_REGNUM 42
+
+ #undef REGISTER_BYTES
+ #define REGISTER_BYTES ((NUM_GREGS * REGISTER_SIZE) + \
+ (NUM_FREGS * FP_REGISTER_RAW_SIZE) + \
+ (NUM_SREGS * STATUS_REGISTER_SIZE) + \
+ (NUM_COPRO_REGS * COPRO_REGISTER_SIZE))
+
+ #undef REGISTER_BYTE
+ #define REGISTER_BYTE(N) \
+ ((N) < F0_REGNUM \
+ ? (N) * REGISTER_SIZE \
+ : ((N) < PS_REGNUM \
+ ? (NUM_GREGS * REGISTER_SIZE + ((N) - F0_REGNUM) * \
+ FP_REGISTER_RAW_SIZE) \
+ : ((N) < COPRO_REGNUM \
+ ? (NUM_GREGS * REGISTER_SIZE + NUM_FREGS * \
+ FP_REGISTER_RAW_SIZE + ((N) - FPS_REGNUM) * \
+ STATUS_REGISTER_SIZE) \
+ : (NUM_GREGS * REGISTER_SIZE + NUM_FREGS * \
+ FP_REGISTER_RAW_SIZE + ((N) - FPS_REGNUM) * \
+ STATUS_REGISTER_SIZE + ((N) - COPRO_REGNUM) * \
+ COPRO_REGISTER_SIZE))))
+
+ #undef REGISTER_RAW_SIZE
+ #define REGISTER_RAW_SIZE(N) \
+ ((N) < F0_REGNUM ? REGISTER_SIZE : \
+ (N) < FPS_REGNUM ? FP_REGISTER_RAW_SIZE : \
+ (N) < COPRO_REGNUM ? STATUS_REGISTER_SIZE : COPRO_REGISTER_SIZE)
+
+ #undef REGISTER_VIRTUAL_SIZE
+ #define REGISTER_VIRTUAL_SIZE(N) \
+ ((N) < F0_REGNUM ? REGISTER_SIZE : \
+ (N) < FPS_REGNUM ? FP_REGISTER_VIRTUAL_SIZE : \
+ (N) < COPRO_REGNUM ? STATUS_REGISTER_SIZE : COPRO_REGISTER_SIZE)
+
+ #undef REGISTER_VIRTUAL_TYPE
+ #define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - F0_REGNUM) < NUM_FREGS \
+ ? builtin_type_double : \
+ ((unsigned)(N) < COPRO_REGNUM) \
+ ? builtin_type_int : COPRO_REGISTER_TYPE)
+
+ #endif /* TM_CIRRUS_H */
Index: include/gdb/sim-arm.h
===================================================================
RCS file: /cvs/src/src/include/gdb/sim-arm.h,v
retrieving revision 1.2
diff -c -3 -p -w -r1.2 sim-arm.h
*** include/gdb/sim-arm.h 15 Jun 2002 22:49:38 -0000 1.2
--- include/gdb/sim-arm.h 10 Feb 2003 11:52:15 -0000
*************** enum sim_arm_regs
*** 55,61 ****
SIM_ARM_FP6_REGNUM,
SIM_ARM_FP7_REGNUM,
SIM_ARM_FPS_REGNUM,
! SIM_ARM_PS_REGNUM
};
#ifdef __cplusplus
--- 55,78 ----
SIM_ARM_FP6_REGNUM,
SIM_ARM_FP7_REGNUM,
SIM_ARM_FPS_REGNUM,
! SIM_ARM_PS_REGNUM,
! SIM_ARM_MAVERIC_COP0R0_REGNUM,
! SIM_ARM_MAVERIC_COP0R1_REGNUM,
! SIM_ARM_MAVERIC_COP0R2_REGNUM,
! SIM_ARM_MAVERIC_COP0R3_REGNUM,
! SIM_ARM_MAVERIC_COP0R4_REGNUM,
! SIM_ARM_MAVERIC_COP0R5_REGNUM,
! SIM_ARM_MAVERIC_COP0R6_REGNUM,
! SIM_ARM_MAVERIC_COP0R7_REGNUM,
! SIM_ARM_MAVERIC_COP0R8_REGNUM,
! SIM_ARM_MAVERIC_COP0R9_REGNUM,
! SIM_ARM_MAVERIC_COP0R10_REGNUM,
! SIM_ARM_MAVERIC_COP0R11_REGNUM,
! SIM_ARM_MAVERIC_COP0R12_REGNUM,
! SIM_ARM_MAVERIC_COP0R13_REGNUM,
! SIM_ARM_MAVERIC_COP0R14_REGNUM,
! SIM_ARM_MAVERIC_COP0R15_REGNUM,
! SIM_ARM_MAVERIC_DSPSC_REGNUM
};
#ifdef __cplusplus
Index: sim/arm/Makefile.in
===================================================================
RCS file: /cvs/src/src/sim/arm/Makefile.in,v
retrieving revision 1.5
diff -c -3 -p -w -r1.5 Makefile.in
*** sim/arm/Makefile.in 12 Jun 2002 21:19:43 -0000 1.5
--- sim/arm/Makefile.in 10 Feb 2003 11:52:08 -0000
*************** SIM_OBJS = armemu26.o armemu32.o arminit
*** 31,36 ****
--- 31,37 ----
armos.o: armos.c armdefs.h armos.h armfpe.h
armcopro.o: armcopro.c armdefs.h
+ maverick.o: maverick.c armdefs.h
armemu26.o: armemu.c armdefs.h armemu.h
$(CC) -c $(srcdir)/armemu.c -o armemu26.o $(ALL_CFLAGS)
Index: sim/arm/armcopro.c
===================================================================
RCS file: /cvs/src/src/sim/arm/armcopro.c,v
retrieving revision 1.10
diff -c -3 -p -w -r1.10 armcopro.c
*** sim/arm/armcopro.c 29 May 2002 19:01:36 -0000 1.10
--- sim/arm/armcopro.c 10 Feb 2003 11:52:08 -0000
*************** ARMul_CoProInit (ARMul_State * state)
*** 1328,1342 ****
MRC routine, MCR routine,
CDP routine,
Read Reg routine, Write Reg routine). */
ARMul_CoProAttach (state, 4, NULL, NULL,
ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL,
NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL);
! ARMul_CoProAttach (state, 15, MMUInit, NULL,
! NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
!
ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
--- 1328,1353 ----
MRC routine, MCR routine,
CDP routine,
Read Reg routine, Write Reg routine). */
+ if (state->is_ep9312)
+ {
+ ARMul_CoProAttach (state, 4, NULL, NULL,
+ DSPLDC4, DSPSTC4, DSPMRC4, DSPMCR4, DSPCDP4, NULL, NULL);
+ ARMul_CoProAttach (state, 5, NULL, NULL,
+ DSPLDC5, DSPSTC5, DSPMRC5, DSPMCR5, DSPCDP5, NULL, NULL);
+ ARMul_CoProAttach (state, 6, NULL, NULL,
+ NULL, NULL, DSPMRC6, DSPMCR6, DSPCDP6, NULL, NULL);
+ }
+ else
+ {
ARMul_CoProAttach (state, 4, NULL, NULL,
ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL,
NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL);
+ }
! if (state->is_XScale)
! {
ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
*************** ARMul_CoProInit (ARMul_State * state)
*** 1350,1355 ****
--- 1361,1372 ----
ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL,
NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR,
NULL, XScale_cp15_read_reg, XScale_cp15_write_reg);
+ }
+ else
+ {
+ ARMul_CoProAttach (state, 15, MMUInit, NULL,
+ NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
+ }
/* No handlers below here. */
Index: sim/arm/armdefs.h
===================================================================
RCS file: /cvs/src/src/sim/arm/armdefs.h,v
retrieving revision 1.9
diff -c -3 -p -w -r1.9 armdefs.h
*** sim/arm/armdefs.h 18 Apr 2001 16:39:37 -0000 1.9
--- sim/arm/armdefs.h 10 Feb 2003 11:52:09 -0000
*************** struct ARMul_State
*** 135,140 ****
--- 135,141 ----
unsigned is_v5; /* Are we emulating a v5 architecture ? */
unsigned is_v5e; /* Are we emulating a v5e architecture ? */
unsigned is_XScale; /* Are we emulating an XScale architecture ? */
+ unsigned is_ep9312; /* Are we emulating a Cirrus Maverick co-processor ? */
unsigned verbose; /* Print various messages like the banner */
};
*************** struct ARMul_State
*** 162,167 ****
--- 163,169 ----
#define ARM_v5_Prop 0x80
#define ARM_v5e_Prop 0x100
#define ARM_XScale_Prop 0x200
+ #define ARM_ep9312_Prop 0x400
/***************************************************************************\
* Macros to extract instruction fields *
Index: sim/arm/armemu.h
===================================================================
RCS file: /cvs/src/src/sim/arm/armemu.h,v
retrieving revision 1.14
diff -c -3 -p -w -r1.14 armemu.h
*** sim/arm/armemu.h 10 Jan 2002 11:14:57 -0000 1.14
--- sim/arm/armemu.h 10 Feb 2003 11:52:09 -0000
*************** extern void ARMul_CoProAttach (ARM
*** 530,532 ****
--- 530,548 ----
extern void ARMul_CoProDetach (ARMul_State *, unsigned);
extern ARMword read_cp15_reg (unsigned, unsigned, unsigned);
+ extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword);
+ extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword);
+ extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *);
+ extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *);
+ extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword);
+ extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword);
+ extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *);
+ extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword);
+ extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *);
+ extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword);
+ extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword);
+ extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *);
+ extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword);
Index: sim/arm/arminit.c
===================================================================
RCS file: /cvs/src/src/sim/arm/arminit.c,v
retrieving revision 1.8
diff -c -3 -p -w -r1.8 arminit.c
*** sim/arm/arminit.c 10 Jan 2002 11:14:57 -0000 1.8
--- sim/arm/arminit.c 10 Feb 2003 11:52:10 -0000
*************** ARMul_SelectProcessor (ARMul_State * sta
*** 157,162 ****
--- 157,167 ----
state->is_v5 = (properties & ARM_v5_Prop) ? HIGH : LOW;
state->is_v5e = (properties & ARM_v5e_Prop) ? HIGH : LOW;
state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW;
+ state->is_ep9312 = (properties & ARM_ep9312_Prop) ? HIGH : LOW;
+
+ /* Only initialse the coprocessor support once we
+ know what kind of chip we are dealing with. */
+ ARMul_CoProInit (state);
}
/***************************************************************************\
Index: sim/arm/configure.in
===================================================================
RCS file: /cvs/src/src/sim/arm/configure.in,v
retrieving revision 1.2
diff -c -3 -p -w -r1.2 configure.in
*** sim/arm/configure.in 30 May 2000 17:13:37 -0000 1.2
--- sim/arm/configure.in 10 Feb 2003 11:52:13 -0000
*************** SIM_AC_COMMON
*** 7,13 ****
AC_CHECK_HEADERS(unistd.h)
! COPRO=armcopro.o
AC_SUBST(COPRO)
SIM_AC_OUTPUT
--- 7,14 ----
AC_CHECK_HEADERS(unistd.h)
! COPRO="armcopro.o maverick.o"
!
AC_SUBST(COPRO)
SIM_AC_OUTPUT
Index: sim/arm/wrapper.c
===================================================================
RCS file: /cvs/src/src/sim/arm/wrapper.c,v
retrieving revision 1.23
diff -c -3 -p -w -r1.23 wrapper.c
*** sim/arm/wrapper.c 27 Sep 2002 23:57:50 -0000 1.23
--- sim/arm/wrapper.c 10 Feb 2003 11:52:13 -0000
*************** static int big_endian;
*** 59,64 ****
--- 59,96 ----
int stop_simulator;
+ /* Cirrus DSP registers.
+
+ We need to define these registers outside of maverick.c because
+ maverick.c might not be linked in unless --target=arm9e-* in which
+ case wrapper.c will not compile because it tries to access Cirrus
+ registers. This should all go away once we get the Cirrus and ARM
+ Coprocessor to coexist in armcopro.c-- aldyh. */
+
+ struct maverick_regs
+ {
+ union
+ {
+ int i;
+ float f;
+ } upper;
+
+ union
+ {
+ int i;
+ float f;
+ } lower;
+ };
+
+ union maverick_acc_regs
+ {
+ long double ld; /* Acc registers are 72-bits. */
+ };
+
+ struct maverick_regs DSPregs[16];
+ union maverick_acc_regs DSPacc[4];
+ ARMword DSPsc;
+
static void
init ()
{
*************** init ()
*** 71,77 ****
state->bigendSig = (big_endian ? HIGH : LOW);
ARMul_MemoryInit (state, mem_size);
ARMul_OSInit (state);
- ARMul_CoProInit (state);
state->verbose = verbosity;
done = 1;
}
--- 103,108 ----
*************** sim_create_inferior (sd, abfd, argv, env
*** 250,255 ****
--- 281,290 ----
}
/* Otherwise drop through. */
+ case bfd_mach_arm_ep9312:
+ ARMul_SelectProcessor (state, ARM_v4_Prop | ARM_ep9312_Prop);
+ break;
+
case bfd_mach_arm_5T:
ARMul_SelectProcessor (state, ARM_v5_Prop);
break;
*************** sim_store_register (sd, rn, memory, leng
*** 422,427 ****
--- 457,486 ----
ARMul_CPSRAltered (state);
break;
+ case SIM_ARM_MAVERIC_COP0R0_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R1_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R2_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R3_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R4_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R5_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R6_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R7_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R8_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R9_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R10_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R11_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R12_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R13_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R14_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R15_REGNUM:
+ memcpy (& DSPregs [rn - SIM_ARM_MAVERIC_COP0R0_REGNUM],
+ memory, sizeof (struct maverick_regs));
+ return sizeof (struct maverick_regs);
+
+ case SIM_ARM_MAVERIC_DSPSC_REGNUM:
+ memcpy (&DSPsc, memory, sizeof DSPsc);
+ return sizeof DSPsc;
+
default:
return 0;
}
*************** sim_fetch_register (sd, rn, memory, leng
*** 476,481 ****
--- 535,564 ----
case SIM_ARM_PS_REGNUM:
regval = ARMul_GetCPSR (state);
break;
+
+ case SIM_ARM_MAVERIC_COP0R0_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R1_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R2_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R3_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R4_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R5_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R6_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R7_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R8_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R9_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R10_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R11_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R12_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R13_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R14_REGNUM:
+ case SIM_ARM_MAVERIC_COP0R15_REGNUM:
+ memcpy (memory, & DSPregs [rn - SIM_ARM_MAVERIC_COP0R0_REGNUM],
+ sizeof (struct maverick_regs));
+ return sizeof (struct maverick_regs);
+
+ case SIM_ARM_MAVERIC_DSPSC_REGNUM:
+ memcpy (memory, & DSPsc, sizeof DSPsc);
+ return sizeof DSPsc;
default:
return 0;
*** /dev/null Sat Oct 19 15:41:17 2002
--- sim/arm/maverick.c Sat Feb 8 12:58:09 2003
***************
*** 0 ****
--- 1,1291 ----
+ /* maverick.c -- Cirrus/DSP co-processor interface.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez (aldyh@redhat.com).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+ #include <assert.h>
+ #include "armdefs.h"
+ #include "ansidecl.h"
+ #include "armemu.h"
+
+ /*#define CIRRUS_DEBUG 1 /**/
+ #if CIRRUS_DEBUG
+ # define printfdbg printf
+ #else
+ # define printfdbg printf_nothing
+ #endif
+
+ #define POS64(i) ( (~(i)) >> 63 )
+ #define NEG64(i) ( (i) >> 63 )
+
+ /* Define Co-Processor instruction handlers here. */
+
+ /* Here's ARMulator's DSP definition. A few things to note:
+ 1) it has 16 64-bit registers and 4 72-bit accumulators
+ 2) you can only access its registers with MCR and MRC. */
+
+ /* We can't define these in here because this file might not be linked
+ unless the target is arm9e-*. They are defined in wrapper.c.
+ Eventually the simulator should be made to handle any coprocessor
+ at run time. */
+ struct maverick_regs
+ {
+ union
+ {
+ int i;
+ float f;
+ } upper;
+
+ union
+ {
+ int i;
+ float f;
+ } lower;
+ };
+
+ union maverick_acc_regs
+ {
+ long double ld; /* Acc registers are 72-bits. */
+ };
+
+ struct maverick_regs DSPregs[16];
+ union maverick_acc_regs DSPacc[4];
+ ARMword DSPsc;
+
+ #define DEST_REG (BITS (12, 15))
+ #define SRC1_REG (BITS (16, 19))
+ #define SRC2_REG (BITS (0, 3))
+
+ static int lsw_int_index, msw_int_index;
+ static int lsw_float_index, msw_float_index;
+
+ static double mv_getRegDouble (int);
+ static long long mv_getReg64int (int);
+ static void mv_setRegDouble (int, double val);
+ static void mv_setReg64int (int, long long val);
+
+ static union
+ {
+ double d;
+ long long ll;
+ int ints[2];
+ } reg_conv;
+
+ static void
+ printf_nothing (void * foo, ...)
+ {
+ }
+
+ static void
+ cirrus_not_implemented (char * insn)
+ {
+ fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
+ fprintf (stderr, "aborting!\n");
+
+ exit (1);
+ }
+
+ static unsigned
+ DSPInit (ARMul_State * state)
+ {
+ ARMul_ConsolePrint (state, ", DSP present");
+ return TRUE;
+ }
+
+ unsigned
+ DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword * value)
+ {
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmvrdl */
+ /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
+ printfdbg ("cfmvrdl\n");
+ printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
+ printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
+
+ *value = (ARMword) DSPregs[SRC1_REG].lower.i;
+ break;
+
+ case 1: /* cfmvrdh */
+ /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
+ printfdbg ("cfmvrdh\n");
+ printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
+ printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
+
+ *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+ break;
+
+ case 2: /* cfmvrs */
+ /* Move SF from upper half of a DSP register to an Arm register. */
+ *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+ printfdbg ("cfmvrs = mvf%d <-- %f\n",
+ SRC1_REG,
+ DSPregs[SRC1_REG].upper.f);
+ break;
+
+ #ifdef doesnt_work
+ case 4: /* cfcmps */
+ {
+ float a, b;
+ int n, z, c, v;
+
+ a = DSPregs[SRC1_REG].upper.f;
+ b = DSPregs[SRC2_REG].upper.f;
+
+ printfdbg ("cfcmps\n");
+ printfdbg ("\tcomparing %f and %f\n", a, b);
+
+ z = a == b; /* zero */
+ n = a != b; /* negative */
+ v = a > b; /* overflow */
+ c = 0; /* carry */
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+
+ case 5: /* cfcmpd */
+ {
+ double a, b;
+ int n, z, c, v;
+
+ a = mv_getRegDouble (SRC1_REG);
+ b = mv_getRegDouble (SRC2_REG);
+
+ printfdbg ("cfcmpd\n");
+ printfdbg ("\tcomparing %g and %g\n", a, b);
+
+ z = a == b; /* zero */
+ n = a != b; /* negative */
+ v = a > b; /* overflow */
+ c = 0; /* carry */
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+ #else
+ case 4: /* cfcmps */
+ {
+ float a, b;
+ int n, z, c, v;
+
+ a = DSPregs[SRC1_REG].upper.f;
+ b = DSPregs[SRC2_REG].upper.f;
+
+ printfdbg ("cfcmps\n");
+ printfdbg ("\tcomparing %f and %f\n", a, b);
+
+ z = a == b; /* zero */
+ n = a < b; /* negative */
+ c = a > b; /* carry */
+ v = 0; /* fixme */
+ printfdbg ("\tz = %d, n = %d\n", z, n);
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+
+ case 5: /* cfcmpd */
+ {
+ double a, b;
+ int n, z, c, v;
+
+ a = mv_getRegDouble (SRC1_REG);
+ b = mv_getRegDouble (SRC2_REG);
+
+ printfdbg ("cfcmpd\n");
+ printfdbg ("\tcomparing %g and %g\n", a, b);
+
+ z = a == b; /* zero */
+ n = a < b; /* negative */
+ c = a > b; /* carry */
+ v = 0; /* fixme */
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+ #endif
+ default:
+ fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword * value)
+ {
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmvr64l */
+ /* Move lower half of 64bit int from Cirrus to Arm. */
+ *value = (ARMword) DSPregs[SRC1_REG].lower.i;
+ printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
+ DEST_REG,
+ (int) *value);
+ break;
+
+ case 1: /* cfmvr64h */
+ /* Move upper half of 64bit int from Cirrus to Arm. */
+ *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+ printfdbg ("cfmvr64h <-- %d\n", (int) *value);
+ break;
+
+ case 4: /* cfcmp32 */
+ {
+ int res;
+ int n, z, c, v;
+ unsigned int a, b;
+
+ printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
+ SRC1_REG,
+ SRC2_REG);
+
+ /* FIXME: see comment for cfcmps. */
+ a = DSPregs[SRC1_REG].lower.i;
+ b = DSPregs[SRC2_REG].lower.i;
+
+ res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
+ /* zero */
+ z = res == 0;
+ /* negative */
+ n = res < 0;
+ /* overflow */
+ v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
+ res);
+ /* carry */
+ c = (NEG (a) && POS (b) ||
+ (NEG (a) && POS (res)) || (POS (b) && POS (res)));
+
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+
+ case 5: /* cfcmp64 */
+ {
+ long long res;
+ int n, z, c, v;
+ unsigned long long a, b;
+
+ printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
+ SRC1_REG,
+ SRC2_REG);
+
+ /* fixme: see comment for cfcmps. */
+
+ a = mv_getReg64int (SRC1_REG);
+ b = mv_getReg64int (SRC2_REG);
+
+ res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
+ /* zero */
+ z = res == 0;
+ /* negative */
+ n = res < 0;
+ /* overflow */
+ v = ((NEG64 (a) && POS64 (b) && POS64 (res))
+ || (POS64 (a) && NEG64 (b) && NEG64 (res)));
+ /* carry */
+ c = (NEG64 (a) && POS64 (b) ||
+ (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
+
+ *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+ break;
+ }
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword * value)
+ {
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmval32 */
+ cirrus_not_implemented ("cfmval32");
+ break;
+
+ case 1: /* cfmvam32 */
+ cirrus_not_implemented ("cfmvam32");
+ break;
+
+ case 2: /* cfmvah32 */
+ cirrus_not_implemented ("cfmvah32");
+ break;
+
+ case 3: /* cfmva32 */
+ cirrus_not_implemented ("cfmva32");
+ break;
+
+ case 4: /* cfmva64 */
+ cirrus_not_implemented ("cfmva64");
+ break;
+
+ case 5: /* cfmvsc32 */
+ cirrus_not_implemented ("cfmvsc32");
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPMCR4 (ARMul_State * state,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword value)
+ {
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmvdlr */
+ /* Move the lower half of a DF value from an Arm register into
+ the lower half of a Cirrus register. */
+ printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
+ DSPregs[SRC1_REG].lower.i = (int) value;
+ break;
+
+ case 1: /* cfmvdhr */
+ /* Move the upper half of a DF value from an Arm register into
+ the upper half of a Cirrus register. */
+ printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
+ DSPregs[SRC1_REG].upper.i = (int) value;
+ break;
+
+ case 2: /* cfmvsr */
+ /* Move SF from Arm register into upper half of Cirrus register. */
+ printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
+ DSPregs[SRC1_REG].upper.i = (int) value;
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPMCR5 (ARMul_State * state,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword value)
+ {
+ union
+ {
+ int s;
+ unsigned int us;
+ } val;
+
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmv64lr */
+ /* Move lower half of a 64bit int from an ARM register into the
+ lower half of a DSP register and sign extend it. */
+ printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
+ DSPregs[SRC1_REG].lower.i = (int) value;
+ break;
+
+ case 1: /* cfmv64hr */
+ /* Move upper half of a 64bit int from an ARM register into the
+ upper half of a DSP register. */
+ printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
+ SRC1_REG,
+ (int) value);
+ DSPregs[SRC1_REG].upper.i = (int) value;
+ break;
+
+ case 2: /* cfrshl32 */
+ printfdbg ("cfrshl32\n");
+ val.us = value;
+ if (val.s > 0)
+ DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
+ else
+ DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
+ break;
+
+ case 3: /* cfrshl64 */
+ printfdbg ("cfrshl64\n");
+ val.us = value;
+ if (val.s > 0)
+ mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
+ else
+ mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPMCR6 (ARMul_State * state,
+ unsigned type ATTRIBUTE_UNUSED,
+ ARMword instr,
+ ARMword value)
+ {
+ switch (BITS (5, 7))
+ {
+ case 0: /* cfmv32al */
+ cirrus_not_implemented ("cfmv32al");
+ break;
+
+ case 1: /* cfmv32am */
+ cirrus_not_implemented ("cfmv32am");
+ break;
+
+ case 2: /* cfmv32ah */
+ cirrus_not_implemented ("cfmv32ah");
+ break;
+
+ case 3: /* cfmv32a */
+ cirrus_not_implemented ("cfmv32a");
+ break;
+
+ case 4: /* cfmv64a */
+ cirrus_not_implemented ("cfmv64a");
+ break;
+
+ case 5: /* cfmv32sc */
+ cirrus_not_implemented ("cfmv32sc");
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type,
+ ARMword instr,
+ ARMword data)
+ {
+ static unsigned words;
+
+ if (type != ARMul_DATA)
+ {
+ words = 0;
+ return ARMul_DONE;
+ }
+
+ if (BIT (22))
+ { /* it's a long access, get two words */
+ /* cfldrd */
+
+ printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
+ data, words, state->bigendSig, DEST_REG);
+
+ if (words == 0)
+ {
+ if (state->bigendSig)
+ DSPregs[DEST_REG].upper.i = (int) data;
+ else
+ DSPregs[DEST_REG].lower.i = (int) data;
+ }
+ else
+ {
+ if (state->bigendSig)
+ DSPregs[DEST_REG].lower.i = (int) data;
+ else
+ DSPregs[DEST_REG].upper.i = (int) data;
+ }
+
+ ++ words;
+
+ if (words == 2)
+ {
+ printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
+ mv_getRegDouble (DEST_REG));
+
+ return ARMul_DONE;
+ }
+ else
+ return ARMul_INC;
+ }
+ else
+ {
+ /* Get just one word. */
+
+ /* cfldrs */
+ printfdbg ("cfldrs\n");
+
+ DSPregs[DEST_REG].upper.i = (int) data;
+
+ printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
+ DSPregs[DEST_REG].upper.f);
+
+ return ARMul_DONE;
+ }
+ }
+
+ unsigned
+ DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type,
+ ARMword instr,
+ ARMword data)
+ {
+ static unsigned words;
+
+ if (type != ARMul_DATA)
+ {
+ words = 0;
+ return ARMul_DONE;
+ }
+
+ if (BIT (22))
+ {
+ /* It's a long access, get two words. */
+
+ /* cfldr64 */
+ printfdbg ("cfldr64: %d\n", data);
+
+ if (words == 0)
+ {
+ if (state->bigendSig)
+ DSPregs[DEST_REG].upper.i = (int) data;
+ else
+ DSPregs[DEST_REG].lower.i = (int) data;
+ }
+ else
+ {
+ if (state->bigendSig)
+ DSPregs[DEST_REG].lower.i = (int) data;
+ else
+ DSPregs[DEST_REG].upper.i = (int) data;
+ }
+
+ ++ words;
+
+ if (words == 2)
+ {
+ printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
+ mv_getReg64int (DEST_REG));
+
+ return ARMul_DONE;
+ }
+ else
+ return ARMul_INC;
+ }
+ else
+ {
+ /* Get just one word. */
+
+ /* cfldr32 */
+ printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
+
+ /* 32bit ints should be sign extended to 64bits when loaded. */
+ mv_setReg64int (DEST_REG, (long long) data);
+
+ return ARMul_DONE;
+ }
+ }
+
+ unsigned
+ DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type,
+ ARMword instr,
+ ARMword * data)
+ {
+ static unsigned words;
+
+ if (type != ARMul_DATA)
+ {
+ words = 0;
+ return ARMul_DONE;
+ }
+
+ if (BIT (22))
+ {
+ /* It's a long access, get two words. */
+ /* cfstrd */
+ printfdbg ("cfstrd\n");
+
+ if (words == 0)
+ {
+ if (state->bigendSig)
+ *data = (ARMword) DSPregs[DEST_REG].upper.i;
+ else
+ *data = (ARMword) DSPregs[DEST_REG].lower.i;
+ }
+ else
+ {
+ if (state->bigendSig)
+ *data = (ARMword) DSPregs[DEST_REG].lower.i;
+ else
+ *data = (ARMword) DSPregs[DEST_REG].upper.i;
+ }
+
+ ++ words;
+
+ if (words == 2)
+ {
+ printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
+ mv_getRegDouble (DEST_REG));
+
+ return ARMul_DONE;
+ }
+ else
+ return ARMul_INC;
+ }
+ else
+ {
+ /* Get just one word. */
+ /* cfstrs */
+ printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
+ DSPregs[DEST_REG].upper.f);
+
+ *data = (ARMword) DSPregs[DEST_REG].upper.i;
+
+ return ARMul_DONE;
+ }
+ }
+
+ unsigned
+ DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned type,
+ ARMword instr,
+ ARMword * data)
+ {
+ static unsigned words;
+
+ if (type != ARMul_DATA)
+ {
+ words = 0;
+ return ARMul_DONE;
+ }
+
+ if (BIT (22))
+ {
+ /* It's a long access, store two words. */
+ /* cfstr64 */
+ printfdbg ("cfstr64\n");
+
+ if (words == 0)
+ {
+ if (state->bigendSig)
+ *data = (ARMword) DSPregs[DEST_REG].upper.i;
+ else
+ *data = (ARMword) DSPregs[DEST_REG].lower.i;
+ }
+ else
+ {
+ if (state->bigendSig)
+ *data = (ARMword) DSPregs[DEST_REG].lower.i;
+ else
+ *data = (ARMword) DSPregs[DEST_REG].upper.i;
+ }
+
+ ++ words;
+
+ if (words == 2)
+ {
+ printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
+ mv_getReg64int (DEST_REG));
+
+ return ARMul_DONE;
+ }
+ else
+ return ARMul_INC;
+ }
+ else
+ {
+ /* Store just one word. */
+ /* cfstr32 */
+ *data = (ARMword) DSPregs[DEST_REG].lower.i;
+
+ printfdbg ("cfstr32 MEM = %d\n", (int) *data);
+
+ return ARMul_DONE;
+ }
+ }
+
+ unsigned
+ DSPCDP4 (ARMul_State * state,
+ unsigned type,
+ ARMword instr)
+ {
+ int opcode2;
+
+ opcode2 = BITS (5,7);
+
+ switch (BITS (20,21))
+ {
+ case 0:
+ switch (opcode2)
+ {
+ case 0: /* cfcpys */
+ printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[SRC1_REG].upper.f);
+ DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
+ break;
+
+ case 1: /* cfcpyd */
+ printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ mv_getRegDouble (SRC1_REG));
+ mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
+ break;
+
+ case 2: /* cfcvtds */
+ printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ (float) mv_getRegDouble (SRC1_REG));
+ DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
+ break;
+
+ case 3: /* cfcvtsd */
+ printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ (double) DSPregs[SRC1_REG].upper.f);
+ mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
+ break;
+
+ case 4: /* cfcvt32s */
+ printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ (float) DSPregs[SRC1_REG].lower.i);
+ DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
+ break;
+
+ case 5: /* cfcvt32d */
+ printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ (double) DSPregs[SRC1_REG].lower.i);
+ mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
+ break;
+
+ case 6: /* cfcvt64s */
+ printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ (float) mv_getReg64int (SRC1_REG));
+ DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
+ break;
+
+ case 7: /* cfcvt64d */
+ printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ (double) mv_getReg64int (SRC1_REG));
+ mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
+ break;
+ }
+ break;
+
+ case 1:
+ switch (opcode2)
+ {
+ case 0: /* cfmuls */
+ printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
+
+ DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+ * DSPregs[SRC2_REG].upper.f;
+ break;
+
+ case 1: /* cfmuld */
+ printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
+
+ mv_setRegDouble (DEST_REG,
+ mv_getRegDouble (SRC1_REG)
+ * mv_getRegDouble (SRC2_REG));
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+ break;
+
+ case 3:
+ switch (opcode2)
+ {
+ case 0: /* cfabss */
+ DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
+ -DSPregs[SRC1_REG].upper.f
+ : DSPregs[SRC1_REG].upper.f);
+ printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].upper.f);
+ break;
+
+ case 1: /* cfabsd */
+ mv_setRegDouble (DEST_REG,
+ (mv_getRegDouble (SRC1_REG) < 0.0 ?
+ -mv_getRegDouble (SRC1_REG)
+ : mv_getRegDouble (SRC1_REG)));
+ printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ mv_getRegDouble (DEST_REG));
+ break;
+
+ case 2: /* cfnegs */
+ DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
+ printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].upper.f);
+ break;
+
+ case 3: /* cfnegd */
+ mv_setRegDouble (DEST_REG,
+ -mv_getRegDouble (SRC1_REG));
+ printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
+ DEST_REG,
+ mv_getRegDouble (DEST_REG));
+ break;
+
+ case 4: /* cfadds */
+ DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+ + DSPregs[SRC2_REG].upper.f;
+ printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].upper.f);
+ break;
+
+ case 5: /* cfaddd */
+ mv_setRegDouble (DEST_REG,
+ mv_getRegDouble (SRC1_REG)
+ + mv_getRegDouble (SRC2_REG));
+ printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getRegDouble (DEST_REG));
+ break;
+
+ case 6: /* cfsubs */
+ DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+ - DSPregs[SRC2_REG].upper.f;
+ printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].upper.f);
+ break;
+
+ case 7: /* cfsubd */
+ mv_setRegDouble (DEST_REG,
+ mv_getRegDouble (SRC1_REG)
+ - mv_getRegDouble (SRC2_REG));
+ printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getRegDouble (DEST_REG));
+ break;
+ }
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPCDP5 (ARMul_State * state,
+ unsigned type,
+ ARMword instr)
+ {
+ int opcode2;
+ char shift;
+
+ opcode2 = BITS (5,7);
+
+ /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
+ shift = BITS (0, 3) | (BITS (5, 7)) << 4;
+ if (shift & 0x40)
+ shift |= 0xc0;
+
+ switch (BITS (20,21))
+ {
+ case 0:
+ /* cfsh32 */
+ printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
+ shift);
+ if (shift < 0)
+ /* Negative shift is a right shift. */
+ DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
+ else
+ /* Positive shift is a left shift. */
+ DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
+ break;
+
+ case 1:
+ switch (opcode2)
+ {
+ case 0: /* cfmul32 */
+ DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+ * DSPregs[SRC2_REG].lower.i;
+ printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 1: /* cfmul64 */
+ mv_setReg64int (DEST_REG,
+ mv_getReg64int (SRC1_REG)
+ * mv_getReg64int (SRC2_REG));
+ printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getReg64int (DEST_REG));
+ break;
+
+ case 2: /* cfmac32 */
+ DSPregs[DEST_REG].lower.i
+ += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
+ printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 3: /* cfmsc32 */
+ DSPregs[DEST_REG].lower.i
+ -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
+ printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 4: /* cfcvts32 */
+ /* fixme: this should round */
+ DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
+ printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 5: /* cfcvtd32 */
+ /* fixme: this should round */
+ DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
+ printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 6: /* cftruncs32 */
+ DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
+ printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 7: /* cftruncd32 */
+ DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
+ printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+ }
+ break;
+
+ case 2:
+ /* cfsh64 */
+ printfdbg ("cfsh64\n");
+
+ if (shift < 0)
+ /* Negative shift is a right shift. */
+ mv_setReg64int (DEST_REG,
+ mv_getReg64int (SRC1_REG) >> -shift);
+ else
+ /* Positive shift is a left shift. */
+ mv_setReg64int (DEST_REG,
+ mv_getReg64int (SRC1_REG) << shift);
+ printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
+ break;
+
+ case 3:
+ switch (opcode2)
+ {
+ case 0: /* cfabs32 */
+ DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
+ ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
+ printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 1: /* cfabs64 */
+ mv_setReg64int (DEST_REG,
+ (mv_getReg64int (SRC1_REG) < 0
+ ? -mv_getReg64int (SRC1_REG)
+ : mv_getReg64int (SRC1_REG)));
+ printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getReg64int (DEST_REG));
+ break;
+
+ case 2: /* cfneg32 */
+ DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
+ printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 3: /* cfneg64 */
+ mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
+ printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getReg64int (DEST_REG));
+ break;
+
+ case 4: /* cfadd32 */
+ DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+ + DSPregs[SRC2_REG].lower.i;
+ printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 5: /* cfadd64 */
+ mv_setReg64int (DEST_REG,
+ mv_getReg64int (SRC1_REG)
+ + mv_getReg64int (SRC2_REG));
+ printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getReg64int (DEST_REG));
+ break;
+
+ case 6: /* cfsub32 */
+ DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+ - DSPregs[SRC2_REG].lower.i;
+ printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ DSPregs[DEST_REG].lower.i);
+ break;
+
+ case 7: /* cfsub64 */
+ mv_setReg64int (DEST_REG,
+ mv_getReg64int (SRC1_REG)
+ - mv_getReg64int (SRC2_REG));
+ printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
+ DEST_REG,
+ SRC1_REG,
+ SRC2_REG,
+ mv_getReg64int (DEST_REG));
+ break;
+ }
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
+ cirrus_not_implemented ("unknown");
+ break;
+ }
+
+ return ARMul_DONE;
+ }
+
+ unsigned
+ DSPCDP6 (ARMul_State * state,
+ unsigned type,
+ ARMword instr)
+ {
+ int opcode2;
+
+ opcode2 = BITS (5,7);
+
+ switch (BITS (20,21))
+ {
+ case 0:
+ /* cfmadd32 */
+ cirrus_not_implemented ("cfmadd32");
+ break;
+
+ case 1:
+ /* cfmsub32 */
+ cirrus_not_implemented ("cfmsub32");
+ break;
+
+ case 2:
+ /* cfmadda32 */
+ cirrus_not_implemented ("cfmadda32");
+ break;
+
+ case 3:
+ /* cfmsuba32 */
+ cirrus_not_implemented ("cfmsuba32");
+ break;
+
+ default:
+ fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
+ }
+
+ return ARMul_DONE;
+ }
+
+ /* Conversion functions.
+
+ 32-bit integers are stored in the LOWER half of a 64-bit physical
+ register.
+
+ Single precision floats are stored in the UPPER half of a 64-bit
+ physical register. */
+
+ static double
+ mv_getRegDouble (int regnum)
+ {
+ reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
+ reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
+ return reg_conv.d;
+ }
+
+ static void
+ mv_setRegDouble (int regnum, double val)
+ {
+ reg_conv.d = val;
+ DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
+ DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
+ }
+
+ static long long
+ mv_getReg64int (int regnum)
+ {
+ reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
+ reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
+ return reg_conv.ll;
+ }
+
+ static void
+ mv_setReg64int (int regnum, long long val)
+ {
+ reg_conv.ll = val;
+ DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
+ DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
+ }
+
+ /* Compute LSW in a double and a long long. */
+
+ void
+ mv_compute_host_endianness (ARMul_State * state)
+ {
+ static union
+ {
+ long long ll;
+ long ints[2];
+ long i;
+ double d;
+ float floats[2];
+ float f;
+ } conv;
+
+ /* Calculate where's the LSW in a 64bit int. */
+ conv.ll = 45;
+
+ if (conv.ints[0] == 0)
+ {
+ msw_int_index = 0;
+ lsw_int_index = 1;
+ }
+ else
+ {
+ assert (conv.ints[1] == 0);
+ msw_int_index = 1;
+ lsw_int_index = 0;
+ }
+
+ /* Calculate where's the LSW in a double. */
+ conv.d = 3.0;
+
+ if (conv.ints[0] == 0)
+ {
+ msw_float_index = 0;
+ lsw_float_index = 1;
+ }
+ else
+ {
+ assert (conv.ints[1] == 0);
+ msw_float_index = 1;
+ lsw_float_index = 0;
+ }
+
+ printfdbg ("lsw_int_index %d\n", lsw_int_index);
+ printfdbg ("lsw_float_index %d\n", lsw_float_index);
+ }