/**
 * TrueReality - N64/rsp_mnemonic.h
 * Copyright (C) 1998, 1999 Niki W. Waibel
 *
 * This program is free software; you can redistribute it and/
 * or modify it under the terms of the GNU General Public Li-
 * cence as published by the Free Software Foundation; either
 * version 2 of the Licence, or any later version.
 *
 * This program is distributed in the hope that it will be use-
 * ful, but WITHOUT ANY WARRANTY; without even the implied war-
 * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public Licence for more details.
 *
 * You should have received a copy of the GNU General Public
 * Licence along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 * USA.
 *
 * Information about me (the author):
 *   Niki W. Waibel, Reichenau 20, 6890 Lustenau, Austria - EUROPE
 *   niki.waibel@gmx.net
**/





#define __RSP_MNEMONIC_H





#include <ansi_esc_codes.h>
        
#ifndef __TYPE_SIZES_H
        #include <type_sizes.h>
#endif





/**********************\
*                      *
* instruction reader   *
*                      *
\**********************/

#define READ_RSP_INSTRUCTION(addr)                      \
(                                                       \
        ( *((WORD *)(mem.sp_imem + (addr & 0xfff))) )   \
)





/**********************\
*                      *
* mnemonic definitions *
*                      *
\**********************/

#define __CODE          (rsp_reg.code = READ_RSP_INSTRUCTION(mem.sp_reg_pc))
#define __NEXT_CODE     (READ_RSP_INSTRUCTION((mem.sp_reg_pc + 4)))

#define __OPCODE        ((BYTE)(__CODE >> 26))

#define __RS            (((BYTE)(rsp_reg.code >> 21)) & 0x1f)

#define __RT            (((BYTE)(rsp_reg.code >> 16)) & 0x1f)

#define __RD            (((BYTE)(rsp_reg.code >> 11)) & 0x1f)

#define __SA            (((BYTE)(rsp_reg.code >>  6)) & 0x1f)

#define __F             ( (BYTE)(rsp_reg.code)       & 0x3f)

#define __I             ( (sWORD)(sHWORD)rsp_reg.code )
#define __O             ( mem.sp_reg_pc + 4 + (__I << 2) )
#define __RSP_O(x)      ( ((sWORD)(sBYTE)((rsp_reg.code & 0x40) ? ((rsp_reg.code & 0x7f) | 0x80) : (rsp_reg.code & 0x7f))) << x )

#define ____T           (rsp_reg.code & 0x3ffffff)
#define __T             ( (mem.sp_reg_pc & 0xf0000000) | (____T << 2) )





/**********************\
*                      *
* mnemonic debugging   *
*                      *
\**********************/

#ifdef DEBUG

        #define PRINT_NOTHING

        #define PRINT_O         printf(" $%08lx", __O);
        #define PRINT_RD        printf(" r%02u", __RD);
        #define PRINT_RS        printf(" r%02u", __RS);
        #define PRINT_T         printf(" $%08lx", __T);

        #define PRINT_RD_RS     printf(" r%02u, r%02u", __RD, __RS);
        #define PRINT_RS_I      printf(" r%02u, $%08lx (%ld)", __RS, (sWORD)__I, (sWORD)__I);
        #define PRINT_RS_O      printf(" r%02u, $%08lx", __RS, __O);
        #define PRINT_RS_RD     printf(" r%02u, r%02u", __RS, __RD);
        #define PRINT_RS_RT     printf(" r%02u, r%02u", __RS, __RT);
        #define PRINT_RT_I      printf(" r%02u, $%04hx ($%08lx)", __RT, (HWORD)__I, (sWORD)(__I << 16));
        #define PRINT_RT_RD     printf(" r%02u, r%02u", __RT, __RD);

        #define PRINT_RD_RS_RT  printf(" r%02u, r%02u, r%02u", __RD, __RS, __RT);
        #define PRINT_RD_RT_SA  printf(" r%02u, r%02u, r%02u", __RD, __RT, __SA);
        #define PRINT_RD_RT_RS  printf(" r%02u, r%02u, r%02u", __RD, __RT, __RS);
        #define PRINT_RS_RT_O   printf(" r%02u, r%02u, $%08lx", __RS, __RT, __O);
        #define PRINT_RT_O_B    printf(" r%02u, $%04lx(r%02u)", __RT, __I, __RS);
        #define PRINT_RT_RS_I   printf(" r%02u, r%02u, $%04hx (%hd)", __RT, __RS, (sHWORD)__I, (sHWORD)__I);

        #define PRINT_VE_O_B(x) printf(" v%02u%s, $%03lx(r%02u) (%ld)", __RT, EL_SP[(__SA>>1)|0x10], __RSP_O(x), __RS, __RSP_O(x));
        #define PRINT_V_V_VE    printf(" v%02u, v%02u, v%02u%s", __SA, __RD, __RT, ELEM[__RS]);
        #define PRINT_VE_VE     printf(" v%02u%s, v%02u%s", __SA, EL_SP[__RD], __RT, EL_SP[__RS]);
        #define PRINT_V_VE      printf(" v%02u%s, v%02u%s", __RD, ELEM[__SA], __RT, ELEM[__RS]);
        #define PRINT_V_V       printf(" v%02u, v%02u", __SA, __RT);

        #define PRINT_RT_FLAG   printf(" r%02u, flag[%1u]", __RT, __RD & 0x03);
        #define PRINT_RT_C2     printf(" r%02u, v%02u%s" , __RT, __RD, EL_C2[(__SA >> 1) & 0x0f]);
        #define PRINT_RT_C0     printf(" r%02u, " ST_BG_RED "%s" ST_BG_DEF , __RT, EL_C0[__RD]);

