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/
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)
amx.c@3:185fdbb7ccf0, 2013-05-24 (annotated)
- 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?
User | Revision | Line number | New 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 */ |