/**
 * TrueReality - n64/mnemonic.h
 * Copyright (C) 1998 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 __MNEMONIC_H





#ifndef __TYPE_SIZES_H
#       include "type_sizes.h"
#endif

#ifndef __COP1_H
#       include "cop1.h"
#endif

#ifndef __ROMIMAGE_EXTERN_H
#       include "../romimage_extern.h"
#endif





/* hope that this increase speed */
/* wow, speed increased dramatically !!! */

#define ReadInstruction(addr)                                                                  \
(                                                                                              \
        ( (addr < 0xa4000040) )                                                                \
        ?                                                                                      \
                ( *((WORD *)(mem.rd_ram + (addr & 0x1fffffff))) )     /* instr in prgcode */   \
        :                                                                                      \
                ( *(WORD *)(mem.sp_dmem + (addr & 0xfff)) )           /* instr in bootcode */  \
)





/*
** mnemonic definitions
*/

/* code                 - 32 bit - RIJ */
#define rs4300i_Code()     (reg.code = ReadInstruction(reg.pc))
#define rs4300i_NCode(x)   (ReadInstruction((reg.pc + x)))

/* operation code       -  6 bit - RIJ */
#define rs4300i_Opcode()  ((BYTE)(rs4300i_Code() >> 26))

/* source register      -  5 bit - RI */
#define rs4300i_RS()     (((BYTE)(reg.code >> 21)) & 0x1f)

/* target register      -  5 bit - RI */
#define rs4300i_RT()     (((BYTE)(reg.code >> 16)) & 0x1f)

/* destination register -  5 bit - R */
#define rs4300i_RD()     (((BYTE)(reg.code >> 11)) & 0x1f)

/* shift amount         -  5 bit - R */
#define rs4300i_SA()     (((BYTE)(reg.code >>  6)) & 0x1f)

/* function field       -  6 bit - R */
#define rs4300i_Funct()   ((BYTE)(reg.code         & 0x3f))

/* immediate            - 16 bit - I */
#define rs4300i_I()      ( (sWORD) (sHWORD) reg.code )

/* target               - 26 bit - J */
#define rs4300i_Target() (reg.code & 0x3ffffff)




/*
** This mnemonic definitions are for the fpu (cop1)
*/


/* format - 5 bit */
#define __fmt           (((BYTE)(reg.code >> 21)) & 0x1f)

/* target - 5 bit */
#define __ft            (((BYTE)(reg.code >> 16)) & 0x1f)

/* source - 5 bit */
#define __fs            (((BYTE)(reg.code >> 11)) & 0x1f)

/* destination - 5 bit */
#define __fd            (((BYTE)(reg.code >>  6)) & 0x1f)

/* function - 6 bit */
#define __function      ((BYTE)(reg.code          & 0x3f))


#define ft                                                              \
(                                                                       \
        (reg.cpr[0][12] & 0x04000000) ?                                 \
                reg.cpr[1][__ft]                                        \
        :                                                               \
                ((reg.cpr[1][__ft+1] << 32) + (reg.cpr[1][__ft]))       \
)

#define fd                                                              \
(                                                                       \
        (reg.cpr[0][12] & 0x04000000) ?                                 \
                reg.cpr[1][__fd]                                        \
        :                                                               \
                ((reg.cpr[1][__fd+1] << 32) + (reg.cpr[1][__fd]))       \
)


#define fs                                                              \
(                                                                       \
        (reg.cpr[0][12] & 0x04000000) ?                                 \
                reg.cpr[1][__fs]                                        \
        :                                                               \
                ((reg.cpr[1][__fs+1] << 32) + (reg.cpr[1][__fs]))       \
)


#define store_fpr(value)                                                \
{                                                                       \
        if(reg.cpr[0][12] & 0x04000000)                                 \
        {                                                               \
                (reg.cpr[1][__fd] = value);                             \
        }                                                               \
        else                                                            \
        {                                                               \
                (reg.cpr[1][__fd+0] = (sDWORD)(sWORD)value);            \
                (reg.cpr[1][__fd+1] = (sDWORD)(sWORD)(value >> 32));    \
        }                                                               \
}

#define fmt                                                             \
(                                                                       \
        (__fmt == FMT_S) ? 's' :                                        \
                (__fmt == FMT_D) ? 'd' :                                \
                        (__fmt == FMT_W) ? 'w' :                        \
                                (__fmt == FMT_L) ? 'l' : '?'            \
)

