/**
 ** Opcodes.h - Opcode definitions for Usecode.
 **
 ** Written: 1/1/01 - JSF
 **/

/*
 *  Copyright (C) 2001-2022  The Exult Team
 *
 *  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.
 */

#ifndef INCL_OPCODES
#define INCL_OPCODES 1

enum UsecodeOps {
	UC_INVALID     = -1,
	UC_EXTOPCODE   = 0x80,
	UC_LOOPTOP     = 0x02,
	UC_CONVERSE    = 0x04,
	UC_JNE         = 0x05,
	UC_JMP         = 0x06,
	UC_CMPS        = 0x07,
	UC_ADD         = 0x09,
	UC_SUB         = 0x0a,
	UC_DIV         = 0x0b,
	UC_MUL         = 0x0c,
	UC_MOD         = 0x0d,
	UC_AND         = 0x0e,
	UC_OR          = 0x0f,
	UC_NOT         = 0x10,
	UC_POP         = 0x12,
	UC_PUSHTRUE    = 0x13,
	UC_PUSHFALSE   = 0x14,
	UC_CMPGT       = 0x16,
	UC_CMPLT       = 0x17,
	UC_CMPGE       = 0x18,
	UC_CMPLE       = 0x19,
	UC_CMPNE       = 0x1a,
	UC_ADDSI       = 0x1c,
	UC_PUSHS       = 0x1d,
	UC_ARRC        = 0x1e,
	UC_PUSHI       = 0x1f,
	UC_PUSH        = 0x21,
	UC_CMPEQ       = 0x22,
	UC_CALL        = 0x24,
	UC_RET         = 0x25,    // No return value.
	UC_AIDX        = 0x26,
	UC_RET2        = 0x2c,    // Identical to UC_RET; UCC never emits this.
	UC_RETV        = 0x2d,    // Returns value from stack.
	UC_LOOP        = 0x2e,
	UC_ADDSV       = 0x2f,
	UC_IN          = 0x30,
	UC_DEFAULT     = 0x31,    // Conversation default.
	UC_RETZ        = 0x32,    // Returns zero.
	UC_SAY         = 0x33,
	UC_CALLIS      = 0x38,
	UC_CALLI       = 0x39,
	UC_PUSHITEMREF = 0x3e,
	UC_ABRT        = 0x3f,
	UC_THROW = 0xbf,    // Like abrt, but accepts an expression to be sent up.
	UC_CONVERSELOC = 0x40,    // CONVERSE jmps here.
	UC_PUSHF       = 0x42,    // PUSH global flag.
	UC_POPF        = 0x43,    // POP global flag.
	UC_PUSHB       = 0x44,    // Push byte that follows.
	UC_POPARR      = 0x46,    // Pop into array elem.
	UC_CALLE       = 0x47,
	UC_PUSHEVENTID = 0x48,
	UC_ARRA        = 0x4a,
	UC_POPEVENTID  = 0x4b,
	UC_DBGLINE     = 0x4c,    // SI debug opcode; UCC never emits this.
	UC_DBGFUNC     = 0x4d,    // SI debug opcode; UCC never emits this.
	// Added for Exult:
	UC_PUSHSTATIC = 0x50,    // Push static.
	UC_POPSTATIC  = 0x51,    // Pop static.
	UC_CALLO      = 0x52,    // Call original.
	UC_CALLIND    = 0x53,    // Call indirect.  Addr. on stack.
	UC_PUSHTHV    = 0x54,    // Push this->var.
	UC_POPTHV     = 0x55,    // Pop this->var.
	UC_CALLM      = 0x56,    // Call method (index is param, class on stack).
	UC_CALLMS     = 0x57,    // Call method (index is param, and so is vtable).
	UC_CLSCREATE  = 0x58,    // Create class instance.
	UC_CLASSDEL   = 0x59,    // Delete class instance.
	UC_AIDXS      = 0x5a,    // Pop static array elem.
	UC_POPARRS    = 0x5b,    // Pop into static array elem.
	UC_LOOPTOPS   = 0x5c,    // Loop with static array
	UC_AIDXTHV    = 0x5d,    // Pop this->var array elem.
	UC_POPARRTHV  = 0x5e,    // Pop this->var array elem.
	UC_LOOPTOPTHV = 0x5f,    // Loop with this->var array.
	UC_PUSHCHOICE = 0x60,    // Pushes last selected user choice.
	UC_TRYSTART   = 0x61,    // TRY/CATCH block start.
	UC_TRYEND     = 0x62,    // TRY/CATCH block end.
	UC_PUSHFVAR   = 0xc2,    // PUSH global flag using stack value.
	UC_POPFVAR    = 0xc3,    // POP global flag using stack value.
	UC_CALLINDEX_OLD = 0xd3,    // Call indirect; UCC never emits this.
	UC_CALLINDEX = 0xd4,    // Call indirect.  Addr. on stack. with arguments

	// 32-bit usecode
	UC_LOOPTOP32  = 0x82,
	UC_CONVERSE32 = 0x84,
	UC_JNE32      = 0x85,
	UC_JMP32      = 0x86,
	UC_CMPS32     = 0x87,
	UC_ADDSI32    = 0x9c,
	UC_PUSHS32    = 0x9d,
	UC_PUSHI32    = 0x9f,
	UC_CALL32     = 0xa4,
	UC_LOOP32     = 0xae,    // 32-bit version of UC_LOOP; UCC never emits this.
	UC_DEFAULT32  = 0xb1,    // 32-bit version of conversation default opcode.
	UC_CALLE32    = 0xc7,
	UC_DBGFUNC32  = 0xcd,      // 32-bit version of SI debug opcode; UCC never
							   // emits this.
	UC_LOOPTOPS32   = 0xdc,    // 32-bit loop with static array.
	UC_LOOPTOPTHV32 = 0xdf,    // 32-bit loop with this->var array.
	UC_TRYSTART32   = 0xe1     // TRY/CATCH block, 32-bit version.
};

inline UsecodeOps& operator|=(UsecodeOps& lhs, int rhs) {
	lhs = static_cast<UsecodeOps>(static_cast<int>(lhs) | rhs);
	return lhs;
}

inline UsecodeOps& operator&=(UsecodeOps& lhs, int rhs) {
	lhs = static_cast<UsecodeOps>(static_cast<int>(lhs) & rhs);
	return lhs;
}

inline UsecodeOps operator|(const UsecodeOps& lhs, int rhs) {
	UsecodeOps ret = lhs;
	return ret |= rhs;
}

inline UsecodeOps operator&(const UsecodeOps& lhs, int rhs) {
	UsecodeOps ret = lhs;
	return ret &= rhs;
}

#endif
