/*****************************************************************************/
/*                                                                           */
/*                                 opcodes.c                                 */
/*                                                                           */
/*                  Opcode and addressing mode definitions                   */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/* (C) 2001-2004 Ullrich von Bassewitz                                       */
/*               Römerstraße 52                                              */
/*               D-70794 Filderstadt                                         */
/* EMail:        uz@cc65.org                                                 */
/*                                                                           */
/*                                                                           */
/* This software is provided 'as-is', without any expressed or implied       */
/* warranty.  In no event will the authors be held liable for any damages    */
/* arising from the use of this software.                                    */
/*                                                                           */
/* Permission is granted to anyone to use this software for any purpose,     */
/* including commercial applications, and to alter it and redistribute it    */
/* freely, subject to the following restrictions:                            */
/*                                                                           */
/* 1. The origin of this software must not be misrepresented; you must not   */
/*    claim that you wrote the original software. If you use this software   */
/*    in a product, an acknowledgment in the product documentation would be  */
/*    appreciated but is not required.                                       */
/* 2. Altered source versions must be plainly marked as such, and must not   */
/*    be misrepresented as being the original software.                      */
/* 3. This notice may not be removed or altered from any source              */
/*    distribution.                                                          */
/*                                                                           */
/*****************************************************************************/



#include "stdlib.h"
#include <string.h>
#include <ctype.h>

/* common */
#include "check.h"
#include "cpu.h"

/* cc65 */
#include "codeinfo.h"
#include "error.h"
#include "opcodes.h"



/*****************************************************************************/
/*                                   Data                                    */
/*****************************************************************************/



