From: Doug Evans Date: Mon, 23 Feb 1998 18:21:14 +0000 (+0000) Subject: * sim-xcat.h: Delete. X-Git-Tag: gdb-4_18~3215 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=36dbc8bb7cfa9399b50cdd0e47e617c7be69a280;p=external%2Fbinutils.git * sim-xcat.h: Delete. * cgen-mem.h: Delete inclusion of sim-xcat.h. * cgen-sim.h: Ditto. * sim-alu.h: Replace sim-xcat.h with symcat.h. * sim-n-bits.h: Ditto. * sim-n-core.h: Ditto. * sim-n-endian.h: Ditto. --- diff --git a/sim/common/.Sanitize b/sim/common/.Sanitize index a939e15..c65449b 100644 --- a/sim/common/.Sanitize +++ b/sim/common/.Sanitize @@ -109,7 +109,6 @@ sim-utils.c sim-utils.h sim-watch.c sim-watch.h -sim-xcat.h syscall.c tconfig.in diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 70af484..c7541f6 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,13 @@ +Mon Feb 23 13:08:35 1998 Doug Evans + + * sim-xcat.h: Delete. + * cgen-mem.h: Delete inclusion of sim-xcat.h. + * cgen-sim.h: Ditto. + * sim-alu.h: Replace sim-xcat.h with symcat.h. + * sim-n-bits.h: Ditto. + * sim-n-core.h: Ditto. + * sim-n-endian.h: Ditto. + Mon Feb 23 13:19:58 1998 Michael Meissner * syscall.c (cb_syscall): Handle short reads, and EOF. diff --git a/sim/common/cgen-mem.h b/sim/common/cgen-mem.h index 9be66d0..2a82c5d 100644 --- a/sim/common/cgen-mem.h +++ b/sim/common/cgen-mem.h @@ -1,10 +1,8 @@ /* Memory ops header for CGEN-based simlators. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. -This file is machine generated. - -Copyright (C) 1996, 1997 Free Software Foundation, Inc. - -This file is part of the GNU Binutils and/or GDB, the GNU debugger. +This file is part of the GNU Simulators. 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 @@ -18,9 +16,7 @@ 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. - -*/ +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef CGEN_MEM_H #define CGEN_MEM_H @@ -31,473 +27,131 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MEMOPS_INLINE extern inline #endif -/* Only used in this file. */ -typedef unsigned char *ptr; - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE QI -GETTQI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return p[0]; - else - return p[0]; -} -#else -extern QI GETTQI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE HI -GETTHI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return ((p[0] << 8) | p[1]); - else - return ((p[1] << 8) | p[0]); -} -#else -extern HI GETTHI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE SI -GETTSI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); - else - return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} -#else -extern SI GETTSI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE DI -GETTDI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return MAKEDI ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3], (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]); - else - return MAKEDI ((p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4], (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} -#else -extern DI GETTDI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UQI -GETTUQI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return p[0]; - else - return p[0]; -} -#else -extern UQI GETTUQI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UHI -GETTUHI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return ((p[0] << 8) | p[1]); - else - return ((p[1] << 8) | p[0]); -} -#else -extern UHI GETTUHI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE USI -GETTUSI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); - else - return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} -#else -extern USI GETTUSI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UDI -GETTUDI (ptr p) -{ - if (TARGET_BIG_ENDIAN) - return MAKEDI ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3], (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]); - else - return MAKEDI ((p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4], (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} -#else -extern UDI GETTUDI (ptr); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTQI (ptr p, QI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val; } while (0); -else - do { p[0] = val; } while (0); -} -#else -extern void SETTQI (ptr, QI); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTHI (ptr p, HI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val >> 8; p[1] = val; } while (0); -else - do { p[1] = val >> 8; p[0] = val; } while (0); -} -#else -extern void SETTHI (ptr, HI); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTSI (ptr p, SI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val >> 24; p[1] = val >> 16; p[2] = val >> 8; p[3] = val; } while (0); -else - do { p[3] = val >> 24; p[2] = val >> 16; p[1] = val >> 8; p[0] = val; } while (0); -} -#else -extern void SETTSI (ptr, SI); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTDI (ptr p, DI val) -{ - if (TARGET_BIG_ENDIAN) - do { SI t = GETHIDI (val); p[0] = t >> 24; p[1] = t >> 16; p[2] = t >> 8; p[3] = t; t = GETLODI (val); p[4] = t >> 24; p[5] = t >> 16; p[6] = t >> 8; p[7] = t; } while (0); -else - do { SI t = GETHIDI (val); p[7] = t >> 24; p[6] = t >> 16; p[5] = t >> 8; p[4] = t; t = GETLODI (val); p[3] = t >> 24; p[2] = t >> 16; p[1] = t >> 8; p[0] = t; } while (0); -} -#else -extern void SETTDI (ptr, DI); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTUQI (ptr p, UQI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val; } while (0); -else - do { p[0] = val; } while (0); -} -#else -extern void SETTUQI (ptr, UQI); -#endif - #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTUHI (ptr p, UHI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val >> 8; p[1] = val; } while (0); -else - do { p[1] = val >> 8; p[0] = val; } while (0); +#define DECLARE_GETMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, ADDR a) \ +{ \ + PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, NULL_CIA, sim_core_read_map, a); \ } #else -extern void SETTUHI (ptr, UHI); +#define DECLARE_GETMEM(mode, size) \ +extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, ADDR); #endif -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTUSI (ptr p, USI val) -{ - if (TARGET_BIG_ENDIAN) - do { p[0] = val >> 24; p[1] = val >> 16; p[2] = val >> 8; p[3] = val; } while (0); -else - do { p[3] = val >> 24; p[2] = val >> 16; p[1] = val >> 8; p[0] = val; } while (0); -} -#else -extern void SETTUSI (ptr, USI); -#endif +DECLARE_GETMEM (QI, 1) +DECLARE_GETMEM (UQI, 1) +DECLARE_GETMEM (HI, 2) +DECLARE_GETMEM (UHI, 2) +DECLARE_GETMEM (SI, 4) +DECLARE_GETMEM (USI, 4) +DECLARE_GETMEM (DI, 8) +DECLARE_GETMEM (UDI, 8) -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETTUDI (ptr p, UDI val) -{ - if (TARGET_BIG_ENDIAN) - do { SI t = GETHIDI (val); p[0] = t >> 24; p[1] = t >> 16; p[2] = t >> 8; p[3] = t; t = GETLODI (val); p[4] = t >> 24; p[5] = t >> 16; p[6] = t >> 8; p[7] = t; } while (0); -else - do { SI t = GETHIDI (val); p[7] = t >> 24; p[6] = t >> 16; p[5] = t >> 8; p[4] = t; t = GETLODI (val); p[3] = t >> 24; p[2] = t >> 16; p[1] = t >> 8; p[0] = t; } while (0); -} -#else -extern void SETTUDI (ptr, UDI); -#endif - - -/* FIXME: Need to merge with sim-core. */ -/* FIXME: Don't perform >= 4, text section checks if OEA. */ -#ifndef MEM_CHECK_READ -#define MEM_CHECK_READ(addr, type) \ - ((addr) >= 4 /*&& (addr) < STATE_MEM_SIZE (current_state)*/) -#endif -#ifndef MEM_CHECK_WRITE -#define MEM_CHECK_WRITE(addr, type) \ - ((addr) >= 4 /*&& (addr) < STATE_MEM_SIZE (current_state)*/ \ - && ((addr) >= STATE_TEXT_END (current_state) \ - || (addr) < STATE_TEXT_START (current_state))) -#endif -#ifndef MEM_CHECK_ALIGNMENT -#define MEM_CHECK_ALIGNMENT(addr, type) \ - (((addr) & (sizeof (type) - 1)) == 0) -#endif +#undef DECLARE_GETMEM #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE QI -GETMEMQI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, QI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, QI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_QI); - return sim_core_read_1 (CPU_STATE (cpu), sim_core_read_map, a); +#define DECLARE_SETMEM(mode, size) \ +MEMOPS_INLINE void \ +XCONCAT2 (SETMEM,mode) (SIM_CPU *cpu, ADDR a, mode val) \ +{ \ + PROFILE_COUNT_WRITE (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */ \ + XCONCAT2 (sim_core_write_unaligned_,size) (cpu, NULL_CIA, sim_core_write_map, a, val); \ } #else -extern QI GETMEMQI (SIM_CPU *, ADDR); +#define DECLARE_SETMEM(mode, size) \ +extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, ADDR, mode); #endif -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE HI -GETMEMHI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, HI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, HI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_HI); - return sim_core_read_2 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern HI GETMEMHI (SIM_CPU *, ADDR); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE SI -GETMEMSI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, SI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, SI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_SI); - return sim_core_read_4 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern SI GETMEMSI (SIM_CPU *, ADDR); -#endif +DECLARE_SETMEM (QI, 1) +DECLARE_SETMEM (UQI, 1) +DECLARE_SETMEM (HI, 2) +DECLARE_SETMEM (UHI, 2) +DECLARE_SETMEM (SI, 4) +DECLARE_SETMEM (USI, 4) +DECLARE_SETMEM (DI, 8) +DECLARE_SETMEM (UDI, 8) -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE DI -GETMEMDI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, DI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, DI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_DI); - return sim_core_read_8 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern DI GETMEMDI (SIM_CPU *, ADDR); -#endif - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UQI -GETMEMUQI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, UQI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, UQI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_UQI); - return sim_core_read_1 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern UQI GETMEMUQI (SIM_CPU *, ADDR); -#endif +#undef DECLARE_SETMEM #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UHI -GETMEMUHI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, UHI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, UHI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_UHI); - return sim_core_read_2 (CPU_STATE (cpu), sim_core_read_map, a); +#define DECLARE_GETIMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETIMEM,mode) (SIM_CPU *cpu, ADDR a) \ +{ \ + /*PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode));*/ \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, NULL_CIA, sim_core_execute_map, a); \ } #else -extern UHI GETMEMUHI (SIM_CPU *, ADDR); +#define DECLARE_GETIMEM(mode, size) \ +extern mode XCONCAT2 (GETIMEM,mode) (SIM_CPU *, ADDR); #endif -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE USI -GETMEMUSI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, USI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, USI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_USI); - return sim_core_read_4 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern USI GETMEMUSI (SIM_CPU *, ADDR); -#endif +DECLARE_GETIMEM (UQI, 1) +DECLARE_GETIMEM (UHI, 2) +DECLARE_GETIMEM (USI, 4) +DECLARE_GETIMEM (UDI, 8) -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE UDI -GETMEMUDI (SIM_CPU *cpu, ADDR a) -{ - if (! MEM_CHECK_READ (a, UDI)) - { engine_signal (cpu, SIM_SIGACCESS); } - if (! MEM_CHECK_ALIGNMENT (a, UDI)) - { engine_signal (cpu, SIM_SIGALIGN); } - PROFILE_COUNT_READ (cpu, a, MODE_UDI); - return sim_core_read_8 (CPU_STATE (cpu), sim_core_read_map, a); -} -#else -extern UDI GETMEMUDI (SIM_CPU *, ADDR); -#endif +#undef DECLARE_GETIMEM -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMQI (SIM_CPU *cpu, ADDR a, QI val) -{ - if (! MEM_CHECK_WRITE (a, QI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, QI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_QI); - sim_core_write_1 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMQI (SIM_CPU *, ADDR, QI); -#endif +/* GETT: translate target value at P to host value. + ??? How inefficient is the current implementation? */ #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMHI (SIM_CPU *cpu, ADDR a, HI val) -{ - if (! MEM_CHECK_WRITE (a, HI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, HI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_HI); - sim_core_write_2 (CPU_STATE (cpu), sim_core_read_map, a, val); +#define DECLARE_GETT(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETT,mode) (unsigned char *p) \ +{ \ + mode tmp; \ + memcpy (&tmp, p, sizeof (mode)); \ + return XCONCAT2 (T2H_,size) (tmp); \ } #else -extern void SETMEMHI (SIM_CPU *, ADDR, HI); +#define DECLARE_GETT(mode, size) \ +extern mode XCONCAT2 (GETT,mode) (unsigned char *); #endif -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMSI (SIM_CPU *cpu, ADDR a, SI val) -{ - if (! MEM_CHECK_WRITE (a, SI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, SI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_SI); - sim_core_write_4 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMSI (SIM_CPU *, ADDR, SI); -#endif +DECLARE_GETT (QI, 1) +DECLARE_GETT (UQI, 1) +DECLARE_GETT (HI, 2) +DECLARE_GETT (UHI, 2) +DECLARE_GETT (SI, 4) +DECLARE_GETT (USI, 4) +DECLARE_GETT (DI, 8) +DECLARE_GETT (UDI, 8) -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMDI (SIM_CPU *cpu, ADDR a, DI val) -{ - if (! MEM_CHECK_WRITE (a, DI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, DI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_DI); - sim_core_write_8 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMDI (SIM_CPU *, ADDR, DI); -#endif +#undef DECLARE_GETT -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMUQI (SIM_CPU *cpu, ADDR a, UQI val) -{ - if (! MEM_CHECK_WRITE (a, UQI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, UQI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_UQI); - sim_core_write_1 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMUQI (SIM_CPU *, ADDR, UQI); -#endif +/* SETT: translate host value to target value and store at P. + ??? How inefficient is the current implementation? */ #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMUHI (SIM_CPU *cpu, ADDR a, UHI val) -{ - if (! MEM_CHECK_WRITE (a, UHI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, UHI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_UHI); - sim_core_write_2 (CPU_STATE (cpu), sim_core_read_map, a, val); +#define DECLARE_SETT(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (SETT,mode) (unsigned char *buf, mode val) \ +{ \ + mode tmp; \ + tmp = XCONCAT2 (H2T_,size) (val); \ + memcpy (buf, &tmp, sizeof (mode)); \ } #else -extern void SETMEMUHI (SIM_CPU *, ADDR, UHI); +#define DECLARE_SETT(mode, size) \ +extern mode XCONCAT2 (GETT,mode) (unsigned char *, mode); #endif -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMUSI (SIM_CPU *cpu, ADDR a, USI val) -{ - if (! MEM_CHECK_WRITE (a, USI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, USI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_USI); - sim_core_write_4 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMUSI (SIM_CPU *, ADDR, USI); -#endif +DECLARE_SETT (QI, 1) +DECLARE_SETT (UQI, 1) +DECLARE_SETT (HI, 2) +DECLARE_SETT (UHI, 2) +DECLARE_SETT (SI, 4) +DECLARE_SETT (USI, 4) +DECLARE_SETT (DI, 8) +DECLARE_SETT (UDI, 8) -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -MEMOPS_INLINE void -SETMEMUDI (SIM_CPU *cpu, ADDR a, UDI val) -{ - if (! MEM_CHECK_WRITE (a, UDI)) - { engine_signal (cpu, SIM_SIGACCESS); return; } - if (! MEM_CHECK_ALIGNMENT (a, UDI)) - { engine_signal (cpu, SIM_SIGALIGN); return; } - PROFILE_COUNT_WRITE (cpu, a, MODE_UDI); - sim_core_write_8 (CPU_STATE (cpu), sim_core_read_map, a, val); -} -#else -extern void SETMEMUDI (SIM_CPU *, ADDR, UDI); -#endif +#undef DECLARE_SETT -#endif /* CGEN_MEMS_H */ +#endif /* CGEN_MEM_H */ diff --git a/sim/common/cgen-sim.h b/sim/common/cgen-sim.h index d6c405a..3fb84b0 100644 --- a/sim/common/cgen-sim.h +++ b/sim/common/cgen-sim.h @@ -21,8 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef CGEN_SIM_H #define CGEN_SIM_H -#include "sim-xcat.h" - #define PC CPU (h_pc) /* Instruction field support macros. */ @@ -44,18 +42,54 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Forward decls. Defined in the machine generated arch.h and cpu.h files. */ typedef struct argbuf ARGBUF; typedef struct scache SCACHE; -typedef struct parallel_exec PARALLEL_EXEC; +typedef struct parexec PAREXEC; + +#ifdef SCACHE_P + +/* instruction address */ +typedef PCADDR IADDR; +/* current instruction address */ +typedef PCADDR CIA; +/* argument to semantic functions */ +typedef SCACHE *SEM_ARG; + +#else /* ! SCACHE_P */ + +/* instruction address */ +typedef PCADDR IADDR; +/* current instruction address */ +typedef PCADDR CIA; +/* argument to semantic functions */ +typedef ARGBUF *SEM_ARG; + +#endif /* ! SCACHE_P */ + +/* Semantic functions come in two versions on two axis: + fast and full (featured), and using or not using scache. + A full featured simulator is always provided. --enable-sim-fast includes + support for fast execution by duplicating the semantic code but leaving + out all features like tracing and profiling. + Using the scache is selected with --enable-sim-scache. */ +/* FIXME: --enable-sim-fast not implemented yet. */ /* Types of the machine generated extract and semantic fns. */ +/* FIXME: Eventually conditionalize EXTRACT_FN on WITH_SCACHE. */ typedef void (EXTRACT_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *); -/* ??? READ_FN isn't currently used anywhere, we always use a switch. */ -typedef void (READ_FN) (SIM_CPU *, PCADDR, insn_t, PARALLEL_EXEC *); -/*typedef CIA (SEMANTIC_FN) (SEM_ARG);*/ -typedef PCADDR (SEMANTIC_FN) (SIM_CPU *, ARGBUF *); -#if 0 /* wip */ -typedef void (EXTRACT_CACHE_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *); +#if WITH_SCACHE +#ifdef HAVE_PARALLEL_EXEC +typedef CIA (SEMANTIC_FN) (SIM_CPU *, SCACHE *, PAREXEC *); +#else +typedef CIA (SEMANTIC_FN) (SIM_CPU *, SCACHE *); +#endif +#else /* ! WITH_SCACHE */ +#ifdef HAVE_PARALLEL_EXEC +typedef CIA (SEMANTIC_FN) (SIM_CPU *, ARGBUF *, PAREXEC *); +#else +typedef CIA (SEMANTIC_FN) (SIM_CPU *, ARGBUF *); #endif -typedef PCADDR (SEMANTIC_CACHE_FN) (SIM_CPU *, SCACHE *); +#endif + +/* DECODE struct, there is one per instruction. */ typedef struct { /* Using cgen_insn_type requires -opc.h. */ @@ -70,7 +104,7 @@ typedef struct { #endif #endif SEMANTIC_FN *semantic; - SEMANTIC_CACHE_FN *semantic_fast; + SEMANTIC_FN *semantic_fast; #if WITH_SEM_SWITCH_FULL && defined (__GNUC__) /* Set at runtime. */ void *sem_full_lab; @@ -81,33 +115,6 @@ typedef struct { #endif } DECODE; -/* Execution support. - - Semantic functions come in two versions. - One that uses the cache, and one that doesn't. - ??? The one that doesn't may eventually be thrown away or replaced with - something else. */ - -#ifdef SCACHE_P - -/* instruction address */ -typedef PCADDR IADDR; -/* current instruction address */ -typedef PCADDR CIA; -/* argument to semantic functions */ -typedef SCACHE *SEM_ARG; - -#else /* ! SCACHE_P */ - -/* instruction address */ -typedef PCADDR IADDR; -/* current instruction address */ -typedef PCADDR CIA; -/* argument to semantic functions */ -typedef ARGBUF *SEM_ARG; - -#endif /* ! SCACHE_P */ - /* Scache data for each cpu. */ typedef struct cpu_scache { @@ -182,17 +189,16 @@ do { \ #define EXEC_SEQUENCE 0 #define EXEC_PARALLEL 1 +/* These are used so that we can compile two copies of the semantic code, + one with full feature support and one without. */ +/* FIXME: Eventually delete extraction if not using scache. */ +#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn) +#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn) + #ifdef SCACHE_P #define CIA_ADDR(cia) (cia) -/* These are used so that we can compile two copies of the semantic code, - one with scache support and one without. */ -/* FIXME: Do we want _ex_ or _exc_? */ -/*#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_exc_,fn)*/ -#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn) -#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semc_,fn) - /* extract.c support */ /* scache_unset is a cache entry that is never used. It's raison d'etre is so BRANCH_VIA_CACHE doesn't have to test for @@ -215,11 +221,6 @@ do { (fld) = (val); } while (0) #define CIA_ADDR(cia) (cia) -/* These are used so that we can compile two copies of the semantic code, - one with scache support and one without. */ -#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn) -#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn) - /* extract.c support */ #define RECORD_IADDR(fld, val) \ do { (fld) = (val); } while (0) diff --git a/sim/common/sim-alu.h b/sim/common/sim-alu.h index e556dce..8473680 100644 --- a/sim/common/sim-alu.h +++ b/sim/common/sim-alu.h @@ -23,48 +23,203 @@ #ifndef _SIM_ALU_H_ #define _SIM_ALU_H_ -#include "sim-xcat.h" +#include "symcat.h" -/* Binary addition, carry and overflow: +/* INTEGER ALU MODULE: + This module provides an implementation of 2's complement arithmetic + including the recording of carry and overflow status bits. - Overflow - method 1: - Overflow occures when the sign of the two operands is identical but - different to the sign of the result: + EXAMPLE: - SIGN_BIT (~(a ^ b) & ((a + b) ^ b)) + Code using this module includes it into sim-main.h and then, as a + convention, defines macro's ALU*_END that records the result of any + aritmetic performed. Ex: - Note that, for subtraction, care must be taken with MIN_INTn. + #include "sim-alu.h" + #define ALU32_END(RES) \ + (RES) = ALU32_OVERFLOW_RESULT; \ + carry = ALU32_HAD_CARRY_BORROW; \ + overflow = ALU32_HAD_OVERFLOW + The macro's are then used vis: + + { + ALU32_BEGIN (GPR[i]); + ALU32_ADDC (GPR[j]); + ALU32_END (GPR[k]); + } + + + NOTES: + + Macros exist for efficiently computing 8, 16, 32 and 64 bit + arithmetic - ALU8_*, ALU16_*, .... In addition, according to + TARGET_WORD_BITSIZE a set of short-hand macros are defined - ALU_* + + Initialization: + + ALU*_BEGIN(ACC): Declare initialize the ALU accumulator with ACC. + + Results: + + The calculation of the final result may be computed a number + of different ways. Three different overflow macro's are + defined, the most efficient one to use depends on which other + outputs from the alu are being used. + + ALU*_RESULT: Generic ALU result output. + + ALU*_HAD_OVERFLOW: Returns a nonzero value if signed overflow + occured. + + ALU*_OVERFLOW_RESULT: If the macro ALU*_HAD_OVERFLOW is being + used this is the most efficient result available. Ex: + + #define ALU16_END(RES) \ + if (ALU16_HAD_OVERFLOW) \ + sim_engine_halt (...); \ + (RES) = ALU16_OVERFLOW_RESULT + + ALU*_HAD_CARRY_BORROW: Returns a nonzero value if unsigned + overflow or underflow (also refered to as carry and borrow) + occured. + + ALU*_CARRY_BORROW_RESULT: If the macro ALU*_HAD_CARRY_BORROW is being + used this is the most efficient result available. Ex: + + #define ALU64_END(RES) \ + State.carry = ALU64_HAD_CARRY_BORROW; \ + (RES) = ALU64_CARRY_BORROW_RESULT + + + Addition: + + ALU*_ADD(VAL): Add VAL to the ALU accumulator. Record any + overflow as well as the final result. + + ALU*_ADDC(VAL): Add VAL to the ALU accumulator. Record any + carry-out or overflow as well as the final result. + + ALU*_ADDC_C(VAL,CI): Add VAL and CI (carry-in). Record any + carry-out or overflow as well as the final result. + + Subtraction: + + ALU*_SUB(VAL): Subtract VAL from the ALU accumulator. Record + any underflow as well as the final result. + + ALU*_SUBC(VAL): Subtract VAL from the ALU accumulator using + negated addition. Record any underflow or carry-out as well + as the final result. + + ALU*_SUBB(VAL): Subtract VAL from the ALU accumulator using + direct subtraction (ACC+~VAL+1). Record any underflow or + borrow-out as well as the final result. + + ALU*_SUBC_X(VAL,CI): Subtract VAL and CI (carry-in) from the + ALU accumulator using extended negated addition (ACC+~VAL+CI). + Record any underflow or carry-out as well as the final result. + + ALU*_SUBB_B(VAL,BI): Subtract VAL and BI (borrow-in) from the + ALU accumulator using direct subtraction. Record any + underflow or borrow-out as well as the final result. + + + */ + + + +/* Twos complement aritmetic - addition/subtraction - carry/borrow + (or you thought you knew the answer to 0-0) + + + + Notation and Properties: + + + Xn denotes the value X stored in N bits. + + MSBn (X): The most significant (sign) bit of X treated as an N bit + value. + + SEXTn (X): The infinite sign extension of X treated as an N bit + value. + + MAXn, MINn: The upper and lower bound of a signed, two's + complement N bit value. + + UMAXn: The upper bound of an unsigned N bit value (the lower + bound is always zero). + + Un: UMAXn + 1. Unsigned arrithmetic is computed `modulo (Un)'. + + X[p]: Is bit P of X. X[0] denotes the least signifant bit. + + ~X[p]: Is the inversion of bit X[p]. Also equal to 1-X[p], + (1+X[p])mod(2). + + + + Addition - Overflow - Introduction: + + + Overflow/Overflow indicates an error in computation of signed + arrithmetic. i.e. given X,Y in [MINn..MAXn]; overflow + indicates that the result X+Y > MAXn or X+Y < MIN_INTx. + + Hardware traditionally implements overflow by computing the XOR of + carry-in/carry-out of the most significant bit of the ALU. Here + other methods need to be found. + + + + Addition - Overflow - method 1: + + + Overflow occures when the sign (most significant bit) of the two N + bit operands is identical but different to the sign of the result: + + Rn = (Xn + Yn) + V = MSBn (~(Xn ^ Yn) & (Rn ^ Xn)) + + + + Addition - Overflow - method 2: - Overflow - method 2: The two N bit operands are sign extended to M>N bits and then added. Overflow occures when SIGN_BIT and SIGN_BIT do not match. - SIGN_BIT (r >> (M-N) ^ r) + Rm = (SEXTn (Xn) + SEXTn (Yn)) + V = MSBn ((Rm >> (M - N)) ^ Rm) + - Overflow - method 3: + Addition - Overflow - method 3: + The two N bit operands are sign extended to M>N bits and then - added. Overflow occures when the result is outside of signextended - MIN_INTn, MAX_INTn. + added. Overflow occures when the result is outside of the sign + extended range [MINn .. MAXn]. + - Overflow - method 4: + Addition - Overflow - method 4: - Given the carry bit, the overflow can be computed using the - equation: - SIGN_BIT (((A ^ B) ^ R) ^ C) + Given the Result and Carry-out bits, the oVerflow from the addition + of X, Y and carry-In can be computed using the equation: + + Rn = (Xn + Yn) + V = (MSBn ((Xn ^ Yn) ^ Rn)) ^ C) As shown in the table below: - I A B R C | V | A^B ^R ^C + I X Y R C | V | X^Y ^R ^C ---------------+---+------------- 0 0 0 0 0 | 0 | 0 0 0 0 0 1 1 0 | 0 | 1 0 0 @@ -77,11 +232,17 @@ - Carry - method 1: + Addition - Carry - Introduction: + - Consider the truth table (carryIn, Result, Carryout, Result): + Carry (poorly named) indicates that an overflow occured for + unsigned N bit addition. i.e. given X, Y in [0..UMAXn] then + carry indicates X+Y > UMAXn or X+Y >= Un. - I A B R | C + The following table lists the output for all given inputs into a + full-adder. + + I X Y R | C ------------+--- 0 0 0 0 | 0 0 0 1 1 | 0 @@ -92,9 +253,16 @@ 1 1 0 0 | 1 1 1 1 1 | 1 - Looking at the terms A, B and R we want an equation for C. + (carry-In, X, Y, Result, Carry-out): + + + + Addition - Carry - method 1: + + + Looking at the terms X, Y and R we want an equation for C. - AB\R 0 1 + XY\R 0 1 +------- 00 | 0 0 01 | 1 0 @@ -103,11 +271,11 @@ This giving us the sum-of-prod equation: - SIGN_BIT ((A & B) | (A & ~R) | (B & ~R)) + MSBn ((Xn & Yn) | (Xn & ~Rn) | (Yn & ~Rn)) Verifying: - I A B R | C | A&B A&~R B&~R + I X Y R | C | X&Y X&~R Y&~R ------------+---+--------------- 0 0 0 0 | 0 | 0 0 0 0 0 1 1 | 0 | 0 0 0 @@ -120,32 +288,136 @@ - Carry - method 2: + Addition - Carry - method 2: + Given two signed N bit numbers, a carry can be detected by treating the numbers as N bit unsigned and adding them using M>N unsigned arrithmetic. Carry is indicated by bit (1 << N) being set (result >= 2**N). - SIGN_BITm (r) - Carry - method 3: + Addition - Carry - method 3: + - Given the overflow bit. The carry can be computed from: + Given the oVerflow bit. The carry can be computed from: (~R&V) | (R&V) - Carry - method 4: - Add the two signed N bit numbers as unsigned N bit numbers, and then - compare the result to either one of the inputs via unsigned compare. - If the result is less than the inputs, carry occurred. - C = ((unsigned)(a+b)) < (unsigned)a if adding - (or) - C = (unsigned)a < (unsigned)b if subtracting - */ + Addition - Carry - method 4: + + Given two signed numbers. Treating them as unsigned we have: + + 0 <= X < Un, 0 <= Y < Un + ==> X + Y < 2 Un + + Consider Y when carry occures: + + X + Y >= Un, Y < Un + ==> (Un - X) <= Y < Un # re-arange + ==> Un <= X + Y < Un + X < 2 Un # add Xn + ==> 0 <= (X + Y) mod Un < X mod Un + + or when carry as occured: + + (X + Y) mod Un < X mod Un + + Consider Y when carry does not occure: + + X + Y < Un + have X < Un, Y >= 0 + ==> X <= X + Y < Un + ==> X mod Un <= (X + Y) mod Un + + or when carry has not occured: + + ! ( (X + Y) mod Un < X mod Un) + + + + Subtraction - Introduction + + + There are two different ways of computing the signed two's + complement difference of two numbers. The first is based on + negative addition, the second on direct subtraction. + + + + Subtraction - Carry - Introduction - Negated Addition + + + The equation X - Y can be computed using: + + X + (-Y) + ==> X + ~Y + 1 # -Y = ~Y + 1 + + In addition to the result, the equation produces Carry-out. For + succeeding extended prrcision calculations, the more general + equation can be used: + + C[p]:R[p] = X[p] + ~Y[p] + C[p-1] + where C[0]:R[0] = X[0] + ~Y[0] + 1 + + + + Subtraction - Borrow - Introduction - Direct Subtraction + + + The alternative to negative addition is direct subtraction where + `X-Y is computed directly. In addition to the result of the + calculation, a Borrow bit is produced. In general terms: + + B[p]:R[p] = X[p] - Y[p] - B[p-1] + where B[0]:R[0] = X[0] - Y[0] + + The Borrow bit is the complement of the Carry bit produced by + Negated Addition above. A dodgy proof follows: + + Case 0: + C[0]:R[0] = X[0] + ~Y[0] + 1 + ==> C[0]:R[0] = X[0] + 1 - Y[0] + 1 # ~Y[0] = (1 - Y[0])? + ==> C[0]:R[0] = 2 + X[0] - Y[0] + ==> C[0]:R[0] = 2 + B[0]:R[0] + ==> C[0]:R[0] = (1 + B[0]):R[0] + ==> C[0] = ~B[0] # (1 + B[0]) mod 2 = ~B[0]? + + Case P: + C[p]:R[p] = X[p] + ~Y[p] + C[p-1] + ==> C[p]:R[p] = X[p] + 1 - Y[0] + 1 - B[p-1] + ==> C[p]:R[p] = 2 + X[p] - Y[0] - B[p-1] + ==> C[p]:R[p] = 2 + B[p]:R[p] + ==> C[p]:R[p] = (1 + B[p]):R[p] + ==> C[p] = ~B[p] + + The table below lists all possible inputs/outputs for a + full-subtractor: + + X Y I | R B + 0 0 0 | 0 0 + 0 0 1 | 1 1 + 0 1 0 | 1 1 + 0 1 1 | 0 1 + 1 0 0 | 1 0 + 1 0 1 | 0 0 + 1 1 0 | 0 0 + 1 1 1 | 1 1 + + + + Subtraction - Method 1 + + + Treating Xn and Yn as unsigned values then a borrow (unsigned + underflow) occures when: + + B = Xn < Yn + ==> C = Xn >= Yn + + */ @@ -155,26 +427,26 @@ overflow method 2 are used. */ #define ALU8_BEGIN(VAL) \ -signed alu8_cr = (unsigned8) (VAL); \ -unsigned alu8_vr = (signed8) (alu8_cr) +unsigned alu8_cr = (unsigned8) (VAL); \ +signed alu8_vr = (signed8) (alu8_cr) #define ALU8_SET(VAL) \ alu8_cr = (unsigned8) (VAL); \ alu8_vr = (signed8) (alu8_cr) -#define ALU8_SET_CARRY(CARRY) \ +#define ALU8_SET_CARRY_BORROW(CARRY) \ do { \ if (CARRY) \ alu8_cr |= ((signed)-1) << 8; \ else \ alu8_cr &= 0xff; \ } while (0) - -#define ALU8_HAD_CARRY (alu8_cr & LSBIT32(8)) + +#define ALU8_HAD_CARRY_BORROW (alu8_cr & LSBIT32(8)) #define ALU8_HAD_OVERFLOW (((alu8_vr >> 8) ^ alu8_vr) & LSBIT32 (8-1)) #define ALU8_RESULT ((unsigned8) alu8_cr) -#define ALU8_CARRY_RESULT ((unsigned8) alu8_cr) +#define ALU8_CARRY_BORROW_RESULT ((unsigned8) alu8_cr) #define ALU8_OVERFLOW_RESULT ((unsigned8) alu8_vr) /* #define ALU8_END ????? - target dependant */ @@ -194,7 +466,7 @@ unsigned alu16_vr = (signed16) (alu16_cr) alu16_cr = (unsigned16) (VAL); \ alu16_vr = (signed16) (alu16_cr) -#define ALU16_SET_CARRY(CARRY) \ +#define ALU16_SET_CARRY_BORROW(CARRY) \ do { \ if (CARRY) \ alu16_cr |= ((signed)-1) << 16; \ @@ -202,11 +474,11 @@ do { \ alu16_cr &= 0xffff; \ } while (0) -#define ALU16_HAD_CARRY (alu16_cr & LSBIT32(16)) +#define ALU16_HAD_CARRY_BORROW (alu16_cr & LSBIT32(16)) #define ALU16_HAD_OVERFLOW (((alu16_vr >> 16) ^ alu16_vr) & LSBIT32 (16-1)) #define ALU16_RESULT ((unsigned16) alu16_cr) -#define ALU16_CARRY_RESULT ((unsigned16) alu16_cr) +#define ALU16_CARRY_BORROW_RESULT ((unsigned16) alu16_cr) #define ALU16_OVERFLOW_RESULT ((unsigned16) alu16_vr) /* #define ALU16_END ????? - target dependant */ @@ -216,10 +488,7 @@ do { \ /* 32 bit target expressions: Since most hosts do not support 64 (> 32) bit arrithmetic, carry - method 4 and overflow method 4 are used. - - FIXME: 64 bit hosts should use the same method as for the 16 bit - ALU. */ + method 4 and overflow method 4 are used. */ #define ALU32_BEGIN(VAL) \ unsigned32 alu32_r = (VAL); \ @@ -231,13 +500,13 @@ alu32_r = (VAL); \ alu32_c = 0; \ alu32_v = 0 -#define ALU32_SET_CARRY(CARRY) alu32_c = (CARRY) +#define ALU32_SET_CARRY_BORROW(CARRY) alu32_c = (CARRY) +#define ALU32_HAD_CARRY_BORROW (alu32_c) #define ALU32_HAD_OVERFLOW (alu32_v) -#define ALU32_HAD_CARRY (alu32_c) #define ALU32_RESULT (alu32_r) -#define ALU32_CARRY_RESULT (alu32_r) +#define ALU32_CARRY_BORROW_RESULT (alu32_r) #define ALU32_OVERFLOW_RESULT (alu32_r) @@ -257,13 +526,13 @@ alu64_r = (VAL); \ alu64_c = 0; \ alu64_v = 0 -#define ALU64_SET_CARRY(CARRY) alu64_c = (CARRY) +#define ALU64_SET_CARRY_BORROW(CARRY) alu64_c = (CARRY) -#define ALU64_HAD_CARRY (alu64_c) +#define ALU64_HAD_CARRY_BORROW (alu64_c) #define ALU64_HAD_OVERFLOW (alu64_v) #define ALU64_RESULT (alu64_r) -#define ALU64_CARRY_RESULT (alu64_r) +#define ALU64_CARRY_BORROW_RESULT (alu64_r) #define ALU64_OVERFLOW_RESULT (alu64_r) @@ -283,141 +552,402 @@ alu64_v = 0 -/* Basic operations */ - +/* Basic operation - add (overflowing) */ #define ALU8_ADD(VAL) \ do { \ - unsigned8 alu8_tmp = (VAL); \ - alu8_cr += (unsigned8)(alu8_tmp); \ - alu8_vr += (signed8)(alu8_tmp); \ + unsigned8 alu8add_val = (VAL); \ + ALU8_ADDC (alu8add_val); \ } while (0) #define ALU16_ADD(VAL) \ do { \ - unsigned16 alu16_tmp = (VAL); \ - alu16_cr += (unsigned16)(alu16_tmp); \ - alu16_vr += (signed16)(alu16_tmp); \ + unsigned16 alu16add_val = (VAL); \ + ALU16_ADDC (alu8add_val); \ } while (0) #define ALU32_ADD(VAL) \ do { \ - unsigned32 alu32_tmp = (unsigned32) (VAL); \ - unsigned32 alu32_sign = alu32_tmp ^ alu32_r; \ - alu32_r += (alu32_tmp); \ - alu32_c = (alu32_r < alu32_tmp); \ - alu32_v = ((alu32_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ + unsigned32 alu32add_val = (VAL); \ + ALU32_ADDC (alu32add_val); \ } while (0) #define ALU64_ADD(VAL) \ do { \ - unsigned64 alu64_tmp = (unsigned64) (VAL); \ - unsigned64 alu64_sign = alu64_tmp ^ alu64_r; \ - alu64_r += (alu64_tmp); \ - alu64_c = (alu64_r < alu64_tmp); \ - alu64_v = ((alu64_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \ + unsigned64 alu64add_val = (unsigned64) (VAL); \ + ALU64_ADDC (alu64add_val); \ +} while (0) + +#define ALU_ADD XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD) + + + +/* Basic operation - add carrying (and overflowing) */ + +#define ALU8_ADDC(VAL) \ +do { \ + unsigned8 alu8addc_val = (VAL); \ + alu8_cr += (unsigned8)(alu8addc_val); \ + alu8_vr += (signed8)(alu8addc_val); \ +} while (0) + +#define ALU16_ADDC(VAL) \ +do { \ + unsigned16 alu16addc_val = (VAL); \ + alu16_cr += (unsigned16)(alu16addc_val); \ + alu16_vr += (signed16)(alu16addc_val); \ } while (0) -#define ALU_ADD(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)(VAL) +#define ALU32_ADDC(VAL) \ +do { \ + unsigned32 alu32addc_val = (VAL); \ + unsigned32 alu32addc_sign = alu32addc_val ^ alu32_r; \ + alu32_r += (alu32addc_val); \ + alu32_c = (alu32_r < alu32addc_val); \ + alu32_v = ((alu32addc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ +} while (0) + +#define ALU64_ADDC(VAL) \ +do { \ + unsigned64 alu64addc_val = (unsigned64) (VAL); \ + unsigned64 alu64addc_sign = alu64addc_val ^ alu64_r; \ + alu64_r += (alu64addc_val); \ + alu64_c = (alu64_r < alu64addc_val); \ + alu64_v = ((alu64addc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \ +} while (0) + +#define ALU_ADDC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC) -#define ALU8_ADD_CA(VAL) \ +/* Compound operation - add carrying (and overflowing) with carry-in */ + +#define ALU8_ADDC_C(VAL,C) \ do { \ - unsigned8 alu8_ca_tmp = (VAL) + ALU8_HAD_CARRY; \ - ALU8_ADD(alu8_ca_tmp); \ + unsigned8 alu8addcc_val = (VAL); \ + unsigned8 alu8addcc_c = (C); \ + alu8_cr += (unsigned)(unsigned8)alu8addcc_val + alu8addcc_c; \ + alu8_vr += (signed)(signed8)(alu8addcc_val) + alu8addcc_c; \ } while (0) -#define ALU16_ADD_CA(VAL) \ +#define ALU16_ADDC_C(VAL,C) \ do { \ - unsigned16 alu16_ca_tmp = (VAL) + ALU16_HAD_CARRY; \ - ALU16_ADD(alu16_ca_tmp); \ + unsigned16 alu16addcc_val = (VAL); \ + unsigned16 alu16addcc_c = (C); \ + alu16_cr += (unsigned)(unsigned16)alu16addcc_val + alu16addcc_c; \ + alu16_vr += (signed)(signed16)(alu16addcc_val) + alu16addcc_c; \ } while (0) -#define ALU32_ADD_CA(VAL) \ +#define ALU32_ADDC_C(VAL,C) \ do { \ - unsigned32 alu32_ca_tmp = (VAL) + ALU32_HAD_CARRY; \ - ALU32_ADD(alu32_ca_tmp); \ + unsigned32 alu32addcc_val = (VAL); \ + unsigned32 alu32addcc_c = (C); \ + unsigned32 alu32addcc_sign = (alu32addcc_val ^ alu32_r); \ + alu32_r += (alu32addcc_val + alu32addcc_c); \ + alu32_c = ((alu32_r < alu32addcc_val) \ + || (alu32addcc_c && alu32_r == alu32addcc_val)); \ + alu32_v = ((alu32addcc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31;\ } while (0) -#define ALU64_ADD_CA(VAL) \ +#define ALU64_ADDC_C(VAL,C) \ do { \ - unsigned64 alu64_ca_tmp = (VAL) + ALU64_HAD_CARRY; \ - ALU64_ADD(alu64_ca_tmp); \ + unsigned64 alu64addcc_val = (VAL); \ + unsigned64 alu64addcc_c = (C); \ + unsigned64 alu64addcc_sign = (alu64addcc_val ^ alu64_r); \ + alu64_r += (alu64addcc_val + alu64addcc_c); \ + alu64_c = ((alu64_r < alu64addcc_val) \ + || (alu64addcc_c && alu64_r == alu64addcc_val)); \ + alu64_v = ((alu64addcc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63;\ } while (0) -#define ALU_ADD_CA(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD_CA)(VAL) +#define ALU_ADDC_C XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC_C) -/* Remember: Hardware implements subtract as an ADD with a carry in of - 1 into the least significant bit */ +/* Basic operation - subtract (overflowing) */ #define ALU8_SUB(VAL) \ do { \ - signed alu8sub_val = ~(VAL); \ - ALU8_ADD (alu8sub_val); \ - ALU8_ADD (1); \ + unsigned8 alu8sub_val = (VAL); \ + ALU8_ADDC_C (~alu8sub_val, 1); \ } while (0) #define ALU16_SUB(VAL) \ do { \ - signed alu16sub_val = ~(VAL); \ - ALU16_ADD (alu16sub_val); \ - ALU16_ADD (1); \ + unsigned16 alu16sub_val = (VAL); \ + ALU16_ADDC_C (~alu16sub_val, 1); \ } while (0) #define ALU32_SUB(VAL) \ do { \ - unsigned32 alu32_tmp = (unsigned32) (VAL); \ - unsigned32 alu32_sign = alu32_tmp ^ alu32_r; \ - alu32_c = (alu32_r < alu32_tmp); \ - alu32_r -= (alu32_tmp); \ - alu32_v = ((alu32_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ + unsigned32 alu32sub_val = (VAL); \ + ALU32_ADDC_C (~alu32sub_val, 1); \ } while (0) #define ALU64_SUB(VAL) \ do { \ - unsigned64 alu64_tmp = (unsigned64) (VAL); \ - unsigned64 alu64_sign = alu64_tmp ^ alu64_r; \ - alu64_c = (alu64_r < alu64_tmp); \ - alu64_r -= (alu64_tmp); \ - alu64_v = ((alu64_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \ + unsigned64 alu64sub_val = (VAL); \ + ALU64_ADDC_C (~alu64sub_val, 1); \ +} while (0) + +#define ALU_SUB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB) + + + +/* Basic operation - subtract carrying (and overflowing) */ + +#define ALU8_SUBC(VAL) \ +do { \ + unsigned8 alu8subc_val = (VAL); \ + ALU8_ADDC_C (~alu8subc_val, 1); \ } while (0) -#define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL) +#define ALU16_SUBC(VAL) \ +do { \ + unsigned16 alu16subc_val = (VAL); \ + ALU16_ADDC_C (~alu16subc_val, 1); \ +} while (0) +#define ALU32_SUBC(VAL) \ +do { \ + unsigned32 alu32subc_val = (VAL); \ + ALU32_ADDC_C (~alu32subc_val, 1); \ +} while (0) + +#define ALU64_SUBC(VAL) \ +do { \ + unsigned64 alu64subc_val = (VAL); \ + ALU64_ADDC_C (~alu64subc_val, 1); \ +} while (0) +#define ALU_SUBC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC) -#define ALU8_SUB_CA(VAL) \ + +/* Compound operation - subtract carrying (and overflowing), extended */ + +#define ALU8_SUBC_X(VAL,C) \ do { \ - unsigned8 alu8_ca_tmp = (VAL) + ALU8_HAD_CARRY; \ - ALU8_SUB(alu8_ca_tmp); \ + unsigned8 alu8subcx_val = (VAL); \ + unsigned8 alu8subcx_c = (C); \ + ALU8_ADDC_C (~alu8subcx_val, alu8subcx_c); \ } while (0) -#define ALU16_SUB_CA(VAL) \ +#define ALU16_SUBC_X(VAL,C) \ do { \ - unsigned16 alu16_ca_tmp = (VAL) + ALU16_HAD_CARRY; \ - ALU16_SUB(alu16_ca_tmp); \ + unsigned16 alu16subcx_val = (VAL); \ + unsigned16 alu16subcx_c = (C); \ + ALU16_ADDC_C (~alu16subcx_val, alu16subcx_c); \ } while (0) -#define ALU32_SUB_CA(VAL) \ +#define ALU32_SUBC_X(VAL,C) \ do { \ - unsigned32 alu32_ca_tmp = (VAL) + ALU32_HAD_CARRY; \ - ALU32_SUB(alu32_ca_tmp); \ + unsigned32 alu32subcx_val = (VAL); \ + unsigned32 alu32subcx_c = (C); \ + ALU32_ADDC_C (~alu32subcx_val, alu32subcx_c); \ } while (0) -#define ALU64_SUB_CA(VAL) \ +#define ALU64_SUBC_X(VAL,C) \ +do { \ + unsigned64 alu64subcx_val = (VAL); \ + unsigned64 alu64subcx_c = (C); \ + ALU64_ADDC_C (~alu64subcx_val, alu64subcx_c); \ +} while (0) + +#define ALU_SUBC_X XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC_X) + + + +/* Basic operation - subtract borrowing (and overflowing) */ + +#define ALU8_SUBB(VAL) \ +do { \ + unsigned8 alu8subb_val = (VAL); \ + alu8_cr -= (unsigned)(unsigned8)alu8subb_val; \ + alu8_vr -= (signed)(signed8)alu8subb_val; \ +} while (0) + +#define ALU16_SUBB(VAL) \ +do { \ + unsigned16 alu16subb_val = (VAL); \ + alu16_cr -= (unsigned)(unsigned16)alu16subb_val; \ + alu16_vr -= (signed)(signed16)alu16subb_val; \ +} while (0) + +#define ALU32_SUBB(VAL) \ +do { \ + unsigned32 alu32subb_val = (VAL); \ + unsigned32 alu32subb_sign = alu32subb_val ^ alu32_r; \ + alu32_c = (alu32_r < alu32subb_val); \ + alu32_r -= (alu32subb_val); \ + alu32_v = ((alu32subb_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ +} while (0) + +#define ALU64_SUBB(VAL) \ +do { \ + unsigned64 alu64subb_val = (VAL); \ + unsigned64 alu64subb_sign = alu64subb_val ^ alu64_r; \ + alu64_c = (alu64_r < alu64subb_val); \ + alu64_r -= (alu64subb_val); \ + alu64_v = ((alu64subb_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 31; \ +} while (0) + +#define ALU_SUBB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB) + + + +/* Compound operation - subtract borrowing (and overflowing) with borrow-in */ + +#define ALU8_SUBB_B(VAL,B) \ +do { \ + unsigned8 alu8subbb_val = (VAL); \ + unsigned8 alu8subbb_b = (B); \ + alu8_cr -= (unsigned)(unsigned8)alu8subbb_val; \ + alu8_cr -= (unsigned)(unsigned8)alu8subbb_b; \ + alu8_vr -= (signed)(signed8)alu8subbb_val + alu8subbb_b; \ +} while (0) + +#define ALU16_SUBB_B(VAL,B) \ +do { \ + unsigned16 alu16subbb_val = (VAL); \ + unsigned16 alu16subbb_b = (B); \ + alu16_cr -= (unsigned)(unsigned16)alu16subbb_val; \ + alu16_cr -= (unsigned)(unsigned16)alu16subbb_b; \ + alu16_vr -= (signed)(signed16)alu16subbb_val + alu16subbb_b; \ +} while (0) + +#define ALU32_SUBB_B(VAL,B) \ +do { \ + unsigned32 alu32subbb_val = (VAL); \ + unsigned32 alu32subbb_b = (B); \ + ALU32_ADDC_C (~alu32subbb_val, !alu32subbb_b); \ + alu32_c = !alu32_c; \ +} while (0) + +#define ALU64_SUBB_B(VAL,B) \ +do { \ + unsigned64 alu64subbb_val = (VAL); \ + unsigned64 alu64subbb_b = (B); \ + ALU64_ADDC_C (~alu64subbb_val, !alu64subbb_b); \ + alu64_c = !alu64_c; \ +} while (0) + +#define ALU_SUBB_B XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB_B) + + + +/* Basic operation - negate (overflowing) */ + +#define ALU8_NEG() \ +do { \ + signed alu8neg_val = (ALU8_RESULT); \ + ALU8_SET (1); \ + ALU8_ADDC (~alu8neg_val); \ +} while (0) + +#define ALU16_NEG() \ +do { \ + signed alu16neg_val = (ALU16_RESULT); \ + ALU16_SET (1); \ + ALU16_ADDC (~alu16neg_val); \ +} while (0) + +#define ALU32_NEG() \ +do { \ + unsigned32 alu32neg_val = (ALU32_RESULT); \ + ALU32_SET (1); \ + ALU32_ADDC (~alu32neg_val); \ +} while(0) + +#define ALU64_NEG() \ do { \ - unsigned64 alu64_ca_tmp = (VAL) + ALU64_HAD_CARRY; \ - ALU64_SUB(alu64_ca_tmp); \ + unsigned64 alu64neg_val = (ALU64_RESULT); \ + ALU64_SET (1); \ + ALU64_ADDC (~alu64neg_val); \ } while (0) -#define ALU_SUB_CA(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)(VAL) +#define ALU_NEG XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEG) + +/* Basic operation - negate carrying (and overflowing) */ + +#define ALU8_NEGC() \ +do { \ + signed alu8negc_val = (ALU8_RESULT); \ + ALU8_SET (1); \ + ALU8_ADDC (~alu8negc_val); \ +} while (0) + +#define ALU16_NEGC() \ +do { \ + signed alu16negc_val = (ALU16_RESULT); \ + ALU16_SET (1); \ + ALU16_ADDC (~alu16negc_val); \ +} while (0) + +#define ALU32_NEGC() \ +do { \ + unsigned32 alu32negc_val = (ALU32_RESULT); \ + ALU32_SET (1); \ + ALU32_ADDC (~alu32negc_val); \ +} while(0) + +#define ALU64_NEGC() \ +do { \ + unsigned64 alu64negc_val = (ALU64_RESULT); \ + ALU64_SET (1); \ + ALU64_ADDC (~alu64negc_val); \ +} while (0) + +#define ALU_NEGC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGC) + + + + +/* Basic operation - negate borrowing (and overflowing) */ + +#define ALU8_NEGB() \ +do { \ + signed alu8negb_val = (ALU8_RESULT); \ + ALU8_SET (0); \ + ALU8_SUBB (alu8negb_val); \ +} while (0) + +#define ALU16_NEGB() \ +do { \ + signed alu16negb_val = (ALU16_RESULT); \ + ALU16_SET (0); \ + ALU16_SUBB (alu16negb_val); \ +} while (0) + +#define ALU32_NEGB() \ +do { \ + unsigned32 alu32negb_val = (ALU32_RESULT); \ + ALU32_SET (0); \ + ALU32_SUBB (alu32negb_val); \ +} while(0) + +#define ALU64_NEGB() \ +do { \ + unsigned64 alu64negb_val = (ALU64_RESULT); \ + ALU64_SET (0); \ + ALU64_SUBB (alu64negb_val); \ +} while (0) + +#define ALU_NEGB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGB) + + + + +/* Other */ + +#define ALU8_OR(VAL) \ +do { \ + error("ALU16_OR"); \ +} while (0) + #define ALU16_OR(VAL) \ do { \ error("ALU16_OR"); \ @@ -465,39 +995,6 @@ do { \ -#define ALU8_NEGATE() \ -do { \ - signed alu8neg_val = ~(ALU8_RESULT); \ - ALU8_SET (1); \ - ALU8_ADD (alu8neg_val); \ -} while (0) - -#define ALU16_NEGATE() \ -do { \ - signed alu16neg_val = ~(ALU16_RESULT); \ - ALU16_SET (1); \ - ALU16_ADD (alu16neg_val); \ -} while (0) - -#define ALU32_NEGATE() \ -do { \ - unsigned32 alu32_tmp_orig = alu32_r; \ - ALU32_SET (0); \ - ALU32_SUB (alu32_tmp_orig); \ -} while(0) - -#define ALU64_NEGATE() \ -do { \ - unsigned64 alu64_tmp_orig = alu64_r; \ - ALU64_SET (0); \ - ALU64_SUB (alu64_tmp_orig); \ -} while (0) - -#define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE) - - - - #define ALU16_AND(VAL) \ do { \ error("ALU_AND16"); \ diff --git a/sim/common/sim-n-core.h b/sim/common/sim-n-core.h index b355e3b..9691021 100644 --- a/sim/common/sim-n-core.h +++ b/sim/common/sim-n-core.h @@ -26,7 +26,15 @@ #define M N #endif -#include "sim-xcat.h" +/* N: The number of bytes of data to transfer. + M: The number of bytes in the type used to transfer the data */ + +#if (N > M) +#error "N (nr bytes of data) must be <= M (nr of bytes in data type)" +#endif + + +#include "symcat.h" /* NOTE: see end of file for #undef of these macros */ @@ -43,6 +51,14 @@ #define sim_core_write_unaligned_N XCONCAT2(sim_core_write_unaligned_,N) #define sim_core_write_misaligned_N XCONCAT2(sim_core_write_misaligned_,N) #define sim_core_trace_M XCONCAT2(sim_core_trace_,M) +#define sim_core_dummy_M XCONCAT2(sim_core_dummy_,M) + + +#if (M == N && N > 1) +/* dummy variable used as a return value when nothing else is + available and the compiler is complaining */ +static unsigned_M sim_core_dummy_M; +#endif /* TAGS: sim_core_trace_1 sim_core_trace_2 */ @@ -148,7 +164,7 @@ sim_core_read_aligned_N(sim_cpu *cpu, #if (WITH_DEVICES) if (WITH_CALLBACK_MEMORY && mapping->device != NULL) { unsigned_M data; - if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N) != N) + if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N) device_error (mapping->device, "internal error - %s - io_read_buffer should not fail", XSTRING (sim_core_read_aligned_N)); val = T2H_M (data); @@ -209,10 +225,7 @@ sim_core_read_unaligned_N(sim_cpu *cpu, "internal error - %s - bad switch", XSTRING (sim_core_read_unaligned_N)); /* to keep some compilers happy, we return a dummy */ - { - unsigned_M val[1] = { 0 }; - return val[0]; - } + return sim_core_dummy_M; } } #endif @@ -372,5 +385,6 @@ sim_core_write_misaligned_N(sim_cpu *cpu, #undef sim_core_write_unaligned_N #undef sim_core_write_misaligned_N #undef sim_core_trace_M +#undef sim_core_dummy_M #undef M #undef N diff --git a/sim/common/sim-xcat.h b/sim/common/sim-xcat.h deleted file mode 100644 index 559a2ac..0000000 --- a/sim/common/sim-xcat.h +++ /dev/null @@ -1,45 +0,0 @@ -/* This file is part of the program GDB. - - Copyright (C) 1997, Free Software Foundation, Inc. - - 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. - - */ - - -/* from Michael Meissner, macro's to handle concating symbols better */ - -#ifndef _SIM_XCAT_H_ -#define _SIM_XCAT_H_ - -#if defined __STDC__ || defined ALMOST_STDC -#define CONCAT2(a,b) a##b -#define CONCAT3(a,b,c) a##b##c -#define CONCAT4(a,b,c,d) a##b##c##d -#define STRINGX(s) #s -#else -#define CONCAT2(a,b) a/**/b -#define CONCAT3(a,b,c) a/**/b/**/c -#define CONCAT4(a,b,c,d) a/**/b/**/c/**/d -#define STRINGX(s) "?" -#endif - -#define XCONCAT2(a,b) CONCAT2(a,b) -#define XCONCAT3(a,b,c) CONCAT3(a,b,c) -#define XCONCAT4(a,b,c,d) CONCAT4(a,b,c,d) - -#define XSTRING(s) STRINGX(s) - -#endif _SIM_XCAT_H_