From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26946 invoked by alias); 10 Feb 2003 12:12:21 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 26938 invoked from network); 10 Feb 2003 12:12:21 -0000 Received: from unknown (HELO mx1.redhat.com) (172.16.49.200) by 172.16.49.205 with SMTP; 10 Feb 2003 12:12:21 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.11.6/8.11.6) with ESMTP id h1ACCLf20173 for ; Mon, 10 Feb 2003 07:12:21 -0500 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [172.16.52.156]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h1ACCKa04830 for ; Mon, 10 Feb 2003 07:12:20 -0500 Received: from north-pole.nickc.cambridge.redhat.com.redhat.com (vpn50-28.rdu.redhat.com [172.16.50.28]) by pobox.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h1ACCAH21986 for ; Mon, 10 Feb 2003 07:12:12 -0500 To: gdb-patches@sources.redhat.com Subject: RFA: Add support for Cirrus EP9312 From: Nick Clifton Date: Mon, 10 Feb 2003 12:12:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-02/txt/msg00255.txt.bz2 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 * Contribute support for Cirrus Maverick ARM co-processor: 2000-06-02 Andrew Cagney * remote-rdi.c (arm_rdi_fetch_registers): Add #ifdef COPRO_REGNUM. Only return those registers when COPRO is defined. 2000-05-30 Jeff Holcomb * 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 * arm-tdep.c, remote-rdi.c, config/arm/tm-arm.h: Cirrus DSP coprocessor modifications. include/gdb/ChangeLog 2003-02-10 Nick Clifton * sim-arm.h (sim_arm_regs): Add Maverick co-processor registers. sim/arm/ChangeLog 2003-02-10 Nick Clifton * Contribute support for Cirrus Maverick ARM co-processor, written by Aldy Hernandez and Andrew Cagney : * 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 + #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); + }