/* Opcode description table */
const OPCDesc OPCTable[OP65_COUNT] = {

    /* 65XX opcodes */
    {   OP65_ADC,                               /* opcode */
        "adc",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_AND,                               /* opcode */
        "and",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_ASL,                               /* opcode */
        "asl",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    {   OP65_BCC,                               /* opcode */
        "bcc",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA                                 /* flags */
    },
    {   OP65_BCS,                               /* opcode */
        "bcs",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA                                 /* flags */
    },
    {   OP65_BEQ,                               /* opcode */
        "beq",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_ZBRA | OF_FBRA             /* flags */
    },
    {   OP65_BIT,                               /* opcode */
        "bit",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_BMI,                               /* opcode */
        "bmi",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_FBRA                       /* flags */
    },
    {   OP65_BNE,                               /* opcode */
        "bne",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_ZBRA | OF_FBRA             /* flags */
    },
    {   OP65_BPL,                               /* opcode */
        "bpl",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_FBRA                       /* flags */
    },
    {   OP65_BRA,                               /* opcode */
        "bra",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_UBRA                                 /* flags */
    },
    {   OP65_BRK,                               /* opcode */
        "brk",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_BVC,                               /* opcode */
        "bvc",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA                                 /* flags */
    },
    {   OP65_BVS,                               /* opcode */
        "bvs",                                  /* mnemonic */
        2,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA                                 /* flags */
    },
    {   OP65_CLC,                               /* opcode */
        "clc",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_CLD,                               /* opcode */
        "cld",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_CLI,                               /* opcode */
        "cli",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_CLV,                               /* opcode */
        "clv",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_CMP,                               /* opcode */
        "cmp",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_CMP                        /* flags */
    },
    {   OP65_CPX,                               /* opcode */
        "cpx",                                  /* mnemonic */
        0,                                      /* size */
        REG_X,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_CMP                        /* flags */
    },
    {   OP65_CPY,                               /* opcode */
        "cpy",                                  /* mnemonic */
        0,                                      /* size */
        REG_Y,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_CMP                        /* flags */
    },
    {   OP65_DEA,                               /* opcode */
        "dea",                                  /* mnemonic */
        1,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_DEC,                               /* opcode */
        "dec",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    {   OP65_DEX,                               /* opcode */
        "dex",                                  /* mnemonic */
        1,                                      /* size */
        REG_X,                                  /* use */
        REG_X,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_DEY,                               /* opcode */
        "dey",                                  /* mnemonic */
        1,                                      /* size */
        REG_Y,                                  /* use */
        REG_Y,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_EOR,                               /* opcode */
        "eor",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_INA,                               /* opcode */
        "ina",                                  /* mnemonic */
        1,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_INC,                               /* opcode */
        "inc",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    {   OP65_INX,                               /* opcode */
        "inx",                                  /* mnemonic */
        1,                                      /* size */
        REG_X,                                  /* use */
        REG_X,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_INY,                               /* opcode */
        "iny",                                  /* mnemonic */
        1,                                      /* size */
        REG_Y,                                  /* use */
        REG_Y,                                  /* chg */
        OF_REG_INCDEC | OF_SETF                 /* flags */
    },
    {   OP65_JCC,                               /* opcode */
        "jcc",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA                       /* flags */
    },
    {   OP65_JCS,                               /* opcode */
        "jcs",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA                       /* flags */
    },
    {   OP65_JEQ,                               /* opcode */
        "jeq",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA   /* flags */
    },
    {   OP65_JMI,                               /* opcode */
        "jmi",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA | OF_FBRA             /* flags */
    },
    {   OP65_JMP,                               /* opcode */
        "jmp",                                  /* mnemonic */
        3,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_UBRA | OF_LBRA                       /* flags */
    },
    {   OP65_JNE,                               /* opcode */
        "jne",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA   /* flags */
    },
    {   OP65_JPL,                               /* opcode */
        "jpl",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA | OF_FBRA             /* flags */
    },
    {   OP65_JSR,                               /* opcode */
        "jsr",                                  /* mnemonic */
        3,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CALL                                 /* flags */
    },
    {   OP65_JVC,                               /* opcode */
        "jvc",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA                       /* flags */
    },
    {   OP65_JVS,                               /* opcode */
        "jvs",                                  /* mnemonic */
        5,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_CBRA | OF_LBRA                       /* flags */
    },
    {   OP65_LDA,                               /* opcode */
        "lda",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_A,                                  /* chg */
        OF_LOAD | OF_SETF                       /* flags */
    },
    {   OP65_LDX,                               /* opcode */
        "ldx",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_X,                                  /* chg */
        OF_LOAD | OF_SETF                       /* flags */
    },
    {   OP65_LDY,                               /* opcode */
        "ldy",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_Y,                                  /* chg */
        OF_LOAD | OF_SETF                       /* flags */
    },
    {   OP65_LSR,                               /* opcode */
        "lsr",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    {   OP65_NOP,                               /* opcode */
        "nop",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_ORA,                               /* opcode */
        "ora",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_PHA,                               /* opcode */
        "pha",                                  /* mnemonic */
        1,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_PHP,                               /* opcode */
        "php",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_PHX,                               /* opcode */
        "phx",                                  /* mnemonic */
        1,                                      /* size */
        REG_X,                                  /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_PHY,                               /* opcode */
        "phy",                                  /* mnemonic */
        1,                                      /* size */
        REG_Y,                                  /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_PLA,                               /* opcode */
        "pla",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_PLP,                               /* opcode */
        "plp",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_PLX,                               /* opcode */
        "plx",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_X,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_PLY,                               /* opcode */
        "ply",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_Y,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_ROL,                               /* opcode */
        "rol",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    {   OP65_ROR,                               /* opcode */
        "ror",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_SETF | OF_NOIMP                      /* flags */
    },
    /* Mark RTI as "uses all registers but doesn't change them", so the
     * optimizer won't remove preceeding loads.
     */
    {   OP65_RTI,                               /* opcode */
        "rti",                                  /* mnemonic */
        1,                                      /* size */
        REG_AXY,                                /* use */
        REG_NONE,                               /* chg */
        OF_RET                                  /* flags */
    },
    {   OP65_RTS,                               /* opcode */
        "rts",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_RET                                  /* flags */
    },
    {   OP65_SBC,                               /* opcode */
        "sbc",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_A,                                  /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_SEC,                               /* opcode */
        "sec",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_SED,                               /* opcode */
        "sed",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_SEI,                               /* opcode */
        "sei",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_NONE                                 /* flags */
    },
    {   OP65_STA,                               /* opcode */
        "sta",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_STORE                                /* flags */
    },
    {   OP65_STX,                               /* opcode */
        "stx",                                  /* mnemonic */
        0,                                      /* size */
        REG_X,                                  /* use */
        REG_NONE,                               /* chg */
        OF_STORE                                /* flags */
    },
    {   OP65_STY,                               /* opcode */
        "sty",                                  /* mnemonic */
        0,                                      /* size */
        REG_Y,                                  /* use */
        REG_NONE,                               /* chg */
        OF_STORE                                /* flags */
    },
    {   OP65_STZ,                               /* opcode */
        "stz",                                  /* mnemonic */
        0,                                      /* size */
        REG_NONE,                               /* use */
        REG_NONE,                               /* chg */
        OF_STORE                                /* flags */
    },
    {   OP65_TAX,                               /* opcode */
        "tax",                                  /* mnemonic */
        1,                                      /* size */
        REG_A,                                  /* use */
        REG_X,                                  /* chg */
        OF_XFR | OF_SETF                        /* flags */
    },
    {   OP65_TAY,                               /* opcode */
        "tay",                                  /* mnemonic */
        1,                                      /* size */
        REG_A,                                  /* use */
        REG_Y,                                  /* chg */
        OF_XFR | OF_SETF                        /* flags */
    },
    {   OP65_TRB,                               /* opcode */
        "trb",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_TSB,                               /* opcode */
        "tsb",                                  /* mnemonic */
        0,                                      /* size */
        REG_A,                                  /* use */
        REG_NONE,                               /* chg */
        OF_SETF                                 /* flags */
    },
    {   OP65_TSX,                               /* opcode */
        "tsx",                                  /* mnemonic */
        1,                                      /* size */
        REG_NONE,                               /* use */
        REG_X,                                  /* chg */
        OF_XFR | OF_SETF                        /* flags */
    },
    {   OP65_TXA,                               /* opcode */
        "txa",                                  /* mnemonic */
        1,                                      /* size */
        REG_X,                                  /* use */
        REG_A,                                  /* chg */
        OF_XFR | OF_SETF                        /* flags */
    },
    {   OP65_TXS,                               /* opcode */
        "txs",                                  /* mnemonic */
        1,                                      /* size */
        REG_X,                                  /* use */
        REG_NONE,                               /* chg */
        OF_XFR                                  /* flags */
    },
    {   OP65_TYA,                               /* opcode */
        "tya",                                  /* mnemonic */
        1,                                      /* size */
        REG_Y,                                  /* use */
        REG_A,                                  /* chg */
        OF_XFR | OF_SETF                        /* flags */
    },
};



/*****************************************************************************/
/*                                   Code                                    */
/*****************************************************************************/



static int FindCmp (const void* Key, const void* Desc)
/* Compare function for FindOpcode */
{
    return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
}



const OPCDesc* FindOP65 (const char* M)
/* Find the given opcode and return the opcode number. If the opcode was not
 * found, return NULL.
 */
{
    unsigned I;
    unsigned Len;

    /* Check the length of the given string, then copy it into local
     * storage, converting it to upper case.
     */
    char Mnemo[sizeof (OPCTable[0].Mnemo)];
    Len = strlen (M);
    if (Len >= sizeof (OPCTable[0].Mnemo)) {
        /* Invalid length means invalid opcode */
        return 0;
    }
    for (I = 0; I < Len; ++I) {
        Mnemo[I] = tolower (M[I]);
    }
    Mnemo[I] = '\0';

    /* Search for the mnemonic in the table and return the result */
    return bsearch (Mnemo, OPCTable, OP65_COUNT,
                    sizeof (OPCTable[0]), FindCmp );
}



unsigned GetInsnSize (opc_t OPC, am_t AM)
/* Return the size of the given instruction */
{
    /* Get the opcode desc and check the size given there */
    const OPCDesc* D = &OPCTable[OPC];
    if (D->Size != 0) {
        return D->Size;
    }

    /* Check the addressing mode. */
    switch (AM) {
        case AM65_IMP:     return 1;
        case AM65_ACC:     return 1;
        case AM65_IMM:     return 2;
        case AM65_ZP:      return 2;
        case AM65_ZPX:     return 2;
        case AM65_ABS:     return 3;
        case AM65_ABSX:    return 3;
        case AM65_ABSY:    return 3;
        case AM65_ZPX_IND: return 2;
        case AM65_ZP_INDY: return 2;
        case AM65_ZP_IND:  return 2;
        default:
            Internal ("Invalid addressing mode");
            return 0;
    }
}



unsigned char GetAMUseInfo (am_t AM)
/* Get usage info for the given addressing mode (addressing modes that use
 * index registers return REG_r info for these registers).
 */
{
    /* Check the addressing mode. */
    switch (AM) {
        case AM65_ACC:     return REG_A;
        case AM65_ZPX:     return REG_X;
        case AM65_ABSX:    return REG_X;
        case AM65_ABSY:    return REG_Y;
        case AM65_ZPX_IND: return REG_X;
        case AM65_ZP_INDY: return REG_Y;
        default:           return REG_NONE;
    }
}



opc_t GetInverseBranch (opc_t OPC)
/* Return a branch that reverse the condition of the branch given in OPC */
{
    switch (OPC) {
        case OP65_BCC:  return OP65_BCS;
        case OP65_BCS:  return OP65_BCC;
        case OP65_BEQ:  return OP65_BNE;
        case OP65_BMI:  return OP65_BPL;
        case OP65_BNE:  return OP65_BEQ;
        case OP65_BPL:  return OP65_BMI;
        case OP65_BVC:  return OP65_BVS;
        case OP65_BVS:  return OP65_BVC;
        case OP65_JCC:  return OP65_JCS;
        case OP65_JCS:  return OP65_JCC;
        case OP65_JEQ:  return OP65_JNE;
        case OP65_JMI:  return OP65_JPL;
        case OP65_JNE:  return OP65_JEQ;
        case OP65_JPL:  return OP65_JMI;
        case OP65_JVC:  return OP65_JVS;
        case OP65_JVS:  return OP65_JVC;
        default:
            Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
            return 0;
    }
}



opc_t MakeShortBranch (opc_t OPC)
/* Return the short version of the given branch. If the branch is already
 * a short branch, return the opcode unchanged.
 */
{
    switch (OPC) {
        case OP65_BCC:
        case OP65_JCC:  return OP65_BCC;
        case OP65_BCS:
        case OP65_JCS:  return OP65_BCS;
        case OP65_BEQ:
        case OP65_JEQ:  return OP65_BEQ;
        case OP65_BMI:
        case OP65_JMI:  return OP65_BMI;
        case OP65_BNE:
        case OP65_JNE:  return OP65_BNE;
        case OP65_BPL:
        case OP65_JPL:  return OP65_BPL;
        case OP65_BVC:
        case OP65_JVC:  return OP65_BVC;
        case OP65_BVS:
        case OP65_JVS:  return OP65_BVS;
        case OP65_BRA:
        case OP65_JMP:  return (CPUIsets[CPU] & CPU_ISET_65SC02)? OP65_BRA : OP65_JMP;
        default:
            Internal ("MakeShortBranch: Invalid opcode: %d", OPC);
            return 0;
    }
}



opc_t MakeLongBranch (opc_t OPC)
/* Return the long version of the given branch. If the branch is already
 * a long branch, return the opcode unchanged.
 */
{
    switch (OPC) {
        case OP65_BCC:
        case OP65_JCC:  return OP65_JCC;
        case OP65_BCS:
        case OP65_JCS:  return OP65_JCS;
        case OP65_BEQ:
        case OP65_JEQ:  return OP65_JEQ;
        case OP65_BMI:
        case OP65_JMI:  return OP65_JMI;
        case OP65_BNE:
        case OP65_JNE:  return OP65_JNE;
        case OP65_BPL:
        case OP65_JPL:  return OP65_JPL;
        case OP65_BVC:
        case OP65_JVC:  return OP65_JVC;
        case OP65_BVS:
        case OP65_JVS:  return OP65_JVS;
        case OP65_BRA:
        case OP65_JMP:  return OP65_JMP;
        default:
            Internal ("MakeLongBranch: Invalid opcode: %d", OPC);
            return 0;
    }
}



bc_t GetBranchCond (opc_t OPC)
/* Get the condition for the conditional branch in OPC */
{
    switch (OPC) {
        case OP65_BCC:  return BC_CC;
        case OP65_BCS:  return BC_CS;
        case OP65_BEQ:  return BC_EQ;
        case OP65_BMI:  return BC_MI;
        case OP65_BNE:  return BC_NE;
        case OP65_BPL:  return BC_PL;
        case OP65_BVC:  return BC_VC;
        case OP65_BVS:  return BC_VS;
        case OP65_JCC:  return BC_CC;
        case OP65_JCS:  return BC_CS;
        case OP65_JEQ:  return BC_EQ;
        case OP65_JMI:  return BC_MI;
        case OP65_JNE:  return BC_NE;
        case OP65_JPL:  return BC_PL;
        case OP65_JVC:  return BC_VC;
        case OP65_JVS:  return BC_VS;
        default:
            Internal ("GetBranchCond: Invalid opcode: %d", OPC);
            return 0;
    }
}



bc_t GetInverseCond (bc_t BC)
/* Return the inverse condition of the given one */
{
    switch (BC) {
        case BC_CC:     return BC_CS;
        case BC_CS:     return BC_CC;
        case BC_EQ:     return BC_NE;
        case BC_MI:     return BC_PL;
        case BC_NE:     return BC_EQ;
        case BC_PL:     return BC_MI;
        case BC_VC:     return BC_VS;
        case BC_VS:     return BC_VC;
        default:
            Internal ("GetInverseCond: Invalid condition: %d", BC);
            return 0;
    }
}




