#include <stdio.h>
#include <types.h>

#define DECODE_JUMP         (((raw_opcode_ulong & 0x03FFFFFF) << 2) | (raw_opcode_addr & 0xF0000000))
#define DECODE_IMMED        ((uint)((raw_opcode[2] << 8) | raw_opcode[3]))

#define DECODE_RS           ((raw_opcode[0] & 0x03) << 3 | (raw_opcode[1] >> 5))
#define DECODE_RT           (raw_opcode[1] & 0x1F)
#define DECODE_RD           (raw_opcode[2] >> 3)
#define DECODE_SA           ((raw_opcode[2] & 0x07) << 2 | (raw_opcode[3] >> 6))
#define DECODE_FS           (DECODE_RD)
#define DECODE_FT           (DECODE_RT)
#define DECODE_FD           (DECODE_SA)

#define DECODE_BASE         (DECODE_RS)
#define DECODE_OFFSET       ((ulong)(((ulong)(SignExtend16(DECODE_IMMED)) << 2) + raw_opcode_addr + 4))

#define DECODE_SYSCALL      ((raw_opcode_ulong & 0x03FFFFFF) >> 6)
#define DECODE_BREAK        (DECODE_SYSCALL)

#define DECODE_OPCODE       (raw_opcode[0] >> 2)
#define DECODE_FUNCTION     (raw_opcode[3] & 0x3F)
#define DECODE_C0FMT        (DECODE_RS)
#define DECODE_C0FUNC       (DECODE_FUNCTION)
#define DECODE_C1FMT        (DECODE_RS)
#define DECODE_C2TYPE       (DECODE_RD)

#define DECODE_C1BC         (raw_opcode[1] & 0x03)
#define DECODE_C1S          (DECODE_FUNCTION)
#define DECODE_C1D          (DECODE_FUNCTION)
#define DECODE_C1W          (DECODE_FUNCTION)
#define DECODE_C1L          (DECODE_FUNCTION)

#define DECODE_C2IMM        (DECODE_IMMED & 0x07FF)
#define DECODE_C2VEC        (DECODE_SA)

void print_binary(int val, int num_bits)
{
    int t;

    val <<= (8 - num_bits);

    t = num_bits;
    while (t--)
    {
        if (val & 0x80)
            printf("1");
        else
            printf("0");

        val <<= 1;
    }
}

void main(void)
{
    char buf[16];
    ulong raw_opcode_ulong, temp;
    uchar raw_opcode[4];
    int t, x;

    scanf("%x", &raw_opcode_ulong);
    temp = raw_opcode_ulong;

    raw_opcode[3] = (uchar)temp; temp >>= 8;
    raw_opcode[2] = (uchar)temp; temp >>= 8;
    raw_opcode[1] = (uchar)temp; temp >>= 8;
    raw_opcode[0] = (uchar)temp;

    printf("\nBINARY:   ");

    for (x = 0; x < 4; x++)
    {
        print_binary(raw_opcode[x], 8);
        printf(" ");
    }

    printf("\n");
    printf("          |----||----||---| |---||----||----|\n");
    printf("          Opcode  RS    RT    RD    SA   Func\n");
    printf("          |----| |---| |---| |---| |---| |----|\n");

    printf("          ");
    print_binary(DECODE_OPCODE,   6); printf(" ");
    print_binary(DECODE_RS,       5); printf(" ");
    print_binary(DECODE_RT,       5); printf(" ");
    print_binary(DECODE_RD,       5); printf(" ");
    print_binary(DECODE_SA,       5); printf(" ");
    print_binary(DECODE_FUNCTION, 6); printf(" ");
    printf("\n\n");

    printf("OPCODE:   %02Xh (%d)\n",   DECODE_OPCODE,   DECODE_OPCODE);
    printf("FUNCTION: %02Xh (%d)\n\n", DECODE_FUNCTION, DECODE_FUNCTION);

    printf("RS:       %02Xh (%d)\n",   DECODE_RS,       DECODE_RS);
    printf("RT:       %02Xh (%d)\n",   DECODE_RT,       DECODE_RT);
    printf("RD/C2VEC: %02Xh (%d)\n",   DECODE_RD,       DECODE_RD);
    printf("SA:       %02Xh (%d)\n\n", DECODE_SA,       DECODE_SA);

    printf("C2IMM     %04Xh (%d)\n",   DECODE_C2IMM,    DECODE_C2IMM);
}