#else /* #ifndef DEBUG */

        #define PRINT_NOTHING

        #define PRINT_O
        #define PRINT_RD
        #define PRINT_RS
        #define PRINT_T

        #define PRINT_RD_RS
        #define PRINT_RS_I
        #define PRINT_RS_O
        #define PRINT_RS_RD
        #define PRINT_RS_RT
        #define PRINT_RT_I
        #define PRINT_RT_RD

        #define PRINT_RD_RS_RT
        #define PRINT_RD_RT_SA
        #define PRINT_RD_RT_RS
        #define PRINT_RS_RT_O
        #define PRINT_RT_O_B
        #define PRINT_RT_RS_I

        #define PRINT_VE_O_B(x)
        #define PRINT_V_V_VE
        #define PRINT_VE_VE
        #define PRINT_V_VE
        #define PRINT_V_V

        #define PRINT_RT_FLAG
        #define PRINT_RT_C2
        #define PRINT_RT_C0

#endif /* #ifndef DEBUG */





#ifdef DEBUG_NOTIMPLEMENTED
        #define PRINT_NOT_IMPLEMENTED(x) puts(x" - NOT IMPLEMENTED"); fflush(stdout);
#else
        #define PRINT_NOT_IMPLEMENTED(x)
#endif





#ifdef DEBUG_XINST
        #define PRINT_XINST(x)                  \
                if(prefs.debug & DBG_RSP_INSTR) \
                {                               \
                        puts(x); fflush(stdout);\
                }
#else
        #define PRINT_XINST(x)
#endif





#ifdef DEBUG
        #define PRINT_DEBUG_HEAD                                \
                if(prefs.debug & DBG_RSP_COUNT)                 \
                        printf("RSP(%08lx): ", rsp_reg.count);  \
                else                                            \
                        fputs("RSP: ", stdout);                 \
                printf("[$%08lx]: ", mem.sp_reg_pc);            \
                printf("$%08lx: ", rsp_reg.code);               \

        #define PRINT_DEBUG_FOOT                                \
                if(prefs.debug & DBG_RSP_REG)                   \
                {                                               \
                        rsp_print_r();                          \
                        rsp_print_v();                          \
                }
#else
        #define PRINT_DEBUG_HEAD
        #define PRINT_DEBUG_FOOT
#endif






#ifdef DEBUG
        #define PRINT_DEBUGGING_INFO(name, format)              \
                if(prefs.debug & DBG_RSP_INSTR)                 \
                {                                               \
                        PRINT_DEBUG_HEAD                        \
                        printf(" %-10s", name);                 \
                        PRINT_##format                          \
                        putchar('\n');                          \
                        PRINT_DEBUG_FOOT                        \
                }
#else
        #define PRINT_DEBUGGING_INFO(name, format)
#endif





