1 /* Pawn Abstract Machine (for the Pawn language)
3 * Copyright (c) ITB CompuPhase, 1997-2006
5 * This software is provided "as-is", without any express or implied warranty.
6 * In no event will the authors be held liable for any damages arising from
7 * the use of this software.
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software in
15 * a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
24 #ifndef AMX_H_INCLUDED
25 #define AMX_H_INCLUDED
27 #include <stdlib.h> /* for size_t */
30 #if defined FREEBSD && !defined __FreeBSD__
33 #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
39 #if !defined HAVE_STDINT_H
42 #elif !defined HAVE_STDINT_H
43 #if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200)
44 #if defined HAVE_INTTYPES_H
49 #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
50 /* The ISO C99 defines the int16_t and int_32t types. If the compiler got
51 * here, these types are probably undefined.
54 #include <ppc/types.h>
55 typedef unsigned short int uint16_t;
56 typedef unsigned long int uint32_t;
57 #elif defined __FreeBSD__
60 typedef short int int16_t;
61 typedef unsigned short int uint16_t;
62 #if defined SN_TARGET_PS2
64 typedef unsigned int uint32_t;
66 typedef long int int32_t;
67 typedef unsigned long int uint32_t;
69 #if defined __WIN32__ || defined _WIN32 || defined WIN32
70 typedef __int64 int64_t;
71 typedef unsigned __int64 uint64_t;
73 #elif defined __GNUC__
74 typedef long long int64_t;
75 typedef unsigned long long uint64_t;
82 #if defined _LP64 || defined WIN64 || defined _WIN64
83 #if !defined __64BIT__
91 #if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
93 #define alloca(n) _alloca(n)
97 #if !defined arraysize
98 #define arraysize(array) (sizeof(array) / sizeof((array)[0]))
100 #if !defined assert_static
101 /* see "Compile-Time Assertions" by Ralf Holly,
102 * C/C++ Users Journal, November 2004
104 #define assert_static(e) \
106 enum { assert_static__ = 1/(e) }; \
115 #if !defined AMX_NATIVE_CALL
116 #define AMX_NATIVE_CALL __stdcall
119 #define AMXAPI __stdcall
123 /* calling convention for native functions */
124 #if !defined AMX_NATIVE_CALL
125 #define AMX_NATIVE_CALL
127 /* calling convention for all interface functions and callback functions */
130 #define AMXAPI __stdcall
132 #define AMXAPI __cdecl
133 #elif defined GCC_HASCLASSVISIBILITY
134 #define AMXAPI __attribute__ ((visibility("default")))
139 #if !defined AMXEXPORT
143 /* File format version (in CUR_FILE_VERSION)
144 * 0 (original version)
145 * 1 (opcodes JUMP.pri, SWITCH and CASETBL)
146 * 2 (compressed files)
147 * 3 (public variables)
148 * 4 (opcodes SWAP.pri/alt and PUSHADDR)
150 * 6 (reformatted header)
151 * 7 (name table, opcodes SYMTAG & SYSREQ.D)
152 * 8 (opcode STMT, renewed debug interface)
154 * MIN_FILE_VERSION is the lowest file version number that the current AMX
155 * implementation supports. If the AMX file header gets new fields, this number
156 * often needs to be incremented. MAX_AMX_VERSION is the lowest AMX version that
157 * is needed to support the current file version. When there are new opcodes,
158 * this number needs to be incremented.
159 * The file version supported by the JIT may run behind MIN_AMX_VERSION. So
160 * there is an extra constant for it: MAX_FILE_VER_JIT.
162 #define CUR_FILE_VERSION 9 /* current file version; also the current AMX version */
163 #define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */
164 #define MIN_AMX_VERSION 9 /* minimum AMX version needed to support the current file format */
165 #define MAX_FILE_VER_JIT 8 /* file version supported by the JIT */
166 #define MIN_AMX_VER_JIT 8 /* AMX version supported by the JIT */
168 #if !defined PAWN_CELL_SIZE
169 #define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
171 #if PAWN_CELL_SIZE==16
172 typedef uint16_t ucell;
173 typedef int16_t cell;
174 #elif PAWN_CELL_SIZE==32
175 typedef uint32_t ucell;
176 typedef int32_t cell;
177 #elif PAWN_CELL_SIZE==64
178 typedef uint64_t ucell;
179 typedef int64_t cell;
181 #error Unsupported cell size (PAWN_CELL_SIZE)
184 #define UNPACKEDMAX (((cell)1 << (sizeof(cell)-1)*8) - 1)
185 #define UNLIMITED (~1u >> 1)
188 typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
189 typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
190 cell *result, cell *params);
191 typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
192 typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX *, cell *, int));
198 #pragma warning(disable:4103) /* disable warning message 4103 that complains
199 * about pragma pack in a header file */
200 #pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
203 /* Some compilers do not support the #pragma align, which should be fine. Some
204 * compilers give a warning on unknown #pragmas, which is not so fine...
206 #if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
210 #if !defined AMX_NO_ALIGN
211 #if defined LINUX || defined __FreeBSD__
212 #pragma pack(1) /* structures must be packed (byte-aligned) */
213 #elif defined MACOS && defined __MWERKS__
214 #pragma options align=mac68k
217 #pragma pack(1) /* structures must be packed (byte-aligned) */
218 #if defined __TURBOC__
219 #pragma option -a- /* "pack" pragma for older Borland compilers */
224 typedef struct tagAMX_NATIVE_INFO {
225 const char _FAR *name;
229 #define AMX_USERNUM 4
230 #define sEXPMAX 19 /* maximum name length for file version <= 6 */
231 #define sNAMEMAX 63 /* maximum name length of symbol name */
233 typedef struct tagAMX_FUNCSTUB {
235 char name[sEXPMAX+1];
238 typedef struct tagFUNCSTUBNT {
243 /* The AMX structure is the internal structure for many functions. Not all
244 * fields are valid at all times; many fields are cached in local variables.
246 typedef struct tagAMX {
247 unsigned char _FAR *base; /* points to the AMX header plus the code, optionally also the data */
248 unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */
249 AMX_CALLBACK callback;
250 AMX_DEBUG debug ; /* debug callback */
251 /* for external functions a few registers must be accessible from the outside */
252 cell cip ; /* instruction pointer: relative to base + amxhdr->cod */
253 cell frm ; /* stack frame base: relative to base + amxhdr->dat */
254 cell hea ; /* top of the heap: relative to base + amxhdr->dat */
255 cell hlw ; /* bottom of the heap: relative to base + amxhdr->dat */
256 cell stk ; /* stack pointer: relative to base + amxhdr->dat */
257 cell stp ; /* top of the stack: relative to base + amxhdr->dat */
258 int flags ; /* current status, see amx_Flags() */
260 long usertags[AMX_USERNUM] ;
261 void _FAR *userdata[AMX_USERNUM] ;
262 /* native functions can raise an error */
264 /* passing parameters requires a "count" field */
266 /* the sleep opcode needs to store the full AMX status */
271 /* extra fields for increased performance */
272 cell sysreq_d ; /* relocated address/value for the SYSREQ.D opcode */
274 /* support variables for the JIT */
275 int reloc_size ; /* required temporary buffer for relocations */
276 long code_size ; /* estimated memory footprint of the native code */
280 /* The AMX_HEADER structure is both the memory format as the file format. The
281 * structure is used internaly.
283 typedef struct tagAMX_HEADER {
284 int32_t size ; /* size of the "file" */
285 uint16_t magic ; /* signature */
286 char file_version ; /* file format version */
287 char amx_version ; /* required version of the AMX */
289 int16_t defsize ; /* size of a definition record */
290 int32_t cod ; /* initial value of COD - code block */
291 int32_t dat ; /* initial value of DAT - data block */
292 int32_t hea ; /* initial value of HEA - start of the heap */
293 int32_t stp ; /* initial value of STP - stack top */
294 int32_t cip ; /* initial value of CIP - the instruction pointer */
295 int32_t publics ; /* offset to the "public functions" table */
296 int32_t natives ; /* offset to the "native functions" table */
297 int32_t libraries ; /* offset to the table of libraries */
298 int32_t pubvars ; /* the "public variables" table */
299 int32_t tags ; /* the "public tagnames" table */
300 int32_t nametable ; /* name table */
303 #if PAWN_CELL_SIZE==16
304 #define AMX_MAGIC 0xf1e2
305 #elif PAWN_CELL_SIZE==32
306 #define AMX_MAGIC 0xf1e0
307 #elif PAWN_CELL_SIZE==64
308 #define AMX_MAGIC 0xf1e1
313 /* reserve the first 15 error codes for exit codes of the abstract machine */
314 AMX_ERR_EXIT, /* forced exit */
315 AMX_ERR_ASSERT, /* assertion failed */
316 AMX_ERR_STACKERR, /* stack/heap collision */
317 AMX_ERR_BOUNDS, /* index out of bounds */
318 AMX_ERR_MEMACCESS, /* invalid memory access */
319 AMX_ERR_INVINSTR, /* invalid instruction */
320 AMX_ERR_STACKLOW, /* stack underflow */
321 AMX_ERR_HEAPLOW, /* heap underflow */
322 AMX_ERR_CALLBACK, /* no callback, or invalid callback */
323 AMX_ERR_NATIVE, /* native function failed */
324 AMX_ERR_DIVIDE, /* divide by zero */
325 AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
326 AMX_ERR_INVSTATE, /* invalid state for this access */
328 AMX_ERR_MEMORY = 16, /* out of memory */
329 AMX_ERR_FORMAT, /* invalid file format */
330 AMX_ERR_VERSION, /* file is for a newer version of the AMX */
331 AMX_ERR_NOTFOUND, /* function not found */
332 AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */
333 AMX_ERR_DEBUG, /* debugger cannot run */
334 AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */
335 AMX_ERR_USERDATA, /* unable to set user data field (table full) */
336 AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
337 AMX_ERR_PARAMS, /* parameter error */
338 AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
339 AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */
342 /* AMX_FLAG_CHAR16 0x01 no longer used */
343 #define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
344 #define AMX_FLAG_COMPACT 0x04 /* compact encoding */
345 #define AMX_FLAG_SLEEP 0x08 /* script uses the sleep instruction (possible re-entry or power-down mode) */
346 #define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no BREAK opcodes */
347 #define AMX_FLAG_SYSREQN 0x800 /* script new (optimized) version of SYSREQ opcode */
348 #define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
349 #define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
350 #define AMX_FLAG_BROWSE 0x4000 /* busy browsing */
351 #define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
353 #define AMX_EXEC_MAIN (-1) /* start at program entry point */
354 #define AMX_EXEC_CONT (-2) /* continue from last address */
356 #define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
358 #if !defined AMX_COMPACTMARGIN
359 #define AMX_COMPACTMARGIN 64
362 /* for native functions that use floating point parameters, the following
363 * two macros are convenient for casting a "cell" into a "float" type _without_
364 * changing the bit pattern
366 #if PAWN_CELL_SIZE==32
367 #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
368 #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
369 #elif PAWN_CELL_SIZE==64
370 #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
371 #define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */
373 #error Unsupported cell size
376 #define amx_StrParam(amx,param,result) \
378 cell *amx_cstr_; int amx_length_; \
379 amx_GetAddr((amx), (param), &amx_cstr_); \
380 amx_StrLen(amx_cstr_, &amx_length_); \
381 if (amx_length_ > 0 && \
382 ((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
383 amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \
384 else (result) = NULL; \
387 uint16_t * AMXAPI amx_Align16(uint16_t *v);
388 uint32_t * AMXAPI amx_Align32(uint32_t *v);
389 #if defined _I64_MAX || defined HAVE_I64
390 uint64_t * AMXAPI amx_Align64(uint64_t *v);
392 int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
393 int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
394 int AMXAPI amx_Cleanup(AMX *amx);
395 int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
396 int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
397 int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
398 int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
399 int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr);
400 int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
401 int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
402 int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
403 int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
404 int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
405 int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
406 int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
407 int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
408 int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
409 int AMXAPI amx_Init(AMX *amx, void *program);
410 int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
411 int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
412 int AMXAPI amx_NameLength(AMX *amx, int *length);
413 AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func);
414 int AMXAPI amx_NumNatives(AMX *amx, int *number);
415 int AMXAPI amx_NumPublics(AMX *amx, int *number);
416 int AMXAPI amx_NumPubVars(AMX *amx, int *number);
417 int AMXAPI amx_NumTags(AMX *amx, int *number);
418 int AMXAPI amx_Push(AMX *amx, cell value);
419 int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells);
420 int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
421 int AMXAPI amx_RaiseError(AMX *amx, int error);
422 int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
423 int AMXAPI amx_Release(AMX *amx, cell amx_addr);
424 int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
425 int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
426 int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
427 int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
428 int AMXAPI amx_StrLen(const cell *cstring, int *length);
429 int AMXAPI amx_UTF8Check(const char *string, int *length);
430 int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
431 int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
432 int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
434 #if PAWN_CELL_SIZE==16
435 #define amx_AlignCell(v) amx_Align16(v)
436 #elif PAWN_CELL_SIZE==32
437 #define amx_AlignCell(v) amx_Align32(v)
438 #elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
439 #define amx_AlignCell(v) amx_Align64(v)
441 #error Unsupported cell size
444 #define amx_RegisterFunc(amx, name, func) \
445 amx_Register((amx), amx_NativeInfo((name),(func)), 1);
447 #if !defined AMX_NO_ALIGN
448 #if defined LINUX || defined __FreeBSD__
449 #pragma pack() /* reset default packing */
450 #elif defined MACOS && defined __MWERKS__
451 #pragma options align=reset
453 #pragma pack(pop) /* reset previous packing */
462 OP_NONE, /* invalid opcode */
586 OP_FILE, /* obsolete */
587 OP_LINE, /* obsolete */
588 OP_SYMBOL, /* obsolete */
589 OP_SRANGE, /* obsolete */
598 OP_SYMTAG, /* obsolete */
630 #endif /* AMX_H_INCLUDED */