From 867f6902f36c04ab8cf64a6d46510f686563a808 Mon Sep 17 00:00:00 2001 From: Zeex Date: Mon, 6 Apr 2015 16:09:54 +0600 Subject: [PATCH] Remove string compression This removes all scpack-packed strings and moves normal strings from .scp files to corresponding .c files. The code responding for packing and unpacking is gone as well. If you have enough memory to run a SA-MP server you most likely have more than enough of it to not worry about saving a few additional KBs of text. Besides, these strings were kind of hard to navigate / edit, and you could easily forget to regenerate them with scpack (though it could be automated). --- source/compiler/CMakeLists.txt | 4 +- source/compiler/sc5.c | 169 ++- source/compiler/sc5.scp | 344 ------ source/compiler/sc7.c | 1217 ++++++++++++++++++- source/compiler/sc7.scp | 2013 -------------------------------- source/compiler/scexpand.c | 68 -- source/compiler/scpack.c | 450 ------- 7 files changed, 1343 insertions(+), 2922 deletions(-) delete mode 100644 source/compiler/sc5.scp delete mode 100644 source/compiler/sc7.scp delete mode 100644 source/compiler/scexpand.c delete mode 100644 source/compiler/scpack.c 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; -}