#define ACCU_2_VREG(accu)                       \
        rsp_reg.v[__SA][0] = rsp_reg.accu[0];   \
        rsp_reg.v[__SA][1] = rsp_reg.accu[1];   \
        rsp_reg.v[__SA][2] = rsp_reg.accu[2];   \
        rsp_reg.v[__SA][3] = rsp_reg.accu[3];   \
        rsp_reg.v[__SA][4] = rsp_reg.accu[4];   \
        rsp_reg.v[__SA][5] = rsp_reg.accu[5];   \
        rsp_reg.v[__SA][6] = rsp_reg.accu[6];   \
        rsp_reg.v[__SA][7] = rsp_reg.accu[7];





#define STORE_REGISTER                                  \
                                                        \
        rsp_reg.v_src1[0] = rsp_reg.v[__RD][0];         \
        rsp_reg.v_src1[1] = rsp_reg.v[__RD][1];         \
        rsp_reg.v_src1[2] = rsp_reg.v[__RD][2];         \
        rsp_reg.v_src1[3] = rsp_reg.v[__RD][3];         \
        rsp_reg.v_src1[4] = rsp_reg.v[__RD][4];         \
        rsp_reg.v_src1[5] = rsp_reg.v[__RD][5];         \
        rsp_reg.v_src1[6] = rsp_reg.v[__RD][6];         \
        rsp_reg.v_src1[7] = rsp_reg.v[__RD][7];         \
                                                        \
        switch(__RS & 0x0f)                             \
        {                                               \
            case 0:                                     \
            case 1:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][7]; \
                break;                                  \
                                                        \
            case 2:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][6]; \
                break;                                  \
                                                        \
            case 3:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][7]; \
                break;                                  \
                                                        \
            case 4:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][4]; \
                break;                                  \
                                                        \
            case 5:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][5]; \
                break;                                  \
                                                        \
            case 6:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][6]; \
                break;                                  \
                                                        \
            case 7:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][7]; \
                break;                                  \
                                                        \
            case 8:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][0]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][0]; \
                break;                                  \
                                                        \
            case 9:                                     \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][1]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][1]; \
                break;                                  \
                                                        \
            case 10:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][2]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][2]; \
                break;                                  \
                                                        \
            case 11:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][3]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][3]; \
                break;                                  \
                                                        \
            case 12:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][4]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][4]; \
                break;                                  \
                                                        \
            case 13:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][5]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][5]; \
                break;                                  \
                                                        \
            case 14:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][6]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][6]; \
                break;                                  \
                                                        \
            case 15:                                    \
                rsp_reg.v_src2[0] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[1] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[2] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[3] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[4] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[5] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[6] = rsp_reg.v[__RT][7]; \
                rsp_reg.v_src2[7] = rsp_reg.v[__RT][7]; \
                break;                                  \
                                                        \
        } /* switch(__RS & 0x0f) */





#define VECT_OP(op)                                                             \
{                                                                               \
        int     i;                                                              \
                                                                                \
        for(i=0; i<8; i++)                                                      \
        {                                                                       \
                rsp_reg.v[__SA][i] = rsp_reg.v_src1[i] op rsp_reg.v_src2[i];    \
        }                                                                       \
}





#define VECT_N_OP(op)                                                           \
{                                                                               \
        int     i;                                                              \
                                                                                \
        for(i=0; i<8; i++)                                                      \
        {                                                                       \
                rsp_reg.v[__SA][i] = ~(rsp_reg.v_src1[i] op rsp_reg.v_src2[i]); \
        }                                                                       \
}





#define VECT_OP_COMP(comp)                                                              \
{                                                                                       \
        int     i;                                                                      \
        WORD    flags = rsp_reg.flag[1];                                                \
                                                                                        \
                                                                                        \
        for(i=0; i<8; i++)                                                              \
        {                                                                               \
                if(rsp_reg.v_src1[i] comp rsp_reg.v_src2[i])                            \
                        flags |= 0x01 << i;                                             \
                else                                                                    \
                        flags &= ~(0x01 << i);                                          \
                if(0 comp 1)           /* VNE or VLT */                                 \
                {                                                                       \
                        if(1 comp 0)   /* VNE */                                        \
                        {                                                               \
                                if(rsp_reg.flag[0] & (1 << (i+8)))                      \
                                {                                                       \
                                        flags |= 0x01 << i;                             \
                                }                                                       \
                        }                                                               \
                        else           /* VLT */                                        \
                        {                                                               \
                                if(rsp_reg.flag[0] & (1 << i))                          \
                                {                                                       \
                                        if(rsp_reg.v_src1[i] == rsp_reg.v_src2[i])      \
                                                flags |= 0x01 << i;                     \
                                }                                                       \
                        }                                                               \
                }                                                                       \
                else                   /* VEQ or VGE */                                 \
                {                                                                       \
                        if(1 comp 0)   /* VGE */                                        \
                        {                                                               \
                                if(rsp_reg.flag[0] & (1 << i))                          \
                                {                                                       \
                                        if(rsp_reg.v_src1[i] == rsp_reg.v_src2[i])      \
                                                flags &= ~(0x01 << i);                  \
                                }                                                       \
                        }                                                               \
                        else           /* VEQ */                                        \
                        {                                                               \
                                if(rsp_reg.flag[0] & (1 << (i+8)))                      \
                                {                                                       \
                                        flags &= ~(0x01 << i);                          \
                                }                                                       \
                        }                                                               \
                }                                                                       \
        }                                                                               \
                                                                                        \
        rsp_reg.flag[1] = flags;                                                        \
}





