This is the open source Pawn interpreter ported to mbed. See here: http://www.compuphase.com/pawn/pawn.htm and here: http://code.google.com/p/pawnscript/

Dependents:   Pawn4Test

Some instructions:

  • Put the attached include folder next to your source, so when you compile you get all the proper definitions
  • Use the attached main.p as a starting point if you wish
  • Compile your main.p into main.amx - Put your main.amx on the mbed 'drive'
  • Reset and be amazed.

Important Compile Notes:

  • You should use the -S# option to define a smaller default stack size. Start with -S64 and go up from there if needed.
  • To use on the Cortex-M0 version of the mbed (LPC11U24), you MUST include the TARGET=3 command-line option as well, so the pin names are properly defined. In the future this may be handled on the native code side.

Known Issues:

  • At the moment it appears the kbhit() function is not working right - at least on my mac. Will continue testing on Windows. Working fine.

Todo:

  • Add more wrappers for the mbed peripherals
  • Add Pawn overlay support, to allow much larger scripts to run (even on the LPC11U24)
Committer:
Lobo
Date:
Fri May 24 17:49:26 2013 +0000
Revision:
3:185fdbb7ccf0
Parent:
0:3ab1d2d14eb3
Now includes AnalogIn and AnalogOut functions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tylerwilson 0:3ab1d2d14eb3 1 /* Pawn Abstract Machine (for the Pawn language)
tylerwilson 0:3ab1d2d14eb3 2 *
tylerwilson 0:3ab1d2d14eb3 3 * Copyright (c) ITB CompuPhase, 1997-2012
tylerwilson 0:3ab1d2d14eb3 4 *
tylerwilson 0:3ab1d2d14eb3 5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
tylerwilson 0:3ab1d2d14eb3 6 * use this file except in compliance with the License. You may obtain a copy
tylerwilson 0:3ab1d2d14eb3 7 * of the License at
tylerwilson 0:3ab1d2d14eb3 8 *
tylerwilson 0:3ab1d2d14eb3 9 * http://www.apache.org/licenses/LICENSE-2.0
tylerwilson 0:3ab1d2d14eb3 10 *
tylerwilson 0:3ab1d2d14eb3 11 * Unless required by applicable law or agreed to in writing, software
tylerwilson 0:3ab1d2d14eb3 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
tylerwilson 0:3ab1d2d14eb3 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
tylerwilson 0:3ab1d2d14eb3 14 * License for the specific language governing permissions and limitations
tylerwilson 0:3ab1d2d14eb3 15 * under the License.
tylerwilson 0:3ab1d2d14eb3 16 *
tylerwilson 0:3ab1d2d14eb3 17 * Version: $Id: amx.c 4708 2012-05-18 12:52:49Z thiadmer $
tylerwilson 0:3ab1d2d14eb3 18 */
tylerwilson 0:3ab1d2d14eb3 19
tylerwilson 0:3ab1d2d14eb3 20 #define WIN32_LEAN_AND_MEAN
tylerwilson 0:3ab1d2d14eb3 21 #if defined _UNICODE || defined __UNICODE__ || defined UNICODE
tylerwilson 0:3ab1d2d14eb3 22 # if !defined UNICODE /* for Windows API */
tylerwilson 0:3ab1d2d14eb3 23 # define UNICODE
tylerwilson 0:3ab1d2d14eb3 24 # endif
tylerwilson 0:3ab1d2d14eb3 25 # if !defined _UNICODE /* for C library */
tylerwilson 0:3ab1d2d14eb3 26 # define _UNICODE
tylerwilson 0:3ab1d2d14eb3 27 # endif
tylerwilson 0:3ab1d2d14eb3 28 #endif
tylerwilson 0:3ab1d2d14eb3 29
tylerwilson 0:3ab1d2d14eb3 30 #include <assert.h>
tylerwilson 0:3ab1d2d14eb3 31 #include <stdarg.h>
tylerwilson 0:3ab1d2d14eb3 32 #include <stddef.h> /* for wchar_t */
tylerwilson 0:3ab1d2d14eb3 33 #include <stdlib.h> /* for getenv() */
tylerwilson 0:3ab1d2d14eb3 34 #include <string.h>
tylerwilson 0:3ab1d2d14eb3 35 #include "osdefs.h"
tylerwilson 0:3ab1d2d14eb3 36 #if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 37 #include <sclinux.h>
tylerwilson 0:3ab1d2d14eb3 38 #if !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 39 #include <dlfcn.h>
tylerwilson 0:3ab1d2d14eb3 40 #endif
tylerwilson 0:3ab1d2d14eb3 41 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 42 #include <sys/types.h>
tylerwilson 0:3ab1d2d14eb3 43 #include <sys/mman.h>
tylerwilson 0:3ab1d2d14eb3 44 #endif
tylerwilson 0:3ab1d2d14eb3 45 #endif
tylerwilson 0:3ab1d2d14eb3 46 #if defined __LCC__ || defined __LINUX__
tylerwilson 0:3ab1d2d14eb3 47 #include <wchar.h> /* for wcslen() */
tylerwilson 0:3ab1d2d14eb3 48 #endif
tylerwilson 0:3ab1d2d14eb3 49
tylerwilson 0:3ab1d2d14eb3 50 #if defined __ECOS__
tylerwilson 0:3ab1d2d14eb3 51 /* eCos puts include files in cyg/package_name */
tylerwilson 0:3ab1d2d14eb3 52 #include <cyg/pawn/amx.h>
tylerwilson 0:3ab1d2d14eb3 53 #else
tylerwilson 0:3ab1d2d14eb3 54 #include "amx.h"
tylerwilson 0:3ab1d2d14eb3 55 #endif
tylerwilson 0:3ab1d2d14eb3 56
tylerwilson 0:3ab1d2d14eb3 57 #if (defined _Windows && !defined AMX_NODYNALOAD) || (defined AMX_JIT && __WIN32__)
tylerwilson 0:3ab1d2d14eb3 58 #include <windows.h>
tylerwilson 0:3ab1d2d14eb3 59 #endif
tylerwilson 0:3ab1d2d14eb3 60
tylerwilson 0:3ab1d2d14eb3 61
tylerwilson 0:3ab1d2d14eb3 62 /* When one or more of the AMX_funcname macros are defined, we want
tylerwilson 0:3ab1d2d14eb3 63 * to compile only those functions. However, when none of these macros
tylerwilson 0:3ab1d2d14eb3 64 * is present, we want to compile everything.
tylerwilson 0:3ab1d2d14eb3 65 */
tylerwilson 0:3ab1d2d14eb3 66 #if defined AMX_ALIGN || defined AMX_ALLOT || defined AMX_CLEANUP
tylerwilson 0:3ab1d2d14eb3 67 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 68 #endif
tylerwilson 0:3ab1d2d14eb3 69 #if defined AMX_CLONE || defined AMX_DEFCALLBACK || defined AMX_EXEC
tylerwilson 0:3ab1d2d14eb3 70 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 71 #endif
tylerwilson 0:3ab1d2d14eb3 72 #if defined AMX_FLAGS || defined AMX_INIT || defined AMX_MEMINFO
tylerwilson 0:3ab1d2d14eb3 73 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 74 #endif
tylerwilson 0:3ab1d2d14eb3 75 #if defined AMX_NAMELENGTH || defined AMX_NATIVEINFO || defined AMX_PUSHXXX
tylerwilson 0:3ab1d2d14eb3 76 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 77 #endif
tylerwilson 0:3ab1d2d14eb3 78 #if defined AMX_RAISEERROR || defined AMX_REGISTER || defined AMX_SETCALLBACK
tylerwilson 0:3ab1d2d14eb3 79 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 80 #endif
tylerwilson 0:3ab1d2d14eb3 81 #if defined AMX_SETDEBUGHOOK || defined AMX_UTF8XXX || defined AMX_XXXNATIVES
tylerwilson 0:3ab1d2d14eb3 82 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 83 #endif
tylerwilson 0:3ab1d2d14eb3 84 #if defined AMX_XXXPUBLICS || defined AMX_XXXPUBVARS || defined AMX_XXXSTRING
tylerwilson 0:3ab1d2d14eb3 85 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 86 #endif
tylerwilson 0:3ab1d2d14eb3 87 #if defined AMX_XXXTAGS || defined AMX_XXXUSERDATA
tylerwilson 0:3ab1d2d14eb3 88 #define AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 89 #endif
tylerwilson 0:3ab1d2d14eb3 90 #if !defined AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 91 /* no constant set, set them all */
tylerwilson 0:3ab1d2d14eb3 92 #define AMX_ALIGN /* amx_Align16(), amx_Align32() and amx_Align64() */
tylerwilson 0:3ab1d2d14eb3 93 #define AMX_ALLOT /* amx_Allot() and amx_Release() */
tylerwilson 0:3ab1d2d14eb3 94 #define AMX_DEFCALLBACK /* amx_Callback() */
tylerwilson 0:3ab1d2d14eb3 95 #define AMX_CLEANUP /* amx_Cleanup() */
tylerwilson 0:3ab1d2d14eb3 96 #define AMX_CLONE /* amx_Clone() */
tylerwilson 0:3ab1d2d14eb3 97 #define AMX_EXEC /* amx_Exec() */
tylerwilson 0:3ab1d2d14eb3 98 #define AMX_FLAGS /* amx_Flags() */
tylerwilson 0:3ab1d2d14eb3 99 #define AMX_INIT /* amx_Init() and amx_InitJIT() */
tylerwilson 0:3ab1d2d14eb3 100 #define AMX_MEMINFO /* amx_MemInfo() */
tylerwilson 0:3ab1d2d14eb3 101 #define AMX_NAMELENGTH /* amx_NameLength() */
tylerwilson 0:3ab1d2d14eb3 102 #define AMX_NATIVEINFO /* amx_NativeInfo() */
tylerwilson 0:3ab1d2d14eb3 103 #define AMX_PUSHXXX /* amx_Push(), amx_PushAddress(), amx_PushArray() and amx_PushString() */
tylerwilson 0:3ab1d2d14eb3 104 #define AMX_RAISEERROR /* amx_RaiseError() */
tylerwilson 0:3ab1d2d14eb3 105 #define AMX_REGISTER /* amx_Register() */
tylerwilson 0:3ab1d2d14eb3 106 #define AMX_SETCALLBACK /* amx_SetCallback() */
tylerwilson 0:3ab1d2d14eb3 107 #define AMX_SETDEBUGHOOK /* amx_SetDebugHook() */
tylerwilson 0:3ab1d2d14eb3 108 #define AMX_UTF8XXX /* amx_UTF8Check(), amx_UTF8Get(), amx_UTF8Len() and amx_UTF8Put() */
tylerwilson 0:3ab1d2d14eb3 109 #define AMX_XXXNATIVES /* amx_NumNatives(), amx_GetNative() and amx_FindNative() */
tylerwilson 0:3ab1d2d14eb3 110 #define AMX_XXXPUBLICS /* amx_NumPublics(), amx_GetPublic() and amx_FindPublic() */
tylerwilson 0:3ab1d2d14eb3 111 #define AMX_XXXPUBVARS /* amx_NumPubVars(), amx_GetPubVar() and amx_FindPubVar() */
tylerwilson 0:3ab1d2d14eb3 112 #define AMX_XXXSTRING /* amx_StrLen(), amx_GetString() and amx_SetString() */
tylerwilson 0:3ab1d2d14eb3 113 #define AMX_XXXTAGS /* amx_NumTags(), amx_GetTag() and amx_FindTagId() */
tylerwilson 0:3ab1d2d14eb3 114 #define AMX_XXXUSERDATA /* amx_GetUserData() and amx_SetUserData() */
tylerwilson 0:3ab1d2d14eb3 115 #endif
tylerwilson 0:3ab1d2d14eb3 116 #undef AMX_EXPLIT_FUNCTIONS
tylerwilson 0:3ab1d2d14eb3 117 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 118 #undef AMX_UTF8XXX /* no UTF-8 support in ANSI/ASCII-only version */
tylerwilson 0:3ab1d2d14eb3 119 #endif
tylerwilson 0:3ab1d2d14eb3 120 #if defined AMX_NO_NATIVEINFO
tylerwilson 0:3ab1d2d14eb3 121 #undef AMX_NATIVEINFO
tylerwilson 0:3ab1d2d14eb3 122 #endif
tylerwilson 0:3ab1d2d14eb3 123 #if AMX_USERNUM <= 0
tylerwilson 0:3ab1d2d14eb3 124 #undef AMX_XXXUSERDATA
tylerwilson 0:3ab1d2d14eb3 125 #endif
tylerwilson 0:3ab1d2d14eb3 126 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 127 /* JIT is incompatible with macro instructions, packed opcodes and overlays */
tylerwilson 0:3ab1d2d14eb3 128 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 129 #define AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 130 #endif
tylerwilson 0:3ab1d2d14eb3 131 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 132 #define AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 133 #endif
tylerwilson 0:3ab1d2d14eb3 134 #if !defined AMX_NO_OVERLAY
tylerwilson 0:3ab1d2d14eb3 135 #define AMX_NO_OVERLAY
tylerwilson 0:3ab1d2d14eb3 136 #endif
tylerwilson 0:3ab1d2d14eb3 137 #endif
tylerwilson 0:3ab1d2d14eb3 138 #if (defined AMX_ASM || defined AMX_JIT) && !defined AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 139 /* do not use the standard ANSI-C amx_Exec() function */
tylerwilson 0:3ab1d2d14eb3 140 #define AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 141 #endif
tylerwilson 0:3ab1d2d14eb3 142 #if !defined AMX_NO_PACKED_OPC && !defined AMX_TOKENTHREADING
tylerwilson 0:3ab1d2d14eb3 143 #define AMX_TOKENTHREADING /* packed opcodes require token threading */
tylerwilson 0:3ab1d2d14eb3 144 #endif
tylerwilson 0:3ab1d2d14eb3 145
tylerwilson 0:3ab1d2d14eb3 146 #if defined AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 147 #if defined __WIN32__
tylerwilson 0:3ab1d2d14eb3 148 /* For Watcom C/C++ use register calling convention (faster); for
tylerwilson 0:3ab1d2d14eb3 149 * Microsoft C/C++ (and most other C compilers) use "cdecl".
tylerwilson 0:3ab1d2d14eb3 150 * The important point is that you assemble AMXEXEC.ASM with the matching
tylerwilson 0:3ab1d2d14eb3 151 * calling convention, or the right JIT, respectively.
tylerwilson 0:3ab1d2d14eb3 152 * AMXJITR.ASM is for Watcom's register calling convention, AMXJITS.ASM and
tylerwilson 0:3ab1d2d14eb3 153 * AMXJITSN.ASM are for "cdecl".
tylerwilson 0:3ab1d2d14eb3 154 */
tylerwilson 0:3ab1d2d14eb3 155 #if defined __WATCOMC__ && !defined STACKARGS
tylerwilson 0:3ab1d2d14eb3 156 /* register calling convention; the #pragma tells the compiler into which
tylerwilson 0:3ab1d2d14eb3 157 * registers the parameters should go
tylerwilson 0:3ab1d2d14eb3 158 */
tylerwilson 0:3ab1d2d14eb3 159 extern cell amx_exec_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 160 #pragma aux amx_exec_run parm [eax] [edx] [ebx];
tylerwilson 0:3ab1d2d14eb3 161 extern int amx_exec_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 162 #pragma aux amx_exec_run parm [eax] [edx] [ebx];
tylerwilson 0:3ab1d2d14eb3 163 extern cell amx_jit_compile(void *pcode, void *jumparray, void *nativecode);
tylerwilson 0:3ab1d2d14eb3 164 #pragma aux amx_exec_run parm [eax] [edx] [ebx];
tylerwilson 0:3ab1d2d14eb3 165 extern cell amx_jit_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 166 #pragma aux amx_jit_run parm [eax] [edx] [ebx];
tylerwilson 0:3ab1d2d14eb3 167 extern int amx_jit_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 168 #pragma aux amx_exec_run parm [eax] [edx] [ebx];
tylerwilson 0:3ab1d2d14eb3 169 #elif defined __GNUC__
tylerwilson 0:3ab1d2d14eb3 170 /* force "cdecl" by adding an "attribute" to the declaration */
tylerwilson 0:3ab1d2d14eb3 171 extern cell amx_exec_run(AMX *amx,cell *retval,unsigned char *data) __attribute__((cdecl));
tylerwilson 0:3ab1d2d14eb3 172 extern int amx_exec_list(const AMX *amx,const cell **opcodelist,int *numopcodes) __attribute__((cdecl));
tylerwilson 0:3ab1d2d14eb3 173 extern cell amx_jit_compile(void *pcode, void *jumparray, void *nativecode) __attribute__((cdecl));
tylerwilson 0:3ab1d2d14eb3 174 extern cell amx_jit_run(AMX *amx,cell *retval,unsigned char *data) __attribute__((cdecl));
tylerwilson 0:3ab1d2d14eb3 175 extern int amx_jit_list(const AMX *amx,const cell **opcodelist,int *numopcodes) __attribute__((cdecl));
tylerwilson 0:3ab1d2d14eb3 176 #else
tylerwilson 0:3ab1d2d14eb3 177 /* force "cdecl" by specifying it as a "function class" with the "__cdecl" keyword */
tylerwilson 0:3ab1d2d14eb3 178 extern cell __cdecl amx_exec_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 179 extern int __cdecl amx_exec_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 180 extern cell __cdecl amx_jit_compile(void *pcode, void *jumparray, void *nativecode);
tylerwilson 0:3ab1d2d14eb3 181 extern cell __cdecl amx_jit_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 182 extern int __cdecl amx_jit_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 183 #endif
tylerwilson 0:3ab1d2d14eb3 184 #else /* __WIN32__ */
tylerwilson 0:3ab1d2d14eb3 185 /* assume no specific calling conventions for other platforms than Windows */
tylerwilson 0:3ab1d2d14eb3 186 extern cell amx_exec_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 187 extern int amx_exec_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 188 extern cell amx_jit_compile(void *pcode, void *jumparray, void *nativecode);
tylerwilson 0:3ab1d2d14eb3 189 extern cell amx_jit_run(AMX *amx,cell *retval,unsigned char *data);
tylerwilson 0:3ab1d2d14eb3 190 extern int amx_jit_list(const AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 191 #endif /* __WIN32__ */
tylerwilson 0:3ab1d2d14eb3 192 #else
tylerwilson 0:3ab1d2d14eb3 193 int amx_exec_list(AMX *amx,const cell **opcodelist,int *numopcodes);
tylerwilson 0:3ab1d2d14eb3 194 #endif /* AMX_ALTCORE */
tylerwilson 0:3ab1d2d14eb3 195
tylerwilson 0:3ab1d2d14eb3 196 typedef enum {
tylerwilson 0:3ab1d2d14eb3 197 OP_NOP,
tylerwilson 0:3ab1d2d14eb3 198 OP_LOAD_PRI,
tylerwilson 0:3ab1d2d14eb3 199 OP_LOAD_ALT,
tylerwilson 0:3ab1d2d14eb3 200 OP_LOAD_S_PRI,
tylerwilson 0:3ab1d2d14eb3 201 OP_LOAD_S_ALT,
tylerwilson 0:3ab1d2d14eb3 202 OP_LREF_S_PRI,
tylerwilson 0:3ab1d2d14eb3 203 OP_LREF_S_ALT,
tylerwilson 0:3ab1d2d14eb3 204 OP_LOAD_I,
tylerwilson 0:3ab1d2d14eb3 205 OP_LODB_I,
tylerwilson 0:3ab1d2d14eb3 206 OP_CONST_PRI,
tylerwilson 0:3ab1d2d14eb3 207 OP_CONST_ALT,
tylerwilson 0:3ab1d2d14eb3 208 OP_ADDR_PRI,
tylerwilson 0:3ab1d2d14eb3 209 OP_ADDR_ALT,
tylerwilson 0:3ab1d2d14eb3 210 OP_STOR,
tylerwilson 0:3ab1d2d14eb3 211 OP_STOR_S,
tylerwilson 0:3ab1d2d14eb3 212 OP_SREF_S,
tylerwilson 0:3ab1d2d14eb3 213 OP_STOR_I,
tylerwilson 0:3ab1d2d14eb3 214 OP_STRB_I,
tylerwilson 0:3ab1d2d14eb3 215 OP_ALIGN_PRI,
tylerwilson 0:3ab1d2d14eb3 216 OP_LCTRL,
tylerwilson 0:3ab1d2d14eb3 217 OP_SCTRL,
tylerwilson 0:3ab1d2d14eb3 218 OP_XCHG,
tylerwilson 0:3ab1d2d14eb3 219 OP_PUSH_PRI,
tylerwilson 0:3ab1d2d14eb3 220 OP_PUSH_ALT,
tylerwilson 0:3ab1d2d14eb3 221 OP_PUSHR_PRI,
tylerwilson 0:3ab1d2d14eb3 222 OP_POP_PRI,
tylerwilson 0:3ab1d2d14eb3 223 OP_POP_ALT,
tylerwilson 0:3ab1d2d14eb3 224 OP_PICK,
tylerwilson 0:3ab1d2d14eb3 225 OP_STACK,
tylerwilson 0:3ab1d2d14eb3 226 OP_HEAP,
tylerwilson 0:3ab1d2d14eb3 227 OP_PROC,
tylerwilson 0:3ab1d2d14eb3 228 OP_RET,
tylerwilson 0:3ab1d2d14eb3 229 OP_RETN,
tylerwilson 0:3ab1d2d14eb3 230 OP_CALL,
tylerwilson 0:3ab1d2d14eb3 231 OP_JUMP,
tylerwilson 0:3ab1d2d14eb3 232 OP_JZER,
tylerwilson 0:3ab1d2d14eb3 233 OP_JNZ,
tylerwilson 0:3ab1d2d14eb3 234 OP_SHL,
tylerwilson 0:3ab1d2d14eb3 235 OP_SHR,
tylerwilson 0:3ab1d2d14eb3 236 OP_SSHR,
tylerwilson 0:3ab1d2d14eb3 237 OP_SHL_C_PRI,
tylerwilson 0:3ab1d2d14eb3 238 OP_SHL_C_ALT,
tylerwilson 0:3ab1d2d14eb3 239 OP_SMUL,
tylerwilson 0:3ab1d2d14eb3 240 OP_SDIV,
tylerwilson 0:3ab1d2d14eb3 241 OP_ADD,
tylerwilson 0:3ab1d2d14eb3 242 OP_SUB,
tylerwilson 0:3ab1d2d14eb3 243 OP_AND,
tylerwilson 0:3ab1d2d14eb3 244 OP_OR,
tylerwilson 0:3ab1d2d14eb3 245 OP_XOR,
tylerwilson 0:3ab1d2d14eb3 246 OP_NOT,
tylerwilson 0:3ab1d2d14eb3 247 OP_NEG,
tylerwilson 0:3ab1d2d14eb3 248 OP_INVERT,
tylerwilson 0:3ab1d2d14eb3 249 OP_EQ,
tylerwilson 0:3ab1d2d14eb3 250 OP_NEQ,
tylerwilson 0:3ab1d2d14eb3 251 OP_SLESS,
tylerwilson 0:3ab1d2d14eb3 252 OP_SLEQ,
tylerwilson 0:3ab1d2d14eb3 253 OP_SGRTR,
tylerwilson 0:3ab1d2d14eb3 254 OP_SGEQ,
tylerwilson 0:3ab1d2d14eb3 255 OP_INC_PRI,
tylerwilson 0:3ab1d2d14eb3 256 OP_INC_ALT,
tylerwilson 0:3ab1d2d14eb3 257 OP_INC_I,
tylerwilson 0:3ab1d2d14eb3 258 OP_DEC_PRI,
tylerwilson 0:3ab1d2d14eb3 259 OP_DEC_ALT,
tylerwilson 0:3ab1d2d14eb3 260 OP_DEC_I,
tylerwilson 0:3ab1d2d14eb3 261 OP_MOVS,
tylerwilson 0:3ab1d2d14eb3 262 OP_CMPS,
tylerwilson 0:3ab1d2d14eb3 263 OP_FILL,
tylerwilson 0:3ab1d2d14eb3 264 OP_HALT,
tylerwilson 0:3ab1d2d14eb3 265 OP_BOUNDS,
tylerwilson 0:3ab1d2d14eb3 266 OP_SYSREQ,
tylerwilson 0:3ab1d2d14eb3 267 OP_SWITCH,
tylerwilson 0:3ab1d2d14eb3 268 OP_SWAP_PRI,
tylerwilson 0:3ab1d2d14eb3 269 OP_SWAP_ALT,
tylerwilson 0:3ab1d2d14eb3 270 OP_BREAK,
tylerwilson 0:3ab1d2d14eb3 271 OP_CASETBL,
tylerwilson 0:3ab1d2d14eb3 272 /* patched instructions */
tylerwilson 0:3ab1d2d14eb3 273 OP_SYSREQ_D,
tylerwilson 0:3ab1d2d14eb3 274 OP_SYSREQ_ND,
tylerwilson 0:3ab1d2d14eb3 275 /* overlay instructions */
tylerwilson 0:3ab1d2d14eb3 276 OP_CALL_OVL,
tylerwilson 0:3ab1d2d14eb3 277 OP_RETN_OVL,
tylerwilson 0:3ab1d2d14eb3 278 OP_SWITCH_OVL,
tylerwilson 0:3ab1d2d14eb3 279 OP_CASETBL_OVL,
tylerwilson 0:3ab1d2d14eb3 280 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 281 /* supplemental & macro instructions */
tylerwilson 0:3ab1d2d14eb3 282 OP_LIDX,
tylerwilson 0:3ab1d2d14eb3 283 OP_LIDX_B,
tylerwilson 0:3ab1d2d14eb3 284 OP_IDXADDR,
tylerwilson 0:3ab1d2d14eb3 285 OP_IDXADDR_B,
tylerwilson 0:3ab1d2d14eb3 286 OP_PUSH_C,
tylerwilson 0:3ab1d2d14eb3 287 OP_PUSH,
tylerwilson 0:3ab1d2d14eb3 288 OP_PUSH_S,
tylerwilson 0:3ab1d2d14eb3 289 OP_PUSH_ADR,
tylerwilson 0:3ab1d2d14eb3 290 OP_PUSHR_C,
tylerwilson 0:3ab1d2d14eb3 291 OP_PUSHR_S,
tylerwilson 0:3ab1d2d14eb3 292 OP_PUSHR_ADR,
tylerwilson 0:3ab1d2d14eb3 293 OP_JEQ,
tylerwilson 0:3ab1d2d14eb3 294 OP_JNEQ,
tylerwilson 0:3ab1d2d14eb3 295 OP_JSLESS,
tylerwilson 0:3ab1d2d14eb3 296 OP_JSLEQ,
tylerwilson 0:3ab1d2d14eb3 297 OP_JSGRTR,
tylerwilson 0:3ab1d2d14eb3 298 OP_JSGEQ,
tylerwilson 0:3ab1d2d14eb3 299 OP_SDIV_INV,
tylerwilson 0:3ab1d2d14eb3 300 OP_SUB_INV,
tylerwilson 0:3ab1d2d14eb3 301 OP_ADD_C,
tylerwilson 0:3ab1d2d14eb3 302 OP_SMUL_C,
tylerwilson 0:3ab1d2d14eb3 303 OP_ZERO_PRI,
tylerwilson 0:3ab1d2d14eb3 304 OP_ZERO_ALT,
tylerwilson 0:3ab1d2d14eb3 305 OP_ZERO,
tylerwilson 0:3ab1d2d14eb3 306 OP_ZERO_S,
tylerwilson 0:3ab1d2d14eb3 307 OP_EQ_C_PRI,
tylerwilson 0:3ab1d2d14eb3 308 OP_EQ_C_ALT,
tylerwilson 0:3ab1d2d14eb3 309 OP_INC,
tylerwilson 0:3ab1d2d14eb3 310 OP_INC_S,
tylerwilson 0:3ab1d2d14eb3 311 OP_DEC,
tylerwilson 0:3ab1d2d14eb3 312 OP_DEC_S,
tylerwilson 0:3ab1d2d14eb3 313 /* macro instructions */
tylerwilson 0:3ab1d2d14eb3 314 OP_SYSREQ_N,
tylerwilson 0:3ab1d2d14eb3 315 OP_PUSHM_C,
tylerwilson 0:3ab1d2d14eb3 316 OP_PUSHM,
tylerwilson 0:3ab1d2d14eb3 317 OP_PUSHM_S,
tylerwilson 0:3ab1d2d14eb3 318 OP_PUSHM_ADR,
tylerwilson 0:3ab1d2d14eb3 319 OP_PUSHRM_C,
tylerwilson 0:3ab1d2d14eb3 320 OP_PUSHRM_S,
tylerwilson 0:3ab1d2d14eb3 321 OP_PUSHRM_ADR,
tylerwilson 0:3ab1d2d14eb3 322 OP_LOAD2,
tylerwilson 0:3ab1d2d14eb3 323 OP_LOAD2_S,
tylerwilson 0:3ab1d2d14eb3 324 OP_CONST,
tylerwilson 0:3ab1d2d14eb3 325 OP_CONST_S,
tylerwilson 0:3ab1d2d14eb3 326 #endif
tylerwilson 0:3ab1d2d14eb3 327 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 328 /* packed instructions */
tylerwilson 0:3ab1d2d14eb3 329 OP_LOAD_P_PRI,
tylerwilson 0:3ab1d2d14eb3 330 OP_LOAD_P_ALT,
tylerwilson 0:3ab1d2d14eb3 331 OP_LOAD_P_S_PRI,
tylerwilson 0:3ab1d2d14eb3 332 OP_LOAD_P_S_ALT,
tylerwilson 0:3ab1d2d14eb3 333 OP_LREF_P_S_PRI,
tylerwilson 0:3ab1d2d14eb3 334 OP_LREF_P_S_ALT,
tylerwilson 0:3ab1d2d14eb3 335 OP_LODB_P_I,
tylerwilson 0:3ab1d2d14eb3 336 OP_CONST_P_PRI,
tylerwilson 0:3ab1d2d14eb3 337 OP_CONST_P_ALT,
tylerwilson 0:3ab1d2d14eb3 338 OP_ADDR_P_PRI,
tylerwilson 0:3ab1d2d14eb3 339 OP_ADDR_P_ALT,
tylerwilson 0:3ab1d2d14eb3 340 OP_STOR_P,
tylerwilson 0:3ab1d2d14eb3 341 OP_STOR_P_S,
tylerwilson 0:3ab1d2d14eb3 342 OP_SREF_P_S,
tylerwilson 0:3ab1d2d14eb3 343 OP_STRB_P_I,
tylerwilson 0:3ab1d2d14eb3 344 OP_LIDX_P_B,
tylerwilson 0:3ab1d2d14eb3 345 OP_IDXADDR_P_B,
tylerwilson 0:3ab1d2d14eb3 346 OP_ALIGN_P_PRI,
tylerwilson 0:3ab1d2d14eb3 347 OP_PUSH_P_C,
tylerwilson 0:3ab1d2d14eb3 348 OP_PUSH_P,
tylerwilson 0:3ab1d2d14eb3 349 OP_PUSH_P_S,
tylerwilson 0:3ab1d2d14eb3 350 OP_PUSH_P_ADR,
tylerwilson 0:3ab1d2d14eb3 351 OP_PUSHR_P_C,
tylerwilson 0:3ab1d2d14eb3 352 OP_PUSHR_P_S,
tylerwilson 0:3ab1d2d14eb3 353 OP_PUSHR_P_ADR,
tylerwilson 0:3ab1d2d14eb3 354 OP_PUSHM_P_C,
tylerwilson 0:3ab1d2d14eb3 355 OP_PUSHM_P,
tylerwilson 0:3ab1d2d14eb3 356 OP_PUSHM_P_S,
tylerwilson 0:3ab1d2d14eb3 357 OP_PUSHM_P_ADR,
tylerwilson 0:3ab1d2d14eb3 358 OP_PUSHRM_P_C,
tylerwilson 0:3ab1d2d14eb3 359 OP_PUSHRM_P_S,
tylerwilson 0:3ab1d2d14eb3 360 OP_PUSHRM_P_ADR,
tylerwilson 0:3ab1d2d14eb3 361 OP_STACK_P,
tylerwilson 0:3ab1d2d14eb3 362 OP_HEAP_P,
tylerwilson 0:3ab1d2d14eb3 363 OP_SHL_P_C_PRI,
tylerwilson 0:3ab1d2d14eb3 364 OP_SHL_P_C_ALT,
tylerwilson 0:3ab1d2d14eb3 365 OP_ADD_P_C,
tylerwilson 0:3ab1d2d14eb3 366 OP_SMUL_P_C,
tylerwilson 0:3ab1d2d14eb3 367 OP_ZERO_P,
tylerwilson 0:3ab1d2d14eb3 368 OP_ZERO_P_S,
tylerwilson 0:3ab1d2d14eb3 369 OP_EQ_P_C_PRI,
tylerwilson 0:3ab1d2d14eb3 370 OP_EQ_P_C_ALT,
tylerwilson 0:3ab1d2d14eb3 371 OP_INC_P,
tylerwilson 0:3ab1d2d14eb3 372 OP_INC_P_S,
tylerwilson 0:3ab1d2d14eb3 373 OP_DEC_P,
tylerwilson 0:3ab1d2d14eb3 374 OP_DEC_P_S,
tylerwilson 0:3ab1d2d14eb3 375 OP_MOVS_P,
tylerwilson 0:3ab1d2d14eb3 376 OP_CMPS_P,
tylerwilson 0:3ab1d2d14eb3 377 OP_FILL_P,
tylerwilson 0:3ab1d2d14eb3 378 OP_HALT_P,
tylerwilson 0:3ab1d2d14eb3 379 OP_BOUNDS_P,
tylerwilson 0:3ab1d2d14eb3 380 #endif
tylerwilson 0:3ab1d2d14eb3 381 /* ----- */
tylerwilson 0:3ab1d2d14eb3 382 OP_NUM_OPCODES
tylerwilson 0:3ab1d2d14eb3 383 } OPCODE;
tylerwilson 0:3ab1d2d14eb3 384
tylerwilson 0:3ab1d2d14eb3 385 #define NUMENTRIES(hdr,field,nextfield) \
tylerwilson 0:3ab1d2d14eb3 386 (unsigned)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize)
tylerwilson 0:3ab1d2d14eb3 387 #define GETENTRY(hdr,table,index) \
tylerwilson 0:3ab1d2d14eb3 388 (AMX_FUNCSTUB *)((unsigned char*)(hdr) + (unsigned)(hdr)->table + (unsigned)index*(hdr)->defsize)
tylerwilson 0:3ab1d2d14eb3 389 #define GETENTRYNAME(hdr,entry) \
tylerwilson 0:3ab1d2d14eb3 390 (char *)((unsigned char*)(hdr) + (unsigned)((AMX_FUNCSTUB*)(entry))->nameofs)
tylerwilson 0:3ab1d2d14eb3 391
tylerwilson 0:3ab1d2d14eb3 392 #if !defined NDEBUG
tylerwilson 0:3ab1d2d14eb3 393 static int check_endian(void)
tylerwilson 0:3ab1d2d14eb3 394 {
tylerwilson 0:3ab1d2d14eb3 395 uint16_t val=0x00ff;
tylerwilson 0:3ab1d2d14eb3 396 unsigned char *ptr=(unsigned char *)&val;
tylerwilson 0:3ab1d2d14eb3 397 /* "ptr" points to the starting address of "val". If that address
tylerwilson 0:3ab1d2d14eb3 398 * holds the byte "0xff", the computer stored the low byte of "val"
tylerwilson 0:3ab1d2d14eb3 399 * at the lower address, and so the memory lay out is Little Endian.
tylerwilson 0:3ab1d2d14eb3 400 */
tylerwilson 0:3ab1d2d14eb3 401 assert(*ptr==0xff || *ptr==0x00);
tylerwilson 0:3ab1d2d14eb3 402 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 403 return *ptr==0x00; /* return "true" if big endian */
tylerwilson 0:3ab1d2d14eb3 404 #else
tylerwilson 0:3ab1d2d14eb3 405 return *ptr==0xff; /* return "true" if little endian */
tylerwilson 0:3ab1d2d14eb3 406 #endif
tylerwilson 0:3ab1d2d14eb3 407 }
tylerwilson 0:3ab1d2d14eb3 408 #endif
tylerwilson 0:3ab1d2d14eb3 409
tylerwilson 0:3ab1d2d14eb3 410 #if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==16
tylerwilson 0:3ab1d2d14eb3 411 static void swap16(uint16_t *v)
tylerwilson 0:3ab1d2d14eb3 412 {
tylerwilson 0:3ab1d2d14eb3 413 unsigned char *s = (unsigned char *)v;
tylerwilson 0:3ab1d2d14eb3 414 unsigned char t;
tylerwilson 0:3ab1d2d14eb3 415
tylerwilson 0:3ab1d2d14eb3 416 assert_static(sizeof(*v)==2);
tylerwilson 0:3ab1d2d14eb3 417 /* swap two bytes */
tylerwilson 0:3ab1d2d14eb3 418 t=s[0];
tylerwilson 0:3ab1d2d14eb3 419 s[0]=s[1];
tylerwilson 0:3ab1d2d14eb3 420 s[1]=t;
tylerwilson 0:3ab1d2d14eb3 421 }
tylerwilson 0:3ab1d2d14eb3 422 #endif
tylerwilson 0:3ab1d2d14eb3 423
tylerwilson 0:3ab1d2d14eb3 424 #if BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==32
tylerwilson 0:3ab1d2d14eb3 425 static void swap32(uint32_t *v)
tylerwilson 0:3ab1d2d14eb3 426 {
tylerwilson 0:3ab1d2d14eb3 427 unsigned char *s = (unsigned char *)v;
tylerwilson 0:3ab1d2d14eb3 428 unsigned char t;
tylerwilson 0:3ab1d2d14eb3 429
tylerwilson 0:3ab1d2d14eb3 430 assert_static(sizeof(*v)==4);
tylerwilson 0:3ab1d2d14eb3 431 /* swap outer two bytes */
tylerwilson 0:3ab1d2d14eb3 432 t=s[0];
tylerwilson 0:3ab1d2d14eb3 433 s[0]=s[3];
tylerwilson 0:3ab1d2d14eb3 434 s[3]=t;
tylerwilson 0:3ab1d2d14eb3 435 /* swap inner two bytes */
tylerwilson 0:3ab1d2d14eb3 436 t=s[1];
tylerwilson 0:3ab1d2d14eb3 437 s[1]=s[2];
tylerwilson 0:3ab1d2d14eb3 438 s[2]=t;
tylerwilson 0:3ab1d2d14eb3 439 }
tylerwilson 0:3ab1d2d14eb3 440 #endif
tylerwilson 0:3ab1d2d14eb3 441
tylerwilson 0:3ab1d2d14eb3 442 #if (BYTE_ORDER==BIG_ENDIAN || PAWN_CELL_SIZE==64) && (defined _I64_MAX || defined HAVE_I64)
tylerwilson 0:3ab1d2d14eb3 443 static void swap64(uint64_t *v)
tylerwilson 0:3ab1d2d14eb3 444 {
tylerwilson 0:3ab1d2d14eb3 445 unsigned char *s = (unsigned char *)v;
tylerwilson 0:3ab1d2d14eb3 446 unsigned char t;
tylerwilson 0:3ab1d2d14eb3 447
tylerwilson 0:3ab1d2d14eb3 448 assert(sizeof(*v)==8);
tylerwilson 0:3ab1d2d14eb3 449
tylerwilson 0:3ab1d2d14eb3 450 t=s[0];
tylerwilson 0:3ab1d2d14eb3 451 s[0]=s[7];
tylerwilson 0:3ab1d2d14eb3 452 s[7]=t;
tylerwilson 0:3ab1d2d14eb3 453
tylerwilson 0:3ab1d2d14eb3 454 t=s[1];
tylerwilson 0:3ab1d2d14eb3 455 s[1]=s[6];
tylerwilson 0:3ab1d2d14eb3 456 s[6]=t;
tylerwilson 0:3ab1d2d14eb3 457
tylerwilson 0:3ab1d2d14eb3 458 t=s[2];
tylerwilson 0:3ab1d2d14eb3 459 s[2]=s[5];
tylerwilson 0:3ab1d2d14eb3 460 s[5]=t;
tylerwilson 0:3ab1d2d14eb3 461
tylerwilson 0:3ab1d2d14eb3 462 t=s[3];
tylerwilson 0:3ab1d2d14eb3 463 s[3]=s[4];
tylerwilson 0:3ab1d2d14eb3 464 s[4]=t;
tylerwilson 0:3ab1d2d14eb3 465 }
tylerwilson 0:3ab1d2d14eb3 466 #endif
tylerwilson 0:3ab1d2d14eb3 467
tylerwilson 0:3ab1d2d14eb3 468 #if defined AMX_ALIGN || defined AMX_INIT
tylerwilson 0:3ab1d2d14eb3 469 uint16_t * AMXAPI amx_Align16(uint16_t *v)
tylerwilson 0:3ab1d2d14eb3 470 {
tylerwilson 0:3ab1d2d14eb3 471 assert_static(sizeof(*v)==2);
tylerwilson 0:3ab1d2d14eb3 472 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 473 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 474 swap16(v);
tylerwilson 0:3ab1d2d14eb3 475 #endif
tylerwilson 0:3ab1d2d14eb3 476 return v;
tylerwilson 0:3ab1d2d14eb3 477 }
tylerwilson 0:3ab1d2d14eb3 478
tylerwilson 0:3ab1d2d14eb3 479 uint32_t * AMXAPI amx_Align32(uint32_t *v)
tylerwilson 0:3ab1d2d14eb3 480 {
tylerwilson 0:3ab1d2d14eb3 481 assert_static(sizeof(*v)==4);
tylerwilson 0:3ab1d2d14eb3 482 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 483 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 484 swap32(v);
tylerwilson 0:3ab1d2d14eb3 485 #endif
tylerwilson 0:3ab1d2d14eb3 486 return v;
tylerwilson 0:3ab1d2d14eb3 487 }
tylerwilson 0:3ab1d2d14eb3 488
tylerwilson 0:3ab1d2d14eb3 489 #if defined _I64_MAX || defined HAVE_I64
tylerwilson 0:3ab1d2d14eb3 490 uint64_t * AMXAPI amx_Align64(uint64_t *v)
tylerwilson 0:3ab1d2d14eb3 491 {
tylerwilson 0:3ab1d2d14eb3 492 assert(sizeof(*v)==8);
tylerwilson 0:3ab1d2d14eb3 493 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 494 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 495 swap64(v);
tylerwilson 0:3ab1d2d14eb3 496 #endif
tylerwilson 0:3ab1d2d14eb3 497 return v;
tylerwilson 0:3ab1d2d14eb3 498 }
tylerwilson 0:3ab1d2d14eb3 499 #endif /* _I64_MAX || HAVE_I64 */
tylerwilson 0:3ab1d2d14eb3 500 #endif /* AMX_ALIGN || AMX_INIT */
tylerwilson 0:3ab1d2d14eb3 501
tylerwilson 0:3ab1d2d14eb3 502 #if PAWN_CELL_SIZE==16
tylerwilson 0:3ab1d2d14eb3 503 #define swapcell swap16
tylerwilson 0:3ab1d2d14eb3 504 #elif PAWN_CELL_SIZE==32
tylerwilson 0:3ab1d2d14eb3 505 #define swapcell swap32
tylerwilson 0:3ab1d2d14eb3 506 #elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
tylerwilson 0:3ab1d2d14eb3 507 #define swapcell swap64
tylerwilson 0:3ab1d2d14eb3 508 #else
tylerwilson 0:3ab1d2d14eb3 509 #error Unsupported cell size
tylerwilson 0:3ab1d2d14eb3 510 #endif
tylerwilson 0:3ab1d2d14eb3 511
tylerwilson 0:3ab1d2d14eb3 512 #if defined AMX_FLAGS
tylerwilson 0:3ab1d2d14eb3 513 int AMXAPI amx_Flags(AMX *amx,uint16_t *flags)
tylerwilson 0:3ab1d2d14eb3 514 {
tylerwilson 0:3ab1d2d14eb3 515 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 516
tylerwilson 0:3ab1d2d14eb3 517 *flags=0;
tylerwilson 0:3ab1d2d14eb3 518 if (amx==NULL)
tylerwilson 0:3ab1d2d14eb3 519 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 520 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 521 if (hdr->magic!=AMX_MAGIC)
tylerwilson 0:3ab1d2d14eb3 522 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 523 if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_version<MIN_FILE_VERSION)
tylerwilson 0:3ab1d2d14eb3 524 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 525 *flags=hdr->flags;
tylerwilson 0:3ab1d2d14eb3 526 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 527 }
tylerwilson 0:3ab1d2d14eb3 528 #endif /* AMX_FLAGS */
tylerwilson 0:3ab1d2d14eb3 529
tylerwilson 0:3ab1d2d14eb3 530 #if defined AMX_DEFCALLBACK
tylerwilson 0:3ab1d2d14eb3 531 int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, const cell *params)
tylerwilson 0:3ab1d2d14eb3 532 {
tylerwilson 0:3ab1d2d14eb3 533 #if defined AMX_NATIVETABLE
tylerwilson 0:3ab1d2d14eb3 534 extern AMX_NATIVE const AMX_NATIVETABLE[];
tylerwilson 0:3ab1d2d14eb3 535 #endif
tylerwilson 0:3ab1d2d14eb3 536 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 537 AMX_FUNCSTUB *func;
tylerwilson 0:3ab1d2d14eb3 538 AMX_NATIVE f;
tylerwilson 0:3ab1d2d14eb3 539
tylerwilson 0:3ab1d2d14eb3 540 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 541 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 542 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 543 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 544 assert(hdr->natives<=hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 545 #if defined AMX_NATIVETABLE
tylerwilson 0:3ab1d2d14eb3 546 if (index<0) {
tylerwilson 0:3ab1d2d14eb3 547 /* size of AMX_NATIVETABLE is unknown here, so we cannot verify index */
tylerwilson 0:3ab1d2d14eb3 548 f=(AMX_NATIVETABLE)[-(index+1)];
tylerwilson 0:3ab1d2d14eb3 549 } else {
tylerwilson 0:3ab1d2d14eb3 550 #endif
tylerwilson 0:3ab1d2d14eb3 551 assert(index>=0 && index<(cell)NUMENTRIES(hdr,natives,libraries));
tylerwilson 0:3ab1d2d14eb3 552 func=GETENTRY(hdr,natives,index);
tylerwilson 0:3ab1d2d14eb3 553 f=(AMX_NATIVE)func->address;
tylerwilson 0:3ab1d2d14eb3 554 #if defined AMX_NATIVETABLE
tylerwilson 0:3ab1d2d14eb3 555 } /* if */
tylerwilson 0:3ab1d2d14eb3 556 #endif
tylerwilson 0:3ab1d2d14eb3 557 assert(f!=NULL);
tylerwilson 0:3ab1d2d14eb3 558
tylerwilson 0:3ab1d2d14eb3 559 /* Now that we have found the function, patch the program so that any
tylerwilson 0:3ab1d2d14eb3 560 * subsequent call will call the function directly (bypassing this
tylerwilson 0:3ab1d2d14eb3 561 * callback).
tylerwilson 0:3ab1d2d14eb3 562 * This trick cannot work in the JIT, because the program would need to
tylerwilson 0:3ab1d2d14eb3 563 * be re-JIT-compiled after patching a P-code instruction.
tylerwilson 0:3ab1d2d14eb3 564 */
tylerwilson 0:3ab1d2d14eb3 565 assert((amx->flags & AMX_FLAG_JITC)==0 || amx->sysreq_d==0);
tylerwilson 0:3ab1d2d14eb3 566 if (amx->sysreq_d!=0) {
tylerwilson 0:3ab1d2d14eb3 567 /* at the point of the call, the CIP pseudo-register points directly
tylerwilson 0:3ab1d2d14eb3 568 * behind the SYSREQ(.N) instruction and its parameter(s)
tylerwilson 0:3ab1d2d14eb3 569 */
tylerwilson 0:3ab1d2d14eb3 570 unsigned char *code=amx->code+(int)amx->cip-sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 571 if (amx->flags & AMX_FLAG_SYSREQN) /* SYSREQ.N has 2 parameters */
tylerwilson 0:3ab1d2d14eb3 572 code-=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 573 assert(amx->code!=NULL);
tylerwilson 0:3ab1d2d14eb3 574 assert(amx->cip>=4 && amx->cip<(hdr->dat - hdr->cod));
tylerwilson 0:3ab1d2d14eb3 575 assert_static(sizeof(f)<=sizeof(cell)); /* function pointer must fit in a cell */
tylerwilson 0:3ab1d2d14eb3 576 assert(*(cell*)code==index);
tylerwilson 0:3ab1d2d14eb3 577 #if defined AMX_TOKENTHREADING || !(defined __GNUC__ || defined __ICC || defined AMX_ASM || defined AMX_JIT)
tylerwilson 0:3ab1d2d14eb3 578 assert(!(amx->flags & AMX_FLAG_SYSREQN) && *(cell*)(code-sizeof(cell))==OP_SYSREQ
tylerwilson 0:3ab1d2d14eb3 579 || (amx->flags & AMX_FLAG_SYSREQN) && *(cell*)(code-sizeof(cell))==OP_SYSREQ_N);
tylerwilson 0:3ab1d2d14eb3 580 #endif
tylerwilson 0:3ab1d2d14eb3 581 *(cell*)(code-sizeof(cell))=amx->sysreq_d;
tylerwilson 0:3ab1d2d14eb3 582 *(cell*)code=(cell)f;
tylerwilson 0:3ab1d2d14eb3 583 } /* if */
tylerwilson 0:3ab1d2d14eb3 584
tylerwilson 0:3ab1d2d14eb3 585 /* Note:
tylerwilson 0:3ab1d2d14eb3 586 * params[0] == number of bytes for the additional parameters passed to the native function
tylerwilson 0:3ab1d2d14eb3 587 * params[1] == first argument
tylerwilson 0:3ab1d2d14eb3 588 * etc.
tylerwilson 0:3ab1d2d14eb3 589 */
tylerwilson 0:3ab1d2d14eb3 590
tylerwilson 0:3ab1d2d14eb3 591 amx->error=AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 592 *result = f(amx,params);
tylerwilson 0:3ab1d2d14eb3 593 return amx->error;
tylerwilson 0:3ab1d2d14eb3 594 }
tylerwilson 0:3ab1d2d14eb3 595 #endif /* defined AMX_DEFCALLBACK */
tylerwilson 0:3ab1d2d14eb3 596
tylerwilson 0:3ab1d2d14eb3 597
tylerwilson 0:3ab1d2d14eb3 598 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 599 /* convert from relative addresses to absolute physical addresses */
tylerwilson 0:3ab1d2d14eb3 600 #define RELOC_ABS(base,off) (*(ucell *)((base)+(int)(off)) += (ucell)(base)+(int)(off)-sizeof(cell))
tylerwilson 0:3ab1d2d14eb3 601 #else
tylerwilson 0:3ab1d2d14eb3 602 #define JUMPREL(ip) ((cell*)((intptr_t)(ip)+*(cell*)(ip)-sizeof(cell)))
tylerwilson 0:3ab1d2d14eb3 603 #endif
tylerwilson 0:3ab1d2d14eb3 604 #if defined AMX_ASM || defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 605 #define RELOCATE_ADDR(base,v) ((v)+((ucell)(base)))
tylerwilson 0:3ab1d2d14eb3 606 #else
tylerwilson 0:3ab1d2d14eb3 607 #define RELOCATE_ADDR(base,v) (v)
tylerwilson 0:3ab1d2d14eb3 608 #endif
tylerwilson 0:3ab1d2d14eb3 609
tylerwilson 0:3ab1d2d14eb3 610 #define DBGPARAM(v) ( (v)=*(cell *)(amx->code+(int)cip), cip+=sizeof(cell) )
tylerwilson 0:3ab1d2d14eb3 611
tylerwilson 0:3ab1d2d14eb3 612 #if !defined GETOPCODE
tylerwilson 0:3ab1d2d14eb3 613 #if defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 614 #define GETOPCODE(c) (OPCODE)(c)
tylerwilson 0:3ab1d2d14eb3 615 #else
tylerwilson 0:3ab1d2d14eb3 616 #define GETOPCODE(c) (OPCODE)((c) & ((1 << sizeof(cell)*4)-1))
tylerwilson 0:3ab1d2d14eb3 617 #endif
tylerwilson 0:3ab1d2d14eb3 618 #endif
tylerwilson 0:3ab1d2d14eb3 619 #if !defined GETPARAM_P
tylerwilson 0:3ab1d2d14eb3 620 #define GETPARAM_P(v,o) ( v=((cell)(o) >> (int)(sizeof(cell)*4)) )
tylerwilson 0:3ab1d2d14eb3 621 #endif
tylerwilson 0:3ab1d2d14eb3 622
tylerwilson 0:3ab1d2d14eb3 623 #if defined AMX_INIT
tylerwilson 0:3ab1d2d14eb3 624
tylerwilson 0:3ab1d2d14eb3 625 static int VerifyPcode(AMX *amx)
tylerwilson 0:3ab1d2d14eb3 626 {
tylerwilson 0:3ab1d2d14eb3 627 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 628 cell op,cip,tgt,opmask;
tylerwilson 0:3ab1d2d14eb3 629 int sysreq_flg,max_opcode;
tylerwilson 0:3ab1d2d14eb3 630 int datasize,stacksize;
tylerwilson 0:3ab1d2d14eb3 631 const cell *opcode_list;
tylerwilson 0:3ab1d2d14eb3 632 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 633 int opcode_count=0;
tylerwilson 0:3ab1d2d14eb3 634 int reloc_count=0;
tylerwilson 0:3ab1d2d14eb3 635 int jit_codesize=0;
tylerwilson 0:3ab1d2d14eb3 636 #endif
tylerwilson 0:3ab1d2d14eb3 637
tylerwilson 0:3ab1d2d14eb3 638 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 639 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 640 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 641 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 642 amx->flags|=AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 643 datasize=hdr->hea-hdr->dat;
tylerwilson 0:3ab1d2d14eb3 644 stacksize=hdr->stp-hdr->hea;
tylerwilson 0:3ab1d2d14eb3 645
tylerwilson 0:3ab1d2d14eb3 646 #if defined AMX_ASM && defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 647 if ((amx->flags & AMX_FLAG_JITC)!=0)
tylerwilson 0:3ab1d2d14eb3 648 jit_codesize=amx_jit_list(amx,&opcode_list,&max_opcode);
tylerwilson 0:3ab1d2d14eb3 649 else
tylerwilson 0:3ab1d2d14eb3 650 amx_exec_list(amx,&opcode_list,&max_opcode);
tylerwilson 0:3ab1d2d14eb3 651 #elif defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 652 jit_codesize=amx_jit_list(amx,&opcode_list,&max_opcode);
tylerwilson 0:3ab1d2d14eb3 653 #else
tylerwilson 0:3ab1d2d14eb3 654 amx_exec_list(amx,&opcode_list,&max_opcode);
tylerwilson 0:3ab1d2d14eb3 655 #endif
tylerwilson 0:3ab1d2d14eb3 656 #if defined AMX_TOKENTHREADING
tylerwilson 0:3ab1d2d14eb3 657 opcode_list=NULL; /* avoid token translation if token threading is in effect */
tylerwilson 0:3ab1d2d14eb3 658 #endif
tylerwilson 0:3ab1d2d14eb3 659 #if defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 660 opmask= ~0;
tylerwilson 0:3ab1d2d14eb3 661 #else
tylerwilson 0:3ab1d2d14eb3 662 opmask=(1 << sizeof(cell)*4)-1;
tylerwilson 0:3ab1d2d14eb3 663 #endif
tylerwilson 0:3ab1d2d14eb3 664
tylerwilson 0:3ab1d2d14eb3 665 /* sanity checks */
tylerwilson 0:3ab1d2d14eb3 666 assert_static(OP_XCHG==21);
tylerwilson 0:3ab1d2d14eb3 667 assert_static(OP_SMUL==42);
tylerwilson 0:3ab1d2d14eb3 668 assert_static(OP_MOVS==64);
tylerwilson 0:3ab1d2d14eb3 669 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 670 assert_static(OP_LIDX==81);
tylerwilson 0:3ab1d2d14eb3 671 assert_static(OP_ZERO_PRI==102);
tylerwilson 0:3ab1d2d14eb3 672 assert_static(OP_LOAD2==120);
tylerwilson 0:3ab1d2d14eb3 673 #endif
tylerwilson 0:3ab1d2d14eb3 674 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 675 assert_static(OP_LOAD_P_PRI==124);
tylerwilson 0:3ab1d2d14eb3 676 assert_static(OP_ALIGN_P_PRI==141);
tylerwilson 0:3ab1d2d14eb3 677 assert_static(OP_BOUNDS_P==174);
tylerwilson 0:3ab1d2d14eb3 678 #endif
tylerwilson 0:3ab1d2d14eb3 679
tylerwilson 0:3ab1d2d14eb3 680 sysreq_flg=0;
tylerwilson 0:3ab1d2d14eb3 681 if (opcode_list!=NULL) {
tylerwilson 0:3ab1d2d14eb3 682 if (amx->sysreq_d==opcode_list[OP_SYSREQ_D])
tylerwilson 0:3ab1d2d14eb3 683 sysreq_flg=0x01;
tylerwilson 0:3ab1d2d14eb3 684 else if (amx->sysreq_d==opcode_list[OP_SYSREQ_ND])
tylerwilson 0:3ab1d2d14eb3 685 sysreq_flg=0x02;
tylerwilson 0:3ab1d2d14eb3 686 } else {
tylerwilson 0:3ab1d2d14eb3 687 if (amx->sysreq_d==OP_SYSREQ_D)
tylerwilson 0:3ab1d2d14eb3 688 sysreq_flg=0x01;
tylerwilson 0:3ab1d2d14eb3 689 else if (amx->sysreq_d==OP_SYSREQ_ND)
tylerwilson 0:3ab1d2d14eb3 690 sysreq_flg=0x02;
tylerwilson 0:3ab1d2d14eb3 691 } /* if */
tylerwilson 0:3ab1d2d14eb3 692 amx->sysreq_d=0; /* preset */
tylerwilson 0:3ab1d2d14eb3 693
tylerwilson 0:3ab1d2d14eb3 694 /* start browsing code */
tylerwilson 0:3ab1d2d14eb3 695 assert(amx->code!=NULL); /* should already have been set in amx_Init() */
tylerwilson 0:3ab1d2d14eb3 696 for (cip=0; cip<amx->codesize; ) {
tylerwilson 0:3ab1d2d14eb3 697 op=*(cell *)(amx->code+(int)cip);
tylerwilson 0:3ab1d2d14eb3 698 if ((op & opmask)>=max_opcode) {
tylerwilson 0:3ab1d2d14eb3 699 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 700 return AMX_ERR_INVINSTR;
tylerwilson 0:3ab1d2d14eb3 701 } /* if */
tylerwilson 0:3ab1d2d14eb3 702 /* relocate opcode (only works if the size of an opcode is at least
tylerwilson 0:3ab1d2d14eb3 703 * as big as the size of a pointer (jump address); so basically we
tylerwilson 0:3ab1d2d14eb3 704 * rely on the opcode and a pointer being 32-bit
tylerwilson 0:3ab1d2d14eb3 705 */
tylerwilson 0:3ab1d2d14eb3 706 if (opcode_list!=NULL) {
tylerwilson 0:3ab1d2d14eb3 707 /* verify that opcode_list[op]!=NULL, if it is, this instruction
tylerwilson 0:3ab1d2d14eb3 708 * is unsupported
tylerwilson 0:3ab1d2d14eb3 709 */
tylerwilson 0:3ab1d2d14eb3 710 if (opcode_list[op & opmask]==0) {
tylerwilson 0:3ab1d2d14eb3 711 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 712 return AMX_ERR_INVINSTR;
tylerwilson 0:3ab1d2d14eb3 713 } /* if */
tylerwilson 0:3ab1d2d14eb3 714 *(cell *)(amx->code+(int)cip)=opcode_list[op & opmask];
tylerwilson 0:3ab1d2d14eb3 715 } /* if */
tylerwilson 0:3ab1d2d14eb3 716 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 717 opcode_count++;
tylerwilson 0:3ab1d2d14eb3 718 #endif
tylerwilson 0:3ab1d2d14eb3 719 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 720 switch (op & opmask) {
tylerwilson 0:3ab1d2d14eb3 721 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 722 case OP_PUSHM_C: /* instructions with variable number of parameters */
tylerwilson 0:3ab1d2d14eb3 723 case OP_PUSHM:
tylerwilson 0:3ab1d2d14eb3 724 case OP_PUSHM_S:
tylerwilson 0:3ab1d2d14eb3 725 case OP_PUSHM_ADR:
tylerwilson 0:3ab1d2d14eb3 726 case OP_PUSHRM_C:
tylerwilson 0:3ab1d2d14eb3 727 case OP_PUSHRM_S:
tylerwilson 0:3ab1d2d14eb3 728 case OP_PUSHRM_ADR:
tylerwilson 0:3ab1d2d14eb3 729 tgt=*(cell*)(amx->code+(int)cip); /* get count */
tylerwilson 0:3ab1d2d14eb3 730 cip+=sizeof(cell)*(tgt+1);
tylerwilson 0:3ab1d2d14eb3 731 break;
tylerwilson 0:3ab1d2d14eb3 732
tylerwilson 0:3ab1d2d14eb3 733 case OP_LOAD2:
tylerwilson 0:3ab1d2d14eb3 734 tgt=*(cell*)(amx->code+(int)cip); /* verify both addresses */
tylerwilson 0:3ab1d2d14eb3 735 if (tgt<0 || tgt>=datasize) {
tylerwilson 0:3ab1d2d14eb3 736 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 737 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 738 } /* if */
tylerwilson 0:3ab1d2d14eb3 739 tgt=*(cell*)(amx->code+(int)cip+(int)sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 740 if (tgt<0 || tgt>=datasize) {
tylerwilson 0:3ab1d2d14eb3 741 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 742 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 743 } /* if */
tylerwilson 0:3ab1d2d14eb3 744 cip+=sizeof(cell)*2;
tylerwilson 0:3ab1d2d14eb3 745 break;
tylerwilson 0:3ab1d2d14eb3 746
tylerwilson 0:3ab1d2d14eb3 747 case OP_LOAD2_S:
tylerwilson 0:3ab1d2d14eb3 748 tgt=*(cell*)(amx->code+(int)cip); /* verify both addresses */
tylerwilson 0:3ab1d2d14eb3 749 if (tgt<-stacksize || tgt>stacksize) {
tylerwilson 0:3ab1d2d14eb3 750 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 751 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 752 } /* if */
tylerwilson 0:3ab1d2d14eb3 753 tgt=*(cell*)(amx->code+(int)cip+(int)sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 754 if (tgt<-stacksize || tgt>stacksize) {
tylerwilson 0:3ab1d2d14eb3 755 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 756 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 757 } /* if */
tylerwilson 0:3ab1d2d14eb3 758 cip+=sizeof(cell)*2;
tylerwilson 0:3ab1d2d14eb3 759 break;
tylerwilson 0:3ab1d2d14eb3 760
tylerwilson 0:3ab1d2d14eb3 761 case OP_CONST:
tylerwilson 0:3ab1d2d14eb3 762 tgt=*(cell*)(amx->code+(int)cip); /* verify address */
tylerwilson 0:3ab1d2d14eb3 763 if (tgt<0 || tgt>=datasize) {
tylerwilson 0:3ab1d2d14eb3 764 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 765 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 766 } /* if */
tylerwilson 0:3ab1d2d14eb3 767 cip+=sizeof(cell)*2;
tylerwilson 0:3ab1d2d14eb3 768 break;
tylerwilson 0:3ab1d2d14eb3 769
tylerwilson 0:3ab1d2d14eb3 770 case OP_CONST_S:
tylerwilson 0:3ab1d2d14eb3 771 tgt=*(cell*)(amx->code+(int)cip); /* verify both addresses */
tylerwilson 0:3ab1d2d14eb3 772 if (tgt<-stacksize || tgt>stacksize) {
tylerwilson 0:3ab1d2d14eb3 773 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 774 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 775 } /* if */
tylerwilson 0:3ab1d2d14eb3 776 cip+=sizeof(cell)*2;
tylerwilson 0:3ab1d2d14eb3 777 break;
tylerwilson 0:3ab1d2d14eb3 778 #endif /* !defined AMX_NO_MACRO_INSTR */
tylerwilson 0:3ab1d2d14eb3 779
tylerwilson 0:3ab1d2d14eb3 780 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 781 case OP_LODB_P_I: /* instructions with 1 parameter packed inside the same cell */
tylerwilson 0:3ab1d2d14eb3 782 case OP_CONST_P_PRI:
tylerwilson 0:3ab1d2d14eb3 783 case OP_CONST_P_ALT:
tylerwilson 0:3ab1d2d14eb3 784 case OP_ADDR_P_PRI:
tylerwilson 0:3ab1d2d14eb3 785 case OP_ADDR_P_ALT:
tylerwilson 0:3ab1d2d14eb3 786 case OP_STRB_P_I:
tylerwilson 0:3ab1d2d14eb3 787 case OP_LIDX_P_B:
tylerwilson 0:3ab1d2d14eb3 788 case OP_IDXADDR_P_B:
tylerwilson 0:3ab1d2d14eb3 789 case OP_ALIGN_P_PRI:
tylerwilson 0:3ab1d2d14eb3 790 case OP_PUSH_P_C:
tylerwilson 0:3ab1d2d14eb3 791 case OP_PUSH_P:
tylerwilson 0:3ab1d2d14eb3 792 case OP_PUSH_P_S:
tylerwilson 0:3ab1d2d14eb3 793 case OP_PUSH_P_ADR:
tylerwilson 0:3ab1d2d14eb3 794 case OP_PUSHR_P_C:
tylerwilson 0:3ab1d2d14eb3 795 case OP_PUSHR_P_S:
tylerwilson 0:3ab1d2d14eb3 796 case OP_PUSHR_P_ADR:
tylerwilson 0:3ab1d2d14eb3 797 case OP_STACK_P:
tylerwilson 0:3ab1d2d14eb3 798 case OP_HEAP_P:
tylerwilson 0:3ab1d2d14eb3 799 case OP_SHL_P_C_PRI:
tylerwilson 0:3ab1d2d14eb3 800 case OP_SHL_P_C_ALT:
tylerwilson 0:3ab1d2d14eb3 801 case OP_ADD_P_C:
tylerwilson 0:3ab1d2d14eb3 802 case OP_SMUL_P_C:
tylerwilson 0:3ab1d2d14eb3 803 case OP_ZERO_P:
tylerwilson 0:3ab1d2d14eb3 804 case OP_ZERO_P_S:
tylerwilson 0:3ab1d2d14eb3 805 case OP_EQ_P_C_PRI:
tylerwilson 0:3ab1d2d14eb3 806 case OP_EQ_P_C_ALT:
tylerwilson 0:3ab1d2d14eb3 807 case OP_MOVS_P:
tylerwilson 0:3ab1d2d14eb3 808 case OP_CMPS_P:
tylerwilson 0:3ab1d2d14eb3 809 case OP_FILL_P:
tylerwilson 0:3ab1d2d14eb3 810 case OP_HALT_P:
tylerwilson 0:3ab1d2d14eb3 811 case OP_BOUNDS_P:
tylerwilson 0:3ab1d2d14eb3 812 break;
tylerwilson 0:3ab1d2d14eb3 813
tylerwilson 0:3ab1d2d14eb3 814 case OP_LOAD_P_PRI: /* data instructions with 1 parameter packed inside the same cell */
tylerwilson 0:3ab1d2d14eb3 815 case OP_LOAD_P_ALT:
tylerwilson 0:3ab1d2d14eb3 816 case OP_STOR_P:
tylerwilson 0:3ab1d2d14eb3 817 case OP_INC_P:
tylerwilson 0:3ab1d2d14eb3 818 case OP_DEC_P:
tylerwilson 0:3ab1d2d14eb3 819 GETPARAM_P(tgt,op); /* verify address */
tylerwilson 0:3ab1d2d14eb3 820 if (tgt<0 || tgt>=datasize) {
tylerwilson 0:3ab1d2d14eb3 821 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 822 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 823 } /* if */
tylerwilson 0:3ab1d2d14eb3 824 break;
tylerwilson 0:3ab1d2d14eb3 825
tylerwilson 0:3ab1d2d14eb3 826 case OP_LOAD_P_S_PRI: /* stack instructions with 1 parameter packed inside the same cell */
tylerwilson 0:3ab1d2d14eb3 827 case OP_LOAD_P_S_ALT:
tylerwilson 0:3ab1d2d14eb3 828 case OP_LREF_P_S_PRI:
tylerwilson 0:3ab1d2d14eb3 829 case OP_LREF_P_S_ALT:
tylerwilson 0:3ab1d2d14eb3 830 case OP_STOR_P_S:
tylerwilson 0:3ab1d2d14eb3 831 case OP_SREF_P_S:
tylerwilson 0:3ab1d2d14eb3 832 case OP_INC_P_S:
tylerwilson 0:3ab1d2d14eb3 833 case OP_DEC_P_S:
tylerwilson 0:3ab1d2d14eb3 834 GETPARAM_P(tgt,op); /* verify address */
tylerwilson 0:3ab1d2d14eb3 835 if (tgt<-stacksize || tgt>stacksize) {
tylerwilson 0:3ab1d2d14eb3 836 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 837 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 838 } /* if */
tylerwilson 0:3ab1d2d14eb3 839 break;
tylerwilson 0:3ab1d2d14eb3 840
tylerwilson 0:3ab1d2d14eb3 841 case OP_PUSHM_P_C: /* instructions with variable number of parameters */
tylerwilson 0:3ab1d2d14eb3 842 case OP_PUSHM_P:
tylerwilson 0:3ab1d2d14eb3 843 case OP_PUSHM_P_S:
tylerwilson 0:3ab1d2d14eb3 844 case OP_PUSHM_P_ADR:
tylerwilson 0:3ab1d2d14eb3 845 case OP_PUSHRM_P_C:
tylerwilson 0:3ab1d2d14eb3 846 case OP_PUSHRM_P_S:
tylerwilson 0:3ab1d2d14eb3 847 case OP_PUSHRM_P_ADR:
tylerwilson 0:3ab1d2d14eb3 848 GETPARAM_P(tgt,op); /* verify address */
tylerwilson 0:3ab1d2d14eb3 849 cip+=sizeof(cell)*tgt;
tylerwilson 0:3ab1d2d14eb3 850 break;
tylerwilson 0:3ab1d2d14eb3 851 #endif /* !defined AMX_NO_PACKED_OPC */
tylerwilson 0:3ab1d2d14eb3 852
tylerwilson 0:3ab1d2d14eb3 853 case OP_LODB_I: /* instructions with 1 parameter (not packed) */
tylerwilson 0:3ab1d2d14eb3 854 case OP_CONST_PRI:
tylerwilson 0:3ab1d2d14eb3 855 case OP_CONST_ALT:
tylerwilson 0:3ab1d2d14eb3 856 case OP_ADDR_PRI:
tylerwilson 0:3ab1d2d14eb3 857 case OP_ADDR_ALT:
tylerwilson 0:3ab1d2d14eb3 858 case OP_STRB_I:
tylerwilson 0:3ab1d2d14eb3 859 case OP_ALIGN_PRI:
tylerwilson 0:3ab1d2d14eb3 860 case OP_LCTRL:
tylerwilson 0:3ab1d2d14eb3 861 case OP_SCTRL:
tylerwilson 0:3ab1d2d14eb3 862 case OP_PICK:
tylerwilson 0:3ab1d2d14eb3 863 case OP_STACK:
tylerwilson 0:3ab1d2d14eb3 864 case OP_HEAP:
tylerwilson 0:3ab1d2d14eb3 865 case OP_SHL_C_PRI:
tylerwilson 0:3ab1d2d14eb3 866 case OP_SHL_C_ALT:
tylerwilson 0:3ab1d2d14eb3 867 case OP_MOVS:
tylerwilson 0:3ab1d2d14eb3 868 case OP_CMPS:
tylerwilson 0:3ab1d2d14eb3 869 case OP_FILL:
tylerwilson 0:3ab1d2d14eb3 870 case OP_HALT:
tylerwilson 0:3ab1d2d14eb3 871 case OP_BOUNDS:
tylerwilson 0:3ab1d2d14eb3 872 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 873 case OP_LIDX_B:
tylerwilson 0:3ab1d2d14eb3 874 case OP_IDXADDR_B:
tylerwilson 0:3ab1d2d14eb3 875 case OP_PUSH_C:
tylerwilson 0:3ab1d2d14eb3 876 case OP_PUSH_ADR:
tylerwilson 0:3ab1d2d14eb3 877 case OP_PUSHR_C:
tylerwilson 0:3ab1d2d14eb3 878 case OP_PUSHR_ADR:
tylerwilson 0:3ab1d2d14eb3 879 case OP_ADD_C:
tylerwilson 0:3ab1d2d14eb3 880 case OP_SMUL_C:
tylerwilson 0:3ab1d2d14eb3 881 case OP_ZERO:
tylerwilson 0:3ab1d2d14eb3 882 case OP_ZERO_S:
tylerwilson 0:3ab1d2d14eb3 883 case OP_EQ_C_PRI:
tylerwilson 0:3ab1d2d14eb3 884 case OP_EQ_C_ALT:
tylerwilson 0:3ab1d2d14eb3 885 #endif
tylerwilson 0:3ab1d2d14eb3 886 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 887 break;
tylerwilson 0:3ab1d2d14eb3 888
tylerwilson 0:3ab1d2d14eb3 889 case OP_LOAD_PRI:
tylerwilson 0:3ab1d2d14eb3 890 case OP_LOAD_ALT:
tylerwilson 0:3ab1d2d14eb3 891 case OP_STOR:
tylerwilson 0:3ab1d2d14eb3 892 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 893 case OP_PUSH:
tylerwilson 0:3ab1d2d14eb3 894 case OP_INC:
tylerwilson 0:3ab1d2d14eb3 895 case OP_DEC:
tylerwilson 0:3ab1d2d14eb3 896 #endif
tylerwilson 0:3ab1d2d14eb3 897 tgt=*(cell*)(amx->code+(int)cip); /* verify address */
tylerwilson 0:3ab1d2d14eb3 898 if (tgt<0 || tgt>=datasize) {
tylerwilson 0:3ab1d2d14eb3 899 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 900 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 901 } /* if */
tylerwilson 0:3ab1d2d14eb3 902 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 903 break;
tylerwilson 0:3ab1d2d14eb3 904
tylerwilson 0:3ab1d2d14eb3 905 case OP_LOAD_S_PRI:
tylerwilson 0:3ab1d2d14eb3 906 case OP_LOAD_S_ALT:
tylerwilson 0:3ab1d2d14eb3 907 case OP_LREF_S_PRI:
tylerwilson 0:3ab1d2d14eb3 908 case OP_LREF_S_ALT:
tylerwilson 0:3ab1d2d14eb3 909 case OP_STOR_S:
tylerwilson 0:3ab1d2d14eb3 910 case OP_SREF_S:
tylerwilson 0:3ab1d2d14eb3 911 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 912 case OP_PUSH_S:
tylerwilson 0:3ab1d2d14eb3 913 case OP_PUSHR_S:
tylerwilson 0:3ab1d2d14eb3 914 case OP_INC_S:
tylerwilson 0:3ab1d2d14eb3 915 case OP_DEC_S:
tylerwilson 0:3ab1d2d14eb3 916 #endif
tylerwilson 0:3ab1d2d14eb3 917 tgt=*(cell*)(amx->code+(int)cip); /* verify address */
tylerwilson 0:3ab1d2d14eb3 918 if (tgt<-stacksize || tgt>stacksize) {
tylerwilson 0:3ab1d2d14eb3 919 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 920 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 921 } /* if */
tylerwilson 0:3ab1d2d14eb3 922 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 923 break;
tylerwilson 0:3ab1d2d14eb3 924
tylerwilson 0:3ab1d2d14eb3 925 case OP_NOP: /* instructions without parameters */
tylerwilson 0:3ab1d2d14eb3 926 case OP_LOAD_I:
tylerwilson 0:3ab1d2d14eb3 927 case OP_STOR_I:
tylerwilson 0:3ab1d2d14eb3 928 case OP_XCHG:
tylerwilson 0:3ab1d2d14eb3 929 case OP_PUSH_PRI:
tylerwilson 0:3ab1d2d14eb3 930 case OP_PUSH_ALT:
tylerwilson 0:3ab1d2d14eb3 931 case OP_PUSHR_PRI:
tylerwilson 0:3ab1d2d14eb3 932 case OP_POP_PRI:
tylerwilson 0:3ab1d2d14eb3 933 case OP_POP_ALT:
tylerwilson 0:3ab1d2d14eb3 934 case OP_PROC:
tylerwilson 0:3ab1d2d14eb3 935 case OP_RET:
tylerwilson 0:3ab1d2d14eb3 936 case OP_RETN:
tylerwilson 0:3ab1d2d14eb3 937 case OP_SHL:
tylerwilson 0:3ab1d2d14eb3 938 case OP_SHR:
tylerwilson 0:3ab1d2d14eb3 939 case OP_SSHR:
tylerwilson 0:3ab1d2d14eb3 940 case OP_SMUL:
tylerwilson 0:3ab1d2d14eb3 941 case OP_SDIV:
tylerwilson 0:3ab1d2d14eb3 942 case OP_ADD:
tylerwilson 0:3ab1d2d14eb3 943 case OP_SUB:
tylerwilson 0:3ab1d2d14eb3 944 case OP_AND:
tylerwilson 0:3ab1d2d14eb3 945 case OP_OR:
tylerwilson 0:3ab1d2d14eb3 946 case OP_XOR:
tylerwilson 0:3ab1d2d14eb3 947 case OP_NOT:
tylerwilson 0:3ab1d2d14eb3 948 case OP_NEG:
tylerwilson 0:3ab1d2d14eb3 949 case OP_INVERT:
tylerwilson 0:3ab1d2d14eb3 950 case OP_EQ:
tylerwilson 0:3ab1d2d14eb3 951 case OP_NEQ:
tylerwilson 0:3ab1d2d14eb3 952 case OP_SLESS:
tylerwilson 0:3ab1d2d14eb3 953 case OP_SLEQ:
tylerwilson 0:3ab1d2d14eb3 954 case OP_SGRTR:
tylerwilson 0:3ab1d2d14eb3 955 case OP_SGEQ:
tylerwilson 0:3ab1d2d14eb3 956 case OP_INC_PRI:
tylerwilson 0:3ab1d2d14eb3 957 case OP_INC_ALT:
tylerwilson 0:3ab1d2d14eb3 958 case OP_INC_I:
tylerwilson 0:3ab1d2d14eb3 959 case OP_DEC_PRI:
tylerwilson 0:3ab1d2d14eb3 960 case OP_DEC_ALT:
tylerwilson 0:3ab1d2d14eb3 961 case OP_DEC_I:
tylerwilson 0:3ab1d2d14eb3 962 case OP_SWAP_PRI:
tylerwilson 0:3ab1d2d14eb3 963 case OP_SWAP_ALT:
tylerwilson 0:3ab1d2d14eb3 964 case OP_BREAK:
tylerwilson 0:3ab1d2d14eb3 965 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 966 case OP_LIDX:
tylerwilson 0:3ab1d2d14eb3 967 case OP_IDXADDR:
tylerwilson 0:3ab1d2d14eb3 968 case OP_SDIV_INV:
tylerwilson 0:3ab1d2d14eb3 969 case OP_SUB_INV:
tylerwilson 0:3ab1d2d14eb3 970 case OP_ZERO_PRI:
tylerwilson 0:3ab1d2d14eb3 971 case OP_ZERO_ALT:
tylerwilson 0:3ab1d2d14eb3 972 #endif
tylerwilson 0:3ab1d2d14eb3 973 break;
tylerwilson 0:3ab1d2d14eb3 974
tylerwilson 0:3ab1d2d14eb3 975 case OP_CALL: /* opcodes that need relocation (JIT only), or conversion to position-independent code */
tylerwilson 0:3ab1d2d14eb3 976 case OP_JUMP:
tylerwilson 0:3ab1d2d14eb3 977 case OP_JZER:
tylerwilson 0:3ab1d2d14eb3 978 case OP_JNZ:
tylerwilson 0:3ab1d2d14eb3 979 case OP_SWITCH:
tylerwilson 0:3ab1d2d14eb3 980 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 981 case OP_JEQ:
tylerwilson 0:3ab1d2d14eb3 982 case OP_JNEQ:
tylerwilson 0:3ab1d2d14eb3 983 case OP_JSLESS:
tylerwilson 0:3ab1d2d14eb3 984 case OP_JSLEQ:
tylerwilson 0:3ab1d2d14eb3 985 case OP_JSGRTR:
tylerwilson 0:3ab1d2d14eb3 986 case OP_JSGEQ:
tylerwilson 0:3ab1d2d14eb3 987 #endif
tylerwilson 0:3ab1d2d14eb3 988 tgt=*(cell*)(amx->code+(int)cip)+cip-sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 989 if (tgt<0 || tgt>amx->codesize) {
tylerwilson 0:3ab1d2d14eb3 990 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 991 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 992 } /* if */
tylerwilson 0:3ab1d2d14eb3 993 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 994 reloc_count++;
tylerwilson 0:3ab1d2d14eb3 995 RELOC_ABS(amx->code, cip); /* change to absolute physical address */
tylerwilson 0:3ab1d2d14eb3 996 #endif
tylerwilson 0:3ab1d2d14eb3 997 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 998 break;
tylerwilson 0:3ab1d2d14eb3 999
tylerwilson 0:3ab1d2d14eb3 1000 #if !defined AMX_NO_OVERLAY
tylerwilson 0:3ab1d2d14eb3 1001 /* overlay opcodes (overlays must be enabled) */
tylerwilson 0:3ab1d2d14eb3 1002 case OP_SWITCH_OVL:
tylerwilson 0:3ab1d2d14eb3 1003 assert(hdr->file_version>=10);
tylerwilson 0:3ab1d2d14eb3 1004 tgt=*(cell*)(amx->code+(int)cip)+cip-sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1005 if (tgt<0 || tgt>amx->codesize) {
tylerwilson 0:3ab1d2d14eb3 1006 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 1007 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 1008 } /* if */
tylerwilson 0:3ab1d2d14eb3 1009 /* drop through */
tylerwilson 0:3ab1d2d14eb3 1010 case OP_CALL_OVL:
tylerwilson 0:3ab1d2d14eb3 1011 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1012 /* drop through */
tylerwilson 0:3ab1d2d14eb3 1013 case OP_RETN_OVL:
tylerwilson 0:3ab1d2d14eb3 1014 assert(hdr->overlays!=0 && hdr->overlays!=hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1015 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 1016 if ((amx->flags & AMX_FLAG_JITC)!=0)
tylerwilson 0:3ab1d2d14eb3 1017 return AMX_ERR_OVERLAY; /* JIT does not support overlays */
tylerwilson 0:3ab1d2d14eb3 1018 #endif
tylerwilson 0:3ab1d2d14eb3 1019 if (amx->overlay==NULL)
tylerwilson 0:3ab1d2d14eb3 1020 return AMX_ERR_OVERLAY; /* no overlay callback */
tylerwilson 0:3ab1d2d14eb3 1021 break;
tylerwilson 0:3ab1d2d14eb3 1022 case OP_CASETBL_OVL: {
tylerwilson 0:3ab1d2d14eb3 1023 cell num;
tylerwilson 0:3ab1d2d14eb3 1024 DBGPARAM(num); /* number of records follows the opcode */
tylerwilson 0:3ab1d2d14eb3 1025 cip+=(2*num + 1)*sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1026 if (amx->overlay==NULL)
tylerwilson 0:3ab1d2d14eb3 1027 return AMX_ERR_OVERLAY; /* no overlay callback */
tylerwilson 0:3ab1d2d14eb3 1028 break;
tylerwilson 0:3ab1d2d14eb3 1029 } /* case */
tylerwilson 0:3ab1d2d14eb3 1030 #endif
tylerwilson 0:3ab1d2d14eb3 1031
tylerwilson 0:3ab1d2d14eb3 1032 case OP_SYSREQ:
tylerwilson 0:3ab1d2d14eb3 1033 cip+=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1034 sysreq_flg|=0x01; /* mark SYSREQ found */
tylerwilson 0:3ab1d2d14eb3 1035 break;
tylerwilson 0:3ab1d2d14eb3 1036 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 1037 case OP_SYSREQ_N:
tylerwilson 0:3ab1d2d14eb3 1038 cip+=sizeof(cell)*2;
tylerwilson 0:3ab1d2d14eb3 1039 sysreq_flg|=0x02; /* mark SYSREQ.N found */
tylerwilson 0:3ab1d2d14eb3 1040 break;
tylerwilson 0:3ab1d2d14eb3 1041 #endif
tylerwilson 0:3ab1d2d14eb3 1042
tylerwilson 0:3ab1d2d14eb3 1043 case OP_CASETBL: {
tylerwilson 0:3ab1d2d14eb3 1044 cell num,offs;
tylerwilson 0:3ab1d2d14eb3 1045 int i;
tylerwilson 0:3ab1d2d14eb3 1046 DBGPARAM(num); /* number of records follows the opcode */
tylerwilson 0:3ab1d2d14eb3 1047 for (i=0; i<=num; i++) {
tylerwilson 0:3ab1d2d14eb3 1048 offs=cip+2*i*sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1049 tgt=*(cell*)(amx->code+(int)offs)+offs-sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1050 if (tgt<0 || tgt>amx->codesize) {
tylerwilson 0:3ab1d2d14eb3 1051 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 1052 return AMX_ERR_BOUNDS;
tylerwilson 0:3ab1d2d14eb3 1053 } /* if */
tylerwilson 0:3ab1d2d14eb3 1054 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 1055 RELOC_ABS(amx->code, cip+2*i*sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 1056 reloc_count++;
tylerwilson 0:3ab1d2d14eb3 1057 #endif
tylerwilson 0:3ab1d2d14eb3 1058 } /* for */
tylerwilson 0:3ab1d2d14eb3 1059 cip+=(2*num + 1)*sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1060 break;
tylerwilson 0:3ab1d2d14eb3 1061 } /* case */
tylerwilson 0:3ab1d2d14eb3 1062
tylerwilson 0:3ab1d2d14eb3 1063 default:
tylerwilson 0:3ab1d2d14eb3 1064 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 1065 return AMX_ERR_INVINSTR;
tylerwilson 0:3ab1d2d14eb3 1066 } /* switch */
tylerwilson 0:3ab1d2d14eb3 1067 } /* for */
tylerwilson 0:3ab1d2d14eb3 1068
tylerwilson 0:3ab1d2d14eb3 1069 #if !defined AMX_DONT_RELOCATE
tylerwilson 0:3ab1d2d14eb3 1070 /* only either type of system request opcode should be found (otherwise,
tylerwilson 0:3ab1d2d14eb3 1071 * we probably have a non-conforming compiler
tylerwilson 0:3ab1d2d14eb3 1072 */
tylerwilson 0:3ab1d2d14eb3 1073 if ((sysreq_flg==0x01 || sysreq_flg==0x02) && (amx->flags & AMX_FLAG_JITC)==0) {
tylerwilson 0:3ab1d2d14eb3 1074 /* to use direct system requests, a function pointer must fit in a cell;
tylerwilson 0:3ab1d2d14eb3 1075 * because the native function's address will be stored as the parameter
tylerwilson 0:3ab1d2d14eb3 1076 * of SYSREQ.(N)D
tylerwilson 0:3ab1d2d14eb3 1077 */
tylerwilson 0:3ab1d2d14eb3 1078 if (sizeof(AMX_NATIVE)<=sizeof(cell)) {
tylerwilson 0:3ab1d2d14eb3 1079 if (opcode_list!=NULL)
tylerwilson 0:3ab1d2d14eb3 1080 amx->sysreq_d=(sysreq_flg==0x01) ? opcode_list[OP_SYSREQ_D] : opcode_list[OP_SYSREQ_ND];
tylerwilson 0:3ab1d2d14eb3 1081 else
tylerwilson 0:3ab1d2d14eb3 1082 amx->sysreq_d=(sysreq_flg==0x01) ? OP_SYSREQ_D : OP_SYSREQ_ND;
tylerwilson 0:3ab1d2d14eb3 1083 } /* if */
tylerwilson 0:3ab1d2d14eb3 1084 } /* if */
tylerwilson 0:3ab1d2d14eb3 1085 #endif
tylerwilson 0:3ab1d2d14eb3 1086
tylerwilson 0:3ab1d2d14eb3 1087 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 1088 /* adjust the code size to mean: estimated code size of the native code
tylerwilson 0:3ab1d2d14eb3 1089 * (instead of the size of the P-code)
tylerwilson 0:3ab1d2d14eb3 1090 */
tylerwilson 0:3ab1d2d14eb3 1091 amx->codesize=jit_codesize*opcode_count + hdr->cod + (hdr->stp - hdr->dat);
tylerwilson 0:3ab1d2d14eb3 1092 amx->reloc_size=2*sizeof(cell)*reloc_count;
tylerwilson 0:3ab1d2d14eb3 1093 #endif
tylerwilson 0:3ab1d2d14eb3 1094
tylerwilson 0:3ab1d2d14eb3 1095 amx->flags &= ~AMX_FLAG_VERIFY;
tylerwilson 0:3ab1d2d14eb3 1096 amx->flags |= AMX_FLAG_INIT;
tylerwilson 0:3ab1d2d14eb3 1097 if (sysreq_flg & 0x02)
tylerwilson 0:3ab1d2d14eb3 1098 amx->flags |= AMX_FLAG_SYSREQN;
tylerwilson 0:3ab1d2d14eb3 1099
tylerwilson 0:3ab1d2d14eb3 1100 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1101 }
tylerwilson 0:3ab1d2d14eb3 1102
tylerwilson 0:3ab1d2d14eb3 1103 /* definitions used for amx_Init() and amx_Cleanup() */
tylerwilson 0:3ab1d2d14eb3 1104 #if (defined _Windows || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 1105 typedef int AMXEXPORT (AMXAPI _FAR *AMX_ENTRY)(AMX _FAR *amx);
tylerwilson 0:3ab1d2d14eb3 1106 #endif
tylerwilson 0:3ab1d2d14eb3 1107
tylerwilson 0:3ab1d2d14eb3 1108 int AMXAPI amx_Init(AMX *amx,void *program)
tylerwilson 0:3ab1d2d14eb3 1109 {
tylerwilson 0:3ab1d2d14eb3 1110 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1111 int err;
tylerwilson 0:3ab1d2d14eb3 1112 uint16_t *namelength;
tylerwilson 0:3ab1d2d14eb3 1113 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 1114 #if (defined _Windows || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 1115 #if defined _Windows
tylerwilson 0:3ab1d2d14eb3 1116 char libname[sNAMEMAX+8]; /* +1 for '\0', +3 for 'amx' prefix, +4 for extension */
tylerwilson 0:3ab1d2d14eb3 1117 HINSTANCE hlib;
tylerwilson 0:3ab1d2d14eb3 1118 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1119 char libname[_MAX_PATH];
tylerwilson 0:3ab1d2d14eb3 1120 char *root;
tylerwilson 0:3ab1d2d14eb3 1121 void *hlib;
tylerwilson 0:3ab1d2d14eb3 1122 #if !defined AMX_LIBPATH
tylerwilson 0:3ab1d2d14eb3 1123 #define AMX_LIBPATH "AMXLIB"
tylerwilson 0:3ab1d2d14eb3 1124 #endif
tylerwilson 0:3ab1d2d14eb3 1125 #endif
tylerwilson 0:3ab1d2d14eb3 1126 int numlibraries;
tylerwilson 0:3ab1d2d14eb3 1127 AMX_FUNCSTUB *lib;
tylerwilson 0:3ab1d2d14eb3 1128 AMX_ENTRY libinit;
tylerwilson 0:3ab1d2d14eb3 1129 #endif
tylerwilson 0:3ab1d2d14eb3 1130
tylerwilson 0:3ab1d2d14eb3 1131 if ((amx->flags & AMX_FLAG_INIT)!=0)
tylerwilson 0:3ab1d2d14eb3 1132 return AMX_ERR_INIT; /* already initialized (may not do so twice) */
tylerwilson 0:3ab1d2d14eb3 1133
tylerwilson 0:3ab1d2d14eb3 1134 hdr=(AMX_HEADER *)program;
tylerwilson 0:3ab1d2d14eb3 1135 /* the header is in Little Endian, on a Big Endian machine, swap all
tylerwilson 0:3ab1d2d14eb3 1136 * multi-byte words
tylerwilson 0:3ab1d2d14eb3 1137 */
tylerwilson 0:3ab1d2d14eb3 1138 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 1139 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 1140 amx_Align32((uint32_t*)&hdr->size);
tylerwilson 0:3ab1d2d14eb3 1141 amx_Align16(&hdr->magic);
tylerwilson 0:3ab1d2d14eb3 1142 amx_Align16((uint16_t*)&hdr->flags);
tylerwilson 0:3ab1d2d14eb3 1143 amx_Align16((uint16_t*)&hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1144 amx_Align32((uint32_t*)&hdr->cod);
tylerwilson 0:3ab1d2d14eb3 1145 amx_Align32((uint32_t*)&hdr->dat);
tylerwilson 0:3ab1d2d14eb3 1146 amx_Align32((uint32_t*)&hdr->hea);
tylerwilson 0:3ab1d2d14eb3 1147 amx_Align32((uint32_t*)&hdr->stp);
tylerwilson 0:3ab1d2d14eb3 1148 amx_Align32((uint32_t*)&hdr->cip);
tylerwilson 0:3ab1d2d14eb3 1149 amx_Align32((uint32_t*)&hdr->publics);
tylerwilson 0:3ab1d2d14eb3 1150 amx_Align32((uint32_t*)&hdr->natives);
tylerwilson 0:3ab1d2d14eb3 1151 amx_Align32((uint32_t*)&hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 1152 amx_Align32((uint32_t*)&hdr->pubvars);
tylerwilson 0:3ab1d2d14eb3 1153 amx_Align32((uint32_t*)&hdr->tags);
tylerwilson 0:3ab1d2d14eb3 1154 if (hdr->file_version>=10)
tylerwilson 0:3ab1d2d14eb3 1155 amx_Align32((uint32_t*)&hdr->overlays);
tylerwilson 0:3ab1d2d14eb3 1156 #endif
tylerwilson 0:3ab1d2d14eb3 1157
tylerwilson 0:3ab1d2d14eb3 1158 if (hdr->magic!=AMX_MAGIC)
tylerwilson 0:3ab1d2d14eb3 1159 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1160 if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_version<MIN_FILE_VERSION)
tylerwilson 0:3ab1d2d14eb3 1161 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 1162 if (hdr->defsize!=sizeof(AMX_FUNCSTUB))
tylerwilson 0:3ab1d2d14eb3 1163 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1164 /* check the maximum name length in the separate name table */
tylerwilson 0:3ab1d2d14eb3 1165 amx_Align32((uint32_t*)&hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1166 namelength=(uint16_t*)((unsigned char*)program + (unsigned)hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1167 amx_Align16(namelength);
tylerwilson 0:3ab1d2d14eb3 1168 if (*namelength>sNAMEMAX)
tylerwilson 0:3ab1d2d14eb3 1169 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1170 if (hdr->stp<=0)
tylerwilson 0:3ab1d2d14eb3 1171 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1172 assert(hdr->hea == hdr->size);
tylerwilson 0:3ab1d2d14eb3 1173 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 1174 if ((hdr->flags & AMX_FLAG_COMPACT)==0) {
tylerwilson 0:3ab1d2d14eb3 1175 ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod);
tylerwilson 0:3ab1d2d14eb3 1176 while (code<(ucell *)((unsigned char *)program+(int)hdr->hea))
tylerwilson 0:3ab1d2d14eb3 1177 swapcell(code++);
tylerwilson 0:3ab1d2d14eb3 1178 } /* if */
tylerwilson 0:3ab1d2d14eb3 1179 #endif
tylerwilson 0:3ab1d2d14eb3 1180
tylerwilson 0:3ab1d2d14eb3 1181 amx->base=(unsigned char *)program;
tylerwilson 0:3ab1d2d14eb3 1182
tylerwilson 0:3ab1d2d14eb3 1183 /* set initial values */
tylerwilson 0:3ab1d2d14eb3 1184 amx->hlw=hdr->hea - hdr->dat; /* stack and heap relative to data segment */
tylerwilson 0:3ab1d2d14eb3 1185 amx->stp=hdr->stp - hdr->dat - sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1186 amx->hea=amx->hlw;
tylerwilson 0:3ab1d2d14eb3 1187 amx->stk=amx->stp;
tylerwilson 0:3ab1d2d14eb3 1188 #if defined AMX_DEFCALLBACK
tylerwilson 0:3ab1d2d14eb3 1189 if (amx->callback==NULL)
tylerwilson 0:3ab1d2d14eb3 1190 amx->callback=amx_Callback;
tylerwilson 0:3ab1d2d14eb3 1191 #endif
tylerwilson 0:3ab1d2d14eb3 1192
tylerwilson 0:3ab1d2d14eb3 1193 /* when running P-code from ROM (with the header with the native function
tylerwilson 0:3ab1d2d14eb3 1194 * table in RAM), the "code" field must be set to a non-NULL value on
tylerwilson 0:3ab1d2d14eb3 1195 * initialization, before calling amx_Init(); in an overlay scheme, the
tylerwilson 0:3ab1d2d14eb3 1196 * code field is modified dynamically by the overlay callback
tylerwilson 0:3ab1d2d14eb3 1197 */
tylerwilson 0:3ab1d2d14eb3 1198 if (amx->code==NULL)
tylerwilson 0:3ab1d2d14eb3 1199 amx->code=amx->base+(int)hdr->cod;
tylerwilson 0:3ab1d2d14eb3 1200 if (amx->codesize==0)
tylerwilson 0:3ab1d2d14eb3 1201 amx->codesize=hdr->dat-hdr->cod;
tylerwilson 0:3ab1d2d14eb3 1202
tylerwilson 0:3ab1d2d14eb3 1203 /* to split the data segment off the code segment, the "data" field must
tylerwilson 0:3ab1d2d14eb3 1204 * be set to a non-NULL value on initialization, before calling amx_Init();
tylerwilson 0:3ab1d2d14eb3 1205 * you may also need to explicitly initialize the data section with the
tylerwilson 0:3ab1d2d14eb3 1206 * contents read from the AMX file
tylerwilson 0:3ab1d2d14eb3 1207 */
tylerwilson 0:3ab1d2d14eb3 1208 if (amx->data!=NULL) {
tylerwilson 0:3ab1d2d14eb3 1209 data=amx->data;
tylerwilson 0:3ab1d2d14eb3 1210 if ((amx->flags & AMX_FLAG_DSEG_INIT)==0 && amx->overlay==NULL)
tylerwilson 0:3ab1d2d14eb3 1211 memcpy(data,amx->base+(int)hdr->dat,(size_t)(hdr->hea-hdr->dat));
tylerwilson 0:3ab1d2d14eb3 1212 } else {
tylerwilson 0:3ab1d2d14eb3 1213 data=amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1214 } /* if */
tylerwilson 0:3ab1d2d14eb3 1215
tylerwilson 0:3ab1d2d14eb3 1216 /* Set a zero cell at the top of the stack, which functions
tylerwilson 0:3ab1d2d14eb3 1217 * as a sentinel for strings.
tylerwilson 0:3ab1d2d14eb3 1218 */
tylerwilson 0:3ab1d2d14eb3 1219 * (cell *)(data+(int)(hdr->stp-hdr->dat-sizeof(cell)))=0;
tylerwilson 0:3ab1d2d14eb3 1220
tylerwilson 0:3ab1d2d14eb3 1221 /* also align all addresses in the public function, public variable,
tylerwilson 0:3ab1d2d14eb3 1222 * public tag and native function tables --offsets into the name table
tylerwilson 0:3ab1d2d14eb3 1223 * (if present) must also be swapped.
tylerwilson 0:3ab1d2d14eb3 1224 */
tylerwilson 0:3ab1d2d14eb3 1225 #if BYTE_ORDER==BIG_ENDIAN
tylerwilson 0:3ab1d2d14eb3 1226 { /* local */
tylerwilson 0:3ab1d2d14eb3 1227 AMX_FUNCSTUB *fs;
tylerwilson 0:3ab1d2d14eb3 1228 int i,num;
tylerwilson 0:3ab1d2d14eb3 1229
tylerwilson 0:3ab1d2d14eb3 1230 fs=GETENTRY(hdr,natives,0);
tylerwilson 0:3ab1d2d14eb3 1231 num=NUMENTRIES(hdr,natives,libraries);
tylerwilson 0:3ab1d2d14eb3 1232 for (i=0; i<num; i++) {
tylerwilson 0:3ab1d2d14eb3 1233 amx_Align32(&fs->address); /* redundant, because it should be zero */
tylerwilson 0:3ab1d2d14eb3 1234 amx_Align32(&fs->nameofs);
tylerwilson 0:3ab1d2d14eb3 1235 fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1236 } /* for */
tylerwilson 0:3ab1d2d14eb3 1237
tylerwilson 0:3ab1d2d14eb3 1238 fs=GETENTRY(hdr,publics,0);
tylerwilson 0:3ab1d2d14eb3 1239 assert(hdr->publics<=hdr->natives);
tylerwilson 0:3ab1d2d14eb3 1240 num=NUMENTRIES(hdr,publics,natives);
tylerwilson 0:3ab1d2d14eb3 1241 for (i=0; i<num; i++) {
tylerwilson 0:3ab1d2d14eb3 1242 amx_Align32(&fs->address);
tylerwilson 0:3ab1d2d14eb3 1243 amx_Align32(&fs->nameofs);
tylerwilson 0:3ab1d2d14eb3 1244 fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1245 } /* for */
tylerwilson 0:3ab1d2d14eb3 1246
tylerwilson 0:3ab1d2d14eb3 1247 fs=GETENTRY(hdr,pubvars,0);
tylerwilson 0:3ab1d2d14eb3 1248 assert(hdr->pubvars<=hdr->tags);
tylerwilson 0:3ab1d2d14eb3 1249 num=NUMENTRIES(hdr,pubvars,tags);
tylerwilson 0:3ab1d2d14eb3 1250 for (i=0; i<num; i++) {
tylerwilson 0:3ab1d2d14eb3 1251 amx_Align32(&fs->address);
tylerwilson 0:3ab1d2d14eb3 1252 amx_Align32(&fs->nameofs);
tylerwilson 0:3ab1d2d14eb3 1253 fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1254 } /* for */
tylerwilson 0:3ab1d2d14eb3 1255
tylerwilson 0:3ab1d2d14eb3 1256 fs=GETENTRY(hdr,tags,0);
tylerwilson 0:3ab1d2d14eb3 1257 if (hdr->file_version<7) { /* file version 7 introduced the name table */
tylerwilson 0:3ab1d2d14eb3 1258 assert(hdr->tags<=hdr->cod);
tylerwilson 0:3ab1d2d14eb3 1259 num=NUMENTRIES(hdr,tags,cod);
tylerwilson 0:3ab1d2d14eb3 1260 } else {
tylerwilson 0:3ab1d2d14eb3 1261 assert(hdr->tags<=hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1262 num=NUMENTRIES(hdr,tags,nametable);
tylerwilson 0:3ab1d2d14eb3 1263 } /* if */
tylerwilson 0:3ab1d2d14eb3 1264 for (i=0; i<num; i++) {
tylerwilson 0:3ab1d2d14eb3 1265 amx_Align32(&fs->address);
tylerwilson 0:3ab1d2d14eb3 1266 amx_Align32(&fs->nameofs);
tylerwilson 0:3ab1d2d14eb3 1267 fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1268 } /* for */
tylerwilson 0:3ab1d2d14eb3 1269 } /* local */
tylerwilson 0:3ab1d2d14eb3 1270 #endif
tylerwilson 0:3ab1d2d14eb3 1271
tylerwilson 0:3ab1d2d14eb3 1272 /* verify P-code and relocate address in the case of the JIT */
tylerwilson 0:3ab1d2d14eb3 1273 if ((hdr->flags & AMX_FLAG_OVERLAY)==0) {
tylerwilson 0:3ab1d2d14eb3 1274 err=VerifyPcode(amx);
tylerwilson 0:3ab1d2d14eb3 1275 } else {
tylerwilson 0:3ab1d2d14eb3 1276 int i;
tylerwilson 0:3ab1d2d14eb3 1277 err=(amx->overlay==NULL) ? AMX_ERR_OVERLAY : AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1278 /* load every overlay on initialization and verify explicitly; we must
tylerwilson 0:3ab1d2d14eb3 1279 * do this to know whether to use new or old system requests
tylerwilson 0:3ab1d2d14eb3 1280 */
tylerwilson 0:3ab1d2d14eb3 1281 for (i=0; err==AMX_ERR_NONE && i<(int)((hdr->nametable - hdr->overlays)/sizeof(AMX_OVERLAYINFO)); i++) {
tylerwilson 0:3ab1d2d14eb3 1282 err=amx->overlay(amx, i);
tylerwilson 0:3ab1d2d14eb3 1283 if (err==AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 1284 err=VerifyPcode(amx);
tylerwilson 0:3ab1d2d14eb3 1285 } /* for */
tylerwilson 0:3ab1d2d14eb3 1286 } /* if */
tylerwilson 0:3ab1d2d14eb3 1287 if (err!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 1288 return err;
tylerwilson 0:3ab1d2d14eb3 1289
tylerwilson 0:3ab1d2d14eb3 1290 /* load any extension modules that the AMX refers to */
tylerwilson 0:3ab1d2d14eb3 1291 #if (defined _Windows || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 1292 { /* local */
tylerwilson 0:3ab1d2d14eb3 1293 int i;
tylerwilson 0:3ab1d2d14eb3 1294 #if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1295 root=getenv("AMXLIB");
tylerwilson 0:3ab1d2d14eb3 1296 #endif
tylerwilson 0:3ab1d2d14eb3 1297 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1298 numlibraries=NUMENTRIES(hdr,libraries,pubvars);
tylerwilson 0:3ab1d2d14eb3 1299 for (i=0; i<numlibraries; i++) {
tylerwilson 0:3ab1d2d14eb3 1300 lib=GETENTRY(hdr,libraries,i);
tylerwilson 0:3ab1d2d14eb3 1301 libname[0]='\0';
tylerwilson 0:3ab1d2d14eb3 1302 #if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1303 if (root!=NULL && *root!='\0') {
tylerwilson 0:3ab1d2d14eb3 1304 strcpy(libname,root);
tylerwilson 0:3ab1d2d14eb3 1305 if (libname[strlen(libname)-1]!='/')
tylerwilson 0:3ab1d2d14eb3 1306 strcat(libname,"/");
tylerwilson 0:3ab1d2d14eb3 1307 } /* if */
tylerwilson 0:3ab1d2d14eb3 1308 #endif
tylerwilson 0:3ab1d2d14eb3 1309 strcat(libname,"amx");
tylerwilson 0:3ab1d2d14eb3 1310 strcat(libname,GETENTRYNAME(hdr,lib));
tylerwilson 0:3ab1d2d14eb3 1311 #if defined _Windows
tylerwilson 0:3ab1d2d14eb3 1312 strcat(libname,".dll");
tylerwilson 0:3ab1d2d14eb3 1313 #if defined __WIN32__
tylerwilson 0:3ab1d2d14eb3 1314 hlib=LoadLibraryA(libname);
tylerwilson 0:3ab1d2d14eb3 1315 #else
tylerwilson 0:3ab1d2d14eb3 1316 hlib=LoadLibrary(libname);
tylerwilson 0:3ab1d2d14eb3 1317 if (hlib<=HINSTANCE_ERROR)
tylerwilson 0:3ab1d2d14eb3 1318 hlib=NULL;
tylerwilson 0:3ab1d2d14eb3 1319 #endif
tylerwilson 0:3ab1d2d14eb3 1320 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1321 strcat(libname,".so");
tylerwilson 0:3ab1d2d14eb3 1322 hlib=dlopen(libname,RTLD_NOW);
tylerwilson 0:3ab1d2d14eb3 1323 #endif
tylerwilson 0:3ab1d2d14eb3 1324 if (hlib!=NULL) {
tylerwilson 0:3ab1d2d14eb3 1325 /* a library that cannot be loaded or that does not have the required
tylerwilson 0:3ab1d2d14eb3 1326 * initialization function is simply ignored
tylerwilson 0:3ab1d2d14eb3 1327 */
tylerwilson 0:3ab1d2d14eb3 1328 char funcname[sNAMEMAX+9]; /* +1 for '\0', +4 for 'amx_', +4 for 'Init' */
tylerwilson 0:3ab1d2d14eb3 1329 strcpy(funcname,"amx_");
tylerwilson 0:3ab1d2d14eb3 1330 strcat(funcname,GETENTRYNAME(hdr,lib));
tylerwilson 0:3ab1d2d14eb3 1331 strcat(funcname,"Init");
tylerwilson 0:3ab1d2d14eb3 1332 #if defined _Windows
tylerwilson 0:3ab1d2d14eb3 1333 libinit=(AMX_ENTRY)GetProcAddress(hlib,funcname);
tylerwilson 0:3ab1d2d14eb3 1334 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1335 libinit=(AMX_ENTRY)dlsym(hlib,funcname);
tylerwilson 0:3ab1d2d14eb3 1336 #endif
tylerwilson 0:3ab1d2d14eb3 1337 if (libinit!=NULL)
tylerwilson 0:3ab1d2d14eb3 1338 libinit(amx);
tylerwilson 0:3ab1d2d14eb3 1339 } /* if */
tylerwilson 0:3ab1d2d14eb3 1340 lib->address=(ucell)hlib;
tylerwilson 0:3ab1d2d14eb3 1341 } /* for */
tylerwilson 0:3ab1d2d14eb3 1342 } /* local */
tylerwilson 0:3ab1d2d14eb3 1343 #endif
tylerwilson 0:3ab1d2d14eb3 1344
tylerwilson 0:3ab1d2d14eb3 1345 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1346 }
tylerwilson 0:3ab1d2d14eb3 1347
tylerwilson 0:3ab1d2d14eb3 1348 #if defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 1349
tylerwilson 0:3ab1d2d14eb3 1350 #define CODESIZE_JIT 8192 /* approximate size of the code for the JIT */
tylerwilson 0:3ab1d2d14eb3 1351
tylerwilson 0:3ab1d2d14eb3 1352 #if defined __WIN32__ /* this also applies to Win32 "console" applications */
tylerwilson 0:3ab1d2d14eb3 1353
tylerwilson 0:3ab1d2d14eb3 1354 #define ALIGN(addr) (addr)
tylerwilson 0:3ab1d2d14eb3 1355
tylerwilson 0:3ab1d2d14eb3 1356 #define PROT_READ 0x1 /* page can be read */
tylerwilson 0:3ab1d2d14eb3 1357 #define PROT_WRITE 0x2 /* page can be written */
tylerwilson 0:3ab1d2d14eb3 1358 #define PROT_EXEC 0x4 /* page can be executed */
tylerwilson 0:3ab1d2d14eb3 1359 #define PROT_NONE 0x0 /* page can not be accessed */
tylerwilson 0:3ab1d2d14eb3 1360
tylerwilson 0:3ab1d2d14eb3 1361 static int mprotect(void *addr, size_t len, int prot)
tylerwilson 0:3ab1d2d14eb3 1362 {
tylerwilson 0:3ab1d2d14eb3 1363 DWORD prev, p = 0;
tylerwilson 0:3ab1d2d14eb3 1364 if ((prot & PROT_WRITE)!=0)
tylerwilson 0:3ab1d2d14eb3 1365 p = PAGE_EXECUTE_READWRITE;
tylerwilson 0:3ab1d2d14eb3 1366 else
tylerwilson 0:3ab1d2d14eb3 1367 p |= PAGE_EXECUTE_READ;
tylerwilson 0:3ab1d2d14eb3 1368 return !VirtualProtect(addr, len, p, &prev);
tylerwilson 0:3ab1d2d14eb3 1369 }
tylerwilson 0:3ab1d2d14eb3 1370
tylerwilson 0:3ab1d2d14eb3 1371 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1372
tylerwilson 0:3ab1d2d14eb3 1373 /* Linux already has mprotect() */
tylerwilson 0:3ab1d2d14eb3 1374 #define ALIGN(addr) (char *)(((long)addr + sysconf(_SC_PAGESIZE)-1) & ~(sysconf(_SC_PAGESIZE)-1))
tylerwilson 0:3ab1d2d14eb3 1375
tylerwilson 0:3ab1d2d14eb3 1376 #else
tylerwilson 0:3ab1d2d14eb3 1377
tylerwilson 0:3ab1d2d14eb3 1378 // TODO: Add cases for Mac OS/X and other operating systems
tylerwilson 0:3ab1d2d14eb3 1379
tylerwilson 0:3ab1d2d14eb3 1380 /* DOS32 has no imposed limits on its segments */
tylerwilson 0:3ab1d2d14eb3 1381 #define ALIGN(addr) (addr)
tylerwilson 0:3ab1d2d14eb3 1382 #define mprotect(addr, len, prot) (0)
tylerwilson 0:3ab1d2d14eb3 1383
tylerwilson 0:3ab1d2d14eb3 1384 #endif /* #if defined __WIN32 __ */
tylerwilson 0:3ab1d2d14eb3 1385
tylerwilson 0:3ab1d2d14eb3 1386 int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code)
tylerwilson 0:3ab1d2d14eb3 1387 {
tylerwilson 0:3ab1d2d14eb3 1388 int res;
tylerwilson 0:3ab1d2d14eb3 1389 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1390
tylerwilson 0:3ab1d2d14eb3 1391 if ((amx->flags & AMX_FLAG_JITC)==0)
tylerwilson 0:3ab1d2d14eb3 1392 return AMX_ERR_INIT_JIT; /* flag not set, this AMX is not prepared for JIT */
tylerwilson 0:3ab1d2d14eb3 1393 if (hdr->file_version>MAX_FILE_VER_JIT)
tylerwilson 0:3ab1d2d14eb3 1394 return AMX_ERR_VERSION; /* JIT may not support the newest file version(s) */
tylerwilson 0:3ab1d2d14eb3 1395 /* the JIT does not support overlays, but this is already checked in VerifyPcode()
tylerwilson 0:3ab1d2d14eb3 1396 * the same goes for macro instructions: not supported in the JIT, but already
tylerwilson 0:3ab1d2d14eb3 1397 * checked in VerifyPcode()
tylerwilson 0:3ab1d2d14eb3 1398 */
tylerwilson 0:3ab1d2d14eb3 1399
tylerwilson 0:3ab1d2d14eb3 1400 /* Patching SYSREQ(.N) opcodes to SYSREQ.(N)D cannot work in the JIT, because
tylerwilson 0:3ab1d2d14eb3 1401 * the program would need to be re-JIT-compiled after patching a P-code
tylerwilson 0:3ab1d2d14eb3 1402 * instruction. If this field is not zero, something went wrong in
tylerwilson 0:3ab1d2d14eb3 1403 * VerifyPcode().
tylerwilson 0:3ab1d2d14eb3 1404 */
tylerwilson 0:3ab1d2d14eb3 1405 assert(amx->sysreq_d==0);
tylerwilson 0:3ab1d2d14eb3 1406
tylerwilson 0:3ab1d2d14eb3 1407 if (mprotect(ALIGN(amx_jit_compile), CODESIZE_JIT, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
tylerwilson 0:3ab1d2d14eb3 1408 return AMX_ERR_INIT_JIT;
tylerwilson 0:3ab1d2d14eb3 1409
tylerwilson 0:3ab1d2d14eb3 1410 /* copy the prefix */
tylerwilson 0:3ab1d2d14eb3 1411 memcpy(native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod);
tylerwilson 0:3ab1d2d14eb3 1412 hdr = native_code;
tylerwilson 0:3ab1d2d14eb3 1413
tylerwilson 0:3ab1d2d14eb3 1414 /* MP: added check for correct compilation */
tylerwilson 0:3ab1d2d14eb3 1415 if ((res = amx_jit_compile(amx->base, reloc_table, native_code)) == 0) {
tylerwilson 0:3ab1d2d14eb3 1416 /* update the required memory size (the previous value was a
tylerwilson 0:3ab1d2d14eb3 1417 * conservative estimate, now we know the exact size)
tylerwilson 0:3ab1d2d14eb3 1418 */
tylerwilson 0:3ab1d2d14eb3 1419 amx->codesize = (hdr->dat + hdr->stp + sizeof(cell)) & ~(sizeof(cell)-1);
tylerwilson 0:3ab1d2d14eb3 1420 /* The compiled code is relocatable, since only relative jumps are
tylerwilson 0:3ab1d2d14eb3 1421 * used for destinations within the generated code, and absolute
tylerwilson 0:3ab1d2d14eb3 1422 * addresses are only for jumps into the runtime, which is fixed
tylerwilson 0:3ab1d2d14eb3 1423 * in memory.
tylerwilson 0:3ab1d2d14eb3 1424 */
tylerwilson 0:3ab1d2d14eb3 1425 /* set the new pointers */
tylerwilson 0:3ab1d2d14eb3 1426 amx->base = (unsigned char*)native_code;
tylerwilson 0:3ab1d2d14eb3 1427 amx->code = amx->base + (int)hdr->cod;
tylerwilson 0:3ab1d2d14eb3 1428 amx->cip = hdr->cip;
tylerwilson 0:3ab1d2d14eb3 1429 } /* if */
tylerwilson 0:3ab1d2d14eb3 1430
tylerwilson 0:3ab1d2d14eb3 1431 return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT;
tylerwilson 0:3ab1d2d14eb3 1432 }
tylerwilson 0:3ab1d2d14eb3 1433
tylerwilson 0:3ab1d2d14eb3 1434 #else /* #if defined AMX_JIT */
tylerwilson 0:3ab1d2d14eb3 1435
tylerwilson 0:3ab1d2d14eb3 1436 int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table)
tylerwilson 0:3ab1d2d14eb3 1437 {
tylerwilson 0:3ab1d2d14eb3 1438 (void)amx;
tylerwilson 0:3ab1d2d14eb3 1439 (void)compiled_program;
tylerwilson 0:3ab1d2d14eb3 1440 (void)reloc_table;
tylerwilson 0:3ab1d2d14eb3 1441 return AMX_ERR_INIT_JIT;
tylerwilson 0:3ab1d2d14eb3 1442 }
tylerwilson 0:3ab1d2d14eb3 1443
tylerwilson 0:3ab1d2d14eb3 1444 #endif /* #if defined AMX_JIT */
tylerwilson 0:3ab1d2d14eb3 1445
tylerwilson 0:3ab1d2d14eb3 1446 #endif /* AMX_INIT */
tylerwilson 0:3ab1d2d14eb3 1447
tylerwilson 0:3ab1d2d14eb3 1448 #if defined AMX_CLEANUP
tylerwilson 0:3ab1d2d14eb3 1449 int AMXAPI amx_Cleanup(AMX *amx)
tylerwilson 0:3ab1d2d14eb3 1450 {
tylerwilson 0:3ab1d2d14eb3 1451 #if (defined _Windows || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 1452 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1453 int numlibraries,i;
tylerwilson 0:3ab1d2d14eb3 1454 AMX_FUNCSTUB *lib;
tylerwilson 0:3ab1d2d14eb3 1455 AMX_ENTRY libcleanup;
tylerwilson 0:3ab1d2d14eb3 1456 #endif
tylerwilson 0:3ab1d2d14eb3 1457
tylerwilson 0:3ab1d2d14eb3 1458 /* unload all extension modules */
tylerwilson 0:3ab1d2d14eb3 1459 #if (defined _Windows || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
tylerwilson 0:3ab1d2d14eb3 1460 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1461 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1462 numlibraries=NUMENTRIES(hdr,libraries,pubvars);
tylerwilson 0:3ab1d2d14eb3 1463 for (i=0; i<numlibraries; i++) {
tylerwilson 0:3ab1d2d14eb3 1464 lib=GETENTRY(hdr,libraries,i);
tylerwilson 0:3ab1d2d14eb3 1465 if (lib->address!=0) {
tylerwilson 0:3ab1d2d14eb3 1466 char funcname[sNAMEMAX+12]; /* +1 for '\0', +4 for 'amx_', +7 for 'Cleanup' */
tylerwilson 0:3ab1d2d14eb3 1467 strcpy(funcname,"amx_");
tylerwilson 0:3ab1d2d14eb3 1468 strcat(funcname,GETENTRYNAME(hdr,lib));
tylerwilson 0:3ab1d2d14eb3 1469 strcat(funcname,"Cleanup");
tylerwilson 0:3ab1d2d14eb3 1470 #if defined _Windows
tylerwilson 0:3ab1d2d14eb3 1471 libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname);
tylerwilson 0:3ab1d2d14eb3 1472 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1473 libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname);
tylerwilson 0:3ab1d2d14eb3 1474 #endif
tylerwilson 0:3ab1d2d14eb3 1475 if (libcleanup!=NULL)
tylerwilson 0:3ab1d2d14eb3 1476 libcleanup(amx);
tylerwilson 0:3ab1d2d14eb3 1477 #if defined _Windows
tylerwilson 0:3ab1d2d14eb3 1478 FreeLibrary((HINSTANCE)lib->address);
tylerwilson 0:3ab1d2d14eb3 1479 #elif defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__
tylerwilson 0:3ab1d2d14eb3 1480 dlclose((void*)lib->address);
tylerwilson 0:3ab1d2d14eb3 1481 #endif
tylerwilson 0:3ab1d2d14eb3 1482 } /* if */
tylerwilson 0:3ab1d2d14eb3 1483 } /* for */
tylerwilson 0:3ab1d2d14eb3 1484 #else
tylerwilson 0:3ab1d2d14eb3 1485 (void)amx;
tylerwilson 0:3ab1d2d14eb3 1486 #endif
tylerwilson 0:3ab1d2d14eb3 1487 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1488 }
tylerwilson 0:3ab1d2d14eb3 1489 #endif /* AMX_CLEANUP */
tylerwilson 0:3ab1d2d14eb3 1490
tylerwilson 0:3ab1d2d14eb3 1491 #if defined AMX_CLONE
tylerwilson 0:3ab1d2d14eb3 1492 int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data)
tylerwilson 0:3ab1d2d14eb3 1493 {
tylerwilson 0:3ab1d2d14eb3 1494 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1495 unsigned char _FAR *dataSource;
tylerwilson 0:3ab1d2d14eb3 1496
tylerwilson 0:3ab1d2d14eb3 1497 if (amxSource==NULL)
tylerwilson 0:3ab1d2d14eb3 1498 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1499 if (amxClone==NULL)
tylerwilson 0:3ab1d2d14eb3 1500 return AMX_ERR_PARAMS;
tylerwilson 0:3ab1d2d14eb3 1501 if ((amxSource->flags & AMX_FLAG_INIT)==0)
tylerwilson 0:3ab1d2d14eb3 1502 return AMX_ERR_INIT;
tylerwilson 0:3ab1d2d14eb3 1503 hdr=(AMX_HEADER *)amxSource->base;
tylerwilson 0:3ab1d2d14eb3 1504 if (hdr->magic!=AMX_MAGIC)
tylerwilson 0:3ab1d2d14eb3 1505 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1506 if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_version<MIN_FILE_VERSION)
tylerwilson 0:3ab1d2d14eb3 1507 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 1508
tylerwilson 0:3ab1d2d14eb3 1509 /* set initial values */
tylerwilson 0:3ab1d2d14eb3 1510 amxClone->base=amxSource->base;
tylerwilson 0:3ab1d2d14eb3 1511 amxClone->code=amxSource->code;
tylerwilson 0:3ab1d2d14eb3 1512 amxClone->codesize=amxSource->codesize;
tylerwilson 0:3ab1d2d14eb3 1513 amxClone->hlw=hdr->hea - hdr->dat; /* stack and heap relative to data segment */
tylerwilson 0:3ab1d2d14eb3 1514 amxClone->stp=hdr->stp - hdr->dat - sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1515 amxClone->hea=amxClone->hlw;
tylerwilson 0:3ab1d2d14eb3 1516 amxClone->stk=amxClone->stp;
tylerwilson 0:3ab1d2d14eb3 1517 if (amxClone->callback==NULL)
tylerwilson 0:3ab1d2d14eb3 1518 amxClone->callback=amxSource->callback;
tylerwilson 0:3ab1d2d14eb3 1519 if (amxClone->debug==NULL)
tylerwilson 0:3ab1d2d14eb3 1520 amxClone->debug=amxSource->debug;
tylerwilson 0:3ab1d2d14eb3 1521 amxClone->flags=amxSource->flags;
tylerwilson 0:3ab1d2d14eb3 1522
tylerwilson 0:3ab1d2d14eb3 1523 /* copy the data segment; the stack and the heap can be left uninitialized */
tylerwilson 0:3ab1d2d14eb3 1524 assert(data!=NULL);
tylerwilson 0:3ab1d2d14eb3 1525 amxClone->data=(unsigned char _FAR *)data;
tylerwilson 0:3ab1d2d14eb3 1526 dataSource=(amxSource->data!=NULL) ? amxSource->data : amxSource->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1527 memcpy(amxClone->data,dataSource,(size_t)(hdr->hea-hdr->dat));
tylerwilson 0:3ab1d2d14eb3 1528
tylerwilson 0:3ab1d2d14eb3 1529 /* Set a zero cell at the top of the stack, which functions
tylerwilson 0:3ab1d2d14eb3 1530 * as a sentinel for strings.
tylerwilson 0:3ab1d2d14eb3 1531 */
tylerwilson 0:3ab1d2d14eb3 1532 * (cell *)(amxClone->data+(int)amxClone->stp) = 0;
tylerwilson 0:3ab1d2d14eb3 1533
tylerwilson 0:3ab1d2d14eb3 1534 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1535 }
tylerwilson 0:3ab1d2d14eb3 1536 #endif /* AMX_CLONE */
tylerwilson 0:3ab1d2d14eb3 1537
tylerwilson 0:3ab1d2d14eb3 1538 #if defined AMX_MEMINFO
tylerwilson 0:3ab1d2d14eb3 1539 int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap)
tylerwilson 0:3ab1d2d14eb3 1540 {
tylerwilson 0:3ab1d2d14eb3 1541 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1542
tylerwilson 0:3ab1d2d14eb3 1543 if (amx==NULL)
tylerwilson 0:3ab1d2d14eb3 1544 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1545 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1546 if (hdr->magic!=AMX_MAGIC)
tylerwilson 0:3ab1d2d14eb3 1547 return AMX_ERR_FORMAT;
tylerwilson 0:3ab1d2d14eb3 1548 if (hdr->file_version>CUR_FILE_VERSION || hdr->amx_version<MIN_FILE_VERSION)
tylerwilson 0:3ab1d2d14eb3 1549 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 1550
tylerwilson 0:3ab1d2d14eb3 1551 if (codesize!=NULL)
tylerwilson 0:3ab1d2d14eb3 1552 *codesize=amx->codesize;
tylerwilson 0:3ab1d2d14eb3 1553 if (datasize!=NULL)
tylerwilson 0:3ab1d2d14eb3 1554 *datasize=hdr->hea - hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1555 if (stackheap!=NULL)
tylerwilson 0:3ab1d2d14eb3 1556 *stackheap=hdr->stp - hdr->hea;
tylerwilson 0:3ab1d2d14eb3 1557
tylerwilson 0:3ab1d2d14eb3 1558 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1559 }
tylerwilson 0:3ab1d2d14eb3 1560 #endif /* AMX_MEMINFO */
tylerwilson 0:3ab1d2d14eb3 1561
tylerwilson 0:3ab1d2d14eb3 1562 #if defined AMX_NAMELENGTH
tylerwilson 0:3ab1d2d14eb3 1563 int AMXAPI amx_NameLength(AMX *amx, int *length)
tylerwilson 0:3ab1d2d14eb3 1564 {
tylerwilson 0:3ab1d2d14eb3 1565 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1566 uint16_t *namelength;
tylerwilson 0:3ab1d2d14eb3 1567
tylerwilson 0:3ab1d2d14eb3 1568 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1569 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1570 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1571 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1572 namelength=(uint16_t*)(amx->base + (unsigned)hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1573 *length=*namelength;
tylerwilson 0:3ab1d2d14eb3 1574 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1575 }
tylerwilson 0:3ab1d2d14eb3 1576 #endif /* AMX_NAMELENGTH */
tylerwilson 0:3ab1d2d14eb3 1577
tylerwilson 0:3ab1d2d14eb3 1578 #if defined AMX_XXXNATIVES
tylerwilson 0:3ab1d2d14eb3 1579 int AMXAPI amx_NumNatives(AMX *amx, int *number)
tylerwilson 0:3ab1d2d14eb3 1580 {
tylerwilson 0:3ab1d2d14eb3 1581 AMX_HEADER *hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1582 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1583 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1584 assert(hdr->natives<=hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 1585 *number=NUMENTRIES(hdr,natives,libraries);
tylerwilson 0:3ab1d2d14eb3 1586 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1587 }
tylerwilson 0:3ab1d2d14eb3 1588
tylerwilson 0:3ab1d2d14eb3 1589 int AMXAPI amx_GetNative(AMX *amx, int index, char *name)
tylerwilson 0:3ab1d2d14eb3 1590 {
tylerwilson 0:3ab1d2d14eb3 1591 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1592 AMX_FUNCSTUB *func;
tylerwilson 0:3ab1d2d14eb3 1593
tylerwilson 0:3ab1d2d14eb3 1594 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1595 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1596 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1597 assert(hdr->natives<=hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 1598 if (index>=(cell)NUMENTRIES(hdr,natives,libraries))
tylerwilson 0:3ab1d2d14eb3 1599 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1600
tylerwilson 0:3ab1d2d14eb3 1601 func=GETENTRY(hdr,natives,index);
tylerwilson 0:3ab1d2d14eb3 1602 strcpy(name,GETENTRYNAME(hdr,func));
tylerwilson 0:3ab1d2d14eb3 1603 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1604 }
tylerwilson 0:3ab1d2d14eb3 1605
tylerwilson 0:3ab1d2d14eb3 1606 int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index)
tylerwilson 0:3ab1d2d14eb3 1607 {
tylerwilson 0:3ab1d2d14eb3 1608 int idx,last;
tylerwilson 0:3ab1d2d14eb3 1609 char pname[sNAMEMAX+1];
tylerwilson 0:3ab1d2d14eb3 1610
tylerwilson 0:3ab1d2d14eb3 1611 amx_NumNatives(amx, &last);
tylerwilson 0:3ab1d2d14eb3 1612 /* linear search, the natives table is not sorted alphabetically */
tylerwilson 0:3ab1d2d14eb3 1613 for (idx=0; idx<last; idx++) {
tylerwilson 0:3ab1d2d14eb3 1614 amx_GetNative(amx,idx,pname);
tylerwilson 0:3ab1d2d14eb3 1615 if (strcmp(pname,name)==0) {
tylerwilson 0:3ab1d2d14eb3 1616 *index=idx;
tylerwilson 0:3ab1d2d14eb3 1617 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1618 } /* if */
tylerwilson 0:3ab1d2d14eb3 1619 } /* for */
tylerwilson 0:3ab1d2d14eb3 1620 *index=INT_MAX;
tylerwilson 0:3ab1d2d14eb3 1621 return AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 1622 }
tylerwilson 0:3ab1d2d14eb3 1623 #endif /* AMX_XXXNATIVES */
tylerwilson 0:3ab1d2d14eb3 1624
tylerwilson 0:3ab1d2d14eb3 1625 #if defined AMX_XXXPUBLICS
tylerwilson 0:3ab1d2d14eb3 1626 int AMXAPI amx_NumPublics(AMX *amx, int *number)
tylerwilson 0:3ab1d2d14eb3 1627 {
tylerwilson 0:3ab1d2d14eb3 1628 AMX_HEADER *hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1629 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1630 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1631 assert(hdr->publics<=hdr->natives);
tylerwilson 0:3ab1d2d14eb3 1632 *number=NUMENTRIES(hdr,publics,natives);
tylerwilson 0:3ab1d2d14eb3 1633 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1634 }
tylerwilson 0:3ab1d2d14eb3 1635
tylerwilson 0:3ab1d2d14eb3 1636 int AMXAPI amx_GetPublic(AMX *amx, int index, char *name, ucell *address)
tylerwilson 0:3ab1d2d14eb3 1637 {
tylerwilson 0:3ab1d2d14eb3 1638 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1639 AMX_FUNCSTUB *func;
tylerwilson 0:3ab1d2d14eb3 1640
tylerwilson 0:3ab1d2d14eb3 1641 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1642 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1643 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1644 assert(hdr->publics<=hdr->natives);
tylerwilson 0:3ab1d2d14eb3 1645 if (index>=(cell)NUMENTRIES(hdr,publics,natives))
tylerwilson 0:3ab1d2d14eb3 1646 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1647
tylerwilson 0:3ab1d2d14eb3 1648 func=GETENTRY(hdr,publics,index);
tylerwilson 0:3ab1d2d14eb3 1649 if (name!=NULL)
tylerwilson 0:3ab1d2d14eb3 1650 strcpy(name,GETENTRYNAME(hdr,func));
tylerwilson 0:3ab1d2d14eb3 1651 if (address!=NULL)
tylerwilson 0:3ab1d2d14eb3 1652 *address=func->address;
tylerwilson 0:3ab1d2d14eb3 1653 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1654 }
tylerwilson 0:3ab1d2d14eb3 1655
tylerwilson 0:3ab1d2d14eb3 1656 int AMXAPI amx_FindPublic(AMX *amx, const char *name, int *index)
tylerwilson 0:3ab1d2d14eb3 1657 {
tylerwilson 0:3ab1d2d14eb3 1658 int first,last,mid,result;
tylerwilson 0:3ab1d2d14eb3 1659 char pname[sNAMEMAX+1];
tylerwilson 0:3ab1d2d14eb3 1660
tylerwilson 0:3ab1d2d14eb3 1661 amx_NumPublics(amx, &last);
tylerwilson 0:3ab1d2d14eb3 1662 last--; /* last valid index is 1 less than the number of functions */
tylerwilson 0:3ab1d2d14eb3 1663 first=0;
tylerwilson 0:3ab1d2d14eb3 1664 /* binary search */
tylerwilson 0:3ab1d2d14eb3 1665 while (first<=last) {
tylerwilson 0:3ab1d2d14eb3 1666 mid=(first+last)/2;
tylerwilson 0:3ab1d2d14eb3 1667 amx_GetPublic(amx,mid,pname,NULL);
tylerwilson 0:3ab1d2d14eb3 1668 result=strcmp(pname,name);
tylerwilson 0:3ab1d2d14eb3 1669 if (result>0) {
tylerwilson 0:3ab1d2d14eb3 1670 last=mid-1;
tylerwilson 0:3ab1d2d14eb3 1671 } else if (result<0) {
tylerwilson 0:3ab1d2d14eb3 1672 first=mid+1;
tylerwilson 0:3ab1d2d14eb3 1673 } else {
tylerwilson 0:3ab1d2d14eb3 1674 *index=mid;
tylerwilson 0:3ab1d2d14eb3 1675 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1676 } /* if */
tylerwilson 0:3ab1d2d14eb3 1677 } /* while */
tylerwilson 0:3ab1d2d14eb3 1678 /* not found, set to an invalid index, so amx_Exec() on this index will fail
tylerwilson 0:3ab1d2d14eb3 1679 * with an error
tylerwilson 0:3ab1d2d14eb3 1680 */
tylerwilson 0:3ab1d2d14eb3 1681 *index=INT_MAX;
tylerwilson 0:3ab1d2d14eb3 1682 return AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 1683 }
tylerwilson 0:3ab1d2d14eb3 1684 #endif /* AMX_XXXPUBLICS */
tylerwilson 0:3ab1d2d14eb3 1685
tylerwilson 0:3ab1d2d14eb3 1686 #if defined AMX_XXXPUBVARS
tylerwilson 0:3ab1d2d14eb3 1687 int AMXAPI amx_NumPubVars(AMX *amx, int *number)
tylerwilson 0:3ab1d2d14eb3 1688 {
tylerwilson 0:3ab1d2d14eb3 1689 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1690
tylerwilson 0:3ab1d2d14eb3 1691 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1692 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1693 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1694 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1695 assert(hdr->pubvars<=hdr->tags);
tylerwilson 0:3ab1d2d14eb3 1696 *number=NUMENTRIES(hdr,pubvars,tags);
tylerwilson 0:3ab1d2d14eb3 1697 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1698 }
tylerwilson 0:3ab1d2d14eb3 1699
tylerwilson 0:3ab1d2d14eb3 1700 int AMXAPI amx_GetPubVar(AMX *amx, int index, char *name, cell **address)
tylerwilson 0:3ab1d2d14eb3 1701 {
tylerwilson 0:3ab1d2d14eb3 1702 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1703 AMX_FUNCSTUB *var;
tylerwilson 0:3ab1d2d14eb3 1704 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 1705
tylerwilson 0:3ab1d2d14eb3 1706 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1707 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1708 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1709 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1710 assert(hdr->pubvars<=hdr->tags);
tylerwilson 0:3ab1d2d14eb3 1711 if (index>=(cell)NUMENTRIES(hdr,pubvars,tags))
tylerwilson 0:3ab1d2d14eb3 1712 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1713
tylerwilson 0:3ab1d2d14eb3 1714 var=GETENTRY(hdr,pubvars,index);
tylerwilson 0:3ab1d2d14eb3 1715 strcpy(name,GETENTRYNAME(hdr,var));
tylerwilson 0:3ab1d2d14eb3 1716 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1717 assert(address!=NULL);
tylerwilson 0:3ab1d2d14eb3 1718 *address=(cell *)(data+(int)var->address);
tylerwilson 0:3ab1d2d14eb3 1719 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1720 }
tylerwilson 0:3ab1d2d14eb3 1721
tylerwilson 0:3ab1d2d14eb3 1722 int AMXAPI amx_FindPubVar(AMX *amx, const char *name, cell **address)
tylerwilson 0:3ab1d2d14eb3 1723 {
tylerwilson 0:3ab1d2d14eb3 1724 int first,last,mid,result;
tylerwilson 0:3ab1d2d14eb3 1725 char pname[sNAMEMAX+1];
tylerwilson 0:3ab1d2d14eb3 1726
tylerwilson 0:3ab1d2d14eb3 1727 amx_NumPubVars(amx,&last);
tylerwilson 0:3ab1d2d14eb3 1728 last--; /* last valid index is 1 less than the number of functions */
tylerwilson 0:3ab1d2d14eb3 1729 first=0;
tylerwilson 0:3ab1d2d14eb3 1730 /* binary search */
tylerwilson 0:3ab1d2d14eb3 1731 while (first<=last) {
tylerwilson 0:3ab1d2d14eb3 1732 mid=(first+last)/2;
tylerwilson 0:3ab1d2d14eb3 1733 amx_GetPubVar(amx,mid,pname,address);
tylerwilson 0:3ab1d2d14eb3 1734 result=strcmp(pname,name);
tylerwilson 0:3ab1d2d14eb3 1735 if (result>0)
tylerwilson 0:3ab1d2d14eb3 1736 last=mid-1;
tylerwilson 0:3ab1d2d14eb3 1737 else if (result<0)
tylerwilson 0:3ab1d2d14eb3 1738 first=mid+1;
tylerwilson 0:3ab1d2d14eb3 1739 else
tylerwilson 0:3ab1d2d14eb3 1740 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1741 } /* while */
tylerwilson 0:3ab1d2d14eb3 1742 /* not found */
tylerwilson 0:3ab1d2d14eb3 1743 assert(address!=NULL);
tylerwilson 0:3ab1d2d14eb3 1744 *address=NULL;
tylerwilson 0:3ab1d2d14eb3 1745 return AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 1746 }
tylerwilson 0:3ab1d2d14eb3 1747 #endif /* AMX_XXXPUBVARS */
tylerwilson 0:3ab1d2d14eb3 1748
tylerwilson 0:3ab1d2d14eb3 1749 #if defined AMX_XXXTAGS
tylerwilson 0:3ab1d2d14eb3 1750 int AMXAPI amx_NumTags(AMX *amx, int *number)
tylerwilson 0:3ab1d2d14eb3 1751 {
tylerwilson 0:3ab1d2d14eb3 1752 AMX_HEADER *hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1753 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1754 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1755 if (hdr->file_version<5) { /* the tagname table appeared in file format 5 */
tylerwilson 0:3ab1d2d14eb3 1756 *number=0;
tylerwilson 0:3ab1d2d14eb3 1757 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 1758 } /* if */
tylerwilson 0:3ab1d2d14eb3 1759 if (hdr->file_version<7) { /* file version 7 introduced the name table */
tylerwilson 0:3ab1d2d14eb3 1760 assert(hdr->tags<=hdr->cod);
tylerwilson 0:3ab1d2d14eb3 1761 *number=NUMENTRIES(hdr,tags,cod);
tylerwilson 0:3ab1d2d14eb3 1762 } else {
tylerwilson 0:3ab1d2d14eb3 1763 assert(hdr->tags<=hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1764 *number=NUMENTRIES(hdr,tags,nametable);
tylerwilson 0:3ab1d2d14eb3 1765 } /* if */
tylerwilson 0:3ab1d2d14eb3 1766 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1767 }
tylerwilson 0:3ab1d2d14eb3 1768
tylerwilson 0:3ab1d2d14eb3 1769 int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id)
tylerwilson 0:3ab1d2d14eb3 1770 {
tylerwilson 0:3ab1d2d14eb3 1771 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1772 AMX_FUNCSTUB *tag;
tylerwilson 0:3ab1d2d14eb3 1773
tylerwilson 0:3ab1d2d14eb3 1774 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1775 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1776 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1777 if (hdr->file_version<5) { /* the tagname table appeared in file format 5 */
tylerwilson 0:3ab1d2d14eb3 1778 *tagname='\0';
tylerwilson 0:3ab1d2d14eb3 1779 *tag_id=0;
tylerwilson 0:3ab1d2d14eb3 1780 return AMX_ERR_VERSION;
tylerwilson 0:3ab1d2d14eb3 1781 } /* if */
tylerwilson 0:3ab1d2d14eb3 1782
tylerwilson 0:3ab1d2d14eb3 1783 if (hdr->file_version<7) { /* file version 7 introduced the name table */
tylerwilson 0:3ab1d2d14eb3 1784 assert(hdr->tags<=hdr->cod);
tylerwilson 0:3ab1d2d14eb3 1785 if (index>=(cell)NUMENTRIES(hdr,tags,cod))
tylerwilson 0:3ab1d2d14eb3 1786 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1787 } else {
tylerwilson 0:3ab1d2d14eb3 1788 assert(hdr->tags<=hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 1789 if (index>=(cell)NUMENTRIES(hdr,tags,nametable))
tylerwilson 0:3ab1d2d14eb3 1790 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1791 } /* if */
tylerwilson 0:3ab1d2d14eb3 1792
tylerwilson 0:3ab1d2d14eb3 1793 tag=GETENTRY(hdr,tags,index);
tylerwilson 0:3ab1d2d14eb3 1794 strcpy(tagname,GETENTRYNAME(hdr,tag));
tylerwilson 0:3ab1d2d14eb3 1795 *tag_id=tag->address;
tylerwilson 0:3ab1d2d14eb3 1796
tylerwilson 0:3ab1d2d14eb3 1797 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1798 }
tylerwilson 0:3ab1d2d14eb3 1799
tylerwilson 0:3ab1d2d14eb3 1800 int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname)
tylerwilson 0:3ab1d2d14eb3 1801 {
tylerwilson 0:3ab1d2d14eb3 1802 int first,last,mid;
tylerwilson 0:3ab1d2d14eb3 1803 cell mid_id;
tylerwilson 0:3ab1d2d14eb3 1804
tylerwilson 0:3ab1d2d14eb3 1805 #if !defined NDEBUG
tylerwilson 0:3ab1d2d14eb3 1806 /* verify that the tagname table is sorted on the tag_id */
tylerwilson 0:3ab1d2d14eb3 1807 amx_NumTags(amx, &last);
tylerwilson 0:3ab1d2d14eb3 1808 if (last>0) {
tylerwilson 0:3ab1d2d14eb3 1809 cell cur_id;
tylerwilson 0:3ab1d2d14eb3 1810 amx_GetTag(amx,0,tagname,&cur_id);
tylerwilson 0:3ab1d2d14eb3 1811 for (first=1; first<last; first++) {
tylerwilson 0:3ab1d2d14eb3 1812 amx_GetTag(amx,first,tagname,&mid_id);
tylerwilson 0:3ab1d2d14eb3 1813 assert(cur_id<mid_id);
tylerwilson 0:3ab1d2d14eb3 1814 cur_id=mid_id;
tylerwilson 0:3ab1d2d14eb3 1815 } /* for */
tylerwilson 0:3ab1d2d14eb3 1816 } /* if */
tylerwilson 0:3ab1d2d14eb3 1817 #endif
tylerwilson 0:3ab1d2d14eb3 1818
tylerwilson 0:3ab1d2d14eb3 1819 amx_NumTags(amx, &last);
tylerwilson 0:3ab1d2d14eb3 1820 last--; /* last valid index is 1 less than the number of functions */
tylerwilson 0:3ab1d2d14eb3 1821 first=0;
tylerwilson 0:3ab1d2d14eb3 1822 /* binary search */
tylerwilson 0:3ab1d2d14eb3 1823 while (first<=last) {
tylerwilson 0:3ab1d2d14eb3 1824 mid=(first+last)/2;
tylerwilson 0:3ab1d2d14eb3 1825 amx_GetTag(amx,mid,tagname,&mid_id);
tylerwilson 0:3ab1d2d14eb3 1826 if (mid_id>tag_id)
tylerwilson 0:3ab1d2d14eb3 1827 last=mid-1;
tylerwilson 0:3ab1d2d14eb3 1828 else if (mid_id<tag_id)
tylerwilson 0:3ab1d2d14eb3 1829 first=mid+1;
tylerwilson 0:3ab1d2d14eb3 1830 else
tylerwilson 0:3ab1d2d14eb3 1831 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1832 } /* while */
tylerwilson 0:3ab1d2d14eb3 1833 /* not found */
tylerwilson 0:3ab1d2d14eb3 1834 *tagname='\0';
tylerwilson 0:3ab1d2d14eb3 1835 return AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 1836 }
tylerwilson 0:3ab1d2d14eb3 1837 #endif /* AMX_XXXTAGS */
tylerwilson 0:3ab1d2d14eb3 1838
tylerwilson 0:3ab1d2d14eb3 1839 #if defined AMX_XXXUSERDATA
tylerwilson 0:3ab1d2d14eb3 1840 int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr)
tylerwilson 0:3ab1d2d14eb3 1841 {
tylerwilson 0:3ab1d2d14eb3 1842 int index;
tylerwilson 0:3ab1d2d14eb3 1843
tylerwilson 0:3ab1d2d14eb3 1844 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1845 assert(tag!=0);
tylerwilson 0:3ab1d2d14eb3 1846 for (index=0; index<AMX_USERNUM && amx->usertags[index]!=tag; index++)
tylerwilson 0:3ab1d2d14eb3 1847 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 1848 if (index>=AMX_USERNUM)
tylerwilson 0:3ab1d2d14eb3 1849 return AMX_ERR_USERDATA;
tylerwilson 0:3ab1d2d14eb3 1850 *ptr=amx->userdata[index];
tylerwilson 0:3ab1d2d14eb3 1851 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1852 }
tylerwilson 0:3ab1d2d14eb3 1853
tylerwilson 0:3ab1d2d14eb3 1854 int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr)
tylerwilson 0:3ab1d2d14eb3 1855 {
tylerwilson 0:3ab1d2d14eb3 1856 int index;
tylerwilson 0:3ab1d2d14eb3 1857
tylerwilson 0:3ab1d2d14eb3 1858 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1859 assert(tag!=0);
tylerwilson 0:3ab1d2d14eb3 1860 /* try to find existing tag */
tylerwilson 0:3ab1d2d14eb3 1861 for (index=0; index<AMX_USERNUM && amx->usertags[index]!=tag; index++)
tylerwilson 0:3ab1d2d14eb3 1862 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 1863 /* if not found, try to find empty tag */
tylerwilson 0:3ab1d2d14eb3 1864 if (index>=AMX_USERNUM)
tylerwilson 0:3ab1d2d14eb3 1865 for (index=0; index<AMX_USERNUM && amx->usertags[index]!=0; index++)
tylerwilson 0:3ab1d2d14eb3 1866 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 1867 /* if still not found, quit with error */
tylerwilson 0:3ab1d2d14eb3 1868 if (index>=AMX_USERNUM)
tylerwilson 0:3ab1d2d14eb3 1869 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 1870 /* set the tag and the value */
tylerwilson 0:3ab1d2d14eb3 1871 amx->usertags[index]=tag;
tylerwilson 0:3ab1d2d14eb3 1872 amx->userdata[index]=ptr;
tylerwilson 0:3ab1d2d14eb3 1873 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1874 }
tylerwilson 0:3ab1d2d14eb3 1875 #endif /* AMX_XXXUSERDATA */
tylerwilson 0:3ab1d2d14eb3 1876
tylerwilson 0:3ab1d2d14eb3 1877 #if defined AMX_REGISTER
tylerwilson 0:3ab1d2d14eb3 1878 static AMX_NATIVE findfunction(char *name, const AMX_NATIVE_INFO *list, int number)
tylerwilson 0:3ab1d2d14eb3 1879 {
tylerwilson 0:3ab1d2d14eb3 1880 int i;
tylerwilson 0:3ab1d2d14eb3 1881
tylerwilson 0:3ab1d2d14eb3 1882 assert(list!=NULL);
tylerwilson 0:3ab1d2d14eb3 1883 for (i=0; list[i].name!=NULL && (i<number || number==-1); i++)
tylerwilson 0:3ab1d2d14eb3 1884 if (strcmp(name,list[i].name)==0)
tylerwilson 0:3ab1d2d14eb3 1885 return list[i].func;
tylerwilson 0:3ab1d2d14eb3 1886 return NULL;
tylerwilson 0:3ab1d2d14eb3 1887 }
tylerwilson 0:3ab1d2d14eb3 1888
tylerwilson 0:3ab1d2d14eb3 1889 int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number)
tylerwilson 0:3ab1d2d14eb3 1890 {
tylerwilson 0:3ab1d2d14eb3 1891 AMX_FUNCSTUB *func;
tylerwilson 0:3ab1d2d14eb3 1892 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1893 int i,numnatives,err;
tylerwilson 0:3ab1d2d14eb3 1894 AMX_NATIVE funcptr;
tylerwilson 0:3ab1d2d14eb3 1895
tylerwilson 0:3ab1d2d14eb3 1896 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1897 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1898 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1899 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1900 assert(hdr->natives<=hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 1901 numnatives=NUMENTRIES(hdr,natives,libraries);
tylerwilson 0:3ab1d2d14eb3 1902
tylerwilson 0:3ab1d2d14eb3 1903 err=AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1904 func=GETENTRY(hdr,natives,0);
tylerwilson 0:3ab1d2d14eb3 1905 for (i=0; i<numnatives; i++) {
tylerwilson 0:3ab1d2d14eb3 1906 if (func->address==0) {
tylerwilson 0:3ab1d2d14eb3 1907 /* this function is not yet located */
tylerwilson 0:3ab1d2d14eb3 1908 funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL;
tylerwilson 0:3ab1d2d14eb3 1909 if (funcptr!=NULL)
tylerwilson 0:3ab1d2d14eb3 1910 func->address=(ucell)funcptr;
tylerwilson 0:3ab1d2d14eb3 1911 else
tylerwilson 0:3ab1d2d14eb3 1912 err=AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 1913 } /* if */
tylerwilson 0:3ab1d2d14eb3 1914 func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 1915 } /* for */
tylerwilson 0:3ab1d2d14eb3 1916 if (err==AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 1917 amx->flags|=AMX_FLAG_NTVREG;
tylerwilson 0:3ab1d2d14eb3 1918 return err;
tylerwilson 0:3ab1d2d14eb3 1919 }
tylerwilson 0:3ab1d2d14eb3 1920 #endif /* AMX_REGISTER */
tylerwilson 0:3ab1d2d14eb3 1921
tylerwilson 0:3ab1d2d14eb3 1922 #if defined AMX_NATIVEINFO
tylerwilson 0:3ab1d2d14eb3 1923 AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func)
tylerwilson 0:3ab1d2d14eb3 1924 {
tylerwilson 0:3ab1d2d14eb3 1925 static AMX_NATIVE_INFO n;
tylerwilson 0:3ab1d2d14eb3 1926 n.name=name;
tylerwilson 0:3ab1d2d14eb3 1927 n.func=func;
tylerwilson 0:3ab1d2d14eb3 1928 return &n;
tylerwilson 0:3ab1d2d14eb3 1929 }
tylerwilson 0:3ab1d2d14eb3 1930 #endif /* AMX_NATIVEINFO */
tylerwilson 0:3ab1d2d14eb3 1931
tylerwilson 0:3ab1d2d14eb3 1932
tylerwilson 0:3ab1d2d14eb3 1933 #define STKMARGIN ((cell)(16*sizeof(cell)))
tylerwilson 0:3ab1d2d14eb3 1934
tylerwilson 0:3ab1d2d14eb3 1935 #if defined AMX_PUSHXXX
tylerwilson 0:3ab1d2d14eb3 1936
tylerwilson 0:3ab1d2d14eb3 1937 int AMXAPI amx_Push(AMX *amx, cell value)
tylerwilson 0:3ab1d2d14eb3 1938 {
tylerwilson 0:3ab1d2d14eb3 1939 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1940 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 1941
tylerwilson 0:3ab1d2d14eb3 1942 if (amx->hea+STKMARGIN>amx->stk)
tylerwilson 0:3ab1d2d14eb3 1943 return AMX_ERR_STACKERR;
tylerwilson 0:3ab1d2d14eb3 1944 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1945 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1946 amx->stk-=sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 1947 amx->paramcount+=1;
tylerwilson 0:3ab1d2d14eb3 1948 *(cell *)(data+(int)amx->stk)=value;
tylerwilson 0:3ab1d2d14eb3 1949 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 1950 }
tylerwilson 0:3ab1d2d14eb3 1951
tylerwilson 0:3ab1d2d14eb3 1952 int AMXAPI amx_PushAddress(AMX *amx, cell *address)
tylerwilson 0:3ab1d2d14eb3 1953 {
tylerwilson 0:3ab1d2d14eb3 1954 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 1955 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 1956 cell xaddr;
tylerwilson 0:3ab1d2d14eb3 1957
tylerwilson 0:3ab1d2d14eb3 1958 /* reverse relocate the address */
tylerwilson 0:3ab1d2d14eb3 1959 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1960 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 1961 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 1962 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 1963 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 1964 xaddr=(cell)((unsigned char*)address-data);
tylerwilson 0:3ab1d2d14eb3 1965 if ((ucell)xaddr>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 1966 return AMX_ERR_MEMACCESS;
tylerwilson 0:3ab1d2d14eb3 1967 return amx_Push(amx,xaddr);
tylerwilson 0:3ab1d2d14eb3 1968 }
tylerwilson 0:3ab1d2d14eb3 1969
tylerwilson 0:3ab1d2d14eb3 1970 int AMXAPI amx_PushArray(AMX *amx, cell **address, const cell array[], int numcells)
tylerwilson 0:3ab1d2d14eb3 1971 {
tylerwilson 0:3ab1d2d14eb3 1972 cell xaddr;
tylerwilson 0:3ab1d2d14eb3 1973 int err;
tylerwilson 0:3ab1d2d14eb3 1974
tylerwilson 0:3ab1d2d14eb3 1975 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1976 assert(array!=NULL);
tylerwilson 0:3ab1d2d14eb3 1977
tylerwilson 0:3ab1d2d14eb3 1978 xaddr=amx->hea; /* save, before it is modified by amx_Allot() */
tylerwilson 0:3ab1d2d14eb3 1979 err=amx_Allot(amx,numcells,address);
tylerwilson 0:3ab1d2d14eb3 1980 if (err==AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 1981 memcpy(*address,array,numcells*sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 1982 err=amx_Push(amx,xaddr);
tylerwilson 0:3ab1d2d14eb3 1983 } /* if */
tylerwilson 0:3ab1d2d14eb3 1984 return err;
tylerwilson 0:3ab1d2d14eb3 1985 }
tylerwilson 0:3ab1d2d14eb3 1986
tylerwilson 0:3ab1d2d14eb3 1987 int AMXAPI amx_PushString(AMX *amx, cell **address, const char *string, int pack, int use_wchar)
tylerwilson 0:3ab1d2d14eb3 1988 {
tylerwilson 0:3ab1d2d14eb3 1989 cell xaddr;
tylerwilson 0:3ab1d2d14eb3 1990 int numcells,err;
tylerwilson 0:3ab1d2d14eb3 1991
tylerwilson 0:3ab1d2d14eb3 1992 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 1993 assert(string!=NULL);
tylerwilson 0:3ab1d2d14eb3 1994
tylerwilson 0:3ab1d2d14eb3 1995 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 1996 numcells=strlen(string) + 1;
tylerwilson 0:3ab1d2d14eb3 1997 #else
tylerwilson 0:3ab1d2d14eb3 1998 numcells= (use_wchar ? wcslen((const wchar_t*)string) : strlen(string)) + 1;
tylerwilson 0:3ab1d2d14eb3 1999 #endif
tylerwilson 0:3ab1d2d14eb3 2000 if (pack)
tylerwilson 0:3ab1d2d14eb3 2001 numcells=(numcells+sizeof(cell)-1)/sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 2002 xaddr=amx->hea; /* save, before it is modified by amx_Allot() */
tylerwilson 0:3ab1d2d14eb3 2003 err=amx_Allot(amx,numcells,address);
tylerwilson 0:3ab1d2d14eb3 2004 if (err==AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 2005 amx_SetString(*address,string,pack,use_wchar,numcells);
tylerwilson 0:3ab1d2d14eb3 2006 err=amx_Push(amx,xaddr);
tylerwilson 0:3ab1d2d14eb3 2007 } /* if */
tylerwilson 0:3ab1d2d14eb3 2008 return err;
tylerwilson 0:3ab1d2d14eb3 2009 }
tylerwilson 0:3ab1d2d14eb3 2010 #endif /* AMX_PUSHXXX */
tylerwilson 0:3ab1d2d14eb3 2011
tylerwilson 0:3ab1d2d14eb3 2012 #if defined AMX_EXEC
tylerwilson 0:3ab1d2d14eb3 2013
tylerwilson 0:3ab1d2d14eb3 2014 /* It is assumed that the abstract machine can simply access the memory area
tylerwilson 0:3ab1d2d14eb3 2015 * for the global data and the stack. If this is not the case, you need to
tylerwilson 0:3ab1d2d14eb3 2016 * define the macro sets _R() and _W(), for reading and writing to memory.
tylerwilson 0:3ab1d2d14eb3 2017 */
tylerwilson 0:3ab1d2d14eb3 2018 #if !defined _R
tylerwilson 0:3ab1d2d14eb3 2019 #define _R_DEFAULT /* mark default memory access */
tylerwilson 0:3ab1d2d14eb3 2020 #define _R(base,addr) (* (cell *)((unsigned char*)(base)+(int)(addr)))
tylerwilson 0:3ab1d2d14eb3 2021 #define _R8(base,addr) (* (unsigned char *)((unsigned char*)(base)+(int)(addr)))
tylerwilson 0:3ab1d2d14eb3 2022 #define _R16(base,addr) (* (uint16_t *)((unsigned char*)(base)+(int)(addr)))
tylerwilson 0:3ab1d2d14eb3 2023 #define _R32(base,addr) (* (uint32_t *)((unsigned char*)(base)+(int)(addr)))
tylerwilson 0:3ab1d2d14eb3 2024 #endif
tylerwilson 0:3ab1d2d14eb3 2025 #if !defined _W
tylerwilson 0:3ab1d2d14eb3 2026 #define _W_DEFAULT /* mark default memory access */
tylerwilson 0:3ab1d2d14eb3 2027 #define _W(base,addr,value) ((*(cell *)((unsigned char*)(base)+(int)(addr)))=(cell)(value))
tylerwilson 0:3ab1d2d14eb3 2028 #define _W8(base,addr,value) ((*(unsigned char *)((unsigned char*)(base)+(int)(addr)))=(unsigned char)(value))
tylerwilson 0:3ab1d2d14eb3 2029 #define _W16(base,addr,value) ((*(uint16_t *)((unsigned char*)(base)+(int)(addr)))=(uint16_t)(value))
tylerwilson 0:3ab1d2d14eb3 2030 #define _W32(base,addr,value) ((*(uint32_t *)((unsigned char*)(base)+(int)(addr)))=(uint32_t)(value))
tylerwilson 0:3ab1d2d14eb3 2031 #endif
tylerwilson 0:3ab1d2d14eb3 2032
tylerwilson 0:3ab1d2d14eb3 2033 #if -8/3==-2 && 8/-3==-2
tylerwilson 0:3ab1d2d14eb3 2034 #define TRUNC_SDIV /* signed divisions are truncated on this platform */
tylerwilson 0:3ab1d2d14eb3 2035 #else
tylerwilson 0:3ab1d2d14eb3 2036 #define IABS(a) ((a)>=0 ? (a) : (-a))
tylerwilson 0:3ab1d2d14eb3 2037 #endif
tylerwilson 0:3ab1d2d14eb3 2038
tylerwilson 0:3ab1d2d14eb3 2039 /* The pseudo-instructions come from the code stream. Normally, these are just
tylerwilson 0:3ab1d2d14eb3 2040 * accessed from memory. When the instructions must be fetched in some other
tylerwilson 0:3ab1d2d14eb3 2041 * way, the definition below must be pre-defined.
tylerwilson 0:3ab1d2d14eb3 2042 * N.B.:
tylerwilson 0:3ab1d2d14eb3 2043 * - reading from a code address should increment the instruction pointer
tylerwilson 0:3ab1d2d14eb3 2044 * (called "cip")
tylerwilson 0:3ab1d2d14eb3 2045 * - only cell-sized accesses occur in code memory
tylerwilson 0:3ab1d2d14eb3 2046 */
tylerwilson 0:3ab1d2d14eb3 2047 #if !defined _RCODE
tylerwilson 0:3ab1d2d14eb3 2048 #define _RCODE() ( *cip++ )
tylerwilson 0:3ab1d2d14eb3 2049 #endif
tylerwilson 0:3ab1d2d14eb3 2050
tylerwilson 0:3ab1d2d14eb3 2051 #if !defined GETPARAM
tylerwilson 0:3ab1d2d14eb3 2052 #define GETPARAM(v) ( v=_RCODE() ) /* read a parameter from the opcode stream */
tylerwilson 0:3ab1d2d14eb3 2053 #endif
tylerwilson 0:3ab1d2d14eb3 2054 #if !defined SKIPPARAM
tylerwilson 0:3ab1d2d14eb3 2055 #define SKIPPARAM(n) ( cip=(cell *)cip+(n) ) /* for obsolete opcodes */
tylerwilson 0:3ab1d2d14eb3 2056 #endif
tylerwilson 0:3ab1d2d14eb3 2057
tylerwilson 0:3ab1d2d14eb3 2058 #define AMXPUSH(v) ( amx->stk-=sizeof(cell), *(cell*)(data+amx->stk)=(v) )
tylerwilson 0:3ab1d2d14eb3 2059 #define ABORT(amx,v) { (amx)->stk=reset_stk; (amx)->hea=reset_hea; return v; }
tylerwilson 0:3ab1d2d14eb3 2060
tylerwilson 0:3ab1d2d14eb3 2061
tylerwilson 0:3ab1d2d14eb3 2062 #if !defined AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 2063 int amx_exec_list(AMX *amx,const cell **opcodelist,int *numopcodes)
tylerwilson 0:3ab1d2d14eb3 2064 {
tylerwilson 0:3ab1d2d14eb3 2065 (void)amx;
tylerwilson 0:3ab1d2d14eb3 2066 assert(opcodelist!=NULL);
tylerwilson 0:3ab1d2d14eb3 2067 *opcodelist=NULL;
tylerwilson 0:3ab1d2d14eb3 2068 assert(numopcodes!=NULL);
tylerwilson 0:3ab1d2d14eb3 2069 *numopcodes=OP_NUM_OPCODES;
tylerwilson 0:3ab1d2d14eb3 2070 return 0;
tylerwilson 0:3ab1d2d14eb3 2071 }
tylerwilson 0:3ab1d2d14eb3 2072 #endif
tylerwilson 0:3ab1d2d14eb3 2073
tylerwilson 0:3ab1d2d14eb3 2074 int AMXAPI amx_Exec(AMX *amx, cell *retval, int index)
tylerwilson 0:3ab1d2d14eb3 2075 {
tylerwilson 0:3ab1d2d14eb3 2076 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 2077 AMX_FUNCSTUB *func;
tylerwilson 0:3ab1d2d14eb3 2078 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 2079 cell reset_stk,reset_hea;
tylerwilson 0:3ab1d2d14eb3 2080 int i;
tylerwilson 0:3ab1d2d14eb3 2081 #if !defined AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 2082 cell pri,alt,stk,frm,hea;
tylerwilson 0:3ab1d2d14eb3 2083 cell *cip,op,offs,val;
tylerwilson 0:3ab1d2d14eb3 2084 #endif
tylerwilson 0:3ab1d2d14eb3 2085
tylerwilson 0:3ab1d2d14eb3 2086 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 2087 if ((amx->flags & AMX_FLAG_INIT)==0)
tylerwilson 0:3ab1d2d14eb3 2088 return AMX_ERR_INIT;
tylerwilson 0:3ab1d2d14eb3 2089 if (amx->callback==NULL)
tylerwilson 0:3ab1d2d14eb3 2090 return AMX_ERR_CALLBACK;
tylerwilson 0:3ab1d2d14eb3 2091
tylerwilson 0:3ab1d2d14eb3 2092 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 2093 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 2094 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 2095
tylerwilson 0:3ab1d2d14eb3 2096 if ((amx->flags & AMX_FLAG_NTVREG)==0) {
tylerwilson 0:3ab1d2d14eb3 2097 /* verify that all native functions have been registered (or do not
tylerwilson 0:3ab1d2d14eb3 2098 * need registering)
tylerwilson 0:3ab1d2d14eb3 2099 */
tylerwilson 0:3ab1d2d14eb3 2100 int numnatives;
tylerwilson 0:3ab1d2d14eb3 2101 assert(hdr->natives<=hdr->libraries);
tylerwilson 0:3ab1d2d14eb3 2102 numnatives=NUMENTRIES(hdr,natives,libraries);
tylerwilson 0:3ab1d2d14eb3 2103 func=GETENTRY(hdr,natives,0);
tylerwilson 0:3ab1d2d14eb3 2104 for (i=0; i<numnatives && func->address!=0; i++)
tylerwilson 0:3ab1d2d14eb3 2105 func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
tylerwilson 0:3ab1d2d14eb3 2106 if (i<numnatives)
tylerwilson 0:3ab1d2d14eb3 2107 return AMX_ERR_NOTFOUND;
tylerwilson 0:3ab1d2d14eb3 2108 amx->flags|=AMX_FLAG_NTVREG; /* no need to check this again */
tylerwilson 0:3ab1d2d14eb3 2109 } /* if */
tylerwilson 0:3ab1d2d14eb3 2110 assert((amx->flags & AMX_FLAG_VERIFY)==0);
tylerwilson 0:3ab1d2d14eb3 2111
tylerwilson 0:3ab1d2d14eb3 2112 /* set up the registers */
tylerwilson 0:3ab1d2d14eb3 2113 assert(hdr!=NULL && hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 2114 assert(amx->code!=NULL || hdr->overlays!=hdr->nametable);
tylerwilson 0:3ab1d2d14eb3 2115 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 2116 reset_stk=amx->stk;
tylerwilson 0:3ab1d2d14eb3 2117 reset_hea=amx->hea;
tylerwilson 0:3ab1d2d14eb3 2118 amx->error=AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 2119
tylerwilson 0:3ab1d2d14eb3 2120 /* get the start address */
tylerwilson 0:3ab1d2d14eb3 2121 if (index==AMX_EXEC_MAIN) {
tylerwilson 0:3ab1d2d14eb3 2122 if (hdr->cip<0)
tylerwilson 0:3ab1d2d14eb3 2123 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 2124 amx->cip=hdr->cip;
tylerwilson 0:3ab1d2d14eb3 2125 if (hdr->overlays!=hdr->nametable) {
tylerwilson 0:3ab1d2d14eb3 2126 assert(hdr->overlays!=0);
tylerwilson 0:3ab1d2d14eb3 2127 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2128 amx->ovl_index=(int)hdr->cip;
tylerwilson 0:3ab1d2d14eb3 2129 if ((i=amx->overlay(amx,amx->ovl_index))!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 2130 return i;
tylerwilson 0:3ab1d2d14eb3 2131 amx->cip=0;
tylerwilson 0:3ab1d2d14eb3 2132 } /* if */
tylerwilson 0:3ab1d2d14eb3 2133 } else if (index==AMX_EXEC_CONT) {
tylerwilson 0:3ab1d2d14eb3 2134 /* restore registers reset_stk & reset_hea */
tylerwilson 0:3ab1d2d14eb3 2135 reset_stk=amx->reset_stk;
tylerwilson 0:3ab1d2d14eb3 2136 reset_hea=amx->reset_hea;
tylerwilson 0:3ab1d2d14eb3 2137 if (hdr->overlays!=hdr->nametable) {
tylerwilson 0:3ab1d2d14eb3 2138 assert(hdr->overlays!=0);
tylerwilson 0:3ab1d2d14eb3 2139 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2140 if ((i=amx->overlay(amx,amx->ovl_index))!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 2141 return i;
tylerwilson 0:3ab1d2d14eb3 2142 } /* if */
tylerwilson 0:3ab1d2d14eb3 2143 } else if (index<0) {
tylerwilson 0:3ab1d2d14eb3 2144 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 2145 } else {
tylerwilson 0:3ab1d2d14eb3 2146 if (index>=(int)NUMENTRIES(hdr,publics,natives))
tylerwilson 0:3ab1d2d14eb3 2147 return AMX_ERR_INDEX;
tylerwilson 0:3ab1d2d14eb3 2148 func=GETENTRY(hdr,publics,index);
tylerwilson 0:3ab1d2d14eb3 2149 amx->cip=func->address;
tylerwilson 0:3ab1d2d14eb3 2150 if (hdr->overlays!=hdr->nametable) {
tylerwilson 0:3ab1d2d14eb3 2151 assert(hdr->overlays!=0);
tylerwilson 0:3ab1d2d14eb3 2152 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2153 amx->ovl_index=func->address;
tylerwilson 0:3ab1d2d14eb3 2154 if ((i=amx->overlay(amx,amx->ovl_index))!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 2155 return i;
tylerwilson 0:3ab1d2d14eb3 2156 amx->cip=0;
tylerwilson 0:3ab1d2d14eb3 2157 } /* if */
tylerwilson 0:3ab1d2d14eb3 2158 } /* if */
tylerwilson 0:3ab1d2d14eb3 2159 /* check values just copied */
tylerwilson 0:3ab1d2d14eb3 2160 if (amx->stk>amx->stp)
tylerwilson 0:3ab1d2d14eb3 2161 return AMX_ERR_STACKLOW;
tylerwilson 0:3ab1d2d14eb3 2162 if (amx->hea<amx->hlw)
tylerwilson 0:3ab1d2d14eb3 2163 return AMX_ERR_HEAPLOW;
tylerwilson 0:3ab1d2d14eb3 2164 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 2165
tylerwilson 0:3ab1d2d14eb3 2166 /* sanity checks */
tylerwilson 0:3ab1d2d14eb3 2167 assert_static(OP_XCHG==21);
tylerwilson 0:3ab1d2d14eb3 2168 assert_static(OP_SMUL==42);
tylerwilson 0:3ab1d2d14eb3 2169 assert_static(OP_MOVS==64);
tylerwilson 0:3ab1d2d14eb3 2170 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 2171 assert_static(OP_LIDX==81);
tylerwilson 0:3ab1d2d14eb3 2172 assert_static(OP_ZERO_PRI==102);
tylerwilson 0:3ab1d2d14eb3 2173 assert_static(OP_LOAD2==120);
tylerwilson 0:3ab1d2d14eb3 2174 #endif
tylerwilson 0:3ab1d2d14eb3 2175 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 2176 assert_static(OP_LOAD_P_PRI==124);
tylerwilson 0:3ab1d2d14eb3 2177 assert_static(OP_ALIGN_P_PRI==141);
tylerwilson 0:3ab1d2d14eb3 2178 assert_static(OP_BOUNDS_P==174);
tylerwilson 0:3ab1d2d14eb3 2179 #endif
tylerwilson 0:3ab1d2d14eb3 2180 #if PAWN_CELL_SIZE==16
tylerwilson 0:3ab1d2d14eb3 2181 assert_static(sizeof(cell)==2);
tylerwilson 0:3ab1d2d14eb3 2182 #elif PAWN_CELL_SIZE==32
tylerwilson 0:3ab1d2d14eb3 2183 assert_static(sizeof(cell)==4);
tylerwilson 0:3ab1d2d14eb3 2184 #elif PAWN_CELL_SIZE==64
tylerwilson 0:3ab1d2d14eb3 2185 assert_static(sizeof(cell)==8);
tylerwilson 0:3ab1d2d14eb3 2186 #else
tylerwilson 0:3ab1d2d14eb3 2187 #error Unsupported cell size
tylerwilson 0:3ab1d2d14eb3 2188 #endif
tylerwilson 0:3ab1d2d14eb3 2189
tylerwilson 0:3ab1d2d14eb3 2190 if (index!=AMX_EXEC_CONT) {
tylerwilson 0:3ab1d2d14eb3 2191 reset_stk+=amx->paramcount*sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 2192 AMXPUSH(amx->paramcount*sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 2193 amx->paramcount=0; /* push the parameter count to the stack & reset */
tylerwilson 0:3ab1d2d14eb3 2194 AMXPUSH(0); /* return address (for overlays: overlay 0, offset 0) */
tylerwilson 0:3ab1d2d14eb3 2195 } /* if */
tylerwilson 0:3ab1d2d14eb3 2196 /* check stack/heap before starting to run */
tylerwilson 0:3ab1d2d14eb3 2197 if (amx->hea+STKMARGIN>amx->stk)
tylerwilson 0:3ab1d2d14eb3 2198 return AMX_ERR_STACKERR;
tylerwilson 0:3ab1d2d14eb3 2199
tylerwilson 0:3ab1d2d14eb3 2200 #if defined AMX_ALTCORE
tylerwilson 0:3ab1d2d14eb3 2201
tylerwilson 0:3ab1d2d14eb3 2202 /* start running either the ARM or 80x86 assembler abstract machine or the JIT */
tylerwilson 0:3ab1d2d14eb3 2203 #if defined AMX_ASM && defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 2204 if ((amx->flags & AMX_FLAG_JITC)!=0)
tylerwilson 0:3ab1d2d14eb3 2205 i = amx_jit_run(amx,retval,data);
tylerwilson 0:3ab1d2d14eb3 2206 else
tylerwilson 0:3ab1d2d14eb3 2207 i = amx_exec_run(amx,retval,data);
tylerwilson 0:3ab1d2d14eb3 2208 #elif defined AMX_JIT
tylerwilson 0:3ab1d2d14eb3 2209 i = amx_jit_run(amx,retval,data);
tylerwilson 0:3ab1d2d14eb3 2210 #else
tylerwilson 0:3ab1d2d14eb3 2211 /* also for GNU GCC and Intel C/C++ versions */
tylerwilson 0:3ab1d2d14eb3 2212 i = amx_exec_run(amx,retval,data);
tylerwilson 0:3ab1d2d14eb3 2213 #endif
tylerwilson 0:3ab1d2d14eb3 2214 if (i == AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2215 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2216 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2217 } else {
tylerwilson 0:3ab1d2d14eb3 2218 /* remove parameters from the stack; do this the "hard" way, because
tylerwilson 0:3ab1d2d14eb3 2219 * the assembler version has no internal knowledge of the local
tylerwilson 0:3ab1d2d14eb3 2220 * variables, so any "clean" way would be a kludge anyway.
tylerwilson 0:3ab1d2d14eb3 2221 */
tylerwilson 0:3ab1d2d14eb3 2222 amx->stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2223 amx->hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2224 } /* if */
tylerwilson 0:3ab1d2d14eb3 2225 return i;
tylerwilson 0:3ab1d2d14eb3 2226
tylerwilson 0:3ab1d2d14eb3 2227 #else
tylerwilson 0:3ab1d2d14eb3 2228
tylerwilson 0:3ab1d2d14eb3 2229 #define CHKMARGIN() if (hea+STKMARGIN>stk) return AMX_ERR_STACKERR
tylerwilson 0:3ab1d2d14eb3 2230 #define CHKSTACK() if (stk>amx->stp) return AMX_ERR_STACKLOW
tylerwilson 0:3ab1d2d14eb3 2231 #define CHKHEAP() if (hea<amx->hlw) return AMX_ERR_HEAPLOW
tylerwilson 0:3ab1d2d14eb3 2232
tylerwilson 0:3ab1d2d14eb3 2233 /* PUSH() and POP() are defined in terms of the _R() and _W() macros */
tylerwilson 0:3ab1d2d14eb3 2234 #define PUSH(v) ( stk-=sizeof(cell), _W(data,stk,v) )
tylerwilson 0:3ab1d2d14eb3 2235 #define POP(v) ( v=_R(data,stk), stk+=sizeof(cell) )
tylerwilson 0:3ab1d2d14eb3 2236
tylerwilson 0:3ab1d2d14eb3 2237 /* set up registers for ANSI-C core: pri, alt, frm, cip, hea, stk */
tylerwilson 0:3ab1d2d14eb3 2238 pri=amx->pri;
tylerwilson 0:3ab1d2d14eb3 2239 alt=amx->alt;
tylerwilson 0:3ab1d2d14eb3 2240 frm=amx->frm;
tylerwilson 0:3ab1d2d14eb3 2241 cip=(cell *)(amx->code+(int)amx->cip);
tylerwilson 0:3ab1d2d14eb3 2242 hea=amx->hea;
tylerwilson 0:3ab1d2d14eb3 2243 stk=amx->stk;
tylerwilson 0:3ab1d2d14eb3 2244
tylerwilson 0:3ab1d2d14eb3 2245 /* start running */
tylerwilson 0:3ab1d2d14eb3 2246 for ( ;; ) {
tylerwilson 0:3ab1d2d14eb3 2247 op=_RCODE();
tylerwilson 0:3ab1d2d14eb3 2248 switch (GETOPCODE(op)) {
tylerwilson 0:3ab1d2d14eb3 2249 /* core instruction set */
tylerwilson 0:3ab1d2d14eb3 2250 case OP_NOP:
tylerwilson 0:3ab1d2d14eb3 2251 break;
tylerwilson 0:3ab1d2d14eb3 2252 case OP_LOAD_PRI:
tylerwilson 0:3ab1d2d14eb3 2253 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2254 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2255 break;
tylerwilson 0:3ab1d2d14eb3 2256 case OP_LOAD_ALT:
tylerwilson 0:3ab1d2d14eb3 2257 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2258 alt=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2259 break;
tylerwilson 0:3ab1d2d14eb3 2260 case OP_LOAD_S_PRI:
tylerwilson 0:3ab1d2d14eb3 2261 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2262 pri=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2263 break;
tylerwilson 0:3ab1d2d14eb3 2264 case OP_LOAD_S_ALT:
tylerwilson 0:3ab1d2d14eb3 2265 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2266 alt=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2267 break;
tylerwilson 0:3ab1d2d14eb3 2268 case OP_LREF_S_PRI:
tylerwilson 0:3ab1d2d14eb3 2269 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2270 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2271 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2272 break;
tylerwilson 0:3ab1d2d14eb3 2273 case OP_LREF_S_ALT:
tylerwilson 0:3ab1d2d14eb3 2274 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2275 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2276 alt=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2277 break;
tylerwilson 0:3ab1d2d14eb3 2278 case OP_LOAD_I:
tylerwilson 0:3ab1d2d14eb3 2279 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2280 if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2281 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2282 pri=_R(data,pri);
tylerwilson 0:3ab1d2d14eb3 2283 break;
tylerwilson 0:3ab1d2d14eb3 2284 case OP_LODB_I:
tylerwilson 0:3ab1d2d14eb3 2285 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2286 __lodb_i:
tylerwilson 0:3ab1d2d14eb3 2287 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2288 if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2289 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2290 switch ((int)offs) {
tylerwilson 0:3ab1d2d14eb3 2291 case 1:
tylerwilson 0:3ab1d2d14eb3 2292 pri=_R8(data,pri);
tylerwilson 0:3ab1d2d14eb3 2293 break;
tylerwilson 0:3ab1d2d14eb3 2294 case 2:
tylerwilson 0:3ab1d2d14eb3 2295 pri=_R16(data,pri);
tylerwilson 0:3ab1d2d14eb3 2296 break;
tylerwilson 0:3ab1d2d14eb3 2297 case 4:
tylerwilson 0:3ab1d2d14eb3 2298 pri=_R32(data,pri);
tylerwilson 0:3ab1d2d14eb3 2299 break;
tylerwilson 0:3ab1d2d14eb3 2300 } /* switch */
tylerwilson 0:3ab1d2d14eb3 2301 break;
tylerwilson 0:3ab1d2d14eb3 2302 case OP_CONST_PRI:
tylerwilson 0:3ab1d2d14eb3 2303 GETPARAM(pri);
tylerwilson 0:3ab1d2d14eb3 2304 break;
tylerwilson 0:3ab1d2d14eb3 2305 case OP_CONST_ALT:
tylerwilson 0:3ab1d2d14eb3 2306 GETPARAM(alt);
tylerwilson 0:3ab1d2d14eb3 2307 break;
tylerwilson 0:3ab1d2d14eb3 2308 case OP_ADDR_PRI:
tylerwilson 0:3ab1d2d14eb3 2309 GETPARAM(pri);
tylerwilson 0:3ab1d2d14eb3 2310 pri+=frm;
tylerwilson 0:3ab1d2d14eb3 2311 break;
tylerwilson 0:3ab1d2d14eb3 2312 case OP_ADDR_ALT:
tylerwilson 0:3ab1d2d14eb3 2313 GETPARAM(alt);
tylerwilson 0:3ab1d2d14eb3 2314 alt+=frm;
tylerwilson 0:3ab1d2d14eb3 2315 break;
tylerwilson 0:3ab1d2d14eb3 2316 case OP_STOR:
tylerwilson 0:3ab1d2d14eb3 2317 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2318 _W(data,offs,pri);
tylerwilson 0:3ab1d2d14eb3 2319 break;
tylerwilson 0:3ab1d2d14eb3 2320 case OP_STOR_S:
tylerwilson 0:3ab1d2d14eb3 2321 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2322 _W(data,frm+offs,pri);
tylerwilson 0:3ab1d2d14eb3 2323 break;
tylerwilson 0:3ab1d2d14eb3 2324 case OP_SREF_S:
tylerwilson 0:3ab1d2d14eb3 2325 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2326 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2327 _W(data,offs,pri);
tylerwilson 0:3ab1d2d14eb3 2328 break;
tylerwilson 0:3ab1d2d14eb3 2329 case OP_STOR_I:
tylerwilson 0:3ab1d2d14eb3 2330 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2331 if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2332 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2333 _W(data,alt,pri);
tylerwilson 0:3ab1d2d14eb3 2334 break;
tylerwilson 0:3ab1d2d14eb3 2335 case OP_STRB_I:
tylerwilson 0:3ab1d2d14eb3 2336 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2337 __strb_i:
tylerwilson 0:3ab1d2d14eb3 2338 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2339 if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2340 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2341 switch ((int)offs) {
tylerwilson 0:3ab1d2d14eb3 2342 case 1:
tylerwilson 0:3ab1d2d14eb3 2343 _W8(data,alt,pri);
tylerwilson 0:3ab1d2d14eb3 2344 break;
tylerwilson 0:3ab1d2d14eb3 2345 case 2:
tylerwilson 0:3ab1d2d14eb3 2346 _W16(data,alt,pri);
tylerwilson 0:3ab1d2d14eb3 2347 break;
tylerwilson 0:3ab1d2d14eb3 2348 case 4:
tylerwilson 0:3ab1d2d14eb3 2349 _W32(data,alt,pri);
tylerwilson 0:3ab1d2d14eb3 2350 break;
tylerwilson 0:3ab1d2d14eb3 2351 } /* switch */
tylerwilson 0:3ab1d2d14eb3 2352 break;
tylerwilson 0:3ab1d2d14eb3 2353 case OP_ALIGN_PRI:
tylerwilson 0:3ab1d2d14eb3 2354 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2355 #if BYTE_ORDER==LITTLE_ENDIAN
tylerwilson 0:3ab1d2d14eb3 2356 if ((size_t)offs<sizeof(cell))
tylerwilson 0:3ab1d2d14eb3 2357 pri ^= sizeof(cell)-offs;
tylerwilson 0:3ab1d2d14eb3 2358 #endif
tylerwilson 0:3ab1d2d14eb3 2359 break;
tylerwilson 0:3ab1d2d14eb3 2360 case OP_LCTRL:
tylerwilson 0:3ab1d2d14eb3 2361 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2362 switch ((int)offs) {
tylerwilson 0:3ab1d2d14eb3 2363 case 0:
tylerwilson 0:3ab1d2d14eb3 2364 pri=hdr->cod;
tylerwilson 0:3ab1d2d14eb3 2365 break;
tylerwilson 0:3ab1d2d14eb3 2366 case 1:
tylerwilson 0:3ab1d2d14eb3 2367 pri=hdr->dat;
tylerwilson 0:3ab1d2d14eb3 2368 break;
tylerwilson 0:3ab1d2d14eb3 2369 case 2:
tylerwilson 0:3ab1d2d14eb3 2370 pri=hea;
tylerwilson 0:3ab1d2d14eb3 2371 break;
tylerwilson 0:3ab1d2d14eb3 2372 case 3:
tylerwilson 0:3ab1d2d14eb3 2373 pri=amx->stp;
tylerwilson 0:3ab1d2d14eb3 2374 break;
tylerwilson 0:3ab1d2d14eb3 2375 case 4:
tylerwilson 0:3ab1d2d14eb3 2376 pri=stk;
tylerwilson 0:3ab1d2d14eb3 2377 break;
tylerwilson 0:3ab1d2d14eb3 2378 case 5:
tylerwilson 0:3ab1d2d14eb3 2379 pri=frm;
tylerwilson 0:3ab1d2d14eb3 2380 break;
tylerwilson 0:3ab1d2d14eb3 2381 case 6:
tylerwilson 0:3ab1d2d14eb3 2382 pri=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2383 break;
tylerwilson 0:3ab1d2d14eb3 2384 } /* switch */
tylerwilson 0:3ab1d2d14eb3 2385 break;
tylerwilson 0:3ab1d2d14eb3 2386 case OP_SCTRL:
tylerwilson 0:3ab1d2d14eb3 2387 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2388 switch ((int)offs) {
tylerwilson 0:3ab1d2d14eb3 2389 case 0:
tylerwilson 0:3ab1d2d14eb3 2390 case 1:
tylerwilson 0:3ab1d2d14eb3 2391 case 3:
tylerwilson 0:3ab1d2d14eb3 2392 /* cannot change these parameters */
tylerwilson 0:3ab1d2d14eb3 2393 break;
tylerwilson 0:3ab1d2d14eb3 2394 case 2:
tylerwilson 0:3ab1d2d14eb3 2395 hea=pri;
tylerwilson 0:3ab1d2d14eb3 2396 break;
tylerwilson 0:3ab1d2d14eb3 2397 case 4:
tylerwilson 0:3ab1d2d14eb3 2398 stk=pri;
tylerwilson 0:3ab1d2d14eb3 2399 break;
tylerwilson 0:3ab1d2d14eb3 2400 case 5:
tylerwilson 0:3ab1d2d14eb3 2401 frm=pri;
tylerwilson 0:3ab1d2d14eb3 2402 break;
tylerwilson 0:3ab1d2d14eb3 2403 case 6:
tylerwilson 0:3ab1d2d14eb3 2404 cip=(cell *)(amx->code + (int)pri);
tylerwilson 0:3ab1d2d14eb3 2405 break;
tylerwilson 0:3ab1d2d14eb3 2406 } /* switch */
tylerwilson 0:3ab1d2d14eb3 2407 break;
tylerwilson 0:3ab1d2d14eb3 2408 case OP_XCHG:
tylerwilson 0:3ab1d2d14eb3 2409 offs=pri; /* offs is a temporary variable */
tylerwilson 0:3ab1d2d14eb3 2410 pri=alt;
tylerwilson 0:3ab1d2d14eb3 2411 alt=offs;
tylerwilson 0:3ab1d2d14eb3 2412 break;
tylerwilson 0:3ab1d2d14eb3 2413 case OP_PUSH_PRI:
tylerwilson 0:3ab1d2d14eb3 2414 PUSH(pri);
tylerwilson 0:3ab1d2d14eb3 2415 break;
tylerwilson 0:3ab1d2d14eb3 2416 case OP_PUSH_ALT:
tylerwilson 0:3ab1d2d14eb3 2417 PUSH(alt);
tylerwilson 0:3ab1d2d14eb3 2418 break;
tylerwilson 0:3ab1d2d14eb3 2419 case OP_PUSHR_PRI:
tylerwilson 0:3ab1d2d14eb3 2420 PUSH(data+pri);
tylerwilson 0:3ab1d2d14eb3 2421 break;
tylerwilson 0:3ab1d2d14eb3 2422 case OP_POP_PRI:
tylerwilson 0:3ab1d2d14eb3 2423 POP(pri);
tylerwilson 0:3ab1d2d14eb3 2424 break;
tylerwilson 0:3ab1d2d14eb3 2425 case OP_POP_ALT:
tylerwilson 0:3ab1d2d14eb3 2426 POP(alt);
tylerwilson 0:3ab1d2d14eb3 2427 break;
tylerwilson 0:3ab1d2d14eb3 2428 case OP_PICK:
tylerwilson 0:3ab1d2d14eb3 2429 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2430 pri=_R(data,stk+offs);
tylerwilson 0:3ab1d2d14eb3 2431 break;
tylerwilson 0:3ab1d2d14eb3 2432 case OP_STACK:
tylerwilson 0:3ab1d2d14eb3 2433 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2434 alt=stk;
tylerwilson 0:3ab1d2d14eb3 2435 stk+=offs;
tylerwilson 0:3ab1d2d14eb3 2436 CHKMARGIN();
tylerwilson 0:3ab1d2d14eb3 2437 CHKSTACK();
tylerwilson 0:3ab1d2d14eb3 2438 break;
tylerwilson 0:3ab1d2d14eb3 2439 case OP_HEAP:
tylerwilson 0:3ab1d2d14eb3 2440 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2441 alt=hea;
tylerwilson 0:3ab1d2d14eb3 2442 hea+=offs;
tylerwilson 0:3ab1d2d14eb3 2443 CHKMARGIN();
tylerwilson 0:3ab1d2d14eb3 2444 CHKHEAP();
tylerwilson 0:3ab1d2d14eb3 2445 break;
tylerwilson 0:3ab1d2d14eb3 2446 case OP_PROC:
tylerwilson 0:3ab1d2d14eb3 2447 PUSH(frm);
tylerwilson 0:3ab1d2d14eb3 2448 frm=stk;
tylerwilson 0:3ab1d2d14eb3 2449 CHKMARGIN();
tylerwilson 0:3ab1d2d14eb3 2450 break;
tylerwilson 0:3ab1d2d14eb3 2451 case OP_RET:
tylerwilson 0:3ab1d2d14eb3 2452 POP(frm);
tylerwilson 0:3ab1d2d14eb3 2453 POP(offs);
tylerwilson 0:3ab1d2d14eb3 2454 /* verify the return address */
tylerwilson 0:3ab1d2d14eb3 2455 if ((long)offs>=amx->codesize)
tylerwilson 0:3ab1d2d14eb3 2456 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2457 cip=(cell *)(amx->code+(int)offs);
tylerwilson 0:3ab1d2d14eb3 2458 break;
tylerwilson 0:3ab1d2d14eb3 2459 case OP_RETN:
tylerwilson 0:3ab1d2d14eb3 2460 POP(frm);
tylerwilson 0:3ab1d2d14eb3 2461 POP(offs);
tylerwilson 0:3ab1d2d14eb3 2462 /* verify the return address */
tylerwilson 0:3ab1d2d14eb3 2463 if ((long)offs>=amx->codesize)
tylerwilson 0:3ab1d2d14eb3 2464 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2465 cip=(cell *)(amx->code+(int)offs);
tylerwilson 0:3ab1d2d14eb3 2466 stk+=_R(data,stk)+sizeof(cell); /* remove parameters from the stack */
tylerwilson 0:3ab1d2d14eb3 2467 break;
tylerwilson 0:3ab1d2d14eb3 2468 case OP_CALL:
tylerwilson 0:3ab1d2d14eb3 2469 PUSH(((unsigned char *)cip-amx->code)+sizeof(cell));/* skip address */
tylerwilson 0:3ab1d2d14eb3 2470 cip=JUMPREL(cip); /* jump to the address */
tylerwilson 0:3ab1d2d14eb3 2471 break;
tylerwilson 0:3ab1d2d14eb3 2472 case OP_JUMP:
tylerwilson 0:3ab1d2d14eb3 2473 /* since the GETPARAM() macro modifies cip, you cannot
tylerwilson 0:3ab1d2d14eb3 2474 * do GETPARAM(cip) directly */
tylerwilson 0:3ab1d2d14eb3 2475 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2476 break;
tylerwilson 0:3ab1d2d14eb3 2477 case OP_JZER:
tylerwilson 0:3ab1d2d14eb3 2478 if (pri==0)
tylerwilson 0:3ab1d2d14eb3 2479 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2480 else
tylerwilson 0:3ab1d2d14eb3 2481 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2482 break;
tylerwilson 0:3ab1d2d14eb3 2483 case OP_JNZ:
tylerwilson 0:3ab1d2d14eb3 2484 if (pri!=0)
tylerwilson 0:3ab1d2d14eb3 2485 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2486 else
tylerwilson 0:3ab1d2d14eb3 2487 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2488 break;
tylerwilson 0:3ab1d2d14eb3 2489 case OP_SHL:
tylerwilson 0:3ab1d2d14eb3 2490 pri<<=alt;
tylerwilson 0:3ab1d2d14eb3 2491 break;
tylerwilson 0:3ab1d2d14eb3 2492 case OP_SHR:
tylerwilson 0:3ab1d2d14eb3 2493 pri=(ucell)pri >> (int)alt;
tylerwilson 0:3ab1d2d14eb3 2494 break;
tylerwilson 0:3ab1d2d14eb3 2495 case OP_SSHR:
tylerwilson 0:3ab1d2d14eb3 2496 pri>>=alt;
tylerwilson 0:3ab1d2d14eb3 2497 break;
tylerwilson 0:3ab1d2d14eb3 2498 case OP_SHL_C_PRI:
tylerwilson 0:3ab1d2d14eb3 2499 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2500 pri<<=offs;
tylerwilson 0:3ab1d2d14eb3 2501 break;
tylerwilson 0:3ab1d2d14eb3 2502 case OP_SHL_C_ALT:
tylerwilson 0:3ab1d2d14eb3 2503 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2504 alt<<=offs;
tylerwilson 0:3ab1d2d14eb3 2505 break;
tylerwilson 0:3ab1d2d14eb3 2506 case OP_SMUL:
tylerwilson 0:3ab1d2d14eb3 2507 pri*=alt;
tylerwilson 0:3ab1d2d14eb3 2508 break;
tylerwilson 0:3ab1d2d14eb3 2509 case OP_SDIV:
tylerwilson 0:3ab1d2d14eb3 2510 if (pri==0)
tylerwilson 0:3ab1d2d14eb3 2511 ABORT(amx,AMX_ERR_DIVIDE);
tylerwilson 0:3ab1d2d14eb3 2512 /* use floored division and matching remainder */
tylerwilson 0:3ab1d2d14eb3 2513 offs=pri;
tylerwilson 0:3ab1d2d14eb3 2514 #if defined TRUNC_SDIV
tylerwilson 0:3ab1d2d14eb3 2515 pri=alt/offs;
tylerwilson 0:3ab1d2d14eb3 2516 alt=alt%offs;
tylerwilson 0:3ab1d2d14eb3 2517 #else
tylerwilson 0:3ab1d2d14eb3 2518 val=alt; /* portable routine for truncated division */
tylerwilson 0:3ab1d2d14eb3 2519 pri=IABS(alt)/IABS(offs);
tylerwilson 0:3ab1d2d14eb3 2520 if ((cell)(val ^ offs)<0)
tylerwilson 0:3ab1d2d14eb3 2521 pri=-pri;
tylerwilson 0:3ab1d2d14eb3 2522 alt=val-pri*offs; /* calculate the matching remainder */
tylerwilson 0:3ab1d2d14eb3 2523 #endif
tylerwilson 0:3ab1d2d14eb3 2524 /* now "fiddle" with the values to get floored division */
tylerwilson 0:3ab1d2d14eb3 2525 if (alt!=0 && (cell)(alt ^ offs)<0) {
tylerwilson 0:3ab1d2d14eb3 2526 pri--;
tylerwilson 0:3ab1d2d14eb3 2527 alt+=offs;
tylerwilson 0:3ab1d2d14eb3 2528 } /* if */
tylerwilson 0:3ab1d2d14eb3 2529 break;
tylerwilson 0:3ab1d2d14eb3 2530 case OP_ADD:
tylerwilson 0:3ab1d2d14eb3 2531 pri+=alt;
tylerwilson 0:3ab1d2d14eb3 2532 break;
tylerwilson 0:3ab1d2d14eb3 2533 case OP_SUB:
tylerwilson 0:3ab1d2d14eb3 2534 pri=alt-pri;
tylerwilson 0:3ab1d2d14eb3 2535 break;
tylerwilson 0:3ab1d2d14eb3 2536 case OP_AND:
tylerwilson 0:3ab1d2d14eb3 2537 pri&=alt;
tylerwilson 0:3ab1d2d14eb3 2538 break;
tylerwilson 0:3ab1d2d14eb3 2539 case OP_OR:
tylerwilson 0:3ab1d2d14eb3 2540 pri|=alt;
tylerwilson 0:3ab1d2d14eb3 2541 break;
tylerwilson 0:3ab1d2d14eb3 2542 case OP_XOR:
tylerwilson 0:3ab1d2d14eb3 2543 pri^=alt;
tylerwilson 0:3ab1d2d14eb3 2544 break;
tylerwilson 0:3ab1d2d14eb3 2545 case OP_NOT:
tylerwilson 0:3ab1d2d14eb3 2546 pri=!pri;
tylerwilson 0:3ab1d2d14eb3 2547 break;
tylerwilson 0:3ab1d2d14eb3 2548 case OP_NEG:
tylerwilson 0:3ab1d2d14eb3 2549 pri=-pri;
tylerwilson 0:3ab1d2d14eb3 2550 break;
tylerwilson 0:3ab1d2d14eb3 2551 case OP_INVERT:
tylerwilson 0:3ab1d2d14eb3 2552 pri=~pri;
tylerwilson 0:3ab1d2d14eb3 2553 break;
tylerwilson 0:3ab1d2d14eb3 2554 case OP_EQ:
tylerwilson 0:3ab1d2d14eb3 2555 pri= pri==alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2556 break;
tylerwilson 0:3ab1d2d14eb3 2557 case OP_NEQ:
tylerwilson 0:3ab1d2d14eb3 2558 pri= pri!=alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2559 break;
tylerwilson 0:3ab1d2d14eb3 2560 case OP_SLESS:
tylerwilson 0:3ab1d2d14eb3 2561 pri= pri<alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2562 break;
tylerwilson 0:3ab1d2d14eb3 2563 case OP_SLEQ:
tylerwilson 0:3ab1d2d14eb3 2564 pri= pri<=alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2565 break;
tylerwilson 0:3ab1d2d14eb3 2566 case OP_SGRTR:
tylerwilson 0:3ab1d2d14eb3 2567 pri= pri>alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2568 break;
tylerwilson 0:3ab1d2d14eb3 2569 case OP_SGEQ:
tylerwilson 0:3ab1d2d14eb3 2570 pri= pri>=alt ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2571 break;
tylerwilson 0:3ab1d2d14eb3 2572 case OP_INC_PRI:
tylerwilson 0:3ab1d2d14eb3 2573 pri++;
tylerwilson 0:3ab1d2d14eb3 2574 break;
tylerwilson 0:3ab1d2d14eb3 2575 case OP_INC_ALT:
tylerwilson 0:3ab1d2d14eb3 2576 alt++;
tylerwilson 0:3ab1d2d14eb3 2577 break;
tylerwilson 0:3ab1d2d14eb3 2578 case OP_INC_I:
tylerwilson 0:3ab1d2d14eb3 2579 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2580 *(cell *)(data+(int)pri) += 1;
tylerwilson 0:3ab1d2d14eb3 2581 #else
tylerwilson 0:3ab1d2d14eb3 2582 val=_R(data,pri);
tylerwilson 0:3ab1d2d14eb3 2583 _W(data,pri,val+1);
tylerwilson 0:3ab1d2d14eb3 2584 #endif
tylerwilson 0:3ab1d2d14eb3 2585 break;
tylerwilson 0:3ab1d2d14eb3 2586 case OP_DEC_PRI:
tylerwilson 0:3ab1d2d14eb3 2587 pri--;
tylerwilson 0:3ab1d2d14eb3 2588 break;
tylerwilson 0:3ab1d2d14eb3 2589 case OP_DEC_ALT:
tylerwilson 0:3ab1d2d14eb3 2590 alt--;
tylerwilson 0:3ab1d2d14eb3 2591 break;
tylerwilson 0:3ab1d2d14eb3 2592 case OP_DEC_I:
tylerwilson 0:3ab1d2d14eb3 2593 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2594 *(cell *)(data+(int)pri) -= 1;
tylerwilson 0:3ab1d2d14eb3 2595 #else
tylerwilson 0:3ab1d2d14eb3 2596 val=_R(data,pri);
tylerwilson 0:3ab1d2d14eb3 2597 _W(data,pri,val-1);
tylerwilson 0:3ab1d2d14eb3 2598 #endif
tylerwilson 0:3ab1d2d14eb3 2599 break;
tylerwilson 0:3ab1d2d14eb3 2600 case OP_MOVS:
tylerwilson 0:3ab1d2d14eb3 2601 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2602 __movs:
tylerwilson 0:3ab1d2d14eb3 2603 /* verify top & bottom memory addresses, for both source and destination
tylerwilson 0:3ab1d2d14eb3 2604 * addresses
tylerwilson 0:3ab1d2d14eb3 2605 */
tylerwilson 0:3ab1d2d14eb3 2606 if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2607 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2608 if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2609 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2610 if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2611 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2612 if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2613 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2614 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2615 memcpy(data+(int)alt, data+(int)pri, (int)offs);
tylerwilson 0:3ab1d2d14eb3 2616 #else
tylerwilson 0:3ab1d2d14eb3 2617 for (i=0; i+4<offs; i+=4) {
tylerwilson 0:3ab1d2d14eb3 2618 val=_R32(data,pri+i);
tylerwilson 0:3ab1d2d14eb3 2619 _W32(data,alt+i,val);
tylerwilson 0:3ab1d2d14eb3 2620 } /* for */
tylerwilson 0:3ab1d2d14eb3 2621 for ( ; i<offs; i++) {
tylerwilson 0:3ab1d2d14eb3 2622 val=_R8(data,pri+i);
tylerwilson 0:3ab1d2d14eb3 2623 _W8(data,alt+i,val);
tylerwilson 0:3ab1d2d14eb3 2624 } /* for */
tylerwilson 0:3ab1d2d14eb3 2625 #endif
tylerwilson 0:3ab1d2d14eb3 2626 break;
tylerwilson 0:3ab1d2d14eb3 2627 case OP_CMPS:
tylerwilson 0:3ab1d2d14eb3 2628 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2629 __cmps:
tylerwilson 0:3ab1d2d14eb3 2630 /* verify top & bottom memory addresses, for both source and destination
tylerwilson 0:3ab1d2d14eb3 2631 * addresses
tylerwilson 0:3ab1d2d14eb3 2632 */
tylerwilson 0:3ab1d2d14eb3 2633 if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2634 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2635 if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2636 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2637 if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2638 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2639 if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2640 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2641 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2642 pri=memcmp(data+(int)alt, data+(int)pri, (int)offs);
tylerwilson 0:3ab1d2d14eb3 2643 #else
tylerwilson 0:3ab1d2d14eb3 2644 pri=0;
tylerwilson 0:3ab1d2d14eb3 2645 for (i=0; i+4<offs && pri==0; i+=4)
tylerwilson 0:3ab1d2d14eb3 2646 pri=_R32(data,alt+i)-_R32(data,pri+i);
tylerwilson 0:3ab1d2d14eb3 2647 for ( ; i<offs && pri==0; i++)
tylerwilson 0:3ab1d2d14eb3 2648 pri=_R8(data,alt+i)-_R8(data,pri+i);
tylerwilson 0:3ab1d2d14eb3 2649 #endif
tylerwilson 0:3ab1d2d14eb3 2650 break;
tylerwilson 0:3ab1d2d14eb3 2651 case OP_FILL:
tylerwilson 0:3ab1d2d14eb3 2652 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2653 __fill:
tylerwilson 0:3ab1d2d14eb3 2654 /* verify top & bottom memory addresses (destination only) */
tylerwilson 0:3ab1d2d14eb3 2655 if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2656 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2657 if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2658 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2659 for (i=(int)alt; (size_t)offs>=sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell))
tylerwilson 0:3ab1d2d14eb3 2660 _W32(data,i,pri);
tylerwilson 0:3ab1d2d14eb3 2661 break;
tylerwilson 0:3ab1d2d14eb3 2662 case OP_HALT:
tylerwilson 0:3ab1d2d14eb3 2663 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2664 __halt:
tylerwilson 0:3ab1d2d14eb3 2665 if (retval!=NULL)
tylerwilson 0:3ab1d2d14eb3 2666 *retval=pri;
tylerwilson 0:3ab1d2d14eb3 2667 /* store complete status (stk and hea are already set in the ABORT macro) */
tylerwilson 0:3ab1d2d14eb3 2668 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 2669 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 2670 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 2671 amx->cip=(cell)((unsigned char*)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2672 if (offs==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2673 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2674 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 2675 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2676 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2677 return (int)offs;
tylerwilson 0:3ab1d2d14eb3 2678 } /* if */
tylerwilson 0:3ab1d2d14eb3 2679 ABORT(amx,(int)offs);
tylerwilson 0:3ab1d2d14eb3 2680 case OP_BOUNDS:
tylerwilson 0:3ab1d2d14eb3 2681 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2682 if ((ucell)pri>(ucell)offs) {
tylerwilson 0:3ab1d2d14eb3 2683 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2684 ABORT(amx,AMX_ERR_BOUNDS);
tylerwilson 0:3ab1d2d14eb3 2685 } /* if */
tylerwilson 0:3ab1d2d14eb3 2686 break;
tylerwilson 0:3ab1d2d14eb3 2687 case OP_SYSREQ:
tylerwilson 0:3ab1d2d14eb3 2688 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2689 /* save a few registers */
tylerwilson 0:3ab1d2d14eb3 2690 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2691 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 2692 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 2693 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2694 i=amx->callback(amx,offs,&pri,(cell *)(data+(int)stk));
tylerwilson 0:3ab1d2d14eb3 2695 if (i!=AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 2696 if (i==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2697 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 2698 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 2699 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2700 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2701 return i;
tylerwilson 0:3ab1d2d14eb3 2702 } /* if */
tylerwilson 0:3ab1d2d14eb3 2703 ABORT(amx,i);
tylerwilson 0:3ab1d2d14eb3 2704 } /* if */
tylerwilson 0:3ab1d2d14eb3 2705 break;
tylerwilson 0:3ab1d2d14eb3 2706 case OP_SWITCH: {
tylerwilson 0:3ab1d2d14eb3 2707 cell *cptr=JUMPREL(cip)+1;/* +1, to skip the "casetbl" opcode */
tylerwilson 0:3ab1d2d14eb3 2708 assert(*JUMPREL(cip)==OP_CASETBL);
tylerwilson 0:3ab1d2d14eb3 2709 cip=JUMPREL(cptr+1); /* preset to "none-matched" case */
tylerwilson 0:3ab1d2d14eb3 2710 i=(int)*cptr; /* number of records in the case table */
tylerwilson 0:3ab1d2d14eb3 2711 for (cptr+=2; i>0 && *cptr!=pri; i--,cptr+=2)
tylerwilson 0:3ab1d2d14eb3 2712 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 2713 if (i>0)
tylerwilson 0:3ab1d2d14eb3 2714 cip=JUMPREL(cptr+1); /* case found */
tylerwilson 0:3ab1d2d14eb3 2715 break;
tylerwilson 0:3ab1d2d14eb3 2716 } /* case */
tylerwilson 0:3ab1d2d14eb3 2717 case OP_SWAP_PRI:
tylerwilson 0:3ab1d2d14eb3 2718 offs=_R(data,stk);
tylerwilson 0:3ab1d2d14eb3 2719 _W32(data,stk,pri);
tylerwilson 0:3ab1d2d14eb3 2720 pri=offs;
tylerwilson 0:3ab1d2d14eb3 2721 break;
tylerwilson 0:3ab1d2d14eb3 2722 case OP_SWAP_ALT:
tylerwilson 0:3ab1d2d14eb3 2723 offs=_R(data,stk);
tylerwilson 0:3ab1d2d14eb3 2724 _W32(data,stk,alt);
tylerwilson 0:3ab1d2d14eb3 2725 alt=offs;
tylerwilson 0:3ab1d2d14eb3 2726 break;
tylerwilson 0:3ab1d2d14eb3 2727 case OP_BREAK:
tylerwilson 0:3ab1d2d14eb3 2728 assert((amx->flags & AMX_FLAG_VERIFY)==0);
tylerwilson 0:3ab1d2d14eb3 2729 if (amx->debug!=NULL) {
tylerwilson 0:3ab1d2d14eb3 2730 /* store status */
tylerwilson 0:3ab1d2d14eb3 2731 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 2732 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2733 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 2734 amx->cip=(cell)((unsigned char*)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2735 i=amx->debug(amx);
tylerwilson 0:3ab1d2d14eb3 2736 if (i!=AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 2737 if (i==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2738 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 2739 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 2740 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2741 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2742 return i;
tylerwilson 0:3ab1d2d14eb3 2743 } /* if */
tylerwilson 0:3ab1d2d14eb3 2744 ABORT(amx,i);
tylerwilson 0:3ab1d2d14eb3 2745 } /* if */
tylerwilson 0:3ab1d2d14eb3 2746 } /* if */
tylerwilson 0:3ab1d2d14eb3 2747 break;
tylerwilson 0:3ab1d2d14eb3 2748 #if !defined AMX_DONT_RELOCATE
tylerwilson 0:3ab1d2d14eb3 2749 case OP_SYSREQ_D: /* see SYSREQ */
tylerwilson 0:3ab1d2d14eb3 2750 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2751 /* save a few registers */
tylerwilson 0:3ab1d2d14eb3 2752 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2753 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 2754 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 2755 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2756 pri=((AMX_NATIVE)offs)(amx,(cell *)(data+(int)stk));
tylerwilson 0:3ab1d2d14eb3 2757 if (amx->error!=AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 2758 if (amx->error==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2759 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 2760 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 2761 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2762 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2763 return AMX_ERR_SLEEP;
tylerwilson 0:3ab1d2d14eb3 2764 } /* if */
tylerwilson 0:3ab1d2d14eb3 2765 ABORT(amx,amx->error);
tylerwilson 0:3ab1d2d14eb3 2766 } /* if */
tylerwilson 0:3ab1d2d14eb3 2767 break;
tylerwilson 0:3ab1d2d14eb3 2768 #endif
tylerwilson 0:3ab1d2d14eb3 2769 #if !defined AMX_NO_MACRO_INSTR && !defined AMX_DONT_RELOCATE
tylerwilson 0:3ab1d2d14eb3 2770 case OP_SYSREQ_ND: /* see SYSREQ_N */
tylerwilson 0:3ab1d2d14eb3 2771 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2772 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 2773 PUSH(val);
tylerwilson 0:3ab1d2d14eb3 2774 /* save a few registers */
tylerwilson 0:3ab1d2d14eb3 2775 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 2776 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 2777 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 2778 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2779 pri=((AMX_NATIVE)offs)(amx,(cell *)(data+(int)stk));
tylerwilson 0:3ab1d2d14eb3 2780 stk+=val+4;
tylerwilson 0:3ab1d2d14eb3 2781 if (amx->error!=AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 2782 if (amx->error==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 2783 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 2784 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 2785 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 2786 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 2787 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 2788 return AMX_ERR_SLEEP;
tylerwilson 0:3ab1d2d14eb3 2789 } /* if */
tylerwilson 0:3ab1d2d14eb3 2790 ABORT(amx,amx->error);
tylerwilson 0:3ab1d2d14eb3 2791 } /* if */
tylerwilson 0:3ab1d2d14eb3 2792 break;
tylerwilson 0:3ab1d2d14eb3 2793 #endif
tylerwilson 0:3ab1d2d14eb3 2794
tylerwilson 0:3ab1d2d14eb3 2795 /* overlay instructions */
tylerwilson 0:3ab1d2d14eb3 2796 #if !defined AMX_NO_OVERLAY
tylerwilson 0:3ab1d2d14eb3 2797 case OP_CALL_OVL:
tylerwilson 0:3ab1d2d14eb3 2798 offs=(unsigned char *)cip-amx->code+sizeof(cell); /* skip address */
tylerwilson 0:3ab1d2d14eb3 2799 assert(offs>=0 && offs<(1<<(sizeof(cell)*4)));
tylerwilson 0:3ab1d2d14eb3 2800 PUSH((offs<<(sizeof(cell)*4)) | amx->ovl_index);
tylerwilson 0:3ab1d2d14eb3 2801 amx->ovl_index=(int)*cip;
tylerwilson 0:3ab1d2d14eb3 2802 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2803 if ((i=amx->overlay(amx,amx->ovl_index))!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 2804 ABORT(amx,i);
tylerwilson 0:3ab1d2d14eb3 2805 cip=(cell*)amx->code;
tylerwilson 0:3ab1d2d14eb3 2806 break;
tylerwilson 0:3ab1d2d14eb3 2807 case OP_RETN_OVL:
tylerwilson 0:3ab1d2d14eb3 2808 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2809 POP(frm);
tylerwilson 0:3ab1d2d14eb3 2810 POP(offs);
tylerwilson 0:3ab1d2d14eb3 2811 amx->ovl_index=offs & (((ucell)~0)>>4*sizeof(cell));
tylerwilson 0:3ab1d2d14eb3 2812 offs=(ucell)offs >> (sizeof(cell)*4);
tylerwilson 0:3ab1d2d14eb3 2813 /* verify the index */
tylerwilson 0:3ab1d2d14eb3 2814 stk+=_R(data,stk)+sizeof(cell); /* remove parameters from the stack */
tylerwilson 0:3ab1d2d14eb3 2815 i=amx->overlay(amx,amx->ovl_index); /* reload overlay */
tylerwilson 0:3ab1d2d14eb3 2816 if (i!=AMX_ERR_NONE || (long)offs>=amx->codesize)
tylerwilson 0:3ab1d2d14eb3 2817 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2818 cip=(cell *)(amx->code+(int)offs);
tylerwilson 0:3ab1d2d14eb3 2819 break;
tylerwilson 0:3ab1d2d14eb3 2820 case OP_SWITCH_OVL: {
tylerwilson 0:3ab1d2d14eb3 2821 cell *cptr=JUMPREL(cip)+1; /* +1, to skip the "icasetbl" opcode */
tylerwilson 0:3ab1d2d14eb3 2822 assert(*JUMPREL(cip)==OP_CASETBL_OVL);
tylerwilson 0:3ab1d2d14eb3 2823 amx->ovl_index=*(cptr+1); /* preset to "none-matched" case */
tylerwilson 0:3ab1d2d14eb3 2824 i=(int)*cptr; /* number of records in the case table */
tylerwilson 0:3ab1d2d14eb3 2825 for (cptr+=2; i>0 && *cptr!=pri; i--,cptr+=2)
tylerwilson 0:3ab1d2d14eb3 2826 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 2827 if (i>0)
tylerwilson 0:3ab1d2d14eb3 2828 amx->ovl_index=*(cptr+1); /* case found */
tylerwilson 0:3ab1d2d14eb3 2829 assert(amx->overlay!=NULL);
tylerwilson 0:3ab1d2d14eb3 2830 if ((i=amx->overlay(amx,amx->ovl_index))!=AMX_ERR_NONE)
tylerwilson 0:3ab1d2d14eb3 2831 ABORT(amx,i);
tylerwilson 0:3ab1d2d14eb3 2832 cip=(cell*)amx->code;
tylerwilson 0:3ab1d2d14eb3 2833 break;
tylerwilson 0:3ab1d2d14eb3 2834 } /* case */
tylerwilson 0:3ab1d2d14eb3 2835 #endif
tylerwilson 0:3ab1d2d14eb3 2836
tylerwilson 0:3ab1d2d14eb3 2837 /* supplemental and macro instructions */
tylerwilson 0:3ab1d2d14eb3 2838 #if !defined AMX_NO_MACRO_INSTR
tylerwilson 0:3ab1d2d14eb3 2839 case OP_LIDX:
tylerwilson 0:3ab1d2d14eb3 2840 offs=pri*sizeof(cell)+alt;
tylerwilson 0:3ab1d2d14eb3 2841 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2842 if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2843 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2844 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2845 break;
tylerwilson 0:3ab1d2d14eb3 2846 case OP_LIDX_B:
tylerwilson 0:3ab1d2d14eb3 2847 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2848 offs=(pri << (int)offs)+alt;
tylerwilson 0:3ab1d2d14eb3 2849 /* verify address */
tylerwilson 0:3ab1d2d14eb3 2850 if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 2851 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 2852 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2853 break;
tylerwilson 0:3ab1d2d14eb3 2854 case OP_IDXADDR:
tylerwilson 0:3ab1d2d14eb3 2855 pri=pri*sizeof(cell)+alt;
tylerwilson 0:3ab1d2d14eb3 2856 break;
tylerwilson 0:3ab1d2d14eb3 2857 case OP_IDXADDR_B:
tylerwilson 0:3ab1d2d14eb3 2858 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2859 pri=(pri << (int)offs)+alt;
tylerwilson 0:3ab1d2d14eb3 2860 break;
tylerwilson 0:3ab1d2d14eb3 2861 case OP_PUSH_C:
tylerwilson 0:3ab1d2d14eb3 2862 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2863 PUSH(offs);
tylerwilson 0:3ab1d2d14eb3 2864 break;
tylerwilson 0:3ab1d2d14eb3 2865 case OP_PUSH:
tylerwilson 0:3ab1d2d14eb3 2866 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2867 PUSH(_R(data,offs));
tylerwilson 0:3ab1d2d14eb3 2868 break;
tylerwilson 0:3ab1d2d14eb3 2869 case OP_PUSH_S:
tylerwilson 0:3ab1d2d14eb3 2870 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2871 PUSH(_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 2872 break;
tylerwilson 0:3ab1d2d14eb3 2873 case OP_PUSH_ADR:
tylerwilson 0:3ab1d2d14eb3 2874 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2875 PUSH(frm+offs);
tylerwilson 0:3ab1d2d14eb3 2876 break;
tylerwilson 0:3ab1d2d14eb3 2877 case OP_PUSHR_C:
tylerwilson 0:3ab1d2d14eb3 2878 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2879 PUSH(data+offs);
tylerwilson 0:3ab1d2d14eb3 2880 break;
tylerwilson 0:3ab1d2d14eb3 2881 case OP_PUSHR_S:
tylerwilson 0:3ab1d2d14eb3 2882 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2883 PUSH(data+_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 2884 break;
tylerwilson 0:3ab1d2d14eb3 2885 case OP_PUSHR_ADR:
tylerwilson 0:3ab1d2d14eb3 2886 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2887 PUSH(data+frm+offs);
tylerwilson 0:3ab1d2d14eb3 2888 break;
tylerwilson 0:3ab1d2d14eb3 2889 case OP_JEQ:
tylerwilson 0:3ab1d2d14eb3 2890 if (pri==alt)
tylerwilson 0:3ab1d2d14eb3 2891 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2892 else
tylerwilson 0:3ab1d2d14eb3 2893 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2894 break;
tylerwilson 0:3ab1d2d14eb3 2895 case OP_JNEQ:
tylerwilson 0:3ab1d2d14eb3 2896 if (pri!=alt)
tylerwilson 0:3ab1d2d14eb3 2897 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2898 else
tylerwilson 0:3ab1d2d14eb3 2899 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2900 break;
tylerwilson 0:3ab1d2d14eb3 2901 case OP_JSLESS:
tylerwilson 0:3ab1d2d14eb3 2902 if (pri<alt)
tylerwilson 0:3ab1d2d14eb3 2903 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2904 else
tylerwilson 0:3ab1d2d14eb3 2905 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2906 break;
tylerwilson 0:3ab1d2d14eb3 2907 case OP_JSLEQ:
tylerwilson 0:3ab1d2d14eb3 2908 if (pri<=alt)
tylerwilson 0:3ab1d2d14eb3 2909 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2910 else
tylerwilson 0:3ab1d2d14eb3 2911 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2912 break;
tylerwilson 0:3ab1d2d14eb3 2913 case OP_JSGRTR:
tylerwilson 0:3ab1d2d14eb3 2914 if (pri>alt)
tylerwilson 0:3ab1d2d14eb3 2915 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2916 else
tylerwilson 0:3ab1d2d14eb3 2917 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2918 break;
tylerwilson 0:3ab1d2d14eb3 2919 case OP_JSGEQ:
tylerwilson 0:3ab1d2d14eb3 2920 if (pri>=alt)
tylerwilson 0:3ab1d2d14eb3 2921 cip=JUMPREL(cip);
tylerwilson 0:3ab1d2d14eb3 2922 else
tylerwilson 0:3ab1d2d14eb3 2923 SKIPPARAM(1);
tylerwilson 0:3ab1d2d14eb3 2924 break;
tylerwilson 0:3ab1d2d14eb3 2925 case OP_SDIV_INV:
tylerwilson 0:3ab1d2d14eb3 2926 if (alt==0)
tylerwilson 0:3ab1d2d14eb3 2927 ABORT(amx,AMX_ERR_DIVIDE);
tylerwilson 0:3ab1d2d14eb3 2928 /* use floored division and matching remainder */
tylerwilson 0:3ab1d2d14eb3 2929 offs=alt;
tylerwilson 0:3ab1d2d14eb3 2930 #if defined TRUNC_SDIV
tylerwilson 0:3ab1d2d14eb3 2931 pri=pri/offs;
tylerwilson 0:3ab1d2d14eb3 2932 alt=pri%offs;
tylerwilson 0:3ab1d2d14eb3 2933 #else
tylerwilson 0:3ab1d2d14eb3 2934 val=pri; /* portable routine for truncated division */
tylerwilson 0:3ab1d2d14eb3 2935 pri=IABS(pri)/IABS(offs);
tylerwilson 0:3ab1d2d14eb3 2936 if ((cell)(val ^ offs)<0)
tylerwilson 0:3ab1d2d14eb3 2937 pri=-pri;
tylerwilson 0:3ab1d2d14eb3 2938 alt=val-pri*offs; /* calculate the matching remainder */
tylerwilson 0:3ab1d2d14eb3 2939 #endif
tylerwilson 0:3ab1d2d14eb3 2940 /* now "fiddle" with the values to get floored division */
tylerwilson 0:3ab1d2d14eb3 2941 if (alt!=0 && (cell)(alt ^ offs)<0) {
tylerwilson 0:3ab1d2d14eb3 2942 pri--;
tylerwilson 0:3ab1d2d14eb3 2943 alt+=offs;
tylerwilson 0:3ab1d2d14eb3 2944 } /* if */
tylerwilson 0:3ab1d2d14eb3 2945 break;
tylerwilson 0:3ab1d2d14eb3 2946 case OP_SUB_INV:
tylerwilson 0:3ab1d2d14eb3 2947 pri-=alt;
tylerwilson 0:3ab1d2d14eb3 2948 break;
tylerwilson 0:3ab1d2d14eb3 2949 case OP_ADD_C:
tylerwilson 0:3ab1d2d14eb3 2950 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2951 pri+=offs;
tylerwilson 0:3ab1d2d14eb3 2952 break;
tylerwilson 0:3ab1d2d14eb3 2953 case OP_SMUL_C:
tylerwilson 0:3ab1d2d14eb3 2954 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2955 pri*=offs;
tylerwilson 0:3ab1d2d14eb3 2956 break;
tylerwilson 0:3ab1d2d14eb3 2957 case OP_ZERO_PRI:
tylerwilson 0:3ab1d2d14eb3 2958 pri=0;
tylerwilson 0:3ab1d2d14eb3 2959 break;
tylerwilson 0:3ab1d2d14eb3 2960 case OP_ZERO_ALT:
tylerwilson 0:3ab1d2d14eb3 2961 alt=0;
tylerwilson 0:3ab1d2d14eb3 2962 break;
tylerwilson 0:3ab1d2d14eb3 2963 case OP_ZERO:
tylerwilson 0:3ab1d2d14eb3 2964 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2965 _W(data,offs,0);
tylerwilson 0:3ab1d2d14eb3 2966 break;
tylerwilson 0:3ab1d2d14eb3 2967 case OP_ZERO_S:
tylerwilson 0:3ab1d2d14eb3 2968 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2969 _W(data,frm+offs,0);
tylerwilson 0:3ab1d2d14eb3 2970 break;
tylerwilson 0:3ab1d2d14eb3 2971 case OP_EQ_C_PRI:
tylerwilson 0:3ab1d2d14eb3 2972 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2973 pri= pri==offs ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2974 break;
tylerwilson 0:3ab1d2d14eb3 2975 case OP_EQ_C_ALT:
tylerwilson 0:3ab1d2d14eb3 2976 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2977 pri= alt==offs ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 2978 break;
tylerwilson 0:3ab1d2d14eb3 2979 case OP_INC:
tylerwilson 0:3ab1d2d14eb3 2980 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2981 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2982 *(cell *)(data+(int)offs) += 1;
tylerwilson 0:3ab1d2d14eb3 2983 #else
tylerwilson 0:3ab1d2d14eb3 2984 val=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 2985 _W(data,offs,val+1);
tylerwilson 0:3ab1d2d14eb3 2986 #endif
tylerwilson 0:3ab1d2d14eb3 2987 break;
tylerwilson 0:3ab1d2d14eb3 2988 case OP_INC_S:
tylerwilson 0:3ab1d2d14eb3 2989 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2990 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 2991 *(cell *)(data+(int)(frm+offs)) += 1;
tylerwilson 0:3ab1d2d14eb3 2992 #else
tylerwilson 0:3ab1d2d14eb3 2993 val=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 2994 _W(data,frm+offs,val+1);
tylerwilson 0:3ab1d2d14eb3 2995 #endif
tylerwilson 0:3ab1d2d14eb3 2996 break;
tylerwilson 0:3ab1d2d14eb3 2997 case OP_DEC:
tylerwilson 0:3ab1d2d14eb3 2998 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 2999 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3000 *(cell *)(data+(int)offs) -= 1;
tylerwilson 0:3ab1d2d14eb3 3001 #else
tylerwilson 0:3ab1d2d14eb3 3002 val=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3003 _W(data,offs,val-1);
tylerwilson 0:3ab1d2d14eb3 3004 #endif
tylerwilson 0:3ab1d2d14eb3 3005 break;
tylerwilson 0:3ab1d2d14eb3 3006 case OP_DEC_S:
tylerwilson 0:3ab1d2d14eb3 3007 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3008 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3009 *(cell *)(data+(int)(frm+offs)) -= 1;
tylerwilson 0:3ab1d2d14eb3 3010 #else
tylerwilson 0:3ab1d2d14eb3 3011 val=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3012 _W(data,frm+offs,val-1);
tylerwilson 0:3ab1d2d14eb3 3013 #endif
tylerwilson 0:3ab1d2d14eb3 3014 break;
tylerwilson 0:3ab1d2d14eb3 3015 case OP_SYSREQ_N:
tylerwilson 0:3ab1d2d14eb3 3016 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3017 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3018 PUSH(val);
tylerwilson 0:3ab1d2d14eb3 3019 /* save a few registers */
tylerwilson 0:3ab1d2d14eb3 3020 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 3021 amx->hea=hea;
tylerwilson 0:3ab1d2d14eb3 3022 amx->frm=frm;
tylerwilson 0:3ab1d2d14eb3 3023 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 3024 i=amx->callback(amx,offs,&pri,(cell *)(data+(int)stk));
tylerwilson 0:3ab1d2d14eb3 3025 stk+=val+4;
tylerwilson 0:3ab1d2d14eb3 3026 if (i!=AMX_ERR_NONE) {
tylerwilson 0:3ab1d2d14eb3 3027 if (i==AMX_ERR_SLEEP) {
tylerwilson 0:3ab1d2d14eb3 3028 amx->pri=pri;
tylerwilson 0:3ab1d2d14eb3 3029 amx->alt=alt;
tylerwilson 0:3ab1d2d14eb3 3030 amx->stk=stk;
tylerwilson 0:3ab1d2d14eb3 3031 amx->reset_stk=reset_stk;
tylerwilson 0:3ab1d2d14eb3 3032 amx->reset_hea=reset_hea;
tylerwilson 0:3ab1d2d14eb3 3033 return i;
tylerwilson 0:3ab1d2d14eb3 3034 } /* if */
tylerwilson 0:3ab1d2d14eb3 3035 ABORT(amx,i);
tylerwilson 0:3ab1d2d14eb3 3036 } /* if */
tylerwilson 0:3ab1d2d14eb3 3037 break;
tylerwilson 0:3ab1d2d14eb3 3038 case OP_PUSHM_C:
tylerwilson 0:3ab1d2d14eb3 3039 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3040 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3041 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3042 PUSH(offs);
tylerwilson 0:3ab1d2d14eb3 3043 } /* while */
tylerwilson 0:3ab1d2d14eb3 3044 break;
tylerwilson 0:3ab1d2d14eb3 3045 case OP_PUSHM:
tylerwilson 0:3ab1d2d14eb3 3046 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3047 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3048 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3049 PUSH(_R(data,offs));
tylerwilson 0:3ab1d2d14eb3 3050 } /* while */
tylerwilson 0:3ab1d2d14eb3 3051 break;
tylerwilson 0:3ab1d2d14eb3 3052 case OP_PUSHM_S:
tylerwilson 0:3ab1d2d14eb3 3053 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3054 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3055 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3056 PUSH(_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3057 } /* while */
tylerwilson 0:3ab1d2d14eb3 3058 break;
tylerwilson 0:3ab1d2d14eb3 3059 case OP_PUSHM_ADR:
tylerwilson 0:3ab1d2d14eb3 3060 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3061 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3062 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3063 PUSH(frm+offs);
tylerwilson 0:3ab1d2d14eb3 3064 } /* while */
tylerwilson 0:3ab1d2d14eb3 3065 break;
tylerwilson 0:3ab1d2d14eb3 3066 case OP_PUSHRM_C:
tylerwilson 0:3ab1d2d14eb3 3067 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3068 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3069 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3070 PUSH(data+offs);
tylerwilson 0:3ab1d2d14eb3 3071 } /* while */
tylerwilson 0:3ab1d2d14eb3 3072 break;
tylerwilson 0:3ab1d2d14eb3 3073 case OP_PUSHRM_S:
tylerwilson 0:3ab1d2d14eb3 3074 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3075 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3076 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3077 PUSH(data+_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3078 } /* while */
tylerwilson 0:3ab1d2d14eb3 3079 break;
tylerwilson 0:3ab1d2d14eb3 3080 case OP_PUSHRM_ADR:
tylerwilson 0:3ab1d2d14eb3 3081 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3082 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3083 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3084 PUSH(data+frm+offs);
tylerwilson 0:3ab1d2d14eb3 3085 } /* while */
tylerwilson 0:3ab1d2d14eb3 3086 break;
tylerwilson 0:3ab1d2d14eb3 3087 case OP_LOAD2:
tylerwilson 0:3ab1d2d14eb3 3088 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3089 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3090 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3091 alt=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3092 break;
tylerwilson 0:3ab1d2d14eb3 3093 case OP_LOAD2_S:
tylerwilson 0:3ab1d2d14eb3 3094 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3095 pri=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3096 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3097 alt=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3098 break;
tylerwilson 0:3ab1d2d14eb3 3099 case OP_CONST:
tylerwilson 0:3ab1d2d14eb3 3100 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3101 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3102 _W32(data,offs,val);
tylerwilson 0:3ab1d2d14eb3 3103 break;
tylerwilson 0:3ab1d2d14eb3 3104 case OP_CONST_S:
tylerwilson 0:3ab1d2d14eb3 3105 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3106 GETPARAM(val);
tylerwilson 0:3ab1d2d14eb3 3107 _W32(data,frm+offs,val);
tylerwilson 0:3ab1d2d14eb3 3108 break;
tylerwilson 0:3ab1d2d14eb3 3109 #endif /* AMX_NO_MACRO_INSTR */
tylerwilson 0:3ab1d2d14eb3 3110
tylerwilson 0:3ab1d2d14eb3 3111 #if !defined AMX_NO_PACKED_OPC
tylerwilson 0:3ab1d2d14eb3 3112 case OP_LOAD_P_PRI:
tylerwilson 0:3ab1d2d14eb3 3113 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3114 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3115 break;
tylerwilson 0:3ab1d2d14eb3 3116 case OP_LOAD_P_ALT:
tylerwilson 0:3ab1d2d14eb3 3117 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3118 alt=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3119 break;
tylerwilson 0:3ab1d2d14eb3 3120 case OP_LOAD_P_S_PRI:
tylerwilson 0:3ab1d2d14eb3 3121 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3122 pri=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3123 break;
tylerwilson 0:3ab1d2d14eb3 3124 case OP_LOAD_P_S_ALT:
tylerwilson 0:3ab1d2d14eb3 3125 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3126 alt=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3127 break;
tylerwilson 0:3ab1d2d14eb3 3128 case OP_LREF_P_S_PRI:
tylerwilson 0:3ab1d2d14eb3 3129 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3130 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3131 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3132 break;
tylerwilson 0:3ab1d2d14eb3 3133 case OP_LREF_P_S_ALT:
tylerwilson 0:3ab1d2d14eb3 3134 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3135 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3136 alt=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3137 break;
tylerwilson 0:3ab1d2d14eb3 3138 case OP_LODB_P_I:
tylerwilson 0:3ab1d2d14eb3 3139 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3140 goto __lodb_i;
tylerwilson 0:3ab1d2d14eb3 3141 case OP_CONST_P_PRI:
tylerwilson 0:3ab1d2d14eb3 3142 GETPARAM_P(pri,op);
tylerwilson 0:3ab1d2d14eb3 3143 break;
tylerwilson 0:3ab1d2d14eb3 3144 case OP_CONST_P_ALT:
tylerwilson 0:3ab1d2d14eb3 3145 GETPARAM_P(alt,op);
tylerwilson 0:3ab1d2d14eb3 3146 break;
tylerwilson 0:3ab1d2d14eb3 3147 case OP_ADDR_P_PRI:
tylerwilson 0:3ab1d2d14eb3 3148 GETPARAM_P(pri,op);
tylerwilson 0:3ab1d2d14eb3 3149 pri+=frm;
tylerwilson 0:3ab1d2d14eb3 3150 break;
tylerwilson 0:3ab1d2d14eb3 3151 case OP_ADDR_P_ALT:
tylerwilson 0:3ab1d2d14eb3 3152 GETPARAM_P(alt,op);
tylerwilson 0:3ab1d2d14eb3 3153 alt+=frm;
tylerwilson 0:3ab1d2d14eb3 3154 break;
tylerwilson 0:3ab1d2d14eb3 3155 case OP_STOR_P:
tylerwilson 0:3ab1d2d14eb3 3156 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3157 _W(data,offs,pri);
tylerwilson 0:3ab1d2d14eb3 3158 break;
tylerwilson 0:3ab1d2d14eb3 3159 case OP_STOR_P_S:
tylerwilson 0:3ab1d2d14eb3 3160 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3161 _W(data,frm+offs,pri);
tylerwilson 0:3ab1d2d14eb3 3162 break;
tylerwilson 0:3ab1d2d14eb3 3163 case OP_SREF_P_S:
tylerwilson 0:3ab1d2d14eb3 3164 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3165 offs=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3166 _W(data,offs,pri);
tylerwilson 0:3ab1d2d14eb3 3167 break;
tylerwilson 0:3ab1d2d14eb3 3168 case OP_STRB_P_I:
tylerwilson 0:3ab1d2d14eb3 3169 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3170 goto __strb_i;
tylerwilson 0:3ab1d2d14eb3 3171 case OP_LIDX_P_B:
tylerwilson 0:3ab1d2d14eb3 3172 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3173 offs=(pri << (int)offs)+alt;
tylerwilson 0:3ab1d2d14eb3 3174 /* verify address */
tylerwilson 0:3ab1d2d14eb3 3175 if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
tylerwilson 0:3ab1d2d14eb3 3176 ABORT(amx,AMX_ERR_MEMACCESS);
tylerwilson 0:3ab1d2d14eb3 3177 pri=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3178 break;
tylerwilson 0:3ab1d2d14eb3 3179 case OP_IDXADDR_P_B:
tylerwilson 0:3ab1d2d14eb3 3180 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3181 pri=(pri << (int)offs)+alt;
tylerwilson 0:3ab1d2d14eb3 3182 break;
tylerwilson 0:3ab1d2d14eb3 3183 case OP_ALIGN_P_PRI:
tylerwilson 0:3ab1d2d14eb3 3184 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3185 #if BYTE_ORDER==LITTLE_ENDIAN
tylerwilson 0:3ab1d2d14eb3 3186 if ((size_t)offs<sizeof(cell))
tylerwilson 0:3ab1d2d14eb3 3187 pri ^= sizeof(cell)-offs;
tylerwilson 0:3ab1d2d14eb3 3188 #endif
tylerwilson 0:3ab1d2d14eb3 3189 break;
tylerwilson 0:3ab1d2d14eb3 3190 case OP_PUSH_P_C:
tylerwilson 0:3ab1d2d14eb3 3191 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3192 PUSH(offs);
tylerwilson 0:3ab1d2d14eb3 3193 break;
tylerwilson 0:3ab1d2d14eb3 3194 case OP_PUSH_P:
tylerwilson 0:3ab1d2d14eb3 3195 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3196 PUSH(_R(data,offs));
tylerwilson 0:3ab1d2d14eb3 3197 break;
tylerwilson 0:3ab1d2d14eb3 3198 case OP_PUSH_P_S:
tylerwilson 0:3ab1d2d14eb3 3199 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3200 PUSH(_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3201 break;
tylerwilson 0:3ab1d2d14eb3 3202 case OP_PUSH_P_ADR:
tylerwilson 0:3ab1d2d14eb3 3203 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3204 PUSH(frm+offs);
tylerwilson 0:3ab1d2d14eb3 3205 break;
tylerwilson 0:3ab1d2d14eb3 3206 case OP_PUSHR_P_C:
tylerwilson 0:3ab1d2d14eb3 3207 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3208 PUSH(data+offs);
tylerwilson 0:3ab1d2d14eb3 3209 break;
tylerwilson 0:3ab1d2d14eb3 3210 case OP_PUSHR_P_S:
tylerwilson 0:3ab1d2d14eb3 3211 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3212 PUSH(data+_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3213 break;
tylerwilson 0:3ab1d2d14eb3 3214 case OP_PUSHR_P_ADR:
tylerwilson 0:3ab1d2d14eb3 3215 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3216 PUSH(data+frm+offs);
tylerwilson 0:3ab1d2d14eb3 3217 break;
tylerwilson 0:3ab1d2d14eb3 3218 case OP_PUSHM_P:
tylerwilson 0:3ab1d2d14eb3 3219 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3220 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3221 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3222 PUSH(_R(data,offs));
tylerwilson 0:3ab1d2d14eb3 3223 } /* while */
tylerwilson 0:3ab1d2d14eb3 3224 break;
tylerwilson 0:3ab1d2d14eb3 3225 case OP_PUSHM_P_S:
tylerwilson 0:3ab1d2d14eb3 3226 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3227 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3228 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3229 PUSH(_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3230 } /* while */
tylerwilson 0:3ab1d2d14eb3 3231 break;
tylerwilson 0:3ab1d2d14eb3 3232 case OP_PUSHM_P_C:
tylerwilson 0:3ab1d2d14eb3 3233 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3234 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3235 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3236 PUSH(offs);
tylerwilson 0:3ab1d2d14eb3 3237 } /* while */
tylerwilson 0:3ab1d2d14eb3 3238 break;
tylerwilson 0:3ab1d2d14eb3 3239 case OP_PUSHM_P_ADR:
tylerwilson 0:3ab1d2d14eb3 3240 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3241 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3242 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3243 PUSH(frm+offs);
tylerwilson 0:3ab1d2d14eb3 3244 } /* while */
tylerwilson 0:3ab1d2d14eb3 3245 break;
tylerwilson 0:3ab1d2d14eb3 3246 case OP_PUSHRM_P_C:
tylerwilson 0:3ab1d2d14eb3 3247 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3248 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3249 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3250 PUSH(data+offs);
tylerwilson 0:3ab1d2d14eb3 3251 } /* while */
tylerwilson 0:3ab1d2d14eb3 3252 break;
tylerwilson 0:3ab1d2d14eb3 3253 case OP_PUSHRM_P_S:
tylerwilson 0:3ab1d2d14eb3 3254 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3255 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3256 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3257 PUSH(data+_R(data,frm+offs));
tylerwilson 0:3ab1d2d14eb3 3258 } /* while */
tylerwilson 0:3ab1d2d14eb3 3259 break;
tylerwilson 0:3ab1d2d14eb3 3260 case OP_PUSHRM_P_ADR:
tylerwilson 0:3ab1d2d14eb3 3261 GETPARAM_P(val,op);
tylerwilson 0:3ab1d2d14eb3 3262 while (val--) {
tylerwilson 0:3ab1d2d14eb3 3263 GETPARAM(offs);
tylerwilson 0:3ab1d2d14eb3 3264 PUSH(data+frm+offs);
tylerwilson 0:3ab1d2d14eb3 3265 } /* while */
tylerwilson 0:3ab1d2d14eb3 3266 break;
tylerwilson 0:3ab1d2d14eb3 3267 case OP_STACK_P:
tylerwilson 0:3ab1d2d14eb3 3268 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3269 alt=stk;
tylerwilson 0:3ab1d2d14eb3 3270 stk+=offs;
tylerwilson 0:3ab1d2d14eb3 3271 CHKMARGIN();
tylerwilson 0:3ab1d2d14eb3 3272 CHKSTACK();
tylerwilson 0:3ab1d2d14eb3 3273 break;
tylerwilson 0:3ab1d2d14eb3 3274 case OP_HEAP_P:
tylerwilson 0:3ab1d2d14eb3 3275 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3276 alt=hea;
tylerwilson 0:3ab1d2d14eb3 3277 hea+=offs;
tylerwilson 0:3ab1d2d14eb3 3278 CHKMARGIN();
tylerwilson 0:3ab1d2d14eb3 3279 CHKHEAP();
tylerwilson 0:3ab1d2d14eb3 3280 break;
tylerwilson 0:3ab1d2d14eb3 3281 case OP_SHL_P_C_PRI:
tylerwilson 0:3ab1d2d14eb3 3282 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3283 pri<<=offs;
tylerwilson 0:3ab1d2d14eb3 3284 break;
tylerwilson 0:3ab1d2d14eb3 3285 case OP_SHL_P_C_ALT:
tylerwilson 0:3ab1d2d14eb3 3286 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3287 alt<<=offs;
tylerwilson 0:3ab1d2d14eb3 3288 break;
tylerwilson 0:3ab1d2d14eb3 3289 case OP_ADD_P_C:
tylerwilson 0:3ab1d2d14eb3 3290 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3291 pri+=offs;
tylerwilson 0:3ab1d2d14eb3 3292 break;
tylerwilson 0:3ab1d2d14eb3 3293 case OP_SMUL_P_C:
tylerwilson 0:3ab1d2d14eb3 3294 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3295 pri*=offs;
tylerwilson 0:3ab1d2d14eb3 3296 break;
tylerwilson 0:3ab1d2d14eb3 3297 case OP_ZERO_P:
tylerwilson 0:3ab1d2d14eb3 3298 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3299 _W(data,offs,0);
tylerwilson 0:3ab1d2d14eb3 3300 break;
tylerwilson 0:3ab1d2d14eb3 3301 case OP_ZERO_P_S:
tylerwilson 0:3ab1d2d14eb3 3302 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3303 _W(data,frm+offs,0);
tylerwilson 0:3ab1d2d14eb3 3304 break;
tylerwilson 0:3ab1d2d14eb3 3305 case OP_EQ_P_C_PRI:
tylerwilson 0:3ab1d2d14eb3 3306 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3307 pri= pri==offs ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 3308 break;
tylerwilson 0:3ab1d2d14eb3 3309 case OP_EQ_P_C_ALT:
tylerwilson 0:3ab1d2d14eb3 3310 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3311 pri= alt==offs ? 1 : 0;
tylerwilson 0:3ab1d2d14eb3 3312 break;
tylerwilson 0:3ab1d2d14eb3 3313 case OP_INC_P:
tylerwilson 0:3ab1d2d14eb3 3314 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3315 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3316 *(cell *)(data+(int)offs) += 1;
tylerwilson 0:3ab1d2d14eb3 3317 #else
tylerwilson 0:3ab1d2d14eb3 3318 val=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3319 _W(data,offs,val+1);
tylerwilson 0:3ab1d2d14eb3 3320 #endif
tylerwilson 0:3ab1d2d14eb3 3321 break;
tylerwilson 0:3ab1d2d14eb3 3322 case OP_INC_P_S:
tylerwilson 0:3ab1d2d14eb3 3323 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3324 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3325 *(cell *)(data+(int)(frm+offs)) += 1;
tylerwilson 0:3ab1d2d14eb3 3326 #else
tylerwilson 0:3ab1d2d14eb3 3327 val=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3328 _W(data,frm+offs,val+1);
tylerwilson 0:3ab1d2d14eb3 3329 #endif
tylerwilson 0:3ab1d2d14eb3 3330 break;
tylerwilson 0:3ab1d2d14eb3 3331 case OP_DEC_P:
tylerwilson 0:3ab1d2d14eb3 3332 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3333 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3334 *(cell *)(data+(int)offs) -= 1;
tylerwilson 0:3ab1d2d14eb3 3335 #else
tylerwilson 0:3ab1d2d14eb3 3336 val=_R(data,offs);
tylerwilson 0:3ab1d2d14eb3 3337 _W(data,offs,val-1);
tylerwilson 0:3ab1d2d14eb3 3338 #endif
tylerwilson 0:3ab1d2d14eb3 3339 break;
tylerwilson 0:3ab1d2d14eb3 3340 case OP_DEC_P_S:
tylerwilson 0:3ab1d2d14eb3 3341 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3342 #if defined _R_DEFAULT
tylerwilson 0:3ab1d2d14eb3 3343 *(cell *)(data+(int)(frm+offs)) -= 1;
tylerwilson 0:3ab1d2d14eb3 3344 #else
tylerwilson 0:3ab1d2d14eb3 3345 val=_R(data,frm+offs);
tylerwilson 0:3ab1d2d14eb3 3346 _W(data,frm+offs,val-1);
tylerwilson 0:3ab1d2d14eb3 3347 #endif
tylerwilson 0:3ab1d2d14eb3 3348 break;
tylerwilson 0:3ab1d2d14eb3 3349 case OP_MOVS_P:
tylerwilson 0:3ab1d2d14eb3 3350 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3351 goto __movs;
tylerwilson 0:3ab1d2d14eb3 3352 case OP_CMPS_P:
tylerwilson 0:3ab1d2d14eb3 3353 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3354 goto __cmps;
tylerwilson 0:3ab1d2d14eb3 3355 case OP_FILL_P:
tylerwilson 0:3ab1d2d14eb3 3356 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3357 goto __fill;
tylerwilson 0:3ab1d2d14eb3 3358 case OP_HALT_P:
tylerwilson 0:3ab1d2d14eb3 3359 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3360 goto __halt;
tylerwilson 0:3ab1d2d14eb3 3361 case OP_BOUNDS_P:
tylerwilson 0:3ab1d2d14eb3 3362 GETPARAM_P(offs,op);
tylerwilson 0:3ab1d2d14eb3 3363 if ((ucell)pri>(ucell)offs) {
tylerwilson 0:3ab1d2d14eb3 3364 amx->cip=(cell)((unsigned char *)cip-amx->code);
tylerwilson 0:3ab1d2d14eb3 3365 ABORT(amx,AMX_ERR_BOUNDS);
tylerwilson 0:3ab1d2d14eb3 3366 } /* if */
tylerwilson 0:3ab1d2d14eb3 3367 break;
tylerwilson 0:3ab1d2d14eb3 3368 #endif /* AMX_NO_PACKED_OPC */
tylerwilson 0:3ab1d2d14eb3 3369 default:
tylerwilson 0:3ab1d2d14eb3 3370 assert(0); /* invalid instructions should already have been caught in VerifyPcode() */
tylerwilson 0:3ab1d2d14eb3 3371 ABORT(amx,AMX_ERR_INVINSTR);
tylerwilson 0:3ab1d2d14eb3 3372 } /* switch */
tylerwilson 0:3ab1d2d14eb3 3373 } /* for */
tylerwilson 0:3ab1d2d14eb3 3374 #endif /* AMX_ALTCORE */
tylerwilson 0:3ab1d2d14eb3 3375 }
tylerwilson 0:3ab1d2d14eb3 3376
tylerwilson 0:3ab1d2d14eb3 3377 #endif /* AMX_EXEC */
tylerwilson 0:3ab1d2d14eb3 3378
tylerwilson 0:3ab1d2d14eb3 3379 #if defined AMX_SETCALLBACK
tylerwilson 0:3ab1d2d14eb3 3380 int AMXAPI amx_SetCallback(AMX *amx,AMX_CALLBACK callback)
tylerwilson 0:3ab1d2d14eb3 3381 {
tylerwilson 0:3ab1d2d14eb3 3382 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 3383 assert(callback!=NULL);
tylerwilson 0:3ab1d2d14eb3 3384 amx->callback=callback;
tylerwilson 0:3ab1d2d14eb3 3385 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3386 }
tylerwilson 0:3ab1d2d14eb3 3387 #endif /* AMX_SETCALLBACK */
tylerwilson 0:3ab1d2d14eb3 3388
tylerwilson 0:3ab1d2d14eb3 3389 #if defined AMX_SETDEBUGHOOK
tylerwilson 0:3ab1d2d14eb3 3390 int AMXAPI amx_SetDebugHook(AMX *amx,AMX_DEBUG debug)
tylerwilson 0:3ab1d2d14eb3 3391 {
tylerwilson 0:3ab1d2d14eb3 3392 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 3393 amx->debug=debug;
tylerwilson 0:3ab1d2d14eb3 3394 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3395 }
tylerwilson 0:3ab1d2d14eb3 3396 #endif /* AMX_SETDEBUGHOOK */
tylerwilson 0:3ab1d2d14eb3 3397
tylerwilson 0:3ab1d2d14eb3 3398 #if defined AMX_RAISEERROR
tylerwilson 0:3ab1d2d14eb3 3399 int AMXAPI amx_RaiseError(AMX *amx, int error)
tylerwilson 0:3ab1d2d14eb3 3400 {
tylerwilson 0:3ab1d2d14eb3 3401 assert(error>0);
tylerwilson 0:3ab1d2d14eb3 3402 amx->error=error;
tylerwilson 0:3ab1d2d14eb3 3403 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3404 }
tylerwilson 0:3ab1d2d14eb3 3405 #endif /* AMX_RAISEERROR */
tylerwilson 0:3ab1d2d14eb3 3406
tylerwilson 0:3ab1d2d14eb3 3407 #if defined AMX_ALLOT || defined AMX_PUSHXXX
tylerwilson 0:3ab1d2d14eb3 3408 int AMXAPI amx_Allot(AMX *amx,int cells,cell **address)
tylerwilson 0:3ab1d2d14eb3 3409 {
tylerwilson 0:3ab1d2d14eb3 3410 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 3411 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 3412
tylerwilson 0:3ab1d2d14eb3 3413 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 3414 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 3415 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 3416 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 3417 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 3418
tylerwilson 0:3ab1d2d14eb3 3419 if (amx->stk - amx->hea - cells*sizeof(cell) < STKMARGIN)
tylerwilson 0:3ab1d2d14eb3 3420 return AMX_ERR_MEMORY;
tylerwilson 0:3ab1d2d14eb3 3421 if (address!=NULL)
tylerwilson 0:3ab1d2d14eb3 3422 *address=(cell *)(data+(int)amx->hea);
tylerwilson 0:3ab1d2d14eb3 3423 amx->hea+=cells*sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 3424 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3425 }
tylerwilson 0:3ab1d2d14eb3 3426
tylerwilson 0:3ab1d2d14eb3 3427 int AMXAPI amx_Release(AMX *amx,cell *address)
tylerwilson 0:3ab1d2d14eb3 3428 {
tylerwilson 0:3ab1d2d14eb3 3429 AMX_HEADER *hdr;
tylerwilson 0:3ab1d2d14eb3 3430 unsigned char *data;
tylerwilson 0:3ab1d2d14eb3 3431 cell amx_addr;
tylerwilson 0:3ab1d2d14eb3 3432
tylerwilson 0:3ab1d2d14eb3 3433 assert(amx!=NULL);
tylerwilson 0:3ab1d2d14eb3 3434 hdr=(AMX_HEADER *)amx->base;
tylerwilson 0:3ab1d2d14eb3 3435 assert(hdr!=NULL);
tylerwilson 0:3ab1d2d14eb3 3436 assert(hdr->magic==AMX_MAGIC);
tylerwilson 0:3ab1d2d14eb3 3437 data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
tylerwilson 0:3ab1d2d14eb3 3438 amx_addr=(cell)((unsigned char*)address-data);
tylerwilson 0:3ab1d2d14eb3 3439 if (amx->hea>amx_addr)
tylerwilson 0:3ab1d2d14eb3 3440 amx->hea=amx_addr;
tylerwilson 0:3ab1d2d14eb3 3441 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3442 }
tylerwilson 0:3ab1d2d14eb3 3443 #endif /* AMX_ALLOT || AMX_PUSHXXX */
tylerwilson 0:3ab1d2d14eb3 3444
tylerwilson 0:3ab1d2d14eb3 3445 #if defined AMX_XXXSTRING || defined AMX_UTF8XXX
tylerwilson 0:3ab1d2d14eb3 3446
tylerwilson 0:3ab1d2d14eb3 3447 #define CHARBITS (8*sizeof(char))
tylerwilson 0:3ab1d2d14eb3 3448 #if PAWN_CELL_SIZE==16
tylerwilson 0:3ab1d2d14eb3 3449 #define CHARMASK (0xffffu << 8*(2-sizeof(char)))
tylerwilson 0:3ab1d2d14eb3 3450 #elif PAWN_CELL_SIZE==32
tylerwilson 0:3ab1d2d14eb3 3451 #define CHARMASK (0xffffffffuL << 8*(4-sizeof(char)))
tylerwilson 0:3ab1d2d14eb3 3452 #elif PAWN_CELL_SIZE==64
tylerwilson 0:3ab1d2d14eb3 3453 #define CHARMASK (0xffffffffffffffffuLL << 8*(8-sizeof(char)))
tylerwilson 0:3ab1d2d14eb3 3454 #else
tylerwilson 0:3ab1d2d14eb3 3455 #error Unsupported cell size
tylerwilson 0:3ab1d2d14eb3 3456 #endif
tylerwilson 0:3ab1d2d14eb3 3457
tylerwilson 0:3ab1d2d14eb3 3458 int AMXAPI amx_StrLen(const cell *cstr, int *length)
tylerwilson 0:3ab1d2d14eb3 3459 {
tylerwilson 0:3ab1d2d14eb3 3460 int len;
tylerwilson 0:3ab1d2d14eb3 3461 #if BYTE_ORDER==LITTLE_ENDIAN
tylerwilson 0:3ab1d2d14eb3 3462 cell c;
tylerwilson 0:3ab1d2d14eb3 3463 #endif
tylerwilson 0:3ab1d2d14eb3 3464
tylerwilson 0:3ab1d2d14eb3 3465 assert(length!=NULL);
tylerwilson 0:3ab1d2d14eb3 3466 if (cstr==NULL) {
tylerwilson 0:3ab1d2d14eb3 3467 *length=0;
tylerwilson 0:3ab1d2d14eb3 3468 return AMX_ERR_PARAMS;
tylerwilson 0:3ab1d2d14eb3 3469 } /* if */
tylerwilson 0:3ab1d2d14eb3 3470
tylerwilson 0:3ab1d2d14eb3 3471 if ((ucell)*cstr>UNPACKEDMAX) {
tylerwilson 0:3ab1d2d14eb3 3472 /* packed string */
tylerwilson 0:3ab1d2d14eb3 3473 assert_static(sizeof(char)==1);
tylerwilson 0:3ab1d2d14eb3 3474 len=strlen((char *)cstr); /* find '\0' */
tylerwilson 0:3ab1d2d14eb3 3475 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 3476 #if BYTE_ORDER==LITTLE_ENDIAN
tylerwilson 0:3ab1d2d14eb3 3477 /* on Little Endian machines, toggle the last bytes */
tylerwilson 0:3ab1d2d14eb3 3478 c=cstr[len/sizeof(cell)]; /* get last cell */
tylerwilson 0:3ab1d2d14eb3 3479 len=len - len % sizeof(cell); /* len = multiple of "cell" bytes */
tylerwilson 0:3ab1d2d14eb3 3480 while ((c & CHARMASK)!=0) {
tylerwilson 0:3ab1d2d14eb3 3481 len++;
tylerwilson 0:3ab1d2d14eb3 3482 c <<= 8*sizeof(char);
tylerwilson 0:3ab1d2d14eb3 3483 } /* if */
tylerwilson 0:3ab1d2d14eb3 3484 #endif
tylerwilson 0:3ab1d2d14eb3 3485 } else {
tylerwilson 0:3ab1d2d14eb3 3486 for (len=0; cstr[len]!=0; len++)
tylerwilson 0:3ab1d2d14eb3 3487 /* nothing */;
tylerwilson 0:3ab1d2d14eb3 3488 } /* if */
tylerwilson 0:3ab1d2d14eb3 3489 *length = len;
tylerwilson 0:3ab1d2d14eb3 3490 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3491 }
tylerwilson 0:3ab1d2d14eb3 3492 #endif
tylerwilson 0:3ab1d2d14eb3 3493
tylerwilson 0:3ab1d2d14eb3 3494 #if defined AMX_XXXSTRING || defined AMX_PUSHXXX
tylerwilson 0:3ab1d2d14eb3 3495 int AMXAPI amx_SetString(cell *dest,const char *source,int pack,int use_wchar,size_t size)
tylerwilson 0:3ab1d2d14eb3 3496 { /* the memory blocks should not overlap */
tylerwilson 0:3ab1d2d14eb3 3497 int len, i;
tylerwilson 0:3ab1d2d14eb3 3498
tylerwilson 0:3ab1d2d14eb3 3499 assert_static(UNLIMITED>0);
tylerwilson 0:3ab1d2d14eb3 3500 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3501 (void)use_wchar;
tylerwilson 0:3ab1d2d14eb3 3502 len=strlen(source);
tylerwilson 0:3ab1d2d14eb3 3503 #else
tylerwilson 0:3ab1d2d14eb3 3504 len= use_wchar ? wcslen((const wchar_t*)source) : strlen(source);
tylerwilson 0:3ab1d2d14eb3 3505 #endif
tylerwilson 0:3ab1d2d14eb3 3506 if (pack) {
tylerwilson 0:3ab1d2d14eb3 3507 /* create a packed string */
tylerwilson 0:3ab1d2d14eb3 3508 if (size<UNLIMITED/sizeof(cell) && (size_t)len>=size*sizeof(cell))
tylerwilson 0:3ab1d2d14eb3 3509 len=size*sizeof(cell)-1;
tylerwilson 0:3ab1d2d14eb3 3510 dest[len/sizeof(cell)]=0; /* clear last bytes of last (semi-filled) cell*/
tylerwilson 0:3ab1d2d14eb3 3511 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3512 memcpy(dest,source,len);
tylerwilson 0:3ab1d2d14eb3 3513 #else
tylerwilson 0:3ab1d2d14eb3 3514 if (use_wchar) {
tylerwilson 0:3ab1d2d14eb3 3515 for (i=0; i<len; i++)
tylerwilson 0:3ab1d2d14eb3 3516 ((char*)dest)[i]=(char)(((wchar_t*)source)[i]);
tylerwilson 0:3ab1d2d14eb3 3517 } else {
tylerwilson 0:3ab1d2d14eb3 3518 memcpy(dest,source,len);
tylerwilson 0:3ab1d2d14eb3 3519 } /* if */
tylerwilson 0:3ab1d2d14eb3 3520 #endif
tylerwilson 0:3ab1d2d14eb3 3521 /* On Big Endian machines, the characters are well aligned in the
tylerwilson 0:3ab1d2d14eb3 3522 * cells; on Little Endian machines, we must swap all cells.
tylerwilson 0:3ab1d2d14eb3 3523 */
tylerwilson 0:3ab1d2d14eb3 3524 assert(check_endian());
tylerwilson 0:3ab1d2d14eb3 3525 #if BYTE_ORDER==LITTLE_ENDIAN
tylerwilson 0:3ab1d2d14eb3 3526 len /= sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 3527 while (len>=0)
tylerwilson 0:3ab1d2d14eb3 3528 swapcell((ucell *)&dest[len--]);
tylerwilson 0:3ab1d2d14eb3 3529 #endif
tylerwilson 0:3ab1d2d14eb3 3530 } else {
tylerwilson 0:3ab1d2d14eb3 3531 /* create an unpacked string */
tylerwilson 0:3ab1d2d14eb3 3532 if (size<UNLIMITED && (size_t)len>=size)
tylerwilson 0:3ab1d2d14eb3 3533 len=size-1;
tylerwilson 0:3ab1d2d14eb3 3534 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3535 for (i=0; i<len; i++)
tylerwilson 0:3ab1d2d14eb3 3536 dest[i]=(cell)source[i];
tylerwilson 0:3ab1d2d14eb3 3537 #else
tylerwilson 0:3ab1d2d14eb3 3538 if (use_wchar) {
tylerwilson 0:3ab1d2d14eb3 3539 for (i=0; i<len; i++)
tylerwilson 0:3ab1d2d14eb3 3540 dest[i]=(cell)(((wchar_t*)source)[i]);
tylerwilson 0:3ab1d2d14eb3 3541 } else {
tylerwilson 0:3ab1d2d14eb3 3542 for (i=0; i<len; i++)
tylerwilson 0:3ab1d2d14eb3 3543 dest[i]=(cell)source[i];
tylerwilson 0:3ab1d2d14eb3 3544 } /* if */
tylerwilson 0:3ab1d2d14eb3 3545 #endif
tylerwilson 0:3ab1d2d14eb3 3546 dest[len]=0;
tylerwilson 0:3ab1d2d14eb3 3547 } /* if */
tylerwilson 0:3ab1d2d14eb3 3548 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3549 }
tylerwilson 0:3ab1d2d14eb3 3550 #endif
tylerwilson 0:3ab1d2d14eb3 3551
tylerwilson 0:3ab1d2d14eb3 3552 #if defined AMX_XXXSTRING
tylerwilson 0:3ab1d2d14eb3 3553 int AMXAPI amx_GetString(char *dest,const cell *source,int use_wchar,size_t size)
tylerwilson 0:3ab1d2d14eb3 3554 {
tylerwilson 0:3ab1d2d14eb3 3555 int len=0;
tylerwilson 0:3ab1d2d14eb3 3556 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3557 (void)use_wchar; /* unused parameter (if ANSI only) */
tylerwilson 0:3ab1d2d14eb3 3558 #endif
tylerwilson 0:3ab1d2d14eb3 3559 if ((ucell)*source>UNPACKEDMAX) {
tylerwilson 0:3ab1d2d14eb3 3560 /* source string is packed */
tylerwilson 0:3ab1d2d14eb3 3561 cell c=0; /* initialize to 0 to avoid a compiler warning */
tylerwilson 0:3ab1d2d14eb3 3562 int i=sizeof(cell)-1;
tylerwilson 0:3ab1d2d14eb3 3563 char ch;
tylerwilson 0:3ab1d2d14eb3 3564 while ((size_t)len<size) {
tylerwilson 0:3ab1d2d14eb3 3565 if (i==sizeof(cell)-1)
tylerwilson 0:3ab1d2d14eb3 3566 c=*source++;
tylerwilson 0:3ab1d2d14eb3 3567 ch=(char)(c >> i*CHARBITS);
tylerwilson 0:3ab1d2d14eb3 3568 if (ch=='\0')
tylerwilson 0:3ab1d2d14eb3 3569 break; /* terminating zero character found */
tylerwilson 0:3ab1d2d14eb3 3570 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3571 dest[len++]=ch;
tylerwilson 0:3ab1d2d14eb3 3572 #else
tylerwilson 0:3ab1d2d14eb3 3573 if (use_wchar)
tylerwilson 0:3ab1d2d14eb3 3574 ((wchar_t*)dest)[len++]=ch;
tylerwilson 0:3ab1d2d14eb3 3575 else
tylerwilson 0:3ab1d2d14eb3 3576 dest[len++]=ch;
tylerwilson 0:3ab1d2d14eb3 3577 #endif
tylerwilson 0:3ab1d2d14eb3 3578 i=(i+sizeof(cell)-1) % sizeof(cell);
tylerwilson 0:3ab1d2d14eb3 3579 } /* while */
tylerwilson 0:3ab1d2d14eb3 3580 } else {
tylerwilson 0:3ab1d2d14eb3 3581 /* source string is unpacked */
tylerwilson 0:3ab1d2d14eb3 3582 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3583 while (*source!=0 && (size_t)len<size)
tylerwilson 0:3ab1d2d14eb3 3584 dest[len++]=(char)*source++;
tylerwilson 0:3ab1d2d14eb3 3585 #else
tylerwilson 0:3ab1d2d14eb3 3586 if (use_wchar) {
tylerwilson 0:3ab1d2d14eb3 3587 while (*source!=0 && (size_t)len<size)
tylerwilson 0:3ab1d2d14eb3 3588 ((wchar_t*)dest)[len++]=(wchar_t)*source++;
tylerwilson 0:3ab1d2d14eb3 3589 } else {
tylerwilson 0:3ab1d2d14eb3 3590 while (*source!=0 && (size_t)len<size)
tylerwilson 0:3ab1d2d14eb3 3591 dest[len++]=(char)*source++;
tylerwilson 0:3ab1d2d14eb3 3592 } /* if */
tylerwilson 0:3ab1d2d14eb3 3593 #endif
tylerwilson 0:3ab1d2d14eb3 3594 } /* if */
tylerwilson 0:3ab1d2d14eb3 3595 /* store terminator */
tylerwilson 0:3ab1d2d14eb3 3596 if ((size_t)len>=size)
tylerwilson 0:3ab1d2d14eb3 3597 len=size-1;
tylerwilson 0:3ab1d2d14eb3 3598 if (len>=0) {
tylerwilson 0:3ab1d2d14eb3 3599 #if defined AMX_ANSIONLY
tylerwilson 0:3ab1d2d14eb3 3600 dest[len]='\0';
tylerwilson 0:3ab1d2d14eb3 3601 #else
tylerwilson 0:3ab1d2d14eb3 3602 if (use_wchar)
tylerwilson 0:3ab1d2d14eb3 3603 ((wchar_t*)dest)[len]=0;
tylerwilson 0:3ab1d2d14eb3 3604 else
tylerwilson 0:3ab1d2d14eb3 3605 dest[len]='\0';
tylerwilson 0:3ab1d2d14eb3 3606 #endif
tylerwilson 0:3ab1d2d14eb3 3607 } /* IF */
tylerwilson 0:3ab1d2d14eb3 3608 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3609 }
tylerwilson 0:3ab1d2d14eb3 3610 #endif /* AMX_XXXSTRING */
tylerwilson 0:3ab1d2d14eb3 3611
tylerwilson 0:3ab1d2d14eb3 3612 #if defined AMX_UTF8XXX
tylerwilson 0:3ab1d2d14eb3 3613 #if defined __BORLANDC__
tylerwilson 0:3ab1d2d14eb3 3614 #pragma warn -amb -8000 /* ambiguous operators need parentheses */
tylerwilson 0:3ab1d2d14eb3 3615 #endif
tylerwilson 0:3ab1d2d14eb3 3616 /* amx_UTF8Get()
tylerwilson 0:3ab1d2d14eb3 3617 * Extract a single UTF-8 encoded character from a string and return a pointer
tylerwilson 0:3ab1d2d14eb3 3618 * to the character just behind that UTF-8 character. The parameters "endptr"
tylerwilson 0:3ab1d2d14eb3 3619 * and "value" may be NULL.
tylerwilson 0:3ab1d2d14eb3 3620 * If the code is not valid UTF-8, "endptr" has the value of the input
tylerwilson 0:3ab1d2d14eb3 3621 * parameter "string" and "value" is zero.
tylerwilson 0:3ab1d2d14eb3 3622 */
tylerwilson 0:3ab1d2d14eb3 3623 int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value)
tylerwilson 0:3ab1d2d14eb3 3624 {
tylerwilson 0:3ab1d2d14eb3 3625 static const char utf8_count[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4 };
tylerwilson 0:3ab1d2d14eb3 3626 static const long utf8_lowmark[5] = { 0x80, 0x800, 0x10000L, 0x200000L, 0x4000000L };
tylerwilson 0:3ab1d2d14eb3 3627 unsigned char c;
tylerwilson 0:3ab1d2d14eb3 3628 cell result;
tylerwilson 0:3ab1d2d14eb3 3629 int followup;
tylerwilson 0:3ab1d2d14eb3 3630
tylerwilson 0:3ab1d2d14eb3 3631 assert(string!=NULL);
tylerwilson 0:3ab1d2d14eb3 3632 if (value!=NULL) /* preset, in case of an error */
tylerwilson 0:3ab1d2d14eb3 3633 *value=0;
tylerwilson 0:3ab1d2d14eb3 3634 if (endptr!=NULL)
tylerwilson 0:3ab1d2d14eb3 3635 *endptr=string;
tylerwilson 0:3ab1d2d14eb3 3636
tylerwilson 0:3ab1d2d14eb3 3637 c = *(const unsigned char*)string++;
tylerwilson 0:3ab1d2d14eb3 3638 if (c<0x80) {
tylerwilson 0:3ab1d2d14eb3 3639 /* ASCII */
tylerwilson 0:3ab1d2d14eb3 3640 result=c;
tylerwilson 0:3ab1d2d14eb3 3641 } else {
tylerwilson 0:3ab1d2d14eb3 3642 if (c<0xc0 || c>=0xfe)
tylerwilson 0:3ab1d2d14eb3 3643 return AMX_ERR_PARAMS; /* invalid or "follower" code, quit with error */
tylerwilson 0:3ab1d2d14eb3 3644 /* At this point we know that the two top bits of c are ones. The two
tylerwilson 0:3ab1d2d14eb3 3645 * bottom bits are always part of the code. We only need to consider
tylerwilson 0:3ab1d2d14eb3 3646 * the 4 remaining bits; i.e., a 16-byte table. This is "utf8_count[]".
tylerwilson 0:3ab1d2d14eb3 3647 * (Actually the utf8_count[] table records the number of follow-up
tylerwilson 0:3ab1d2d14eb3 3648 * bytes minus 1. This is just for convenience.)
tylerwilson 0:3ab1d2d14eb3 3649 */
tylerwilson 0:3ab1d2d14eb3 3650 assert((c & 0xc0)==0xc0);
tylerwilson 0:3ab1d2d14eb3 3651 followup=(int)utf8_count[(c >> 2) & 0x0f];
tylerwilson 0:3ab1d2d14eb3 3652 /* The mask depends on the code length; this is just a very simple
tylerwilson 0:3ab1d2d14eb3 3653 * relation.
tylerwilson 0:3ab1d2d14eb3 3654 */
tylerwilson 0:3ab1d2d14eb3 3655 #define utf8_mask (0x1f >> followup)
tylerwilson 0:3ab1d2d14eb3 3656 result= c & utf8_mask;
tylerwilson 0:3ab1d2d14eb3 3657 /* Collect the follow-up codes using a drop-through switch statement;
tylerwilson 0:3ab1d2d14eb3 3658 * this avoids a loop. In each case, verify the two leading bits.
tylerwilson 0:3ab1d2d14eb3 3659 */
tylerwilson 0:3ab1d2d14eb3 3660 assert(followup>=0 && followup<=4);
tylerwilson 0:3ab1d2d14eb3 3661 switch (followup) {
tylerwilson 0:3ab1d2d14eb3 3662 case 4:
tylerwilson 0:3ab1d2d14eb3 3663 if (((c=*string++) & 0xc0) != 0x80) goto error;
tylerwilson 0:3ab1d2d14eb3 3664 result = (result << 6) | c & 0x3f;
tylerwilson 0:3ab1d2d14eb3 3665 case 3:
tylerwilson 0:3ab1d2d14eb3 3666 if (((c=*string++) & 0xc0) != 0x80) goto error;
tylerwilson 0:3ab1d2d14eb3 3667 result = (result << 6) | c & 0x3f;
tylerwilson 0:3ab1d2d14eb3 3668 case 2:
tylerwilson 0:3ab1d2d14eb3 3669 if (((c=*string++) & 0xc0) != 0x80) goto error;
tylerwilson 0:3ab1d2d14eb3 3670 result = (result << 6) | c & 0x3f;
tylerwilson 0:3ab1d2d14eb3 3671 case 1:
tylerwilson 0:3ab1d2d14eb3 3672 if (((c=*string++) & 0xc0) != 0x80) goto error;
tylerwilson 0:3ab1d2d14eb3 3673 result = (result << 6) | c & 0x3f;
tylerwilson 0:3ab1d2d14eb3 3674 case 0:
tylerwilson 0:3ab1d2d14eb3 3675 if (((c=*string++) & 0xc0) != 0x80) goto error;
tylerwilson 0:3ab1d2d14eb3 3676 result = (result << 6) | c & 0x3f;
tylerwilson 0:3ab1d2d14eb3 3677 } /* switch */
tylerwilson 0:3ab1d2d14eb3 3678 /* Do additional checks: shortest encoding & reserved positions. The
tylerwilson 0:3ab1d2d14eb3 3679 * lowmark limits also depends on the code length; it can be read from
tylerwilson 0:3ab1d2d14eb3 3680 * a table with 5 elements. This is "utf8_lowmark[]".
tylerwilson 0:3ab1d2d14eb3 3681 */
tylerwilson 0:3ab1d2d14eb3 3682 if (result<utf8_lowmark[followup])
tylerwilson 0:3ab1d2d14eb3 3683 goto error;
tylerwilson 0:3ab1d2d14eb3 3684 if (result>=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff)
tylerwilson 0:3ab1d2d14eb3 3685 goto error;
tylerwilson 0:3ab1d2d14eb3 3686 } /* if */
tylerwilson 0:3ab1d2d14eb3 3687
tylerwilson 0:3ab1d2d14eb3 3688 if (value!=NULL)
tylerwilson 0:3ab1d2d14eb3 3689 *value=result;
tylerwilson 0:3ab1d2d14eb3 3690 if (endptr!=NULL)
tylerwilson 0:3ab1d2d14eb3 3691 *endptr=string;
tylerwilson 0:3ab1d2d14eb3 3692
tylerwilson 0:3ab1d2d14eb3 3693 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3694
tylerwilson 0:3ab1d2d14eb3 3695 error:
tylerwilson 0:3ab1d2d14eb3 3696 return AMX_ERR_PARAMS;
tylerwilson 0:3ab1d2d14eb3 3697 }
tylerwilson 0:3ab1d2d14eb3 3698
tylerwilson 0:3ab1d2d14eb3 3699 /* amx_UTF8Put()
tylerwilson 0:3ab1d2d14eb3 3700 * Encode a single character into a byte string. The character may result in
tylerwilson 0:3ab1d2d14eb3 3701 * a string of up to 6 bytes. The function returns an error code if "maxchars"
tylerwilson 0:3ab1d2d14eb3 3702 * is lower than the required number of characters; in this case nothing is
tylerwilson 0:3ab1d2d14eb3 3703 * stored.
tylerwilson 0:3ab1d2d14eb3 3704 * The function does not zero-terminate the string.
tylerwilson 0:3ab1d2d14eb3 3705 */
tylerwilson 0:3ab1d2d14eb3 3706 int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value)
tylerwilson 0:3ab1d2d14eb3 3707 {
tylerwilson 0:3ab1d2d14eb3 3708 assert(string!=NULL);
tylerwilson 0:3ab1d2d14eb3 3709 if (endptr!=NULL) /* preset, in case of an error */
tylerwilson 0:3ab1d2d14eb3 3710 *endptr=string;
tylerwilson 0:3ab1d2d14eb3 3711
tylerwilson 0:3ab1d2d14eb3 3712 if (value<0x80) {
tylerwilson 0:3ab1d2d14eb3 3713 /* 0xxxxxxx */
tylerwilson 0:3ab1d2d14eb3 3714 if (maxchars < 1) goto error;
tylerwilson 0:3ab1d2d14eb3 3715 *string++ = (char)value;
tylerwilson 0:3ab1d2d14eb3 3716 } else if (value<0x800) {
tylerwilson 0:3ab1d2d14eb3 3717 /* 110xxxxx 10xxxxxx */
tylerwilson 0:3ab1d2d14eb3 3718 if (maxchars < 2) goto error;
tylerwilson 0:3ab1d2d14eb3 3719 *string++ = (char)((value>>6) & 0x1f | 0xc0);
tylerwilson 0:3ab1d2d14eb3 3720 *string++ = (char)(value & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3721 } else if (value<0x10000) {
tylerwilson 0:3ab1d2d14eb3 3722 /* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */
tylerwilson 0:3ab1d2d14eb3 3723 if (maxchars < 3) goto error;
tylerwilson 0:3ab1d2d14eb3 3724 if (value>=0xd800 && value<=0xdfff || value==0xfffe || value==0xffff)
tylerwilson 0:3ab1d2d14eb3 3725 goto error; /* surrogate pairs and invalid characters */
tylerwilson 0:3ab1d2d14eb3 3726 *string++ = (char)((value>>12) & 0x0f | 0xe0);
tylerwilson 0:3ab1d2d14eb3 3727 *string++ = (char)((value>>6) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3728 *string++ = (char)(value & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3729 } else if (value<0x200000) {
tylerwilson 0:3ab1d2d14eb3 3730 /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
tylerwilson 0:3ab1d2d14eb3 3731 if (maxchars < 4) goto error;
tylerwilson 0:3ab1d2d14eb3 3732 *string++ = (char)((value>>18) & 0x07 | 0xf0);
tylerwilson 0:3ab1d2d14eb3 3733 *string++ = (char)((value>>12) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3734 *string++ = (char)((value>>6) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3735 *string++ = (char)(value & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3736 } else if (value<0x4000000) {
tylerwilson 0:3ab1d2d14eb3 3737 /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
tylerwilson 0:3ab1d2d14eb3 3738 if (maxchars < 5) goto error;
tylerwilson 0:3ab1d2d14eb3 3739 *string++ = (char)((value>>24) & 0x03 | 0xf8);
tylerwilson 0:3ab1d2d14eb3 3740 *string++ = (char)((value>>18) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3741 *string++ = (char)((value>>12) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3742 *string++ = (char)((value>>6) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3743 *string++ = (char)(value & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3744 } else {
tylerwilson 0:3ab1d2d14eb3 3745 /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (31 bits) */
tylerwilson 0:3ab1d2d14eb3 3746 if (maxchars < 6) goto error;
tylerwilson 0:3ab1d2d14eb3 3747 *string++ = (char)((value>>30) & 0x01 | 0xfc);
tylerwilson 0:3ab1d2d14eb3 3748 *string++ = (char)((value>>24) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3749 *string++ = (char)((value>>18) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3750 *string++ = (char)((value>>12) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3751 *string++ = (char)((value>>6) & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3752 *string++ = (char)(value & 0x3f | 0x80);
tylerwilson 0:3ab1d2d14eb3 3753 } /* if */
tylerwilson 0:3ab1d2d14eb3 3754
tylerwilson 0:3ab1d2d14eb3 3755 if (endptr!=NULL)
tylerwilson 0:3ab1d2d14eb3 3756 *endptr=string;
tylerwilson 0:3ab1d2d14eb3 3757 return AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3758
tylerwilson 0:3ab1d2d14eb3 3759 error:
tylerwilson 0:3ab1d2d14eb3 3760 return AMX_ERR_PARAMS;
tylerwilson 0:3ab1d2d14eb3 3761 }
tylerwilson 0:3ab1d2d14eb3 3762
tylerwilson 0:3ab1d2d14eb3 3763 /* amx_UTF8Check()
tylerwilson 0:3ab1d2d14eb3 3764 * Run through a zero-terminated string and check the validity of the UTF-8
tylerwilson 0:3ab1d2d14eb3 3765 * encoding. The function returns an error code, it is AMX_ERR_NONE if the
tylerwilson 0:3ab1d2d14eb3 3766 * string is valid UTF-8 (or valid ASCII for that matter).
tylerwilson 0:3ab1d2d14eb3 3767 */
tylerwilson 0:3ab1d2d14eb3 3768 int AMXAPI amx_UTF8Check(const char *string, int *length)
tylerwilson 0:3ab1d2d14eb3 3769 {
tylerwilson 0:3ab1d2d14eb3 3770 int err=AMX_ERR_NONE;
tylerwilson 0:3ab1d2d14eb3 3771 int len=0;
tylerwilson 0:3ab1d2d14eb3 3772 while (err==AMX_ERR_NONE && *string!='\0') {
tylerwilson 0:3ab1d2d14eb3 3773 err=amx_UTF8Get(string,&string,NULL);
tylerwilson 0:3ab1d2d14eb3 3774 len++;
tylerwilson 0:3ab1d2d14eb3 3775 } /* while */
tylerwilson 0:3ab1d2d14eb3 3776 if (length!=NULL)
tylerwilson 0:3ab1d2d14eb3 3777 *length=len;
tylerwilson 0:3ab1d2d14eb3 3778 return err;
tylerwilson 0:3ab1d2d14eb3 3779 }
tylerwilson 0:3ab1d2d14eb3 3780
tylerwilson 0:3ab1d2d14eb3 3781 /* amx_UTF8Len()
tylerwilson 0:3ab1d2d14eb3 3782 * Run through a wide string and return how many 8-bit characters are needed to
tylerwilson 0:3ab1d2d14eb3 3783 * store the string in UTF-8 format. The returned cound excludes the terminating
tylerwilson 0:3ab1d2d14eb3 3784 * zero byte. The function returns an error code.
tylerwilson 0:3ab1d2d14eb3 3785 */
tylerwilson 0:3ab1d2d14eb3 3786 int AMXAPI amx_UTF8Len(const cell *cstr, int *length)
tylerwilson 0:3ab1d2d14eb3 3787 {
tylerwilson 0:3ab1d2d14eb3 3788 int err;
tylerwilson 0:3ab1d2d14eb3 3789
tylerwilson 0:3ab1d2d14eb3 3790 assert(length!=NULL);
tylerwilson 0:3ab1d2d14eb3 3791 err=amx_StrLen(cstr, length);
tylerwilson 0:3ab1d2d14eb3 3792 if (err==AMX_ERR_NONE && (ucell)*cstr<=UNPACKEDMAX) {
tylerwilson 0:3ab1d2d14eb3 3793 char buffer[10]; /* maximum UTF-8 code is 6 characters */
tylerwilson 0:3ab1d2d14eb3 3794 char *endptr;
tylerwilson 0:3ab1d2d14eb3 3795 int len=*length, count=0;
tylerwilson 0:3ab1d2d14eb3 3796 while (len-->0) {
tylerwilson 0:3ab1d2d14eb3 3797 amx_UTF8Put(buffer, &endptr, sizeof buffer, *cstr++);
tylerwilson 0:3ab1d2d14eb3 3798 count+=(int)(endptr-buffer);
tylerwilson 0:3ab1d2d14eb3 3799 } /* while */
tylerwilson 0:3ab1d2d14eb3 3800 *length=count;
tylerwilson 0:3ab1d2d14eb3 3801 } /* while */
tylerwilson 0:3ab1d2d14eb3 3802 return err;
tylerwilson 0:3ab1d2d14eb3 3803 }
tylerwilson 0:3ab1d2d14eb3 3804 #endif /* AMX_UTF8XXX */