diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 6db9580..e7008cd 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -56,8 +56,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) # The Pawn compiler shared library set(PAWNC_SRCS sc1.c sc2.c sc3.c sc4.c sc5.c sc6.c sc7.c - scexpand.c sci18n.c sclist.c scmemfil.c scstate.c scvars.c - lstring.c memfile.c libpawnc.c) + sci18n.c sclist.c scmemfil.c scstate.c scvars.c + lstring.c memfile.c libpawnc.c) set_source_files_properties(sc1.c COMPILE_FLAGS -DNO_MAIN) if(WIN32) set(PAWNC_SRCS ${PAWNC_SRCS} libpawnc.rc) diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 992f3e9..c4a5543 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -37,16 +37,161 @@ #endif #include "sc.h" -#if defined _MSC_VER - #pragma warning(push) - #pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */ -#endif +static char *errmsg[] = { +/*001*/ "expected token: \"%s\", but found \"%s\"\n", +/*002*/ "only a single statement (or expression) can follow each \"case\"\n", +/*003*/ "declaration of a local variable must appear in a compound block\n", +/*004*/ "function \"%s\" is not implemented\n", +/*005*/ "function may not have arguments\n", +/*006*/ "must be assigned to an array\n", +/*007*/ "operator cannot be redefined\n", +/*008*/ "must be a constant expression; assumed zero\n", +/*009*/ "invalid array size (negative, zero or out of bounds)\n", +/*010*/ "invalid function or declaration\n", +/*011*/ "invalid outside functions\n", +/*012*/ "invalid function call, not a valid address\n", +/*013*/ "no entry point (no public functions)\n", +/*014*/ "invalid statement; not in switch\n", +/*015*/ "\"default\" case must be the last case in switch statement\n", +/*016*/ "multiple defaults in \"switch\"\n", +/*017*/ "undefined symbol \"%s\"\n", +/*018*/ "initialization data exceeds declared size\n", +/*019*/ "not a label: \"%s\"\n", +/*020*/ "invalid symbol name \"%s\"\n", +/*021*/ "symbol already defined: \"%s\"\n", +/*022*/ "must be lvalue (non-constant)\n", +/*023*/ "array assignment must be simple assignment\n", +/*024*/ "\"break\" or \"continue\" is out of context\n", +/*025*/ "function heading differs from prototype\n", +/*026*/ "no matching \"#if...\"\n", +/*027*/ "invalid character constant\n", +/*028*/ "invalid subscript (not an array or too many subscripts): \"%s\"\n", +/*029*/ "invalid expression, assumed zero\n", +/*030*/ "compound statement not closed at the end of file (started at line %d)\n", +/*031*/ "unknown directive\n", +/*032*/ "array index out of bounds (variable \"%s\")\n", +/*033*/ "array must be indexed (variable \"%s\")\n", +/*034*/ "argument does not have a default value (argument %d)\n", +/*035*/ "argument type mismatch (argument %d)\n", +/*036*/ "empty statement\n", +/*037*/ "invalid string (possibly non-terminated string)\n", +/*038*/ "extra characters on line\n", +/*039*/ "constant symbol has no size\n", +/*040*/ "duplicate \"case\" label (value %d)\n", +/*041*/ "invalid ellipsis, array size is not known\n", +/*042*/ "invalid combination of class specifiers\n", +/*043*/ "character constant exceeds range for packed string\n", +/*044*/ "positional parameters must precede all named parameters\n", +/*045*/ "too many function arguments\n", +/*046*/ "unknown array size (variable \"%s\")\n", +/*047*/ "array sizes do not match, or destination array is too small\n", +/*048*/ "array dimensions do not match\n", +/*049*/ "invalid line continuation\n", +/*050*/ "invalid range\n", +/*051*/ "invalid subscript, use \"[ ]\" operators on major dimensions\n", +/*052*/ "multi-dimensional arrays must be fully initialized\n", +/*053*/ "exceeding maximum number of dimensions\n", +/*054*/ "unmatched closing brace (\"}\")\n", +/*055*/ "start of function body without function header\n", +/*056*/ "arrays, local variables and function arguments cannot be public (variable \"%s\")\n", +/*057*/ "unfinished expression before compiler directive\n", +/*058*/ "duplicate argument; same argument is passed twice\n", +/*059*/ "function argument may not have a default value (variable \"%s\")\n", +/*060*/ "multiple \"#else\" directives between \"#if ... #endif\"\n", +/*061*/ "\"#elseif\" directive follows an \"#else\" directive\n", +/*062*/ "number of operands does not fit the operator\n", +/*063*/ "function result tag of operator \"%s\" must be \"%s\"\n", +/*064*/ "cannot change predefined operators\n", +/*065*/ "function argument may only have a single tag (argument %d)\n", +/*066*/ "function argument may not be a reference argument or an array (argument \"%s\")\n", +/*067*/ "variable cannot be both a reference and an array (variable \"%s\")\n", +/*068*/ "invalid rational number precision in #pragma\n", +/*069*/ "rational number format already defined\n", +/*070*/ "rational number support was not enabled\n", +/*071*/ "user-defined operator must be declared before use (function \"%s\")\n", +/*072*/ "\"sizeof\" operator is invalid on \"function\" symbols\n", +/*073*/ "function argument must be an array (argument \"%s\")\n", +/*074*/ "#define pattern must start with an alphabetic character\n", +/*075*/ "input line too long (after substitutions)\n", +/*076*/ "syntax error in the expression, or invalid function call\n", +/*077*/ "malformed UTF-8 encoding, or corrupted file: %s\n", +/*078*/ "function uses both \"return\" and \"return \"\n", +/*079*/ "inconsistent return types (array & non-array)\n", +/*080*/ "unknown symbol, or not a constant symbol (symbol \"%s\")\n", +/*081*/ "cannot take a tag as a default value for an indexed array parameter (symbol \"%s\")\n", +/*082*/ "user-defined operators and native functions may not have states\n", +/*083*/ "a function or variable may only belong to a single automaton (symbol \"%s\")\n", +/*084*/ "state conflict: one of the states is already assigned to another implementation (symbol \"%s\")\n", +/*085*/ "no states are defined for symbol \"%s\"\n", +/*086*/ "unknown automaton \"%s\"\n", +/*087*/ "unknown state \"%s\" for automaton \"%s\"\n", +/*088*/ "public variables and local variables may not have states (symbol \"%s\")\n", +/*089*/ "state variables may not be initialized (symbol \"%s\")\n", +/*090*/ "public functions may not return arrays (symbol \"%s\")\n", +/*091*/ "ambiguous constant; tag override is required (symbol \"%s\")\n" +}; -#include "sc5.scp" +static char *fatalmsg[] = { +/*100*/ "cannot read from file: \"%s\"\n", +/*101*/ "cannot write to file: \"%s\"\n", +/*102*/ "table overflow: \"%s\"\n", + /* table can be: loop table + * literal table + * staging buffer + * option table (response file) + * peephole optimizer table + */ +/*103*/ "insufficient memory\n", +/*104*/ "invalid assembler instruction \"%s\"\n", +/*105*/ "numeric overflow, exceeding capacity\n", +/*106*/ "compiled script exceeds the maximum memory size (%ld bytes)\n", +/*107*/ "too many error messages on one line\n", +/*108*/ "codepage mapping file not found\n", +/*109*/ "invalid path: \"%s\"\n", +/*110*/ "assertion failed: %s\n", +/*111*/ "user error: %s\n" +}; -#if defined _MSC_VER - #pragma warning(pop) -#endif +static char *warnmsg[] = { +/*200*/ "symbol \"%s\" is truncated to %d characters\n", +/*201*/ "redefinition of constant/macro (symbol \"%s\")\n", +/*202*/ "number of arguments does not match definition\n", +/*203*/ "symbol is never used: \"%s\"\n", +/*204*/ "symbol is assigned a value that is never used: \"%s\"\n", +/*205*/ "redundant code: constant expression is zero\n", +/*206*/ "redundant test: constant expression is non-zero\n", +/*207*/ "unknown #pragma\n", +/*208*/ "function with tag result used before definition, forcing reparse\n", +/*209*/ "function \"%s\" should return a value\n", +/*210*/ "possible use of symbol before initialization: \"%s\"\n", +/*211*/ "possibly unintended assignment\n", +/*212*/ "possibly unintended bitwise operation\n", +/*213*/ "tag mismatch\n", +/*214*/ "possibly a \"const\" array argument was intended: \"%s\"\n", +/*215*/ "expression has no effect\n", +/*216*/ "nested comment\n", +/*217*/ "loose indentation\n", +/*218*/ "old style prototypes used with optional semicolumns\n", +/*219*/ "local variable \"%s\" shadows a variable at a preceding level\n", +/*220*/ "expression with tag override must appear between parentheses\n", +/*221*/ "label name \"%s\" shadows tag name\n", +/*222*/ "number of digits exceeds rational number precision\n", +/*223*/ "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n", +/*224*/ "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n", +/*225*/ "unreachable code\n", +/*226*/ "a variable is assigned to itself (symbol \"%s\")\n", +/*227*/ "more initiallers than enum fields\n", +/*228*/ "length of initialler exceeds size of the enum field\n", +/*229*/ "index tag mismatch (symbol \"%s\")\n", +/*230*/ "no implementation for state \"%s\" in function \"%s\", no fall-back\n", +/*231*/ "state specification on forward declaration is ignored\n", +/*232*/ "output file is written, but with compact encoding disabled\n", +/*233*/ "state variable \"%s\" shadows a global variable\n", +/*234*/ "function is deprecated (symbol \"%s\") %s\n", +/*235*/ "public function lacks forward declaration (symbol \"%s\")\n", +/*236*/ "unknown parameter in substitution (incorrect #define pattern)\n", +/*237*/ "user warning: %s\n" +}; #define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0]) static struct s_warnstack { @@ -77,7 +222,6 @@ static int lastline,errorcount; static short lastfile; char *msg,*pre; va_list argptr; - char string[128]; /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore @@ -110,8 +254,6 @@ static short lastfile; warnnum++; } /* if */ - strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE); - assert(errstart<=fline); if (errline>0) errstart=errline; @@ -121,7 +263,7 @@ static short lastfile; va_start(argptr,number); if (strlen(errfname)==0) { int start= (errstart==errline) ? -1 : errstart; - if (pc_error(number,string,inpfname,start,errline,argptr)) { + if (pc_error(number,msg,inpfname,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; @@ -135,7 +277,7 @@ static short lastfile; fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number); else fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number); - vfprintf(fp,string,argptr); + vfprintf(fp,msg,argptr); fclose(fp); } /* if */ } /* if */ @@ -258,4 +400,3 @@ int pc_popwarnings() return TRUE; } -#undef SCPACK_TABLE diff --git a/source/compiler/sc5.scp b/source/compiler/sc5.scp deleted file mode 100644 index 43c9c88..0000000 --- a/source/compiler/sc5.scp +++ /dev/null @@ -1,344 +0,0 @@ -/* Pawn compiler - Error message strings (plain and compressed formats) - * - * Copyright (c) ITB CompuPhase, 2000-2006 - * - * This software is provided "as-is", without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id: sc5.sch 3633 2006-08-11 16:20:18Z thiadmer $ - */ - -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]); - -#define SCPACK_TABLE errstr_table -/*-*SCPACK start of pair table, do not change or remove this line */ -unsigned char errstr_table[][2] = { - {101,32}, {111,110}, {116,32}, {105,110}, {97,114}, {116,105}, {100,32}, {115,32}, {101,114}, {37,115}, {97,108}, {101,110}, {133,129}, {34,137}, {141,34}, {117,110}, - {114,101}, {110,111}, {115,105}, {121,32}, {97,116}, {111,114}, {97,110}, {32,142}, {109,98}, {115,116}, {41,10}, {100,101}, {109,139}, {101,134}, {98,108}, {140,32}, - {111,108}, {114,97}, {145,130}, {118,138}, {143,99}, {102,164}, {115,121}, {166,152}, {167,160}, {117,115}, {97,32}, {115,146}, {97,158}, {149,32}, {132,161}, {105,134}, - {103,32}, {136,32}, {163,175}, {103,117}, {179,156}, {131,178}, {132,180}, {111,102}, {116,104}, {101,120}, {105,135}, {165,159}, {101,100}, {99,104}, {118,132}, {168,151}, - {105,172}, {190,192}, {155,102}, {174,147}, {183,32}, {109,97}, {116,111}, {99,129}, {101,135}, {112,144}, {182,130}, {98,128}, {115,10}, {153,148}, {44,32}, {40,191}, - {169,130}, {151,10}, {101,10}, {207,154}, {109,208}, {116,97}, {194,131}, {193,128}, {34,32}, {129,32}, {105,99}, {132,97}, {100,105}, {146,122}, {110,32}, {138,32}, - {104,97}, {101,108}, {117,108}, {99,111}, {108,111}, {109,148}, {199,153}, {58,209}, {111,112}, {97,115}, {108,128}, {232,136}, {230,150}, {150,32}, {201,171}, {131,176}, - {212,203}, {102,105}, {119,105}, {185,238}, {109,112}, {116,136}, {165,140}, {197,147}, {102,149}, {111,32}, {131,32}, {213,176}, {110,117}, {115,117}, {118,128} -}; -/*-*SCPACK end of pair table, do not change or remove this line */ - -static char *errmsg[] = { -#ifdef SCPACK -/*001*/ "expected token: \"%s\", but found \"%s\"\n", -/*002*/ "only a single statement (or expression) can follow each \"case\"\n", -/*003*/ "declaration of a local variable must appear in a compound block\n", -/*004*/ "function \"%s\" is not implemented\n", -/*005*/ "function may not have arguments\n", -/*006*/ "must be assigned to an array\n", -/*007*/ "operator cannot be redefined\n", -/*008*/ "must be a constant expression; assumed zero\n", -/*009*/ "invalid array size (negative, zero or out of bounds)\n", -/*010*/ "invalid function or declaration\n", -/*011*/ "invalid outside functions\n", -/*012*/ "invalid function call, not a valid address\n", -/*013*/ "no entry point (no public functions)\n", -/*014*/ "invalid statement; not in switch\n", -/*015*/ "\"default\" case must be the last case in switch statement\n", -/*016*/ "multiple defaults in \"switch\"\n", -/*017*/ "undefined symbol \"%s\"\n", -/*018*/ "initialization data exceeds declared size\n", -/*019*/ "not a label: \"%s\"\n", -/*020*/ "invalid symbol name \"%s\"\n", -/*021*/ "symbol already defined: \"%s\"\n", -/*022*/ "must be lvalue (non-constant)\n", -/*023*/ "array assignment must be simple assignment\n", -/*024*/ "\"break\" or \"continue\" is out of context\n", -/*025*/ "function heading differs from prototype\n", -/*026*/ "no matching \"#if...\"\n", -/*027*/ "invalid character constant\n", -/*028*/ "invalid subscript (not an array or too many subscripts): \"%s\"\n", -/*029*/ "invalid expression, assumed zero\n", -/*030*/ "compound statement not closed at the end of file (started at line %d)\n", -/*031*/ "unknown directive\n", -/*032*/ "array index out of bounds (variable \"%s\")\n", -/*033*/ "array must be indexed (variable \"%s\")\n", -/*034*/ "argument does not have a default value (argument %d)\n", -/*035*/ "argument type mismatch (argument %d)\n", -/*036*/ "empty statement\n", -/*037*/ "invalid string (possibly non-terminated string)\n", -/*038*/ "extra characters on line\n", -/*039*/ "constant symbol has no size\n", -/*040*/ "duplicate \"case\" label (value %d)\n", -/*041*/ "invalid ellipsis, array size is not known\n", -/*042*/ "invalid combination of class specifiers\n", -/*043*/ "character constant exceeds range for packed string\n", -/*044*/ "positional parameters must precede all named parameters\n", -/*045*/ "too many function arguments\n", -/*046*/ "unknown array size (variable \"%s\")\n", -/*047*/ "array sizes do not match, or destination array is too small\n", -/*048*/ "array dimensions do not match\n", -/*049*/ "invalid line continuation\n", -/*050*/ "invalid range\n", -/*051*/ "invalid subscript, use \"[ ]\" operators on major dimensions\n", -/*052*/ "multi-dimensional arrays must be fully initialized\n", -/*053*/ "exceeding maximum number of dimensions\n", -/*054*/ "unmatched closing brace (\"}\")\n", -/*055*/ "start of function body without function header\n", -/*056*/ "arrays, local variables and function arguments cannot be public (variable \"%s\")\n", -/*057*/ "unfinished expression before compiler directive\n", -/*058*/ "duplicate argument; same argument is passed twice\n", -/*059*/ "function argument may not have a default value (variable \"%s\")\n", -/*060*/ "multiple \"#else\" directives between \"#if ... #endif\"\n", -/*061*/ "\"#elseif\" directive follows an \"#else\" directive\n", -/*062*/ "number of operands does not fit the operator\n", -/*063*/ "function result tag of operator \"%s\" must be \"%s\"\n", -/*064*/ "cannot change predefined operators\n", -/*065*/ "function argument may only have a single tag (argument %d)\n", -/*066*/ "function argument may not be a reference argument or an array (argument \"%s\")\n", -/*067*/ "variable cannot be both a reference and an array (variable \"%s\")\n", -/*068*/ "invalid rational number precision in #pragma\n", -/*069*/ "rational number format already defined\n", -/*070*/ "rational number support was not enabled\n", -/*071*/ "user-defined operator must be declared before use (function \"%s\")\n", -/*072*/ "\"sizeof\" operator is invalid on \"function\" symbols\n", -/*073*/ "function argument must be an array (argument \"%s\")\n", -/*074*/ "#define pattern must start with an alphabetic character\n", -/*075*/ "input line too long (after substitutions)\n", -/*076*/ "syntax error in the expression, or invalid function call\n", -/*077*/ "malformed UTF-8 encoding, or corrupted file: %s\n", -/*078*/ "function uses both \"return\" and \"return \"\n", -/*079*/ "inconsistent return types (array & non-array)\n", -/*080*/ "unknown symbol, or not a constant symbol (symbol \"%s\")\n", -/*081*/ "cannot take a tag as a default value for an indexed array parameter (symbol \"%s\")\n", -/*082*/ "user-defined operators and native functions may not have states\n", -/*083*/ "a function or variable may only belong to a single automaton (symbol \"%s\")\n", -/*084*/ "state conflict: one of the states is already assigned to another implementation (symbol \"%s\")\n", -/*085*/ "no states are defined for symbol \"%s\"\n", -/*086*/ "unknown automaton \"%s\"\n", -/*087*/ "unknown state \"%s\" for automaton \"%s\"\n", -/*088*/ "public variables and local variables may not have states (symbol \"%s\")\n", -/*089*/ "state variables may not be initialized (symbol \"%s\")\n", -/*090*/ "public functions may not return arrays (symbol \"%s\")\n", -/*091*/ "ambiguous constant; tag override is required (symbol \"%s\")\n" -#else - "\271pect\235\306k\213:\227\316bu\202fo\217\206\216\012", - "\201l\223\252s\203g\352\315e\234\202(\255\363\201) c\355f\240\344w ea\275 \042c\351e\042\012", - "\233cl\333\237\304\252\344c\337\327\324appe\204 \372\252\343\364o\217\206\236ock\012", - "\366\227 \272\242i\364le\234t\274\012", - "\273\367\242\340\376\266t\314", - "\360a\253gn\235\306 \355\256y\012", - "\353\224\255c\226\242\313\220\326\274\012", - "\360\252\354\202\363\201; \351\375m\235z\210o\012", - "\265\303\335\200(nega\205ve\316z\210\371\255ou\202\304bo\217ds\232", - "\265\273\255\233cl\333\214\012", - "\265out\222d\200\366\314", - "\265\273c\212l\316\242\252\262add\220s\314", - "\221 \213tr\223po\203\202(\221 pu\236\332 \366s\232", - "\265\315e\234t; \242\372s\362t\275\012", - "\042\302a\342t\330c\351\200\360\270\200l\351\202c\351\200\372s\362t\275 \315e\234t\012", - "m\342\205p\352\302a\342t\207\372\042s\362t\275\042\012", - "\217\326\235\277\012", - "\203i\205\212iza\237d\224\252\271ce\274\207\233cl\204\235\335\322", - "\242\252lab\341\347", - "\265\250 nam\200\216\012", - "\250 \212\220ad\223\326\274\347", - "\360l\243u\200(n\201-\354t\232", - "\303a\253gn\234\202\360\222\364\352a\253gn\234t\012", - "\042b\220ak\330\255\042\307t\203ue\330\272ou\202\304\307t\271t\012", - "\273head\357\334ff\210\207from pro\306typ\322", - "\221 \345\275\357\042#if...\042\012", - "\265\275\333ct\261\354t\012", - "\265\375bscrip\202(\242\355\303\255\306\371m\226\223\375bscripts)\347", - "\265\363\201\316\351\375m\235z\210o\012", - "\343\364o\217\206\315e\234\202\242c\344s\235a\202\270\200\213\206\304\361\352(\231\204t\235a\202l\203\200%d\232", - "\217k\221w\336\334\220c\205v\322", - "\303\203\233x ou\202\304bo\217d\207(\327\216\232", - "\303\360\203\233x\235(\327\216\232", - "\312do\310\242\340\376\252\302a\342\202\243u\200(\312%d\232", - "\312typ\200mis\345\275 (\312%d\232", - "e\364t\223\315e\234t\012", - "\265\231r\357(po\253\236\223n\201-\365m\203\224\235\231r\203g\232", - "\271t\241 \275\333c\365\207\331l\203\322", - "\354\202\250 \340\207\221 \335\322", - "dupl\332\224\200\042c\351e\330lab\341 (\243u\200%d\232", - "\265\341lip\222s\316\303\335\200\272\242k\221wn\012", - "\265\343\230\203a\237\304cl\351\207speci\361\210\314", - "\275\333ct\261\354\202\271ce\274\207r\226g\200f\255pack\235\231r\203g\012", - "po\222\214\337p\333me\365\207\324\311c\274\200\212l nam\235p\333me\365\314", - "\306\371m\226\223\273\266t\314", - "\217k\221w\336\303\335\200(\327\216\232", - "\303\335\310d\371\242\345\275\316\255\233\231\203a\237\303\272\306\371sm\212l\012", - "\303\334\234\222\201\207d\371\242\345\275\012", - "\265l\203\200\307t\203ua\214\012", - "\265r\226g\322", - "\265\375bscript\316\251\200\042[ ]\330\353\224\225\207\331\305j\255\334\234\222\201\314", - "m\342\205-\334\234\222\201\337\256y\207\360f\342l\223\203i\205\212iz\274\012", - "\271ce\274\357\305ximum \374\230\261\304\334\234\222\201\314", - "\217\345\275\235c\344s\357b\241c\200(\042}\042\232", - "\231\204\202\304\273bod\223\362\270ou\202\273head\210\012", - "\256ys\316\344c\337\301\310\226\206\273\266t\207c\226\242\313pu\236\332 (\327\216\232", - "\217f\203ish\235\363\331be\370\200\343\364il\261\334\220c\205v\322", - "dupl\332\224\200\266t; sam\200\312\272p\351s\235tw\332\322", - "\273\312\367\242\340\376\252\302a\342\202\243u\200(\327\216\232", - "m\342\205p\352\042#\341se\330\334\220c\205v\310betwe\213 \042#if ... #\213\334f\042\012", - "\042#\341seif\330\334\220c\205\376f\240\344w\207\355\042#\341se\330\334\220c\205v\322", - "\374\230\261\304\353\226d\207do\310\242\361\202\270\200\353\224\225\012", - "\273\220s\342\202\373\304\353\224\225\227 \360\216\012", - "c\226\242\275\226g\200\311\326\235\353\224\225\314", - "\273\312\367\201l\223\340\376\252s\203g\352\373(\312%d\232", - "\273\312\367\242\313\252\220f\210\213c\200\312\255\355\303(\312\216\232", - "\327c\226\242\313bo\270 \252\220f\210\213c\200\226\206\355\303(\327\216\232", - "\265\241\214\337\374\230\261\311ci\222\331\372#p\241g\305\012", - "\241\214\337\374\230\261\370\305\202\212\220ad\223\326\274\012", - "\241\214\337\374\230\261\375pp\225\202wa\207\242\213\254\274\012", - "\251\210-\326\235\353\224\255\360\233cl\204\235be\370\200\251\200(\366\227\232", - "\042\335e\267\330\353\224\255\272\265\331\042\366\330\250\314", - "\273\312\360\355\303(\312\216\232", - "#\326\200p\224\365\336\324\231\204\202\362\270 \355\212p\340be\205c \275\333c\365\012", - "\203pu\202l\203\200\306\371l\201\260(aft\261\375bs\205tu\214s\232", - "\246n\325x \210r\255\372\270\200\363\201\316\255\265\273c\212l\012", - "m\212\370m\235UTF-8 \213\343d\203g\316\255c\225rupt\235\361le: \211\012", - "\273\251\310bo\270 \042\220turn\330\226\206\042\220tur\336<\243ue>\042\012", - "\203\307\222\231\213\202\220tur\336typ\310(\303& n\201-\256y\232", - "\217k\221w\336\250\316\255\242\252\354\202\250 \323", - "c\226\242\325k\200\252\373a\207\252\302a\342\202\243u\200f\255\355\203\233x\235\303p\333met\261\323", - "\251\210-\326\235\353\224\225\207\226\206na\205\376\366\207\367\242\340\376\315e\314", - "\252\273\255\327\367\201l\223b\341\201\260\306 \252s\203g\352au\306\345\331\323", - "\315\200\307fl\332t: \201\200\304\270\200\315\310\272\212\220ad\223a\253gn\235\306 a\221\270\261i\364le\234\325\237\323", - "\221 \315\310\204\200\326\235f\255\277\012", - "\217k\221w\336au\306\345\201\321", - "\217k\221w\336\315\200\216 f\255au\306\345\201\321", - "pu\236\332 \301\310\226\206\344c\337\301\310\367\242\340\376\315\310\323", - "\315\200\301\310\367\242\313\203i\205\212iz\235\323", - "pu\236\332 \366\207\367\242\220tur\336\256y\207\323", - "a\230i\263ou\207\354t; \373ov\210rid\200\272\220qui\220\206\323" -#endif - }; - -static char *fatalmsg[] = { -#ifdef SCPACK -/*100*/ "cannot read from file: \"%s\"\n", -/*101*/ "cannot write to file: \"%s\"\n", -/*102*/ "table overflow: \"%s\"\n", - /* table can be: loop table - * literal table - * staging buffer - * option table (response file) - * peephole optimizer table - */ -/*103*/ "insufficient memory\n", -/*104*/ "invalid assembler instruction \"%s\"\n", -/*105*/ "numeric overflow, exceeding capacity\n", -/*106*/ "compiled script exceeds the maximum memory size (%ld bytes)\n", -/*107*/ "too many error messages on one line\n", -/*108*/ "codepage mapping file not found\n", -/*109*/ "invalid path: \"%s\"\n", -/*110*/ "assertion failed: %s\n", -/*111*/ "user error: %s\n" -#else - "c\226\242\220a\206from \361le\347", - "c\226\242writ\200\306 \361le\347", - "t\254\200ov\210f\344w\347", - "\203\375ff\332i\213\202mem\225y\012", - "\265\351se\230l\261\203\231ruc\214\321", - "\374m\210\332 ov\210f\344w\316\271ce\274\357capacity\012", - "\343\364il\235scrip\202\271ce\274\207\270\200\305ximum mem\225\223\335\200(%l\206bytes\232", - "\306\371m\226\223\210r\255messag\310\331\201\200l\203\322", - "\343\233pag\200\305pp\357\361\352\242fo\217d\012", - "\265p\224h\347", - "\351s\210\237fail\274: \211\012", - "\251\261\210r\225: \211\012" -#endif - }; - -static char *warnmsg[] = { -#ifdef SCPACK -/*200*/ "symbol \"%s\" is truncated to %d characters\n", -/*201*/ "redefinition of constant/macro (symbol \"%s\")\n", -/*202*/ "number of arguments does not match definition\n", -/*203*/ "symbol is never used: \"%s\"\n", -/*204*/ "symbol is assigned a value that is never used: \"%s\"\n", -/*205*/ "redundant code: constant expression is zero\n", -/*206*/ "redundant test: constant expression is non-zero\n", -/*207*/ "unknown #pragma\n", -/*208*/ "function with tag result used before definition, forcing reparse\n", -/*209*/ "function \"%s\" should return a value\n", -/*210*/ "possible use of symbol before initialization: \"%s\"\n", -/*211*/ "possibly unintended assignment\n", -/*212*/ "possibly unintended bitwise operation\n", -/*213*/ "tag mismatch\n", -/*214*/ "possibly a \"const\" array argument was intended: \"%s\"\n", -/*215*/ "expression has no effect\n", -/*216*/ "nested comment\n", -/*217*/ "loose indentation\n", -/*218*/ "old style prototypes used with optional semicolumns\n", -/*219*/ "local variable \"%s\" shadows a variable at a preceding level\n", -/*220*/ "expression with tag override must appear between parentheses\n", -/*221*/ "label name \"%s\" shadows tag name\n", -/*222*/ "number of digits exceeds rational number precision\n", -/*223*/ "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n", -/*224*/ "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n", -/*225*/ "unreachable code\n", -/*226*/ "a variable is assigned to itself (symbol \"%s\")\n", -/*227*/ "more initiallers than enum fields\n", -/*228*/ "length of initialler exceeds size of the enum field\n", -/*229*/ "index tag mismatch (symbol \"%s\")\n", -/*230*/ "no implementation for state \"%s\" in function \"%s\", no fall-back\n", -/*231*/ "state specification on forward declaration is ignored\n", -/*232*/ "output file is written, but with compact encoding disabled\n", -/*233*/ "state variable \"%s\" shadows a global variable\n", -/*234*/ "function is deprecated (symbol \"%s\") %s\n", -/*235*/ "public function lacks forward declaration (symbol \"%s\")\n", -/*236*/ "unknown parameter in substitution (incorrect #define pattern)\n", -/*237*/ "user warning: %s\n" -#else - "\277 \272tr\244\224\235\306 %\206\275\333c\365\314", - "\220\326i\237\304\354t/\305cr\371\323", - "\374\230\261\304\266t\207do\310\242\345\275 \326i\214\012", - "\250 \272nev\261\251\274\347", - "\250 \272a\253gn\235\252\243u\200\270a\202\272nev\261\251\274\347", - "\220d\217d\226\202\343\233: \354\202\363\331\272z\210o\012", - "\220d\217d\226\202te\231: \354\202\363\331\272n\201-z\210o\012", - "\217k\221w\336#p\241g\305\012", - "\273\362\270 \373\220s\342\202\251\235be\370\200\326i\214\316\370c\357\220p\204s\322", - "\366\227 sho\342\206\220tur\336\252\243u\322", - "po\253\236\200\251\200\304\250 be\370\200\203i\205\212iza\214\347", - "po\253\236\223\217\203t\213\233\206a\253gn\234t\012", - "po\253\236\223\217\203t\213\233\206bit\362s\200\353a\214\012", - "\373mis\345\275\012", - "po\253\236\223\252\042\346\330\303\312wa\207\203t\213\233d\347", - "\363\331\340\207\221 effect\012", - "ne\231\235\343m\234t\012", - "\344os\200\203d\213\325\214\012", - "\240\206\231y\352pro\306typ\310\251\235\362\270 \350\214\337sem\332\240umn\314", - "\344c\337\327\216 s\340dow\207\252\327a\202\252\311c\274\357lev\341\012", - "\363\331\362\270 \373ov\210rid\200\324appe\204 betwe\213 p\204\213\270ese\314", - "lab\341 nam\200\216 s\340dow\207\373nam\322", - "\374\230\261\304\334git\207\271ce\274\207\241\214\337\374\230\261\311ci\222\201\012", - "\220d\217d\226\202\042\335e\267\042: \312\335\200\272\212way\2071 \323", - "\203\233\365m\203\224\200\303\335\200\372\042\335e\267\330\363\331\323", - "\217\220a\275\254\200\343\233\012", - "\252\327\272a\253gn\235\306 its\341f \323", - "m\225\200\203i\205\212l\210\207\270\355\213um \361\341d\314", - "l\213g\270 \304\203i\205\212l\261\271ce\274\207\335\200\304\270\200\213um \361\341d\012", - "\203\233x \373mis\345\275 \323", - "\221 i\364le\234\325\237f\255\315\200\216 \372\366\227\316\221 f\212l-back\012", - "\315\200specif\332a\237\331\370w\204\206\233cl\333\237\272ig\221\220d\012", - "outpu\202\361\352\272writt\213\316bu\202\362\270 \343\364ac\202\213\343d\357\334s\254\274\012", - "\315\200\327\216 s\340dow\207\252g\344b\337\301\322", - "\273\272\233\311c\224\235\317) \211\012", - "pu\236\332 \273lack\207\370w\204\206\233cl\333\237\323", - "\217k\221w\336p\333met\261\372\375bs\205tu\237(\203c\225\220c\202#\326\200p\224\365n\232", - "\251\261w\204n\203g: \211\012" -#endif - }; diff --git a/source/compiler/sc7.c b/source/compiler/sc7.c index e460b45..abe28d4 100644 --- a/source/compiler/sc7.c +++ b/source/compiler/sc7.c @@ -57,16 +57,1193 @@ #endif #include "sc.h" -#if defined _MSC_VER - #pragma warning(push) - #pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */ -#endif +#define seqsize(o,p) (opcodes(o)+opargs(p)) +typedef struct { + char *find; + char *replace; + int savesize; /* number of bytes saved (in bytecode) */ +} SEQUENCE; -#include "sc7.scp" - -#if defined _MSC_VER - #pragma warning(pop) +static SEQUENCE sequences_cmp[] = { + /* A very common sequence in four varieties + * load.s.pri n1 load.s.pri n2 + * push.pri load.s.alt n1 + * load.s.pri n2 - + * pop.alt - + * -------------------------------------- + * load.pri n1 load.s.pri n2 + * push.pri load.alt n1 + * load.s.pri n2 - + * pop.alt - + * -------------------------------------- + * load.s.pri n1 load.pri n2 + * push.pri load.s.alt n1 + * load.pri n2 - + * pop.alt - + * -------------------------------------- + * load.pri n1 load.pri n2 + * push.pri load.alt n1 + * load.pri n2 - + * pop.alt - + */ + { + "load.s.pri %1!push.pri!load.s.pri %2!pop.alt!", + "load.s.pri %2!load.s.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!push.pri!load.s.pri %2!pop.alt!", + "load.s.pri %2!load.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.s.pri %1!push.pri!load.pri %2!pop.alt!", + "load.pri %2!load.s.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!push.pri!load.pri %2!pop.alt!", + "load.pri %2!load.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + /* (#1#) The above also occurs with "addr.pri" (array + * indexing) as the first line; so that adds 2 cases. + */ + { + "addr.pri %1!push.pri!load.s.pri %2!pop.alt!", + "addr.alt %1!load.s.pri %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "addr.pri %1!push.pri!load.pri %2!pop.alt!", + "addr.alt %1!load.pri %2!", + seqsize(4,2) - seqsize(2,2) + }, + /* And the same sequence with const.pri as either the first + * or the second load instruction: four more cases. + */ + { + "const.pri %1!push.pri!load.s.pri %2!pop.alt!", + "load.s.pri %2!const.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "const.pri %1!push.pri!load.pri %2!pop.alt!", + "load.pri %2!const.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.s.pri %1!push.pri!const.pri %2!pop.alt!", + "const.pri %2!load.s.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!push.pri!const.pri %2!pop.alt!", + "const.pri %2!load.alt %1!", + seqsize(4,2) - seqsize(2,2) + }, + /* The same as above, but now with "addr.pri" (array + * indexing) on the first line and const.pri on + * the second. + */ + { + "addr.pri %1!push.pri!const.pri %2!pop.alt!", + "addr.alt %1!const.pri %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "addr.pri %1!push.pri!zero.pri!pop.alt!", + "addr.alt %1!zero.pri!", + seqsize(4,1) - seqsize(2,1) + }, + /* ??? add references */ + /* Chained relational operators can contain sequences like: + * move.pri load.s.pri n1 + * push.pri - + * load.s.pri n1 - + * pop.alt - + * The above also accurs for "load.pri" and for "const.pri", + * so add another two cases. + */ + { + "move.pri!push.pri!load.s.pri %1!pop.alt!", + "load.s.pri %1!", + seqsize(4,1) - seqsize(1,1) + }, + { + "move.pri!push.pri!load.pri %1!pop.alt!", + "load.pri %1!", + seqsize(4,1) - seqsize(1,1) + }, + { + "move.pri!push.pri!const.pri %1!pop.alt!", + "const.pri %1!", + seqsize(4,1) - seqsize(1,1) + }, + /* More optimizations for chained relational operators; the + * continuation sequences can be simplified if they turn out + * to be termination sequences: + * xchg sless also for sless, sgeq and sleq + * sgrtr pop.alt + * swap.alt and + * and ;$exp + * pop.alt - + * ;$exp - + * -------------------------------------- + * xchg sless also for sless, sgeq and sleq + * sgrtr pop.alt + * swap.alt and + * and jzer n1 + * pop.alt - + * jzer n1 - + * -------------------------------------- + * xchg jsgeq n1 also for sless, sgeq and sleq + * sgrtr ;$exp (occurs for non-chained comparisons) + * jzer n1 - + * ;$exp - + * -------------------------------------- + * xchg sless also for sless, sgeq and sleq + * sgrtr ;$exp (occurs for non-chained comparisons) + * ;$exp - + */ + { + "xchg!sgrtr!swap.alt!and!pop.alt!;$exp!", + "sless!pop.alt!and!;$exp!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sless!swap.alt!and!pop.alt!;$exp!", + "sgrtr!pop.alt!and!;$exp!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sgeq!swap.alt!and!pop.alt!;$exp!", + "sleq!pop.alt!and!;$exp!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sleq!swap.alt!and!pop.alt!;$exp!", + "sgeq!pop.alt!and!;$exp!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sgrtr!swap.alt!and!pop.alt!jzer %1!", + "sless!pop.alt!and!jzer %1!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sless!swap.alt!and!pop.alt!jzer %1!", + "sgrtr!pop.alt!and!jzer %1!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sgeq!swap.alt!and!pop.alt!jzer %1!", + "sleq!pop.alt!and!jzer %1!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sleq!swap.alt!and!pop.alt!jzer %1!", + "sgeq!pop.alt!and!jzer %1!", + seqsize(5,0) - seqsize(3,0) + }, + { + "xchg!sgrtr!jzer %1!;$exp!", + "jsgeq %1!;$exp!", + seqsize(3,1) - seqsize(1,1) + }, + { + "xchg!sless!jzer %1!;$exp!", + "jsleq %1!;$exp!", + seqsize(3,1) - seqsize(1,1) + }, + { + "xchg!sgeq!jzer %1!;$exp!", + "jsgrtr %1!;$exp!", + seqsize(3,1) - seqsize(1,1) + }, + { + "xchg!sleq!jzer %1!;$exp!", + "jsless %1!;$exp!", + seqsize(3,1) - seqsize(1,1) + }, + { + "xchg!sgrtr!;$exp!", + "sless!;$exp!", + seqsize(2,0) - seqsize(1,0) + }, + { + "xchg!sless!;$exp!", + "sgrtr!;$exp!", + seqsize(2,0) - seqsize(1,0) + }, + { + "xchg!sgeq!;$exp!", + "sleq!;$exp!", + seqsize(2,0) - seqsize(1,0) + }, + { + "xchg!sleq!;$exp!", + "sgeq!;$exp!", + seqsize(2,0) - seqsize(1,0) + }, + /* The entry to chained operators is also opt to optimization + * load.s.pri n1 load.s.pri n2 + * load.s.alt n2 load.s.alt n1 + * xchg - + * -------------------------------------- + * load.s.pri n1 load.pri n2 + * load.alt n2 load.s.alt n1 + * xchg - + * -------------------------------------- + * load.s.pri n1 const.pri n2 + * const.alt n2 load.s.alt n1 + * xchg - + * -------------------------------------- + * and all permutations... + */ + { + "load.s.pri %1!load.s.alt %2!xchg!", + "load.s.pri %2!load.s.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "load.s.pri %1!load.alt %2!xchg!", + "load.pri %2!load.s.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "load.s.pri %1!const.alt %2!xchg!", + "const.pri %2!load.s.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "load.pri %1!load.s.alt %2!xchg!", + "load.s.pri %2!load.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "load.pri %1!load.alt %2!xchg!", + "load.pri %2!load.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "load.pri %1!const.alt %2!xchg!", + "const.pri %2!load.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "const.pri %1!load.s.alt %2!xchg!", + "load.s.pri %2!const.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "const.pri %1!load.alt %2!xchg!", + "load.pri %2!const.alt %1!", + seqsize(3,2) - seqsize(2,2) + }, + /* some sequences where PRI is moved to ALT can be optimized + * further when considering what follows + * move.alt const.alt n1 + * const.pri %1 - + * xchg - + * (also for load.s.pri and load.pri) + * -------------------------------------- + * lref.pri %1 lref.alt %1 + * move.alt [load.pri %2] + * [load.pri %2] - + * (where [load.pri %2] may also be another operatrion loading PRI) + */ + { + "move.alt!const.pri %1!xchg!", + "const.alt %1!", + seqsize(3,1) - seqsize(1,1) + }, + { + "move.alt!load.pri %1!xchg!", + "load.alt %1!", + seqsize(3,1) - seqsize(1,1) + }, + { + "move.alt!load.s.pri %1!xchg!", + "load.s.alt %1!", + seqsize(3,1) - seqsize(1,1) + }, + /* ----- */ + { + "lref.pri %1!move.alt!load.pri %2!", + "lref.alt %1!load.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + { + "lref.pri %1!move.alt!load.s.pri %2!", + "lref.alt %1!load.s.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + { + "lref.pri %1!move.alt!const.pri %2!", + "lref.alt %1!const.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + { + "lref.s.pri %1!move.alt!load.pri %2!", + "lref.s.alt %1!load.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + { + "lref.s.pri %1!move.alt!load.s.pri %2!", + "lref.s.alt %1!load.s.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + { + "lref.s.pri %1!move.alt!const.pri %2!", + "lref.s.alt %1!const.pri %2!", + seqsize(3,2) - seqsize(2,2) + }, + /* Array indexing can merit from special instructions. + * Simple indexed array lookup can be optimized quite + * a bit. + * addr.pri n1 addr.alt n1 + * push.pri load.s.pri n2 + * load.s.pri n2 bounds n3 + * bounds n3 lidx.b n4 + * shl.c.pri n4 - + * pop.alt - + * add - + * load.i - + * + * And to prepare for storing a value in an array + * addr.pri n1 addr.alt n1 + * push.pri load.s.pri n2 + * load.s.pri n2 bounds n3 + * bounds n3 idxaddr.b n4 + * shl.c.pri n4 - + * pop.alt - + * add - + * + * Notes (additional cases): + * 1. instruction addr.pri can also be const.pri (for + * global arrays) + * 2. the bounds instruction can be absent + * 3. when "n4" (the shift value) is the 2 (with 32-bit cells), use the + * even more optimal instructions LIDX and IDDXADDR + * + * If the array index is more complex, one can only optimize + * the last four instructions: + * shl.c.pri n1 pop.alt + * pop.alt lidx.b n1 + * add - + * loadi - + * -------------------------------------- + * shl.c.pri n1 pop.alt + * pop.alt idxaddr.b n1 + * add - + */ +#if !defined BIT16 + /* loading from array, "cell" shifted */ + { + "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!", + "addr.alt %1!load.s.pri %2!bounds %3!lidx!", + seqsize(8,4) - seqsize(4,3) + }, + { + "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!", + "const.alt %1!load.s.pri %2!bounds %3!lidx!", + seqsize(8,4) - seqsize(4,3) + }, + { + "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!", + "addr.alt %1!load.s.pri %2!lidx!", + seqsize(7,3) - seqsize(3,2) + }, + { + "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!", + "const.alt %1!load.s.pri %2!lidx!", + seqsize(7,3) - seqsize(3,2) + }, #endif + /* loading from array, not "cell" shifted */ + { + "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!", + "addr.alt %1!load.s.pri %2!bounds %3!lidx.b %4!", + seqsize(8,4) - seqsize(4,4) + }, + { + "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!", + "const.alt %1!load.s.pri %2!bounds %3!lidx.b %4!", + seqsize(8,4) - seqsize(4,4) + }, + { + "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!", + "addr.alt %1!load.s.pri %2!lidx.b %3!", + seqsize(7,3) - seqsize(3,3) + }, + { + "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!", + "const.alt %1!load.s.pri %2!lidx.b %3!", + seqsize(7,3) - seqsize(3,3) + }, +#if !defined BIT16 + /* array index calculation for storing a value, "cell" aligned */ + { + "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!", + "addr.alt %1!load.s.pri %2!bounds %3!idxaddr!", + seqsize(7,4) - seqsize(4,3) + }, + { + "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!", + "const.alt %1!load.s.pri %2!bounds %3!idxaddr!", + seqsize(7,4) - seqsize(4,3) + }, + { + "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!", + "addr.alt %1!load.s.pri %2!idxaddr!", + seqsize(6,3) - seqsize(3,2) + }, + { + "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!", + "const.alt %1!load.s.pri %2!idxaddr!", + seqsize(6,3) - seqsize(3,2) + }, +#endif + /* array index calculation for storing a value, not "cell" packed */ + { + "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!", + "addr.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!", + seqsize(7,4) - seqsize(4,4) + }, + { + "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!", + "const.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!", + seqsize(7,4) - seqsize(4,4) + }, + { + "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!", + "addr.alt %1!load.s.pri %2!idxaddr.b %3!", + seqsize(6,3) - seqsize(3,3) + }, + { + "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!", + "const.alt %1!load.s.pri %2!idxaddr.b %3!", + seqsize(6,3) - seqsize(3,3) + }, +#if !defined BIT16 + /* the shorter array indexing sequences, see above for comments */ + { + "shl.c.pri 2!pop.alt!add!loadi!", + "pop.alt!lidx!", + seqsize(4,1) - seqsize(2,0) + }, + { + "shl.c.pri 2!pop.alt!add!", + "pop.alt!idxaddr!", + seqsize(3,1) - seqsize(2,0) + }, +#endif + { + "shl.c.pri %1!pop.alt!add!loadi!", + "pop.alt!lidx.b %1!", + seqsize(4,1) - seqsize(2,1) + }, + { + "shl.c.pri %1!pop.alt!add!", + "pop.alt!idxaddr.b %1!", + seqsize(3,1) - seqsize(2,1) + }, + /* For packed arrays, there is another case (packed arrays + * do not take advantage of the LIDX or IDXADDR instructions). + * addr.pri n1 addr.alt n1 + * push.pri load.s.pri n2 + * load.s.pri n2 bounds n3 + * bounds n3 - + * pop.alt - + * + * Notes (additional cases): + * 1. instruction addr.pri can also be const.pri (for + * global arrays) + * 2. the bounds instruction can be absent, but that + * case is already handled (see #1#) + */ + { + "addr.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!", + "addr.alt %1!load.s.pri %2!bounds %3!", + seqsize(5,3) - seqsize(3,3) + }, + { + "const.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!", + "const.alt %1!load.s.pri %2!bounds %3!", + seqsize(5,3) - seqsize(3,3) + }, + /* Declaration of simple variables often follows the sequence: + * ;$lcl ;$lcl + * stack -4 push.c + * const.pri ;$exp + * stor.s.pri - + * ;$exp - + */ + { + ";$lcl %1 %2!stack -4!const.pri %3!stor.s.pri %2!;$exp!", + ";$lcl %1 %2!push.c %3!;$exp!", + seqsize(3,3) - seqsize(1,1) + }, + { + ";$lcl %1 %2!stack -4!zero.pri!stor.s.pri %2!;$exp!", + ";$lcl %1 %2!push.c 0!;$exp!", + seqsize(3,2) - seqsize(1,1) + }, + /* During a calculation, the intermediate result must sometimes + * be moved from PRI to ALT, like in: + * push.pri move.alt + * load.s.pri n1 load.s.pri n1 + * pop.alt - + * + * The above also accurs for "load.pri" and for "const.pri", + * so add another two cases. + */ + { + "push.pri!load.s.pri %1!pop.alt!", + "move.alt!load.s.pri %1!", + seqsize(3,1) - seqsize(2,1) + }, + { + "push.pri!load.pri %1!pop.alt!", + "move.alt!load.pri %1!", + seqsize(3,1) - seqsize(2,1) + }, + { + "push.pri!const.pri %1!pop.alt!", + "move.alt!const.pri %1!", + seqsize(3,1) - seqsize(2,1) + }, + { + "push.pri!zero.pri!pop.alt!", + "move.alt!zero.pri!", + seqsize(3,0) - seqsize(2,0) + }, + /* saving PRI and then loading from its address + * occurs when indexing a multi-dimensional array + */ + { + "push.pri!load.i!pop.alt!", + "move.alt!load.i!", + seqsize(3,0) - seqsize(2,0) + }, + /* An even simpler PUSH/POP optimization (occurs in + * switch statements): + * push.pri move.alt + * pop.alt - + */ + { + "push.pri!pop.alt!", + "move.alt!", + seqsize(2,0) - seqsize(1,0) + }, + /* Some simple arithmetic sequences + */ + { + "move.alt!load.s.pri %1!add!", + "load.s.alt %1!add!", + seqsize(3,1) - seqsize(2,1) + }, + { + "move.alt!load.pri %1!add!", + "load.alt %1!add!", + seqsize(3,1) - seqsize(2,1) + }, + { + "move.alt!const.pri %1!add!", + "const.alt %1!add!", + seqsize(3,1) - seqsize(2,1) + }, + { + "move.alt!load.s.pri %1!sub.alt!", + "load.s.alt %1!sub!", + seqsize(3,1) - seqsize(2,1) + }, + { + "move.alt!load.pri %1!sub.alt!", + "load.alt %1!sub!", + seqsize(3,1) - seqsize(2,1) + }, + { + "move.alt!const.pri %1!sub.alt!", + "const.alt %1!sub!", + seqsize(3,1) - seqsize(2,1) + }, + /* User-defined operators first load the operands into registers and + * then have them pushed onto the stack. This can give rise to sequences + * like: + * const.pri n1 push.c n1 + * const.alt n2 push.c n2 + * push.pri - + * push.alt - + * A similar sequence occurs with the two PUSH.pri/alt instructions inverted. + * The first, second, or both CONST.pri/alt instructions can also be + * LOAD.pri/alt. + * This gives 2 x 4 cases. + */ + { + "const.pri %1!const.alt %2!push.pri!push.alt!", + "push.c %1!push.c %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "const.pri %1!const.alt %2!push.alt!push.pri!", + "push.c %2!push.c %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "const.pri %1!load.alt %2!push.pri!push.alt!", + "push.c %1!push %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "const.pri %1!load.alt %2!push.alt!push.pri!", + "push %2!push.c %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!const.alt %2!push.pri!push.alt!", + "push %1!push.c %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!const.alt %2!push.alt!push.pri!", + "push.c %2!push %1!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!load.alt %2!push.pri!push.alt!", + "push %1!push %2!", + seqsize(4,2) - seqsize(2,2) + }, + { + "load.pri %1!load.alt %2!push.alt!push.pri!", + "push %2!push %1!", + seqsize(4,2) - seqsize(2,2) + }, + /* Function calls (parameters are passed on the stack) + * load.s.pri n1 push.s n1 + * push.pri - + * -------------------------------------- + * load.pri n1 push n1 + * push.pri - + * -------------------------------------- + * const.pri n1 push.c n1 + * push.pri - + * -------------------------------------- + * zero.pri push.c 0 + * push.pri - + * -------------------------------------- + * addr.pri n1 push.adr n1 + * push.pri - + * + * However, PRI must not be needed after this instruction + * if this shortcut is used. Check for the ;$par comment. + */ + { + "load.s.pri %1!push.pri!;$par!", + "push.s %1!;$par!", + seqsize(2,1) - seqsize(1,1) + }, + { + "load.pri %1!push.pri!;$par!", + "push %1!;$par!", + seqsize(2,1) - seqsize(1,1) + }, + { + "const.pri %1!push.pri!;$par!", + "push.c %1!;$par!", + seqsize(2,1) - seqsize(1,1) + }, + { + "zero.pri!push.pri!;$par!", + "push.c 0!;$par!", + seqsize(2,0) - seqsize(1,1) + }, + { + "addr.pri %1!push.pri!;$par!", + "push.adr %1!;$par!", + seqsize(2,1) - seqsize(1,1) + }, + /* References with a default value generate new cells on the heap + * dynamically. That code often ends with: + * move.pri push.alt + * push.pri - + */ + { + "move.pri!push.pri!", + "push.alt!", + seqsize(2,0) - seqsize(1,0) + }, + /* Simple arithmetic operations on constants. Noteworthy is the + * subtraction of a constant, since it is converted to the addition + * of the inverse value. + * const.alt n1 add.c n1 + * add - + * -------------------------------------- + * const.alt n1 add.c -n1 + * sub - + * -------------------------------------- + * const.alt n1 smul.c n1 + * smul - + * -------------------------------------- + * const.alt n1 eq.c.pri n1 + * eq - + */ + { + "const.alt %1!add!", + "add.c %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "const.alt %1!smul!", + "smul.c %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "const.alt %1!eq!", + "eq.c.pri %1!", + seqsize(2,1) - seqsize(1,1) + }, + /* Subtraction of a constant. Note that the subtraction is converted to + * the addition of the inverse value. + * const.pri n1 load.s.pri n2 + * load.s.alt n2 add.c -n1 + * sub - + * -------------------------------------- + * const.pri n1 load.pri n2 + * load.alt n2 add.c -n1 + * sub - + */ + { + "const.pri %1!load.s.alt %2!sub!", + "load.s.pri %2!add.c -%1!", + seqsize(3,2) - seqsize(2,2) + }, + { + "const.pri %1!load.alt %2!sub.alt!", + "load.pri %2!add.c -%1!", + seqsize(3,2) - seqsize(2,2) + }, + /* With arrays indexed with constants that come from enumerations, it happens + * multiple add.c opcodes follow in sequence. + * add.c n1 add.c n1+n2 + * add.c n2 - + */ + { + "add.c %1!add.c %2!", + "add.c %1+%2!", + seqsize(2,2) - seqsize(1,1) + }, + /* Compare and jump + * eq jneq n1 + * jzer n1 - + * -------------------------------------- + * eq jeq n1 + * jnz n1 - + * -------------------------------------- + * neq jeq n1 + * jzer n1 - + * -------------------------------------- + * neq jneq n1 + * jnz n1 - + * An similarly for other relations + * sless jsgeq n1 + * jzer n1 - + * -------------------------------------- + * sless jsless n1 + * jnz n1 - + * -------------------------------------- + * sleq jsgrtr n1 + * jzer n1 - + * -------------------------------------- + * sleq jsleq n1 + * jnz n1 - + * -------------------------------------- + * sgrtr jsleq n1 + * jzer n1 - + * -------------------------------------- + * sgrtr jsgrtr n1 + * jnz n1 - + * -------------------------------------- + * sgeq jsless n1 + * jzer n1 - + * -------------------------------------- + * sgeq jsgeq n1 + * jnz n1 - + * We can relax the optimizations for the unsigned comparisons, + * because the Pawn compiler currently only generates signed + * comparisons. + */ + { + "eq!jzer %1!", + "jneq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "eq!jnz %1!", + "jeq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "neq!jzer %1!", + "jeq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "neq!jnz %1!", + "jneq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sless!jzer %1!", + "jsgeq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sless!jnz %1!", + "jsless %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sleq!jzer %1!", + "jsgrtr %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sleq!jnz %1!", + "jsleq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sgrtr!jzer %1!", + "jsleq %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sgrtr!jnz %1!", + "jsgrtr %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sgeq!jzer %1!", + "jsless %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "sgeq!jnz %1!", + "jsgeq %1!", + seqsize(2,1) - seqsize(1,1) + }, + /* Test for zero (common case, especially for strings) + * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)" + * + * zero.alt jzer n1 + * jeq n1 - + * -------------------------------------- + * zero.alt jnz n1 + * jneq n1 - + */ + { + "zero.alt!jeq %1!", + "jzer %1!", + seqsize(2,1) - seqsize(1,1) + }, + { + "zero.alt!jneq %1!", + "jnz %1!", + seqsize(2,1) - seqsize(1,1) + }, + /* Incrementing and decrementing leaves a value in + * in PRI which may not be used (for example, as the + * third expression in a "for" loop). + * inc n1 inc n1 ; ++n + * load.pri n1 ;$exp + * ;$exp - + * -------------------------------------- + * load.pri n1 inc n1 ; n++, e.g. "for (n=0; n<10; n++)" + * inc n1 ;$exp + * ;$exp - + * Plus the varieties for stack relative increments + * and decrements. + */ + { + "inc %1!load.pri %1!;$exp!", + "inc %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "load.pri %1!inc %1!;$exp!", + "inc %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "inc.s %1!load.s.pri %1!;$exp!", + "inc.s %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "load.s.pri %1!inc.s %1!;$exp!", + "inc.s %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "dec %1!load.pri %1!;$exp!", + "dec %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "load.pri %1!dec %1!;$exp!", + "dec %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "dec.s %1!load.s.pri %1!;$exp!", + "dec.s %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "load.s.pri %1!dec.s %1!;$exp!", + "dec.s %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + /* ??? the same (increments and decrements) for references */ + /* Loading the constant zero has a special opcode. + * When storing zero in memory, the value of PRI must not be later on. + * const.pri 0 zero n1 + * stor.pri n1 ;$exp + * ;$exp - + * -------------------------------------- + * const.pri 0 zero.s n1 + * stor.s.pri n1 ;$exp + * ;$exp - + * -------------------------------------- + * zero.pri zero n1 + * stor.pri n1 ;$exp + * ;$exp - + * -------------------------------------- + * zero.pri zero.s n1 + * stor.s.pri n1 ;$exp + * ;$exp - + * -------------------------------------- + * const.pri 0 zero.pri + * -------------------------------------- + * const.alt 0 zero.alt + * The last two alternatives save more memory than they save + * time, but anyway... + */ + { + "const.pri 0!stor.pri %1!;$exp!", + "zero %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "const.pri 0!stor.s.pri %1!;$exp!", + "zero.s %1!;$exp!", + seqsize(2,2) - seqsize(1,1) + }, + { + "zero.pri!stor.pri %1!;$exp!", + "zero %1!;$exp!", + seqsize(2,1) - seqsize(1,1) + }, + { + "zero.pri!stor.s.pri %1!;$exp!", + "zero.s %1!;$exp!", + seqsize(2,1) - seqsize(1,1) + }, + { + "const.pri 0!", + "zero.pri!", + seqsize(1,1) - seqsize(1,0) + }, + { + "const.alt 0!", + "zero.alt!", + seqsize(1,1) - seqsize(1,0) + }, + + /* ------------------ */ + /* Macro instructions */ + /* ------------------ */ + + { "", "", 0 }, /* separator, so optimizer can stop before generating macro opcodes */ + + /* optimizing the calling of native functions (which always have a parameter + * count pushed before, and the stack pointer restored afterwards + */ + { + "push.c %1!sysreq.c %2!stack %3!", /* note: %3 == %1 + 4 */ + "sysreq.n %2 %1!", + seqsize(3,3) - seqsize(1,2) + }, + /* ----- */ + /* Functions with many parameters with the same "type" have sequences like: + * push.c n1 push3.c n1 n2 n3 + * ;$par ;$par + * push.c n2 - + * ;$par - + * push.c n3 - + * ;$par - + * etc. etc. + * + * Similar sequences occur with PUSH, PUSH.s and PUSHADDR + */ + { + "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!push.c %5!;$par!", + "push5.c %1 %2 %3 %4 %5!", + seqsize(5,5) - seqsize(1,5) + }, + { + "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!", + "push4.c %1 %2 %3 %4!", + seqsize(4,4) - seqsize(1,4) + }, + { + "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!", + "push3.c %1 %2 %3!", + seqsize(3,3) - seqsize(1,3) + }, + { + "push.c %1!;$par!push.c %2!;$par!", + "push2.c %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + /* ----- */ + { + "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!push %5!;$par!", + "push5 %1 %2 %3 %4 %5!", + seqsize(5,5) - seqsize(1,5) + }, + { + "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!", + "push4 %1 %2 %3 %4!", + seqsize(4,4) - seqsize(1,4) + }, + { + "push %1!;$par!push %2!;$par!push %3!;$par!", + "push3 %1 %2 %3!", + seqsize(3,3) - seqsize(1,3) + }, + { + "push %1!;$par!push %2!;$par!", + "push2 %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + /* ----- */ + { + "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!push.s %5!;$par!", + "push5.s %1 %2 %3 %4 %5!", + seqsize(5,5) - seqsize(1,5) + }, + { + "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!", + "push4.s %1 %2 %3 %4!", + seqsize(4,4) - seqsize(1,4) + }, + { + "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!", + "push3.s %1 %2 %3!", + seqsize(3,3) - seqsize(1,3) + }, + { + "push.s %1!;$par!push.s %2!;$par!", + "push2.s %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + /* ----- */ + { + "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!push.adr %5!;$par!", + "push5.adr %1 %2 %3 %4 %5!", + seqsize(5,5) - seqsize(1,5) + }, + { + "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!", + "push4.adr %1 %2 %3 %4!", + seqsize(4,4) - seqsize(1,4) + }, + { + "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!", + "push3.adr %1 %2 %3!", + seqsize(3,3) - seqsize(1,3) + }, + { + "push.adr %1!;$par!push.adr %2!;$par!", + "push2.adr %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + /* Loading two registers at a time + * load.pri n1 load.both n1 n2 + * load.alt n2 - + * -------------------------------------- + * load.alt n2 load.both n1 n2 + * load.pri n1 - + * -------------------------------------- + * load.s.pri n1 load.s.both n1 n2 + * load.s.alt n2 - + * -------------------------------------- + * load.s.alt n2 load.s.both n1 n2 + * load.s.pri n1 - + */ + { + "load.pri %1!load.alt %2!", + "load.both %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + { + "load.alt %2!load.pri %1!", + "load.both %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + { + "load.s.pri %1!load.s.alt %2!", + "load.s.both %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + { + "load.s.alt %2!load.s.pri %1!", + "load.s.both %1 %2!", + seqsize(2,2) - seqsize(1,2) + }, + /* Loading two registers and then pushing them occurs with user operators + * load.both n1 n2 push2 n1 n2 + * push.pri - + * push.alt - + * -------------------------------------- + * load.s.both n1 n2 push2.s n1 n2 + * push.pri - + * push.alt - + */ + { + "load.both %1 %2!push.pri!push.alt!", + "push2 %1 %2!", + seqsize(3,2) - seqsize(1,2) + }, + { + "load.s.both %1 %2!push.pri!push.alt!", + "push2.s %1 %2!", + seqsize(3,2) - seqsize(1,2) + }, + /* Load a constant in a variable + * const.pri n1 const n2 n1 + * stor.pri n2 - + * -------------------------------------- + * const.pri n1 const.s n2 n1 + * stor.s.pri n2 - + */ + { + "const.pri %1!stor.pri %2!", + "const %2 %1!", + seqsize(2,2) - seqsize(1,2) + }, + { + "const.pri %1!stor.s.pri %2!", + "const.s %2 %1!", + seqsize(2,2) - seqsize(1,2) + }, + /* ----- */ + { NULL, NULL, 0 } +}; static int stgstring(char *start,char *end); static void stgopt(char *start,char *end,int (*outputfunc)(char *str)); @@ -400,8 +1577,7 @@ static SEQUENCE *sequences; SC_FUNC int phopt_init(void) { - int number, i, len; - char str[160]; + int number, i; /* count number of sequences */ for (number=0; sequences_cmp[number].find!=NULL; number++) @@ -418,25 +1594,6 @@ SC_FUNC int phopt_init(void) sequences[i].savesize=0; } /* for */ - /* expand all strings */ - for (i=0; i ;$lcl - * stack -4 push.c - * const.pri ;$exp - * stor.s.pri - - * ;$exp - - */ - { - #ifdef SCPACK - ";$lcl %1 %2!stack -4!const.pri %3!stor.s.pri %2!;$exp!", - ";$lcl %1 %2!push.c %3!;$exp!", - #else - "\223lcl\331\230ack -4!\234\206\256\230or\222\227\255", - "\223lcl\331\330\256\255", - #endif - seqsize(3,3) - seqsize(1,1) - }, - { - #ifdef SCPACK - ";$lcl %1 %2!stack -4!zero.pri!stor.s.pri %2!;$exp!", - ";$lcl %1 %2!push.c 0!;$exp!", - #else - "\223lcl\331\230ack -4!\375\230or\222\227\255", - "\223lcl\331\330 0!\255", - #endif - seqsize(3,2) - seqsize(1,1) - }, - /* During a calculation, the intermediate result must sometimes - * be moved from PRI to ALT, like in: - * push.pri move.alt - * load.s.pri n1 load.s.pri n1 - * pop.alt - - * - * The above also accurs for "load.pri" and for "const.pri", - * so add another two cases. - */ - { - #ifdef SCPACK - "push.pri!load.s.pri %1!pop.alt!", - "move.alt!load.s.pri %1!", - #else - "\247\333\244", - "\307\333", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "push.pri!load.pri %1!pop.alt!", - "move.alt!load.pri %1!", - #else - "\247\312\244", - "\307\312", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "push.pri!const.pri %1!pop.alt!", - "move.alt!const.pri %1!", - #else - "\247\327\244", - "\307\327", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "push.pri!zero.pri!pop.alt!", - "move.alt!zero.pri!", - #else - "\247\375\244", - "\307\375", - #endif - seqsize(3,0) - seqsize(2,0) - }, - /* saving PRI and then loading from its address - * occurs when indexing a multi-dimensional array - */ - { - #ifdef SCPACK - "push.pri!load.i!pop.alt!", - "move.alt!load.i!", - #else - "\247\342i\266", - "\307\342\357", - #endif - seqsize(3,0) - seqsize(2,0) - }, - /* An even simpler PUSH/POP optimization (occurs in - * switch statements): - * push.pri move.alt - * pop.alt - - */ - { - #ifdef SCPACK - "push.pri!pop.alt!", - "move.alt!", - #else - "\247\244", - "\307", - #endif - seqsize(2,0) - seqsize(1,0) - }, - /* Some simple arithmetic sequences - */ - { - #ifdef SCPACK - "move.alt!load.s.pri %1!add!", - "load.s.alt %1!add!", - #else - "\307\333\271", - "\226\246\271", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "move.alt!load.pri %1!add!", - "load.alt %1!add!", - #else - "\307\312\271", - "\376\271", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "move.alt!const.pri %1!add!", - "const.alt %1!add!", - #else - "\307\327\271", - "\362\271", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "move.alt!load.s.pri %1!sub.alt!", - "load.s.alt %1!sub!", - #else - "\307\333sub\224", - "\226\246sub!", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "move.alt!load.pri %1!sub.alt!", - "load.alt %1!sub!", - #else - "\307\312sub\224", - "\376sub!", - #endif - seqsize(3,1) - seqsize(2,1) - }, - { - #ifdef SCPACK - "move.alt!const.pri %1!sub.alt!", - "const.alt %1!sub!", - #else - "\307\327sub\224", - "\362sub!", - #endif - seqsize(3,1) - seqsize(2,1) - }, - /* User-defined operators first load the operands into registers and - * then have them pushed onto the stack. This can give rise to sequences - * like: - * const.pri n1 push.c n1 - * const.alt n2 push.c n2 - * push.pri - - * push.alt - - * A similar sequence occurs with the two PUSH.pri/alt instructions inverted. - * The first, second, or both CONST.pri/alt instructions can also be - * LOAD.pri/alt. - * This gives 2 x 4 cases. - */ - { - #ifdef SCPACK - "const.pri %1!const.alt %2!push.pri!push.alt!", - "push.c %1!push.c %2!", - #else - "\327\234\305\247\356", - "\330\202\330\221", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "const.pri %1!const.alt %2!push.alt!push.pri!", - "push.c %2!push.c %1!", - #else - "\327\234\305\356\247", - "\330\221\330\202", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "const.pri %1!load.alt %2!push.pri!push.alt!", - "push.c %1!push %2!", - #else - "\327\366\247\356", - "\330\202\216\221", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "const.pri %1!load.alt %2!push.alt!push.pri!", - "push %2!push.c %1!", - #else - "\327\366\356\247", - "\216\221\330\202", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "load.pri %1!const.alt %2!push.pri!push.alt!", - "push %1!push.c %2!", - #else - "\312\234\305\247\356", - "\216\202\330\221", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "load.pri %1!const.alt %2!push.alt!push.pri!", - "push.c %2!push %1!", - #else - "\312\234\305\356\247", - "\330\221\216\202", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "load.pri %1!load.alt %2!push.pri!push.alt!", - "push %1!push %2!", - #else - "\312\366\247\356", - "\216\202\216\221", - #endif - seqsize(4,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "load.pri %1!load.alt %2!push.alt!push.pri!", - "push %2!push %1!", - #else - "\312\366\356\247", - "\216\221\216\202", - #endif - seqsize(4,2) - seqsize(2,2) - }, - /* Function calls (parameters are passed on the stack) - * load.s.pri n1 push.s n1 - * push.pri - - * -------------------------------------- - * load.pri n1 push n1 - * push.pri - - * -------------------------------------- - * const.pri n1 push.c n1 - * push.pri - - * -------------------------------------- - * zero.pri push.c 0 - * push.pri - - * -------------------------------------- - * addr.pri n1 push.adr n1 - * push.pri - - * - * However, PRI must not be needed after this instruction - * if this shortcut is used. Check for the ;$par comment. - */ - { - #ifdef SCPACK - "load.s.pri %1!push.pri!;$par!", - "push.s %1!;$par!", - #else - "\226\264\242", - "\216\222\202\242", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "load.pri %1!push.pri!;$par!", - "push %1!;$par!", - #else - "\217\264\242", - "\216\202\242", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "const.pri %1!push.pri!;$par!", - "push.c %1!;$par!", - #else - "\234\264\242", - "\330\202\242", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "zero.pri!push.pri!;$par!", - "push.c 0!;$par!", - #else - "\375\247\242", - "\330 0!\242", - #endif - seqsize(2,0) - seqsize(1,1) - }, - { - #ifdef SCPACK - "addr.pri %1!push.pri!;$par!", - "push.adr %1!;$par!", - #else - "\265\264\242", - "\216\325\202\242", - #endif - seqsize(2,1) - seqsize(1,1) - }, - /* References with a default value generate new cells on the heap - * dynamically. That code often ends with: - * move.pri push.alt - * push.pri - - */ - { - #ifdef SCPACK - "move.pri!push.pri!", - "push.alt!", - #else - "\300\237\247", - "\356", - #endif - seqsize(2,0) - seqsize(1,0) - }, - /* Simple arithmetic operations on constants. Noteworthy is the - * subtraction of a constant, since it is converted to the addition - * of the inverse value. - * const.alt n1 add.c n1 - * add - - * -------------------------------------- - * const.alt n1 add.c -n1 - * sub - - * -------------------------------------- - * const.alt n1 smul.c n1 - * smul - - * -------------------------------------- - * const.alt n1 eq.c.pri n1 - * eq - - */ - { - #ifdef SCPACK - "const.alt %1!add!", - "add.c %1!", - #else - "\362\271", - "\236\245\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "const.alt %1!smul!", - "smul.c %1!", - #else - "\362smul!", - "smu\310\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "const.alt %1!eq!", - "eq.c.pri %1!", - #else - "\362\323", - "\260\245\225", - #endif - seqsize(2,1) - seqsize(1,1) - }, - /* Subtraction of a constant. Note that the subtraction is converted to - * the addition of the inverse value. - * const.pri n1 load.s.pri n2 - * load.s.alt n2 add.c -n1 - * sub - - * -------------------------------------- - * const.pri n1 load.pri n2 - * load.alt n2 add.c -n1 - * sub - - */ - { - #ifdef SCPACK - "const.pri %1!load.s.alt %2!sub!", - "load.s.pri %2!add.c -%1!", - #else - "\327\226\305sub!", - "\251\236\245 -\201", - #endif - seqsize(3,2) - seqsize(2,2) - }, - { - #ifdef SCPACK - "const.pri %1!load.alt %2!sub.alt!", - "load.pri %2!add.c -%1!", - #else - "\327\366sub\224", - "\332\236\245 -\201", - #endif - seqsize(3,2) - seqsize(2,2) - }, - /* With arrays indexed with constants that come from enumerations, it happens - * multiple add.c opcodes follow in sequence. - * add.c n1 add.c n1+n2 - * add.c n2 - - */ - { - #ifdef SCPACK - "add.c %1!add.c %2!", - "add.c %1+%2!", - #else - "\236\245\202\236\245\221", - "\236\245\267+%2!", - #endif - seqsize(2,2) - seqsize(1,1) - }, - /* Compare and jump - * eq jneq n1 - * jzer n1 - - * -------------------------------------- - * eq jeq n1 - * jnz n1 - - * -------------------------------------- - * neq jeq n1 - * jzer n1 - - * -------------------------------------- - * neq jneq n1 - * jnz n1 - - * An similarly for other relations - * sless jsgeq n1 - * jzer n1 - - * -------------------------------------- - * sless jsless n1 - * jnz n1 - - * -------------------------------------- - * sleq jsgrtr n1 - * jzer n1 - - * -------------------------------------- - * sleq jsleq n1 - * jnz n1 - - * -------------------------------------- - * sgrtr jsleq n1 - * jzer n1 - - * -------------------------------------- - * sgrtr jsgrtr n1 - * jnz n1 - - * -------------------------------------- - * sgeq jsless n1 - * jzer n1 - - * -------------------------------------- - * sgeq jsgeq n1 - * jnz n1 - - * We can relax the optimizations for the unsigned comparisons, - * because the Pawn compiler currently only generates signed - * comparisons. - */ - { - #ifdef SCPACK - "eq!jzer %1!", - "jneq %1!", - #else - "\323\340", - "\373\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "eq!jnz %1!", - "jeq %1!", - #else - "\323\373z\202", - "j\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "neq!jzer %1!", - "jeq %1!", - #else - "n\323\340", - "j\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "neq!jnz %1!", - "jneq %1!", - #else - "n\323\373z\202", - "\373\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sless!jzer %1!", - "jsgeq %1!", - #else - "\353!\340", - "j\303\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sless!jnz %1!", - "jsless %1!", - #else - "\353!\373z\202", - "j\353\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sleq!jzer %1!", - "jsgrtr %1!", - #else - "\304\323\340", - "j\355r\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sleq!jnz %1!", - "jsleq %1!", - #else - "\304\323\373z\202", - "j\304\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sgrtr!jzer %1!", - "jsleq %1!", - #else - "\374\340", - "j\304\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sgrtr!jnz %1!", - "jsgrtr %1!", - #else - "\374\373z\202", - "j\355r\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sgeq!jzer %1!", - "jsless %1!", - #else - "\303\323\340", - "j\353\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "sgeq!jnz %1!", - "jsgeq %1!", - #else - "\303\323\373z\202", - "j\303\360", - #endif - seqsize(2,1) - seqsize(1,1) - }, - /* Test for zero (common case, especially for strings) - * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)" - * - * zero.alt jzer n1 - * jeq n1 - - * -------------------------------------- - * zero.alt jnz n1 - * jneq n1 - - */ - { - #ifdef SCPACK - "zero.alt!jeq %1!", - "jzer %1!", - #else - "\337\224j\360", - "\340", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "zero.alt!jneq %1!", - "jnz %1!", - #else - "\337\224\373\360", - "\373z\202", - #endif - seqsize(2,1) - seqsize(1,1) - }, - /* Incrementing and decrementing leaves a value in - * in PRI which may not be used (for example, as the - * third expression in a "for" loop). - * inc n1 inc n1 ; ++n - * load.pri n1 ;$exp - * ;$exp - - * -------------------------------------- - * load.pri n1 inc n1 ; n++, e.g. "for (n=0; n<10; n++)" - * inc n1 ;$exp - * ;$exp - - * Plus the varieties for stack relative increments - * and decrements. - */ - { - #ifdef SCPACK - "inc %1!load.pri %1!;$exp!", - "inc %1!;$exp!", - #else - "inc\202\312\255", - "inc\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "load.pri %1!inc %1!;$exp!", - "inc %1!;$exp!", - #else - "\312inc\301", - "inc\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "inc.s %1!load.s.pri %1!;$exp!", - "inc.s %1!;$exp!", - #else - "inc\222\202\333\255", - "inc\222\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "load.s.pri %1!inc.s %1!;$exp!", - "inc.s %1!;$exp!", - #else - "\333inc\222\301", - "inc\222\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "dec %1!load.pri %1!;$exp!", - "dec %1!;$exp!", - #else - "dec\202\312\255", - "dec\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "load.pri %1!dec %1!;$exp!", - "dec %1!;$exp!", - #else - "\312dec\301", - "dec\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "dec.s %1!load.s.pri %1!;$exp!", - "dec.s %1!;$exp!", - #else - "dec\222\202\333\255", - "dec\222\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "load.s.pri %1!dec.s %1!;$exp!", - "dec.s %1!;$exp!", - #else - "\333dec\222\301", - "dec\222\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - /* ??? the same (increments and decrements) for references */ - /* Loading the constant zero has a special opcode. - * When storing zero in memory, the value of PRI must not be later on. - * const.pri 0 zero n1 - * stor.pri n1 ;$exp - * ;$exp - - * -------------------------------------- - * const.pri 0 zero.s n1 - * stor.s.pri n1 ;$exp - * ;$exp - - * -------------------------------------- - * zero.pri zero n1 - * stor.pri n1 ;$exp - * ;$exp - - * -------------------------------------- - * zero.pri zero.s n1 - * stor.s.pri n1 ;$exp - * ;$exp - - * -------------------------------------- - * const.pri 0 zero.pri - * -------------------------------------- - * const.alt 0 zero.alt - * The last two alternatives save more memory than they save - * time, but anyway... - */ - { - #ifdef SCPACK - "const.pri 0!stor.pri %1!;$exp!", - "zero %1!;$exp!", - #else - "\234\206 0!\230or\225\255", - "\337\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "const.pri 0!stor.s.pri %1!;$exp!", - "zero.s %1!;$exp!", - #else - "\234\206 0!\230or\222\225\255", - "\337\222\301", - #endif - seqsize(2,2) - seqsize(1,1) - }, - { - #ifdef SCPACK - "zero.pri!stor.pri %1!;$exp!", - "zero %1!;$exp!", - #else - "\375\230or\225\255", - "\337\301", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "zero.pri!stor.s.pri %1!;$exp!", - "zero.s %1!;$exp!", - #else - "\375\230or\222\225\255", - "\337\222\301", - #endif - seqsize(2,1) - seqsize(1,1) - }, - { - #ifdef SCPACK - "const.pri 0!", - "zero.pri!", - #else - "\234\206 0!", - "\375", - #endif - seqsize(1,1) - seqsize(1,0) - }, - { - #ifdef SCPACK - "const.alt 0!", - "zero.alt!", - #else - "\234\212 0!", - "\337\224", - #endif - seqsize(1,1) - seqsize(1,0) - }, - - /* ------------------ */ - /* Macro instructions */ - /* ------------------ */ - - { "", "", 0 }, /* separator, so optimizer can stop before generating macro opcodes */ - - /* optimizing the calling of native functions (which always have a parameter - * count pushed before, and the stack pointer restored afterwards - */ - { - #ifdef SCPACK - "push.c %1!sysreq.c %2!stack %3!", //note: %3 == %1 + 4 - "sysreq.n %2 %1!", - #else - "\330\202sysr\260\245\221\230ack\256", - "sysr\260.n\220\202", - #endif - seqsize(3,3) - seqsize(1,2) - }, - /* ----- */ - /* Functions with many parameters with the same "type" have sequences like: - * push.c n1 push3.c n1 n2 n3 - * ;$par ;$par - * push.c n2 - - * ;$par - - * push.c n3 - - * ;$par - - * etc. etc. - * - * Similar sequences occur with PUSH, PUSH.s and PUSHADDR - */ - { - #ifdef SCPACK - "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!push.c %5!;$par!", - "push5.c %1 %2 %3 %4 %5!", - #else - "\330\335\245\345\245\256\257\245\334\257\245\2035!\242", - "\2165\245\343\250\302\2035!", - #endif - seqsize(5,5) - seqsize(1,5) - }, - { - #ifdef SCPACK - "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!", - "push4.c %1 %2 %3 %4!", - #else - "\330\335\245\345\245\256\257\245\334\242", - "\2164\245\343\250\334", - #endif - seqsize(4,4) - seqsize(1,4) - }, - { - #ifdef SCPACK - "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!", - "push3.c %1 %2 %3!", - #else - "\330\335\245\345\245\256\242", - "\2163\245\343\256", - #endif - seqsize(3,3) - seqsize(1,3) - }, - { - #ifdef SCPACK - "push.c %1!;$par!push.c %2!;$par!", - "push2.c %1 %2!", - #else - "\330\335\245\221\242", - "\2162\245\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* ----- */ - { - #ifdef SCPACK - "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!push %5!;$par!", - "push5 %1 %2 %3 %4 %5!", - #else - "\216\335\345\256\257\334\257\2035!\242", - "\2165\343\250\302\2035!", - #endif - seqsize(5,5) - seqsize(1,5) - }, - { - #ifdef SCPACK - "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!", - "push4 %1 %2 %3 %4!", - #else - "\216\335\345\256\257\334\242", - "\2164\343\250\334", - #endif - seqsize(4,4) - seqsize(1,4) - }, - { - #ifdef SCPACK - "push %1!;$par!push %2!;$par!push %3!;$par!", - "push3 %1 %2 %3!", - #else - "\216\335\345\256\242", - "\2163\343\256", - #endif - seqsize(3,3) - seqsize(1,3) - }, - { - #ifdef SCPACK - "push %1!;$par!push %2!;$par!", - "push2 %1 %2!", - #else - "\216\335\221\242", - "\2162\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* ----- */ - { - #ifdef SCPACK - "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!push.s %5!;$par!", - "push5.s %1 %2 %3 %4 %5!", - #else - "\216\222\335\222\345\222\256\257\222\334\257\222\2035!\242", - "\2165\222\343\250\302\2035!", - #endif - seqsize(5,5) - seqsize(1,5) - }, - { - #ifdef SCPACK - "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!", - "push4.s %1 %2 %3 %4!", - #else - "\216\222\335\222\345\222\256\257\222\334\242", - "\2164\222\343\250\334", - #endif - seqsize(4,4) - seqsize(1,4) - }, - { - #ifdef SCPACK - "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!", - "push3.s %1 %2 %3!", - #else - "\216\222\335\222\345\222\256\242", - "\2163\222\343\256", - #endif - seqsize(3,3) - seqsize(1,3) - }, - { - #ifdef SCPACK - "push.s %1!;$par!push.s %2!;$par!", - "push2.s %1 %2!", - #else - "\216\222\335\222\221\242", - "\2162\222\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* ----- */ - { - #ifdef SCPACK - "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!push.adr %5!;$par!", - "push5.adr %1 %2 %3 %4 %5!", - #else - "\216\325\335\325\345\325\256\257\325\334\257\325\2035!\242", - "\2165\325\343\250\302\2035!", - #endif - seqsize(5,5) - seqsize(1,5) - }, - { - #ifdef SCPACK - "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!", - "push4.adr %1 %2 %3 %4!", - #else - "\216\325\335\325\345\325\256\257\325\334\242", - "\2164\325\343\250\334", - #endif - seqsize(4,4) - seqsize(1,4) - }, - { - #ifdef SCPACK - "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!", - "push3.adr %1 %2 %3!", - #else - "\216\325\335\325\345\325\256\242", - "\2163\325\343\256", - #endif - seqsize(3,3) - seqsize(1,3) - }, - { - #ifdef SCPACK - "push.adr %1!;$par!push.adr %2!;$par!", - "push2.adr %1 %2!", - #else - "\216\325\335\325\221\242", - "\2162\325\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* Loading two registers at a time - * load.pri n1 load.both n1 n2 - * load.alt n2 - - * -------------------------------------- - * load.alt n2 load.both n1 n2 - * load.pri n1 - - * -------------------------------------- - * load.s.pri n1 load.s.both n1 n2 - * load.s.alt n2 - - * -------------------------------------- - * load.s.alt n2 load.s.both n1 n2 - * load.s.pri n1 - - */ - { - #ifdef SCPACK - "load.pri %1!load.alt %2!", - "load.both %1 %2!", - #else - "\312\366", - "\342\275th\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - { - #ifdef SCPACK - "load.alt %2!load.pri %1!", - "load.both %1 %2!", - #else - "\366\312", - "\342\275th\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - { - #ifdef SCPACK - "load.s.pri %1!load.s.alt %2!", - "load.s.both %1 %2!", - #else - "\333\226\305", - "\226.\275th\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - { - #ifdef SCPACK - "load.s.alt %2!load.s.pri %1!", - "load.s.both %1 %2!", - #else - "\226\305\333", - "\226.\275th\331", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* Loading two registers and then pushing them occurs with user operators - * load.both n1 n2 push2 n1 n2 - * push.pri - - * push.alt - - * -------------------------------------- - * load.s.both n1 n2 push2.s n1 n2 - * push.pri - - * push.alt - - */ - { - #ifdef SCPACK - "load.both %1 %2!push.pri!push.alt!", - "push2 %1 %2!", - #else - "\342\275th\331\247\356", - "\2162\331", - #endif - seqsize(3,2) - seqsize(1,2) - }, - { - #ifdef SCPACK - "load.s.both %1 %2!push.pri!push.alt!", - "push2.s %1 %2!", - #else - "\226.\275th\331\247\356", - "\2162\222\331", - #endif - seqsize(3,2) - seqsize(1,2) - }, - /* Load a constant in a variable - * const.pri n1 const n2 n1 - * stor.pri n2 - - * -------------------------------------- - * const.pri n1 const.s n2 n1 - * stor.s.pri n2 - - */ - { - #ifdef SCPACK - "const.pri %1!stor.pri %2!", - "const %2 %1!", - #else - "\327\230or\227", - "\234\220\202", - #endif - seqsize(2,2) - seqsize(1,2) - }, - { - #ifdef SCPACK - "const.pri %1!stor.s.pri %2!", - "const.s %2 %1!", - #else - "\327\230or\222\227", - "\234\222\220\202", - #endif - seqsize(2,2) - seqsize(1,2) - }, - /* ----- */ - { NULL, NULL, 0 } -}; diff --git a/source/compiler/scexpand.c b/source/compiler/scexpand.c deleted file mode 100644 index e0d6a9e..0000000 --- a/source/compiler/scexpand.c +++ /dev/null @@ -1,68 +0,0 @@ -/* expand.c -- Byte Pair Encoding decompression */ -/* Copyright 1996 Philip Gage */ - -/* Byte Pair Compression appeared in the September 1997 - * issue of C/C++ Users Journal. The original source code - * may still be found at the web site of the magazine - * (www.cuj.com). - * - * The decompressor has been modified by me (Thiadmer - * Riemersma) to accept a string as input, instead of a - * complete file. - */ -#include -#include -#include "sc.h" - -#define STACKSIZE 16 - -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]) -{ - unsigned char stack[STACKSIZE]; - short c, top = 0; - int len; - - assert(maxlen > 0); - len = 1; /* already 1 byte for '\0' */ - for (;;) { - - /* Pop byte from stack or read byte from the input string */ - if (top) - c = stack[--top]; - else if ((c = *(unsigned char *)source++) == '\0') - break; - - /* Push pair on stack or output byte to the output string */ - if (c > 127) { - assert(top+2 <= STACKSIZE); - stack[top++] = pairtable[c-128][1]; - stack[top++] = pairtable[c-128][0]; - } - else { - len++; - if (maxlen > 1) { /* reserve one byte for the '\0' */ - *dest++ = (char)c; - maxlen--; - } - } - } - *dest = '\0'; - return len; /* return number of bytes decoded */ -} - -#if 0 /*for testing*/ -#include "sc5.scp" - -int main (int argc, char **argv) -{ - int i; - char str[128]; - - for (i=0; i<58; i++) { - strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE); - printf("%s", str); - } /* for */ - return 0; -} -#endif - diff --git a/source/compiler/scpack.c b/source/compiler/scpack.c deleted file mode 100644 index 459532b..0000000 --- a/source/compiler/scpack.c +++ /dev/null @@ -1,450 +0,0 @@ -/* compress.c -- Byte Pair Encoding compression */ -/* Copyright 1996 Philip Gage */ - -/* This program appeared in the September 1997 issue of - * C/C++ Users Journal. The original source code may still - * be found at the web site of the magazine (www.cuj.com). - * - * It has been modified by me (Thiadmer Riemersma) to - * compress only a section of the input file and to store - * the compressed output along with the input as "C" strings. - * - * Compiling instructions: - * Borland C++ 16-bit (large memory model is required): - * bcc -ml scpack.c - * - * Watcom C/C++ 32-bit: - * wcl386 scpack.c - * - * GNU C (Linux), 32-bit: - * gcc scpack.c -o scpack - */ - -#include -#include -#include -#include -#include - -#if UINT_MAX > 0xFFFFU - #define MAXSIZE 1024*1024L -#else - #define MAXSIZE UINT_MAX /* Input file buffer size */ -#endif -#define HASHSIZE 8192 /* Hash table size, power of 2 */ -#define THRESHOLD 3 /* Increase for speed, min 3 */ - -#define START_TOKEN "#ifdef SCPACK" /* start reading the buffer here */ -#define NAME_TOKEN "#define SCPACK_TABLE" -#define SEP_TOKEN "#define SCPACK_SEPARATOR" -#define TERM_TOKEN "#define SCPACK_TERMINATOR" -#define TEMPFILE "~SCPACK.TMP" -static char tablename[32+1] = "scpack_table"; -static char separator[16]=","; -static char terminator[16]=""; - -int compress(unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2]) -{ - unsigned char *left, *right, *count; - unsigned char a, b, bestcount; - unsigned i, j, index, bestindex, code=128; - - /* Dynamically allocate buffers and check for errors */ - left = (unsigned char *)malloc(HASHSIZE); - right = (unsigned char *)malloc(HASHSIZE); - count = (unsigned char *)malloc(HASHSIZE); - if (left==NULL || right==NULL || count==NULL) { - printf("Error allocating memory\n"); - exit(1); - } - - /* Check for errors */ - for (i=0; i 127) { - printf("This program works only on text files (7-bit ASCII)\n"); - exit(1); - } - - memset(pairtable, 0, 128*2*sizeof(char)); - - do { /* Replace frequent pairs with bytes 128..255 */ - - /* Enter counts of all byte pairs into hash table */ - memset(count,0,HASHSIZE); - for (i=0; i bestcount) { - bestcount = count[i]; - bestindex = i; - } - } - - /* Compress if enough occurrences of pair */ - if (bestcount >= THRESHOLD) { - - /* Add pair to table using code as index */ - a = pairtable[code-128][0] = left[bestindex]; - b = pairtable[code-128][1] = right[bestindex]; - - /* Replace all pair occurrences with unused byte */ - for (i=0, j=0; i= 128 || *bufptr == '"' || *bufptr == '\\') - fprintf(output, "\\%03o", *bufptr); - else - fprintf(output, "%c", *bufptr); - bufptr++; - } /* while */ - fprintf(output, "\""); - needseparator = 1; - bufptr++; /* skip '\0' */ - } /* while */ - fprintf(output, "%s\n",terminator); - bufptr++; - - /* skip the input file until the #endif section */ - while (fgets(str,sizeof str,input)!=NULL) { - if (strmatch(str,"#endif",NULL)) { - fprintf(output,"%s",str); - break; /* done */ - } /* if */ - } /* while */ - } /* while - !feof(input) */ -} - -static void usage(void) -{ - printf("Usage: scpack [output file]\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - FILE *in, *out; - unsigned char *buffer; - unsigned buffersize, orgbuffersize; - unsigned char pairtable[128][2]; - - if (argc < 2 || argc > 3) - usage(); - if ((in=fopen(argv[1],"rt"))==NULL) { - printf("SCPACK: error opening input %s\n",argv[1]); - usage(); - } /* if */ - if (argc == 2) { - if ((out=fopen(TEMPFILE,"wt"))==NULL) { - printf("SCPACK: error opening temporary file %s\n",TEMPFILE); - usage(); - } /* if */ - } else { - if ((out=fopen(argv[2],"wt"))==NULL) { - printf("SCPACK: error opening output file %s\n",argv[2]); - usage(); - } /* if */ - } /* if */ - - buffer = (unsigned char *)malloc(MAXSIZE); - if (buffer == NULL) { - printf("SCPACK: error allocating memory\n"); - return 1; - } /* if */ - /* 1. read the buffer - * 2. compress the buffer - * 3. copy the file, insert the compressed buffer - */ - buffersize = readbuffer(in, buffer); - orgbuffersize = buffersize; - if (buffersize > 0) { - buffersize = compress(buffer, buffersize, pairtable); - writefile(in, out, buffer, buffersize, pairtable); - printf("SCPACK: compression ratio: %ld%% (%d -> %d)\n", - 100L-(100L*buffersize)/orgbuffersize, orgbuffersize, buffersize); - } else { - printf("SCPACK: no SCPACK section found, nothing to do\n"); - } /* if */ - fclose(out); - fclose(in); - /* let the new file replace the old file */ - if (buffersize == 0) { - if (argc == 2) - remove(TEMPFILE); - else - remove(argv[2]); - } else if (argc == 2) { - remove(argv[1]); - rename(TEMPFILE,argv[1]); - } /* if */ - return 0; -}