#define VECT_OP_COPY(which)                                     \
{                                                               \
        int i;                                                  \
                                                                \
        for(i=0; i<8; i++)                                      \
        {                                                       \
                if(which & (1 << i))                            \
                        rsp_reg.v[__SA][i] = rsp_reg.v_src1[i]; \
                else                                            \
                        rsp_reg.v[__SA][i] = rsp_reg.v_src2[i]; \
        }                                                       \
}





#define VECT_OP_ABS                                                             \
{                                                                               \
        int     i;                                                              \
                                                                                \
                                                                                \
                                                                                \
        for(i=0; i<8; i++)                                                      \
        {                                                                       \
                if(rsp_reg.v_src1[i] == 0)                                      \
                        rsp_reg.v[__SA][i] = 0;                                 \
                else if(rsp_reg.v_src1[i] < 0)                                  \
                {                                                               \
                        rsp_reg.v[__SA][i] = -rsp_reg.v_src2[i];                \
                        if(((HWORD)rsp_reg.v[__SA][i]) == 0x8000)               \
                                rsp_reg.v[__SA][i] = 0x7fff;                    \
                }                                                               \
                else if(rsp_reg.v_src1[i] > 0)                                  \
                        rsp_reg.v[__SA][i] = rsp_reg.v_src2[i];                 \
        }                                                                       \
}






#define CLIP_RESULT_ADD                                                                         \
{                                                                                               \
        int     i;                                                                              \
                                                                                                \
        for(i=0; i<8; i++)                                                                      \
        {                                                                                       \
                if((~rsp_reg.v_src1[i] & ~rsp_reg.v_src2[i] & rsp_reg.v[__SA][i]) & 0x8000)     \
                        rsp_reg.v[__SA][i] = 0x7fff;                                            \
                else if((rsp_reg.v_src1[i] & rsp_reg.v_src2[i] & ~rsp_reg.v[__SA][i]) & 0x8000) \
                        rsp_reg.v[__SA][i] = 0x8000;                                            \
        }                                                                                       \
}





#define CLIP_RESULT_SUB                                                                         \
{                                                                                               \
        int     i;                                                                              \
                                                                                                \
        for(i=0; i<8; i++)                                                                      \
        {                                                                                       \
                if((~rsp_reg.v_src1[i] & rsp_reg.v_src2[i] & rsp_reg.v[__SA][i]) & 0x8000)      \
                        rsp_reg.v[__SA][i] = 0x7fff;                                            \
                else if((rsp_reg.v_src1[i] & ~rsp_reg.v_src2[i] & ~rsp_reg.v[__SA][i]) & 0x8000)\
                        rsp_reg.v[__SA][i] = 0x8000;                                            \
        }                                                                                       \
}





#define SET_CARRY_ADD                                                                                   \
{                                                                                                       \
        int     i;                                                                                      \
                                                                                                        \
                                                                                                        \
                                                                                                        \
        rsp_reg.flag[0] = 0;                                                                            \
                                                                                                        \
        for(i=0; i<8; i++)                                                                              \
        {                                                                                               \
                if(((sWORD)(HWORD)rsp_reg.v_src1[i] + (sWORD)(HWORD)rsp_reg.v_src2[i]) != (sWORD)(HWORD)rsp_reg.v[__SA][i])  \
                        rsp_reg.flag[0] |= 1 << i;                                                      \
        }                                                                                               \
}





#define SET_CARRY_SUB                                                                                   \
{                                                                                                       \
        int     i;                                                                                      \
                                                                                                        \
                                                                                                        \
                                                                                                        \
        rsp_reg.flag[0] = 0;                                                                            \
                                                                                                        \
        for(i=0; i<8; i++)                                                                              \
        {                                                                                               \
                if(((sWORD)(HWORD)rsp_reg.v_src1[i] - (sWORD)(HWORD)rsp_reg.v_src2[i]) != (sWORD)(HWORD)rsp_reg.v[__SA][i])  \
                        rsp_reg.flag[0] |= 1 << i;                                                      \
        }                                                                                               \
}





#define VECT_ACCU_OP(accu, pre, cast, op, shift)                                                                \
{                                                                                                               \
        int     i;                                                                                              \
                                                                                                                \
        for(i=0; i<8; i++)                                                                                      \
        {                                                                                                       \
                rsp_reg.accu[i] pre##= ((WORD)(cast rsp_reg.v[__RD][i] op cast rsp_reg.v[__RT][i])) shift;      \
        }                                                                                                       \
}





/* zero? */
#define SET_ZERO_FLAGS(x)                       \
        rsp_reg.flag[0] &= 0x00ff;              \
        if(rsp_reg.v[x][0] != 0)                \
                rsp_reg.flag[0] |= 0x0100;      \
        if(rsp_reg.v[x][1] != 0)                \
                rsp_reg.flag[0] |= 0x0200;      \
        if(rsp_reg.v[x][2] != 0)                \
                rsp_reg.flag[0] |= 0x0400;      \
        if(rsp_reg.v[x][3] != 0)                \
                rsp_reg.flag[0] |= 0x0800;      \
        if(rsp_reg.v[x][4] != 0)                \
                rsp_reg.flag[0] |= 0x1000;      \
        if(rsp_reg.v[x][5] != 0)                \
                rsp_reg.flag[0] |= 0x2000;      \
        if(rsp_reg.v[x][6] != 0)                \
                rsp_reg.flag[0] |= 0x4000;      \
        if(rsp_reg.v[x][7] != 0)                \
                rsp_reg.flag[0] |= 0x8000;





#define ADD_CARRY(x)                    \
        if(rsp_reg.flag[0] & 0x01)      \
                rsp_reg.v[x][0]++;      \
        if(rsp_reg.flag[0] & 0x02)      \
                rsp_reg.v[x][1]++;      \
        if(rsp_reg.flag[0] & 0x04)      \
                rsp_reg.v[x][2]++;      \
        if(rsp_reg.flag[0] & 0x08)      \
                rsp_reg.v[x][3]++;      \
        if(rsp_reg.flag[0] & 0x10)      \
                rsp_reg.v[x][4]++;      \
        if(rsp_reg.flag[0] & 0x20)      \
                rsp_reg.v[x][5]++;      \
        if(rsp_reg.flag[0] & 0x40)      \
                rsp_reg.v[x][6]++;      \
        if(rsp_reg.flag[0] & 0x80)      \
                rsp_reg.v[x][7]++;      \
        rsp_reg.flag[0] &= 0xff00;





#define SUB_CARRY(x)                    \
        if(rsp_reg.flag[0] & 0x01)      \
                rsp_reg.v[x][0]--;      \
        if(rsp_reg.flag[0] & 0x02)      \
                rsp_reg.v[x][1]--;      \
        if(rsp_reg.flag[0] & 0x04)      \
                rsp_reg.v[x][2]--;      \
        if(rsp_reg.flag[0] & 0x08)      \
                rsp_reg.v[x][3]--;      \
        if(rsp_reg.flag[0] & 0x10)      \
                rsp_reg.v[x][4]--;      \
        if(rsp_reg.flag[0] & 0x20)      \
                rsp_reg.v[x][5]--;      \
        if(rsp_reg.flag[0] & 0x40)      \
                rsp_reg.v[x][6]--;      \
        if(rsp_reg.flag[0] & 0x80)      \
                rsp_reg.v[x][7]--;      \
        rsp_reg.flag[0] &= 0xff00;





#ifdef HALT
        #define RSP_HALT rsp_reg.halt = 1;                      \
                         puts(ST_FG_RED "RSP halted!" ST_FG_DEF); fflush(stdout);
#else
        #define RSP_HALT
#endif




