From a3d1759c37fa399c45561eda23f696dd25cd5b62 Mon Sep 17 00:00:00 2001 From: michaelh Date: Mon, 17 Jan 2000 05:43:29 +0000 Subject: [PATCH] Removed some generated files, added Makefile.common, shifted mcs51 sdcc ports into the port directory, added hack to get it to compile. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@10 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- Makefile.common.in | 49 + configure | 2 + configure.in | 1 + debugger/mcs51/Makefile.dep | 18 - device/lib/Makefile.dep | 0 src/Makefile.in | 46 +- src/SDCClex.c | 3040 -------------- src/SDCCy.c | 3093 --------------- src/mcs51/Makefile | 19 + src/mcs51/gen.c | 7383 +++++++++++++++++++++++++++++++++++ src/mcs51/gen.h | 72 + src/mcs51/ralloc.c | 2313 +++++++++++ src/mcs51/ralloc.h | 58 + support/cpp/Makefile.dep | 7 - support/gc/Makefile | 417 -- 15 files changed, 9906 insertions(+), 6612 deletions(-) create mode 100644 Makefile.common.in delete mode 100644 debugger/mcs51/Makefile.dep delete mode 100644 device/lib/Makefile.dep delete mode 100644 src/SDCClex.c delete mode 100644 src/SDCCy.c create mode 100644 src/mcs51/Makefile create mode 100644 src/mcs51/gen.c create mode 100644 src/mcs51/gen.h create mode 100644 src/mcs51/ralloc.c create mode 100644 src/mcs51/ralloc.h delete mode 100644 support/cpp/Makefile.dep delete mode 100644 support/gc/Makefile diff --git a/Makefile.common.in b/Makefile.common.in new file mode 100644 index 00000000..73ef6bec --- /dev/null +++ b/Makefile.common.in @@ -0,0 +1,49 @@ +# +# +# + +# HACK +PORT = mcs51 + +# Version +VERSION = @VERSION@ +VERSIONHI = @VERSIONHI@ +VERSIONLO = @VERSIONLO@ +VERSIONP = @VERSIONP@ + +# Programs +SHELL = /bin/sh +CC = @CC@ +CPP = @CPP@ +RANLIB = @RANLIB@ +INSTALL = @INSTALL@ +YACC = @YACC@ +LEX = @LEX@ +AWK = @AWK@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +datadir = @datadir@ +includedir = @includedir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +infodir = @infodir@ +srcdir = @srcdir@ + +# Flags +DEFS = $(subs -DHAVE_CONFIG_H,,@DEFS@) +CPPFLAGS = @CPPFLAGS@ -I$(PRJDIR) -I$(PRJDIR)/support +CFLAGS = @CFLAGS@ -Wall +M_OR_MM = @M_OR_MM@ + +# Shared settings between all the sub Makefiles +# Done here so that we don't have to start a Make from the top levelport +# directory. + +# Library compilation options +SCC = $(PRJDIR)/src/sdcc +SAS = $(PRJDIR)/as/$(PORT)/as +CLEANSPEC = *.lst *.asm *.sym *~ *.cdb diff --git a/configure b/configure index 77b4483e..ab9eaed3 100755 --- a/configure +++ b/configure @@ -2561,6 +2561,7 @@ support/cpp/Makefile device/include/Makefile device/lib/Makefile debugger/mcs51/Makefile +Makefile.common:Makefile.common.in sdccconf.h:sdccconf_in.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF diff --git a/configure.in b/configure.in index 5fe04135..7126afdb 100755 --- a/configure.in +++ b/configure.in @@ -201,6 +201,7 @@ support/cpp/Makefile device/include/Makefile device/lib/Makefile debugger/mcs51/Makefile +Makefile.common:Makefile.common.in ) # End of configure/configure.in diff --git a/debugger/mcs51/Makefile.dep b/debugger/mcs51/Makefile.dep deleted file mode 100644 index 69d31967..00000000 --- a/debugger/mcs51/Makefile.dep +++ /dev/null @@ -1,18 +0,0 @@ -sdcdb.o: sdcdb.c sdcdb.h ../../sdccconf.h ../../support/gc/gc.h \ - ../../src/SDCCset.h ../../src/SDCChasht.h ../../src/SDCCbitv.h \ - symtab.h simi.h break.h cmd.h -symtab.o: symtab.c sdcdb.h ../../sdccconf.h ../../support/gc/gc.h \ - ../../src/SDCCset.h ../../src/SDCChasht.h ../../src/SDCCbitv.h \ - symtab.h -simi.o: simi.c sdcdb.h ../../sdccconf.h ../../support/gc/gc.h \ - ../../src/SDCCset.h ../../src/SDCChasht.h ../../src/SDCCbitv.h simi.h -SDCCset.o: ../../src/SDCCset.c ../../src/SDCCset.h \ - ../../support/gc/gc.h -break.o: break.c sdcdb.h ../../sdccconf.h ../../support/gc/gc.h \ - ../../src/SDCCset.h ../../src/SDCChasht.h ../../src/SDCCbitv.h \ - symtab.h break.h simi.h -cmd.o: cmd.c sdcdb.h ../../sdccconf.h ../../support/gc/gc.h \ - ../../src/SDCCset.h ../../src/SDCChasht.h ../../src/SDCCbitv.h \ - symtab.h simi.h break.h cmd.h -SDCChasht.o: ../../src/SDCChasht.c ../../src/SDCChasht.h \ - ../../support/gc/gc.h diff --git a/device/lib/Makefile.dep b/device/lib/Makefile.dep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Makefile.in b/src/Makefile.in index bcdf6ecc..dc6aa1fe 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -2,49 +2,18 @@ # # -# Version -VERSION = @VERSION@ -VERSIONHI = @VERSIONHI@ -VERSIONLO = @VERSIONLO@ -VERSIONP = @VERSIONP@ - -# Programs -SHELL = /bin/sh -CC = @CC@ -CPP = @CPP@ -RANLIB = @RANLIB@ -INSTALL = @INSTALL@ -YACC = @YACC@ -LEX = @LEX@ -AWK = @AWK@ -# Directories PRJDIR = .. -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -libdir = @libdir@ -datadir = @datadir@ -includedir = @includedir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 -man2dir = $(mandir)/man2 -infodir = @infodir@ -srcdir = @srcdir@ - -# Flags -DEFS = $(subs -DHAVE_CONFIG_H,,@DEFS@) -CPPFLAGS = @CPPFLAGS@ -I$(PRJDIR) -I$(PRJDIR)/support -CFLAGS = @CFLAGS@ -Wall -M_OR_MM = @M_OR_MM@ -LIBS = -lgc @LIBS@ +include $(PRJDIR)/Makefile.common + +LIBS = $(PORT)/port.a -lgc @LIBS@ LIBDIRS = -L$(PRJDIR)/support/gc OBJECTS = SDCCy.o SDCClex.o SDCCerr.o SDCChasht.o SDCCmain.o \ SDCCsymt.o SDCCopt.o SDCCast.o SDCCmem.o SDCCval.o \ - SDCCralloc.o SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \ + SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \ SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \ - SDCClrange.o SDCCptropt.o SDCCgen51.o SDCCpeeph.o SDCCglue.o spawn.o + SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o spawn.o SOURCES = $(patsubst %.o,%.c,$(OBJECTS)) TARGET = $(PRJDIR)/bin/sdcc @@ -52,7 +21,10 @@ TARGET = $(PRJDIR)/bin/sdcc # Compiling entire program or any subproject # ------------------------------------------ -all: checkconf $(PRJDIR)/support/gc/libgc.a $(TARGET) +all: port checkconf $(PRJDIR)/support/gc/libgc.a $(TARGET) + +port: + $(MAKE) -C $(PORT) $(PRJDIR)/support/gc/libgc.a: cd $(PRJDIR)/support/gc && $(MAKE) diff --git a/src/SDCClex.c b/src/SDCClex.c deleted file mode 100644 index 0cfdc4ec..00000000 --- a/src/SDCClex.c +++ /dev/null @@ -1,3040 +0,0 @@ -/* A lexical scanner generated by flex */ - -/* Scanner skeleton version: - * $Header$ - */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 - -#include - - -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif -#endif - - -#ifdef __cplusplus - -#include -#include - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -#if __STDC__ - -#define YY_USE_PROTOS -#define YY_USE_CONST - -#endif /* __STDC__ */ -#endif /* ! __cplusplus */ - -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include -#include -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#define YY_BUF_SIZE 16384 - -typedef struct yy_buffer_state *YY_BUFFER_STATE; - -extern int yyleng; -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yytext_ptr ) - -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ -typedef unsigned int yy_size_t; - - -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - }; - -static YY_BUFFER_STATE yy_current_buffer = 0; - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - */ -#define YY_CURRENT_BUFFER yy_current_buffer - - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; - -static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 1; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart YY_PROTO(( FILE *input_file )); - -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) - -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); - -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); - -#define yy_new_buffer yy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) - -typedef unsigned char YY_CHAR; -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; -typedef int yy_state_type; -extern char *yytext; -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 123 -#define YY_END_OF_BUFFER 124 -static yyconst short int yy_accept[767] = - { 0, - 0, 0, 0, 0, 124, 122, 121, 120, 122, 103, - 69, 109, 102, 122, 97, 98, 107, 106, 94, 105, - 101, 108, 64, 64, 95, 91, 110, 96, 111, 114, - 61, 99, 100, 112, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 92, 113, 93, 104, 122, 121, 120, - 122, 103, 69, 122, 109, 102, 122, 98, 107, 106, - 94, 105, 101, 108, 64, 64, 95, 91, 110, 96, - 111, 114, 61, 99, 100, 112, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - - 61, 61, 61, 61, 61, 92, 113, 93, 104, 3, - 4, 3, 119, 90, 76, 85, 77, 0, 0, 74, - 82, 72, 83, 73, 84, 0, 67, 5, 75, 68, - 63, 0, 64, 0, 64, 81, 87, 89, 88, 80, - 61, 78, 61, 61, 61, 61, 61, 61, 61, 61, - 6, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 18, 61, 61, 61, 61, 61, 61, 61, 61, 28, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 79, 86, 0, - 0, 119, 90, 0, 0, 76, 85, 77, 0, 0, - - 0, 74, 82, 72, 83, 73, 84, 0, 67, 5, - 75, 68, 63, 0, 64, 0, 64, 81, 87, 89, - 88, 80, 61, 78, 61, 61, 61, 61, 61, 61, - 61, 61, 6, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 18, 61, 61, 61, 61, 61, 61, 61, - 61, 28, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 79, - 86, 0, 65, 60, 0, 67, 67, 0, 68, 63, - 0, 66, 62, 71, 70, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 8, 61, 61, 61, 61, 61, - - 61, 61, 61, 61, 61, 61, 61, 23, 61, 25, - 61, 61, 29, 61, 61, 61, 61, 61, 61, 61, - 37, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 61, 0, 0, 0, 65, 0, - 60, 0, 67, 67, 0, 68, 63, 0, 66, 62, - 71, 70, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 8, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 23, 61, 25, 61, 61, 29, - 61, 61, 61, 61, 61, 61, 61, 37, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - - 61, 61, 0, 0, 67, 0, 67, 0, 68, 66, - 62, 1, 61, 61, 61, 61, 61, 61, 61, 7, - 61, 10, 11, 12, 61, 61, 61, 16, 61, 61, - 20, 21, 61, 61, 26, 61, 61, 31, 32, 61, - 61, 61, 61, 38, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 61, 48, 61, 61, 61, 0, 0, - 0, 0, 0, 67, 0, 67, 0, 68, 66, 62, - 1, 61, 61, 61, 61, 61, 61, 61, 7, 61, - 10, 11, 12, 61, 61, 61, 16, 61, 61, 20, - 21, 61, 61, 26, 61, 61, 31, 32, 61, 61, - - 61, 61, 38, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 48, 61, 61, 61, 0, 0, 67, - 54, 53, 61, 61, 56, 61, 61, 9, 13, 61, - 61, 61, 61, 61, 24, 27, 61, 33, 61, 61, - 61, 39, 61, 61, 61, 61, 61, 61, 46, 61, - 50, 61, 51, 52, 0, 0, 0, 0, 0, 67, - 54, 53, 61, 61, 56, 61, 61, 9, 13, 61, - 61, 61, 61, 61, 24, 27, 61, 33, 61, 61, - 61, 39, 61, 61, 61, 61, 61, 61, 46, 61, - 50, 61, 51, 52, 0, 61, 59, 58, 57, 61, - - 61, 61, 19, 22, 61, 61, 61, 36, 40, 41, - 42, 43, 44, 61, 61, 61, 0, 0, 115, 0, - 0, 0, 61, 59, 58, 57, 61, 61, 61, 19, - 22, 61, 61, 61, 36, 40, 41, 42, 43, 44, - 61, 61, 61, 0, 61, 61, 61, 17, 61, 61, - 61, 45, 61, 61, 0, 0, 115, 0, 0, 0, - 61, 61, 61, 17, 61, 61, 61, 45, 61, 61, - 2, 55, 14, 15, 61, 61, 35, 47, 49, 0, - 0, 0, 0, 116, 0, 0, 0, 55, 14, 15, - 61, 61, 35, 47, 49, 30, 34, 0, 0, 0, - - 0, 116, 0, 0, 0, 30, 34, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, - 0, 117, 65, 117, 0, 0, 0, 0, 0, 0, - 0, 118, 0, 0, 0, 0, 118, 65, 118, 0, - 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, - 118, 117, 0, 0, 118, 0 - } ; - -static yyconst int yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 5, 6, 7, 8, 1, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 22, 23, 24, - 25, 26, 27, 1, 28, 28, 28, 28, 29, 30, - 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, - 31, 31, 31, 31, 33, 31, 31, 34, 31, 31, - 35, 36, 37, 38, 39, 1, 40, 41, 42, 43, - - 44, 45, 46, 47, 48, 31, 49, 50, 51, 52, - 53, 54, 31, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst int yy_meta[68] = - { 0, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 4, - 4, 1, 1, 1, 1, 1, 1, 4, 4, 4, - 5, 5, 5, 5, 1, 1, 1, 1, 5, 4, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 1, 1, 1, 1 - } ; - -static yyconst short int yy_base[785] = - { 0, - 0, 67, 132, 133, 1347, 1348, 1348, 1348, 1343, 1320, - 1348, 1319, 127, 1307, 1348, 1348, 1317, 123, 1348, 124, - 122, 130, 155, 133, 1348, 1348, 121, 1316, 131, 1348, - 0, 1348, 1348, 1315, 150, 101, 112, 154, 142, 118, - 168, 1286, 167, 1285, 1293, 1293, 1291, 179, 1272, 122, - 1280, 1285, 1288, 1348, 138, 1348, 1348, 1318, 1317, 1316, - 194, 203, 1315, 188, 205, 219, 211, 1314, 220, 225, - 1313, 229, 231, 244, 258, 253, 1312, 1311, 236, 241, - 255, 1310, 319, 1309, 1308, 247, 253, 123, 209, 347, - 260, 338, 351, 1266, 232, 1265, 1273, 1273, 1271, 348, - - 1252, 242, 1260, 1265, 1268, 1298, 385, 1297, 1296, 1348, - 1348, 1263, 1348, 1348, 1348, 1348, 1348, 128, 158, 1348, - 1348, 1348, 1348, 1348, 1348, 1288, 386, 1348, 1348, 393, - 424, 412, 402, 0, 443, 1280, 1348, 1348, 1348, 1279, - 0, 1348, 1247, 1249, 1261, 1256, 1256, 1254, 1254, 1253, - 0, 1238, 1237, 1249, 1236, 1251, 182, 1242, 1232, 1243, - 1229, 1230, 1227, 1227, 1228, 1229, 1226, 1223, 1239, 0, - 1221, 1225, 1236, 1235, 382, 1226, 1218, 1219, 243, 228, - 1223, 1216, 261, 1221, 185, 1220, 1227, 1348, 1348, 1254, - 242, 1253, 1252, 399, 386, 1251, 1250, 1249, 437, 458, - - 400, 1248, 1247, 1246, 1245, 1244, 1243, 300, 468, 1242, - 1241, 487, 509, 450, 478, 556, 531, 434, 1240, 1239, - 1238, 471, 0, 1237, 1192, 1194, 1206, 1201, 1201, 1199, - 1199, 1198, 0, 1183, 1182, 1194, 1181, 1196, 434, 1187, - 1177, 1188, 1174, 1175, 1172, 1172, 1173, 1174, 1171, 1168, - 1184, 0, 1166, 1170, 1181, 1180, 458, 1171, 1163, 1164, - 346, 400, 1168, 1161, 410, 1166, 369, 1165, 1172, 1199, - 1198, 1157, 1348, 1348, 505, 1348, 558, 541, 1348, 507, - 400, 562, 522, 1348, 1348, 1157, 1164, 1149, 1153, 1164, - 1163, 1162, 1161, 1147, 0, 1159, 1154, 1142, 1152, 428, - - 1138, 1154, 1153, 1151, 1147, 1139, 1145, 0, 1148, 0, - 1134, 1129, 1141, 1138, 1128, 1125, 1129, 1132, 1121, 1121, - 0, 1122, 1124, 1131, 1117, 1115, 1115, 1127, 1117, 1121, - 1116, 1124, 1126, 1115, 1107, 553, 439, 469, 1151, 593, - 1150, 603, 1149, 605, 621, 1148, 598, 607, 631, 670, - 1147, 1146, 1106, 1113, 1098, 1102, 1113, 1112, 1111, 1110, - 1096, 0, 1108, 1103, 1091, 1101, 449, 1087, 1103, 1102, - 1100, 1096, 1088, 1094, 0, 1097, 0, 1083, 1078, 1090, - 1087, 1077, 1074, 1078, 1081, 1070, 1070, 0, 1071, 1073, - 1080, 1066, 1064, 1064, 1076, 1066, 1070, 1065, 1073, 1075, - - 1064, 1056, 1069, 503, 638, 645, 1348, 513, 674, 1348, - 589, 0, 1067, 1070, 1065, 1051, 1052, 1049, 1048, 0, - 1055, 0, 0, 0, 1046, 1054, 1053, 0, 1042, 1049, - 0, 0, 1043, 1040, 0, 1056, 1040, 0, 0, 1054, - 1036, 1036, 1036, 0, 1033, 1045, 1035, 1039, 1044, 1043, - 1041, 1031, 1036, 1035, 0, 1023, 1035, 1038, 1072, 491, - 502, 635, 633, 697, 652, 1064, 665, 711, 1063, 675, - 0, 1030, 1033, 1028, 1014, 1015, 1012, 1011, 0, 1018, - 0, 0, 0, 1009, 1017, 1016, 0, 1005, 1012, 0, - 0, 1006, 1003, 0, 1019, 1003, 0, 0, 1017, 999, - - 999, 999, 0, 996, 1008, 998, 1002, 1007, 1006, 1004, - 994, 999, 998, 0, 986, 998, 1001, 1000, 524, 714, - 0, 0, 984, 998, 0, 997, 996, 0, 0, 983, - 992, 983, 988, 979, 0, 0, 975, 0, 974, 971, - 975, 0, 983, 980, 982, 966, 975, 977, 0, 968, - 0, 971, 0, 0, 996, 672, 558, 694, 728, 733, - 0, 0, 962, 976, 0, 975, 974, 0, 0, 961, - 970, 961, 966, 957, 0, 0, 953, 0, 952, 949, - 953, 0, 961, 958, 960, 944, 953, 955, 0, 946, - 0, 949, 0, 0, 940, 947, 0, 0, 0, 936, - - 953, 935, 0, 0, 933, 950, 945, 0, 0, 0, - 0, 0, 0, 943, 943, 936, 980, 677, 972, 676, - 604, 746, 935, 0, 0, 0, 924, 941, 923, 0, - 0, 921, 938, 933, 0, 0, 0, 0, 0, 0, - 931, 931, 924, 894, 893, 855, 838, 0, 833, 834, - 830, 0, 839, 837, 551, 877, 1348, 747, 689, 726, - 837, 833, 826, 0, 819, 820, 816, 0, 827, 825, - 1348, 0, 0, 0, 810, 808, 0, 0, 0, 806, - 820, 566, 763, 846, 718, 741, 744, 0, 0, 0, - 799, 796, 0, 0, 0, 0, 0, 797, 796, 671, - - 847, 1348, 768, 758, 761, 0, 0, 796, 684, 588, - 771, 762, 768, 671, 674, 782, 784, 781, 782, 0, - 626, 492, 755, 796, 797, 791, 0, 586, 602, 800, - 787, 808, 0, 547, 799, 0, 788, 802, 804, 806, - 821, 0, 809, 818, 819, 820, 826, 0, 543, 489, - 811, 825, 831, 451, 822, 835, 836, 421, 312, 837, - 307, 285, 845, 211, 182, 1348, 891, 896, 898, 903, - 908, 143, 913, 918, 923, 928, 933, 938, 943, 948, - 953, 958, 963, 968 - } ; - -static yyconst short int yy_def[785] = - { 0, - 766, 766, 767, 767, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 768, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 769, 766, 766, 766, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 766, 766, 766, 766, 770, 770, 770, - 770, 770, 770, 770, 770, 770, 771, 770, 770, 770, - 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, - 770, 770, 766, 770, 770, 770, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - - 83, 83, 83, 83, 83, 770, 770, 770, 770, 766, - 766, 766, 766, 766, 766, 766, 766, 768, 768, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 772, 766, 766, 766, 766, 766, 766, - 769, 766, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 766, 766, 770, - 766, 770, 770, 770, 770, 770, 770, 770, 771, 768, - - 771, 770, 770, 770, 770, 770, 770, 770, 770, 770, - 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, - 770, 770, 83, 770, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 770, - 770, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 772, 766, 766, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 766, 770, 770, 770, 768, - 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, - 770, 770, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - - 83, 83, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 766, 770, - 770, 768, 770, 770, 770, 770, 770, 770, 770, 770, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 766, 766, 766, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 766, 773, 770, 768, 770, 770, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 766, 769, 769, 769, 769, 769, - - 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 769, 769, 766, 773, 770, 774, - 770, 768, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 766, 769, 769, 769, 769, 769, 769, - 769, 769, 769, 769, 766, 774, 766, 774, 775, 768, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 766, 769, 769, 769, 769, 769, 769, 769, 769, 766, - 766, 774, 775, 770, 776, 768, 768, 83, 83, 83, - 83, 83, 83, 83, 83, 769, 769, 766, 766, 774, - - 776, 766, 776, 768, 768, 83, 83, 766, 766, 774, - 776, 768, 768, 766, 766, 774, 776, 768, 768, 777, - 766, 774, 774, 776, 778, 768, 777, 766, 774, 774, - 776, 778, 777, 778, 768, 779, 774, 774, 776, 776, - 780, 779, 774, 774, 776, 776, 780, 779, 780, 781, - 774, 776, 776, 781, 774, 776, 776, 782, 783, 776, - 782, 783, 776, 784, 784, 0, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766 - } ; - -static yyconst short int yy_nxt[1416] = - { 0, - 6, 7, 8, 9, 7, 10, 11, 6, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 31, 31, - 31, 31, 31, 31, 32, 6, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 31, 43, 31, 44, - 31, 45, 31, 46, 47, 48, 49, 50, 51, 52, - 53, 31, 31, 54, 55, 56, 57, 58, 59, 60, - 61, 59, 62, 63, 64, 65, 66, 67, 15, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 83, 83, 83, 83, 83, - - 83, 84, 58, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 83, 95, 83, 96, 83, 97, 83, - 98, 99, 100, 101, 102, 103, 104, 105, 83, 83, - 106, 107, 108, 109, 111, 111, 116, 121, 273, 126, - 123, 127, 127, 128, 136, 137, 283, 122, 124, 125, - 130, 117, 135, 135, 129, 139, 140, 151, 152, 153, - 766, 132, 188, 119, 133, 133, 154, 162, 118, 163, - 112, 112, 130, 183, 131, 131, 132, 184, 164, 233, - 234, 159, 133, 132, 702, 160, 133, 133, 134, 143, - 133, 144, 145, 155, 161, 146, 192, 147, 132, 191, - - 156, 148, 189, 149, 133, 191, 157, 165, 158, 169, - 150, 170, 133, 702, 191, 134, 191, 166, 171, 176, - 167, 190, 200, 177, 299, 178, 179, 193, 197, 196, - 191, 191, 332, 300, 333, 180, 191, 194, 181, 203, - 191, 195, 191, 198, 202, 205, 201, 191, 208, 204, - 209, 209, 191, 206, 207, 191, 235, 210, 191, 218, - 219, 336, 336, 236, 191, 220, 191, 325, 211, 191, - 212, 224, 217, 217, 251, 212, 252, 213, 213, 221, - 222, 214, 326, 253, 215, 215, 214, 702, 323, 215, - 215, 216, 225, 265, 226, 227, 214, 266, 228, 241, - - 229, 214, 215, 242, 230, 324, 231, 215, 329, 657, - 215, 191, 243, 232, 702, 215, 330, 341, 216, 190, - 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, - 191, 190, 190, 190, 190, 190, 190, 190, 223, 223, - 190, 190, 190, 190, 190, 190, 223, 223, 223, 223, - 223, 223, 223, 190, 190, 190, 190, 223, 223, 223, - 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, - 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, - 223, 223, 190, 190, 190, 190, 237, 244, 258, 245, - 247, 390, 259, 238, 260, 261, 191, 191, 246, 239, - - 248, 240, 190, 249, 262, 127, 127, 263, 391, 270, - 191, 200, 277, 277, 275, 276, 399, 276, 400, 282, - 282, 278, 279, 657, 279, 317, 281, 318, 281, 275, - 276, 282, 282, 133, 133, 276, 278, 279, 319, 392, - 338, 130, 279, 131, 131, 191, 337, 339, 200, 271, - 191, 133, 132, 657, 393, 280, 280, 396, 351, 133, - 130, 191, 135, 135, 348, 397, 348, 132, 273, 349, - 349, 132, 201, 280, 133, 133, 366, 340, 340, 191, - 191, 280, 191, 425, 426, 367, 132, 209, 209, 191, - 460, 657, 133, 119, 657, 352, 342, 343, 191, 343, - - 133, 384, 191, 385, 484, 485, 344, 344, 461, 215, - 215, 342, 343, 191, 386, 345, 346, 343, 346, 404, - 191, 404, 405, 405, 405, 405, 212, 215, 213, 213, - 345, 346, 409, 409, 556, 215, 346, 214, 280, 280, - 347, 347, 191, 520, 520, 766, 729, 557, 212, 766, - 217, 217, 214, 411, 411, 408, 280, 408, 347, 214, - 409, 409, 215, 215, 280, 459, 347, 191, 657, 191, - 700, 411, 336, 336, 214, 350, 350, 277, 277, 411, - 215, 282, 282, 350, 350, 350, 406, 407, 215, 407, - 657, 410, 716, 410, 680, 350, 350, 350, 350, 350, - - 350, 406, 407, 273, 657, 462, 410, 407, 621, 191, - 681, 410, 340, 340, 191, 191, 191, 463, 191, 463, - 411, 411, 464, 464, 344, 344, 349, 349, 119, 347, - 347, 736, 191, 465, 466, 467, 466, 467, 411, 558, - 468, 468, 191, 659, 191, 273, 411, 347, 465, 466, - 349, 349, 464, 464, 466, 347, 737, 405, 405, 519, - 469, 519, 469, 191, 520, 520, 559, 276, 559, 276, - 119, 560, 560, 657, 619, 469, 191, 728, 657, 619, - 469, 191, 276, 620, 468, 468, 191, 276, 620, 350, - 350, 684, 710, 409, 409, 658, 658, 350, 350, 350, - - 685, 470, 470, 279, 273, 279, 470, 470, 191, 350, - 350, 350, 350, 350, 350, 622, 464, 464, 279, 470, - 702, 721, 191, 279, 470, 720, 343, 470, 343, 119, - 468, 468, 470, 520, 520, 715, 273, 703, 703, 191, - 346, 343, 346, 407, 191, 407, 343, 560, 560, 657, - 660, 273, 560, 560, 273, 346, 273, 657, 407, 682, - 346, 119, 466, 407, 466, 684, 658, 658, 273, 686, - 702, 273, 273, 702, 685, 717, 119, 466, 273, 119, - 711, 119, 466, 705, 657, 687, 702, 703, 703, 702, - 657, 273, 273, 119, 730, 704, 119, 119, 702, 118, - - 731, 273, 657, 119, 657, 724, 702, 733, 702, 273, - 118, 657, 712, 657, 718, 713, 119, 119, 733, 719, - 657, 702, 702, 118, 657, 722, 119, 702, 118, 726, - 739, 748, 734, 702, 119, 725, 748, 702, 702, 702, - 743, 723, 735, 734, 741, 746, 740, 702, 714, 702, - 709, 708, 707, 744, 738, 706, 749, 191, 745, 699, - 698, 749, 755, 750, 697, 751, 696, 758, 695, 694, - 693, 692, 691, 752, 753, 690, 689, 756, 688, 657, - 679, 678, 757, 760, 677, 676, 675, 674, 763, 759, - 764, 110, 110, 110, 110, 110, 118, 118, 673, 118, - - 118, 141, 141, 190, 190, 190, 190, 190, 199, 199, - 199, 199, 199, 618, 618, 618, 618, 618, 656, 656, - 656, 656, 656, 683, 683, 683, 683, 683, 701, 701, - 701, 701, 701, 727, 672, 727, 727, 727, 732, 732, - 732, 732, 732, 742, 671, 742, 742, 742, 747, 747, - 747, 747, 747, 754, 754, 754, 754, 754, 761, 761, - 761, 761, 761, 762, 762, 762, 762, 762, 765, 765, - 765, 765, 765, 670, 669, 668, 667, 666, 665, 664, - 663, 662, 661, 191, 655, 654, 653, 652, 651, 650, - 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, - - 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, - 629, 628, 627, 626, 625, 624, 623, 617, 616, 615, - 614, 613, 612, 611, 610, 609, 608, 607, 606, 605, - 604, 603, 602, 601, 600, 599, 598, 597, 596, 595, - 594, 593, 592, 591, 590, 589, 588, 587, 586, 585, - 584, 583, 582, 581, 580, 579, 578, 577, 576, 575, - 574, 573, 572, 571, 570, 569, 568, 567, 566, 565, - 564, 563, 562, 561, 191, 191, 555, 554, 553, 552, - 551, 550, 549, 548, 547, 546, 545, 544, 543, 542, - 541, 540, 539, 538, 537, 536, 535, 534, 533, 532, - - 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, - 521, 518, 517, 516, 515, 514, 513, 512, 511, 510, - 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, - 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, - 489, 488, 487, 486, 483, 482, 481, 480, 479, 478, - 477, 476, 475, 474, 473, 472, 471, 191, 191, 191, - 191, 191, 191, 458, 457, 456, 455, 454, 453, 452, - 451, 450, 449, 448, 447, 446, 445, 444, 443, 442, - 441, 440, 439, 438, 437, 436, 435, 434, 433, 432, - 431, 430, 429, 428, 427, 424, 423, 422, 421, 420, - - 419, 418, 417, 416, 415, 414, 413, 412, 403, 191, - 191, 402, 401, 398, 395, 394, 389, 388, 387, 383, - 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, - 372, 371, 370, 369, 368, 365, 364, 363, 362, 361, - 360, 359, 358, 357, 356, 355, 354, 353, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 335, 334, 331, 328, - 327, 322, 321, 320, 316, 315, 314, 313, 312, 311, - 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, - 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, - - 288, 287, 286, 285, 284, 274, 272, 191, 191, 191, - 269, 268, 267, 264, 257, 256, 255, 254, 250, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 187, 186, 185, 182, 175, 174, 173, 172, 168, 142, - 138, 120, 119, 115, 114, 113, 766, 5, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766 - } ; - -static yyconst short int yy_chk[1416] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 4, 13, 18, 118, 21, - 20, 21, 21, 22, 27, 27, 772, 18, 20, 20, - 24, 13, 24, 24, 22, 29, 29, 36, 36, 37, - 119, 24, 55, 118, 24, 24, 37, 40, 119, 40, - 3, 4, 23, 50, 23, 23, 24, 50, 40, 88, - 88, 39, 24, 23, 765, 39, 23, 23, 23, 35, - 24, 35, 35, 38, 39, 35, 61, 35, 23, 64, - - 38, 35, 55, 35, 23, 61, 38, 41, 38, 43, - 35, 43, 23, 764, 62, 23, 65, 41, 43, 48, - 41, 67, 67, 48, 157, 48, 48, 62, 66, 65, - 66, 69, 185, 157, 185, 48, 70, 64, 48, 70, - 72, 64, 73, 66, 69, 72, 67, 79, 73, 70, - 73, 73, 80, 72, 72, 74, 89, 74, 86, 79, - 79, 191, 191, 89, 76, 80, 81, 180, 74, 75, - 76, 86, 76, 76, 95, 75, 95, 75, 75, 81, - 81, 76, 180, 95, 76, 76, 75, 762, 179, 75, - 75, 75, 87, 102, 87, 87, 76, 102, 87, 91, - - 87, 75, 76, 91, 87, 179, 87, 75, 183, 761, - 76, 208, 91, 87, 759, 75, 183, 208, 75, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 90, 92, 100, 92, - 93, 261, 100, 90, 100, 100, 107, 195, 92, 90, - - 93, 90, 201, 93, 100, 127, 127, 100, 261, 107, - 194, 201, 130, 130, 127, 127, 267, 127, 267, 281, - 281, 130, 130, 758, 130, 175, 132, 175, 132, 127, - 127, 132, 132, 133, 133, 127, 130, 130, 175, 262, - 195, 131, 130, 131, 131, 218, 194, 199, 199, 107, - 337, 133, 131, 754, 262, 131, 131, 265, 218, 133, - 135, 214, 135, 135, 214, 265, 214, 131, 200, 214, - 214, 135, 199, 131, 135, 135, 239, 200, 200, 209, - 338, 131, 222, 300, 300, 239, 135, 209, 209, 215, - 337, 750, 135, 200, 722, 222, 209, 209, 212, 209, - - 135, 257, 460, 257, 367, 367, 212, 212, 338, 215, - 215, 209, 209, 461, 257, 212, 212, 209, 212, 275, - 213, 275, 404, 404, 275, 275, 213, 215, 213, 213, - 212, 212, 408, 408, 460, 215, 212, 213, 280, 280, - 213, 213, 217, 519, 519, 749, 722, 461, 217, 734, - 217, 217, 213, 283, 283, 278, 280, 278, 213, 217, - 278, 278, 217, 217, 280, 336, 213, 216, 682, 557, - 682, 283, 336, 336, 217, 216, 216, 277, 277, 283, - 217, 282, 282, 216, 216, 216, 277, 277, 217, 277, - 710, 282, 710, 282, 655, 216, 216, 216, 216, 216, - - 216, 277, 277, 340, 729, 340, 282, 277, 557, 347, - 655, 282, 340, 340, 342, 621, 344, 342, 348, 342, - 411, 411, 342, 342, 344, 344, 348, 348, 340, 347, - 347, 728, 345, 344, 344, 345, 344, 345, 411, 462, - 345, 345, 349, 621, 463, 462, 411, 347, 344, 344, - 349, 349, 463, 463, 344, 347, 729, 405, 405, 406, - 349, 406, 349, 465, 406, 406, 465, 405, 465, 405, - 462, 465, 465, 700, 556, 349, 467, 721, 620, 618, - 349, 350, 405, 556, 467, 467, 470, 405, 618, 350, - 350, 659, 700, 409, 409, 620, 620, 350, 350, 350, - - 659, 350, 350, 409, 558, 409, 470, 470, 464, 350, - 350, 350, 350, 350, 350, 558, 464, 464, 409, 350, - 685, 715, 468, 409, 470, 714, 464, 350, 464, 558, - 468, 468, 470, 520, 520, 709, 660, 685, 685, 559, - 468, 464, 468, 520, 560, 520, 464, 559, 559, 658, - 622, 686, 560, 560, 687, 468, 622, 723, 520, 658, - 468, 660, 560, 520, 560, 683, 658, 658, 704, 660, - 703, 705, 712, 711, 683, 711, 686, 560, 713, 687, - 703, 622, 560, 687, 716, 660, 717, 703, 703, 731, - 737, 718, 719, 704, 723, 686, 705, 712, 724, 725, - - 724, 726, 730, 713, 738, 717, 739, 725, 740, 735, - 732, 743, 704, 751, 712, 705, 718, 719, 732, 713, - 744, 745, 746, 741, 755, 716, 726, 752, 747, 719, - 731, 741, 725, 753, 735, 718, 747, 756, 757, 760, - 737, 716, 726, 732, 735, 740, 731, 763, 708, 701, - 699, 698, 692, 738, 730, 691, 741, 684, 739, 681, - 680, 747, 751, 743, 676, 744, 675, 755, 670, 669, - 667, 666, 665, 745, 746, 663, 662, 752, 661, 656, - 654, 653, 753, 757, 651, 650, 649, 647, 760, 756, - 763, 767, 767, 767, 767, 767, 768, 768, 646, 768, - - 768, 769, 769, 770, 770, 770, 770, 770, 771, 771, - 771, 771, 771, 773, 773, 773, 773, 773, 774, 774, - 774, 774, 774, 775, 775, 775, 775, 775, 776, 776, - 776, 776, 776, 777, 645, 777, 777, 777, 778, 778, - 778, 778, 778, 779, 644, 779, 779, 779, 780, 780, - 780, 780, 780, 781, 781, 781, 781, 781, 782, 782, - 782, 782, 782, 783, 783, 783, 783, 783, 784, 784, - 784, 784, 784, 643, 642, 641, 634, 633, 632, 629, - 628, 627, 623, 619, 617, 616, 615, 614, 607, 606, - 605, 602, 601, 600, 596, 595, 592, 590, 588, 587, - - 586, 585, 584, 583, 581, 580, 579, 577, 574, 573, - 572, 571, 570, 567, 566, 564, 563, 555, 552, 550, - 548, 547, 546, 545, 544, 543, 541, 540, 539, 537, - 534, 533, 532, 531, 530, 527, 526, 524, 523, 518, - 517, 516, 515, 513, 512, 511, 510, 509, 508, 507, - 506, 505, 504, 502, 501, 500, 499, 496, 495, 493, - 492, 489, 488, 486, 485, 484, 480, 478, 477, 476, - 475, 474, 473, 472, 469, 466, 459, 458, 457, 456, - 454, 453, 452, 451, 450, 449, 448, 447, 446, 445, - 443, 442, 441, 440, 437, 436, 434, 433, 430, 429, - - 427, 426, 425, 421, 419, 418, 417, 416, 415, 414, - 413, 403, 402, 401, 400, 399, 398, 397, 396, 395, - 394, 393, 392, 391, 390, 389, 387, 386, 385, 384, - 383, 382, 381, 380, 379, 378, 376, 374, 373, 372, - 371, 370, 369, 368, 366, 365, 364, 363, 361, 360, - 359, 358, 357, 356, 355, 354, 353, 352, 351, 346, - 343, 341, 339, 335, 334, 333, 332, 331, 330, 329, - 328, 327, 326, 325, 324, 323, 322, 320, 319, 318, - 317, 316, 315, 314, 313, 312, 311, 309, 307, 306, - 305, 304, 303, 302, 301, 299, 298, 297, 296, 294, - - 293, 292, 291, 290, 289, 288, 287, 286, 272, 271, - 270, 269, 268, 266, 264, 263, 260, 259, 258, 256, - 255, 254, 253, 251, 250, 249, 248, 247, 246, 245, - 244, 243, 242, 241, 240, 238, 237, 236, 235, 234, - 232, 231, 230, 229, 228, 227, 226, 225, 224, 221, - 220, 219, 211, 210, 207, 206, 205, 204, 203, 202, - 198, 197, 196, 193, 192, 190, 187, 186, 184, 182, - 181, 178, 177, 176, 174, 173, 172, 171, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, - 156, 155, 154, 153, 152, 150, 149, 148, 147, 146, - - 145, 144, 143, 140, 136, 126, 112, 109, 108, 106, - 105, 104, 103, 101, 99, 98, 97, 96, 94, 85, - 84, 82, 78, 77, 71, 68, 63, 60, 59, 58, - 53, 52, 51, 49, 47, 46, 45, 44, 42, 34, - 28, 17, 14, 12, 10, 9, 5, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - - 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, - 766, 766, 766, 766, 766 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "SDCC.lex" -#define INITIAL 0 -/*----------------------------------------------------------------------- - SDCC.lex - lexical analyser for use with sdcc ( a freeware compiler for - 8/16 bit microcontrollers) - Written by : Sandeep Dutta . sandeep.dutta@usa.net (1997) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! --------------------------------------------------------------------------*/ -#line 32 "SDCC.lex" - -#include -#include -#include -#include "SDCCglobl.h" -#include "SDCCsymt.h" -#include "SDCCval.h" -#include "SDCCast.h" -#include "SDCCy.h" -#include "SDCChasht.h" -#include "SDCCmem.h" - -char *stringLiteral(); -char *currFname; - -extern int lineno ; -extern char *filename ; -extern char *fullSrcFileName ; -int yylineno = 1 ; -void count() ; -void comment(); -int process_pragma(char *); -#undef yywrap - -int yywrap YY_PROTO((void)) -{ - return(1); -} - -char asmbuff[MAX_INLINEASM] ; -char *asmp ; -extern int check_type ( ); -extern int checkCurrFile (char *); -extern int processPragma (char *); -extern int printListing (int ); -struct optimize save_optimize ; -struct options save_options ; - - enum { - P_SAVE = 1, - P_RESTORE , - P_NOINDUCTION, - P_NOINVARIANT, - P_INDUCTION , - P_STACKAUTO , - P_NOJTBOUND , - P_NOOVERLAY , - P_NOGCSE , - P_CALLEE_SAVES, - P_EXCLUDE , - P_LOOPREV - }; - -#define asm 1 - - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); -#else -extern int yywrap YY_PROTO(( void )); -#endif -#endif - -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput YY_PROTO(( void )); -#else -static int input YY_PROTO(( void )); -#endif -#endif - -#if YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif - -#else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 -#endif - -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#if __STDC__ -#ifndef __cplusplus -#include -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ - -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ - { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - if ( yyleng > 0 ) \ - yy_current_buffer->yy_at_bol = \ - (yytext[yyleng - 1] == '\n'); \ - YY_USER_ACTION - -YY_DECL - { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 87 "SDCC.lex" - - - if ( yy_init ) - { - yy_init = 0; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yy_start ) - yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_load_buffer_state(); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 767 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 1348 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - - -do_action: /* This label is used only to access EOF actions. */ - - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 88 "SDCC.lex" -{ count(); asmp = asmbuff ;BEGIN(asm) ;} - YY_BREAK -case 2: -YY_RULE_SETUP -#line 89 "SDCC.lex" -{ count() ; - *asmp = '\0' ; - strcpy(yylval.yyinline,asmbuff) ; - BEGIN(INITIAL) ; - return (INLINEASM) ; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 94 "SDCC.lex" -{ *asmp++ = yytext[0] ; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 95 "SDCC.lex" -{ count(); *asmp++ = '\n' ;} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 96 "SDCC.lex" -{ comment(); } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 97 "SDCC.lex" -{ count(); return(AT) ; } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 98 "SDCC.lex" -{ count(); return(AUTO); } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 99 "SDCC.lex" -{ count(); return(BIT) ; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 100 "SDCC.lex" -{ count(); return(BREAK); } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 101 "SDCC.lex" -{ count(); return(CASE); } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 102 "SDCC.lex" -{ count(); return(CHAR); } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 103 "SDCC.lex" -{ count(); return(CODE); } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 104 "SDCC.lex" -{ count(); return(CONST); } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 105 "SDCC.lex" -{ count(); return(CONTINUE); } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 106 "SDCC.lex" -{ count(); return(CRITICAL); } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 107 "SDCC.lex" -{ count(); return(DATA); } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 108 "SDCC.lex" -{ count(); return(DEFAULT); } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 109 "SDCC.lex" -{ count(); return(DO); } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 110 "SDCC.lex" -{ count(); werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 111 "SDCC.lex" -{ count(); return(ELSE); } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 112 "SDCC.lex" -{ count(); return(ENUM); } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 113 "SDCC.lex" -{ count(); return(EXTERN); } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 114 "SDCC.lex" -{ count(); return(XDATA); } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 115 "SDCC.lex" -{ count(); return(FLOAT); } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 116 "SDCC.lex" -{ count(); return(FOR); } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 117 "SDCC.lex" -{ count(); return(GOTO); } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 118 "SDCC.lex" -{ count(); return(IDATA);} - YY_BREAK -case 28: -YY_RULE_SETUP -#line 119 "SDCC.lex" -{ count(); return(IF); } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 120 "SDCC.lex" -{ count(); return(INT); } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 121 "SDCC.lex" -{ count(); return(INTERRUPT);} - YY_BREAK -case 31: -YY_RULE_SETUP -#line 122 "SDCC.lex" -{ count(); return(LONG); } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 123 "SDCC.lex" -{ count(); return(DATA);} - YY_BREAK -case 33: -YY_RULE_SETUP -#line 124 "SDCC.lex" -{ count(); return(PDATA); } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 125 "SDCC.lex" -{ count(); return(REENTRANT);} - YY_BREAK -case 35: -YY_RULE_SETUP -#line 126 "SDCC.lex" -{ count(); return(REGISTER); } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 127 "SDCC.lex" -{ count(); return(RETURN); } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 128 "SDCC.lex" -{ count(); return(SFR) ; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 129 "SDCC.lex" -{ count(); return(SBIT) ; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 130 "SDCC.lex" -{ count(); return(SHORT); } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 131 "SDCC.lex" -{ count(); return(SIGNED); } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 132 "SDCC.lex" -{ count(); return(SIZEOF); } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 133 "SDCC.lex" -{ count(); return(STATIC); } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 134 "SDCC.lex" -{ count(); return(STRUCT); } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 135 "SDCC.lex" -{ count(); return(SWITCH); } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 136 "SDCC.lex" -{ count(); return(TYPEDEF); } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 137 "SDCC.lex" -{ count(); return(UNION); } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 138 "SDCC.lex" -{ count(); return(UNSIGNED); } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 139 "SDCC.lex" -{ count(); return(VOID); } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 140 "SDCC.lex" -{ count(); return(VOLATILE); } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 141 "SDCC.lex" -{ count(); return(USING); } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 142 "SDCC.lex" -{ count(); return(WHILE); } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 143 "SDCC.lex" -{ count(); return(XDATA); } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 144 "SDCC.lex" -{ count(); return(_NEAR); } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 145 "SDCC.lex" -{ count(); return(_CODE); } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 146 "SDCC.lex" -{ count(); return(_GENERIC); } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 147 "SDCC.lex" -{ count(); return(_NEAR); } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 148 "SDCC.lex" -{ count(); return(_XDATA);} - YY_BREAK -case 58: -YY_RULE_SETUP -#line 149 "SDCC.lex" -{ count () ; return(_PDATA); } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 150 "SDCC.lex" -{ count () ; return(_IDATA); } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 151 "SDCC.lex" -{ count(); return(VAR_ARGS);} - YY_BREAK -case 61: -YY_RULE_SETUP -#line 152 "SDCC.lex" -{ count(); return(check_type()); } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 153 "SDCC.lex" -{ count(); yylval.val = constVal(yytext); return(CONSTANT); } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 154 "SDCC.lex" -{ count(); yylval.val = constVal(yytext); return(CONSTANT); } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 155 "SDCC.lex" -{ count(); yylval.val = constVal(yytext); return(CONSTANT); } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 156 "SDCC.lex" -{ count();yylval.val = charVal (yytext); return(CONSTANT); } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 157 "SDCC.lex" -{ count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 158 "SDCC.lex" -{ count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 159 "SDCC.lex" -{ count(); yylval.val = constFloatVal(yytext);return(CONSTANT); } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 160 "SDCC.lex" -{ count(); yylval.val=strVal(stringLiteral()); return(STRING_LITERAL);} - YY_BREAK -case 70: -YY_RULE_SETUP -#line 161 "SDCC.lex" -{ count(); yylval.yyint = RIGHT_ASSIGN ; return(RIGHT_ASSIGN); } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 162 "SDCC.lex" -{ count(); yylval.yyint = LEFT_ASSIGN ; return(LEFT_ASSIGN) ; } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 163 "SDCC.lex" -{ count(); yylval.yyint = ADD_ASSIGN ; return(ADD_ASSIGN) ; } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 164 "SDCC.lex" -{ count(); yylval.yyint = SUB_ASSIGN ; return(SUB_ASSIGN) ; } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 165 "SDCC.lex" -{ count(); yylval.yyint = MUL_ASSIGN ; return(MUL_ASSIGN) ; } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 166 "SDCC.lex" -{ count(); yylval.yyint = DIV_ASSIGN ; return(DIV_ASSIGN) ; } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 167 "SDCC.lex" -{ count(); yylval.yyint = MOD_ASSIGN ; return(MOD_ASSIGN) ; } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 168 "SDCC.lex" -{ count(); yylval.yyint = AND_ASSIGN ; return(AND_ASSIGN) ; } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 169 "SDCC.lex" -{ count(); yylval.yyint = XOR_ASSIGN ; return(XOR_ASSIGN) ; } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 170 "SDCC.lex" -{ count(); yylval.yyint = OR_ASSIGN ; return(OR_ASSIGN) ; } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 171 "SDCC.lex" -{ count(); return(RIGHT_OP); } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 172 "SDCC.lex" -{ count(); return(LEFT_OP); } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 173 "SDCC.lex" -{ count(); return(INC_OP); } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 174 "SDCC.lex" -{ count(); return(DEC_OP); } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 175 "SDCC.lex" -{ count(); return(PTR_OP); } - YY_BREAK -case 85: -YY_RULE_SETUP -#line 176 "SDCC.lex" -{ count(); return(AND_OP); } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 177 "SDCC.lex" -{ count(); return(OR_OP); } - YY_BREAK -case 87: -YY_RULE_SETUP -#line 178 "SDCC.lex" -{ count(); return(LE_OP); } - YY_BREAK -case 88: -YY_RULE_SETUP -#line 179 "SDCC.lex" -{ count(); return(GE_OP); } - YY_BREAK -case 89: -YY_RULE_SETUP -#line 180 "SDCC.lex" -{ count(); return(EQ_OP); } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 181 "SDCC.lex" -{ count(); return(NE_OP); } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 182 "SDCC.lex" -{ count(); return(';'); } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 183 "SDCC.lex" -{ count() ; NestLevel++ ; return('{'); } - YY_BREAK -case 93: -YY_RULE_SETUP -#line 184 "SDCC.lex" -{ count(); NestLevel--; return('}'); } - YY_BREAK -case 94: -YY_RULE_SETUP -#line 185 "SDCC.lex" -{ count(); return(','); } - YY_BREAK -case 95: -YY_RULE_SETUP -#line 186 "SDCC.lex" -{ count(); return(':'); } - YY_BREAK -case 96: -YY_RULE_SETUP -#line 187 "SDCC.lex" -{ count(); return('='); } - YY_BREAK -case 97: -YY_RULE_SETUP -#line 188 "SDCC.lex" -{ count(); return('('); } - YY_BREAK -case 98: -YY_RULE_SETUP -#line 189 "SDCC.lex" -{ count(); return(')'); } - YY_BREAK -case 99: -YY_RULE_SETUP -#line 190 "SDCC.lex" -{ count(); return('['); } - YY_BREAK -case 100: -YY_RULE_SETUP -#line 191 "SDCC.lex" -{ count(); return(']'); } - YY_BREAK -case 101: -YY_RULE_SETUP -#line 192 "SDCC.lex" -{ count(); return('.'); } - YY_BREAK -case 102: -YY_RULE_SETUP -#line 193 "SDCC.lex" -{ count(); return('&'); } - YY_BREAK -case 103: -YY_RULE_SETUP -#line 194 "SDCC.lex" -{ count(); return('!'); } - YY_BREAK -case 104: -YY_RULE_SETUP -#line 195 "SDCC.lex" -{ count(); return('~'); } - YY_BREAK -case 105: -YY_RULE_SETUP -#line 196 "SDCC.lex" -{ count(); return('-'); } - YY_BREAK -case 106: -YY_RULE_SETUP -#line 197 "SDCC.lex" -{ count(); return('+'); } - YY_BREAK -case 107: -YY_RULE_SETUP -#line 198 "SDCC.lex" -{ count(); return('*'); } - YY_BREAK -case 108: -YY_RULE_SETUP -#line 199 "SDCC.lex" -{ count(); return('/'); } - YY_BREAK -case 109: -YY_RULE_SETUP -#line 200 "SDCC.lex" -{ count(); return('%'); } - YY_BREAK -case 110: -YY_RULE_SETUP -#line 201 "SDCC.lex" -{ count(); return('<'); } - YY_BREAK -case 111: -YY_RULE_SETUP -#line 202 "SDCC.lex" -{ count(); return('>'); } - YY_BREAK -case 112: -YY_RULE_SETUP -#line 203 "SDCC.lex" -{ count(); return('^'); } - YY_BREAK -case 113: -YY_RULE_SETUP -#line 204 "SDCC.lex" -{ count(); return('|'); } - YY_BREAK -case 114: -YY_RULE_SETUP -#line 205 "SDCC.lex" -{ count(); return('?'); } - YY_BREAK -case 115: -YY_RULE_SETUP -#line 206 "SDCC.lex" -{ count(); checkCurrFile(yytext); } - YY_BREAK -case 116: -YY_RULE_SETUP -#line 207 "SDCC.lex" -{ count(); process_pragma(yytext); } - YY_BREAK -case 117: -YY_RULE_SETUP -#line 209 "SDCC.lex" -{ werror(E_PRE_PROC_FAILED,yytext);count(); } - YY_BREAK -case 118: -YY_RULE_SETUP -#line 210 "SDCC.lex" -{ werror(W_PRE_PROC_WARNING,yytext);count(); } - YY_BREAK -case 119: -YY_RULE_SETUP -#line 211 "SDCC.lex" -{ count(); } - YY_BREAK -case 120: -YY_RULE_SETUP -#line 212 "SDCC.lex" -{ count(); } - YY_BREAK -case 121: -YY_RULE_SETUP -#line 213 "SDCC.lex" -{ count(); } - YY_BREAK -case 122: -YY_RULE_SETUP -#line 214 "SDCC.lex" -{ count() ; } - YY_BREAK -case 123: -YY_RULE_SETUP -#line 215 "SDCC.lex" -ECHO; - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(asm): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yy_c_buf_p; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer() ) - { - case EOB_ACT_END_OF_FILE: - { - yy_did_buffer_switch_on_eof = 0; - - if ( yywrap() ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of yylex */ - - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; - register int number_to_move, i; - int ret_val; - - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( yy_current_buffer->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; - - else - { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; - - int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = yy_current_buffer->yy_buf_size - - number_to_move - 1; -#endif - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); - - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - if ( yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; - - return ret_val; - } - - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -static yy_state_type yy_get_previous_state() - { - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 767 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; - } - - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { - register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 767 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 766); - - return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - - -#ifdef __cplusplus -static int yyinput() -#else -static int input() -#endif - { - int c; - - *yy_c_buf_p = yy_hold_char; - - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - /* This was really a NUL. */ - *yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yy_c_buf_p - yytext_ptr; - ++yy_c_buf_p; - - switch ( yy_get_next_buffer() ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /* fall through */ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap() ) - return EOF; - - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - - yy_current_buffer->yy_at_bol = (c == '\n'); - - return c; - } - - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); - } - - -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) - return; - - if ( yy_current_buffer ) - { - /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - yy_current_buffer = new_buffer; - yy_load_buffer_state(); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } - - -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; - } - - -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { - if ( ! b ) - return; - - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - - -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -extern int isatty YY_PROTO(( int )); -#endif -#endif - -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif - - - { - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - -#if YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - } - - -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif - - { - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == yy_current_buffer ) - yy_load_buffer_state(); - } - - -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; - } -#endif - - -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; - - return yy_scan_bytes( yy_str, len ); - } -#endif - - -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; - - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; - } -#endif - - -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; -#endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; - - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); - - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); - - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); - - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } - - yy_start_stack[yy_start_stack_ptr++] = YY_START; - - BEGIN(new_state); - } -#endif - - -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif - - -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) -#else -static void yy_fatal_error( msg ) -char msg[]; -#endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } - - - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) - - -/* Internal utility routines. */ - -#ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; - } -#endif - -#ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; - } -#endif - - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { - return (void *) malloc( size ); - } - -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); - } - -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } - -#if YY_MAIN -int main() - { - yylex(); - return 0; - } -#endif -#line 215 "SDCC.lex" - - -int checkCurrFile ( char *s) -{ - char lineNum[10] ; - int lNum ; - char *tptr ; - - /* first check if this is a #line */ - if ( strncmp(s,"#line",5) ) - return 0 ; - - /* get to the line number */ - while (!isdigit(*s)) - s++ ; - tptr = lineNum ; - while (isdigit(*s)) - *tptr++ = *s++ ; - *tptr = '\0'; - sscanf(lineNum,"%d",&lNum); - - /* now see if we have a file name */ - while (*s != '\"' && *s) - s++ ; - - /* if we don't have a filename then */ - /* set the current line number to */ - /* line number if printFlag is on */ - if (!*s) { - yylineno = lNum ; - return 0; - } - - /* if we have a filename then check */ - /* if it is "standard in" if yes then */ - /* get the currentfile name info */ - s++ ; - - if ( strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) { - yylineno = lNum - 2; - currFname = fullSrcFileName ; - } else { - char *sb = s; - /* mark the end of the filename */ - while (*s != '"') s++; - *s = '\0'; - ALLOC_ATOMIC(currFname,strlen(sb)+1); - strcpy(currFname,sb); - yylineno = lNum - 2; - } - filename = currFname ; - return 0; -} - -void comment() -{ - char c, c1; - -loop: - while ((c = input()) != '*' && c != 0) - if ( c == '\n') - yylineno++ ; - - if ((c1 = input()) != '/' && c != 0) { - if ( c1 == '\n' ) - yylineno++ ; - - unput(c1); - goto loop; - } - -} - - - -int column = 0; -int plineIdx=0; - -void count() -{ - int i; - for (i = 0; yytext[i] != '\0'; i++) { - if (yytext[i] == '\n') { - column = 0; - lineno = ++yylineno ; - } - else - if (yytext[i] == '\t') - column += 8 - (column % 8); - else - column++; - } - - /* ECHO; */ -} - -int check_type() -{ - /* check if it is in the typedef table */ - if (findSym(TypedefTab,NULL,yytext)) { - strcpy(yylval.yychar,yytext); - return (TYPE_NAME) ; - } - else { - strcpy (yylval.yychar,yytext); - return(IDENTIFIER); - } -} - -char strLitBuff[2048] ; - -char *stringLiteral () -{ - int ch; - char *str = strLitBuff ; - - *str++ = '\"' ; - /* put into the buffer till we hit the */ - /* first \" */ - while (1) { - - ch = input() ; - if (!ch) break ; /* end of input */ - /* if it is a \ then everything allowed */ - if (ch == '\\') { - *str++ = ch ; /* backslash in place */ - *str++ = input() ; /* following char in place */ - continue ; /* carry on */ - } - - /* if new line we have a new line break */ - if (ch == '\n') break ; - - /* if this is a quote then we have work to do */ - /* find the next non whitespace character */ - /* if that is a double quote then carry on */ - if (ch == '\"') { - - while ((ch = input()) && isspace(ch)) ; - if (!ch) break ; - if (ch != '\"') { - unput(ch) ; - break ; - } - - continue ; - } - *str++ = ch; - } - *str++ = '\"' ; - *str = '\0'; - return strLitBuff ; -} - -void doPragma (int op, char *cp) -{ - switch (op) { - case P_SAVE: - memcpy(&save_options,&options,sizeof(options)); - memcpy(&save_optimize,&optimize,sizeof(optimize)); - break; - case P_RESTORE: - memcpy(&options,&save_options,sizeof(options)); - memcpy(&optimize,&save_optimize,sizeof(optimize)); - break; - case P_NOINDUCTION: - optimize.loopInduction = 0 ; - break; - case P_NOINVARIANT: - optimize.loopInvariant = 0 ; - break; - case P_INDUCTION: - optimize.loopInduction = 1 ; - break; - case P_STACKAUTO: - options.stackAuto = 1; - break; - case P_NOJTBOUND: - optimize.noJTabBoundary = 1; - break; - case P_NOGCSE: - optimize.global_cse = 0; - break; - case P_NOOVERLAY: - options.noOverlay = 1; - break; - case P_CALLEE_SAVES: - { - int i=0; - /* append to the functions already listed - in callee-saves */ - for (; options.calleeSaves[i] ;i++); - parseWithComma(&options.calleeSaves[i],strdup(cp)); - } - break; - case P_EXCLUDE: - parseWithComma(options.excludeRegs,strdup(cp)); - break; - case P_LOOPREV: - optimize.noLoopReverse = 1; - break; - } -} - -int process_pragma(char *s) -{ - char *cp ; - /* find the pragma */ - while (strncmp(s,"#pragma",7)) - s++; - s += 7; - - /* look for the directive */ - while(isspace(*s)) s++; - - cp = s; - /* look for the end of the directive */ - while ((! isspace(*s)) && - (*s != '\n')) - s++ ; - - /* now compare and do what needs to be done */ - if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) { - doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE)); - return 0; - } - - if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) { - doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE)); - return 0; - } - - if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) { - doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ; - return 0; - } - - if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) { - doPragma (P_NOINVARIANT,NULL) ; - return 0; - } - - if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) { - doPragma (P_INDUCTION,NULL) ; - return 0; - } - - if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) { - doPragma (P_STACKAUTO,NULL); - return 0; - } - - if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) { - doPragma (P_NOJTBOUND,NULL); - return 0; - } - - if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) { - doPragma (P_NOGCSE,NULL); - return 0; - } - - if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) { - doPragma (P_NOOVERLAY,NULL); - return 0; - } - - if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) { - doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES)); - return 0; - } - - if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) { - doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE)); - return 0; - } - - if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) { - doPragma(P_EXCLUDE,NULL); - return 0; - } - - werror(W_UNKNOWN_PRAGMA,cp); - return 0; -} diff --git a/src/SDCCy.c b/src/SDCCy.c deleted file mode 100644 index 596ca698..00000000 --- a/src/SDCCy.c +++ /dev/null @@ -1,3093 +0,0 @@ - -/* A Bison parser, made from SDCC.y - by GNU Bison version 1.28 */ - -#define YYBISON 1 /* Identify Bison output. */ - -#define IDENTIFIER 257 -#define TYPE_NAME 258 -#define CONSTANT 259 -#define STRING_LITERAL 260 -#define SIZEOF 261 -#define PTR_OP 262 -#define INC_OP 263 -#define DEC_OP 264 -#define LEFT_OP 265 -#define RIGHT_OP 266 -#define LE_OP 267 -#define GE_OP 268 -#define EQ_OP 269 -#define NE_OP 270 -#define AND_OP 271 -#define OR_OP 272 -#define MUL_ASSIGN 273 -#define DIV_ASSIGN 274 -#define MOD_ASSIGN 275 -#define ADD_ASSIGN 276 -#define SUB_ASSIGN 277 -#define LEFT_ASSIGN 278 -#define RIGHT_ASSIGN 279 -#define AND_ASSIGN 280 -#define XOR_ASSIGN 281 -#define OR_ASSIGN 282 -#define TYPEDEF 283 -#define EXTERN 284 -#define STATIC 285 -#define AUTO 286 -#define REGISTER 287 -#define CODE 288 -#define INTERRUPT 289 -#define SFR 290 -#define AT 291 -#define SBIT 292 -#define REENTRANT 293 -#define USING 294 -#define XDATA 295 -#define DATA 296 -#define IDATA 297 -#define PDATA 298 -#define VAR_ARGS 299 -#define CRITICAL 300 -#define CHAR 301 -#define SHORT 302 -#define INT 303 -#define LONG 304 -#define SIGNED 305 -#define UNSIGNED 306 -#define FLOAT 307 -#define DOUBLE 308 -#define CONST 309 -#define VOLATILE 310 -#define VOID 311 -#define BIT 312 -#define STRUCT 313 -#define UNION 314 -#define ENUM 315 -#define ELIPSIS 316 -#define RANGE 317 -#define FAR 318 -#define _XDATA 319 -#define _CODE 320 -#define _GENERIC 321 -#define _NEAR 322 -#define _PDATA 323 -#define _IDATA 324 -#define CASE 325 -#define DEFAULT 326 -#define IF 327 -#define ELSE 328 -#define SWITCH 329 -#define WHILE 330 -#define DO 331 -#define FOR 332 -#define GOTO 333 -#define CONTINUE 334 -#define BREAK 335 -#define RETURN 336 -#define INLINEASM 337 -#define IFX 338 -#define ADDRESS_OF 339 -#define GET_VALUE_AT_ADDRESS 340 -#define SPIL 341 -#define UNSPIL 342 -#define GETHBIT 343 -#define BITWISEAND 344 -#define UNARYMINUS 345 -#define IPUSH 346 -#define IPOP 347 -#define PCALL 348 -#define ENDFUNCTION 349 -#define JUMPTABLE 350 -#define RRC 351 -#define RLC 352 -#define CAST 353 -#define CALL 354 -#define PARAM 355 -#define NULLOP 356 -#define BLOCK 357 -#define LABEL 358 -#define RECEIVE 359 -#define SEND 360 - -#line 24 "SDCC.y" - -#include -#include -#include -#include "SDCCglobl.h" -#include "SDCCsymt.h" -#include "SDCChasht.h" -#include "SDCCval.h" -#include "SDCCmem.h" -#include "SDCCast.h" -extern int yyerror (char *); -extern FILE *yyin; -extern char srcLstFname[]; -int NestLevel = 0 ; /* current NestLevel */ -int stackPtr = 1 ; /* stack pointer */ -int xstackPtr = 0 ; /* xstack pointer */ -int reentrant = 0 ; -int blockNo = 0 ; /* sequential block number */ -int currBlockno=0 ; -extern int yylex(); -int yyparse(void); -extern int noLineno ; -char lbuff[1024]; /* local buffer */ - -/* break & continue stacks */ -STACK_DCL(continueStack ,symbol *,MAX_NEST_LEVEL) -STACK_DCL(breakStack ,symbol *,MAX_NEST_LEVEL) -STACK_DCL(forStack ,symbol *,MAX_NEST_LEVEL) -STACK_DCL(swStk ,ast *,MAX_NEST_LEVEL) -STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3) - -value *cenum = NULL ; /* current enumeration type chain*/ - - -#line 58 "SDCC.y" -typedef union { - symbol *sym ; /* symbol table pointer */ - structdef *sdef; /* structure definition */ - char yychar[SDCC_NAME_MAX+1]; - link *lnk ; /* declarator or specifier */ - int yyint; /* integer value returned */ - value *val ; /* for integer constant */ - initList *ilist; /* initial list */ - char yyinline[MAX_INLINEASM]; /* inlined assembler code */ - ast *asts; /* expression tree */ -} YYSTYPE; -#include - -#ifndef __cplusplus -#ifndef __STDC__ -#define const -#endif -#endif - - - -#define YYFINAL 392 -#define YYFLAG -32768 -#define YYNTBASE 131 - -#define YYTRANSLATE(x) ((unsigned)(x) <= 360 ? yytranslate[x] : 218) - -static const short yytranslate[] = { 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 118, 2, 2, 2, 120, 113, 2, 107, - 108, 114, 115, 112, 116, 111, 119, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 126, 128, 121, - 127, 122, 125, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 109, 2, 110, 123, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 129, 124, 130, 117, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106 -}; - -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 2, 5, 7, 9, 12, 16, 18, 21, 24, - 26, 28, 30, 32, 35, 37, 39, 41, 45, 47, - 49, 54, 58, 63, 67, 71, 74, 77, 79, 83, - 85, 88, 91, 94, 97, 102, 104, 106, 108, 110, - 112, 114, 116, 121, 123, 127, 131, 135, 137, 141, - 145, 147, 151, 155, 157, 161, 165, 169, 173, 175, - 179, 183, 185, 189, 191, 195, 197, 201, 203, 207, - 209, 213, 215, 221, 223, 227, 229, 231, 233, 235, - 237, 239, 241, 243, 245, 247, 249, 251, 255, 257, - 260, 264, 266, 269, 271, 274, 276, 280, 282, 286, - 288, 290, 292, 294, 296, 299, 301, 305, 307, 309, - 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, - 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, - 355, 358, 360, 362, 364, 365, 367, 369, 372, 376, - 378, 382, 384, 387, 391, 396, 402, 405, 407, 411, - 414, 417, 418, 420, 423, 425, 428, 430, 434, 438, - 443, 447, 448, 454, 459, 461, 464, 467, 471, 474, - 476, 478, 480, 482, 484, 486, 487, 489, 492, 494, - 498, 500, 504, 506, 510, 512, 516, 519, 521, 523, - 526, 528, 530, 533, 537, 540, 544, 548, 553, 556, - 560, 564, 569, 571, 575, 580, 582, 586, 588, 590, - 592, 594, 596, 598, 601, 605, 610, 614, 616, 618, - 621, 625, 626, 631, 632, 638, 641, 643, 646, 648, - 651, 653, 656, 659, 660, 667, 668, 675, 677, 679, - 681, 687, 695, 705, 706, 708, 712, 715, 718, 721, - 725 -}; - -static const short yyrhs[] = { 132, - 0, 131, 132, 0, 133, 0, 159, 0, 180, 136, - 0, 160, 180, 136, 0, 135, 0, 135, 134, 0, - 40, 5, 0, 39, 0, 46, 0, 164, 0, 202, - 0, 205, 202, 0, 217, 0, 5, 0, 138, 0, - 107, 157, 108, 0, 6, 0, 137, 0, 139, 109, - 157, 110, 0, 139, 107, 108, 0, 139, 107, 140, - 108, 0, 139, 111, 217, 0, 139, 8, 217, 0, - 139, 9, 0, 139, 10, 0, 155, 0, 155, 112, - 140, 0, 139, 0, 9, 141, 0, 10, 141, 0, - 142, 143, 0, 7, 141, 0, 7, 107, 193, 108, - 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, - 0, 118, 0, 141, 0, 107, 193, 108, 143, 0, - 143, 0, 144, 114, 143, 0, 144, 119, 143, 0, - 144, 120, 143, 0, 144, 0, 145, 115, 144, 0, - 145, 116, 144, 0, 145, 0, 146, 11, 145, 0, - 146, 12, 145, 0, 146, 0, 147, 121, 146, 0, - 147, 122, 146, 0, 147, 13, 146, 0, 147, 14, - 146, 0, 147, 0, 148, 15, 147, 0, 148, 16, - 147, 0, 148, 0, 149, 113, 148, 0, 149, 0, - 150, 123, 149, 0, 150, 0, 151, 124, 150, 0, - 151, 0, 152, 17, 151, 0, 152, 0, 153, 18, - 152, 0, 153, 0, 153, 125, 153, 126, 154, 0, - 154, 0, 141, 156, 155, 0, 127, 0, 19, 0, - 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, - 25, 0, 26, 0, 27, 0, 28, 0, 155, 0, - 157, 112, 155, 0, 154, 0, 160, 128, 0, 160, - 161, 128, 0, 163, 0, 163, 160, 0, 165, 0, - 165, 160, 0, 162, 0, 161, 112, 162, 0, 180, - 0, 180, 127, 196, 0, 29, 0, 30, 0, 31, - 0, 32, 0, 33, 0, 35, 5, 0, 166, 0, - 166, 37, 5, 0, 47, 0, 48, 0, 49, 0, - 50, 0, 51, 0, 52, 0, 57, 0, 55, 0, - 56, 0, 53, 0, 41, 0, 34, 0, 42, 0, - 43, 0, 44, 0, 58, 0, 168, 0, 176, 0, - 4, 0, 167, 0, 38, 0, 36, 0, 169, 170, - 129, 172, 130, 0, 169, 171, 0, 59, 0, 60, - 0, 171, 0, 0, 217, 0, 173, 0, 172, 173, - 0, 187, 174, 128, 0, 175, 0, 174, 112, 175, - 0, 180, 0, 126, 158, 0, 180, 126, 158, 0, - 61, 129, 177, 130, 0, 61, 217, 129, 177, 130, - 0, 61, 217, 0, 178, 0, 177, 112, 178, 0, - 217, 179, 0, 127, 158, 0, 0, 181, 0, 184, - 181, 0, 182, 0, 182, 134, 0, 217, 0, 107, - 180, 108, 0, 182, 109, 110, 0, 182, 109, 158, - 110, 0, 182, 107, 108, 0, 0, 182, 107, 183, - 190, 108, 0, 182, 107, 188, 108, 0, 185, 0, - 185, 187, 0, 185, 184, 0, 185, 187, 184, 0, - 186, 114, 0, 65, 0, 66, 0, 69, 0, 70, - 0, 68, 0, 67, 0, 0, 165, 0, 187, 165, - 0, 189, 0, 189, 112, 62, 0, 217, 0, 189, - 112, 217, 0, 191, 0, 191, 112, 45, 0, 192, - 0, 191, 112, 192, 0, 187, 180, 0, 193, 0, - 187, 0, 187, 194, 0, 184, 0, 195, 0, 184, - 195, 0, 107, 194, 108, 0, 109, 110, 0, 109, - 158, 110, 0, 195, 109, 110, 0, 195, 109, 158, - 110, 0, 107, 108, 0, 107, 190, 108, 0, 195, - 107, 108, 0, 195, 107, 190, 108, 0, 155, 0, - 129, 197, 130, 0, 129, 197, 112, 130, 0, 196, - 0, 197, 112, 196, 0, 199, 0, 202, 0, 207, - 0, 209, 0, 214, 0, 216, 0, 83, 128, 0, - 217, 126, 198, 0, 71, 158, 126, 198, 0, 72, - 126, 198, 0, 129, 0, 130, 0, 200, 201, 0, - 200, 206, 201, 0, 0, 200, 205, 203, 201, 0, - 0, 200, 205, 204, 206, 201, 0, 1, 128, 0, - 159, 0, 205, 159, 0, 198, 0, 206, 198, 0, - 128, 0, 157, 128, 0, 74, 198, 0, 0, 73, - 107, 157, 108, 198, 208, 0, 0, 75, 107, 157, - 108, 210, 198, 0, 76, 0, 77, 0, 78, 0, - 211, 107, 157, 108, 198, 0, 212, 198, 76, 107, - 157, 108, 128, 0, 213, 107, 215, 128, 215, 128, - 215, 108, 198, 0, 0, 157, 0, 79, 217, 128, - 0, 80, 128, 0, 81, 128, 0, 82, 128, 0, - 82, 157, 128, 0, 3, 0 -}; - -#endif - -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 120, 121, 125, 126, 134, 139, 148, 149, 153, 159, - 163, 167, 177, 178, 186, 187, 188, 189, 193, 197, - 198, 199, 201, 205, 212, 218, 220, 225, 226, 230, - 231, 232, 233, 234, 235, 239, 240, 241, 242, 243, - 244, 248, 249, 253, 254, 255, 256, 260, 261, 262, - 266, 267, 268, 272, 273, 274, 275, 284, 296, 297, - 298, 311, 312, 316, 317, 321, 322, 326, 327, 332, - 333, 338, 339, 347, 348, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 404, 405, 409, 413, - 414, 431, 432, 445, 446, 462, 463, 467, 468, 473, - 478, 483, 488, 493, 501, 505, 506, 516, 521, 527, - 532, 538, 543, 548, 553, 559, 564, 569, 574, 579, - 584, 589, 594, 603, 604, 608, 617, 621, 627, 637, - 652, 662, 663, 667, 668, 676, 687, 688, 700, 720, - 721, 729, 730, 734, 741, 746, 762, 779, 780, 787, - 799, 805, 818, 819, 827, 828, 832, 833, 834, 843, - 859, 860, 860, 873, 884, 885, 890, 895, 927, 938, - 939, 940, 941, 942, 943, 944, 948, 949, 953, 954, - 958, 959, 967, 968, 972, 973, 981, 990, 998, 999, - 1011, 1012, 1013, 1017, 1018, 1023, 1029, 1035, 1043, 1044, - 1045, 1046, 1050, 1051, 1052, 1056, 1057, 1061, 1062, 1063, - 1064, 1065, 1066, 1067, 1076, 1077, 1078, 1081, 1084, 1088, - 1089, 1090, 1092, 1093, 1096, 1097, 1101, 1112, 1136, 1137, - 1141, 1142, 1146, 1147, 1152, 1153, 1168, 1176, 1189, 1202, - 1220, 1228, 1236, 1264, 1265, 1269, 1274, 1287, 1297, 1298, - 1302 -}; -#endif - - -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","IDENTIFIER", -"TYPE_NAME","CONSTANT","STRING_LITERAL","SIZEOF","PTR_OP","INC_OP","DEC_OP", -"LEFT_OP","RIGHT_OP","LE_OP","GE_OP","EQ_OP","NE_OP","AND_OP","OR_OP","MUL_ASSIGN", -"DIV_ASSIGN","MOD_ASSIGN","ADD_ASSIGN","SUB_ASSIGN","LEFT_ASSIGN","RIGHT_ASSIGN", -"AND_ASSIGN","XOR_ASSIGN","OR_ASSIGN","TYPEDEF","EXTERN","STATIC","AUTO","REGISTER", -"CODE","INTERRUPT","SFR","AT","SBIT","REENTRANT","USING","XDATA","DATA","IDATA", -"PDATA","VAR_ARGS","CRITICAL","CHAR","SHORT","INT","LONG","SIGNED","UNSIGNED", -"FLOAT","DOUBLE","CONST","VOLATILE","VOID","BIT","STRUCT","UNION","ENUM","ELIPSIS", -"RANGE","FAR","_XDATA","_CODE","_GENERIC","_NEAR","_PDATA","_IDATA","CASE","DEFAULT", -"IF","ELSE","SWITCH","WHILE","DO","FOR","GOTO","CONTINUE","BREAK","RETURN","INLINEASM", -"IFX","ADDRESS_OF","GET_VALUE_AT_ADDRESS","SPIL","UNSPIL","GETHBIT","BITWISEAND", -"UNARYMINUS","IPUSH","IPOP","PCALL","ENDFUNCTION","JUMPTABLE","RRC","RLC","CAST", -"CALL","PARAM","NULLOP","BLOCK","LABEL","RECEIVE","SEND","'('","')'","'['","']'", -"'.'","','","'&'","'*'","'+'","'-'","'~'","'!'","'/'","'%'","'<'","'>'","'^'", -"'|'","'?'","':'","'='","';'","'{'","'}'","file","external_definition","function_definition", -"using_reentrant","using_reentrant_interrupt","function_body","primary_expr", -"string_literal","postfix_expr","argument_expr_list","unary_expr","unary_operator", -"cast_expr","multiplicative_expr","additive_expr","shift_expr","relational_expr", -"equality_expr","and_expr","exclusive_or_expr","inclusive_or_expr","logical_and_expr", -"logical_or_expr","conditional_expr","assignment_expr","assignment_operator", -"expr","constant_expr","declaration","declaration_specifiers","init_declarator_list", -"init_declarator","storage_class_specifier","Interrupt_storage","type_specifier", -"type_specifier2","sfr_reg_bit","struct_or_union_specifier","struct_or_union", -"opt_stag","stag","struct_declaration_list","struct_declaration","struct_declarator_list", -"struct_declarator","enum_specifier","enumerator_list","enumerator","opt_assign_expr", -"declarator","declarator2_using_reentrant","declarator2","@1","pointer","far_near_pointer", -"far_near","type_specifier_list","parameter_identifier_list","identifier_list", -"parameter_type_list","parameter_list","parameter_declaration","type_name","abstract_declarator", -"abstract_declarator2","initializer","initializer_list","statement","labeled_statement", -"start_block","end_block","compound_statement","@2","@3","declaration_list", -"statement_list","expression_statement","else_statement","selection_statement", -"@4","while","do","for","iteration_statement","expr_opt","jump_statement","identifier", NULL -}; -#endif - -static const short yyr1[] = { 0, - 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, - 135, 135, 136, 136, 137, 137, 137, 137, 138, 139, - 139, 139, 139, 139, 139, 139, 139, 140, 140, 141, - 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, - 142, 143, 143, 144, 144, 144, 144, 145, 145, 145, - 146, 146, 146, 147, 147, 147, 147, 147, 148, 148, - 148, 149, 149, 150, 150, 151, 151, 152, 152, 153, - 153, 154, 154, 155, 155, 156, 156, 156, 156, 156, - 156, 156, 156, 156, 156, 156, 157, 157, 158, 159, - 159, 160, 160, 160, 160, 161, 161, 162, 162, 163, - 163, 163, 163, 163, 164, 165, 165, 166, 166, 166, - 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, - 166, 166, 166, 166, 166, 166, 166, 167, 167, 168, - 168, 169, 169, 170, 170, 171, 172, 172, 173, 174, - 174, 175, 175, 175, 176, 176, 176, 177, 177, 178, - 179, 179, 180, 180, 181, 181, 182, 182, 182, 182, - 182, 183, 182, 182, 184, 184, 184, 184, 185, 186, - 186, 186, 186, 186, 186, 186, 187, 187, 188, 188, - 189, 189, 190, 190, 191, 191, 192, 192, 193, 193, - 194, 194, 194, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 196, 196, 196, 197, 197, 198, 198, 198, - 198, 198, 198, 198, 199, 199, 199, 200, 201, 202, - 202, 203, 202, 204, 202, 202, 205, 205, 206, 206, - 207, 207, 208, 208, 209, 210, 209, 211, 212, 213, - 214, 214, 214, 215, 215, 216, 216, 216, 216, 216, - 217 -}; - -static const short yyr2[] = { 0, - 1, 2, 1, 1, 2, 3, 1, 2, 2, 1, - 1, 1, 1, 2, 1, 1, 1, 3, 1, 1, - 4, 3, 4, 3, 3, 2, 2, 1, 3, 1, - 2, 2, 2, 2, 4, 1, 1, 1, 1, 1, - 1, 1, 4, 1, 3, 3, 3, 1, 3, 3, - 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, - 3, 1, 2, 1, 2, 1, 3, 1, 3, 1, - 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, - 2, 1, 1, 1, 0, 1, 1, 2, 3, 1, - 3, 1, 2, 3, 4, 5, 2, 1, 3, 2, - 2, 0, 1, 2, 1, 2, 1, 3, 3, 4, - 3, 0, 5, 4, 1, 2, 2, 3, 2, 1, - 1, 1, 1, 1, 1, 0, 1, 2, 1, 3, - 1, 3, 1, 3, 1, 3, 2, 1, 1, 2, - 1, 1, 2, 3, 2, 3, 3, 4, 2, 3, - 3, 4, 1, 3, 4, 1, 3, 1, 1, 1, - 1, 1, 1, 2, 3, 4, 3, 1, 1, 2, - 3, 0, 4, 0, 5, 2, 1, 2, 1, 2, - 1, 2, 2, 0, 6, 0, 6, 1, 1, 1, - 5, 7, 9, 0, 1, 3, 2, 2, 2, 3, - 1 -}; - -static const short yydefact[] = { 176, - 251, 126, 100, 101, 102, 103, 104, 119, 129, 128, - 118, 120, 121, 122, 108, 109, 110, 111, 112, 113, - 117, 115, 116, 114, 123, 132, 133, 0, 170, 171, - 175, 174, 172, 173, 176, 176, 1, 3, 4, 176, - 92, 94, 106, 127, 124, 135, 125, 0, 153, 155, - 0, 165, 0, 157, 0, 147, 0, 2, 90, 0, - 96, 0, 93, 95, 0, 0, 131, 136, 0, 218, - 5, 227, 176, 0, 13, 0, 0, 10, 0, 11, - 162, 0, 156, 7, 12, 154, 177, 167, 166, 169, - 0, 148, 152, 0, 158, 176, 91, 0, 6, 107, - 0, 226, 98, 16, 19, 0, 0, 0, 0, 0, - 0, 0, 238, 239, 240, 0, 0, 0, 0, 0, - 0, 36, 37, 38, 39, 40, 41, 231, 219, 20, - 17, 30, 42, 0, 44, 48, 51, 54, 59, 62, - 64, 66, 68, 70, 72, 74, 87, 0, 229, 208, - 220, 209, 224, 0, 210, 211, 0, 0, 0, 212, - 213, 15, 228, 14, 105, 9, 161, 0, 0, 179, - 181, 159, 42, 89, 0, 15, 8, 178, 168, 0, - 145, 0, 150, 0, 97, 0, 203, 99, 0, 137, - 176, 0, 34, 0, 31, 32, 0, 0, 0, 0, - 0, 247, 248, 249, 0, 214, 0, 176, 0, 0, - 26, 27, 0, 0, 0, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 76, 0, 33, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, - 0, 230, 221, 0, 0, 244, 0, 189, 0, 183, - 185, 188, 164, 0, 160, 149, 151, 146, 206, 0, - 130, 138, 0, 0, 140, 142, 0, 0, 217, 0, - 0, 246, 250, 18, 176, 0, 191, 190, 192, 0, - 25, 22, 0, 28, 0, 24, 75, 45, 46, 47, - 49, 50, 52, 53, 57, 58, 55, 56, 60, 61, - 63, 65, 67, 69, 71, 0, 88, 223, 0, 0, - 0, 245, 0, 215, 176, 187, 191, 163, 0, 180, - 182, 0, 204, 143, 176, 139, 0, 35, 216, 0, - 236, 199, 0, 0, 195, 0, 193, 0, 0, 43, - 23, 0, 21, 0, 225, 0, 0, 244, 184, 186, - 205, 207, 141, 144, 234, 0, 200, 194, 196, 201, - 0, 197, 0, 29, 73, 241, 0, 0, 0, 235, - 237, 202, 198, 0, 244, 233, 242, 0, 0, 243, - 0, 0 -}; - -static const short yydefgoto[] = { 36, - 37, 38, 83, 84, 71, 130, 131, 132, 293, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 227, 148, 175, 72, 73, 60, - 61, 41, 85, 87, 43, 44, 45, 46, 66, 67, - 189, 190, 274, 275, 47, 91, 92, 183, 48, 49, - 50, 168, 51, 52, 53, 258, 169, 170, 343, 260, - 261, 262, 288, 289, 188, 270, 149, 150, 74, 151, - 152, 250, 251, 76, 154, 155, 380, 156, 366, 157, - 158, 159, 160, 323, 161, 176 -}; - -static const short yypact[] = { 1568, --32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768,-32768, 11,-32768,-32768, --32768,-32768,-32768,-32768, 317, 1267,-32768,-32768,-32768, 53, - 1610, 1610, -7,-32768,-32768, 19,-32768, 634,-32768, 165, - 30, 1193, -26,-32768, 19, 21, 45,-32768,-32768, -33, --32768, 598,-32768,-32768, 173, 55, 58,-32768, 62,-32768, --32768,-32768, 53, 412,-32768, 634, 189,-32768, 191,-32768, - 24, 906,-32768, 126,-32768,-32768,-32768,-32768, 1193,-32768, - -93,-32768, 70, 19,-32768, 317,-32768, 430,-32768,-32768, - 1452,-32768, 72,-32768,-32768, 987, 1022, 1022, 1034, 76, - 100, 102,-32768,-32768,-32768, 19, 84, 92, 776, 93, - 892,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768, 40, 348, 1034,-32768, -44, -15, 46, 12, 129, - 110, 105, 101, 212, 16,-32768,-32768, -25,-32768,-32768, --32768,-32768, 699, 496,-32768,-32768, 123, 695, 125,-32768, --32768, 108,-32768,-32768,-32768,-32768,-32768, 1452, 136, 134, --32768,-32768,-32768,-32768, 137,-32768,-32768,-32768,-32768, 19, --32768, 1034,-32768, -69,-32768, 430,-32768,-32768, 784,-32768, - 812, 892,-32768, 1034,-32768,-32768, 122, 695, 1034, 1034, - 124,-32768,-32768,-32768, 27,-32768, 2, 1411, 145, 19, --32768,-32768, 951, 1034, 19,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768, 1034,-32768, 1034, 1034, - 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, - 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034,-32768, 130, - 695,-32768,-32768, 1034, 178, 1034, 695, 1119, 147, 149, --32768,-32768,-32768, 18,-32768,-32768,-32768,-32768,-32768, -58, --32768,-32768, 1034, 31,-32768, 139, 154, 695,-32768, 63, - 65,-32768,-32768,-32768, 1487, 963, -62,-32768, 4, 1034, --32768,-32768, 158, 163, 52,-32768,-32768,-32768,-32768,-32768, - -44, -44, -15, -15, 46, 46, 46, 46, 12, 12, - 129, 110, 105, 101, 212, -2,-32768,-32768, 496, 71, - 166, 170, 155,-32768, 1335,-32768, 29,-32768, 1376,-32768, --32768, 232,-32768,-32768, 60,-32768, 1034,-32768,-32768, 695, --32768,-32768, 177, 179,-32768, 176, 4, 1160, 975,-32768, --32768, 1034,-32768, 1034,-32768, 695, 1034, 1034,-32768,-32768, --32768,-32768,-32768,-32768, 214, 695,-32768,-32768,-32768,-32768, - 181,-32768, 180,-32768,-32768,-32768, 77, 164, 695,-32768, --32768,-32768,-32768, 168, 1034,-32768,-32768, 185, 695,-32768, - 294,-32768 -}; - -static const short yypgoto[] = {-32768, - 261,-32768, 215,-32768, 236,-32768,-32768,-32768, -50, 161, --32768, -122, -165, -42, -20, -14, 61, 64, 67, 59, - 66, 68, -78, -96,-32768, -108, -104, 17, 41,-32768, - 209,-32768,-32768, 23,-32768,-32768,-32768,-32768,-32768,-32768, --32768, 117,-32768, -27,-32768, 219, 138,-32768, -34, -48, --32768,-32768, -45,-32768,-32768, 14,-32768,-32768, -160,-32768, - -13, -103, -265, -258, -176,-32768, -56,-32768,-32768, -145, - -24,-32768,-32768, 235, 73,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768, -343,-32768, 0 -}; - - -#define YYLAST 1675 - - -static const short yytable[] = { 54, - 57, 187, 86, 174, 197, 62, 88, 259, 253, 269, - 205, 228, 207, 1, 378, 246, 39, 209, 180, 344, - 1, 1, 42, 75, 236, 237, 1, 56, 347, 65, - 174, 1, 1, 246, 54, 54, 181, 75, 103, 54, - 40, 388, 180, 179, 285, 68, 286, 210, 211, 212, - 54, 164, 39, 332, 93, 1, 234, 235, 42, 344, - 268, 103, 1, 42, 42, 89, 301, 302, 347, 229, - 42, 333, 54, 162, 230, 231, 40, 267, 96, 330, - 171, 63, 64, 207, 42, 207, 248, 90, 277, 187, - 280, 281, 163, 93, 97, 54, 42, 252, 42, 232, - 233, 255, 249, 174, 318, 295, 298, 299, 300, 284, - 348, 178, 349, 248, 191, 201, 294, 29, 30, 31, - 32, 33, 34, 354, 29, 30, 31, 32, 33, 34, - 297, 167, 238, 239, 208, 325, 35, 286, 248, 55, - 247, 279, 335, 240, 241, 320, 213, 322, 214, 94, - 215, 317, 95, 162, 283, 362, 276, 162, 336, 35, - 77, 353, 287, 248, 78, 79, 35, 350, 334, 163, - 340, 80, 341, 355, 248, 42, 248, 100, 356, 93, - 59, 346, 248, 101, 384, 273, -134, 371, 248, 102, - 54, 303, 304, 165, 174, 166, 182, 162, 98, 77, - 324, 198, 191, 78, 79, 208, 199, 174, 200, 291, - 80, 202, 327, 178, 296, 305, 306, 307, 308, 203, - 206, 339, 242, 326, 244, 309, 310, 243, 245, 254, - 178, 256, 364, 257, 1, 187, 104, 105, 106, 287, - 107, 108, 173, 263, 373, 264, 265, 278, 377, 322, - 162, 282, 290, 321, 328, 294, 162, 54, 174, 129, - 329, 338, 252, 331, 337, 351, 193, 195, 196, 173, - 174, 81, 357, 82, 352, 375, 322, 162, 86, 327, - 178, 248, 358, 365, 367, 369, 368, 379, 382, 383, - 57, 385, 389, 392, 173, 387, 58, 99, 177, 376, - 276, 374, 311, 314, 185, 272, 312, 363, 153, 381, - 313, 315, 184, 0, 316, 360, 0, 266, 162, 1, - 0, 0, 386, 319, 54, 0, 54, 0, 0, 0, - 0, 0, 390, 0, 54, 0, 0, 0, 121, 162, - 0, 0, 173, 0, 122, 123, 124, 125, 126, 127, - 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, - 186, 361, 0, 0, 0, 162, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 0, 0, 162, 0, - 0, 29, 30, 31, 32, 33, 34, 0, 162, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 173, 173, 173, 0, 0, - 0, 0, 69, 0, 1, 2, 104, 105, 106, 0, - 107, 108, 0, 35, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 173, 104, 105, 106, 0, 107, 108, - 3, 4, 5, 6, 7, 8, 173, 9, 0, 10, - 173, 0, 11, 12, 13, 14, 0, 0, 15, 16, - 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, - 26, 27, 28, 0, 226, 0, 0, 0, 0, 0, - 0, 0, 109, 110, 111, 0, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 0, 69, 173, 1, 0, - 104, 105, 106, 0, 107, 108, 0, 0, 0, 173, - 0, 0, 0, 0, 173, 0, 0, 0, 121, 0, - 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 121, 0, 0, 128, - 70, 129, 122, 123, 124, 125, 126, 127, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 186, 0, - 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, - 0, 2, 121, 0, 0, 0, 0, 0, 122, 123, - 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 128, 70, 129, 3, 4, 5, 6, - 7, 8, 0, 9, 69, 10, 0, 2, 11, 12, - 13, 14, 0, 0, 15, 16, 17, 18, 19, 20, - 21, 0, 22, 23, 24, 25, 26, 27, 28, 0, - 0, 0, 3, 4, 5, 6, 7, 8, 0, 9, - 0, 10, 0, 0, 11, 12, 13, 14, 0, 0, - 15, 16, 17, 18, 19, 20, 21, 0, 22, 23, - 24, 25, 26, 27, 28, 69, 0, 1, 0, 104, - 105, 106, 2, 107, 108, 0, 0, 0, 0, -98, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 98, -98, 70, 3, 4, 5, - 6, 7, 8, 0, 9, 0, 10, 0, 0, 11, - 12, 13, 14, 0, 0, 15, 16, 17, 18, 19, - 20, 21, 0, 22, 23, 24, 25, 26, 27, 28, - 0, 0, 70, 0, 0, 109, 110, 111, 0, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 1, 0, - 104, 105, 106, 0, 107, 108, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 121, 0, 0, 0, 0, 0, 122, 123, 124, - 125, 126, 127, 0, 1, 2, 0, 8, 0, 9, - 0, 10, 128, 70, 11, 12, 13, 14, -222, 0, - 15, 16, 17, 18, 19, 20, 21, 0, 22, 23, - 24, 25, 26, 27, 28, 8, 0, 9, 0, 10, - 0, 0, 11, 12, 13, 14, 0, 0, 15, 16, - 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, - 26, 27, 28, 0, 0, 0, 29, 30, 31, 32, - 33, 34, 121, 0, 0, 0, 0, 0, 122, 123, - 124, 125, 126, 127, 1, 2, 104, 105, 106, 0, - 107, 108, 0, 204, 0, 0, 0, 0, 1, 0, - 104, 105, 106, 271, 107, 108, 0, 0, 35, 0, - 0, 0, 0, 0, 0, 8, 0, 9, 0, 10, - 0, 0, 11, 12, 13, 14, 0, 273, 15, 16, - 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, - 26, 27, 28, 1, 0, 104, 105, 106, 0, 107, - 108, 0, 0, 0, 0, 1, 0, 104, 105, 106, - 0, 107, 108, 0, 0, 0, 0, 1, 0, 104, - 105, 106, 0, 107, 108, 0, 0, 0, 0, 1, - 0, 104, 105, 106, 0, 107, 108, 0, 121, 0, - 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, - 0, 0, 121, 0, 0, 172, 0, 0, 122, 123, - 124, 125, 126, 127, 1, 0, 104, 105, 106, 0, - 107, 108, 0, 0, 0, 0, 1, 0, 104, 105, - 106, 0, 107, 108, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 121, 292, 0, - 0, 0, 0, 122, 123, 124, 125, 126, 127, 121, - 0, 0, 345, 0, 0, 122, 123, 124, 125, 126, - 127, 121, 0, 0, 372, 0, 0, 122, 123, 124, - 125, 126, 127, 192, 0, 0, 0, 0, 0, 122, - 123, 124, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 0, 0, 0, 0, 0, 194, 0, - 0, 0, 0, 0, 122, 123, 124, 125, 126, 127, - 121, 0, 0, 0, 0, 0, 122, 123, 124, 125, - 126, 127, 8, 0, 9, 0, 10, 0, 0, 11, - 12, 13, 14, 2, 0, 15, 16, 17, 18, 19, - 20, 21, 0, 22, 23, 24, 25, 26, 27, 28, - 0, 0, 0, 29, 30, 31, 32, 33, 34, 0, - 0, 0, 0, 8, 0, 9, 2, 10, 0, 0, - 11, 12, 13, 14, 0, 0, 15, 16, 17, 18, - 19, 20, 21, 0, 22, 23, 24, 25, 26, 27, - 28, 0, 0, 0, 0, 325, 8, 286, 9, 0, - 10, 0, -176, 11, 12, 13, 14, 0, 0, 15, - 16, 17, 18, 19, 20, 21, 0, 22, 23, 24, - 25, 26, 27, 28, 0, 0, 0, 29, 30, 31, - 32, 33, 34, 0, 0, 0, 391, 370, 0, 1, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, - 8, 0, 9, 0, 10, 0, -176, 11, 12, 13, - 14, 0, 0, 15, 16, 17, 18, 19, 20, 21, - 0, 22, 23, 24, 25, 26, 27, 28, 0, 0, - 0, 29, 30, 31, 32, 33, 34, 1, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, - 9, 0, 10, 35, 0, 11, 12, 13, 14, 2, - 0, 15, 16, 17, 18, 19, 20, 21, 0, 22, - 23, 24, 25, 26, 27, 28, 0, 0, 0, 29, - 30, 31, 32, 33, 34, 0, 0, 0, 0, 8, - 0, 9, 0, 10, 2, 0, 11, 12, 13, 14, - 359, 0, 15, 16, 17, 18, 19, 20, 21, 0, - 22, 23, 24, 25, 26, 27, 28, 0, 0, 0, - 0, 325, 342, 286, 8, 0, 9, 0, 10, 0, - 0, 11, 12, 13, 14, 2, 0, 15, 16, 17, - 18, 19, 20, 21, 0, 22, 23, 24, 25, 26, - 27, 28, 0, 0, 0, 29, 30, 31, 32, 33, - 34, 0, 0, 0, 0, 8, 0, 9, 0, 10, - 2, 0, 11, 12, 13, 14, 0, 0, 15, 16, - 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, - 26, 27, 28, 0, 0, 0, 0, 285, -189, 286, - 8, 0, 9, 0, 10, 0, 0, 11, 12, 13, - 14, 0, 0, 15, 16, 17, 18, 19, 20, 21, - 0, 22, 23, 24, 25, 26, 27, 28, 0, 0, - 0, 29, 30, 31, 32, 33, 34, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 285, 342, 286, 3, 4, 5, 6, - 7, 8, 0, 9, 0, 10, 0, 0, 11, 12, - 13, 14, 0, 2, 15, 16, 17, 18, 19, 20, - 21, 0, 22, 23, 24, 25, 26, 27, 28, 0, - 0, 0, 29, 30, 31, 32, 33, 34, 3, 4, - 5, 6, 7, 8, 0, 9, 0, 10, 0, 0, - 11, 12, 13, 14, 0, 0, 15, 16, 17, 18, - 19, 20, 21, 0, 22, 23, 24, 25, 26, 27, - 28, 0, 0, 0, 35 -}; - -static const short yycheck[] = { 0, - 35, 98, 51, 82, 109, 40, 52, 168, 154, 186, - 119, 134, 121, 3, 358, 18, 0, 121, 112, 285, - 3, 3, 0, 48, 13, 14, 3, 28, 287, 37, - 109, 3, 3, 18, 35, 36, 130, 62, 73, 40, - 0, 385, 112, 89, 107, 46, 109, 8, 9, 10, - 51, 76, 36, 112, 55, 3, 11, 12, 36, 325, - 130, 96, 3, 41, 42, 52, 232, 233, 327, 114, - 48, 130, 73, 74, 119, 120, 36, 182, 112, 62, - 81, 41, 42, 192, 62, 194, 112, 114, 192, 186, - 199, 200, 76, 94, 128, 96, 74, 154, 76, 115, - 116, 158, 128, 182, 250, 214, 229, 230, 231, 108, - 107, 89, 109, 112, 101, 116, 213, 65, 66, 67, - 68, 69, 70, 126, 65, 66, 67, 68, 69, 70, - 227, 108, 121, 122, 121, 107, 107, 109, 112, 129, - 125, 198, 112, 15, 16, 254, 107, 256, 109, 129, - 111, 248, 108, 154, 128, 332, 191, 158, 128, 107, - 35, 110, 208, 112, 39, 40, 107, 290, 273, 153, - 108, 46, 108, 319, 112, 153, 112, 5, 108, 180, - 128, 286, 112, 129, 108, 126, 129, 348, 112, 128, - 191, 234, 235, 5, 273, 5, 127, 198, 127, 35, - 257, 126, 189, 39, 40, 192, 107, 286, 107, 210, - 46, 128, 258, 191, 215, 236, 237, 238, 239, 128, - 128, 278, 113, 258, 124, 240, 241, 123, 17, 107, - 208, 107, 337, 126, 3, 332, 5, 6, 7, 285, - 9, 10, 82, 108, 349, 112, 110, 126, 357, 358, - 251, 128, 108, 76, 108, 352, 257, 258, 337, 130, - 112, 108, 319, 264, 126, 108, 106, 107, 108, 109, - 349, 107, 107, 109, 112, 354, 385, 278, 327, 325, - 258, 112, 128, 340, 108, 110, 108, 74, 108, 110, - 325, 128, 108, 0, 134, 128, 36, 62, 84, 356, - 335, 352, 242, 245, 96, 189, 243, 335, 74, 366, - 244, 246, 94, -1, 247, 329, -1, 180, 319, 3, - -1, -1, 379, 251, 325, -1, 327, -1, -1, -1, - -1, -1, 389, -1, 335, -1, -1, -1, 107, 340, - -1, -1, 182, -1, 113, 114, 115, 116, 117, 118, - -1, -1, -1, -1, -1, 356, -1, -1, -1, -1, - 129, 130, -1, -1, -1, 366, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, -1, -1, 379, -1, - -1, 65, 66, 67, 68, 69, 70, -1, 389, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, -1, -1, - -1, -1, 1, -1, 3, 4, 5, 6, 7, -1, - 9, 10, -1, 107, -1, -1, -1, -1, -1, -1, - -1, -1, 3, 273, 5, 6, 7, -1, 9, 10, - 29, 30, 31, 32, 33, 34, 286, 36, -1, 38, - 290, -1, 41, 42, 43, 44, -1, -1, 47, 48, - 49, 50, 51, 52, 53, -1, 55, 56, 57, 58, - 59, 60, 61, -1, 127, -1, -1, -1, -1, -1, - -1, -1, 71, 72, 73, -1, 75, 76, 77, 78, - 79, 80, 81, 82, 83, -1, 1, 337, 3, -1, - 5, 6, 7, -1, 9, 10, -1, -1, -1, 349, - -1, -1, -1, -1, 354, -1, -1, -1, 107, -1, - -1, -1, -1, -1, 113, 114, 115, 116, 117, 118, - -1, -1, -1, -1, -1, -1, 107, -1, -1, 128, - 129, 130, 113, 114, 115, 116, 117, 118, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, - -1, -1, -1, -1, -1, -1, 71, 72, 73, -1, - 75, 76, 77, 78, 79, 80, 81, 82, 83, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, - -1, 4, 107, -1, -1, -1, -1, -1, 113, 114, - 115, 116, 117, 118, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 128, 129, 130, 29, 30, 31, 32, - 33, 34, -1, 36, 1, 38, -1, 4, 41, 42, - 43, 44, -1, -1, 47, 48, 49, 50, 51, 52, - 53, -1, 55, 56, 57, 58, 59, 60, 61, -1, - -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, - -1, 38, -1, -1, 41, 42, 43, 44, -1, -1, - 47, 48, 49, 50, 51, 52, 53, -1, 55, 56, - 57, 58, 59, 60, 61, 1, -1, 3, -1, 5, - 6, 7, 4, 9, 10, -1, -1, -1, -1, 112, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 127, 128, 129, 29, 30, 31, - 32, 33, 34, -1, 36, -1, 38, -1, -1, 41, - 42, 43, 44, -1, -1, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - -1, -1, 129, -1, -1, 71, 72, 73, -1, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 3, -1, - 5, 6, 7, -1, 9, 10, -1, 4, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 107, -1, -1, -1, -1, -1, 113, 114, 115, - 116, 117, 118, -1, 3, 4, -1, 34, -1, 36, - -1, 38, 128, 129, 41, 42, 43, 44, 130, -1, - 47, 48, 49, 50, 51, 52, 53, -1, 55, 56, - 57, 58, 59, 60, 61, 34, -1, 36, -1, 38, - -1, -1, 41, 42, 43, 44, -1, -1, 47, 48, - 49, 50, 51, 52, 53, -1, 55, 56, 57, 58, - 59, 60, 61, -1, -1, -1, 65, 66, 67, 68, - 69, 70, 107, -1, -1, -1, -1, -1, 113, 114, - 115, 116, 117, 118, 3, 4, 5, 6, 7, -1, - 9, 10, -1, 128, -1, -1, -1, -1, 3, -1, - 5, 6, 7, 130, 9, 10, -1, -1, 107, -1, - -1, -1, -1, -1, -1, 34, -1, 36, -1, 38, - -1, -1, 41, 42, 43, 44, -1, 126, 47, 48, - 49, 50, 51, 52, 53, -1, 55, 56, 57, 58, - 59, 60, 61, 3, -1, 5, 6, 7, -1, 9, - 10, -1, -1, -1, -1, 3, -1, 5, 6, 7, - -1, 9, 10, -1, -1, -1, -1, 3, -1, 5, - 6, 7, -1, 9, 10, -1, -1, -1, -1, 3, - -1, 5, 6, 7, -1, 9, 10, -1, 107, -1, - -1, -1, -1, -1, 113, 114, 115, 116, 117, 118, - -1, -1, 107, -1, -1, 110, -1, -1, 113, 114, - 115, 116, 117, 118, 3, -1, 5, 6, 7, -1, - 9, 10, -1, -1, -1, -1, 3, -1, 5, 6, - 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 107, 108, -1, - -1, -1, -1, 113, 114, 115, 116, 117, 118, 107, - -1, -1, 110, -1, -1, 113, 114, 115, 116, 117, - 118, 107, -1, -1, 110, -1, -1, 113, 114, 115, - 116, 117, 118, 107, -1, -1, -1, -1, -1, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, -1, -1, -1, -1, -1, 107, -1, - -1, -1, -1, -1, 113, 114, 115, 116, 117, 118, - 107, -1, -1, -1, -1, -1, 113, 114, 115, 116, - 117, 118, 34, -1, 36, -1, 38, -1, -1, 41, - 42, 43, 44, 4, -1, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, - -1, -1, -1, 34, -1, 36, 4, 38, -1, -1, - 41, 42, 43, 44, -1, -1, 47, 48, 49, 50, - 51, 52, 53, -1, 55, 56, 57, 58, 59, 60, - 61, -1, -1, -1, -1, 107, 34, 109, 36, -1, - 38, -1, 114, 41, 42, 43, 44, -1, -1, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, -1, -1, -1, 0, 108, -1, 3, - 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, - 34, -1, 36, -1, 38, -1, 114, 41, 42, 43, - 44, -1, -1, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, -1, -1, - -1, 65, 66, 67, 68, 69, 70, 3, 4, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, - 36, -1, 38, 107, -1, 41, 42, 43, 44, 4, - -1, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, -1, -1, -1, 65, - 66, 67, 68, 69, 70, -1, -1, -1, -1, 34, - -1, 36, -1, 38, 4, -1, 41, 42, 43, 44, - 45, -1, 47, 48, 49, 50, 51, 52, 53, -1, - 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, - -1, 107, 108, 109, 34, -1, 36, -1, 38, -1, - -1, 41, 42, 43, 44, 4, -1, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, -1, -1, -1, 65, 66, 67, 68, 69, - 70, -1, -1, -1, -1, 34, -1, 36, -1, 38, - 4, -1, 41, 42, 43, 44, -1, -1, 47, 48, - 49, 50, 51, 52, 53, -1, 55, 56, 57, 58, - 59, 60, 61, -1, -1, -1, -1, 107, 108, 109, - 34, -1, 36, -1, 38, -1, -1, 41, 42, 43, - 44, -1, -1, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, -1, -1, - -1, 65, 66, 67, 68, 69, 70, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 107, 108, 109, 29, 30, 31, 32, - 33, 34, -1, 36, -1, 38, -1, -1, 41, 42, - 43, 44, -1, 4, 47, 48, 49, 50, 51, 52, - 53, -1, 55, 56, 57, 58, 59, 60, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, 29, 30, - 31, 32, 33, 34, -1, 36, -1, 38, -1, -1, - 41, 42, 43, 44, -1, -1, 47, 48, 49, 50, - 51, 52, 53, -1, 55, 56, 57, 58, 59, 60, - 61, -1, -1, -1, 107 -}; -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/misc/bison.simple" -/* This file comes from bison-1.28. */ - -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc -#endif - -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 -#define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. - This remains here temporarily to ease the - transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ -#define YYFAIL goto yyerrlab -#define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(token, value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { yychar = (token), yylval = (value); \ - yychar1 = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ -while (0) - -#define YYTERROR 1 -#define YYERRCODE 256 - -#ifndef YYPURE -#define YYLEX yylex() -#endif - -#ifdef YYPURE -#ifdef YYLSP_NEEDED -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval, &yylloc) -#endif -#else /* not YYLSP_NEEDED */ -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval) -#endif -#endif /* not YYLSP_NEEDED */ -#endif - -/* If nonreentrant, generate the variables here */ - -#ifndef YYPURE - -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ - -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ -#endif - -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ - -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ -#endif - -/* YYINITDEPTH indicates the initial size of the parser's stacks */ - -#ifndef YYINITDEPTH -#define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ - -#if YYMAXDEPTH == 0 -#undef YYMAXDEPTH -#endif - -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 -#endif - -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ - -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; -{ - register char *f = from; - register char *t = to; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#else /* __cplusplus */ - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (char *to, char *from, unsigned int count) -{ - register char *t = to; - register char *f = from; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#endif -#endif - -#line 217 "/usr/share/misc/bison.simple" - -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ - -#ifdef YYPARSE_PARAM -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -#ifdef YYPARSE_PARAM -int yyparse (void *); -#else -int yyparse (void); -#endif -#endif - -int -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - register int yystate; - register int yyn; - register short *yyssp; - register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ - - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ - -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else -#define YYPOPSTACK (yyvsp--, yyssp--) -#endif - - int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; - -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif - - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ - - int yylen; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss - 1; - yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif - -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: - - *++yyssp = yystate; - - if (yyssp >= yyss + yystacksize - 1) - { - /* Give user a chance to reallocate the stack */ - /* Use copies of these so that the &'s don't force the real ones into memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif - - /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; - -#ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif - - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif -#else /* no yyoverflow */ - /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 2; - } - yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) - yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif -#endif /* no yyoverflow */ - - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - - if (yyssp >= yyss + yystacksize - 1) - YYABORT; - } - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif - - goto yybackup; - yybackup: - -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ - - /* First try to decide what to do without reference to lookahead token. */ - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - - if (yychar == YYEMPTY) - { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif - yychar = YYLEX; - } - - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ - { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif - } - else - { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise meaning - of a token, for further debugging info. */ -#ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -#endif - fprintf (stderr, ")\n"); - } -#endif - } - - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) - goto yydefault; - - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrlab; - - if (yyn == YYFINAL) - YYACCEPT; - - /* Shift the lookahead token. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; - - yystate = yyn; - goto yynewstate; - -/* Do the default action for the current state. */ -yydefault: - - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - -/* Do a reduction. yyn is the number of a rule to reduce with. */ -yyreduce: - yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ - -#if YYDEBUG != 0 - if (yydebug) - { - int i; - - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif - - - switch (yyn) { - -case 3: -#line 125 "SDCC.y" -{ blockNo=0;; - break;} -case 4: -#line 126 "SDCC.y" -{ - addSymChain (yyvsp[0].sym); - allocVariables (yyvsp[0].sym) ; - cleanUpLevel (SymbolTab,1); - ; - break;} -case 5: -#line 134 "SDCC.y" -{ /* function type not specified */ - /* assume it to be 'int' */ - addDecl(yyvsp[-1].sym,0,newIntLink()); - yyval.asts = createFunction(yyvsp[-1].sym,yyvsp[0].asts); - ; - break;} -case 6: -#line 140 "SDCC.y" -{ - pointerTypes(yyvsp[-1].sym->type,copyLinkChain(yyvsp[-2].lnk)); - addDecl(yyvsp[-1].sym,0,yyvsp[-2].lnk); - yyval.asts = createFunction(yyvsp[-1].sym,yyvsp[0].asts); - ; - break;} -case 8: -#line 149 "SDCC.y" -{ yyval.lnk = mergeSpec(yyvsp[-1].lnk,yyvsp[0].lnk); ; - break;} -case 9: -#line 153 "SDCC.y" -{ - yyval.lnk = newLink() ; - yyval.lnk->class = SPECIFIER ; - SPEC_BNKF(yyval.lnk) = 1; - SPEC_BANK(yyval.lnk) = (int) floatFromVal(yyvsp[0].val); - ; - break;} -case 10: -#line 159 "SDCC.y" -{ yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_RENT(yyval.lnk) = 1; - ; - break;} -case 11: -#line 163 "SDCC.y" -{ yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_CRTCL(yyval.lnk) = 1; - ; - break;} -case 12: -#line 168 "SDCC.y" -{ - yyval.lnk = newLink () ; - yyval.lnk->class = SPECIFIER ; - SPEC_INTN(yyval.lnk) = yyvsp[0].yyint ; - SPEC_INTRTN(yyval.lnk) = 1; - ; - break;} -case 14: -#line 179 "SDCC.y" -{ - werror(E_OLD_STYLE,(yyvsp[-1].sym ? yyvsp[-1].sym->name: "")) ; - exit(1); - ; - break;} -case 15: -#line 186 "SDCC.y" -{ yyval.asts = newAst(EX_VALUE,symbolVal(yyvsp[0].sym)); ; - break;} -case 16: -#line 187 "SDCC.y" -{ yyval.asts = newAst(EX_VALUE,yyvsp[0].val); ; - break;} -case 18: -#line 189 "SDCC.y" -{ yyval.asts = yyvsp[-1].asts ; ; - break;} -case 19: -#line 193 "SDCC.y" -{ yyval.asts = newAst(EX_VALUE,yyvsp[0].val); ; - break;} -case 21: -#line 198 "SDCC.y" -{ yyval.asts = newNode ('[', yyvsp[-3].asts, yyvsp[-1].asts) ; ; - break;} -case 22: -#line 199 "SDCC.y" -{ yyval.asts = newNode (CALL,yyvsp[-2].asts,NULL); - yyval.asts->left->funcName = 1;; - break;} -case 23: -#line 202 "SDCC.y" -{ - yyval.asts = newNode (CALL,yyvsp[-3].asts,yyvsp[-1].asts) ; yyval.asts->left->funcName = 1; - ; - break;} -case 24: -#line 206 "SDCC.y" -{ - yyvsp[0].sym = newSymbol(yyvsp[0].sym->name,NestLevel); - yyvsp[0].sym->implicit = 1; - yyval.asts = newNode(PTR_OP,newNode('&',yyvsp[-2].asts,NULL),newAst(EX_VALUE,symbolVal(yyvsp[0].sym))); -/* $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ; */ - ; - break;} -case 25: -#line 213 "SDCC.y" -{ - yyvsp[0].sym = newSymbol(yyvsp[0].sym->name,NestLevel); - yyvsp[0].sym->implicit = 1; - yyval.asts = newNode(PTR_OP,yyvsp[-2].asts,newAst(EX_VALUE,symbolVal(yyvsp[0].sym))); - ; - break;} -case 26: -#line 219 "SDCC.y" -{ yyval.asts = newNode(INC_OP,yyvsp[-1].asts,NULL);; - break;} -case 27: -#line 221 "SDCC.y" -{ yyval.asts = newNode(DEC_OP,yyvsp[-1].asts,NULL); ; - break;} -case 29: -#line 226 "SDCC.y" -{ yyval.asts = newNode(PARAM,yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 31: -#line 231 "SDCC.y" -{ yyval.asts = newNode(INC_OP,NULL,yyvsp[0].asts); ; - break;} -case 32: -#line 232 "SDCC.y" -{ yyval.asts = newNode(DEC_OP,NULL,yyvsp[0].asts); ; - break;} -case 33: -#line 233 "SDCC.y" -{ yyval.asts = newNode(yyvsp[-1].yyint,yyvsp[0].asts,NULL) ; ; - break;} -case 34: -#line 234 "SDCC.y" -{ yyval.asts = newNode(SIZEOF,NULL,yyvsp[0].asts); ; - break;} -case 35: -#line 235 "SDCC.y" -{ yyval.asts = newAst(EX_VALUE,sizeofOp(yyvsp[-1].lnk)); ; - break;} -case 36: -#line 239 "SDCC.y" -{ yyval.yyint = '&' ;; - break;} -case 37: -#line 240 "SDCC.y" -{ yyval.yyint = '*' ;; - break;} -case 38: -#line 241 "SDCC.y" -{ yyval.yyint = '+' ;; - break;} -case 39: -#line 242 "SDCC.y" -{ yyval.yyint = '-' ;; - break;} -case 40: -#line 243 "SDCC.y" -{ yyval.yyint = '~' ;; - break;} -case 41: -#line 244 "SDCC.y" -{ yyval.yyint = '!' ;; - break;} -case 43: -#line 249 "SDCC.y" -{ yyval.asts = newNode(CAST,newAst(EX_LINK,yyvsp[-2].lnk),yyvsp[0].asts); ; - break;} -case 45: -#line 254 "SDCC.y" -{ yyval.asts = newNode('*',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 46: -#line 255 "SDCC.y" -{ yyval.asts = newNode('/',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 47: -#line 256 "SDCC.y" -{ yyval.asts = newNode('%',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 49: -#line 261 "SDCC.y" -{ yyval.asts=newNode('+',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 50: -#line 262 "SDCC.y" -{ yyval.asts=newNode('-',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 52: -#line 267 "SDCC.y" -{ yyval.asts = newNode(LEFT_OP,yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 53: -#line 268 "SDCC.y" -{ yyval.asts = newNode(RIGHT_OP,yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 55: -#line 273 "SDCC.y" -{ yyval.asts = newNode('<',yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 56: -#line 274 "SDCC.y" -{ yyval.asts = newNode('>',yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 57: -#line 275 "SDCC.y" -{ - /* $$ = newNode(LE_OP,$1,$3); */ - /* getting 8051 specific here : will change - LE_OP operation to "not greater than" i.e. - ( a <= b ) === ( ! ( a > b )) */ - yyval.asts = newNode('!', - newNode('>', yyvsp[-2].asts , yyvsp[0].asts ), - NULL); - ; - break;} -case 58: -#line 284 "SDCC.y" -{ - /* $$ = newNode(GE_OP,$1,$3) ; */ - /* getting 8051 specific here : will change - GE_OP operation to "not less than" i.e. - ( a >= b ) === ( ! ( a < b )) */ - yyval.asts = newNode('!', - newNode('<', yyvsp[-2].asts , yyvsp[0].asts ), - NULL); - ; - break;} -case 60: -#line 297 "SDCC.y" -{ yyval.asts = newNode(EQ_OP,yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 61: -#line 299 "SDCC.y" -{ - /* $$ = newNode(NE_OP,$1,$3); */ - /* NE_OP changed : - expr1 != expr2 is equivalent to - (! expr1 == expr2) */ - yyval.asts = newNode('!', - newNode(EQ_OP,yyvsp[-2].asts,yyvsp[0].asts), - NULL); - ; - break;} -case 63: -#line 312 "SDCC.y" -{ yyval.asts = newNode('&',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 65: -#line 317 "SDCC.y" -{ yyval.asts = newNode('^',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 67: -#line 322 "SDCC.y" -{ yyval.asts = newNode('|',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 69: -#line 328 "SDCC.y" -{ yyval.asts = newNode(AND_OP,yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 71: -#line 334 "SDCC.y" -{ yyval.asts = newNode(OR_OP,yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 73: -#line 340 "SDCC.y" -{ - yyval.asts = newNode(':',yyvsp[-2].asts,yyvsp[0].asts) ; - yyval.asts = newNode('?',yyvsp[-4].asts,yyval.asts) ; - ; - break;} -case 75: -#line 349 "SDCC.y" -{ - - switch (yyvsp[-1].yyint) { - case '=': - yyval.asts = newNode(yyvsp[-1].yyint,yyvsp[-2].asts,yyvsp[0].asts); - break; - case MUL_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('*',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case DIV_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('/',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case ADD_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('+',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case SUB_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('-',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case LEFT_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode(LEFT_OP,copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case RIGHT_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode(RIGHT_OP,copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case AND_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('&',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case XOR_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('^',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - case OR_ASSIGN: - yyval.asts = newNode('=',yyvsp[-2].asts,newNode('|',copyAst(yyvsp[-2].asts),yyvsp[0].asts)); - break; - default : - yyval.asts = NULL; - } - - ; - break;} -case 76: -#line 390 "SDCC.y" -{ yyval.yyint = '=' ;; - break;} -case 88: -#line 405 "SDCC.y" -{ yyval.asts = newNode(',',yyvsp[-2].asts,yyvsp[0].asts);; - break;} -case 90: -#line 413 "SDCC.y" -{ yyval.sym = NULL ; ; - break;} -case 91: -#line 415 "SDCC.y" -{ - /* add the specifier list to the id */ - symbol *sym , *sym1; - - for (sym1 = sym = reverseSyms(yyvsp[-1].sym);sym != NULL;sym = sym->next) { - link *lnk = copyLinkChain(yyvsp[-2].lnk); - /* do the pointer stuff */ - pointerTypes(sym->type,lnk); - addDecl (sym,0,lnk) ; - } - - yyval.sym = sym1 ; - ; - break;} -case 92: -#line 431 "SDCC.y" -{ yyval.lnk = yyvsp[0].lnk; ; - break;} -case 93: -#line 432 "SDCC.y" -{ - /* if the decl $2 is not a specifier */ - /* find the spec and replace it */ - if ( !IS_SPEC(yyvsp[0].lnk)) { - link *lnk = yyvsp[0].lnk ; - while (lnk && !IS_SPEC(lnk->next)) - lnk = lnk->next; - lnk->next = mergeSpec(yyvsp[-1].lnk,lnk->next); - yyval.lnk = yyvsp[0].lnk ; - } - else - yyval.lnk = mergeSpec(yyvsp[-1].lnk,yyvsp[0].lnk); - ; - break;} -case 94: -#line 445 "SDCC.y" -{ yyval.lnk = yyvsp[0].lnk; ; - break;} -case 95: -#line 446 "SDCC.y" -{ - /* if the decl $2 is not a specifier */ - /* find the spec and replace it */ - if ( !IS_SPEC(yyvsp[0].lnk)) { - link *lnk = yyvsp[0].lnk ; - while (lnk && !IS_SPEC(lnk->next)) - lnk = lnk->next; - lnk->next = mergeSpec(yyvsp[-1].lnk,lnk->next); - yyval.lnk = yyvsp[0].lnk ; - } - else - yyval.lnk = mergeSpec(yyvsp[-1].lnk,yyvsp[0].lnk); - ; - break;} -case 97: -#line 463 "SDCC.y" -{ yyvsp[0].sym->next = yyvsp[-2].sym ; yyval.sym = yyvsp[0].sym;; - break;} -case 98: -#line 467 "SDCC.y" -{ yyvsp[0].sym->ival = NULL ; ; - break;} -case 99: -#line 468 "SDCC.y" -{ yyvsp[-2].sym->ival = yyvsp[0].ilist ; ; - break;} -case 100: -#line 473 "SDCC.y" -{ - yyval.lnk = newLink () ; - yyval.lnk->class = SPECIFIER ; - SPEC_TYPEDEF(yyval.lnk) = 1 ; - ; - break;} -case 101: -#line 478 "SDCC.y" -{ - yyval.lnk = newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_EXTR(yyval.lnk) = 1 ; - ; - break;} -case 102: -#line 483 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_STAT(yyval.lnk) = 1 ; - ; - break;} -case 103: -#line 488 "SDCC.y" -{ - yyval.lnk = newLink () ; - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_AUTO ; - ; - break;} -case 104: -#line 493 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_REGISTER ; - ; - break;} -case 105: -#line 501 "SDCC.y" -{ yyval.yyint = (int) floatFromVal(yyvsp[0].val) ; ; - break;} -case 107: -#line 507 "SDCC.y" -{ - /* add this to the storage class specifier */ - SPEC_ABSA(yyvsp[-2].lnk) = 1; /* set the absolute addr flag */ - /* now get the abs addr from value */ - SPEC_ADDR(yyvsp[-2].lnk) = (int) floatFromVal (yyvsp[0].val) ; - ; - break;} -case 108: -#line 516 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_CHAR ; - ; - break;} -case 109: -#line 521 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_LONG(yyval.lnk) = 0 ; - SPEC_SHORT(yyval.lnk) = 1 ; - ; - break;} -case 110: -#line 527 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_INT ; - ; - break;} -case 111: -#line 532 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_LONG(yyval.lnk) = 1 ; - SPEC_SHORT(yyval.lnk) = 0; - ; - break;} -case 112: -#line 538 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_USIGN(yyval.lnk) = 0 ; - ; - break;} -case 113: -#line 543 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_USIGN(yyval.lnk) = 1 ; - ; - break;} -case 114: -#line 548 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_VOID ; - ; - break;} -case 115: -#line 553 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_CONSTANT ; - SPEC_CONST(yyval.lnk) = 1; - ; - break;} -case 116: -#line 559 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_VOLATILE(yyval.lnk) = 1 ; - ; - break;} -case 117: -#line 564 "SDCC.y" -{ - yyval.lnk=newLink(); - SPEC_NOUN(yyval.lnk) = V_FLOAT; - yyval.lnk->class = SPECIFIER ; - ; - break;} -case 118: -#line 569 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_XDATA ; - ; - break;} -case 119: -#line 574 "SDCC.y" -{ - yyval.lnk = newLink () ; - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_CODE ; - ; - break;} -case 120: -#line 579 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_DATA ; - ; - break;} -case 121: -#line 584 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_IDATA ; - ; - break;} -case 122: -#line 589 "SDCC.y" -{ - yyval.lnk = newLink (); - yyval.lnk->class = SPECIFIER ; - SPEC_SCLS(yyval.lnk) = S_PDATA ; - ; - break;} -case 123: -#line 594 "SDCC.y" -{ - yyval.lnk=newLink(); - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_BIT ; - SPEC_SCLS(yyval.lnk) = S_BIT ; - SPEC_BLEN(yyval.lnk) = 1; - SPEC_BSTR(yyval.lnk) = 0; - ; - break;} -case 125: -#line 604 "SDCC.y" -{ - cenum = NULL ; - yyval.lnk = yyvsp[0].lnk ; - ; - break;} -case 126: -#line 609 "SDCC.y" -{ - symbol *sym; - link *p ; - - sym = findSym(TypedefTab,NULL,yyvsp[0].yychar) ; - yyval.lnk = p = copyLinkChain(sym->type); - SPEC_TYPEDEF(getSpec(p)) = 0; - ; - break;} -case 128: -#line 621 "SDCC.y" -{ - yyval.lnk = newLink() ; - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_SBIT; - SPEC_SCLS(yyval.lnk) = S_SBIT; - ; - break;} -case 129: -#line 627 "SDCC.y" -{ - yyval.lnk = newLink() ; - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_CHAR; - SPEC_SCLS(yyval.lnk) = S_SFR ; - SPEC_USIGN(yyval.lnk) = 1 ; - ; - break;} -case 130: -#line 638 "SDCC.y" -{ - structdef *sdef ; - - /* Create a structdef */ - sdef = yyvsp[-3].sdef ; - sdef->fields = reverseSyms(yyvsp[-1].sym) ; /* link the fields */ - sdef->size = compStructSize(yyvsp[-4].yyint,sdef); /* update size of */ - - /* Create the specifier */ - yyval.lnk = newLink () ; - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_STRUCT; - SPEC_STRUCT(yyval.lnk)= sdef ; - ; - break;} -case 131: -#line 653 "SDCC.y" -{ - yyval.lnk = newLink() ; - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_STRUCT; - SPEC_STRUCT(yyval.lnk) = yyvsp[0].sdef ; - ; - break;} -case 132: -#line 662 "SDCC.y" -{ yyval.yyint = STRUCT ; ; - break;} -case 133: -#line 663 "SDCC.y" -{ yyval.yyint = UNION ; ; - break;} -case 135: -#line 668 "SDCC.y" -{ /* synthesize a name add to structtable */ - yyval.sdef = newStruct(genSymName(NestLevel)) ; - yyval.sdef->level = NestLevel ; - addSym (StructTab, yyval.sdef, yyval.sdef->tag,yyval.sdef->level,currBlockno) ; - ; - break;} -case 136: -#line 676 "SDCC.y" -{ /* add name to structure table */ - yyval.sdef = findSymWithBlock (StructTab,yyvsp[0].sym,currBlockno); - if (! yyval.sdef ) { - yyval.sdef = newStruct(yyvsp[0].sym->name) ; - yyval.sdef->level = NestLevel ; - addSym (StructTab, yyval.sdef, yyval.sdef->tag,yyval.sdef->level,currBlockno) ; - } - ; - break;} -case 138: -#line 689 "SDCC.y" -{ - symbol *sym = yyvsp[0].sym; - /* go to the end of the chain */ - while (sym->next) sym = sym->next; - - sym->next = yyvsp[-1].sym ; - yyval.sym = yyvsp[0].sym; - ; - break;} -case 139: -#line 701 "SDCC.y" -{ - /* add this type to all the symbols */ - symbol *sym ; - for ( sym = yyvsp[-1].sym ; sym != NULL ; sym = sym->next ) { - - pointerTypes(sym->type,copyLinkChain(yyvsp[-2].lnk)); - if (!sym->type) { - sym->type = copyLinkChain(yyvsp[-2].lnk); - sym->etype = getSpec(sym->type); - } - else - addDecl (sym,0,cloneSpec(yyvsp[-2].lnk)); - - } - yyval.sym = yyvsp[-1].sym; - ; - break;} -case 141: -#line 722 "SDCC.y" -{ - yyvsp[0].sym->next = yyvsp[-2].sym ; - yyval.sym = yyvsp[0].sym ; - ; - break;} -case 143: -#line 730 "SDCC.y" -{ - yyval.sym = newSymbol (genSymName(NestLevel),NestLevel) ; - yyval.sym->bitVar = (int) floatFromVal(constExprValue(yyvsp[0].asts,TRUE)); - ; - break;} -case 144: -#line 735 "SDCC.y" -{ - yyvsp[-2].sym->bitVar = (int) floatFromVal(constExprValue(yyvsp[0].asts,TRUE)); - ; - break;} -case 145: -#line 741 "SDCC.y" -{ - addSymChain (yyvsp[-1].sym); - allocVariables(reverseSyms(yyvsp[-1].sym)) ; - yyval.lnk = copyLinkChain(cenum->type); - ; - break;} -case 146: -#line 746 "SDCC.y" -{ - symbol *csym ; - - yyvsp[-3].sym->type = copyLinkChain(cenum->type); - yyvsp[-3].sym->etype = getSpec(yyvsp[-3].sym->type); - /* add this to the enumerator table */ - if (!(csym=findSym(enumTab,yyvsp[-3].sym,yyvsp[-3].sym->name)) && - (csym && csym->level == yyvsp[-3].sym->level)) - werror(E_DUPLICATE_TYPEDEF,csym->name); - - addSym ( enumTab,yyvsp[-3].sym,yyvsp[-3].sym->name,yyvsp[-3].sym->level,yyvsp[-3].sym->block); - addSymChain (yyvsp[-1].sym); - allocVariables (reverseSyms(yyvsp[-1].sym)); - yyval.lnk = copyLinkChain(cenum->type); - SPEC_SCLS(getSpec(yyval.lnk)) = 0 ; - ; - break;} -case 147: -#line 762 "SDCC.y" -{ - symbol *csym ; - - /* check the enumerator table */ - if ((csym = findSym(enumTab,yyvsp[0].sym,yyvsp[0].sym->name))) - yyval.lnk = copyLinkChain(csym->type); - else { - yyval.lnk = newLink() ; - yyval.lnk->class = SPECIFIER ; - SPEC_NOUN(yyval.lnk) = V_INT ; - } - - SPEC_SCLS(getSpec(yyval.lnk)) = 0 ; - ; - break;} -case 149: -#line 780 "SDCC.y" -{ - yyvsp[0].sym->next = yyvsp[-2].sym ; - yyval.sym = yyvsp[0].sym ; - ; - break;} -case 150: -#line 787 "SDCC.y" -{ - /* make the symbol one level up */ - yyvsp[-1].sym->level-- ; - yyvsp[-1].sym->type = copyLinkChain(yyvsp[0].val->type); - yyvsp[-1].sym->etype= getSpec(yyvsp[-1].sym->type); - SPEC_ENUM(yyvsp[-1].sym->etype) = 1; - yyval.sym = yyvsp[-1].sym ; - - ; - break;} -case 151: -#line 799 "SDCC.y" -{ - value *val ; - - val = constExprValue(yyvsp[0].asts,TRUE); - yyval.val = cenum = val ; - ; - break;} -case 152: -#line 805 "SDCC.y" -{ - if (cenum) { - sprintf(lbuff,"%d",(int) floatFromVal(cenum)+1); - yyval.val = cenum = constVal(lbuff); - } - else { - sprintf(lbuff,"%d",0); - yyval.val = cenum = constVal(lbuff); - } - ; - break;} -case 153: -#line 818 "SDCC.y" -{ yyval.sym = yyvsp[0].sym; ; - break;} -case 154: -#line 820 "SDCC.y" -{ - addDecl (yyvsp[0].sym,0,reverseLink(yyvsp[-1].lnk)); - yyval.sym = yyvsp[0].sym ; - ; - break;} -case 155: -#line 827 "SDCC.y" -{ yyval.sym = yyvsp[0].sym ; ; - break;} -case 156: -#line 828 "SDCC.y" -{ addDecl (yyvsp[-1].sym,0,yyvsp[0].lnk); ; - break;} -case 158: -#line 833 "SDCC.y" -{ yyval.sym = yyvsp[-1].sym; ; - break;} -case 159: -#line 835 "SDCC.y" -{ - link *p; - - p = newLink (); - DCL_TYPE(p) = ARRAY ; - DCL_ELEM(p) = 0 ; - addDecl(yyvsp[-2].sym,0,p); - ; - break;} -case 160: -#line 844 "SDCC.y" -{ - link *p ; - value *tval; - - p = (tval = constExprValue(yyvsp[-1].asts,TRUE))->etype; - /* if it is not a constant then Error */ - if ( SPEC_SCLS(p) != S_LITERAL) - werror(E_CONST_EXPECTED) ; - else { - p = newLink (); - DCL_TYPE(p) = ARRAY ; - DCL_ELEM(p) = (int) floatFromVal(tval) ; - addDecl(yyvsp[-3].sym,0,p); - } - ; - break;} -case 161: -#line 859 "SDCC.y" -{ addDecl (yyvsp[-2].sym,FUNCTION,NULL) ; ; - break;} -case 162: -#line 860 "SDCC.y" -{ NestLevel++ ; currBlockno++; ; - break;} -case 163: -#line 861 "SDCC.y" -{ - - addDecl (yyvsp[-4].sym,FUNCTION,NULL) ; - - yyvsp[-4].sym->hasVargs = IS_VARG(yyvsp[-1].val); - yyvsp[-4].sym->args = reverseVal(yyvsp[-1].val) ; - - /* nest level was incremented to take care of the parms */ - NestLevel-- ; - currBlockno--; - yyval.sym = yyvsp[-4].sym; - ; - break;} -case 164: -#line 874 "SDCC.y" -{ - werror(E_OLD_STYLE,yyvsp[-3].sym->name) ; - - /* assume it returns an it */ - yyvsp[-3].sym->type = yyvsp[-3].sym->etype = newIntLink(); - yyval.sym = yyvsp[-3].sym ; - ; - break;} -case 165: -#line 884 "SDCC.y" -{ yyval.lnk = yyvsp[0].lnk ;; - break;} -case 166: -#line 886 "SDCC.y" -{ - yyval.lnk = yyvsp[-1].lnk ; - DCL_TSPEC(yyvsp[-1].lnk) = yyvsp[0].lnk; - ; - break;} -case 167: -#line 891 "SDCC.y" -{ - yyval.lnk = yyvsp[-1].lnk ; - yyval.lnk->next = yyvsp[0].lnk ; - ; - break;} -case 168: -#line 896 "SDCC.y" -{ - yyval.lnk = yyvsp[-2].lnk ; - if (IS_SPEC(yyvsp[-1].lnk) && DCL_TYPE(yyvsp[0].lnk) == UPOINTER) { - DCL_PTR_CONST(yyvsp[-2].lnk) = SPEC_CONST(yyvsp[-1].lnk); - DCL_PTR_VOLATILE(yyvsp[-2].lnk) = SPEC_VOLATILE(yyvsp[-1].lnk); - switch (SPEC_SCLS(yyvsp[-1].lnk)) { - case S_XDATA: - DCL_TYPE(yyvsp[0].lnk) = FPOINTER; - break; - case S_IDATA: - DCL_TYPE(yyvsp[0].lnk) = IPOINTER ; - break; - case S_PDATA: - DCL_TYPE(yyvsp[0].lnk) = PPOINTER ; - break; - case S_DATA: - DCL_TYPE(yyvsp[0].lnk) = POINTER ; - break; - case S_CODE: - DCL_PTR_CONST(yyvsp[0].lnk) = 1; - DCL_TYPE(yyvsp[0].lnk) = CPOINTER ; - break; - } - } - else - werror (W_PTR_TYPE_INVALID); - yyval.lnk->next = yyvsp[0].lnk ; - ; - break;} -case 169: -#line 927 "SDCC.y" -{ - if (yyvsp[-1].lnk == NULL) { - yyval.lnk = newLink(); - DCL_TYPE(yyval.lnk) = POINTER ; - } - else - yyval.lnk = yyvsp[-1].lnk ; - ; - break;} -case 170: -#line 938 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = FPOINTER ; ; - break;} -case 171: -#line 939 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = CPOINTER ; DCL_PTR_CONST(yyval.lnk) = 1;; - break;} -case 172: -#line 940 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = PPOINTER ; ; - break;} -case 173: -#line 941 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = IPOINTER ; ; - break;} -case 174: -#line 942 "SDCC.y" -{ yyval.lnk = NULL ; ; - break;} -case 175: -#line 943 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = GPOINTER ; ; - break;} -case 176: -#line 944 "SDCC.y" -{ yyval.lnk = newLink() ; DCL_TYPE(yyval.lnk) = UPOINTER ; ; - break;} -case 178: -#line 949 "SDCC.y" -{ yyval.lnk = mergeSpec (yyvsp[-1].lnk,yyvsp[0].lnk); ; - break;} -case 182: -#line 960 "SDCC.y" -{ - yyvsp[0].sym->next = yyvsp[-2].sym; - yyval.sym = yyvsp[0].sym ; - ; - break;} -case 184: -#line 968 "SDCC.y" -{ yyvsp[-2].val->vArgs = 1;; - break;} -case 186: -#line 974 "SDCC.y" -{ - yyvsp[0].val->next = yyvsp[-2].val ; - yyval.val = yyvsp[0].val ; - ; - break;} -case 187: -#line 982 "SDCC.y" -{ - symbol *loop ; - pointerTypes(yyvsp[0].sym->type,yyvsp[-1].lnk); - addDecl (yyvsp[0].sym,0,yyvsp[-1].lnk); - for (loop=yyvsp[0].sym;loop;loop->_isparm=1,loop=loop->next); - addSymChain (yyvsp[0].sym); - yyval.val = symbolVal(yyvsp[0].sym); - ; - break;} -case 188: -#line 990 "SDCC.y" -{ - yyval.val = newValue() ; - yyval.val->type = yyvsp[0].lnk; - yyval.val->etype = getSpec(yyval.val->type); - ; - break;} -case 189: -#line 998 "SDCC.y" -{ yyval.lnk = yyvsp[0].lnk ;; - break;} -case 190: -#line 1000 "SDCC.y" -{ - /* go to the end of the list */ - link *p; - pointerTypes(yyvsp[0].lnk,yyvsp[-1].lnk); - for ( p = yyvsp[0].lnk ; p->next ; p=p->next); - p->next = yyvsp[-1].lnk ; - yyval.lnk = yyvsp[0].lnk ; - ; - break;} -case 191: -#line 1011 "SDCC.y" -{ yyval.lnk = reverseLink(yyvsp[0].lnk); ; - break;} -case 193: -#line 1013 "SDCC.y" -{ yyvsp[-1].lnk = reverseLink(yyvsp[-1].lnk); yyvsp[-1].lnk->next = yyvsp[0].lnk ; yyval.lnk = yyvsp[-1].lnk;; - break;} -case 194: -#line 1017 "SDCC.y" -{ yyval.lnk = yyvsp[-1].lnk ; ; - break;} -case 195: -#line 1018 "SDCC.y" -{ - yyval.lnk = newLink (); - DCL_TYPE(yyval.lnk) = ARRAY ; - DCL_ELEM(yyval.lnk) = 0 ; - ; - break;} -case 196: -#line 1023 "SDCC.y" -{ - value *val ; - yyval.lnk = newLink (); - DCL_TYPE(yyval.lnk) = ARRAY ; - DCL_ELEM(yyval.lnk) = (int) floatFromVal(val = constExprValue(yyvsp[-1].asts,TRUE)); - ; - break;} -case 197: -#line 1029 "SDCC.y" -{ - yyval.lnk = newLink (); - DCL_TYPE(yyval.lnk) = ARRAY ; - DCL_ELEM(yyval.lnk) = 0 ; - yyval.lnk->next = yyvsp[-2].lnk ; - ; - break;} -case 198: -#line 1036 "SDCC.y" -{ - value *val ; - yyval.lnk = newLink (); - DCL_TYPE(yyval.lnk) = ARRAY ; - DCL_ELEM(yyval.lnk) = (int) floatFromVal(val = constExprValue(yyvsp[-1].asts,TRUE)); - yyval.lnk->next = yyvsp[-3].lnk ; - ; - break;} -case 199: -#line 1043 "SDCC.y" -{ yyval.lnk = NULL;; - break;} -case 200: -#line 1044 "SDCC.y" -{ yyval.lnk = NULL;; - break;} -case 203: -#line 1050 "SDCC.y" -{ yyval.ilist = newiList(INIT_NODE,yyvsp[0].asts); ; - break;} -case 204: -#line 1051 "SDCC.y" -{ yyval.ilist = newiList(INIT_DEEP,revinit(yyvsp[-1].ilist)); ; - break;} -case 205: -#line 1052 "SDCC.y" -{ yyval.ilist = newiList(INIT_DEEP,revinit(yyvsp[-2].ilist)); ; - break;} -case 207: -#line 1057 "SDCC.y" -{ yyvsp[0].ilist->next = yyvsp[-2].ilist; yyval.ilist = yyvsp[0].ilist; ; - break;} -case 214: -#line 1067 "SDCC.y" -{ - ast *ex = newNode(INLINEASM,NULL,NULL); - ALLOC_ATOMIC(ex->values.inlineasm,strlen(yyvsp[-1].yyinline)); - strcpy(ex->values.inlineasm,yyvsp[-1].yyinline); - yyval.asts = ex; - ; - break;} -case 215: -#line 1076 "SDCC.y" -{ yyval.asts = createLabel(yyvsp[-2].sym,yyvsp[0].asts); ; - break;} -case 216: -#line 1077 "SDCC.y" -{ yyval.asts = createCase(STACK_PEEK(swStk),yyvsp[-2].asts,yyvsp[0].asts); ; - break;} -case 217: -#line 1078 "SDCC.y" -{ yyval.asts = createDefault(STACK_PEEK(swStk),yyvsp[0].asts); ; - break;} -case 218: -#line 1081 "SDCC.y" -{ STACK_PUSH(blockNum,currBlockno); currBlockno = ++blockNo ; ; - break;} -case 219: -#line 1084 "SDCC.y" -{ currBlockno = STACK_POP(blockNum); ; - break;} -case 220: -#line 1088 "SDCC.y" -{ yyval.asts = createBlock(NULL,NULL); ; - break;} -case 221: -#line 1089 "SDCC.y" -{ yyval.asts = createBlock(NULL,yyvsp[-1].asts) ; ; - break;} -case 222: -#line 1091 "SDCC.y" -{ addSymChain(yyvsp[0].sym); ; - break;} -case 223: -#line 1092 "SDCC.y" -{ yyval.asts = createBlock(yyvsp[-2].sym,NULL) ; ; - break;} -case 224: -#line 1094 "SDCC.y" -{ addSymChain (yyvsp[0].sym); ; - break;} -case 225: -#line 1096 "SDCC.y" -{yyval.asts = createBlock(yyvsp[-3].sym,yyvsp[-1].asts) ; ; - break;} -case 226: -#line 1097 "SDCC.y" -{ yyval.asts = NULL ; ; - break;} -case 227: -#line 1102 "SDCC.y" -{ - /* if this is typedef declare it immediately */ - if ( yyvsp[0].sym && IS_TYPEDEF(yyvsp[0].sym->etype)) { - allocVariables (yyvsp[0].sym); - yyval.sym = NULL ; - } - else - yyval.sym = yyvsp[0].sym ; - ; - break;} -case 228: -#line 1113 "SDCC.y" -{ - symbol *sym; - - /* if this is a typedef */ - if (yyvsp[0].sym && IS_TYPEDEF(yyvsp[0].sym->etype)) { - allocVariables (yyvsp[0].sym); - yyval.sym = yyvsp[-1].sym ; - } - else { - /* get to the end of the previous decl */ - if ( yyvsp[-1].sym ) { - yyval.sym = sym = yyvsp[-1].sym ; - while (sym->next) - sym = sym->next ; - sym->next = yyvsp[0].sym; - } - else - yyval.sym = yyvsp[0].sym ; - } - ; - break;} -case 230: -#line 1137 "SDCC.y" -{ yyval.asts = newNode(NULLOP,yyvsp[-1].asts,yyvsp[0].asts) ;; - break;} -case 231: -#line 1141 "SDCC.y" -{ yyval.asts = NULL;; - break;} -case 233: -#line 1146 "SDCC.y" -{ yyval.asts = yyvsp[0].asts ; ; - break;} -case 234: -#line 1147 "SDCC.y" -{ yyval.asts = NULL;; - break;} -case 235: -#line 1152 "SDCC.y" -{ noLineno++ ; yyval.asts = createIf (yyvsp[-3].asts, yyvsp[-1].asts, yyvsp[0].asts ); noLineno--;; - break;} -case 236: -#line 1153 "SDCC.y" -{ - ast *ex ; - static int swLabel = 0 ; - - /* create a node for expression */ - ex = newNode(SWITCH,yyvsp[-1].asts,NULL); - STACK_PUSH(swStk,ex); /* save it in the stack */ - ex->values.switchVals.swNum = swLabel ; - - /* now create the label */ - sprintf(lbuff,"_swBrk_%d",swLabel++); - yyval.sym = newSymbol(lbuff,NestLevel); - /* put label in the break stack */ - STACK_PUSH(breakStack,yyval.sym); - ; - break;} -case 237: -#line 1168 "SDCC.y" -{ - /* get back the switch form the stack */ - yyval.asts = STACK_POP(swStk) ; - yyval.asts->right = newNode (NULLOP,yyvsp[0].asts,createLabel(yyvsp[-1].sym,NULL)); - STACK_POP(breakStack); - ; - break;} -case 238: -#line 1176 "SDCC.y" -{ /* create and push the continue , break & body labels */ - static int Lblnum = 0 ; - /* continue */ - sprintf (lbuff,"_whilecontinue_%d",Lblnum); - STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); - /* break */ - sprintf (lbuff,"_whilebreak_%d",Lblnum); - STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); - /* body */ - sprintf (lbuff,"_whilebody_%d",Lblnum++); - yyval.sym = newSymbol(lbuff,NestLevel); - ; - break;} -case 239: -#line 1189 "SDCC.y" -{ /* create and push the continue , break & body Labels */ - static int Lblnum = 0 ; - - /* continue */ - sprintf(lbuff,"_docontinue_%d",Lblnum); - STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); - /* break */ - sprintf (lbuff,"_dobreak_%d",Lblnum); - STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); - /* do body */ - sprintf (lbuff,"_dobody_%d",Lblnum++); - yyval.sym = newSymbol (lbuff,NestLevel); - ; - break;} -case 240: -#line 1202 "SDCC.y" -{ /* create & push continue, break & body labels */ - static int Lblnum = 0 ; - - /* continue */ - sprintf (lbuff,"_forcontinue_%d",Lblnum); - STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); - /* break */ - sprintf (lbuff,"_forbreak_%d",Lblnum); - STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); - /* body */ - sprintf (lbuff,"_forbody_%d",Lblnum); - yyval.sym = newSymbol(lbuff,NestLevel); - /* condition */ - sprintf (lbuff,"_forcond_%d",Lblnum++); - STACK_PUSH(forStack,newSymbol(lbuff,NestLevel)); - ; - break;} -case 241: -#line 1221 "SDCC.y" -{ - noLineno++ ; - yyval.asts = createWhile ( yyvsp[-4].sym, STACK_POP(continueStack), - STACK_POP(breakStack), yyvsp[-2].asts, yyvsp[0].asts ); - yyval.asts->lineno = yyvsp[-4].sym->lineDef ; - noLineno-- ; - ; - break;} -case 242: -#line 1229 "SDCC.y" -{ - noLineno++ ; - yyval.asts = createDo ( yyvsp[-6].sym , STACK_POP(continueStack), - STACK_POP(breakStack), yyvsp[-2].asts, yyvsp[-5].asts); - yyval.asts->lineno = yyvsp[-6].sym->lineDef ; - noLineno-- ; - ; - break;} -case 243: -#line 1237 "SDCC.y" -{ - noLineno++ ; - - /* if break or continue statement present - then create a general case loop */ - if (STACK_PEEK(continueStack)->isref || - STACK_PEEK(breakStack)->isref) { - yyval.asts = createFor (yyvsp[-8].sym, STACK_POP(continueStack), - STACK_POP(breakStack) , - STACK_POP(forStack) , - yyvsp[-6].asts , yyvsp[-4].asts , yyvsp[-2].asts, yyvsp[0].asts ); - } else { - yyval.asts = newNode(FOR,yyvsp[0].asts,NULL); - AST_FOR(yyval.asts,trueLabel) = yyvsp[-8].sym; - AST_FOR(yyval.asts,continueLabel) = STACK_POP(continueStack); - AST_FOR(yyval.asts,falseLabel) = STACK_POP(breakStack); - AST_FOR(yyval.asts,condLabel) = STACK_POP(forStack) ; - AST_FOR(yyval.asts,initExpr) = yyvsp[-6].asts; - AST_FOR(yyval.asts,condExpr) = yyvsp[-4].asts; - AST_FOR(yyval.asts,loopExpr) = yyvsp[-2].asts; - } - - noLineno-- ; - ; - break;} -case 244: -#line 1264 "SDCC.y" -{ yyval.asts = NULL ; ; - break;} -case 246: -#line 1269 "SDCC.y" -{ - yyvsp[-1].sym->islbl = 1; - yyval.asts = newAst(EX_VALUE,symbolVal(yyvsp[-1].sym)); - yyval.asts = newNode(GOTO,yyval.asts,NULL); - ; - break;} -case 247: -#line 1274 "SDCC.y" -{ - /* make sure continue is in context */ - if (STACK_PEEK(continueStack) == NULL) { - werror(E_BREAK_CONTEXT); - yyval.asts = NULL; - } - else { - yyval.asts = newAst(EX_VALUE,symbolVal(STACK_PEEK(continueStack))); - yyval.asts = newNode(GOTO,yyval.asts,NULL); - /* mark the continue label as referenced */ - STACK_PEEK(continueStack)->isref = 1; - } - ; - break;} -case 248: -#line 1287 "SDCC.y" -{ - if (STACK_PEEK(breakStack) == NULL) { - werror(E_BREAK_CONTEXT); - yyval.asts = NULL; - } else { - yyval.asts = newAst(EX_VALUE,symbolVal(STACK_PEEK(breakStack))); - yyval.asts = newNode(GOTO,yyval.asts,NULL); - STACK_PEEK(breakStack)->isref = 1; - } - ; - break;} -case 249: -#line 1297 "SDCC.y" -{ yyval.asts = newNode(RETURN,NULL,NULL) ; ; - break;} -case 250: -#line 1298 "SDCC.y" -{ yyval.asts = newNode(RETURN,NULL,yyvsp[-1].asts) ; ; - break;} -case 251: -#line 1302 "SDCC.y" -{ yyval.sym = newSymbol (yyvsp[0].yychar,NestLevel) ; ; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 543 "/usr/share/misc/bison.simple" - - yyvsp -= yylen; - yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - - *++yyvsp = yyval; - -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#endif - - /* Now "shift" the result of the reduction. - Determine what state that goes to, - based on the state we popped back to - and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTBASE]; - - goto yynewstate; - -yyerrlab: /* here on detecting error */ - - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ - { - ++yynerrs; - -#ifdef YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (yyn > YYFLAG && yyn < YYLAST) - { - int size = 0; - char *msg; - int x, count; - - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) - { - strcpy(msg, "parse error"); - - if (count < 5) - { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; - } - } - yyerror(msg); - free(msg); - } - else - yyerror ("parse error; also virtual memory exceeded"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror("parse error"); - } - - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ - - if (yyerrstatus == 3) - { - /* if just tried and failed to reuse lookahead token after an error, discard it. */ - - /* return failure if at end of input */ - if (yychar == YYEOF) - YYABORT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif - - yychar = YYEMPTY; - } - - /* Else will try to reuse lookahead token - after shifting the error token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; - -yyerrdefault: /* current state does not do anything special for the error token. */ - -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; -#endif - -yyerrpop: /* pop the current state because it cannot handle the error token */ - - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - -yyerrhandle: - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; - - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; - - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrpop; - - if (yyn == YYFINAL) - YYACCEPT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - yystate = yyn; - goto yynewstate; - - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 1; -} -#line 1304 "SDCC.y" - - -extern unsigned char *yytext; -extern int column; -extern char *filename; -extern int fatalError; - -int yyerror(char *s) -{ - fflush(stdout); - - if ( yylineno ) - fprintf(stderr,"\n%s(%d) %s: token -> '%s' ; column %d\n", - filename,yylineno, - s,yytext,column); - fatalError++; - return 0; -} - diff --git a/src/mcs51/Makefile b/src/mcs51/Makefile new file mode 100644 index 00000000..ccf2b5b7 --- /dev/null +++ b/src/mcs51/Makefile @@ -0,0 +1,19 @@ +PRJDIR = ../.. + +include $(PRJDIR)/Makefile.common + +OBJ = gen.o ralloc.o +LIB = port.a + +CFLAGS = -ggdb -Wall +CFLAGS += -I.. -I. -I../.. + +all: $(LIB) + +$(LIB): $(OBJ) + rm -f $(LIB) + ar r $(LIB) $(OBJ) + ranlib $(LIB) + +clean: + rm -f $(LIB) *.o *~ diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c new file mode 100644 index 00000000..b7e238f8 --- /dev/null +++ b/src/mcs51/gen.c @@ -0,0 +1,7383 @@ +/*------------------------------------------------------------------------- + SDCCgen51.c - source file for code generation for 8051 + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) + and - Jean-Louis VERN.jlvern@writeme.com (1999) + Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! + +-------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "SDCCglobl.h" + +#ifdef HAVE_SYS_ISA_DEFS_H +#include +#else +#ifdef HAVE_ENDIAN_H +#include +#else +#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN" +#warning "If you running sdcc on an INTEL 80x86 Platform you are okay" +#endif +#endif + +#include "SDCCast.h" +#include "SDCCmem.h" +#include "SDCCy.h" +#include "SDCChasht.h" +#include "SDCCbitv.h" +#include "SDCCset.h" +#include "SDCCicode.h" +#include "SDCClabel.h" +#include "SDCCBBlock.h" +#include "SDCCloop.h" +#include "SDCCcse.h" +#include "SDCCcflow.h" +#include "SDCCdflow.h" +#include "SDCClrange.h" +#include "SDCCralloc.h" +#include "SDCCgen51.h" +#include "SDCCpeeph.h" + +/* this is the down and dirty file with all kinds of +kludgy & hacky stuff. This is what it is all about +CODE GENERATION for a specific MCU . some of the +routines may be reusable, will have to see */ + +static char *zero = "#0x00"; +static char *one = "#0x01"; +static char *spname ; +static char *fReturn[] = {"dpl","dph","b","a" }; +static char *accUse[] = {"a","b"}; +short r0Pushed = 0; +short r1Pushed = 0; +short rbank = -1; +short accInUse = 0 ; +short inLine = 0; +short debugLine = 0; +short nregssaved = 0; +extern int ptrRegReq ; +extern int nRegs; +extern FILE *codeOutFile; +set *sendSet = NULL; +static void saverbank (int, iCode *,bool); +#define RESULTONSTACK(x) \ + (IC_RESULT(x) && IC_RESULT(x)->aop && \ + IC_RESULT(x)->aop->type == AOP_STK ) + +#define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); +#define CLRC emitcode("clr","c"); + +lineNode *lineHead = NULL; +lineNode *lineCurr = NULL; + +unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, +0xE0, 0xC0, 0x80, 0x00}; +unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, +0x07, 0x03, 0x01, 0x00}; + +#define LSB 0 +#define MSB16 1 +#define MSB24 2 +#define MSB32 3 + +/*-----------------------------------------------------------------*/ +/* emitcode - writes the code into a file : for now it is simple */ +/*-----------------------------------------------------------------*/ +void emitcode (char *inst,char *fmt, ...) +{ + va_list ap; + char lb[MAX_INLINEASM]; + char *lbp = lb; + + va_start(ap,fmt); + + if (inst && *inst) { + if (fmt && *fmt) + sprintf(lb,"%s\t",inst); + else + sprintf(lb,"%s",inst); + vsprintf(lb+(strlen(lb)),fmt,ap); + } else + vsprintf(lb,fmt,ap); + + while (isspace(*lbp)) lbp++; + + if (lbp && *lbp) + lineCurr = (lineCurr ? + connectLine(lineCurr,newLineNode(lb)) : + (lineHead = newLineNode(lb))); + lineCurr->isInline = inLine; + lineCurr->isDebug = debugLine; + va_end(ap); +} + +/*-----------------------------------------------------------------*/ +/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/ +/*-----------------------------------------------------------------*/ +static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) +{ + bool r0iu = FALSE , r1iu = FALSE; + bool r0ou = FALSE , r1ou = FALSE; + + /* the logic: if r0 & r1 used in the instruction + then we are in trouble otherwise */ + + /* first check if r0 & r1 are used by this + instruction, in which case we are in trouble */ + if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) && + (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) + goto endOfWorld; + + + r0ou = bitVectBitValue(ic->rMask,R0_IDX); + r1ou = bitVectBitValue(ic->rMask,R1_IDX); + + /* if no usage of r0 then return it */ + if (!r0iu && !r0ou) { + ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX); + (*aopp)->type = AOP_R0; + return (*aopp)->aopu.aop_ptr = regWithIdx(R0_IDX); + } + + /* if no usage of r1 then return it */ + if (!r1iu && !r1ou) { + ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX); + (*aopp)->type = AOP_R1; + return (*aopp)->aopu.aop_ptr = regWithIdx(R1_IDX); + } + + /* now we know they both have usage */ + /* if r0 not used in this instruction */ + if (!r0iu) { + /* push it if not already pushed */ + if (!r0Pushed) { + emitcode ("push","%s", + regWithIdx(R0_IDX)->dname); + r0Pushed++ ; + } + + ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX); + (*aopp)->type = AOP_R0; + + return (*aopp)->aopu.aop_ptr = regWithIdx(R0_IDX); + } + + /* if r1 not used then */ + + if (!r1iu) { + /* push it if not already pushed */ + if (!r1Pushed) { + emitcode ("push","%s", + regWithIdx(R1_IDX)->dname); + r1Pushed++ ; + } + + ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX); + (*aopp)->type = AOP_R1; + return regWithIdx(R1_IDX); + } + + +endOfWorld : + /* I said end of world but not quite end of world yet */ + /* if this is a result then we canpush it on the stack*/ + if (result) { + (*aopp)->type = AOP_STK; + return NULL; + } + + piCode(ic,stdout); + /* other wise this is true end of the world */ + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "getFreePtr should never reach here"); + exit(0); +} + +/*-----------------------------------------------------------------*/ +/* newAsmop - creates a new asmOp */ +/*-----------------------------------------------------------------*/ +static asmop *newAsmop (short type) +{ + asmop *aop; + + ALLOC(aop,sizeof(asmop)); + aop->type = type; + return aop; +} + +/*-----------------------------------------------------------------*/ +/* pointerCode - returns the code for a pointer type */ +/*-----------------------------------------------------------------*/ +static int pointerCode (link *etype) +{ + int p_type; + if (SPEC_OCLS(etype)->codesp ) { + p_type = CPOINTER ; + } + else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) + p_type = FPOINTER ; + else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) + p_type = PPOINTER; + else + if (SPEC_OCLS(etype) == idata ) + p_type = IPOINTER; + else + p_type = POINTER ; + return p_type; +} + +/*-----------------------------------------------------------------*/ +/* aopForSym - for a true symbol */ +/*-----------------------------------------------------------------*/ +static asmop *aopForSym (iCode *ic,symbol *sym,bool result) +{ + asmop *aop; + memmap *space= SPEC_OCLS(sym->etype); + + /* if already has one */ + if (sym->aop) + return sym->aop; + + /* assign depending on the storage class */ + /* if it is on the stack or indirectly addressable */ + /* space we need to assign either r0 or r1 to it */ + if (sym->onStack || sym->iaccess) { + sym->aop = aop = newAsmop(0); + aop->aopu.aop_ptr = getFreePtr(ic,&aop,result); + aop->size = getSize(sym->type); + + /* now assign the address of the variable to + the pointer register */ + if (aop->type != AOP_STK) { + + if (sym->onStack) { + + if ( accInUse ) + emitcode("push","acc"); + + emitcode("mov","a,_bp"); + emitcode("add","a,#0x%02x", + ((sym->stack < 0) ? + ((char)(sym->stack - nregssaved )) : + ((char)sym->stack)) & 0xff); + emitcode("mov","%s,a", + aop->aopu.aop_ptr->name); + + if ( accInUse ) + emitcode("pop","acc"); + + } else + emitcode("mov","%s,#%s", + aop->aopu.aop_ptr->name, + sym->rname); + aop->paged = space->paged; + } else + aop->aopu.aop_stk = sym->stack; + return aop; + } + + /* if in bit space */ + if (IN_BITSPACE(space)) { + sym->aop = aop = newAsmop (AOP_CRY); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + return aop; + } + /* if it is in direct space */ + if (IN_DIRSPACE(space)) { + sym->aop = aop = newAsmop (AOP_DIR); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + return aop; + } + + /* special case for a function */ + if (IS_FUNC(sym->type)) { + sym->aop = aop = newAsmop(AOP_IMMD); + ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1); + strcpy(aop->aopu.aop_immd,sym->rname); + aop->size = 2; + return aop; + } + + /* only remaining is far space */ + /* in which case DPTR gets the address */ + sym->aop = aop = newAsmop(AOP_DPTR); + emitcode ("mov","dptr,#%s", sym->rname); + aop->size = getSize(sym->type); + + /* if it is in code space */ + if (IN_CODESPACE(space)) + aop->code = 1; + + return aop; +} + +/*-----------------------------------------------------------------*/ +/* aopForRemat - rematerialzes an object */ +/*-----------------------------------------------------------------*/ +static asmop *aopForRemat (symbol *sym) +{ + char *s = buffer; + iCode *ic = sym->rematiCode; + asmop *aop = newAsmop(AOP_IMMD); + + while (1) { + + /* if plus or minus print the right hand side */ + if (ic->op == '+' || ic->op == '-') { + sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)), + ic->op ); + s += strlen(s); + ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode; + continue ; + } + + /* we reached the end */ + sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname); + break; + } + + ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1); + strcpy(aop->aopu.aop_immd,buffer); + return aop; +} + +/*-----------------------------------------------------------------*/ +/* regsInCommon - two operands have some registers in common */ +/*-----------------------------------------------------------------*/ +bool regsInCommon (operand *op1, operand *op2) +{ + symbol *sym1, *sym2; + int i; + + /* if they have registers in common */ + if (!IS_SYMOP(op1) || !IS_SYMOP(op2)) + return FALSE ; + + sym1 = OP_SYMBOL(op1); + sym2 = OP_SYMBOL(op2); + + if (sym1->nRegs == 0 || sym2->nRegs == 0) + return FALSE ; + + for (i = 0 ; i < sym1->nRegs ; i++) { + int j; + if (!sym1->regs[i]) + continue ; + + for (j = 0 ; j < sym2->nRegs ;j++ ) { + if (!sym2->regs[j]) + continue ; + + if (sym2->regs[j] == sym1->regs[i]) + return TRUE ; + } + } + + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* operandsEqu - equivalent */ +/*-----------------------------------------------------------------*/ +bool operandsEqu ( operand *op1, operand *op2) +{ + symbol *sym1, *sym2; + + /* if they not symbols */ + if (!IS_SYMOP(op1) || !IS_SYMOP(op2)) + return FALSE; + + sym1 = OP_SYMBOL(op1); + sym2 = OP_SYMBOL(op2); + + /* if both are itemps & one is spilt + and the other is not then false */ + if (IS_ITEMP(op1) && IS_ITEMP(op2) && + sym1->isspilt != sym2->isspilt ) + return FALSE ; + + /* if they are the same */ + if (sym1 == sym2) + return TRUE ; + + if (strcmp(sym1->rname,sym2->rname) == 0) + return TRUE; + + + /* if left is a tmp & right is not */ + if (IS_ITEMP(op1) && + !IS_ITEMP(op2) && + sym1->isspilt && + (sym1->usl.spillLoc == sym2)) + return TRUE; + + if (IS_ITEMP(op2) && + !IS_ITEMP(op1) && + sym2->isspilt && + sym1->level > 0 && + (sym2->usl.spillLoc == sym1)) + return TRUE ; + + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* sameRegs - two asmops have the same registers */ +/*-----------------------------------------------------------------*/ +bool sameRegs (asmop *aop1, asmop *aop2 ) +{ + int i; + + if (aop1 == aop2) + return TRUE ; + + if (aop1->type != AOP_REG || + aop2->type != AOP_REG ) + return FALSE ; + + if (aop1->size != aop2->size ) + return FALSE ; + + for (i = 0 ; i < aop1->size ; i++ ) + if (aop1->aopu.aop_reg[i] != + aop2->aopu.aop_reg[i] ) + return FALSE ; + + return TRUE ; +} + +/*-----------------------------------------------------------------*/ +/* aopOp - allocates an asmop for an operand : */ +/*-----------------------------------------------------------------*/ +static void aopOp (operand *op, iCode *ic, bool result) +{ + asmop *aop; + symbol *sym; + int i; + + if (!op) + return ; + + /* if this a literal */ + if (IS_OP_LITERAL(op)) { + op->aop = aop = newAsmop(AOP_LIT); + aop->aopu.aop_lit = op->operand.valOperand; + aop->size = getSize(operandType(op)); + return; + } + + /* if already has a asmop then continue */ + if (op->aop) + return ; + + /* if the underlying symbol has a aop */ + if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) { + op->aop = OP_SYMBOL(op)->aop; + return; + } + + /* if this is a true symbol */ + if (IS_TRUE_SYMOP(op)) { + op->aop = aopForSym(ic,OP_SYMBOL(op),result); + return ; + } + + /* this is a temporary : this has + only four choices : + a) register + b) spillocation + c) rematerialize + d) conditional + e) can be a return use only */ + + sym = OP_SYMBOL(op); + + + /* if the type is a conditional */ + if (sym->regType == REG_CND) { + aop = op->aop = sym->aop = newAsmop(AOP_CRY); + aop->size = 0; + return; + } + + /* if it is spilt then two situations + a) is rematerialize + b) has a spill location */ + if (sym->isspilt || sym->nRegs == 0) { + + /* rematerialize it NOW */ + if (sym->remat) { + sym->aop = op->aop = aop = + aopForRemat (sym); + aop->size = getSize(sym->type); + return; + } + + if (sym->accuse) { + int i; + aop = op->aop = sym->aop = newAsmop(AOP_ACC); + aop->size = getSize(sym->type); + for ( i = 0 ; i < 2 ; i++ ) + aop->aopu.aop_str[i] = accUse[i]; + return; + } + + if (sym->ruonly ) { + int i; + aop = op->aop = sym->aop = newAsmop(AOP_STR); + aop->size = getSize(sym->type); + for ( i = 0 ; i < 4 ; i++ ) + aop->aopu.aop_str[i] = fReturn[i]; + return; + } + + /* else spill location */ + sym->aop = op->aop = aop = + aopForSym(ic,sym->usl.spillLoc,result); + aop->size = getSize(sym->type); + return; + } + + /* must be in a register */ + sym->aop = op->aop = aop = newAsmop(AOP_REG); + aop->size = sym->nRegs; + for ( i = 0 ; i < sym->nRegs ;i++) + aop->aopu.aop_reg[i] = sym->regs[i]; +} + +/*-----------------------------------------------------------------*/ +/* freeAsmop - free up the asmop given to an operand */ +/*----------------------------------------------------------------*/ +static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) +{ + asmop *aop ; + + if (!op) + aop = aaop; + else + aop = op->aop; + + if (!aop) + return ; + + if (aop->freed) + goto dealloc; + + aop->freed = 1; + + /* depending on the asmop type only three cases need work AOP_RO + , AOP_R1 && AOP_STK */ + switch (aop->type) { + case AOP_R0 : + if (r0Pushed ) { + if (pop) { + emitcode ("pop","ar0"); + r0Pushed--; + } + } + bitVectUnSetBit(ic->rUsed,R0_IDX); + break; + + case AOP_R1 : + if (r1Pushed ) { + if (pop) { + emitcode ("pop","ar1"); + r1Pushed--; + } + } + bitVectUnSetBit(ic->rUsed,R1_IDX); + break; + + case AOP_STK : + { + int sz = aop->size; + int stk = aop->aopu.aop_stk + aop->size; + bitVectUnSetBit(ic->rUsed,R0_IDX); + bitVectUnSetBit(ic->rUsed,R1_IDX); + + getFreePtr(ic,&aop,FALSE); + if (stk) { + emitcode ("mov","a,_bp"); + emitcode ("add","a,#0x%02x",((char)stk) & 0xff); + emitcode ("mov","%s,a",aop->aopu.aop_ptr->name); + } else + emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name); + + while (sz--) { + emitcode("pop","acc"); + emitcode("mov","@%s,a",aop->aopu.aop_ptr->name); + if (!sz) break; + emitcode("dec","%s",aop->aopu.aop_ptr->name); + } + op->aop = aop; + freeAsmop(op,NULL,ic,TRUE); + if (r0Pushed) { + emitcode("pop","ar0"); + r0Pushed--; + } + + if (r1Pushed) { + emitcode("pop","ar1"); + r1Pushed--; + } + } + } + +dealloc: + /* all other cases just dealloc */ + if (op ) { + op->aop = NULL; + if (IS_SYMOP(op)) { + OP_SYMBOL(op)->aop = NULL; + /* if the symbol has a spill */ + if (SPIL_LOC(op)) + SPIL_LOC(op)->aop = NULL; + } + } +} + +/*-----------------------------------------------------------------*/ +/* aopLiteral - string from a literal value */ +/*-----------------------------------------------------------------*/ +char *aopLiteral (value *val, int offset) +{ + char *rs; + union { + float f; + unsigned char c[4]; + } fl; + + /* if it is a float then it gets tricky */ + /* otherwise it is fairly simple */ + if (!IS_FLOAT(val->type)) { + unsigned long v = floatFromVal(val); + + v >>= (offset * 8); + sprintf(buffer,"#0x%02x",((char) v) & 0xff); + ALLOC_ATOMIC(rs,strlen(buffer)+1); + return strcpy (rs,buffer); + } + + /* it is type float */ + fl.f = (float) floatFromVal(val); +#ifdef _BIG_ENDIAN + sprintf(buffer,"#0x%02x",fl.c[3-offset]); +#else + sprintf(buffer,"#0x%02x",fl.c[offset]); +#endif + ALLOC_ATOMIC(rs,strlen(buffer)+1); + return strcpy (rs,buffer); +} + +/*-----------------------------------------------------------------*/ +/* aopGet - for fetching value of the aop */ +/*-----------------------------------------------------------------*/ +static char *aopGet (asmop *aop, int offset, bool bit16, bool dname) +{ + char *s = buffer ; + char *rs; + + /* offset is greater than + size then zero */ + if (offset > (aop->size - 1) && + aop->type != AOP_LIT) + return zero; + + /* depending on type */ + switch (aop->type) { + + case AOP_R0: + case AOP_R1: + /* if we need to increment it */ + while (offset > aop->coff) { + emitcode ("inc","%s",aop->aopu.aop_ptr->name); + aop->coff++; + } + + while (offset < aop->coff) { + emitcode("dec","%s",aop->aopu.aop_ptr->name); + aop->coff--; + } + + aop->coff = offset ; + if (aop->paged) { + emitcode("movx","a,@%s",aop->aopu.aop_ptr->name); + return (dname ? "acc" : "a"); + } + sprintf(s,"@%s",aop->aopu.aop_ptr->name); + ALLOC_ATOMIC(rs,strlen(s)+1); + strcpy(rs,s); + return rs; + + case AOP_DPTR: + while (offset > aop->coff) { + emitcode ("inc","dptr"); + aop->coff++; + } + + while (offset < aop->coff) { + emitcode("lcall","__decdptr"); + aop->coff--; + } + + aop->coff = offset; + if (aop->code) { + emitcode("clr","a"); + emitcode("movc","a,@a+dptr"); + } + else + emitcode("movx","a,@dptr"); + return (dname ? "acc" : "a"); + + + case AOP_IMMD: + if (bit16) + sprintf (s,"#(%s)",aop->aopu.aop_immd); + else + if (offset) + sprintf(s,"#(%s >> %d)", + aop->aopu.aop_immd, + offset*8); + else + sprintf(s,"#%s", + aop->aopu.aop_immd); + ALLOC_ATOMIC(rs,strlen(s)+1); + strcpy(rs,s); + return rs; + + case AOP_DIR: + if (offset) + sprintf(s,"(%s + %d)", + aop->aopu.aop_dir, + offset); + else + sprintf(s,"%s",aop->aopu.aop_dir); + ALLOC_ATOMIC(rs,strlen(s)+1); + strcpy(rs,s); + return rs; + + case AOP_REG: + if (dname) + return aop->aopu.aop_reg[offset]->dname; + else + return aop->aopu.aop_reg[offset]->name; + + case AOP_CRY: + emitcode("clr","a"); + emitcode("mov","c,%s",aop->aopu.aop_dir); + emitcode("rlc","a") ; + return (dname ? "acc" : "a"); + + case AOP_ACC: + if (!offset && dname) + return "acc"; + return aop->aopu.aop_str[offset]; + + case AOP_LIT: + return aopLiteral (aop->aopu.aop_lit,offset); + + case AOP_STR: + aop->coff = offset ; + if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && + dname) + return "acc"; + + return aop->aopu.aop_str[offset]; + + } + + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "aopget got unsupported aop->type"); + exit(0); +} +/*-----------------------------------------------------------------*/ +/* aopPut - puts a string for a aop */ +/*-----------------------------------------------------------------*/ +static void aopPut (asmop *aop, char *s, int offset) +{ + char *d = buffer ; + symbol *lbl ; + + if (aop->size && offset > ( aop->size - 1)) { + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "aopPut got offset > aop->size"); + exit(0); + } + + /* will assign value to value */ + /* depending on where it is ofcourse */ + switch (aop->type) { + case AOP_DIR: + if (offset) + sprintf(d,"(%s + %d)", + aop->aopu.aop_dir,offset); + else + sprintf(d,"%s",aop->aopu.aop_dir); + + if (strcmp(d,s)) + emitcode("mov","%s,%s",d,s); + + break; + + case AOP_REG: + if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 && + strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){ + if (*s == '@' || + strcmp(s,"r0") == 0 || + strcmp(s,"r1") == 0 || + strcmp(s,"r2") == 0 || + strcmp(s,"r3") == 0 || + strcmp(s,"r4") == 0 || + strcmp(s,"r5") == 0 || + strcmp(s,"r6") == 0 || + strcmp(s,"r7") == 0 ) + emitcode("mov","%s,%s", + aop->aopu.aop_reg[offset]->dname,s); + else + emitcode("mov","%s,%s", + aop->aopu.aop_reg[offset]->name,s); + } + break; + + case AOP_DPTR: + if (aop->code) { + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "aopPut writting to code space"); + exit(0); + } + + while (offset > aop->coff) { + aop->coff++; + emitcode ("inc","dptr"); + } + + while (offset < aop->coff) { + aop->coff-- ; + emitcode("lcall","__decdptr"); + } + + aop->coff = offset; + + /* if not in accumulater */ + MOVA(s); + + emitcode ("movx","@dptr,a"); + break; + + case AOP_R0: + case AOP_R1: + while (offset > aop->coff) { + aop->coff++; + emitcode("inc","%s",aop->aopu.aop_ptr->name); + } + while (offset < aop->coff) { + aop->coff-- ; + emitcode ("dec","%s",aop->aopu.aop_ptr->name); + } + aop->coff = offset; + + if (aop->paged) { + MOVA(s); + emitcode("movx","@%s,a",aop->aopu.aop_ptr->name); + + } else + if (*s == '@') { + MOVA(s); + emitcode("mov","@%s,a",aop->aopu.aop_ptr->name); + } else + if (strcmp(s,"r0") == 0 || + strcmp(s,"r1") == 0 || + strcmp(s,"r2") == 0 || + strcmp(s,"r3") == 0 || + strcmp(s,"r4") == 0 || + strcmp(s,"r5") == 0 || + strcmp(s,"r6") == 0 || + strcmp(s,"r7") == 0 ) { + char buffer[10]; + sprintf(buffer,"a%s",s); + emitcode("mov","@%s,%s", + aop->aopu.aop_ptr->name,buffer); + } else + emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s); + + break; + + case AOP_STK: + if (strcmp(s,"a") == 0) + emitcode("push","acc"); + else + emitcode("push","%s",s); + + break; + + case AOP_CRY: + /* if bit variable */ + if (!aop->aopu.aop_dir) { + emitcode("clr","a"); + emitcode("rlc","a"); + } else { + if (s == zero) + emitcode("clr","%s",aop->aopu.aop_dir); + else + if (s == one) + emitcode("setb","%s",aop->aopu.aop_dir); + else + if (!strcmp(s,"c")) + emitcode("mov","%s,c",aop->aopu.aop_dir); + else { + lbl = newiTempLabel(NULL); + + if (strcmp(s,"a")) { + MOVA(s); + } + emitcode("cjne","a,#0x01,%05d$",lbl->key+100); + emitcode("","%05d$:",lbl->key+100); + emitcode("cpl","c"); + emitcode("mov","%s,c",aop->aopu.aop_dir); + } + } + break; + + case AOP_STR: + aop->coff = offset; + if (strcmp(aop->aopu.aop_str[offset],s)) + emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s); + break; + + case AOP_ACC: + aop->coff = offset; + if (!offset && (strcmp(s,"acc") == 0)) + break; + + if (strcmp(aop->aopu.aop_str[offset],s)) + emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s); + break; + + default : + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "aopPut got unsupported aop->type"); + exit(0); + } + +} + + +#if 0 +/*-----------------------------------------------------------------*/ +/* pointToEnd :- points to the last byte of the operand */ +/*-----------------------------------------------------------------*/ +static void pointToEnd (asmop *aop) +{ + int count ; + if (!aop) + return ; + + aop->coff = count = (aop->size - 1); + switch (aop->type) { + case AOP_R0 : + case AOP_R1 : + while (count--) + emitcode("inc","%s",aop->aopu.aop_ptr->name); + break; + case AOP_DPTR : + while (count--) + emitcode("inc","dptr"); + break; + } + +} +#endif + +/*-----------------------------------------------------------------*/ +/* reAdjustPreg - points a register back to where it should */ +/*-----------------------------------------------------------------*/ +static void reAdjustPreg (asmop *aop) +{ + int size ; + + aop->coff = 0; + if ((size = aop->size) <= 1) + return ; + size-- ; + switch (aop->type) { + case AOP_R0 : + case AOP_R1 : + while (size--) + emitcode("dec","%s",aop->aopu.aop_ptr->name); + break; + case AOP_DPTR : + while (size--) + emitcode("lcall","__decdptr"); + break; + + } + +} + +#define AOP(op) op->aop +#define AOP_TYPE(op) AOP(op)->type +#define AOP_SIZE(op) AOP(op)->size +#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \ + AOP_TYPE(x) == AOP_R0)) + +#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \ + AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged)) + +#define AOP_INPREG(x) (x && (x->type == AOP_REG && \ + (x->aopu.aop_reg[0] == regWithIdx(R0_IDX) || \ + x->aopu.aop_reg[0] == regWithIdx(R1_IDX) ))) + +/*-----------------------------------------------------------------*/ +/* genNotFloat - generates not for float operations */ +/*-----------------------------------------------------------------*/ +static void genNotFloat (operand *op, operand *res) +{ + int size, offset; + char *l; + symbol *tlbl ; + + /* we will put 127 in the first byte of + the result */ + aopPut(AOP(res),"#127",0); + size = AOP_SIZE(op) - 1; + offset = 1; + + l = aopGet(op->aop,offset++,FALSE,FALSE); + MOVA(l); + + while(size--) { + emitcode("orl","a,%s", + aopGet(op->aop, + offset++,FALSE,FALSE)); + } + tlbl = newiTempLabel(NULL); + + tlbl = newiTempLabel(NULL); + aopPut(res->aop,one,1); + emitcode("jz","%05d$",(tlbl->key+100)); + aopPut(res->aop,zero,1); + emitcode("","%05d$:",(tlbl->key+100)); + + size = res->aop->size - 2; + offset = 2; + /* put zeros in the rest */ + while (size--) + aopPut(res->aop,zero,offset++); +} + +/*-----------------------------------------------------------------*/ +/* getDataSize - get the operand data size */ +/*-----------------------------------------------------------------*/ +int getDataSize(operand *op) +{ + int size; + size = AOP_SIZE(op); + if(size == 3) + /* pointer */ + size--; + return size; +} + +/*-----------------------------------------------------------------*/ +/* outAcc - output Acc */ +/*-----------------------------------------------------------------*/ +void outAcc(operand *result) +{ + int size, offset; + size = getDataSize(result); + if(size){ + aopPut(AOP(result),"a",0); + size--; + offset = 1; + /* unsigned or positive */ + while(size--){ + aopPut(AOP(result),zero,offset++); + } + } +} + +/*-----------------------------------------------------------------*/ +/* outBitC - output a bit C */ +/*-----------------------------------------------------------------*/ +void outBitC(operand *result) +{ + /* if the result is bit */ + if (AOP_TYPE(result) == AOP_CRY) + aopPut(AOP(result),"c",0); + else { + emitcode("clr","a"); + emitcode("rlc","a"); + outAcc(result); + } +} + +/*-----------------------------------------------------------------*/ +/* toBoolean - emit code for orl a,operator(sizeop) */ +/*-----------------------------------------------------------------*/ +void toBoolean(operand *oper) +{ + int size = AOP_SIZE(oper) - 1; + int offset = 1; + MOVA(aopGet(AOP(oper),0,FALSE,FALSE)); + while (size--) + emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE)); +} + + +/*-----------------------------------------------------------------*/ +/* genNot - generate code for ! operation */ +/*-----------------------------------------------------------------*/ +static void genNot (iCode *ic) +{ + symbol *tlbl; + link *optype = operandType(IC_LEFT(ic)); + + /* assign asmOps to operand & result */ + aopOp (IC_LEFT(ic),ic,FALSE); + aopOp (IC_RESULT(ic),ic,TRUE); + + /* if in bit space then a special case */ + if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) { + emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); + emitcode("cpl","c"); + outBitC(IC_RESULT(ic)); + goto release; + } + + /* if type float then do float */ + if (IS_FLOAT(optype)) { + genNotFloat(IC_LEFT(ic),IC_RESULT(ic)); + goto release; + } + + toBoolean(IC_LEFT(ic)); + + tlbl = newiTempLabel(NULL); + emitcode("cjne","a,#0x01,%05d$",tlbl->key+100); + emitcode("","%05d$:",tlbl->key+100); + outBitC(IC_RESULT(ic)); + +release: + /* release the aops */ + freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + + +/*-----------------------------------------------------------------*/ +/* genCpl - generate code for complement */ +/*-----------------------------------------------------------------*/ +static void genCpl (iCode *ic) +{ + int offset = 0; + int size ; + + + /* assign asmOps to operand & result */ + aopOp (IC_LEFT(ic),ic,FALSE); + aopOp (IC_RESULT(ic),ic,TRUE); + + /* if both are in bit space then + a special case */ + if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && + AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { + + emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); + emitcode("cpl","c"); + emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); + goto release; + } + + size = AOP_SIZE(IC_RESULT(ic)); + while (size--) { + char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE); + MOVA(l); + emitcode("cpl","a"); + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + + +release: + /* release the aops */ + freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genUminusFloat - unary minus for floating points */ +/*-----------------------------------------------------------------*/ +static void genUminusFloat(operand *op,operand *result) +{ + int size ,offset =0 ; + char *l; + /* for this we just need to flip the + first it then copy the rest in place */ + size = AOP_SIZE(op) - 1; + l = aopGet(AOP(op),3,FALSE,FALSE); + + MOVA(l); + + emitcode("cpl","acc.7"); + aopPut(AOP(result),"a",3); + + while(size--) { + aopPut(AOP(result), + aopGet(AOP(op),offset,FALSE,FALSE), + offset); + offset++; + } +} + +/*-----------------------------------------------------------------*/ +/* genUminus - unary minus code generation */ +/*-----------------------------------------------------------------*/ +static void genUminus (iCode *ic) +{ + int offset ,size ; + link *optype, *rtype; + + + /* assign asmops */ + aopOp(IC_LEFT(ic),ic,FALSE); + aopOp(IC_RESULT(ic),ic,TRUE); + + /* if both in bit space then special + case */ + if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && + AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { + + emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); + emitcode("cpl","c"); + emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); + goto release; + } + + optype = operandType(IC_LEFT(ic)); + rtype = operandType(IC_RESULT(ic)); + + /* if float then do float stuff */ + if (IS_FLOAT(optype)) { + genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); + goto release; + } + + /* otherwise subtract from zero */ + size = AOP_SIZE(IC_LEFT(ic)); + offset = 0 ; + CLRC ; + while(size--) { + char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE); + if (!strcmp(l,"a")) { + emitcode("cpl","a"); + emitcode("inc","a"); + } else { + emitcode("clr","a"); + emitcode("subb","a,%s",l); + } + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + + /* if any remaining bytes in the result */ + /* we just need to propagate the sign */ + if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) { + emitcode("rlc","a"); + emitcode("subb","a,acc"); + while (size--) + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + +release: + /* release the aops */ + freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* saveRegisters - will look for a call and save the registers */ +/*-----------------------------------------------------------------*/ +static void saveRegisters(iCode *lic) +{ + int i; + iCode *ic; + bitVect *rsave; + link *detype; + + /* look for call */ + for (ic = lic ; ic ; ic = ic->next) + if (ic->op == CALL || ic->op == PCALL) + break; + + if (!ic) { + fprintf(stderr,"found parameter push with no function call\n"); + return ; + } + + /* if the registers have been saved already then + do nothing */ + if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave)) + return ; + + /* find the registers in use at this time + and push them away to safety */ + rsave = bitVectCplAnd(bitVectCopy(ic->rMask), + ic->rUsed); + + ic->regsSaved = 1; + if (options.useXstack) { + if (bitVectBitValue(rsave,R0_IDX)) + emitcode("mov","b,r0"); + emitcode("mov","r0,%s",spname); + for (i = 0 ; i < nRegs ; i++) { + if (bitVectBitValue(rsave,i)) { + if (i == R0_IDX) + emitcode("mov","a,b"); + else + emitcode("mov","a,%s",regWithIdx(i)->name); + emitcode("movx","@r0,a"); + emitcode("inc","r0"); + } + } + emitcode("mov","%s,r0",spname); + if (bitVectBitValue(rsave,R0_IDX)) + emitcode("mov","r0,b"); + } else + for (i = 0 ; i < nRegs ; i++) { + if (bitVectBitValue(rsave,i)) + emitcode("push","%s",regWithIdx(i)->dname); + } + + detype = getSpec(operandType(IC_LEFT(ic))); + if (detype && + (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) && + IS_ISR(currFunc->etype) && + !ic->bankSaved) + + saverbank(SPEC_BANK(detype),ic,TRUE); + +} +/*-----------------------------------------------------------------*/ +/* unsaveRegisters - pop the pushed registers */ +/*-----------------------------------------------------------------*/ +static void unsaveRegisters (iCode *ic) +{ + int i; + bitVect *rsave; + /* find the registers in use at this time + and push them away to safety */ + rsave = bitVectCplAnd(bitVectCopy(ic->rMask), + ic->rUsed); + + if (options.useXstack) { + emitcode("mov","r0,%s",spname); + for (i = nRegs ; i >= 0 ; i--) { + if (bitVectBitValue(rsave,i)) { + emitcode("dec","r0"); + emitcode("movx","a,@r0"); + if (i == R0_IDX) + emitcode("mov","b,a"); + else + emitcode("mov","%s,a",regWithIdx(i)->name); + } + + } + emitcode("mov","%s,r0",spname); + if (bitVectBitValue(rsave,R0_IDX)) + emitcode("mov","r0,b"); + } else + for (i = nRegs ; i >= 0 ; i--) { + if (bitVectBitValue(rsave,i)) + emitcode("pop","%s",regWithIdx(i)->dname); + } + +} + + +/*-----------------------------------------------------------------*/ +/* pushSide - */ +/*-----------------------------------------------------------------*/ +void pushSide(operand * oper, int size) +{ + int offset = 0; + while (size--) { + char *l = aopGet(AOP(oper),offset++,FALSE,TRUE); + if (AOP_TYPE(oper) != AOP_REG && + AOP_TYPE(oper) != AOP_DIR && + strcmp(l,"a") ) { + emitcode("mov","a,%s",l); + emitcode("push","acc"); + } else + emitcode("push","%s",l); + } +} + +/*-----------------------------------------------------------------*/ +/* assignResultValue - */ +/*-----------------------------------------------------------------*/ +void assignResultValue(operand * oper) +{ + int offset = 0; + int size = AOP_SIZE(oper); + while (size--) { + aopPut(AOP(oper),fReturn[offset],offset); + offset++; + } +} + + +/*-----------------------------------------------------------------*/ +/* genXpush - pushes onto the external stack */ +/*-----------------------------------------------------------------*/ +static void genXpush (iCode *ic) +{ + asmop *aop = newAsmop(0); + regs *r ; + int size,offset = 0; + + aopOp(IC_LEFT(ic),ic,FALSE); + r = getFreePtr(ic,&aop,FALSE); + + + emitcode("mov","%s,_spx",r->name); + + size = AOP_SIZE(IC_LEFT(ic)); + while(size--) { + + char *l = aopGet(AOP(IC_LEFT(ic)), + offset++,FALSE,FALSE); + MOVA(l); + emitcode("movx","@%s,a",r->name); + emitcode("inc","%s",r->name); + + } + + + emitcode("mov","_spx,%s",r->name); + + freeAsmop(NULL,aop,ic,TRUE); + freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genIpush - genrate code for pushing this gets a little complex */ +/*-----------------------------------------------------------------*/ +static void genIpush (iCode *ic) +{ + int size, offset = 0 ; + char *l; + + + /* if this is not a parm push : ie. it is spill push + and spill push is always done on the local stack */ + if (!ic->parmPush) { + + /* and the item is spilt then do nothing */ + if (OP_SYMBOL(IC_LEFT(ic))->isspilt) + return ; + + aopOp(IC_LEFT(ic),ic,FALSE); + size = AOP_SIZE(IC_LEFT(ic)); + /* push it on the stack */ + while(size--) { + l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE); + if (*l == '#') { + MOVA(l); + l = "acc"; + } + emitcode("push","%s",l); + } + return ; + } + + /* this is a paramter push: in this case we call + the routine to find the call and save those + registers that need to be saved */ + saveRegisters(ic); + + /* if use external stack then call the external + stack pushing routine */ + if (options.useXstack) { + genXpush(ic); + return ; + } + + /* then do the push */ + aopOp(IC_LEFT(ic),ic,FALSE); + + + // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic))); + size = AOP_SIZE(IC_LEFT(ic)); + + while (size--) { + l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE); + if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && + AOP_TYPE(IC_LEFT(ic)) != AOP_DIR && + strcmp(l,"a") ) { + emitcode("mov","a,%s",l); + emitcode("push","acc"); + } else + emitcode("push","%s",l); + } + + freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genIpop - recover the registers: can happen only for spilling */ +/*-----------------------------------------------------------------*/ +static void genIpop (iCode *ic) +{ + int size,offset ; + + + /* if the temp was not pushed then */ + if (OP_SYMBOL(IC_LEFT(ic))->isspilt) + return ; + + aopOp(IC_LEFT(ic),ic,FALSE); + size = AOP_SIZE(IC_LEFT(ic)); + offset = (size-1); + while (size--) + emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--, + FALSE,TRUE)); + + freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* unsaverbank - restores the resgister bank from stack */ +/*-----------------------------------------------------------------*/ +static void unsaverbank (int bank,iCode *ic,bool popPsw) +{ + int i; + asmop *aop ; + regs *r = NULL; + + if (popPsw) { + if (options.useXstack) { + aop = newAsmop(0); + r = getFreePtr(ic,&aop,FALSE); + + + emitcode("mov","%s,_spx",r->name); + emitcode("movx","a,@%s",r->name); + emitcode("mov","psw,a"); + emitcode("dec","%s",r->name); + + }else + emitcode ("pop","psw"); + } + + for (i = (nRegs - 1) ; i >= 0 ;i--) { + if (options.useXstack) { + emitcode("movx","a,@%s",r->name); + emitcode("mov","(%s+%d),a", + regs8051[i].base,8*bank+regs8051[i].offset); + emitcode("dec","%s",r->name); + + } else + emitcode("pop","(%s+%d)", + regs8051[i].base,8*bank+regs8051[i].offset); + } + + if (options.useXstack) { + + emitcode("mov","_spx,%s",r->name); + freeAsmop(NULL,aop,ic,TRUE); + + } +} + +/*-----------------------------------------------------------------*/ +/* saverbank - saves an entire register bank on the stack */ +/*-----------------------------------------------------------------*/ +static void saverbank (int bank, iCode *ic, bool pushPsw) +{ + int i; + asmop *aop ; + regs *r = NULL; + + if (options.useXstack) { + + aop = newAsmop(0); + r = getFreePtr(ic,&aop,FALSE); + emitcode("mov","%s,_spx",r->name); + + } + + for (i = 0 ; i < nRegs ;i++) { + if (options.useXstack) { + emitcode("inc","%s",r->name); + emitcode("mov","a,(%s+%d)", + regs8051[i].base,8*bank+regs8051[i].offset); + emitcode("movx","@%s,a",r->name); + } else + emitcode("push","(%s+%d)", + regs8051[i].base,8*bank+regs8051[i].offset); + } + + if (pushPsw) { + if (options.useXstack) { + emitcode("mov","a,psw"); + emitcode("movx","@%s,a",r->name); + emitcode("inc","%s",r->name); + emitcode("mov","_spx,%s",r->name); + freeAsmop (NULL,aop,ic,TRUE); + + } else + emitcode("push","psw"); + + emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff); + } + ic->bankSaved = 1; + +} + +/*-----------------------------------------------------------------*/ +/* genCall - generates a call statement */ +/*-----------------------------------------------------------------*/ +static void genCall (iCode *ic) +{ + link *detype; + + /* if caller saves & we have not saved then */ + if (!ic->regsSaved) + saveRegisters(ic); + + /* if we are calling a function that is not using + the same register bank then we need to save the + destination registers on the stack */ + detype = getSpec(operandType(IC_LEFT(ic))); + if (detype && + (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) && + IS_ISR(currFunc->etype) && + !ic->bankSaved) + + saverbank(SPEC_BANK(detype),ic,TRUE); + + /* if send set is not empty the assign */ + if (sendSet) { + iCode *sic ; + + for (sic = setFirstItem(sendSet) ; sic ; + sic = setNextItem(sendSet)) { + int size, offset = 0; + aopOp(IC_LEFT(sic),sic,FALSE); + size = AOP_SIZE(IC_LEFT(sic)); + while (size--) { + char *l = aopGet(AOP(IC_LEFT(sic)),offset, + FALSE,FALSE); + if (strcmp(l,fReturn[offset])) + emitcode("mov","%s,%s", + fReturn[offset], + l); + offset++; + } + freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); + } + sendSet = NULL; + } + /* make the call */ + emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ? + OP_SYMBOL(IC_LEFT(ic))->rname : + OP_SYMBOL(IC_LEFT(ic))->name)); + + /* if we need assign a result value */ + if ((IS_ITEMP(IC_RESULT(ic)) && + (OP_SYMBOL(IC_RESULT(ic))->nRegs || + OP_SYMBOL(IC_RESULT(ic))->spildir )) || + IS_TRUE_SYMOP(IC_RESULT(ic)) ) { + + accInUse++; + aopOp(IC_RESULT(ic),ic,FALSE); + accInUse--; + + assignResultValue(IC_RESULT(ic)); + + freeAsmop(IC_RESULT(ic),NULL, ic,TRUE); + } + + /* adjust the stack for parameters if + required */ + if (IC_LEFT(ic)->parmBytes) { + int i; + if (IC_LEFT(ic)->parmBytes > 3) { + emitcode("mov","a,%s",spname); + emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff); + emitcode("mov","%s,a",spname); + } else + for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++) + emitcode("dec","%s",spname); + + } + + /* if register bank was saved then pop them */ + if (ic->bankSaved) + unsaverbank(SPEC_BANK(detype),ic,TRUE); + + /* if we hade saved some registers then unsave them */ + if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave)) + unsaveRegisters (ic); + + +} + +/*-----------------------------------------------------------------*/ +/* genPcall - generates a call by pointer statement */ +/*-----------------------------------------------------------------*/ +static void genPcall (iCode *ic) +{ + link *detype; + symbol *rlbl = newiTempLabel(NULL); + + + /* if caller saves & we have not saved then */ + if (!ic->regsSaved) + saveRegisters(ic); + + /* if we are calling a function that is not using + the same register bank then we need to save the + destination registers on the stack */ + detype = getSpec(operandType(IC_LEFT(ic))); + if (detype && + IS_ISR(currFunc->etype) && + (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype))) + saverbank(SPEC_BANK(detype),ic,TRUE); + + + /* push the return address on to the stack */ + emitcode("mov","a,#%05d$",(rlbl->key+100)); + emitcode("push","acc"); + emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100)); + emitcode("push","acc"); + + /* now push the calling address */ + aopOp(IC_LEFT(ic),ic,FALSE); + + pushSide(IC_LEFT(ic), 2); + + freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); + + /* if send set is not empty the assign */ + if (sendSet) { + iCode *sic ; + + for (sic = setFirstItem(sendSet) ; sic ; + sic = setNextItem(sendSet)) { + int size, offset = 0; + aopOp(IC_LEFT(sic),sic,FALSE); + size = AOP_SIZE(IC_LEFT(sic)); + while (size--) { + char *l = aopGet(AOP(IC_LEFT(sic)),offset, + FALSE,FALSE); + if (strcmp(l,fReturn[offset])) + emitcode("mov","%s,%s", + fReturn[offset], + l); + offset++; + } + freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); + } + sendSet = NULL; + } + + emitcode("ret",""); + emitcode("","%05d$:",(rlbl->key+100)); + + + /* if we need assign a result value */ + if ((IS_ITEMP(IC_RESULT(ic)) && + (OP_SYMBOL(IC_RESULT(ic))->nRegs || + OP_SYMBOL(IC_RESULT(ic))->spildir)) || + IS_TRUE_SYMOP(IC_RESULT(ic)) ) { + + accInUse++; + aopOp(IC_RESULT(ic),ic,FALSE); + accInUse--; + + assignResultValue(IC_RESULT(ic)); + + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + } + + /* adjust the stack for parameters if + required */ + if (IC_LEFT(ic)->parmBytes) { + int i; + if (IC_LEFT(ic)->parmBytes > 3) { + emitcode("mov","a,%s",spname); + emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff); + emitcode("mov","%s,a",spname); + } else + for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++) + emitcode("dec","%s",spname); + + } + + /* if register bank was saved then unsave them */ + if (detype && + (SPEC_BANK(currFunc->etype) != + SPEC_BANK(detype))) + unsaverbank(SPEC_BANK(detype),ic,TRUE); + + /* if we hade saved some registers then + unsave them */ + if (ic->regsSaved) + unsaveRegisters (ic); + +} + +/*-----------------------------------------------------------------*/ +/* resultRemat - result is rematerializable */ +/*-----------------------------------------------------------------*/ +static int resultRemat (iCode *ic) +{ + if (SKIP_IC(ic) || ic->op == IFX) + return 0; + + if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) { + symbol *sym = OP_SYMBOL(IC_RESULT(ic)); + if (sym->remat && !POINTER_SET(ic)) + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* inExcludeList - return 1 if the string is in exclude Reg list */ +/*-----------------------------------------------------------------*/ +static bool inExcludeList(char *s) +{ + int i =0; + + if (options.excludeRegs[i] && + strcasecmp(options.excludeRegs[i],"none") == 0) + return FALSE ; + + for ( i = 0 ; options.excludeRegs[i]; i++) { + if (options.excludeRegs[i] && + strcasecmp(s,options.excludeRegs[i]) == 0) + return TRUE; + } + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* genFunction - generated code for function entry */ +/*-----------------------------------------------------------------*/ +static void genFunction (iCode *ic) +{ + symbol *sym; + link *fetype; + + nregssaved = 0; + /* create the function header */ + emitcode(";","-----------------------------------------"); + emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name); + emitcode(";","-----------------------------------------"); + + emitcode("","%s:",sym->rname); + fetype = getSpec(operandType(IC_LEFT(ic))); + + /* if critical function then turn interrupts off */ + if (SPEC_CRTCL(fetype)) + emitcode("clr","ea"); + + /* here we need to generate the equates for the + register bank if required */ + if (SPEC_BANK(fetype) != rbank) { + int i ; + + rbank = SPEC_BANK(fetype); + for ( i = 0 ; i < nRegs ; i++ ) { + if (strcmp(regs8051[i].base,"0") == 0) + emitcode("","%s = 0x%02x", + regs8051[i].dname, + 8*rbank+regs8051[i].offset); + else + emitcode ("","%s = %s + 0x%02x", + regs8051[i].dname, + regs8051[i].base, + 8*rbank+regs8051[i].offset); + } + } + + /* if this is an interrupt service routine then + save acc, b, dpl, dph */ + if (IS_ISR(sym->etype)) { + + if (!inExcludeList("acc")) + emitcode ("push","acc"); + if (!inExcludeList("b")) + emitcode ("push","b"); + if (!inExcludeList("dpl")) + emitcode ("push","dpl"); + if (!inExcludeList("dph")) + emitcode ("push","dph"); + + /* if this isr has no bank i.e. is going to + run with bank 0 , then we need to save more + registers :-) */ + if (!SPEC_BANK(sym->etype)) { + + /* if this function does not call any other + function then we can be economical and + save only those registers that are used */ + if (! sym->hasFcall) { + int i; + + /* if any registers used */ + if (sym->regsUsed) { + /* save the registers used */ + for ( i = 0 ; i < sym->regsUsed->size ; i++) { + if (bitVectBitValue(sym->regsUsed,i) || + (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) + emitcode("push","%s",regWithIdx(i)->dname); + } + } + + } else { + /* this function has a function call cannot + determines register usage so we will have the + entire bank */ + saverbank(0,ic,FALSE); + } + } + } else { + /* if callee-save to be used for this function + then save the registers being used in this function */ + if (sym->calleeSave) { + int i; + + /* if any registers used */ + if (sym->regsUsed) { + /* save the registers used */ + for ( i = 0 ; i < sym->regsUsed->size ; i++) { + if (bitVectBitValue(sym->regsUsed,i) || + (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) { + emitcode("push","%s",regWithIdx(i)->dname); + nregssaved++; + } + } + } + } + } + + /* set the register bank to the desired value */ + if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) { + emitcode("push","psw"); + emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff); + } + + if (IS_RENT(sym->etype) || options.stackAuto) { + + if (options.useXstack) { + emitcode("mov","r0,%s",spname); + emitcode("mov","a,_bp"); + emitcode("movx","@r0,a"); + emitcode("inc","%s",spname); + } + else + /* set up the stack */ + emitcode ("push","_bp"); /* save the callers stack */ + emitcode ("mov","_bp,%s",spname); + } + + /* adjust the stack for the function */ + if (sym->stack) { + + int i = sym->stack; + if (i > 256 ) + werror(W_STACK_OVERFLOW,sym->name); + + if (i > 3 && sym->recvSize < 4) { + + emitcode ("mov","a,sp"); + emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff)); + emitcode ("mov","sp,a"); + + } + else + while(i--) + emitcode("inc","sp"); + } + + if (sym->xstack) { + + emitcode ("mov","a,_spx"); + emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff)); + emitcode ("mov","_spx,a"); + } + +} + +/*-----------------------------------------------------------------*/ +/* genEndFunction - generates epilogue for functions */ +/*-----------------------------------------------------------------*/ +static void genEndFunction (iCode *ic) +{ + symbol *sym = OP_SYMBOL(IC_LEFT(ic)); + + if (IS_RENT(sym->etype) || options.stackAuto) + emitcode ("mov","%s,_bp",spname); + + /* if use external stack but some variables were + added to the local stack then decrement the + local stack */ + if (options.useXstack && sym->stack) { + emitcode("mov","a,sp"); + emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff); + emitcode("mov","sp,a"); + } + + + if ((IS_RENT(sym->etype) || options.stackAuto)) { + if (options.useXstack) { + emitcode("mov","r0,%s",spname); + emitcode("movx","a,@r0"); + emitcode("mov","_bp,a"); + emitcode("dec","%s",spname); + } + else + emitcode ("pop","_bp"); + } + + /* restore the register bank */ + if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) + emitcode ("pop","psw"); + + if (IS_ISR(sym->etype)) { + + /* now we need to restore the registers */ + /* if this isr has no bank i.e. is going to + run with bank 0 , then we need to save more + registers :-) */ + if (!SPEC_BANK(sym->etype)) { + + /* if this function does not call any other + function then we can be economical and + save only those registers that are used */ + if (! sym->hasFcall) { + int i; + + /* if any registers used */ + if (sym->regsUsed) { + /* save the registers used */ + for ( i = sym->regsUsed->size ; i >= 0 ; i--) { + if (bitVectBitValue(sym->regsUsed,i) || + (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) + emitcode("pop","%s",regWithIdx(i)->dname); + } + } + + } else { + /* this function has a function call cannot + determines register usage so we will have the + entire bank */ + unsaverbank(0,ic,FALSE); + } + } + + if (!inExcludeList("dph")) + emitcode ("pop","dph"); + if (!inExcludeList("dpl")) + emitcode ("pop","dpl"); + if (!inExcludeList("b")) + emitcode ("pop","b"); + if (!inExcludeList("acc")) + emitcode ("pop","acc"); + + if (SPEC_CRTCL(sym->etype)) + emitcode("setb","ea"); + + /* if debug then send end of function */ +/* if (options.debug && currFunc) { */ + if (currFunc) { + debugLine = 1; + emitcode("","C$%s$%d$%d$%d ==.", + ic->filename,currFunc->lastLine, + ic->level,ic->block); + if (IS_STATIC(currFunc->etype)) + emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); + else + emitcode("","XG$%s$0$0 ==.",currFunc->name); + debugLine = 0; + } + + emitcode ("reti",""); + } + else { + if (SPEC_CRTCL(sym->etype)) + emitcode("setb","ea"); + + if (sym->calleeSave) { + int i; + + /* if any registers used */ + if (sym->regsUsed) { + /* save the registers used */ + for ( i = sym->regsUsed->size ; i >= 0 ; i--) { + if (bitVectBitValue(sym->regsUsed,i) || + (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) + emitcode("pop","%s",regWithIdx(i)->dname); + } + } + + } + + /* if debug then send end of function */ +/* if (options.debug && currFunc) { */ + if (currFunc) { + debugLine = 1; + emitcode("","C$%s$%d$%d$%d ==.", + ic->filename,currFunc->lastLine, + ic->level,ic->block); + if (IS_STATIC(currFunc->etype)) + emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); + else + emitcode("","XG$%s$0$0 ==.",currFunc->name); + debugLine = 0; + } + + emitcode ("ret",""); + } + +} + +/*-----------------------------------------------------------------*/ +/* genRet - generate code for return statement */ +/*-----------------------------------------------------------------*/ +static void genRet (iCode *ic) +{ + int size,offset = 0 , pushed = 0; + + /* if we have no return value then + just generate the "ret" */ + if (!IC_LEFT(ic)) + goto jumpret; + + /* we have something to return then + move the return value into place */ + aopOp(IC_LEFT(ic),ic,FALSE); + size = AOP_SIZE(IC_LEFT(ic)); + + while (size--) { + char *l ; + if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) { + l = aopGet(AOP(IC_LEFT(ic)),offset++, + FALSE,TRUE); + emitcode("push","%s",l); + pushed++; + } else { + l = aopGet(AOP(IC_LEFT(ic)),offset, + FALSE,FALSE); + if (strcmp(fReturn[offset],l)) + emitcode("mov","%s,%s",fReturn[offset++],l); + } + } + + if (pushed) { + while(pushed) { + pushed--; + if (strcmp(fReturn[pushed],"a")) + emitcode("pop",fReturn[pushed]); + else + emitcode("pop","acc"); + } + } + freeAsmop (IC_LEFT(ic),NULL,ic,TRUE); + + jumpret: + /* generate a jump to the return label + if the next is not the return statement */ + if (!(ic->next && ic->next->op == LABEL && + IC_LABEL(ic->next) == returnLabel)) + + emitcode("ljmp","%05d$",(returnLabel->key+100)); + +} + +/*-----------------------------------------------------------------*/ +/* genLabel - generates a label */ +/*-----------------------------------------------------------------*/ +static void genLabel (iCode *ic) +{ + /* special case never generate */ + if (IC_LABEL(ic) == entryLabel) + return ; + + emitcode("","%05d$:",(IC_LABEL(ic)->key+100)); +} + +/*-----------------------------------------------------------------*/ +/* genGoto - generates a ljmp */ +/*-----------------------------------------------------------------*/ +static void genGoto (iCode *ic) +{ + emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100)); +} + +/*-----------------------------------------------------------------*/ +/* genPlusIncr :- does addition with increment if possible */ +/*-----------------------------------------------------------------*/ +static bool genPlusIncr (iCode *ic) +{ + unsigned int icount ; + unsigned int size = getDataSize(IC_RESULT(ic)); + + /* will try to generate an increment */ + /* if the right side is not a literal + we cannot */ + if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) + return FALSE ; + + /* if the literal value of the right hand side + is greater than 4 then it is not worth it */ + if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4) + return FALSE ; + + /* if increment 16 bits in register */ + if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && + (size > 1) && + (icount == 1)) { + symbol *tlbl = newiTempLabel(NULL); + emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)); + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0x00,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE) + ,tlbl->key+100); + else { + emitcode("clr","a"); + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE) + ,tlbl->key+100); + } + + emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)); + if(size == 4){ + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0x00,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE) + ,tlbl->key+100); + else + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE) + ,tlbl->key+100); + + emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)); + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0x00,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE) + ,tlbl->key+100); + else{ + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE) + ,tlbl->key+100); + } + emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE)); + } + emitcode("","%05d$:",tlbl->key+100); + return TRUE; + } + + /* if the sizes are greater than 1 then we cannot */ + if (AOP_SIZE(IC_RESULT(ic)) > 1 || + AOP_SIZE(IC_LEFT(ic)) > 1 ) + return FALSE ; + + /* we can if the aops of the left & result match or + if they are in registers and the registers are the + same */ + if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { + + if (icount > 3) { + MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); + emitcode("add","a,#0x%02x",((char) icount) & 0xff); + aopPut(AOP(IC_RESULT(ic)),"a",0); + } else { + + while (icount--) + emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); + } + + return TRUE ; + } + + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* outBitAcc - output a bit in acc */ +/*-----------------------------------------------------------------*/ +void outBitAcc(operand *result) +{ + symbol *tlbl = newiTempLabel(NULL); + /* if the result is a bit */ + if (AOP_TYPE(result) == AOP_CRY){ + aopPut(AOP(result),"a",0); + } + else { + emitcode("jz","%05d$",tlbl->key+100); + emitcode("mov","a,%s",one); + emitcode("","%05d$:",tlbl->key+100); + outAcc(result); + } +} + +/*-----------------------------------------------------------------*/ +/* genPlusBits - generates code for addition of two bits */ +/*-----------------------------------------------------------------*/ +static void genPlusBits (iCode *ic) +{ + if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){ + symbol *lbl = newiTempLabel(NULL); + emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir); + emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100)); + emitcode("cpl","c"); + emitcode("","%05d$:",(lbl->key+100)); + outBitC(IC_RESULT(ic)); + } + else{ + emitcode("clr","a"); + emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir); + emitcode("rlc","a"); + emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir); + emitcode("addc","a,#0x00"); + outAcc(IC_RESULT(ic)); + } +} + +/*-----------------------------------------------------------------*/ +/* genPlus - generates code for addition */ +/*-----------------------------------------------------------------*/ +static void genPlus (iCode *ic) +{ + int size, offset = 0; + + /* special cases :- */ + + aopOp (IC_LEFT(ic),ic,FALSE); + aopOp (IC_RIGHT(ic),ic,FALSE); + aopOp (IC_RESULT(ic),ic,TRUE); + + /* if literal, literal on the right or + if left requires ACC or right is already + in ACC */ + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || + (AOP_NEEDSACC(IC_LEFT(ic))) || + AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){ + operand *t = IC_RIGHT(ic); + IC_RIGHT(ic) = IC_LEFT(ic); + IC_LEFT(ic) = t; + } + + /* if both left & right are in bit + space */ + if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && + AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { + genPlusBits (ic); + goto release ; + } + + /* if left in bit space & right literal */ + if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && + AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) { + emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir); + /* if result in bit space */ + if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){ + if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) + emitcode("cpl","c"); + outBitC(IC_RESULT(ic)); + } else { + size = getDataSize(IC_RESULT(ic)); + while (size--) { + MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); + emitcode("addc","a,#00"); + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + } + goto release ; + } + + /* if I can do an increment instead + of add then GOOD for ME */ + if (genPlusIncr (ic) == TRUE) + goto release; + + size = getDataSize(IC_RESULT(ic)); + + while(size--){ + if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) { + MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE)); + if(offset == 0) + emitcode("add","a,%s", + aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); + else + emitcode("addc","a,%s", + aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); + } else { + MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); + if(offset == 0) + emitcode("add","a,%s", + aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE)); + else + emitcode("addc","a,%s", + aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE)); + } + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_LEFT(ic)) == 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)))) + aopPut(AOP(IC_RESULT(ic)), + aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE), + 2); + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_RIGHT(ic)) == 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) + aopPut(AOP(IC_RESULT(ic)), + aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE), + 2); + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_LEFT(ic)) < 3 && + AOP_SIZE(IC_RIGHT(ic)) < 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) { + char buffer[5]; + sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic))))); + aopPut(AOP(IC_RESULT(ic)),buffer,2); + } +release: + freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genMinusDec :- does subtraction with deccrement if possible */ +/*-----------------------------------------------------------------*/ +static bool genMinusDec (iCode *ic) +{ + unsigned int icount ; + unsigned int size = getDataSize(IC_RESULT(ic)); + + /* will try to generate an increment */ + /* if the right side is not a literal + we cannot */ + if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) + return FALSE ; + + /* if the literal value of the right hand side + is greater than 4 then it is not worth it */ + if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4) + return FALSE ; + + size = getDataSize(IC_RESULT(ic)); + /* if decrement 16 bits in register */ + if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && + (size > 1) && + (icount == 1)) { + symbol *tlbl = newiTempLabel(NULL); + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)); + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0xff,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE) + ,tlbl->key+100); + else{ + emitcode("mov","a,#0xff"); + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE) + ,tlbl->key+100); + } + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)); + if(size == 4){ + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0xff,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE) + ,tlbl->key+100); + else{ + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE) + ,tlbl->key+100); + } + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)); + if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG || + IS_AOP_PREG(IC_RESULT(ic))) + emitcode("cjne","%s,#0xff,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE) + ,tlbl->key+100); + else{ + emitcode("cjne","a,%s,%05d$" + ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE) + ,tlbl->key+100); + } + emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE)); + } + emitcode("","%05d$:",tlbl->key+100); + return TRUE; + } + + /* if the sizes are greater than 1 then we cannot */ + if (AOP_SIZE(IC_RESULT(ic)) > 1 || + AOP_SIZE(IC_LEFT(ic)) > 1 ) + return FALSE ; + + /* we can if the aops of the left & result match or + if they are in registers and the registers are the + same */ + if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) { + + while (icount--) + emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + + return TRUE ; + } + + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* addSign - complete with sign */ +/*-----------------------------------------------------------------*/ +static void addSign(operand *result, int offset, int sign) +{ + int size = (getDataSize(result) - offset); + if(size > 0){ + if(sign){ + emitcode("rlc","a"); + emitcode("subb","a,acc"); + while(size--) + aopPut(AOP(result),"a",offset++); + } else + while(size--) + aopPut(AOP(result),zero,offset++); + } +} + +/*-----------------------------------------------------------------*/ +/* genMinusBits - generates code for subtraction of two bits */ +/*-----------------------------------------------------------------*/ +static void genMinusBits (iCode *ic) +{ + symbol *lbl = newiTempLabel(NULL); + if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){ + emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir); + emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100)); + emitcode("cpl","c"); + emitcode("","%05d$:",(lbl->key+100)); + outBitC(IC_RESULT(ic)); + } + else{ + emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir); + emitcode("subb","a,acc"); + emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100)); + emitcode("inc","a"); + emitcode("","%05d$:",(lbl->key+100)); + aopPut(AOP(IC_RESULT(ic)),"a",0); + addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic))))); + } +} + +/*-----------------------------------------------------------------*/ +/* genMinus - generates code for subtraction */ +/*-----------------------------------------------------------------*/ +static void genMinus (iCode *ic) +{ + int size, offset = 0; + unsigned long lit = 0L; + + aopOp (IC_LEFT(ic),ic,FALSE); + aopOp (IC_RIGHT(ic),ic,FALSE); + aopOp (IC_RESULT(ic),ic,TRUE); + + /* special cases :- */ + /* if both left & right are in bit space */ + if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY && + AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { + genMinusBits (ic); + goto release ; + } + + /* if I can do an decrement instead + of subtract then GOOD for ME */ + if (genMinusDec (ic) == TRUE) + goto release; + + size = getDataSize(IC_RESULT(ic)); + + if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){ + CLRC; + } + else{ + lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + lit = - (long)lit; + } + + /* if literal, add a,#-lit, else normal subb */ + while (size--) { + MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE)); + if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) + emitcode("subb","a,%s", + aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); + else{ + /* first add without previous c */ + if(!offset) + emitcode("add","a,#0x%02x", + (unsigned int)(lit & 0x0FFL)); + else + emitcode("addc","a,#0x%02x", + (unsigned int)((lit >> (offset*8)) & 0x0FFL)); + } + aopPut(AOP(IC_RESULT(ic)),"a",offset++); + } + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_LEFT(ic)) == 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic)))) + aopPut(AOP(IC_RESULT(ic)), + aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE), + 2); + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_RIGHT(ic)) == 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) + aopPut(AOP(IC_RESULT(ic)), + aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE), + 2); + + if (AOP_SIZE(IC_RESULT(ic)) == 3 && + AOP_SIZE(IC_LEFT(ic)) < 3 && + AOP_SIZE(IC_RIGHT(ic)) < 3 && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) && + !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) { + char buffer[5]; + sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic))))); + aopPut(AOP(IC_RESULT(ic)),buffer,2); + } +release: + freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + + +/*-----------------------------------------------------------------*/ +/* genMultbits :- multiplication of bits */ +/*-----------------------------------------------------------------*/ +static void genMultbits (operand *left, + operand *right, + operand *result) +{ + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); + outBitC(result); +} + + +/*-----------------------------------------------------------------*/ +/* genMultOneByte : 8 bit multiplication & division */ +/*-----------------------------------------------------------------*/ +static void genMultOneByte (operand *left, + operand *right, + operand *result) +{ + link *opetype = operandType(result); + char *l ; + symbol *lbl ; + int size,offset; + + /* (if two literals, the value is computed before) */ + /* if one literal, literal on the right */ + if (AOP_TYPE(left) == AOP_LIT){ + operand *t = right; + right = left; + left = t; + } + + size = AOP_SIZE(result); + /* signed or unsigned */ + emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE)); + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("mul","ab"); + /* if result size = 1, mul signed = mul unsigned */ + aopPut(AOP(result),"a",0); + if (size > 1){ + if (SPEC_USIGN(opetype)){ + aopPut(AOP(result),"b",1); + if (size > 2) + /* for filling the MSBs */ + emitcode("clr","a"); + } + else{ + emitcode("mov","a,b"); + + /* adjust the MSB if left or right neg */ + + /* if one literal */ + if (AOP_TYPE(right) == AOP_LIT){ + /* AND literal negative */ + if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){ + /* adjust MSB (c==0 after mul) */ + emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE)); + } + } + else{ + lbl = newiTempLabel(NULL); + emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("cjne","a,#0x80,%05d$", (lbl->key+100)); + emitcode("","%05d$:",(lbl->key+100)); + emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE)); + lbl = newiTempLabel(NULL); + emitcode("jc","%05d$",(lbl->key+100)); + emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE)); + emitcode("","%05d$:",(lbl->key+100)); + } + + lbl = newiTempLabel(NULL); + emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE)); + emitcode("cjne","a,#0x80,%05d$", (lbl->key+100)); + emitcode("","%05d$:",(lbl->key+100)); + emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE)); + lbl = newiTempLabel(NULL); + emitcode("jc","%05d$",(lbl->key+100)); + emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("","%05d$:",(lbl->key+100)); + + aopPut(AOP(result),"a",1); + if(size > 2){ + /* get the sign */ + emitcode("rlc","a"); + emitcode("subb","a,acc"); + } + } + size -= 2; + offset = 2; + if (size > 0) + while (size--) + aopPut(AOP(result),"a",offset++); + } +} + +/*-----------------------------------------------------------------*/ +/* genMult - generates code for multiplication */ +/*-----------------------------------------------------------------*/ +static void genMult (iCode *ic) +{ + operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + operand *result= IC_RESULT(ic); + + /* assign the amsops */ + aopOp (left,ic,FALSE); + aopOp (right,ic,FALSE); + aopOp (result,ic,TRUE); + + /* special cases first */ + /* both are bits */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right)== AOP_CRY) { + genMultbits(left,right,result); + goto release ; + } + + /* if both are of size == 1 */ + if (AOP_SIZE(left) == 1 && + AOP_SIZE(right) == 1 ) { + genMultOneByte(left,right,result); + goto release ; + } + + /* should have been converted to function call */ + assert(1) ; + +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genDivbits :- division of bits */ +/*-----------------------------------------------------------------*/ +static void genDivbits (operand *left, + operand *right, + operand *result) +{ + + char *l; + + /* the result must be bit */ + emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE)); + l = aopGet(AOP(left),0,FALSE,FALSE); + + MOVA(l); + + emitcode("div","ab"); + emitcode("rrc","a"); + aopPut(AOP(result),"c",0); +} + +/*-----------------------------------------------------------------*/ +/* genDivOneByte : 8 bit division */ +/*-----------------------------------------------------------------*/ +static void genDivOneByte (operand *left, + operand *right, + operand *result) +{ + link *opetype = operandType(result); + char *l ; + symbol *lbl ; + int size,offset; + + size = AOP_SIZE(result) - 1; + offset = 1; + /* signed or unsigned */ + if (SPEC_USIGN(opetype)) { + /* unsigned is easy */ + emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE)); + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("div","ab"); + aopPut(AOP(result),"a",0); + while (size--) + aopPut(AOP(result),zero,offset++); + return ; + } + + /* signed is a little bit more difficult */ + + /* save the signs of the operands */ + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE)); + emitcode("push","acc"); /* save it on the stack */ + + /* now sign adjust for both left & right */ + l = aopGet(AOP(right),0,FALSE,FALSE); + MOVA(l); + lbl = newiTempLabel(NULL); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + emitcode("cpl","a"); + emitcode("inc","a"); + emitcode("","%05d$:",(lbl->key+100)); + emitcode("mov","b,a"); + + /* sign adjust left side */ + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + + lbl = newiTempLabel(NULL); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + emitcode("cpl","a"); + emitcode("inc","a"); + emitcode("","%05d$:",(lbl->key+100)); + + /* now the division */ + emitcode("div","ab"); + /* we are interested in the lower order + only */ + emitcode("mov","b,a"); + lbl = newiTempLabel(NULL); + emitcode("pop","acc"); + /* if there was an over flow we don't + adjust the sign of the result */ + emitcode("jb","ov,%05d$",(lbl->key+100)); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + CLRC; + emitcode("clr","a"); + emitcode("subb","a,b"); + emitcode("mov","b,a"); + emitcode("","%05d$:",(lbl->key+100)); + + /* now we are done */ + aopPut(AOP(result),"b",0); + if(size > 0){ + emitcode("mov","c,b.7"); + emitcode("subb","a,acc"); + } + while (size--) + aopPut(AOP(result),"a",offset++); + +} + +/*-----------------------------------------------------------------*/ +/* genDiv - generates code for division */ +/*-----------------------------------------------------------------*/ +static void genDiv (iCode *ic) +{ + operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + operand *result= IC_RESULT(ic); + + /* assign the amsops */ + aopOp (left,ic,FALSE); + aopOp (right,ic,FALSE); + aopOp (result,ic,TRUE); + + /* special cases first */ + /* both are bits */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right)== AOP_CRY) { + genDivbits(left,right,result); + goto release ; + } + + /* if both are of size == 1 */ + if (AOP_SIZE(left) == 1 && + AOP_SIZE(right) == 1 ) { + genDivOneByte(left,right,result); + goto release ; + } + + /* should have been converted to function call */ + assert(1); +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genModbits :- modulus of bits */ +/*-----------------------------------------------------------------*/ +static void genModbits (operand *left, + operand *right, + operand *result) +{ + + char *l; + + /* the result must be bit */ + emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE)); + l = aopGet(AOP(left),0,FALSE,FALSE); + + MOVA(l); + + emitcode("div","ab"); + emitcode("mov","a,b"); + emitcode("rrc","a"); + aopPut(AOP(result),"c",0); +} + +/*-----------------------------------------------------------------*/ +/* genModOneByte : 8 bit modulus */ +/*-----------------------------------------------------------------*/ +static void genModOneByte (operand *left, + operand *right, + operand *result) +{ + link *opetype = operandType(result); + char *l ; + symbol *lbl ; + + /* signed or unsigned */ + if (SPEC_USIGN(opetype)) { + /* unsigned is easy */ + emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE)); + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("div","ab"); + aopPut(AOP(result),"b",0); + return ; + } + + /* signed is a little bit more difficult */ + + /* save the signs of the operands */ + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + + emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("push","acc"); /* save it on the stack */ + + /* now sign adjust for both left & right */ + l = aopGet(AOP(right),0,FALSE,FALSE); + MOVA(l); + + lbl = newiTempLabel(NULL); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + emitcode("cpl","a"); + emitcode("inc","a"); + emitcode("","%05d$:",(lbl->key+100)); + emitcode("mov","b,a"); + + /* sign adjust left side */ + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + + lbl = newiTempLabel(NULL); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + emitcode("cpl","a"); + emitcode("inc","a"); + emitcode("","%05d$:",(lbl->key+100)); + + /* now the multiplication */ + emitcode("div","ab"); + /* we are interested in the lower order + only */ + lbl = newiTempLabel(NULL); + emitcode("pop","acc"); + /* if there was an over flow we don't + adjust the sign of the result */ + emitcode("jb","ov,%05d$",(lbl->key+100)); + emitcode("jnb","acc.7,%05d$",(lbl->key+100)); + CLRC ; + emitcode("clr","a"); + emitcode("subb","a,b"); + emitcode("mov","b,a"); + emitcode("","%05d$:",(lbl->key+100)); + + /* now we are done */ + aopPut(AOP(result),"b",0); + +} + +/*-----------------------------------------------------------------*/ +/* genMod - generates code for division */ +/*-----------------------------------------------------------------*/ +static void genMod (iCode *ic) +{ + operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + operand *result= IC_RESULT(ic); + + /* assign the amsops */ + aopOp (left,ic,FALSE); + aopOp (right,ic,FALSE); + aopOp (result,ic,TRUE); + + /* special cases first */ + /* both are bits */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right)== AOP_CRY) { + genModbits(left,right,result); + goto release ; + } + + /* if both are of size == 1 */ + if (AOP_SIZE(left) == 1 && + AOP_SIZE(right) == 1 ) { + genModOneByte(left,right,result); + goto release ; + } + + /* should have been converted to function call */ + assert(1); + +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genIfxJump :- will create a jump depending on the ifx */ +/*-----------------------------------------------------------------*/ +static void genIfxJump (iCode *ic, char *jval) +{ + symbol *jlbl ; + symbol *tlbl = newiTempLabel(NULL); + char *inst; + + /* if true label then we jump if condition + supplied is true */ + if ( IC_TRUE(ic) ) { + jlbl = IC_TRUE(ic); + inst = ((strcmp(jval,"a") == 0 ? "jz" : + (strcmp(jval,"c") == 0 ? "jnc" : "jnb" ))); + } + else { + /* false label is present */ + jlbl = IC_FALSE(ic) ; + inst = ((strcmp(jval,"a") == 0 ? "jnz" : + (strcmp(jval,"c") == 0 ? "jc" : "jb" ))); + } + if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) + emitcode(inst,"%s,%05d$",jval,(tlbl->key+100)); + else + emitcode(inst,"%05d$",tlbl->key+100); + emitcode("ljmp","%05d$",jlbl->key+100); + emitcode("","%05d$:",tlbl->key+100); + + /* mark the icode as generated */ + ic->generated = 1; +} + +/*-----------------------------------------------------------------*/ +/* genCmp :- greater or less than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmp (operand *left,operand *right, + operand *result, iCode *ifx, int sign) +{ + int size, offset = 0 ; + unsigned long lit = 0L; + + /* if left & right are bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_CRY ) { + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); + } else { + /* subtract right from left if at the + end the carry flag is set then we know that + left is greater than right */ + size = max(AOP_SIZE(left),AOP_SIZE(right)); + + /* if unsigned char cmp with lit, do cjne left,#right,zz */ + if((size == 1) && !sign && + (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){ + symbol *lbl = newiTempLabel(NULL); + emitcode("cjne","%s,%s,%05d$", + aopGet(AOP(left),offset,FALSE,FALSE), + aopGet(AOP(right),offset,FALSE,FALSE), + lbl->key+100); + emitcode("","%05d$:",lbl->key+100); + } else { + if(AOP_TYPE(right) == AOP_LIT){ + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + /* optimize if(x < 0) or if(x >= 0) */ + if(lit == 0L){ + if(!sign){ + CLRC; + } + else{ + MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE)); + if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){ + genIfxJump (ifx,"acc.7"); + return; + } + else + emitcode("rlc","a"); + } + goto release; + } + } + CLRC; + while (size--) { + MOVA(aopGet(AOP(left),offset,FALSE,FALSE)); + if (sign && size == 0) { + emitcode("xrl","a,#0x80"); + if (AOP_TYPE(right) == AOP_LIT){ + unsigned long lit = (unsigned long) + floatFromVal(AOP(right)->aopu.aop_lit); + emitcode("subb","a,#0x%02x", + 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL)); + } else { + emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE)); + emitcode("xrl","b,#0x80"); + emitcode("subb","a,b"); + } + } else + emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE)); + } + } + } + +release: + if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { + outBitC(result); + } else { + /* if the result is used in the next + ifx conditional branch then generate + code a little differently */ + if (ifx ) + genIfxJump (ifx,"c"); + else + outBitC(result); + /* leave the result in acc */ + } +} + +/*-----------------------------------------------------------------*/ +/* genCmpGt :- greater than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmpGt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + link *letype , *retype; + int sign ; + + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); + + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + /* assign the amsops */ + aopOp (left,ic,FALSE); + aopOp (right,ic,FALSE); + aopOp (result,ic,TRUE); + + genCmp(right, left, result, ifx, sign); + + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + link *letype , *retype; + int sign ; + + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); + + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + + /* assign the amsops */ + aopOp (left,ic,FALSE); + aopOp (right,ic,FALSE); + aopOp (result,ic,TRUE); + + genCmp(left, right, result, ifx, sign); + + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* gencjneshort - compare and jump if not equal */ +/*-----------------------------------------------------------------*/ +static void gencjneshort(operand *left, operand *right, symbol *lbl) +{ + int size = max(AOP_SIZE(left),AOP_SIZE(right)); + int offset = 0; + unsigned long lit = 0L; + + /* if the left side is a literal or + if the right is in a pointer register and left + is not */ + if ((AOP_TYPE(left) == AOP_LIT) || + (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) { + operand *t = right; + right = left; + left = t; + } + if(AOP_TYPE(right) == AOP_LIT) + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + + /* if the right side is a literal then anything goes */ + if (AOP_TYPE(right) == AOP_LIT && + AOP_TYPE(left) != AOP_DIR ) { + while (size--) { + emitcode("cjne","%s,%s,%05d$", + aopGet(AOP(left),offset,FALSE,FALSE), + aopGet(AOP(right),offset,FALSE,FALSE), + lbl->key+100); + offset++; + } + } + + /* if the right side is in a register or in direct space or + if the left is a pointer register & right is not */ + else if (AOP_TYPE(right) == AOP_REG || + AOP_TYPE(right) == AOP_DIR || + (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) || + (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) { + while (size--) { + MOVA(aopGet(AOP(left),offset,FALSE,FALSE)); + if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) && + ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0)) + emitcode("jnz","%05d$",lbl->key+100); + else + emitcode("cjne","a,%s,%05d$", + aopGet(AOP(right),offset,FALSE,TRUE), + lbl->key+100); + offset++; + } + } else { + /* right is a pointer reg need both a & b */ + while(size--) { + char *l = aopGet(AOP(left),offset,FALSE,FALSE); + if(strcmp(l,"b")) + emitcode("mov","b,%s",l); + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("cjne","a,b,%05d$",lbl->key+100); + offset++; + } + } +} + +/*-----------------------------------------------------------------*/ +/* gencjne - compare and jump if not equal */ +/*-----------------------------------------------------------------*/ +static void gencjne(operand *left, operand *right, symbol *lbl) +{ + symbol *tlbl = newiTempLabel(NULL); + + gencjneshort(left, right, lbl); + + emitcode("mov","a,%s",one); + emitcode("sjmp","%05d$",tlbl->key+100); + emitcode("","%05d$:",lbl->key+100); + emitcode("clr","a"); + emitcode("","%05d$:",tlbl->key+100); +} + +/*-----------------------------------------------------------------*/ +/* genCmpEq - generates code for equal to */ +/*-----------------------------------------------------------------*/ +static void genCmpEq (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + + aopOp((left=IC_LEFT(ic)),ic,FALSE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE); + + /* if literal, literal on the right or + if the right is in a pointer register and left + is not */ + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || + (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) { + operand *t = IC_RIGHT(ic); + IC_RIGHT(ic) = IC_LEFT(ic); + IC_LEFT(ic) = t; + } + + if(ifx && !AOP_SIZE(result)){ + symbol *tlbl; + /* if they are both bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { + if(AOP_TYPE(right) == AOP_LIT){ + unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + if(lit == 0L){ + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("cpl","c"); + } else if(lit == 1L) { + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else { + emitcode("clr","c"); + } + /* AOP_TYPE(right) == AOP_CRY */ + } else { + symbol *lbl = newiTempLabel(NULL); + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100)); + emitcode("cpl","c"); + emitcode("","%05d$:",(lbl->key+100)); + } + /* if true label then we jump if condition + supplied is true */ + tlbl = newiTempLabel(NULL); + if ( IC_TRUE(ifx) ) { + emitcode("jnc","%05d$",tlbl->key+100); + emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100); + } else { + emitcode("jc","%05d$",tlbl->key+100); + emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100); + } + emitcode("","%05d$:",tlbl->key+100); + } else { + tlbl = newiTempLabel(NULL); + gencjneshort(left, right, tlbl); + if ( IC_TRUE(ifx) ) { + emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100); + emitcode("","%05d$:",tlbl->key+100); + } else { + symbol *lbl = newiTempLabel(NULL); + emitcode("sjmp","%05d$",lbl->key+100); + emitcode("","%05d$:",tlbl->key+100); + emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100); + emitcode("","%05d$:",lbl->key+100); + } + } + /* mark the icode as generated */ + ifx->generated = 1; + goto release ; + } + + /* if they are both bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { + if(AOP_TYPE(right) == AOP_LIT){ + unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + if(lit == 0L){ + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("cpl","c"); + } else if(lit == 1L) { + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else { + emitcode("clr","c"); + } + /* AOP_TYPE(right) == AOP_CRY */ + } else { + symbol *lbl = newiTempLabel(NULL); + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100)); + emitcode("cpl","c"); + emitcode("","%05d$:",(lbl->key+100)); + } + /* c = 1 if egal */ + if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){ + outBitC(result); + goto release ; + } + if (ifx) { + genIfxJump (ifx,"c"); + goto release ; + } + /* if the result is used in an arithmetic operation + then put the result in place */ + outBitC(result); + } else { + gencjne(left,right,newiTempLabel(NULL)); + if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { + aopPut(AOP(result),"a",0); + goto release ; + } + if (ifx) { + genIfxJump (ifx,"a"); + goto release ; + } + /* if the result is used in an arithmetic operation + then put the result in place */ + if (AOP_TYPE(result) != AOP_CRY) + outAcc(result); + /* leave the result in acc */ + } + +release: + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* ifxForOp - returns the icode containing the ifx for operand */ +/*-----------------------------------------------------------------*/ +static iCode *ifxForOp ( operand *op, iCode *ic ) +{ + /* if true symbol then needs to be assigned */ + if (IS_TRUE_SYMOP(op)) + return NULL ; + + /* if this has register type condition and + the next instruction is ifx with the same operand + and live to of the operand is upto the ifx only then */ + if (ic->next && + ic->next->op == IFX && + IC_COND(ic->next)->key == op->key && + OP_SYMBOL(op)->liveTo <= ic->next->seq ) + return ic->next; + + return NULL; +} +/*-----------------------------------------------------------------*/ +/* genAndOp - for && operation */ +/*-----------------------------------------------------------------*/ +static void genAndOp (iCode *ic) +{ + operand *left,*right, *result; + symbol *tlbl; + + /* note here that && operations that are in an + if statement are taken away by backPatchLabels + only those used in arthmetic operations remain */ + aopOp((left=IC_LEFT(ic)),ic,FALSE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,FALSE); + + /* if both are bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_CRY ) { + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); + outBitC(result); + } else { + tlbl = newiTempLabel(NULL); + toBoolean(left); + emitcode("jz","%05d$",tlbl->key+100); + toBoolean(right); + emitcode("","%05d$:",tlbl->key+100); + outBitAcc(result); + } + + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + + +/*-----------------------------------------------------------------*/ +/* genOrOp - for || operation */ +/*-----------------------------------------------------------------*/ +static void genOrOp (iCode *ic) +{ + operand *left,*right, *result; + symbol *tlbl; + + /* note here that || operations that are in an + if statement are taken away by backPatchLabels + only those used in arthmetic operations remain */ + aopOp((left=IC_LEFT(ic)),ic,FALSE); + aopOp((right=IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,FALSE); + + /* if both are bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_CRY ) { + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("orl","c,%s",AOP(right)->aopu.aop_dir); + outBitC(result); + } else { + tlbl = newiTempLabel(NULL); + toBoolean(left); + emitcode("jnz","%05d$",tlbl->key+100); + toBoolean(right); + emitcode("","%05d$:",tlbl->key+100); + outBitAcc(result); + } + + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* isLiteralBit - test if lit == 2^n */ +/*-----------------------------------------------------------------*/ +int isLiteralBit(unsigned long lit) +{ + unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L, + 0x100L,0x200L,0x400L,0x800L, + 0x1000L,0x2000L,0x4000L,0x8000L, + 0x10000L,0x20000L,0x40000L,0x80000L, + 0x100000L,0x200000L,0x400000L,0x800000L, + 0x1000000L,0x2000000L,0x4000000L,0x8000000L, + 0x10000000L,0x20000000L,0x40000000L,0x80000000L}; + int idx; + + for(idx = 0; idx < 32; idx++) + if(lit == pw[idx]) + return idx+1; + return 0; +} + +/*-----------------------------------------------------------------*/ +/* continueIfTrue - */ +/*-----------------------------------------------------------------*/ +static void continueIfTrue (iCode *ic) +{ + if(IC_TRUE(ic)) + emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100); + ic->generated = 1; +} + +/*-----------------------------------------------------------------*/ +/* jmpIfTrue - */ +/*-----------------------------------------------------------------*/ +static void jumpIfTrue (iCode *ic) +{ + if(!IC_TRUE(ic)) + emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100); + ic->generated = 1; +} + +/*-----------------------------------------------------------------*/ +/* jmpTrueOrFalse - */ +/*-----------------------------------------------------------------*/ +static void jmpTrueOrFalse (iCode *ic, symbol *tlbl) +{ + // ugly but optimized by peephole + if(IC_TRUE(ic)){ + symbol *nlbl = newiTempLabel(NULL); + emitcode("sjmp","%05d$",nlbl->key+100); + emitcode("","%05d$:",tlbl->key+100); + emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100); + emitcode("","%05d$:",nlbl->key+100); + } + else{ + emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100); + emitcode("","%05d$:",tlbl->key+100); + } + ic->generated = 1; +} + +/*-----------------------------------------------------------------*/ +/* genAnd - code for and */ +/*-----------------------------------------------------------------*/ +static void genAnd (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + int size, offset=0; + unsigned long lit = 0L; + int bytelit = 0; + char buffer[10]; + + aopOp((left = IC_LEFT(ic)),ic,FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE); + +#ifdef DEBUG_TYPE + emitcode("","; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE(result), + AOP_TYPE(left), AOP_TYPE(right)); + emitcode("","; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE(result), + AOP_SIZE(left), AOP_SIZE(right)); +#endif + + /* if left is a literal & right is not then exchange them */ + if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || + AOP_NEEDSACC(left)) { + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if result = right then exchange them */ + if(sameRegs(AOP(result),AOP(right))){ + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if right is bit then exchange them */ + if (AOP_TYPE(right) == AOP_CRY && + AOP_TYPE(left) != AOP_CRY){ + operand *tmp = right ; + right = left; + left = tmp; + } + if(AOP_TYPE(right) == AOP_LIT) + lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit); + + size = AOP_SIZE(result); + + // if(bit & yy) + // result = bit & yy; + if (AOP_TYPE(left) == AOP_CRY){ + // c = bit & literal; + if(AOP_TYPE(right) == AOP_LIT){ + if(lit & 1) { + if(size && sameRegs(AOP(result),AOP(left))) + // no change + goto release; + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else { + // bit(result) = 0; + if(size && (AOP_TYPE(result) == AOP_CRY)){ + emitcode("clr","%s",AOP(result)->aopu.aop_dir); + goto release; + } + if((AOP_TYPE(result) == AOP_CRY) && ifx){ + jumpIfTrue(ifx); + goto release; + } + emitcode("clr","c"); + } + } else { + if (AOP_TYPE(right) == AOP_CRY){ + // c = bit & bit; + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); + } else { + // c = bit & val; + MOVA(aopGet(AOP(right),0,FALSE,FALSE)); + // c = lsb + emitcode("rrc","a"); + emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); + } + } + // bit = c + // val = c + if(size) + outBitC(result); + // if(bit & ...) + else if((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release ; + } + + // if(val & 0xZZ) - size = 0, ifx != FALSE - + // bit = val & 0xZZ - size = 1, ifx = FALSE - + if((AOP_TYPE(right) == AOP_LIT) && + (AOP_TYPE(result) == AOP_CRY) && + (AOP_TYPE(left) != AOP_CRY)){ + int posbit = isLiteralBit(lit); + /* left & 2^n */ + if(posbit){ + posbit--; + MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE)); + // bit = left & 2^n + if(size) + emitcode("mov","c,acc.%d",posbit&0x07); + // if(left & 2^n) + else{ + if(ifx){ + sprintf(buffer,"acc.%d",posbit&0x07); + genIfxJump(ifx, buffer); + } + goto release; + } + } else { + symbol *tlbl = newiTempLabel(NULL); + int sizel = AOP_SIZE(left); + if(size) + emitcode("setb","c"); + while(sizel--){ + if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){ + MOVA( aopGet(AOP(left),offset,FALSE,FALSE)); + // byte == 2^n ? + if((posbit = isLiteralBit(bytelit)) != 0) + emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100); + else{ + if(bytelit != 0x0FFL) + emitcode("anl","a,%s", + aopGet(AOP(right),offset,FALSE,TRUE)); + emitcode("jnz","%05d$",tlbl->key+100); + } + } + offset++; + } + // bit = left & literal + if(size){ + emitcode("clr","c"); + emitcode("","%05d$:",tlbl->key+100); + } + // if(left & literal) + else{ + if(ifx) + jmpTrueOrFalse(ifx, tlbl); + goto release ; + } + } + outBitC(result); + goto release ; + } + + /* if left is same as result */ + if(sameRegs(AOP(result),AOP(left))){ + for(;size--; offset++) { + if(AOP_TYPE(right) == AOP_LIT){ + if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF) + continue; + else + if (bytelit == 0) + aopPut(AOP(result),zero,offset); + else + if (IS_AOP_PREG(result)) { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + } else + emitcode("anl","%s,%s", + aopGet(AOP(left),offset,FALSE,TRUE), + aopGet(AOP(right),offset,FALSE,FALSE)); + } else { + if (AOP_TYPE(left) == AOP_ACC) + emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + if (IS_AOP_PREG(result)) { + emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + + } else + emitcode("anl","%s,a", + aopGet(AOP(left),offset,FALSE,TRUE)); + } + } + } + } else { + // left & result in different registers + if(AOP_TYPE(result) == AOP_CRY){ + // result = bit + // if(size), result in bit + // if(!size && ifx), conditional oper: if(left & right) + symbol *tlbl = newiTempLabel(NULL); + int sizer = min(AOP_SIZE(left),AOP_SIZE(right)); + if(size) + emitcode("setb","c"); + while(sizer--){ + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("anl","a,%s", + aopGet(AOP(left),offset,FALSE,FALSE)); + emitcode("jnz","%05d$",tlbl->key+100); + offset++; + } + if(size){ + CLRC; + emitcode("","%05d$:",tlbl->key+100); + outBitC(result); + } else if(ifx) + jmpTrueOrFalse(ifx, tlbl); + } else { + for(;(size--);offset++) { + // normal case + // result = left & right + if(AOP_TYPE(right) == AOP_LIT){ + if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){ + aopPut(AOP(result), + aopGet(AOP(left),offset,FALSE,FALSE), + offset); + continue; + } else if(bytelit == 0){ + aopPut(AOP(result),zero,offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE(left) == AOP_ACC) + emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("anl","a,%s", + aopGet(AOP(left),offset,FALSE,FALSE)); + } + aopPut(AOP(result),"a",offset); + } + } + } + +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genOr - code for or */ +/*-----------------------------------------------------------------*/ +static void genOr (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + int size, offset=0; + unsigned long lit = 0L; + + aopOp((left = IC_LEFT(ic)),ic,FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE); + +#ifdef DEBUG_TYPE + emitcode("","; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE(result), + AOP_TYPE(left), AOP_TYPE(right)); + emitcode("","; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE(result), + AOP_SIZE(left), AOP_SIZE(right)); +#endif + + /* if left is a literal & right is not then exchange them */ + if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || + AOP_NEEDSACC(left)) { + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if result = right then exchange them */ + if(sameRegs(AOP(result),AOP(right))){ + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if right is bit then exchange them */ + if (AOP_TYPE(right) == AOP_CRY && + AOP_TYPE(left) != AOP_CRY){ + operand *tmp = right ; + right = left; + left = tmp; + } + if(AOP_TYPE(right) == AOP_LIT) + lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit); + + size = AOP_SIZE(result); + + // if(bit | yy) + // xx = bit | yy; + if (AOP_TYPE(left) == AOP_CRY){ + if(AOP_TYPE(right) == AOP_LIT){ + // c = bit & literal; + if(lit){ + // lit != 0 => result = 1 + if(AOP_TYPE(result) == AOP_CRY){ + if(size) + emitcode("setb","%s",AOP(result)->aopu.aop_dir); + else if(ifx) + continueIfTrue(ifx); + goto release; + } + emitcode("setb","c"); + } else { + // lit == 0 => result = left + if(size && sameRegs(AOP(result),AOP(left))) + goto release; + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } + } else { + if (AOP_TYPE(right) == AOP_CRY){ + // c = bit | bit; + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + emitcode("orl","c,%s",AOP(left)->aopu.aop_dir); + } + else{ + // c = bit | val; + symbol *tlbl = newiTempLabel(NULL); + if(!((AOP_TYPE(result) == AOP_CRY) && ifx)) + emitcode("setb","c"); + emitcode("jb","%s,%05d$", + AOP(left)->aopu.aop_dir,tlbl->key+100); + toBoolean(right); + emitcode("jnz","%05d$",tlbl->key+100); + if((AOP_TYPE(result) == AOP_CRY) && ifx){ + jmpTrueOrFalse(ifx, tlbl); + goto release; + } else { + CLRC; + emitcode("","%05d$:",tlbl->key+100); + } + } + } + // bit = c + // val = c + if(size) + outBitC(result); + // if(bit | ...) + else if((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release ; + } + + // if(val | 0xZZ) - size = 0, ifx != FALSE - + // bit = val | 0xZZ - size = 1, ifx = FALSE - + if((AOP_TYPE(right) == AOP_LIT) && + (AOP_TYPE(result) == AOP_CRY) && + (AOP_TYPE(left) != AOP_CRY)){ + if(lit){ + // result = 1 + if(size) + emitcode("setb","%s",AOP(result)->aopu.aop_dir); + else + continueIfTrue(ifx); + goto release; + } else { + // lit = 0, result = boolean(left) + if(size) + emitcode("setb","c"); + toBoolean(right); + if(size){ + symbol *tlbl = newiTempLabel(NULL); + emitcode("jnz","%05d$",tlbl->key+100); + CLRC; + emitcode("","%05d$:",tlbl->key+100); + } else { + genIfxJump (ifx,"a"); + goto release; + } + } + outBitC(result); + goto release ; + } + + /* if left is same as result */ + if(sameRegs(AOP(result),AOP(left))){ + for(;size--; offset++) { + if(AOP_TYPE(right) == AOP_LIT){ + if(((lit >> (offset*8)) & 0x0FFL) == 0x00L) + continue; + else + if (IS_AOP_PREG(left)) { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + } else + emitcode("orl","%s,%s", + aopGet(AOP(left),offset,FALSE,TRUE), + aopGet(AOP(right),offset,FALSE,FALSE)); + } else { + if (AOP_TYPE(left) == AOP_ACC) + emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + if (IS_AOP_PREG(left)) { + emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + } else + emitcode("orl","%s,a", + aopGet(AOP(left),offset,FALSE,TRUE)); + } + } + } + } else { + // left & result in different registers + if(AOP_TYPE(result) == AOP_CRY){ + // result = bit + // if(size), result in bit + // if(!size && ifx), conditional oper: if(left | right) + symbol *tlbl = newiTempLabel(NULL); + int sizer = max(AOP_SIZE(left),AOP_SIZE(right)); + if(size) + emitcode("setb","c"); + while(sizer--){ + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("orl","a,%s", + aopGet(AOP(left),offset,FALSE,FALSE)); + emitcode("jnz","%05d$",tlbl->key+100); + offset++; + } + if(size){ + CLRC; + emitcode("","%05d$:",tlbl->key+100); + outBitC(result); + } else if(ifx) + jmpTrueOrFalse(ifx, tlbl); + } else for(;(size--);offset++){ + // normal case + // result = left & right + if(AOP_TYPE(right) == AOP_LIT){ + if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){ + aopPut(AOP(result), + aopGet(AOP(left),offset,FALSE,FALSE), + offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE(left) == AOP_ACC) + emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("orl","a,%s", + aopGet(AOP(left),offset,FALSE,FALSE)); + } + aopPut(AOP(result),"a",offset); + } + } + +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genXor - code for xclusive or */ +/*-----------------------------------------------------------------*/ +static void genXor (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + int size, offset=0; + unsigned long lit = 0L; + + aopOp((left = IC_LEFT(ic)),ic,FALSE); + aopOp((right= IC_RIGHT(ic)),ic,FALSE); + aopOp((result=IC_RESULT(ic)),ic,TRUE); + +#ifdef DEBUG_TYPE + emitcode("","; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE(result), + AOP_TYPE(left), AOP_TYPE(right)); + emitcode("","; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE(result), + AOP_SIZE(left), AOP_SIZE(right)); +#endif + + /* if left is a literal & right is not || + if left needs acc & right does not */ + if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || + (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) { + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if result = right then exchange them */ + if(sameRegs(AOP(result),AOP(right))){ + operand *tmp = right ; + right = left; + left = tmp; + } + + /* if right is bit then exchange them */ + if (AOP_TYPE(right) == AOP_CRY && + AOP_TYPE(left) != AOP_CRY){ + operand *tmp = right ; + right = left; + left = tmp; + } + if(AOP_TYPE(right) == AOP_LIT) + lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit); + + size = AOP_SIZE(result); + + // if(bit ^ yy) + // xx = bit ^ yy; + if (AOP_TYPE(left) == AOP_CRY){ + if(AOP_TYPE(right) == AOP_LIT){ + // c = bit & literal; + if(lit>>1){ + // lit>>1 != 0 => result = 1 + if(AOP_TYPE(result) == AOP_CRY){ + if(size) + emitcode("setb","%s",AOP(result)->aopu.aop_dir); + else if(ifx) + continueIfTrue(ifx); + goto release; + } + emitcode("setb","c"); + } else{ + // lit == (0 or 1) + if(lit == 0){ + // lit == 0, result = left + if(size && sameRegs(AOP(result),AOP(left))) + goto release; + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else{ + // lit == 1, result = not(left) + if(size && sameRegs(AOP(result),AOP(left))){ + emitcode("cpl","%s",AOP(result)->aopu.aop_dir); + goto release; + } else { + emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + emitcode("cpl","c"); + } + } + } + + } else { + // right != literal + symbol *tlbl = newiTempLabel(NULL); + if (AOP_TYPE(right) == AOP_CRY){ + // c = bit ^ bit; + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + } + else{ + int sizer = AOP_SIZE(right); + // c = bit ^ val + // if val>>1 != 0, result = 1 + emitcode("setb","c"); + while(sizer--){ + MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE)); + if(sizer == 1) + // test the msb of the lsb + emitcode("anl","a,#0xfe"); + emitcode("jnz","%05d$",tlbl->key+100); + } + // val = (0,1) + emitcode("rrc","a"); + } + emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100)); + emitcode("cpl","c"); + emitcode("","%05d$:",(tlbl->key+100)); + } + // bit = c + // val = c + if(size) + outBitC(result); + // if(bit | ...) + else if((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release ; + } + + if(sameRegs(AOP(result),AOP(left))){ + /* if left is same as result */ + for(;size--; offset++) { + if(AOP_TYPE(right) == AOP_LIT){ + if(((lit >> (offset*8)) & 0x0FFL) == 0x00L) + continue; + else + if (IS_AOP_PREG(left)) { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + } else + emitcode("xrl","%s,%s", + aopGet(AOP(left),offset,FALSE,TRUE), + aopGet(AOP(right),offset,FALSE,FALSE)); + } else { + if (AOP_TYPE(left) == AOP_ACC) + emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + if (IS_AOP_PREG(left)) { + emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE)); + aopPut(AOP(result),"a",offset); + } else + emitcode("xrl","%s,a", + aopGet(AOP(left),offset,FALSE,TRUE)); + } + } + } + } else { + // left & result in different registers + if(AOP_TYPE(result) == AOP_CRY){ + // result = bit + // if(size), result in bit + // if(!size && ifx), conditional oper: if(left ^ right) + symbol *tlbl = newiTempLabel(NULL); + int sizer = max(AOP_SIZE(left),AOP_SIZE(right)); + if(size) + emitcode("setb","c"); + while(sizer--){ + if((AOP_TYPE(right) == AOP_LIT) && + (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){ + MOVA(aopGet(AOP(left),offset,FALSE,FALSE)); + } else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("xrl","a,%s", + aopGet(AOP(left),offset,FALSE,FALSE)); + } + emitcode("jnz","%05d$",tlbl->key+100); + offset++; + } + if(size){ + CLRC; + emitcode("","%05d$:",tlbl->key+100); + outBitC(result); + } else if(ifx) + jmpTrueOrFalse(ifx, tlbl); + } else for(;(size--);offset++){ + // normal case + // result = left & right + if(AOP_TYPE(right) == AOP_LIT){ + if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){ + aopPut(AOP(result), + aopGet(AOP(left),offset,FALSE,FALSE), + offset); + continue; + } + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE(left) == AOP_ACC) + emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE)); + else { + MOVA(aopGet(AOP(right),offset,FALSE,FALSE)); + emitcode("xrl","a,%s", + aopGet(AOP(left),offset,FALSE,TRUE)); + } + aopPut(AOP(result),"a",offset); + } + } + +release : + freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genInline - write the inline code out */ +/*-----------------------------------------------------------------*/ +static void genInline (iCode *ic) +{ + char buffer[MAX_INLINEASM]; + char *bp = buffer; + char *bp1= buffer; + + inLine += (!options.asmpeep); + strcpy(buffer,IC_INLINE(ic)); + + /* emit each line as a code */ + while (*bp) { + if (*bp == '\n') { + *bp++ = '\0'; + emitcode(bp1,""); + bp1 = bp; + } else { + if (*bp == ':') { + bp++; + *bp = '\0'; + bp++; + emitcode(bp1,""); + bp1 = bp; + } else + bp++; + } + } + if (bp1 != bp) + emitcode(bp1,""); + /* emitcode("",buffer); */ + inLine -= (!options.asmpeep); +} + +/*-----------------------------------------------------------------*/ +/* genRRC - rotate right with carry */ +/*-----------------------------------------------------------------*/ +static void genRRC (iCode *ic) +{ + operand *left , *result ; + int size, offset = 0; + char *l; + + /* rotate right with carry */ + left = IC_LEFT(ic); + result=IC_RESULT(ic); + aopOp (left,ic,FALSE); + aopOp (result,ic,FALSE); + + /* move it to the result */ + size = AOP_SIZE(result); + offset = size - 1 ; + CLRC; + while (size--) { + l = aopGet(AOP(left),offset,FALSE,FALSE); + MOVA(l); + emitcode("rrc","a"); + if (AOP_SIZE(result) > 1) + aopPut(AOP(result),"a",offset--); + } + /* now we need to put the carry into the + highest order byte of the result */ + if (AOP_SIZE(result) > 1) { + l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE); + MOVA(l); + } + emitcode("mov","acc.7,c"); + aopPut(AOP(result),"a",AOP_SIZE(result)-1); + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genRLC - generate code for rotate left with carry */ +/*-----------------------------------------------------------------*/ +static void genRLC (iCode *ic) +{ + operand *left , *result ; + int size, offset = 0; + char *l; + + /* rotate right with carry */ + left = IC_LEFT(ic); + result=IC_RESULT(ic); + aopOp (left,ic,FALSE); + aopOp (result,ic,FALSE); + + /* move it to the result */ + size = AOP_SIZE(result); + offset = 0 ; + if (size--) { + l = aopGet(AOP(left),offset,FALSE,FALSE); + MOVA(l); + emitcode("add","a,acc"); + if (AOP_SIZE(result) > 1) + aopPut(AOP(result),"a",offset++); + while (size--) { + l = aopGet(AOP(left),offset,FALSE,FALSE); + MOVA(l); + emitcode("rlc","a"); + if (AOP_SIZE(result) > 1) + aopPut(AOP(result),"a",offset++); + } + } + /* now we need to put the carry into the + highest order byte of the result */ + if (AOP_SIZE(result) > 1) { + l = aopGet(AOP(result),0,FALSE,FALSE); + MOVA(l); + } + emitcode("mov","acc.0,c"); + aopPut(AOP(result),"a",0); + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGetHbit - generates code get highest order bit */ +/*-----------------------------------------------------------------*/ +static void genGetHbit (iCode *ic) +{ + operand *left, *result; + left = IC_LEFT(ic); + result=IC_RESULT(ic); + aopOp (left,ic,FALSE); + aopOp (result,ic,FALSE); + + /* get the highest order byte into a */ + MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE)); + if(AOP_TYPE(result) == AOP_CRY){ + emitcode("rlc","a"); + outBitC(result); + } + else{ + emitcode("rl","a"); + emitcode("anl","a,#0x01"); + outAcc(result); + } + + + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* AccRol - rotate left accumulator by known count */ +/*-----------------------------------------------------------------*/ +static void AccRol (int shCount) +{ + shCount &= 0x0007; // shCount : 0..7 + switch(shCount){ + case 0 : + break; + case 1 : + emitcode("rl","a"); + break; + case 2 : + emitcode("rl","a"); + emitcode("rl","a"); + break; + case 3 : + emitcode("swap","a"); + emitcode("rr","a"); + break; + case 4 : + emitcode("swap","a"); + break; + case 5 : + emitcode("swap","a"); + emitcode("rl","a"); + break; + case 6 : + emitcode("rr","a"); + emitcode("rr","a"); + break; + case 7 : + emitcode("rr","a"); + break; + } +} + +/*-----------------------------------------------------------------*/ +/* AccLsh - left shift accumulator by known count */ +/*-----------------------------------------------------------------*/ +static void AccLsh (int shCount) +{ + if(shCount != 0){ + if(shCount == 1) + emitcode("add","a,acc"); + else + if(shCount == 2) { + emitcode("add","a,acc"); + emitcode("add","a,acc"); + } else { + /* rotate left accumulator */ + AccRol(shCount); + /* and kill the lower order bits */ + emitcode("anl","a,#0x%02x", SLMask[shCount]); + } + } +} + +/*-----------------------------------------------------------------*/ +/* AccRsh - right shift accumulator by known count */ +/*-----------------------------------------------------------------*/ +static void AccRsh (int shCount) +{ + if(shCount != 0){ + if(shCount == 1){ + CLRC; + emitcode("rrc","a"); + } else { + /* rotate right accumulator */ + AccRol(8 - shCount); + /* and kill the higher order bits */ + emitcode("anl","a,#0x%02x", SRMask[shCount]); + } + } +} + +/*-----------------------------------------------------------------*/ +/* AccSRsh - signed right shift accumulator by known count */ +/*-----------------------------------------------------------------*/ +static void AccSRsh (int shCount) +{ + symbol *tlbl ; + if(shCount != 0){ + if(shCount == 1){ + emitcode("mov","c,acc.7"); + emitcode("rrc","a"); + } else if(shCount == 2){ + emitcode("mov","c,acc.7"); + emitcode("rrc","a"); + emitcode("mov","c,acc.7"); + emitcode("rrc","a"); + } else { + tlbl = newiTempLabel(NULL); + /* rotate right accumulator */ + AccRol(8 - shCount); + /* and kill the higher order bits */ + emitcode("anl","a,#0x%02x", SRMask[shCount]); + emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); + emitcode("orl","a,#0x%02x", + (unsigned char)~SRMask[shCount]); + emitcode("","%05d$:",tlbl->key+100); + } + } +} + +/*-----------------------------------------------------------------*/ +/* shiftR1Left2Result - shift right one byte from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftR1Left2Result (operand *left, int offl, + operand *result, int offr, + int shCount, int sign) +{ + MOVA(aopGet(AOP(left),offl,FALSE,FALSE)); + /* shift right accumulator */ + if(sign) + AccSRsh(shCount); + else + AccRsh(shCount); + aopPut(AOP(result),"a",offr); +} + +/*-----------------------------------------------------------------*/ +/* shiftL1Left2Result - shift left one byte from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftL1Left2Result (operand *left, int offl, + operand *result, int offr, int shCount) +{ + char *l; + l = aopGet(AOP(left),offl,FALSE,FALSE); + MOVA(l); + /* shift left accumulator */ + AccLsh(shCount); + aopPut(AOP(result),"a",offr); +} + +/*-----------------------------------------------------------------*/ +/* movLeft2Result - move byte from left to result */ +/*-----------------------------------------------------------------*/ +static void movLeft2Result (operand *left, int offl, + operand *result, int offr, int sign) +{ + char *l; + if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){ + l = aopGet(AOP(left),offl,FALSE,FALSE); + + if (*l == '@' && (IS_AOP_PREG(result))) { + emitcode("mov","a,%s",l); + aopPut(AOP(result),"a",offr); + } else { + if(!sign) + aopPut(AOP(result),l,offr); + else{ + /* MSB sign in acc.7 ! */ + if(getDataSize(left) == offl+1){ + emitcode("mov","a,%s",l); + aopPut(AOP(result),"a",offr); + } + } + } + } +} + +/*-----------------------------------------------------------------*/ +/* AccAXRrl1 - right rotate c->a:x->c by 1 */ +/*-----------------------------------------------------------------*/ +static void AccAXRrl1 (char *x) +{ + emitcode("rrc","a"); + emitcode("xch","a,%s", x); + emitcode("rrc","a"); + emitcode("xch","a,%s", x); +} + +/*-----------------------------------------------------------------*/ +/* AccAXLrl1 - left rotate c<-a:x<-c by 1 */ +/*-----------------------------------------------------------------*/ +static void AccAXLrl1 (char *x) +{ + emitcode("xch","a,%s",x); + emitcode("rlc","a"); + emitcode("xch","a,%s",x); + emitcode("rlc","a"); +} + +/*-----------------------------------------------------------------*/ +/* AccAXLsh1 - left shift a:x<-0 by 1 */ +/*-----------------------------------------------------------------*/ +static void AccAXLsh1 (char *x) +{ + emitcode("xch","a,%s",x); + emitcode("add","a,acc"); + emitcode("xch","a,%s",x); + emitcode("rlc","a"); +} + +/*-----------------------------------------------------------------*/ +/* AccAXLsh - left shift a:x by known count (0..7) */ +/*-----------------------------------------------------------------*/ +static void AccAXLsh (char *x, int shCount) +{ + switch(shCount){ + case 0 : + break; + case 1 : + AccAXLsh1(x); + break; + case 2 : + AccAXLsh1(x); + AccAXLsh1(x); + break; + case 3 : + case 4 : + case 5 : // AAAAABBB:CCCCCDDD + AccRol(shCount); // BBBAAAAA:CCCCCDDD + emitcode("anl","a,#0x%02x", + SLMask[shCount]); // BBB00000:CCCCCDDD + emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000 + AccRol(shCount); // DDDCCCCC:BBB00000 + emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC + emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC + emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC + emitcode("anl","a,#0x%02x", + SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC + emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000 + emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000 + break; + case 6 : // AAAAAABB:CCCCCCDD + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000000BB:CCCCCCDD + emitcode("mov","c,acc.0"); // c = B + emitcode("xch","a,%s",x); // CCCCCCDD:000000BB + AccAXRrl1(x); // BCCCCCCD:D000000B + AccAXRrl1(x); // BBCCCCCC:DD000000 + break; + case 7 : // a:x <<= 7 + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 0000000B:CCCCCCCD + emitcode("mov","c,acc.0"); // c = B + emitcode("xch","a,%s",x); // CCCCCCCD:0000000B + AccAXRrl1(x); // BCCCCCCC:D0000000 + break; + default : + break; + } +} + +/*-----------------------------------------------------------------*/ +/* AccAXRsh - right shift a:x known count (0..7) */ +/*-----------------------------------------------------------------*/ +static void AccAXRsh (char *x, int shCount) +{ + switch(shCount){ + case 0 : + break; + case 1 : + CLRC; + AccAXRrl1(x); // 0->a:x + break; + case 2 : + CLRC; + AccAXRrl1(x); // 0->a:x + CLRC; + AccAXRrl1(x); // 0->a:x + break; + case 3 : + case 4 : + case 5 : // AAAAABBB:CCCCCDDD = a:x + AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC + emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA + AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000CCCCC:BBBAAAAA + emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA + emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA) + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA) + emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA + emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA + emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC + break; + case 6 : // AABBBBBB:CCDDDDDD + emitcode("mov","c,acc.7"); + AccAXLrl1(x); // ABBBBBBC:CDDDDDDA + AccAXLrl1(x); // BBBBBBCC:DDDDDDAA + emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000000AA:BBBBBBCC + break; + case 7 : // ABBBBBBB:CDDDDDDD + emitcode("mov","c,acc.7"); // c = A + AccAXLrl1(x); // BBBBBBBC:DDDDDDDA + emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 0000000A:BBBBBBBC + break; + default : + break; + } +} + +/*-----------------------------------------------------------------*/ +/* AccAXRshS - right shift signed a:x known count (0..7) */ +/*-----------------------------------------------------------------*/ +static void AccAXRshS (char *x, int shCount) +{ + symbol *tlbl ; + switch(shCount){ + case 0 : + break; + case 1 : + emitcode("mov","c,acc.7"); + AccAXRrl1(x); // s->a:x + break; + case 2 : + emitcode("mov","c,acc.7"); + AccAXRrl1(x); // s->a:x + emitcode("mov","c,acc.7"); + AccAXRrl1(x); // s->a:x + break; + case 3 : + case 4 : + case 5 : // AAAAABBB:CCCCCDDD = a:x + tlbl = newiTempLabel(NULL); + AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD + emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA + AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000CCCCC:BBBAAAAA + emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA + emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA) + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA) + emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA + emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA + emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC + emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); + emitcode("orl","a,#0x%02x", + (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC + emitcode("","%05d$:",tlbl->key+100); + break; // SSSSAAAA:BBBCCCCC + case 6 : // AABBBBBB:CCDDDDDD + tlbl = newiTempLabel(NULL); + emitcode("mov","c,acc.7"); + AccAXLrl1(x); // ABBBBBBC:CDDDDDDA + AccAXLrl1(x); // BBBBBBCC:DDDDDDAA + emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 000000AA:BBBBBBCC + emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); + emitcode("orl","a,#0x%02x", + (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC + emitcode("","%05d$:",tlbl->key+100); + break; + case 7 : // ABBBBBBB:CDDDDDDD + tlbl = newiTempLabel(NULL); + emitcode("mov","c,acc.7"); // c = A + AccAXLrl1(x); // BBBBBBBC:DDDDDDDA + emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC + emitcode("anl","a,#0x%02x", + SRMask[shCount]); // 0000000A:BBBBBBBC + emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); + emitcode("orl","a,#0x%02x", + (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC + emitcode("","%05d$:",tlbl->key+100); + break; + default : + break; + } +} + +/*-----------------------------------------------------------------*/ +/* shiftL2Left2Result - shift left two bytes from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftL2Left2Result (operand *left, int offl, + operand *result, int offr, int shCount) +{ + if(sameRegs(AOP(result), AOP(left)) && + ((offl + MSB16) == offr)){ + /* don't crash result[offr] */ + MOVA(aopGet(AOP(left),offl,FALSE,FALSE)); + emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE)); + } else { + movLeft2Result(left,offl, result, offr, 0); + MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE)); + } + /* ax << shCount (x = lsb(result))*/ + AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount); + aopPut(AOP(result),"a",offr+MSB16); +} + + +/*-----------------------------------------------------------------*/ +/* shiftR2Left2Result - shift right two bytes from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftR2Left2Result (operand *left, int offl, + operand *result, int offr, + int shCount, int sign) +{ + if(sameRegs(AOP(result), AOP(left)) && + ((offl + MSB16) == offr)){ + /* don't crash result[offr] */ + MOVA(aopGet(AOP(left),offl,FALSE,FALSE)); + emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE)); + } else { + movLeft2Result(left,offl, result, offr, 0); + MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE)); + } + /* a:x >> shCount (x = lsb(result))*/ + if(sign) + AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount); + else + AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount); + if(getDataSize(result) > 1) + aopPut(AOP(result),"a",offr+MSB16); +} + +/*-----------------------------------------------------------------*/ +/* shiftLLeftOrResult - shift left one byte from left, or to result*/ +/*-----------------------------------------------------------------*/ +static void shiftLLeftOrResult (operand *left, int offl, + operand *result, int offr, int shCount) +{ + MOVA(aopGet(AOP(left),offl,FALSE,FALSE)); + /* shift left accumulator */ + AccLsh(shCount); + /* or with result */ + emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE)); + /* back to result */ + aopPut(AOP(result),"a",offr); +} + +/*-----------------------------------------------------------------*/ +/* shiftRLeftOrResult - shift right one byte from left,or to result*/ +/*-----------------------------------------------------------------*/ +static void shiftRLeftOrResult (operand *left, int offl, + operand *result, int offr, int shCount) +{ + MOVA(aopGet(AOP(left),offl,FALSE,FALSE)); + /* shift right accumulator */ + AccRsh(shCount); + /* or with result */ + emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE)); + /* back to result */ + aopPut(AOP(result),"a",offr); +} + +/*-----------------------------------------------------------------*/ +/* genlshOne - left shift a one byte quantity by known count */ +/*-----------------------------------------------------------------*/ +static void genlshOne (operand *result, operand *left, int shCount) +{ + shiftL1Left2Result(left, LSB, result, LSB, shCount); +} + +/*-----------------------------------------------------------------*/ +/* genlshTwo - left shift two bytes by known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genlshTwo (operand *result,operand *left, int shCount) +{ + int size = AOP_SIZE(result); + + if (size == 3) + size--; + + /* if shCount >= 8 */ + if (shCount >= 8) { + shCount -= 8 ; + + if (size > 1){ + if (shCount) + shiftL1Left2Result(left, LSB, result, MSB16, shCount); + else + movLeft2Result(left, LSB, result, MSB16, 0); + } + aopPut(AOP(result),zero,LSB); + } + + /* 1 <= shCount <= 7 */ + else { + if(size == 1) + shiftL1Left2Result(left, LSB, result, LSB, shCount); + else + shiftL2Left2Result(left, LSB, result, LSB, shCount); + } +} + +/*-----------------------------------------------------------------*/ +/* shiftLLong - shift left one long from left to result */ +/* offl = LSB or MSB16 */ +/*-----------------------------------------------------------------*/ +static void shiftLLong (operand *left, operand *result, int offr ) +{ + char *l; + int size = AOP_SIZE(result); + + if(size >= LSB+offr){ + l = aopGet(AOP(left),LSB,FALSE,FALSE); + MOVA(l); + emitcode("add","a,acc"); + if (sameRegs(AOP(left),AOP(result)) && + size >= MSB16+offr && offr != LSB ) + emitcode("xch","a,%s", + aopGet(AOP(left),LSB+offr,FALSE,FALSE)); + else + aopPut(AOP(result),"a",LSB+offr); + } + + if(size >= MSB16+offr){ + if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) { + l = aopGet(AOP(left),MSB16,FALSE,FALSE); + MOVA(l); + } + emitcode("rlc","a"); + if (sameRegs(AOP(left),AOP(result)) && + size >= MSB24+offr && offr != LSB) + emitcode("xch","a,%s", + aopGet(AOP(left),MSB16+offr,FALSE,FALSE)); + else + aopPut(AOP(result),"a",MSB16+offr); + } + + if(size >= MSB24+offr){ + if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) { + l = aopGet(AOP(left),MSB24,FALSE,FALSE); + MOVA(l); + } + emitcode("rlc","a"); + if (sameRegs(AOP(left),AOP(result)) && + size >= MSB32+offr && offr != LSB ) + emitcode("xch","a,%s", + aopGet(AOP(left),MSB24+offr,FALSE,FALSE)); + else + aopPut(AOP(result),"a",MSB24+offr); + } + + if(size > MSB32+offr){ + if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) { + l = aopGet(AOP(left),MSB32,FALSE,FALSE); + MOVA(l); + } + emitcode("rlc","a"); + aopPut(AOP(result),"a",MSB32+offr); + } + if(offr != LSB) + aopPut(AOP(result),zero,LSB); +} + +/*-----------------------------------------------------------------*/ +/* genlshFour - shift four byte by a known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genlshFour (operand *result, operand *left, int shCount) +{ + int size; + + size = AOP_SIZE(result); + + /* if shifting more that 3 bytes */ + if (shCount >= 24 ) { + shCount -= 24; + if (shCount) + /* lowest order of left goes to the highest + order of the destination */ + shiftL1Left2Result(left, LSB, result, MSB32, shCount); + else + movLeft2Result(left, LSB, result, MSB32, 0); + aopPut(AOP(result),zero,LSB); + aopPut(AOP(result),zero,MSB16); + aopPut(AOP(result),zero,MSB32); + return; + } + + /* more than two bytes */ + else if ( shCount >= 16 ) { + /* lower order two bytes goes to higher order two bytes */ + shCount -= 16; + /* if some more remaining */ + if (shCount) + shiftL2Left2Result(left, LSB, result, MSB24, shCount); + else { + movLeft2Result(left, MSB16, result, MSB32, 0); + movLeft2Result(left, LSB, result, MSB24, 0); + } + aopPut(AOP(result),zero,MSB16); + aopPut(AOP(result),zero,LSB); + return; + } + + /* if more than 1 byte */ + else if ( shCount >= 8 ) { + /* lower order three bytes goes to higher order three bytes */ + shCount -= 8; + if(size == 2){ + if(shCount) + shiftL1Left2Result(left, LSB, result, MSB16, shCount); + else + movLeft2Result(left, LSB, result, MSB16, 0); + } + else{ /* size = 4 */ + if(shCount == 0){ + movLeft2Result(left, MSB24, result, MSB32, 0); + movLeft2Result(left, MSB16, result, MSB24, 0); + movLeft2Result(left, LSB, result, MSB16, 0); + aopPut(AOP(result),zero,LSB); + } + else if(shCount == 1) + shiftLLong(left, result, MSB16); + else{ + shiftL2Left2Result(left, MSB16, result, MSB24, shCount); + shiftL1Left2Result(left, LSB, result, MSB16, shCount); + shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount); + aopPut(AOP(result),zero,LSB); + } + } + } + + /* 1 <= shCount <= 7 */ + else if(shCount <= 2){ + shiftLLong(left, result, LSB); + if(shCount == 2) + shiftLLong(result, result, LSB); + } + /* 3 <= shCount <= 7, optimize */ + else{ + shiftL2Left2Result(left, MSB24, result, MSB24, shCount); + shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount); + shiftL2Left2Result(left, LSB, result, LSB, shCount); + } +} + +/*-----------------------------------------------------------------*/ +/* genLeftShiftLiteral - left shifting by known count */ +/*-----------------------------------------------------------------*/ +static void genLeftShiftLiteral (operand *left, + operand *right, + operand *result, + iCode *ic) +{ + int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int size; + + freeAsmop(right,NULL,ic,TRUE); + + aopOp(left,ic,FALSE); + aopOp(result,ic,FALSE); + + size = getSize(operandType(result)); + +#if VIEW_SIZE + emitcode("; shift left ","result %d, left %d",size, + AOP_SIZE(left)); +#endif + + /* I suppose that the left size >= result size */ + if(shCount == 0){ + while(size--){ + movLeft2Result(left, size, result, size, 0); + } + } + + else if(shCount >= (size * 8)) + while(size--) + aopPut(AOP(result),zero,size); + else{ + switch (size) { + case 1: + genlshOne (result,left,shCount); + break; + + case 2: + case 3: + genlshTwo (result,left,shCount); + break; + + case 4: + genlshFour (result,left,shCount); + break; + } + } + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genLeftShift - generates code for left shifting */ +/*-----------------------------------------------------------------*/ +static void genLeftShift (iCode *ic) +{ + operand *left,*right, *result; + int size, offset; + char *l; + symbol *tlbl , *tlbl1; + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + aopOp(right,ic,FALSE); + + /* if the shift count is known then do it + as efficiently as possible */ + if (AOP_TYPE(right) == AOP_LIT) { + genLeftShiftLiteral (left,right,result,ic); + return ; + } + + /* shift count is unknown then we have to form + a loop get the loop count in B : Note: we take + only the lower order byte since shifting + more that 32 bits make no sense anyway, ( the + largest size of an object can be only 32 bits ) */ + + emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("inc","b"); + freeAsmop (right,NULL,ic,TRUE); + aopOp(left,ic,FALSE); + aopOp(result,ic,FALSE); + + /* now move the left to the result if they are not the + same */ + if (!sameRegs(AOP(left),AOP(result)) && + AOP_SIZE(result) > 1) { + + size = AOP_SIZE(result); + offset=0; + while (size--) { + l = aopGet(AOP(left),offset,FALSE,TRUE); + if (*l == '@' && (IS_AOP_PREG(result))) { + + emitcode("mov","a,%s",l); + aopPut(AOP(result),"a",offset); + } else + aopPut(AOP(result),l,offset); + offset++; + } + } + + tlbl = newiTempLabel(NULL); + size = AOP_SIZE(result); + offset = 0 ; + tlbl1 = newiTempLabel(NULL); + + /* if it is only one byte then */ + if (size == 1) { + symbol *tlbl1 = newiTempLabel(NULL); + + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + emitcode("add","a,acc"); + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); + aopPut(AOP(result),"a",0); + goto release ; + } + + reAdjustPreg(AOP(result)); + + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + l = aopGet(AOP(result),offset,FALSE,FALSE); + MOVA(l); + emitcode("add","a,acc"); + aopPut(AOP(result),"a",offset++); + while (--size) { + l = aopGet(AOP(result),offset,FALSE,FALSE); + MOVA(l); + emitcode("rlc","a"); + aopPut(AOP(result),"a",offset++); + } + reAdjustPreg(AOP(result)); + + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); +release: + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genrshOne - right shift a one byte quantity by known count */ +/*-----------------------------------------------------------------*/ +static void genrshOne (operand *result, operand *left, + int shCount, int sign) +{ + shiftR1Left2Result(left, LSB, result, LSB, shCount, sign); +} + +/*-----------------------------------------------------------------*/ +/* genrshTwo - right shift two bytes by known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genrshTwo (operand *result,operand *left, + int shCount, int sign) +{ + /* if shCount >= 8 */ + if (shCount >= 8) { + shCount -= 8 ; + if (shCount) + shiftR1Left2Result(left, MSB16, result, LSB, + shCount, sign); + else + movLeft2Result(left, MSB16, result, LSB, sign); + addSign(result, MSB16, sign); + } + + /* 1 <= shCount <= 7 */ + else + shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); +} + +/*-----------------------------------------------------------------*/ +/* shiftRLong - shift right one long from left to result */ +/* offl = LSB or MSB16 */ +/*-----------------------------------------------------------------*/ +static void shiftRLong (operand *left, int offl, + operand *result, int sign) +{ + if(!sign) + emitcode("clr","c"); + MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE)); + if(sign) + emitcode("mov","c,acc.7"); + emitcode("rrc","a"); + aopPut(AOP(result),"a",MSB32-offl); + if(offl == MSB16) + /* add sign of "a" */ + addSign(result, MSB32, sign); + + MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE)); + emitcode("rrc","a"); + aopPut(AOP(result),"a",MSB24-offl); + + MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE)); + emitcode("rrc","a"); + aopPut(AOP(result),"a",MSB16-offl); + + if(offl == LSB){ + MOVA(aopGet(AOP(left),LSB,FALSE,FALSE)); + emitcode("rrc","a"); + aopPut(AOP(result),"a",LSB); + } +} + +/*-----------------------------------------------------------------*/ +/* genrshFour - shift four byte by a known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genrshFour (operand *result, operand *left, + int shCount, int sign) +{ + /* if shifting more that 3 bytes */ + if(shCount >= 24 ) { + shCount -= 24; + if(shCount) + shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign); + else + movLeft2Result(left, MSB32, result, LSB, sign); + addSign(result, MSB16, sign); + } + else if(shCount >= 16){ + shCount -= 16; + if(shCount) + shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign); + else{ + movLeft2Result(left, MSB24, result, LSB, 0); + movLeft2Result(left, MSB32, result, MSB16, sign); + } + addSign(result, MSB24, sign); + } + else if(shCount >= 8){ + shCount -= 8; + if(shCount == 1) + shiftRLong(left, MSB16, result, sign); + else if(shCount == 0){ + movLeft2Result(left, MSB16, result, LSB, 0); + movLeft2Result(left, MSB24, result, MSB16, 0); + movLeft2Result(left, MSB32, result, MSB24, sign); + addSign(result, MSB32, sign); + } + else{ + shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0); + shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount); + /* the last shift is signed */ + shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign); + addSign(result, MSB32, sign); + } + } + else{ /* 1 <= shCount <= 7 */ + if(shCount <= 2){ + shiftRLong(left, LSB, result, sign); + if(shCount == 2) + shiftRLong(result, LSB, result, sign); + } + else{ + shiftR2Left2Result(left, LSB, result, LSB, shCount, 0); + shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount); + shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign); + } + } +} + +/*-----------------------------------------------------------------*/ +/* genRightShiftLiteral - right shifting by known count */ +/*-----------------------------------------------------------------*/ +static void genRightShiftLiteral (operand *left, + operand *right, + operand *result, + iCode *ic, + int sign) +{ + int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int size; + + freeAsmop(right,NULL,ic,TRUE); + + aopOp(left,ic,FALSE); + aopOp(result,ic,FALSE); + +#if VIEW_SIZE + emitcode("; shift right ","result %d, left %d",AOP_SIZE(result), + AOP_SIZE(left)); +#endif + + size = getDataSize(left); + /* test the LEFT size !!! */ + + /* I suppose that the left size >= result size */ + if(shCount == 0){ + size = getDataSize(result); + while(size--) + movLeft2Result(left, size, result, size, 0); + } + + else if(shCount >= (size * 8)){ + if(sign) + /* get sign in acc.7 */ + MOVA(aopGet(AOP(left),size-1,FALSE,FALSE)); + addSign(result, LSB, sign); + } else{ + switch (size) { + case 1: + genrshOne (result,left,shCount,sign); + break; + + case 2: + genrshTwo (result,left,shCount,sign); + break; + + case 4: + genrshFour (result,left,shCount,sign); + break; + default : + break; + } + + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); + } +} + +/*-----------------------------------------------------------------*/ +/* genSignedRightShift - right shift of signed number */ +/*-----------------------------------------------------------------*/ +static void genSignedRightShift (iCode *ic) +{ + operand *right, *left, *result; + int size, offset; + char *l; + symbol *tlbl, *tlbl1 ; + + /* we do it the hard way put the shift count in b + and loop thru preserving the sign */ + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + aopOp(right,ic,FALSE); + + + if ( AOP_TYPE(right) == AOP_LIT) { + genRightShiftLiteral (left,right,result,ic,1); + return ; + } + /* shift count is unknown then we have to form + a loop get the loop count in B : Note: we take + only the lower order byte since shifting + more that 32 bits make no sense anyway, ( the + largest size of an object can be only 32 bits ) */ + + emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("inc","b"); + freeAsmop (right,NULL,ic,TRUE); + aopOp(left,ic,FALSE); + aopOp(result,ic,FALSE); + + /* now move the left to the result if they are not the + same */ + if (!sameRegs(AOP(left),AOP(result)) && + AOP_SIZE(result) > 1) { + + size = AOP_SIZE(result); + offset=0; + while (size--) { + l = aopGet(AOP(left),offset,FALSE,TRUE); + if (*l == '@' && IS_AOP_PREG(result)) { + + emitcode("mov","a,%s",l); + aopPut(AOP(result),"a",offset); + } else + aopPut(AOP(result),l,offset); + offset++; + } + } + + /* mov the highest order bit to OVR */ + tlbl = newiTempLabel(NULL); + tlbl1= newiTempLabel(NULL); + + size = AOP_SIZE(result); + offset = size - 1; + emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE)); + emitcode("rlc","a"); + emitcode("mov","ov,c"); + /* if it is only one byte then */ + if (size == 1) { + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + emitcode("mov","c,ov"); + emitcode("rrc","a"); + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); + aopPut(AOP(result),"a",0); + goto release ; + } + + reAdjustPreg(AOP(result)); + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + emitcode("mov","c,ov"); + while (size--) { + l = aopGet(AOP(result),offset,FALSE,FALSE); + MOVA(l); + emitcode("rrc","a"); + aopPut(AOP(result),"a",offset--); + } + reAdjustPreg(AOP(result)); + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); + +release: + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genRightShift - generate code for right shifting */ +/*-----------------------------------------------------------------*/ +static void genRightShift (iCode *ic) +{ + operand *right, *left, *result; + link *retype ; + int size, offset; + char *l; + symbol *tlbl, *tlbl1 ; + + /* if signed then we do it the hard way preserve the + sign bit moving it inwards */ + retype = getSpec(operandType(IC_RESULT(ic))); + + if (!SPEC_USIGN(retype)) { + genSignedRightShift (ic); + return ; + } + + /* signed & unsigned types are treated the same : i.e. the + signed is NOT propagated inwards : quoting from the + ANSI - standard : "for E1 >> E2, is equivalent to division + by 2**E2 if unsigned or if it has a non-negative value, + otherwise the result is implementation defined ", MY definition + is that the sign does not get propagated */ + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + aopOp(right,ic,FALSE); + + /* if the shift count is known then do it + as efficiently as possible */ + if (AOP_TYPE(right) == AOP_LIT) { + genRightShiftLiteral (left,right,result,ic, 0); + return ; + } + + /* shift count is unknown then we have to form + a loop get the loop count in B : Note: we take + only the lower order byte since shifting + more that 32 bits make no sense anyway, ( the + largest size of an object can be only 32 bits ) */ + + emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE)); + emitcode("inc","b"); + freeAsmop (right,NULL,ic,TRUE); + aopOp(left,ic,FALSE); + aopOp(result,ic,FALSE); + + /* now move the left to the result if they are not the + same */ + if (!sameRegs(AOP(left),AOP(result)) && + AOP_SIZE(result) > 1) { + + size = AOP_SIZE(result); + offset=0; + while (size--) { + l = aopGet(AOP(left),offset,FALSE,TRUE); + if (*l == '@' && IS_AOP_PREG(result)) { + + emitcode("mov","a,%s",l); + aopPut(AOP(result),"a",offset); + } else + aopPut(AOP(result),l,offset); + offset++; + } + } + + tlbl = newiTempLabel(NULL); + tlbl1= newiTempLabel(NULL); + size = AOP_SIZE(result); + offset = size - 1; + + /* if it is only one byte then */ + if (size == 1) { + l = aopGet(AOP(left),0,FALSE,FALSE); + MOVA(l); + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + CLRC; + emitcode("rrc","a"); + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); + aopPut(AOP(result),"a",0); + goto release ; + } + + reAdjustPreg(AOP(result)); + emitcode("sjmp","%05d$",tlbl1->key+100); + emitcode("","%05d$:",tlbl->key+100); + CLRC; + while (size--) { + l = aopGet(AOP(result),offset,FALSE,FALSE); + MOVA(l); + emitcode("rrc","a"); + aopPut(AOP(result),"a",offset--); + } + reAdjustPreg(AOP(result)); + + emitcode("","%05d$:",tlbl1->key+100); + emitcode("djnz","b,%05d$",tlbl->key+100); + +release: + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genUnpackBits - generates code for unpacking bits */ +/*-----------------------------------------------------------------*/ +static void genUnpackBits (operand *result, char *rname, int ptype) +{ + int shCnt ; + int rlen = 0 ; + link *etype; + int offset = 0 ; + + etype = getSpec(operandType(result)); + + /* read the first byte */ + switch (ptype) { + + case POINTER: + case IPOINTER: + emitcode("mov","a,@%s",rname); + break; + + case PPOINTER: + emitcode("movx","a,@%s",rname); + break; + + case FPOINTER: + emitcode("movx","a,@dptr"); + break; + + case CPOINTER: + emitcode("clr","a"); + emitcode("movc","a","@a+dptr"); + break; + + case GPOINTER: + emitcode("lcall","__gptrget"); + break; + } + + /* if we have bitdisplacement then it fits */ + /* into this byte completely or if length is */ + /* less than a byte */ + if ((shCnt = SPEC_BSTR(etype)) || + (SPEC_BLEN(etype) <= 8)) { + + /* shift right acc */ + AccRsh(shCnt); + + emitcode("anl","a,#0x%02x", + ((unsigned char) -1)>>(8 - SPEC_BLEN(etype))); + aopPut(AOP(result),"a",offset); + return ; + } + + /* bit field did not fit in a byte */ + rlen = SPEC_BLEN(etype) - 8; + aopPut(AOP(result),"a",offset++); + + while (1) { + + switch (ptype) { + case POINTER: + case IPOINTER: + emitcode("inc","%s",rname); + emitcode("mov","a,@%s",rname); + break; + + case PPOINTER: + emitcode("inc","%s",rname); + emitcode("movx","a,@%s",rname); + break; + + case FPOINTER: + emitcode("inc","dptr"); + emitcode("movx","a,@dptr"); + break; + + case CPOINTER: + emitcode("clr","a"); + emitcode("inc","dptr"); + emitcode("movc","a","@a+dptr"); + break; + + case GPOINTER: + emitcode("inc","dptr"); + emitcode("lcall","__gptrget"); + break; + } + + rlen -= 8; + /* if we are done */ + if ( rlen <= 0 ) + break ; + + aopPut(AOP(result),"a",offset++); + + } + + if (rlen) { + emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen)); + aopPut(AOP(result),"a",offset); + } + + return ; +} + + +/*-----------------------------------------------------------------*/ +/* genDataPointerGet - generates code when ptr offset is known */ +/*-----------------------------------------------------------------*/ +static void genDataPointerGet (operand *left, + operand *result, + iCode *ic) +{ + char *l; + char buffer[256]; + int size , offset = 0; + aopOp(result,ic,TRUE); + + /* get the string representation of the name */ + l = aopGet(AOP(left),0,FALSE,TRUE); + size = AOP_SIZE(result); + while (size--) { + if (offset) + sprintf(buffer,"(%s + %d)",l+1,offset); + else + sprintf(buffer,"%s",l+1); + aopPut(AOP(result),buffer,offset++); + } + + freeAsmop(left,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genNearPointerGet - emitcode for near pointer fetch */ +/*-----------------------------------------------------------------*/ +static void genNearPointerGet (operand *left, + operand *result, + iCode *ic) +{ + asmop *aop = NULL; + regs *preg = NULL ; + char *rname ; + link *rtype, *retype; + link *ltype = operandType(left); + char buffer[80]; + + rtype = operandType(result); + retype= getSpec(rtype); + + aopOp(left,ic,FALSE); + + /* if left is rematerialisable and + result is not bit variable type and + the left is pointer to data space i.e + lower 128 bytes of space */ + if (AOP_TYPE(left) == AOP_IMMD && + !IS_BITVAR(retype) && + DCL_TYPE(ltype) == POINTER) { + genDataPointerGet (left,result,ic); + return ; + } + + /* if the value is already in a pointer register + then don't need anything more */ + if (!AOP_INPREG(AOP(left))) { + /* otherwise get a free pointer register */ + aop = newAsmop(0); + preg = getFreePtr(ic,&aop,FALSE); + emitcode("mov","%s,%s", + preg->name, + aopGet(AOP(left),0,FALSE,TRUE)); + rname = preg->name ; + } else + rname = aopGet(AOP(left),0,FALSE,FALSE); + + freeAsmop(left,NULL,ic,TRUE); + aopOp (result,ic,FALSE); + + /* if bitfield then unpack the bits */ + if (IS_BITVAR(retype)) + genUnpackBits (result,rname,POINTER); + else { + /* we have can just get the values */ + int size = AOP_SIZE(result); + int offset = 0 ; + + while (size--) { + if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) { + + emitcode("mov","a,@%s",rname); + aopPut(AOP(result),"a",offset); + } else { + sprintf(buffer,"@%s",rname); + aopPut(AOP(result),buffer,offset); + } + offset++ ; + if (size) + emitcode("inc","%s",rname); + } + } + + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + already in a pointer register, then + if size > 0 && this could be used again + we have to point it back to where it + belongs */ + if (AOP_SIZE(result) > 1 && + !OP_SYMBOL(left)->remat && + ( OP_SYMBOL(left)->liveTo > ic->seq || + ic->depth )) { + int size = AOP_SIZE(result) - 1; + while (size--) + emitcode("dec","%s",rname); + } + } + + /* done */ + freeAsmop(result,NULL,ic,TRUE); + +} + +/*-----------------------------------------------------------------*/ +/* genPagedPointerGet - emitcode for paged pointer fetch */ +/*-----------------------------------------------------------------*/ +static void genPagedPointerGet (operand *left, + operand *result, + iCode *ic) +{ + asmop *aop = NULL; + regs *preg = NULL ; + char *rname ; + link *rtype, *retype; + + rtype = operandType(result); + retype= getSpec(rtype); + + aopOp(left,ic,FALSE); + + /* if the value is already in a pointer register + then don't need anything more */ + if (!AOP_INPREG(AOP(left))) { + /* otherwise get a free pointer register */ + aop = newAsmop(0); + preg = getFreePtr(ic,&aop,FALSE); + emitcode("mov","%s,%s", + preg->name, + aopGet(AOP(left),0,FALSE,TRUE)); + rname = preg->name ; + } else + rname = aopGet(AOP(left),0,FALSE,FALSE); + + freeAsmop(left,NULL,ic,TRUE); + aopOp (result,ic,FALSE); + + /* if bitfield then unpack the bits */ + if (IS_BITVAR(retype)) + genUnpackBits (result,rname,PPOINTER); + else { + /* we have can just get the values */ + int size = AOP_SIZE(result); + int offset = 0 ; + + while (size--) { + + emitcode("movx","a,@%s",rname); + aopPut(AOP(result),"a",offset); + + offset++ ; + + if (size) + emitcode("inc","%s",rname); + } + } + + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + already in a pointer register, then + if size > 0 && this could be used again + we have to point it back to where it + belongs */ + if (AOP_SIZE(result) > 1 && + !OP_SYMBOL(left)->remat && + ( OP_SYMBOL(left)->liveTo > ic->seq || + ic->depth )) { + int size = AOP_SIZE(result) - 1; + while (size--) + emitcode("dec","%s",rname); + } + } + + /* done */ + freeAsmop(result,NULL,ic,TRUE); + + +} + +/*-----------------------------------------------------------------*/ +/* genFarPointerGet - gget value from far space */ +/*-----------------------------------------------------------------*/ +static void genFarPointerGet (operand *left, + operand *result, iCode *ic) +{ + int size, offset ; + link *retype = getSpec(operandType(result)); + + aopOp(left,ic,FALSE); + + /* if the operand is already in dptr + then we do nothing else we move the value to dptr */ + if (AOP_TYPE(left) != AOP_STR) { + /* if this is remateriazable */ + if (AOP_TYPE(left) == AOP_IMMD) + emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE)); + else { /* we need to get it byte by byte */ + emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE)); + emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE)); + } + } + /* so dptr know contains the address */ + freeAsmop(left,NULL,ic,TRUE); + aopOp(result,ic,FALSE); + + /* if bit then unpack */ + if (IS_BITVAR(retype)) + genUnpackBits(result,"dptr",FPOINTER); + else { + size = AOP_SIZE(result); + offset = 0 ; + + while (size--) { + emitcode("movx","a,@dptr"); + aopPut(AOP(result),"a",offset++); + if (size) + emitcode("inc","dptr"); + } + } + + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* emitcodePointerGet - gget value from code space */ +/*-----------------------------------------------------------------*/ +static void emitcodePointerGet (operand *left, + operand *result, iCode *ic) +{ + int size, offset ; + link *retype = getSpec(operandType(result)); + + aopOp(left,ic,FALSE); + + /* if the operand is already in dptr + then we do nothing else we move the value to dptr */ + if (AOP_TYPE(left) != AOP_STR) { + /* if this is remateriazable */ + if (AOP_TYPE(left) == AOP_IMMD) + emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE)); + else { /* we need to get it byte by byte */ + emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE)); + emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE)); + } + } + /* so dptr know contains the address */ + freeAsmop(left,NULL,ic,TRUE); + aopOp(result,ic,FALSE); + + /* if bit then unpack */ + if (IS_BITVAR(retype)) + genUnpackBits(result,"dptr",CPOINTER); + else { + size = AOP_SIZE(result); + offset = 0 ; + + while (size--) { + emitcode("clr","a"); + emitcode("movc","a,@a+dptr"); + aopPut(AOP(result),"a",offset++); + if (size) + emitcode("inc","dptr"); + } + } + + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGenPointerGet - gget value from generic pointer space */ +/*-----------------------------------------------------------------*/ +static void genGenPointerGet (operand *left, + operand *result, iCode *ic) +{ + int size, offset ; + link *retype = getSpec(operandType(result)); + + aopOp(left,ic,FALSE); + + /* if the operand is already in dptr + then we do nothing else we move the value to dptr */ + if (AOP_TYPE(left) != AOP_STR) { + /* if this is remateriazable */ + if (AOP_TYPE(left) == AOP_IMMD) { + emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE)); + emitcode("mov","b,#%d",pointerCode(retype)); + } + else { /* we need to get it byte by byte */ + emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE)); + emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE)); + emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE)); + } + } + /* so dptr know contains the address */ + freeAsmop(left,NULL,ic,TRUE); + aopOp(result,ic,FALSE); + + /* if bit then unpack */ + if (IS_BITVAR(retype)) + genUnpackBits(result,"dptr",GPOINTER); + else { + size = AOP_SIZE(result); + offset = 0 ; + + while (size--) { + emitcode("lcall","__gptrget"); + aopPut(AOP(result),"a",offset++); + if (size) + emitcode("inc","dptr"); + } + } + + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genPointerGet - generate code for pointer get */ +/*-----------------------------------------------------------------*/ +static void genPointerGet (iCode *ic) +{ + operand *left, *result ; + link *type, *etype; + int p_type; + + left = IC_LEFT(ic); + result = IC_RESULT(ic) ; + + /* depending on the type of pointer we need to + move it to the correct pointer register */ + type = operandType(left); + etype = getSpec(type); + /* if left is of type of pointer then it is simple */ + if (IS_PTR(type) && !IS_FUNC(type->next)) + p_type = DCL_TYPE(type); + else { + + /* we have to go by the storage class */ + if (SPEC_OCLS(etype)->codesp ) { + p_type = CPOINTER ; + } + else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) + p_type = FPOINTER ; + else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) + p_type = PPOINTER; + else + if (SPEC_OCLS(etype) == idata ) + p_type = IPOINTER; + else + p_type = POINTER ; + } + + /* now that we have the pointer type we assign + the pointer values */ + switch (p_type) { + + case POINTER: + case IPOINTER: + genNearPointerGet (left,result,ic); + break; + + case PPOINTER: + genPagedPointerGet(left,result,ic); + break; + + case FPOINTER: + genFarPointerGet (left,result,ic); + break; + + case CPOINTER: + emitcodePointerGet (left,result,ic); + break; + + case GPOINTER: + genGenPointerGet (left,result,ic); + break; + } + +} + +/*-----------------------------------------------------------------*/ +/* genPackBits - generates code for packed bit storage */ +/*-----------------------------------------------------------------*/ +static void genPackBits (link *etype , + operand *right , + char *rname, int p_type) +{ + int shCount = 0 ; + int offset = 0 ; + int rLen = 0 ; + int blen, bstr ; + char *l ; + + blen = SPEC_BLEN(etype); + bstr = SPEC_BSTR(etype); + + l = aopGet(AOP(right),offset++,FALSE,FALSE); + MOVA(l); + + /* if the bit lenth is less than or */ + /* it exactly fits a byte then */ + if (SPEC_BLEN(etype) <= 8 ) { + shCount = SPEC_BSTR(etype) ; + + /* shift left acc */ + AccLsh(shCount); + + if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */ + + + switch (p_type) { + case POINTER: + emitcode ("mov","b,a"); + emitcode("mov","a,@%s",rname); + break; + + case FPOINTER: + emitcode ("mov","b,a"); + emitcode("movx","a,@dptr"); + break; + + case GPOINTER: + emitcode ("push","b"); + emitcode ("push","acc"); + emitcode ("lcall","__gptrget"); + emitcode ("pop","b"); + break; + } + + emitcode ("anl","a,#0x%02x",(unsigned char) + ((unsigned char)(0xFF << (blen+bstr)) | + (unsigned char)(0xFF >> (8-bstr)) ) ); + emitcode ("orl","a,b"); + if (p_type == GPOINTER) + emitcode("pop","b"); + } + } + + switch (p_type) { + case POINTER: + emitcode("mov","@%s,a",rname); + break; + + case FPOINTER: + emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + emitcode("lcall","__gptrput"); + break; + } + + /* if we r done */ + if ( SPEC_BLEN(etype) <= 8 ) + return ; + + emitcode("inc","%s",rname); + rLen = SPEC_BLEN(etype) ; + + /* now generate for lengths greater than one byte */ + while (1) { + + l = aopGet(AOP(right),offset++,FALSE,TRUE); + + rLen -= 8 ; + if (rLen <= 0 ) + break ; + + switch (p_type) { + case POINTER: + if (*l == '@') { + MOVA(l); + emitcode("mov","@%s,a",rname); + } else + emitcode("mov","@%s,%s",rname,l); + break; + + case FPOINTER: + MOVA(l); + emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + MOVA(l); + emitcode("lcall","__gptrput"); + break; + } + emitcode ("inc","%s",rname); + } + + MOVA(l); + + /* last last was not complete */ + if (rLen) { + /* save the byte & read byte */ + switch (p_type) { + case POINTER: + emitcode ("mov","b,a"); + emitcode("mov","a,@%s",rname); + break; + + case FPOINTER: + emitcode ("mov","b,a"); + emitcode("movx","a,@dptr"); + break; + + case GPOINTER: + emitcode ("push","b"); + emitcode ("push","acc"); + emitcode ("lcall","__gptrget"); + emitcode ("pop","b"); + break; + } + + emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); + emitcode ("orl","a,b"); + } + + if (p_type == GPOINTER) + emitcode("pop","b"); + + switch (p_type) { + + case POINTER: + emitcode("mov","@%s,a",rname); + break; + + case FPOINTER: + emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + emitcode("lcall","__gptrput"); + break; + } +} +/*-----------------------------------------------------------------*/ +/* genDataPointerSet - remat pointer to data space */ +/*-----------------------------------------------------------------*/ +static void genDataPointerSet(operand *right, + operand *result, + iCode *ic) +{ + int size, offset = 0 ; + char *l, buffer[256]; + + aopOp(right,ic,FALSE); + + l = aopGet(AOP(result),0,FALSE,TRUE); + size = AOP_SIZE(right); + while (size--) { + if (offset) + sprintf(buffer,"(%s + %d)",l+1,offset); + else + sprintf(buffer,"%s",l+1); + emitcode("mov","%s,%s",buffer, + aopGet(AOP(right),offset++,FALSE,FALSE)); + } + + freeAsmop(right,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genNearPointerSet - emitcode for near pointer put */ +/*-----------------------------------------------------------------*/ +static void genNearPointerSet (operand *right, + operand *result, + iCode *ic) +{ + asmop *aop = NULL; + regs *preg = NULL ; + char *rname , *l; + link *retype; + link *ptype = operandType(result); + + retype= getSpec(operandType(right)); + + aopOp(result,ic,FALSE); + + /* if the result is rematerializable & + in data space & not a bit variable */ + if (AOP_TYPE(result) == AOP_IMMD && + DCL_TYPE(ptype) == POINTER && + !IS_BITVAR(retype)) { + genDataPointerSet (right,result,ic); + return; + } + + /* if the value is already in a pointer register + then don't need anything more */ + if (!AOP_INPREG(AOP(result))) { + /* otherwise get a free pointer register */ + aop = newAsmop(0); + preg = getFreePtr(ic,&aop,FALSE); + emitcode("mov","%s,%s", + preg->name, + aopGet(AOP(result),0,FALSE,TRUE)); + rname = preg->name ; + } else + rname = aopGet(AOP(result),0,FALSE,FALSE); + + freeAsmop(result,NULL,ic,TRUE); + aopOp (right,ic,FALSE); + + /* if bitfield then unpack the bits */ + if (IS_BITVAR(retype)) + genPackBits (retype,right,rname,POINTER); + else { + /* we have can just get the values */ + int size = AOP_SIZE(right); + int offset = 0 ; + + while (size--) { + l = aopGet(AOP(right),offset,FALSE,TRUE); + if (*l == '@' ) { + MOVA(l); + emitcode("mov","@%s,a",rname); + } else + emitcode("mov","@%s,%s",rname,l); + if (size) + emitcode("inc","%s",rname); + offset++; + } + } + + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + already in a pointer register, then + if size > 0 && this could be used again + we have to point it back to where it + belongs */ + if (AOP_SIZE(right) > 1 && + !OP_SYMBOL(result)->remat && + ( OP_SYMBOL(result)->liveTo > ic->seq || + ic->depth )) { + int size = AOP_SIZE(right) - 1; + while (size--) + emitcode("dec","%s",rname); + } + } + + /* done */ + freeAsmop(right,NULL,ic,TRUE); + + +} + +/*-----------------------------------------------------------------*/ +/* genPagedPointerSet - emitcode for Paged pointer put */ +/*-----------------------------------------------------------------*/ +static void genPagedPointerSet (operand *right, + operand *result, + iCode *ic) +{ + asmop *aop = NULL; + regs *preg = NULL ; + char *rname , *l; + link *retype; + + retype= getSpec(operandType(right)); + + aopOp(result,ic,FALSE); + + /* if the value is already in a pointer register + then don't need anything more */ + if (!AOP_INPREG(AOP(result))) { + /* otherwise get a free pointer register */ + aop = newAsmop(0); + preg = getFreePtr(ic,&aop,FALSE); + emitcode("mov","%s,%s", + preg->name, + aopGet(AOP(result),0,FALSE,TRUE)); + rname = preg->name ; + } else + rname = aopGet(AOP(result),0,FALSE,FALSE); + + freeAsmop(result,NULL,ic,TRUE); + aopOp (right,ic,FALSE); + + /* if bitfield then unpack the bits */ + if (IS_BITVAR(retype)) + genPackBits (retype,right,rname,PPOINTER); + else { + /* we have can just get the values */ + int size = AOP_SIZE(right); + int offset = 0 ; + + while (size--) { + l = aopGet(AOP(right),offset,FALSE,TRUE); + + MOVA(l); + emitcode("movx","@%s,a",rname); + + if (size) + emitcode("inc","%s",rname); + + offset++; + } + } + + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + already in a pointer register, then + if size > 0 && this could be used again + we have to point it back to where it + belongs */ + if (AOP_SIZE(right) > 1 && + !OP_SYMBOL(result)->remat && + ( OP_SYMBOL(result)->liveTo > ic->seq || + ic->depth )) { + int size = AOP_SIZE(right) - 1; + while (size--) + emitcode("dec","%s",rname); + } + } + + /* done */ + freeAsmop(right,NULL,ic,TRUE); + + +} + +/*-----------------------------------------------------------------*/ +/* genFarPointerSet - set value from far space */ +/*-----------------------------------------------------------------*/ +static void genFarPointerSet (operand *right, + operand *result, iCode *ic) +{ + int size, offset ; + link *retype = getSpec(operandType(right)); + + aopOp(result,ic,FALSE); + + /* if the operand is already in dptr + then we do nothing else we move the value to dptr */ + if (AOP_TYPE(result) != AOP_STR) { + /* if this is remateriazable */ + if (AOP_TYPE(result) == AOP_IMMD) + emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE)); + else { /* we need to get it byte by byte */ + emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE)); + emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE)); + } + } + /* so dptr know contains the address */ + freeAsmop(result,NULL,ic,TRUE); + aopOp(right,ic,FALSE); + + /* if bit then unpack */ + if (IS_BITVAR(retype)) + genPackBits(retype,right,"dptr",FPOINTER); + else { + size = AOP_SIZE(right); + offset = 0 ; + + while (size--) { + char *l = aopGet(AOP(right),offset++,FALSE,FALSE); + MOVA(l); + emitcode("movx","@dptr,a"); + if (size) + emitcode("inc","dptr"); + } + } + + freeAsmop(right,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGenPointerSet - set value from generic pointer space */ +/*-----------------------------------------------------------------*/ +static void genGenPointerSet (operand *right, + operand *result, iCode *ic) +{ + int size, offset ; + link *retype = getSpec(operandType(right)); + + aopOp(result,ic,FALSE); + + /* if the operand is already in dptr + then we do nothing else we move the value to dptr */ + if (AOP_TYPE(result) != AOP_STR) { + /* if this is remateriazable */ + if (AOP_TYPE(result) == AOP_IMMD) { + emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE)); + emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE)); + } + else { /* we need to get it byte by byte */ + emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE)); + emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE)); + emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE)); + } + } + /* so dptr know contains the address */ + freeAsmop(result,NULL,ic,TRUE); + aopOp(right,ic,FALSE); + + /* if bit then unpack */ + if (IS_BITVAR(retype)) + genPackBits(retype,right,"dptr",GPOINTER); + else { + size = AOP_SIZE(right); + offset = 0 ; + + while (size--) { + char *l = aopGet(AOP(right),offset++,FALSE,FALSE); + MOVA(l); + emitcode("lcall","__gptrput"); + if (size) + emitcode("inc","dptr"); + } + } + + freeAsmop(right,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genPointerSet - stores the value into a pointer location */ +/*-----------------------------------------------------------------*/ +static void genPointerSet (iCode *ic) +{ + operand *right, *result ; + link *type, *etype; + int p_type; + + right = IC_RIGHT(ic); + result = IC_RESULT(ic) ; + + /* depending on the type of pointer we need to + move it to the correct pointer register */ + type = operandType(result); + etype = getSpec(type); + /* if left is of type of pointer then it is simple */ + if (IS_PTR(type) && !IS_FUNC(type->next)) { + p_type = DCL_TYPE(type); + } + else { + + /* we have to go by the storage class */ + if (SPEC_OCLS(etype)->codesp ) { + p_type = CPOINTER ; + } + else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) + p_type = FPOINTER ; + else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) + p_type = PPOINTER ; + else + if (SPEC_OCLS(etype) == idata ) + p_type = IPOINTER ; + else + p_type = POINTER ; + } + + /* now that we have the pointer type we assign + the pointer values */ + switch (p_type) { + + case POINTER: + case IPOINTER: + genNearPointerSet (right,result,ic); + break; + + case PPOINTER: + genPagedPointerSet (right,result,ic); + break; + + case FPOINTER: + genFarPointerSet (right,result,ic); + break; + + case GPOINTER: + genGenPointerSet (right,result,ic); + break; + } + +} + +/*-----------------------------------------------------------------*/ +/* genIfx - generate code for Ifx statement */ +/*-----------------------------------------------------------------*/ +static void genIfx (iCode *ic, iCode *popIc) +{ + operand *cond = IC_COND(ic); + int isbit =0; + + aopOp(cond,ic,FALSE); + + /* get the value into acc */ + if (AOP_TYPE(cond) != AOP_CRY) + toBoolean(cond); + else + isbit = 1; + /* the result is now in the accumulator */ + freeAsmop(cond,NULL,ic,TRUE); + + /* if there was something to be popped then do it */ + if (popIc) + genIpop(popIc); + + /* if the condition is a bit variable */ + if (isbit && IS_ITEMP(cond) && + SPIL_LOC(cond)) + genIfxJump(ic,SPIL_LOC(cond)->rname); + else + if (isbit && !IS_ITEMP(cond)) + genIfxJump(ic,OP_SYMBOL(cond)->rname); + else + genIfxJump(ic,"a"); + + ic->generated = 1; +} + +/*-----------------------------------------------------------------*/ +/* genAddrOf - generates code for address of */ +/*-----------------------------------------------------------------*/ +static void genAddrOf (iCode *ic) +{ + symbol *sym = OP_SYMBOL(IC_LEFT(ic)); + int size, offset ; + + aopOp(IC_RESULT(ic),ic,FALSE); + + /* if the operand is on the stack then we + need to get the stack offset of this + variable */ + if (sym->onStack) { + /* if it has an offset then we need to compute + it */ + if (sym->stack) { + emitcode("mov","a,_bp"); + emitcode("add","a,#0x%02x",((char) sym->stack & 0xff)); + aopPut(AOP(IC_RESULT(ic)),"a",0); + } else + /* we can just move _bp */ + aopPut(AOP(IC_RESULT(ic)),"_bp",0); + /* fill the result with zero */ + size = AOP_SIZE(IC_RESULT(ic)) - 1; + offset = 1; + while (size--) + aopPut(AOP(IC_RESULT(ic)),zero,offset++); + + goto release; + } + + /* object not on stack then we need the name */ + size = AOP_SIZE(IC_RESULT(ic)); + offset = 0; + + while (size--) { + char s[SDCC_NAME_MAX]; + if (offset) + sprintf(s,"#(%s >> %d)", + sym->rname, + offset*8); + else + sprintf(s,"#%s",sym->rname); + aopPut(AOP(IC_RESULT(ic)),s,offset++); + } + +release: + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + +} + +/*-----------------------------------------------------------------*/ +/* genFarFarAssign - assignment when both are in far space */ +/*-----------------------------------------------------------------*/ +static void genFarFarAssign (operand *result, operand *right, iCode *ic) +{ + int size = AOP_SIZE(right); + int offset = 0; + char *l ; + /* first push the right side on to the stack */ + while (size--) { + l = aopGet(AOP(right),offset++,FALSE,FALSE); + MOVA(l); + emitcode ("push","acc"); + } + + freeAsmop(right,NULL,ic,FALSE); + /* now assign DPTR to result */ + aopOp(result,ic,FALSE); + size = AOP_SIZE(result); + while (size--) { + emitcode ("pop","acc"); + aopPut(AOP(result),"a",--offset); + } + freeAsmop(result,NULL,ic,FALSE); + +} + +/*-----------------------------------------------------------------*/ +/* genAssign - generate code for assignment */ +/*-----------------------------------------------------------------*/ +static void genAssign (iCode *ic) +{ + operand *result, *right; + int size, offset ; + unsigned long lit = 0L; + + result = IC_RESULT(ic); + right = IC_RIGHT(ic) ; + + /* if they are the same */ + if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) + return ; + + aopOp(right,ic,FALSE); + + /* special case both in far space */ + if (AOP_TYPE(right) == AOP_DPTR && + IS_TRUE_SYMOP(result) && + isOperandInFarSpace(result)) { + + genFarFarAssign (result,right,ic); + return ; + } + + aopOp(result,ic,TRUE); + + /* if they are the same registers */ + if (sameRegs(AOP(right),AOP(result))) + goto release; + + /* if the result is a bit */ + if (AOP_TYPE(result) == AOP_CRY) { + + /* if the right size is a literal then + we know what the value is */ + if (AOP_TYPE(right) == AOP_LIT) { + if (((int) operandLitValue(right))) + aopPut(AOP(result),one,0); + else + aopPut(AOP(result),zero,0); + goto release; + } + + /* the right is also a bit variable */ + if (AOP_TYPE(right) == AOP_CRY) { + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + aopPut(AOP(result),"c",0); + goto release ; + } + + /* we need to or */ + toBoolean(right); + aopPut(AOP(result),"a",0); + goto release ; + } + + /* bit variables done */ + /* general case */ + size = AOP_SIZE(result); + offset = 0 ; + if(AOP_TYPE(right) == AOP_LIT) + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + if((size > 1) && + (AOP_TYPE(result) != AOP_REG) && + (AOP_TYPE(right) == AOP_LIT) && + !IS_FLOAT(operandType(right)) && + (lit < 256L)){ + emitcode("clr","a"); + while (size--) { + if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) + aopPut(AOP(result),"a",size); + else + aopPut(AOP(result), + aopGet(AOP(right),size,FALSE,FALSE), + size); + } + } else { + while (size--) { + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE,FALSE), + offset); + offset++; + } + } + +release: + freeAsmop (right,NULL,ic,FALSE); + freeAsmop (result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genJumpTab - genrates code for jump table */ +/*-----------------------------------------------------------------*/ +static void genJumpTab (iCode *ic) +{ + symbol *jtab; + char *l; + + aopOp(IC_JTCOND(ic),ic,FALSE); + /* get the condition into accumulator */ + l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE); + MOVA(l); + /* multiply by three */ + emitcode("add","a,acc"); + emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE)); + freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE); + + jtab = newiTempLabel(NULL); + emitcode("mov","dptr,#%05d$",jtab->key+100); + emitcode("jmp","@a+dptr"); + emitcode("","%05d$:",jtab->key+100); + /* now generate the jump labels */ + for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab; + jtab = setNextItem(IC_JTLABELS(ic))) + emitcode("ljmp","%05d$",jtab->key+100); + +} + +/*-----------------------------------------------------------------*/ +/* genCast - gen code for casting */ +/*-----------------------------------------------------------------*/ +static void genCast (iCode *ic) +{ + operand *result = IC_RESULT(ic); + link *ctype = operandType(IC_LEFT(ic)); + operand *right = IC_RIGHT(ic); + int size, offset ; + + /* if they are equivalent then do nothing */ + if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic))) + return ; + + aopOp(right,ic,FALSE) ; + aopOp(result,ic,FALSE); + + /* if the result is a bit */ + if (AOP_TYPE(result) == AOP_CRY) { + /* if the right size is a literal then + we know what the value is */ + if (AOP_TYPE(right) == AOP_LIT) { + if (((int) operandLitValue(right))) + aopPut(AOP(result),one,0); + else + aopPut(AOP(result),zero,0); + + goto release; + } + + /* the right is also a bit variable */ + if (AOP_TYPE(right) == AOP_CRY) { + emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + aopPut(AOP(result),"c",0); + goto release ; + } + + /* we need to or */ + toBoolean(right); + aopPut(AOP(result),"a",0); + goto release ; + } + + /* if they are the same size : or less */ + if (AOP_SIZE(result) <= AOP_SIZE(right)) { + + /* if they are in the same place */ + if (sameRegs(AOP(right),AOP(result))) + goto release; + + /* if they in different places then copy */ + size = AOP_SIZE(result); + offset = 0 ; + while (size--) { + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE,FALSE), + offset); + offset++; + } + goto release; + } + + + /* if the result is of type pointer */ + if (IS_PTR(ctype)) { + + int p_type; + link *type = operandType(right); + link *etype = getSpec(type); + + /* pointer to generic pointer */ + if (IS_GENPTR(ctype)) { + char *l = zero; + + if (IS_PTR(type)) + p_type = DCL_TYPE(type); + else { + /* we have to go by the storage class */ + if (SPEC_OCLS(etype)->codesp ) + p_type = CPOINTER ; + else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) + p_type = FPOINTER ; + else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) + p_type = PPOINTER; + else + if (SPEC_OCLS(etype) == idata ) + p_type = IPOINTER ; + else + p_type = POINTER ; + } + + /* the first two bytes are known */ + size = 2; + offset = 0 ; + while (size--) { + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE,FALSE), + offset); + offset++; + } + /* the last byte depending on type */ + switch (p_type) { + case IPOINTER: + case POINTER: + l = zero; + break; + case FPOINTER: + l = one; + break; + case CPOINTER: + l = "#0x02"; + break; + case PPOINTER: + l = "#0x03"; + break; + + default: + /* this should never happen */ + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "got unknown pointer type"); + exit(1); + } + aopPut(AOP(result),l,2); + goto release ; + } + + /* just copy the pointers */ + size = AOP_SIZE(result); + offset = 0 ; + while (size--) { + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE,FALSE), + offset); + offset++; + } + goto release ; + } + + /* so we now know that the size of destination is greater + than the size of the source */ + /* we move to result for the size of source */ + size = AOP_SIZE(right); + offset = 0 ; + while (size--) { + aopPut(AOP(result), + aopGet(AOP(right),offset,FALSE,FALSE), + offset); + offset++; + } + + /* now depending on the sign of the destination */ + size = AOP_SIZE(result) - AOP_SIZE(right); + /* if unsigned or not an integral type */ + if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) { + while (size--) + aopPut(AOP(result),zero,offset++); + } else { + /* we need to extend the sign :{ */ + char *l = aopGet(AOP(right),AOP_SIZE(right) - 1, + FALSE,FALSE); + MOVA(l); + emitcode("rlc","a"); + emitcode("subb","a,acc"); + while (size--) + aopPut(AOP(result),"a",offset++); + } + + /* we are done hurray !!!! */ + +release: + freeAsmop(right,NULL,ic,TRUE); + freeAsmop(result,NULL,ic,TRUE); + +} + +/*-----------------------------------------------------------------*/ +/* genDjnz - generate decrement & jump if not zero instrucion */ +/*-----------------------------------------------------------------*/ +static int genDjnz (iCode *ic, iCode *ifx) +{ + symbol *lbl, *lbl1; + if (!ifx) + return 0; + + /* if the if condition has a false label + then we cannot save */ + if (IC_FALSE(ifx)) + return 0; + + /* if the minus is not of the form + a = a - 1 */ + if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) || + !IS_OP_LITERAL(IC_RIGHT(ic))) + return 0; + + if (operandLitValue(IC_RIGHT(ic)) != 1) + return 0; + + /* if the size of this greater than one then no + saving */ + if (getSize(operandType(IC_RESULT(ic))) > 1) + return 0; + + /* otherwise we can save BIG */ + lbl = newiTempLabel(NULL); + lbl1= newiTempLabel(NULL); + + aopOp(IC_RESULT(ic),ic,FALSE); + + if (IS_AOP_PREG(IC_RESULT(ic))) { + emitcode("dec","%s", + aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + emitcode("jnz","%05d$",lbl->key+100); + } else { + emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE), + lbl->key+100); + } + emitcode ("sjmp","%05d$",lbl1->key+100); + emitcode ("","%05d$:",lbl->key+100); + emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100); + emitcode ("","%05d$:",lbl1->key+100); + + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + ifx->generated = 1; + return 1; +} + +/*-----------------------------------------------------------------*/ +/* genReceive - generate code for a receive iCode */ +/*-----------------------------------------------------------------*/ +static void genReceive (iCode *ic) +{ + if (isOperandInFarSpace(IC_RESULT(ic)) && + ( OP_SYMBOL(IC_RESULT(ic))->isspilt || + IS_TRUE_SYMOP(IC_RESULT(ic))) ) { + + int size = getSize(operandType(IC_RESULT(ic))); + int offset = 4 - size; + while (size--) { + emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ? + fReturn[3 - offset] : "acc")); + offset++; + } + aopOp(IC_RESULT(ic),ic,FALSE); + size = AOP_SIZE(IC_RESULT(ic)); + offset = 0; + while (size--) { + emitcode ("pop","acc"); + aopPut (AOP(IC_RESULT(ic)),"a",offset++); + } + + } else { + accInUse++; + aopOp(IC_RESULT(ic),ic,FALSE); + accInUse--; + assignResultValue(IC_RESULT(ic)); + } + + freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------*/ +/* gen51Code - generate code for 8051 based controllers */ +/*-----------------------------------------------------------------*/ +void gen51Code (iCode *lic) +{ + iCode *ic; + int cln = 0; + + lineHead = lineCurr = NULL; + + /* if debug information required */ +/* if (options.debug && currFunc) { */ + if (currFunc) { + cdbSymbol(currFunc,cdbFile,FALSE,TRUE); + debugLine = 1; + if (IS_STATIC(currFunc->etype)) + emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); + else + emitcode("","G$%s$0$0 ==.",currFunc->name); + debugLine = 0; + } + /* stack pointer name */ + if (options.useXstack) + spname = "_spx"; + else + spname = "sp"; + + + for (ic = lic ; ic ; ic = ic->next ) { + + if ( cln != ic->lineno ) { + if ( options.debug ) { + debugLine = 1; + emitcode("","C$%s$%d$%d$%d ==.", + ic->filename,ic->lineno, + ic->level,ic->block); + debugLine = 0; + } + emitcode(";","%s %d",ic->filename,ic->lineno); + cln = ic->lineno ; + } + /* if the result is marked as + spilt and rematerializable or code for + this has already been generated then + do nothing */ + if (resultRemat(ic) || ic->generated ) + continue ; + + /* depending on the operation */ + switch (ic->op) { + case '!' : + genNot(ic); + break; + + case '~' : + genCpl(ic); + break; + + case UNARYMINUS: + genUminus (ic); + break; + + case IPUSH: + genIpush (ic); + break; + + case IPOP: + /* IPOP happens only when trying to restore a + spilt live range, if there is an ifx statement + following this pop then the if statement might + be using some of the registers being popped which + would destory the contents of the register so + we need to check for this condition and handle it */ + if (ic->next && + ic->next->op == IFX && + regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) + genIfx (ic->next,ic); + else + genIpop (ic); + break; + + case CALL: + genCall (ic); + break; + + case PCALL: + genPcall (ic); + break; + + case FUNCTION: + genFunction (ic); + break; + + case ENDFUNCTION: + genEndFunction (ic); + break; + + case RETURN: + genRet (ic); + break; + + case LABEL: + genLabel (ic); + break; + + case GOTO: + genGoto (ic); + break; + + case '+' : + genPlus (ic) ; + break; + + case '-' : + if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic))) + genMinus (ic); + break; + + case '*' : + genMult (ic); + break; + + case '/' : + genDiv (ic) ; + break; + + case '%' : + genMod (ic); + break; + + case '>' : + genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case '<' : + genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case LE_OP: + case GE_OP: + case NE_OP: + + /* note these two are xlated by algebraic equivalence + during parsing SDCC.y */ + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "got '>=' or '<=' shouldn't have come here"); + break; + + case EQ_OP: + genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case AND_OP: + genAndOp (ic); + break; + + case OR_OP: + genOrOp (ic); + break; + + case '^' : + genXor (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case '|' : + genOr (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case BITWISEAND: + genAnd (ic,ifxForOp(IC_RESULT(ic),ic)); + break; + + case INLINEASM: + genInline (ic); + break; + + case RRC: + genRRC (ic); + break; + + case RLC: + genRLC (ic); + break; + + case GETHBIT: + genGetHbit (ic); + break; + + case LEFT_OP: + genLeftShift (ic); + break; + + case RIGHT_OP: + genRightShift (ic); + break; + + case GET_VALUE_AT_ADDRESS: + genPointerGet(ic); + break; + + case '=' : + if (POINTER_SET(ic)) + genPointerSet(ic); + else + genAssign(ic); + break; + + case IFX: + genIfx (ic,NULL); + break; + + case ADDRESS_OF: + genAddrOf (ic); + break; + + case JUMPTABLE: + genJumpTab (ic); + break; + + case CAST: + genCast (ic); + break; + + case RECEIVE: + genReceive(ic); + break; + + case SEND: + addSet(&sendSet,ic); + break; + + default : + ic = ic; + /* piCode(ic,stdout); */ + + } + } + + + /* now we are ready to call the + peep hole optimizer */ + if (!options.nopeep) + peepHole (&lineHead); + + /* now do the actual printing */ + printLine (lineHead,codeOutFile); + return; +} diff --git a/src/mcs51/gen.h b/src/mcs51/gen.h new file mode 100644 index 00000000..3c56dcfd --- /dev/null +++ b/src/mcs51/gen.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------- + SDCCgen51.h - header file for code generation for 8051 + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#ifndef SDCCGEN51_H +#define SDCCGEN51_H + +enum { + AOP_LIT = 1, + AOP_REG, AOP_DIR, + AOP_DPTR,AOP_R0,AOP_R1, + AOP_STK ,AOP_IMMD, AOP_STR, + AOP_CRY, AOP_ACC }; + +/* type asmop : a homogenised type for + all the different spaces an operand can be + in */ +typedef struct asmop { + + short type ; /* can have values + AOP_LIT - operand is a literal value + AOP_REG - is in registers + AOP_DIR - direct just a name + AOP_DPTR - dptr contains address of operand + AOP_R0/R1 - r0/r1 contains address of operand + AOP_STK - should be pushed on stack this + can happen only for the result + AOP_IMMD - immediate value for eg. remateriazable + AOP_CRY - carry contains the value of this + AOP_STR - array of strings + AOP_ACC - result is in the acc:b pair + */ + short coff ; /* current offset */ + short size ; /* total size */ + unsigned code :1 ; /* is in Code space */ + unsigned paged:1 ; /* in paged memory */ + unsigned freed:1 ; /* already freed */ + union { + value *aop_lit ; /* if literal */ + regs *aop_reg[4]; /* array of registers */ + char *aop_dir ; /* if direct */ + regs *aop_ptr ; /* either -> to r0 or r1 */ + char *aop_immd; /* if immediate others are implied */ + int aop_stk ; /* stack offset when AOP_STK */ + char *aop_str[4]; /* just a string array containing the location */ + } aopu; +} asmop; + +void gen51Code (iCode *); + + +#endif diff --git a/src/mcs51/ralloc.c b/src/mcs51/ralloc.c new file mode 100644 index 00000000..2a7dc805 --- /dev/null +++ b/src/mcs51/ralloc.c @@ -0,0 +1,2313 @@ +/*------------------------------------------------------------------------ + + SDCCralloc.c - source file for register allocation. (8051) specific + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ +#include +#include +#include "SDCCglobl.h" +#include "SDCCast.h" +#include "SDCCmem.h" +#include "SDCCy.h" +#include "SDCChasht.h" +#include "SDCCbitv.h" +#include "SDCCset.h" +#include "SDCCicode.h" +#include "SDCClabel.h" +#include "SDCCBBlock.h" +#include "SDCCloop.h" +#include "SDCCcse.h" +#include "SDCCcflow.h" +#include "SDCCdflow.h" +#include "SDCClrange.h" +#include "SDCCralloc.h" + +/*-----------------------------------------------------------------*/ +/* At this point we start getting processor specific although */ +/* some routines are non-processor specific & can be reused when */ +/* targetting other processors. The decision for this will have */ +/* to be made on a routine by routine basis */ +/* routines used to pack registers are most definitely not reusable*/ +/* since the pack the registers depending strictly on the MCU */ +/*-----------------------------------------------------------------*/ + +bitVect *spiltSet = NULL ; +set *stackSpil = NULL; +bitVect *regAssigned = NULL; +short blockSpil = 0; +int slocNum = 0 ; +extern void gen51Code(iCode *); +int ptrRegReq = 0; /* one byte pointer register required */ +bitVect *funcrUsed = NULL; /* registers used in a function */ +int stackExtend = 0; +int dataExtend = 0; + +/* 8051 registers */ +regs regs8051[] = +{ + + { REG_GPR ,R2_IDX , REG_GPR , "r2", "ar2", "0", 2, 1 }, + { REG_GPR ,R3_IDX , REG_GPR , "r3", "ar3", "0", 3, 1 }, + { REG_GPR ,R4_IDX , REG_GPR , "r4", "ar4", "0", 4, 1 }, + { REG_GPR ,R5_IDX , REG_GPR , "r5", "ar5", "0", 5, 1 }, + { REG_GPR ,R6_IDX , REG_GPR , "r6", "ar6", "0", 6, 1 }, + { REG_GPR ,R7_IDX , REG_GPR , "r7", "ar7", "0", 7, 1 }, + { REG_PTR ,R0_IDX , REG_PTR , "r0" , "ar0", "0", 0, 1 }, + { REG_PTR ,R1_IDX , REG_PTR , "r1" , "ar1", "0", 1, 1 }, + { REG_GPR ,X8_IDX , REG_GPR , "x8", "x8" , "xreg", 0, 1 }, + { REG_GPR ,X9_IDX , REG_GPR , "x9", "x9" , "xreg", 1, 1 }, + { REG_GPR ,X10_IDX,REG_GPR , "x10", "x10", "xreg", 2, 1 }, + { REG_GPR ,X11_IDX,REG_GPR , "x11", "x11", "xreg", 3, 1 }, + { REG_GPR ,X12_IDX,REG_GPR , "x12", "x12", "xreg", 4, 1 }, + { REG_CND ,CND_IDX,REG_CND , "C" , "C" , "xreg", 0, 1 }, +}; +int nRegs = 13; +void spillThis (symbol *); + +/*-----------------------------------------------------------------*/ +/* allocReg - allocates register of given type */ +/*-----------------------------------------------------------------*/ +regs *allocReg (short type) +{ + int i; + + for ( i = 0 ; i < nRegs ; i++ ) { + + /* if type is given as 0 then any + free register will do */ + if (!type && + regs8051[i].isFree ) { + regs8051[i].isFree = 0; + if (currFunc) + currFunc->regsUsed = + bitVectSetBit(currFunc->regsUsed,i); + return ®s8051[i]; + } + /* other wise look for specific type + of register */ + if (regs8051[i].isFree && + regs8051[i].type == type) { + regs8051[i].isFree = 0; + if (currFunc) + currFunc->regsUsed = + bitVectSetBit(currFunc->regsUsed,i); + return ®s8051[i]; + } + } + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* regWithIdx - returns pointer to register wit index number */ +/*-----------------------------------------------------------------*/ +regs *regWithIdx (int idx) +{ + int i ; + + for (i=0;i < nRegs;i++) + if (regs8051[i].rIdx == idx) + return ®s8051[i]; + + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "regWithIdx not found"); + exit(1); +} + +/*-----------------------------------------------------------------*/ +/* freeReg - frees a register */ +/*-----------------------------------------------------------------*/ +void freeReg (regs *reg) +{ + reg->isFree = 1; +} + + +/*-----------------------------------------------------------------*/ +/* nFreeRegs - returns number of free registers */ +/*-----------------------------------------------------------------*/ +int nFreeRegs (int type) +{ + int i; + int nfr=0; + + for (i = 0 ; i < nRegs; i++ ) + if (regs8051[i].isFree && regs8051[i].type == type) + nfr++; + return nfr; +} + +/*-----------------------------------------------------------------*/ +/* nfreeRegsType - free registers with type */ +/*-----------------------------------------------------------------*/ +int nfreeRegsType (int type) +{ + int nfr ; + if (type == REG_PTR) { + if ((nfr = nFreeRegs(type)) == 0) + return nFreeRegs(REG_GPR); + } + + return nFreeRegs(type); +} + + +/*-----------------------------------------------------------------*/ +/* allDefsOutOfRange - all definitions are out of a range */ +/*-----------------------------------------------------------------*/ +bool allDefsOutOfRange (bitVect *defs,int fseq, int toseq) +{ + int i ; + + if (!defs) + return TRUE ; + + for ( i = 0 ;i < defs->size ; i++ ) { + iCode *ic; + + if (bitVectBitValue(defs,i) && + (ic = hTabItemWithKey(iCodehTab,i)) && + ( ic->seq >= fseq && ic->seq <= toseq)) + + return FALSE; + + } + + return TRUE; +} + +/*-----------------------------------------------------------------*/ +/* computeSpillable - given a point find the spillable live ranges */ +/*-----------------------------------------------------------------*/ +bitVect *computeSpillable (iCode *ic) +{ + bitVect *spillable ; + + /* spillable live ranges are those that are live at this + point . the following categories need to be subtracted + from this set. + a) - those that are already spilt + b) - if being used by this one + c) - defined by this one */ + + spillable = bitVectCopy(ic->rlive); + spillable = + bitVectCplAnd(spillable,spiltSet); /* those already spilt */ + spillable = + bitVectCplAnd(spillable,ic->uses); /* used in this one */ + bitVectUnSetBit(spillable,ic->defKey); + spillable = bitVectIntersect(spillable,regAssigned); + return spillable; + +} + +/*-----------------------------------------------------------------*/ +/* noSpilLoc - return true if a variable has no spil location */ +/*-----------------------------------------------------------------*/ +int noSpilLoc (symbol *sym, eBBlock *ebp,iCode *ic) +{ + return (sym->usl.spillLoc ? 0 : 1); +} + +/*-----------------------------------------------------------------*/ +/* hasSpilLoc - will return 1 if the symbol has spil location */ +/*-----------------------------------------------------------------*/ +int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return (sym->usl.spillLoc ? 1 : 0); +} + +/*-----------------------------------------------------------------*/ +/* directSpilLoc - will return 1 if the splilocation is in direct */ +/*-----------------------------------------------------------------*/ +int directSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic) +{ + if ( sym->usl.spillLoc && + (IN_DIRSPACE(SPEC_OCLS(sym->usl.spillLoc->etype)))) + return 1; + else + return 0; +} + +/*-----------------------------------------------------------------*/ +/* hasSpilLocnoUptr - will return 1 if the symbol has spil location*/ +/* but is not used as a pointer */ +/*-----------------------------------------------------------------*/ +int hasSpilLocnoUptr (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0); +} + +/*-----------------------------------------------------------------*/ +/* rematable - will return 1 if the remat flag is set */ +/*-----------------------------------------------------------------*/ +int rematable (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return sym->remat; +} + +/*-----------------------------------------------------------------*/ +/* notUsedInBlock - not used in this block */ +/*-----------------------------------------------------------------*/ +int notUsedInBlock (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs) && + allDefsOutOfRange (sym->defs,ebp->fSeq,ebp->lSeq)); +/* return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */ +} + +/*-----------------------------------------------------------------*/ +/* notUsedInRemaining - not used or defined in remain of the block */ +/*-----------------------------------------------------------------*/ +int notUsedInRemaining (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return ((usedInRemaining (operandFromSymbol(sym),ic) ? 0 : 1) && + allDefsOutOfRange (sym->defs,ic->seq,ebp->lSeq)); +} + +/*-----------------------------------------------------------------*/ +/* allLRs - return true for all */ +/*-----------------------------------------------------------------*/ +int allLRs (symbol *sym, eBBlock *ebp, iCode *ic) +{ + return 1; +} + +/*-----------------------------------------------------------------*/ +/* liveRangesWith - applies function to a given set of live range */ +/*-----------------------------------------------------------------*/ +set *liveRangesWith (bitVect *lrs, int (func)(symbol *,eBBlock *, iCode *), + eBBlock *ebp, iCode *ic) +{ + set *rset = NULL; + int i; + + if (!lrs || !lrs->size) + return NULL; + + for ( i = 1 ; i < lrs->size ; i++ ) { + symbol *sym; + if (!bitVectBitValue(lrs,i)) + continue ; + + /* if we don't find it in the live range + hash table we are in serious trouble */ + if (!(sym = hTabItemWithKey(liveRanges,i))) { + werror(E_INTERNAL_ERROR,__FILE__,__LINE__, + "liveRangesWith could not find liveRange"); + exit(1); + } + + if (func(sym,ebp,ic) && bitVectBitValue(regAssigned,sym->key)) + addSetHead(&rset,sym); + } + + return rset; +} + + +/*-----------------------------------------------------------------*/ +/* leastUsedLR - given a set determines which is the least used */ +/*-----------------------------------------------------------------*/ +symbol *leastUsedLR (set *sset) +{ + symbol *sym = NULL, *lsym = NULL ; + + sym = lsym = setFirstItem(sset); + + if (!lsym) + return NULL; + + for (; lsym; lsym = setNextItem(sset)) { + + /* if usage is the same then prefer + the spill the smaller of the two */ + if ( lsym->used == sym->used ) + if (getSize(lsym->type) < getSize(sym->type)) + sym = lsym; + + /* if less usage */ + if (lsym->used < sym->used ) + sym = lsym; + + } + + setToNull((void **)&sset); + sym->blockSpil = 0; + return sym; +} + +/*-----------------------------------------------------------------*/ +/* noOverLap - will iterate through the list looking for over lap */ +/*-----------------------------------------------------------------*/ +int noOverLap (set *itmpStack, symbol *fsym) +{ + symbol *sym; + + + for (sym = setFirstItem(itmpStack); sym; + sym = setNextItem(itmpStack)) { + if (sym->liveTo > fsym->liveFrom ) + return 0; + + } + + return 1; +} + +/*-----------------------------------------------------------------*/ +/* isFree - will return 1 if the a free spil location is found */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(isFree) +{ + symbol *sym = item; + V_ARG(symbol **,sloc); + V_ARG(symbol *,fsym); + + /* if already found */ + if (*sloc) + return 0; + + /* if it is free && and the itmp assigned to + this does not have any overlapping live ranges + with the one currently being assigned and + the size can be accomodated */ + if (sym->isFree && + noOverLap(sym->usl.itmpStack,fsym) && + getSize(sym->type) >= getSize(fsym->type)) { + *sloc = sym; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* spillLRWithPtrReg :- will spil those live ranges which use PTR */ +/*-----------------------------------------------------------------*/ +void spillLRWithPtrReg (symbol *forSym) +{ + symbol *lrsym; + regs *r0,*r1; + int k; + + if (!regAssigned || + bitVectIsZero(regAssigned)) + return; + + r0 = regWithIdx(R0_IDX); + r1 = regWithIdx(R1_IDX); + + /* for all live ranges */ + for (lrsym = hTabFirstItem(liveRanges,&k) ; lrsym ; + lrsym = hTabNextItem(liveRanges,&k) ) { + int j; + + /* if no registers assigned to it or + spilt */ + /* if it does not overlap with this then + not need to spill it */ + + if (lrsym->isspilt || !lrsym->nRegs || + (lrsym->liveTo < forSym->liveFrom)) + continue ; + + /* go thru the registers : if it is either + r0 or r1 then spil it */ + for (j = 0 ; j < lrsym->nRegs ; j++ ) + if (lrsym->regs[j] == r0 || + lrsym->regs[j] == r1 ) { + spillThis (lrsym); + break; + } + } + +} + +/*-----------------------------------------------------------------*/ +/* createStackSpil - create a location on the stack to spil */ +/*-----------------------------------------------------------------*/ +symbol *createStackSpil (symbol *sym) +{ + symbol *sloc= NULL; + int useXstack, model, noOverlay; + int stackAuto; + + /* first go try and find a free one that is already + existing on the stack */ + if (applyToSet(stackSpil,isFree,&sloc, sym)) { + /* found a free one : just update & return */ + sym->usl.spillLoc = sloc; + sym->stackSpil= 1; + sloc->isFree = 0; + addSetHead(&sloc->usl.itmpStack,sym); + return sym; + } + + /* could not then have to create one , this is the hard part + we need to allocate this on the stack : this is really a + hack!! but cannot think of anything better at this time */ + + sprintf(buffer,"sloc%d",slocNum++); + sloc = newiTemp(buffer); + + /* set the type to the spilling symbol */ + sloc->type = copyLinkChain(sym->type); + sloc->etype = getSpec(sloc->type); + SPEC_SCLS(sloc->etype) = S_AUTO ; + SPEC_EXTR(sloc->etype) = 0; + + /* we don't allow it to be allocated` + onto the external stack since : so we + temporarily turn it off ; we also + turn off memory model to prevent + the spil from going to the external storage + and turn off overlaying + */ + + useXstack = options.useXstack; + model = options.model; + noOverlay = options.noOverlay; + stackAuto = options.stackAuto; + options.noOverlay = 1; + options.model = options.useXstack = 0; + + allocLocal(sloc); + + options.useXstack = useXstack; + options.model = model; + options.noOverlay = noOverlay; + options.stackAuto = stackAuto; + sloc->isref = 1; /* to prevent compiler warning */ + + /* if it is on the stack then update the stack */ + if (IN_STACK(sloc->etype)) { + currFunc->stack += getSize(sloc->type); + stackExtend += getSize(sloc->type); + } else + dataExtend += getSize(sloc->type); + + /* add it to the stackSpil set */ + addSetHead(&stackSpil,sloc); + sym->usl.spillLoc = sloc; + sym->stackSpil = 1; + + /* add it to the set of itempStack set + of the spill location */ + addSetHead(&sloc->usl.itmpStack,sym); + return sym; +} + +/*-----------------------------------------------------------------*/ +/* isSpiltOnStack - returns true if the spil location is on stack */ +/*-----------------------------------------------------------------*/ +bool isSpiltOnStack (symbol *sym) +{ + link *etype; + + if (!sym) + return FALSE ; + + if (!sym->isspilt) + return FALSE ; + +/* if (sym->stackSpil) */ +/* return TRUE; */ + + if (!sym->usl.spillLoc) + return FALSE; + + etype = getSpec(sym->usl.spillLoc->type); + if (IN_STACK(etype)) + return TRUE; + + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* spillThis - spils a specific operand */ +/*-----------------------------------------------------------------*/ +void spillThis (symbol *sym) +{ + int i; + /* if this is rematerializable or has a spillLocation + we are okay, else we need to create a spillLocation + for it */ + if (!(sym->remat || sym->usl.spillLoc)) + createStackSpil (sym); + + + /* mark it has spilt & put it in the spilt set */ + sym->isspilt = 1; + spiltSet = bitVectSetBit(spiltSet,sym->key); + + bitVectUnSetBit(regAssigned,sym->key); + + for (i = 0 ; i < sym->nRegs ; i++) + + if (sym->regs[i]) { + freeReg(sym->regs[i]); + sym->regs[i] = NULL; + } + + /* if spilt on stack then free up r0 & r1 + if they could have been assigned to some + LIVE ranges */ + if (!ptrRegReq && isSpiltOnStack(sym)) { + ptrRegReq++ ; + spillLRWithPtrReg(sym); + } + + if (sym->usl.spillLoc && !sym->remat) + sym->usl.spillLoc->allocreq = 1; + return; +} + +/*-----------------------------------------------------------------*/ +/* selectSpil - select a iTemp to spil : rather a simple procedure */ +/*-----------------------------------------------------------------*/ +symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym) +{ + bitVect *lrcs= NULL ; + set *selectS ; + symbol *sym; + + /* get the spillable live ranges */ + lrcs = computeSpillable (ic); + + /* get all live ranges that are rematerizable */ + if ((selectS = liveRangesWith(lrcs,rematable,ebp,ic))) { + + /* return the least used of these */ + return leastUsedLR(selectS); + } + + /* get live ranges with spillLocations in direct space */ + if ((selectS = liveRangesWith(lrcs,directSpilLoc,ebp,ic))) { + sym = leastUsedLR(selectS); + strcpy(sym->rname,(sym->usl.spillLoc->rname[0] ? + sym->usl.spillLoc->rname : + sym->usl.spillLoc->name)); + sym->spildir = 1; + /* mark it as allocation required */ + sym->usl.spillLoc->allocreq = 1; + return sym; + } + + /* if the symbol is local to the block then */ + if (forSym->liveTo < ebp->lSeq ) { + + /* check if there are any live ranges allocated + to registers that are not used in this block */ + if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInBlock,ebp,ic))) { + sym = leastUsedLR(selectS); + /* if this is not rematerializable */ + if (!sym->remat) { + blockSpil++; + sym->blockSpil = 1; + } + return sym; + } + + /* check if there are any live ranges that not + used in the remainder of the block */ + if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) { + sym = leastUsedLR (selectS); + if (!sym->remat) { + sym->remainSpil = 1; + blockSpil++; + } + return sym; + } + } + + /* find live ranges with spillocation && not used as pointers */ + if ((selectS = liveRangesWith(lrcs,hasSpilLocnoUptr,ebp,ic))) { + + sym = leastUsedLR(selectS); + /* mark this as allocation required */ + sym->usl.spillLoc->allocreq = 1; + return sym; + } + + /* find live ranges with spillocation */ + if ((selectS = liveRangesWith(lrcs,hasSpilLoc,ebp,ic))) { + + sym = leastUsedLR(selectS); + sym->usl.spillLoc->allocreq = 1; + return sym; + } + + /* couldn't find then we need to create a spil + location on the stack , for which one? the least + used ofcourse */ + if ((selectS = liveRangesWith(lrcs,noSpilLoc,ebp,ic))) { + + /* return a created spil location */ + sym = createStackSpil(leastUsedLR(selectS)); + sym->usl.spillLoc->allocreq = 1; + return sym; + } + + /* this is an extreme situation we will spill + this one : happens very rarely but it does happen */ + spillThis ( forSym ); + return forSym ; + +} + +/*-----------------------------------------------------------------*/ +/* spilSomething - spil some variable & mark registers as free */ +/*-----------------------------------------------------------------*/ +bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym) +{ + symbol *ssym; + int i ; + + /* get something we can spil */ + ssym = selectSpil(ic,ebp,forSym); + + /* mark it as spilt */ + ssym->isspilt = 1; + spiltSet = bitVectSetBit(spiltSet,ssym->key); + + /* mark it as not register assigned & + take it away from the set */ + bitVectUnSetBit(regAssigned,ssym->key); + + /* mark the registers as free */ + for (i = 0 ; i < ssym->nRegs ;i++ ) + if (ssym->regs[i]) + freeReg(ssym->regs[i]); + + /* if spilt on stack then free up r0 & r1 + if they could have been assigned to as gprs */ + if (!ptrRegReq && isSpiltOnStack(ssym) ) { + ptrRegReq++ ; + spillLRWithPtrReg(ssym); + } + + /* if this was a block level spil then insert push & pop + at the start & end of block respectively */ + if (ssym->blockSpil) { + iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL); + /* add push to the start of the block */ + addiCodeToeBBlock(ebp,nic,( ebp->sch->op == LABEL ? + ebp->sch->next : ebp->sch)); + nic = newiCode(IPOP,operandFromSymbol(ssym),NULL); + /* add pop to the end of the block */ + addiCodeToeBBlock(ebp,nic,NULL); + } + + /* if spilt because not used in the remainder of the + block then add a push before this instruction and + a pop at the end of the block */ + if (ssym->remainSpil) { + + iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL); + /* add push just before this instruction */ + addiCodeToeBBlock(ebp,nic,ic); + + nic = newiCode(IPOP,operandFromSymbol(ssym),NULL); + /* add pop to the end of the block */ + addiCodeToeBBlock(ebp,nic,NULL); + } + + if (ssym == forSym ) + return FALSE ; + else + return TRUE ; +} + +/*-----------------------------------------------------------------*/ +/* getRegPtr - will try for PTR if not a GPR type if not spil */ +/*-----------------------------------------------------------------*/ +regs *getRegPtr (iCode *ic, eBBlock *ebp, symbol *sym) +{ + regs *reg; + + tryAgain: + /* try for a ptr type */ + if ((reg = allocReg(REG_PTR))) + return reg; + + /* try for gpr type */ + if ((reg = allocReg(REG_GPR))) + return reg; + + /* we have to spil */ + if (!spilSomething (ic,ebp,sym)) + return NULL ; + + /* this looks like an infinite loop but + in really selectSpil will abort */ + goto tryAgain ; +} + +/*-----------------------------------------------------------------*/ +/* getRegGpr - will try for GPR if not spil */ +/*-----------------------------------------------------------------*/ +regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym) +{ + regs *reg; + + tryAgain: + /* try for gpr type */ + if ((reg = allocReg(REG_GPR))) + return reg; + + if (!ptrRegReq) + if ((reg = allocReg(REG_PTR))) + return reg ; + + /* we have to spil */ + if (!spilSomething (ic,ebp,sym)) + return NULL ; + + /* this looks like an infinite loop but + in really selectSpil will abort */ + goto tryAgain ; +} + +/*-----------------------------------------------------------------*/ +/* symHasReg - symbol has a given register */ +/*-----------------------------------------------------------------*/ +static bool symHasReg(symbol *sym,regs *reg) +{ + int i; + + for ( i = 0 ; i < sym->nRegs ; i++) + if (sym->regs[i] == reg) + return TRUE; + + return FALSE; +} + +/*-----------------------------------------------------------------*/ +/* deassignLRs - check the live to and if they have registers & are*/ +/* not spilt then free up the registers */ +/*-----------------------------------------------------------------*/ +void deassignLRs (iCode *ic, eBBlock *ebp) +{ + symbol *sym; + int k; + symbol *result; + + for (sym = hTabFirstItem(liveRanges,&k); sym; + sym = hTabNextItem(liveRanges,&k)) { + + symbol *psym= NULL; + /* if it does not end here */ + if (sym->liveTo > ic->seq ) + continue ; + + /* if it was spilt on stack then we can + mark the stack spil location as free */ + if (sym->isspilt ) { + if (sym->stackSpil) { + sym->usl.spillLoc->isFree = 1; + sym->stackSpil = 0; + } + continue ; + } + + if (!bitVectBitValue(regAssigned,sym->key)) + continue; + + /* special case check if this is an IFX & + the privious one was a pop and the + previous one was not spilt then keep track + of the symbol */ + if (ic->op == IFX && ic->prev && + ic->prev->op == IPOP && + !ic->prev->parmPush && + !OP_SYMBOL(IC_LEFT(ic->prev))->isspilt) + psym = OP_SYMBOL(IC_LEFT(ic->prev)); + + if (sym->nRegs) { + int i = 0; + + bitVectUnSetBit(regAssigned,sym->key); + + /* if the result of this one needs registers + and does not have it then assign it right + away */ + if (IC_RESULT(ic) && + ! (SKIP_IC2(ic) || /* not a special icode */ + ic->op == JUMPTABLE || + ic->op == IFX || + ic->op == IPUSH || + ic->op == IPOP || + ic->op == RETURN || + POINTER_SET(ic)) && + (result = OP_SYMBOL(IC_RESULT(ic))) && /* has a result */ + result->liveTo > ic->seq && /* and will live beyond this */ + result->liveTo <= ebp->lSeq && /* does not go beyond this block */ + result->regType == sym->regType && /* same register types */ + result->nRegs && /* which needs registers */ + ! result->isspilt && /* and does not already have them */ + ! result->remat && + ! bitVectBitValue(regAssigned,result->key) && + /* the number of free regs + number of regs in this LR + can accomodate the what result Needs */ + ((nfreeRegsType(result->regType) + + sym->nRegs) >= result->nRegs) + ) { + + for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) + if (i < sym->nRegs ) + result->regs[i] = sym->regs[i] ; + else + result->regs[i] = getRegGpr (ic,ebp,result); + + regAssigned = bitVectSetBit(regAssigned,result->key); + + } + + /* free the remaining */ + for (; i < sym->nRegs ; i++) { + if (psym) { + if (!symHasReg(psym,sym->regs[i])) + freeReg(sym->regs[i]); + } else + freeReg(sym->regs[i]); + } + } + } +} + + +/*-----------------------------------------------------------------*/ +/* reassignLR - reassign this to registers */ +/*-----------------------------------------------------------------*/ +void reassignLR (operand *op) +{ + symbol *sym = OP_SYMBOL(op); + int i; + + /* not spilt any more */ + sym->isspilt = sym->blockSpil = sym->remainSpil = 0; + bitVectUnSetBit(spiltSet,sym->key); + + regAssigned = bitVectSetBit(regAssigned,sym->key); + + blockSpil--; + + for (i=0;inRegs;i++) + sym->regs[i]->isFree = 0; +} + +/*-----------------------------------------------------------------*/ +/* willCauseSpill - determines if allocating will cause a spill */ +/*-----------------------------------------------------------------*/ +int willCauseSpill ( int nr, int rt) +{ + /* first check if there are any avlb registers + of te type required */ + if (rt == REG_PTR) { + /* special case for pointer type + if pointer type not avlb then + check for type gpr */ + if (nFreeRegs(rt) >= nr) + return 0; + if (nFreeRegs(REG_GPR) >= nr) + return 0; + } else { + if (ptrRegReq) { + if (nFreeRegs(rt) >= nr) + return 0; + } else { + if (nFreeRegs(REG_PTR) + + nFreeRegs(REG_GPR) >= nr) + return 0; + } + } + + /* it will cause a spil */ + return 1; +} + +/*-----------------------------------------------------------------*/ +/* positionRegs - the allocator can allocate same registers to res-*/ +/* ult and operand, if this happens make sure they are in the same */ +/* position as the operand otherwise chaos results */ +/*-----------------------------------------------------------------*/ +static void positionRegs (symbol *result, symbol *opsym, int lineno) +{ + int count = min(result->nRegs,opsym->nRegs); + int i , j = 0, shared = 0; + + /* if the result has been spilt then cannot share */ + if (opsym->isspilt) + return ; + again: + shared = 0; + /* first make sure that they actually share */ + for ( i = 0 ; i < count; i++ ) { + for (j = 0 ; j < count ; j++ ) { + if (result->regs[i] == opsym->regs[j] && i !=j) { + shared = 1; + goto xchgPositions; + } + } + } + xchgPositions: + if (shared) { + regs *tmp = result->regs[i]; + result->regs[i] = result->regs[j]; + result->regs[j] = tmp; + goto again; + } +} + +/*-----------------------------------------------------------------*/ +/* serialRegAssign - serially allocate registers to the variables */ +/*-----------------------------------------------------------------*/ +void serialRegAssign (eBBlock **ebbs, int count) +{ + int i; + + /* for all blocks */ + for (i = 0; i < count ; i++ ) { + + iCode *ic; + + if (ebbs[i]->noPath && + (ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel )) + continue ; + + /* of all instructions do */ + for (ic = ebbs[i]->sch ; ic ; ic = ic->next) { + + /* if this is an ipop that means some live + range will have to be assigned again */ + if (ic->op == IPOP) + reassignLR (IC_LEFT(ic)); + + /* if result is present && is a true symbol */ + if (IC_RESULT(ic) && ic->op != IFX && + IS_TRUE_SYMOP(IC_RESULT(ic))) + OP_SYMBOL(IC_RESULT(ic))->allocreq = 1; + + /* take away registers from live + ranges that end at this instruction */ + deassignLRs (ic, ebbs[i]) ; + + /* some don't need registers */ + if (SKIP_IC2(ic) || + ic->op == JUMPTABLE || + ic->op == IFX || + ic->op == IPUSH || + ic->op == IPOP || + (IC_RESULT(ic) &&POINTER_SET(ic)) ) + continue; + + /* now we need to allocate registers + only for the result */ + if (IC_RESULT(ic)) { + symbol *sym = OP_SYMBOL(IC_RESULT(ic)); + bitVect *spillable; + int willCS ; + int j; + int ptrRegSet = 0; + + /* if it does not need or is spilt + or is already assigned to registers + or will not live beyond this instructions */ + if (!sym->nRegs || + sym->isspilt || + bitVectBitValue(regAssigned,sym->key) || + sym->liveTo <= ic->seq) + continue ; + + /* if some liverange has been spilt at the block level + and this one live beyond this block then spil this + to be safe */ + if (blockSpil && sym->liveTo > ebbs[i]->lSeq) { + spillThis (sym); + continue ; + } + /* if trying to allocate this will cause + a spill and there is nothing to spill + or this one is rematerializable then + spill this one */ + willCS = willCauseSpill(sym->nRegs,sym->regType); + spillable = computeSpillable(ic); + if ( sym->remat || + (willCS && bitVectIsZero(spillable) ) ) { + + spillThis (sym) ; + continue ; + + } + + /* if it has a spillocation & is used less than + all other live ranges then spill this */ + if ( willCS && sym->usl.spillLoc ) { + + symbol *leastUsed = + leastUsedLR(liveRangesWith (spillable , + allLRs, + ebbs[i], + ic)); + if (leastUsed && + leastUsed->used > sym->used) { + spillThis (sym); + continue; + } + } + + /* if we need ptr regs for the right side + then mark it */ + if (POINTER_GET(ic) && getSize(OP_SYMBOL(IC_LEFT(ic))->type) < 2) { + ptrRegReq++; + ptrRegSet = 1; + } + /* else we assign registers to it */ + regAssigned = bitVectSetBit(regAssigned,sym->key); + + for (j = 0 ; j < sym->nRegs ;j++ ) { + if (sym->regType == REG_PTR) + sym->regs[j] = getRegPtr(ic,ebbs[i],sym); + else + sym->regs[j] = getRegGpr(ic,ebbs[i],sym); + + /* if the allocation falied which means + this was spilt then break */ + if (!sym->regs[j]) + break; + } + /* if it shares registers with operands make sure + that they are in the same position */ + if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && + OP_SYMBOL(IC_LEFT(ic))->nRegs && ic->op != '=') + positionRegs(OP_SYMBOL(IC_RESULT(ic)), + OP_SYMBOL(IC_LEFT(ic)),ic->lineno); + /* do the same for the right operand */ + if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && + OP_SYMBOL(IC_RIGHT(ic))->nRegs && ic->op != '=') + positionRegs(OP_SYMBOL(IC_RESULT(ic)), + OP_SYMBOL(IC_RIGHT(ic)),ic->lineno); + + if (ptrRegSet) { + ptrRegReq--; + ptrRegSet = 0; + } + + } + } + } +} + +/*-----------------------------------------------------------------*/ +/* rUmaskForOp :- returns register mask for an operand */ +/*-----------------------------------------------------------------*/ +bitVect *rUmaskForOp (operand *op) +{ + bitVect *rumask; + symbol *sym; + int j; + + /* only temporaries are assigned registers */ + if (!IS_ITEMP(op)) + return NULL; + + sym = OP_SYMBOL(op); + + /* if spilt or no registers assigned to it + then nothing */ + if (sym->isspilt || !sym->nRegs) + return NULL; + + rumask = newBitVect(nRegs); + + for (j = 0; j < sym->nRegs; j++) { + rumask = bitVectSetBit(rumask, + sym->regs[j]->rIdx); + } + + return rumask; +} + +/*-----------------------------------------------------------------*/ +/* regsUsedIniCode :- returns bit vector of registers used in iCode*/ +/*-----------------------------------------------------------------*/ +bitVect *regsUsedIniCode (iCode *ic) +{ + bitVect *rmask = newBitVect(nRegs); + + /* do the special cases first */ + if (ic->op == IFX ) { + rmask = bitVectUnion(rmask, + rUmaskForOp(IC_COND(ic))); + goto ret; + } + + /* for the jumptable */ + if (ic->op == JUMPTABLE) { + rmask = bitVectUnion(rmask, + rUmaskForOp(IC_JTCOND(ic))); + + goto ret; + } + + /* of all other cases */ + if (IC_LEFT(ic)) + rmask = bitVectUnion(rmask, + rUmaskForOp(IC_LEFT(ic))); + + + if (IC_RIGHT(ic)) + rmask = bitVectUnion(rmask, + rUmaskForOp(IC_RIGHT(ic))); + + if (IC_RESULT(ic)) + rmask = bitVectUnion(rmask, + rUmaskForOp(IC_RESULT(ic))); + + ret: + return rmask; +} + +/*-----------------------------------------------------------------*/ +/* createRegMask - for each instruction will determine the regsUsed*/ +/*-----------------------------------------------------------------*/ +void createRegMask (eBBlock **ebbs, int count) +{ + int i; + + /* for all blocks */ + for (i = 0; i < count ; i++ ) { + iCode *ic ; + + if ( ebbs[i]->noPath && + ( ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel )) + continue ; + + /* for all instructions */ + for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) { + + int j; + + if (SKIP_IC2(ic) || !ic->rlive) + continue ; + + /* first mark the registers used in this + instruction */ + ic->rUsed = regsUsedIniCode(ic); + funcrUsed = bitVectUnion(funcrUsed,ic->rUsed); + + /* now create the register mask for those + registers that are in use : this is a + super set of ic->rUsed */ + ic->rMask = newBitVect(nRegs+1); + + /* for all live Ranges alive at this point */ + for (j = 1; j < ic->rlive->size; j++ ) { + symbol *sym; + int k; + + /* if not alive then continue */ + if (!bitVectBitValue(ic->rlive,j)) + continue ; + + /* find the live range we are interested in */ + if (!(sym = hTabItemWithKey(liveRanges,j))) { + werror (E_INTERNAL_ERROR,__FILE__,__LINE__, + "createRegMask cannot find live range"); + exit(0); + } + + /* if no register assigned to it */ + if (!sym->nRegs || sym->isspilt) + continue ; + + /* for all the registers allocated to it */ + for (k = 0 ; k < sym->nRegs ;k++) + if (sym->regs[k]) + ic->rMask = + bitVectSetBit(ic->rMask,sym->regs[k]->rIdx); + } + } + } +} + +/*-----------------------------------------------------------------*/ +/* rematStr - returns the rematerialized string for a remat var */ +/*-----------------------------------------------------------------*/ +char *rematStr (symbol *sym) +{ + char *s = buffer; + iCode *ic = sym->rematiCode; + + while (1) { + + /* if plus or minus print the right hand side */ + if (ic->op == '+' || ic->op == '-') { + sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)), + ic->op ); + s += strlen(s); + ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode; + continue ; + } + + /* we reached the end */ + sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname); + break; + } + + return buffer ; +} + +/*-----------------------------------------------------------------*/ +/* regTypeNum - computes the type & number of registers required */ +/*-----------------------------------------------------------------*/ +void regTypeNum () +{ + symbol *sym; + int k; + iCode *ic; + + /* for each live range do */ + for ( sym = hTabFirstItem(liveRanges,&k); sym ; + sym = hTabNextItem(liveRanges,&k)) { + + /* if used zero times then no registers needed */ + if ((sym->liveTo - sym->liveFrom) == 0) + continue ; + + + /* if the live range is a temporary */ + if (sym->isitmp) { + + /* if the type is marked as a conditional */ + if (sym->regType == REG_CND) + continue ; + + /* if used in return only then we don't + need registers */ + if (sym->ruonly || sym->accuse) { + if (IS_AGGREGATE(sym->type) || sym->isptr) + sym->type = aggrToPtr(sym->type,FALSE); + continue ; + } + + /* if the symbol has only one definition & + that definition is a get_pointer and the + pointer we are getting is rematerializable and + in "data" space */ + + if (bitVectnBitsOn(sym->defs) == 1 && + (ic = hTabItemWithKey(iCodehTab, + bitVectFirstBit(sym->defs))) && + POINTER_GET(ic) && + !IS_BITVAR(sym->etype)) { + + + /* if remat in data space */ + if (OP_SYMBOL(IC_LEFT(ic))->remat && + DCL_TYPE(aggrToPtr(sym->type,FALSE)) == POINTER) { + + /* create a psuedo symbol & force a spil */ + symbol *psym = newSymbol(rematStr(OP_SYMBOL(IC_LEFT(ic))),1); + psym->type = sym->type; + psym->etype = sym->etype; + strcpy(psym->rname,psym->name); + sym->isspilt = 1; + sym->usl.spillLoc = psym; + continue ; + } + + /* if in data space or idata space then try to + allocate pointer register */ + + } + + /* if not then we require registers */ + sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ? + getSize(sym->type = aggrToPtr(sym->type,FALSE)) : + getSize(sym->type)); + + if (sym->nRegs > 4) { + fprintf(stderr,"allocated more than 4 or 0 registers for type "); + printTypeChain(sym->type,stderr);fprintf(stderr,"\n"); + } + + /* determine the type of register required */ + if (sym->nRegs == 1 && + IS_PTR(sym->type) && + sym->uptr) + sym->regType = REG_PTR ; + else + sym->regType = REG_GPR ; + + } else + /* for the first run we don't provide */ + /* registers for true symbols we will */ + /* see how things go */ + sym->nRegs = 0 ; + } + +} + +/*-----------------------------------------------------------------*/ +/* freeAllRegs - mark all registers as free */ +/*-----------------------------------------------------------------*/ +void freeAllRegs() +{ + int i; + + for (i=0;i< nRegs;i++ ) + regs8051[i].isFree = 1; +} + +/*-----------------------------------------------------------------*/ +/* deallocStackSpil - this will set the stack pointer back */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(deallocStackSpil) +{ + symbol *sym = item; + + deallocLocal(sym); + return 0; +} + +/*-----------------------------------------------------------------*/ +/* farSpacePackable - returns the packable icode for far variables */ +/*-----------------------------------------------------------------*/ +static iCode *farSpacePackable (iCode *ic) +{ + iCode *dic ; + + /* go thru till we find a definition for the + symbol on the right */ + for ( dic = ic->prev ; dic ; dic = dic->prev) { + + /* if the definition is a call then no */ + if ((dic->op == CALL || dic->op == PCALL) && + IC_RESULT(dic)->key == IC_RIGHT(ic)->key) { + return NULL; + } + + /* if shift by unknown amount then not */ + if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) && + IC_RESULT(dic)->key == IC_RIGHT(ic)->key) + return NULL; + + /* if pointer get and size > 1 */ + if (POINTER_GET(dic) && + getSize(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)) > 1) + return NULL ; + + if (POINTER_SET(dic) && + getSize(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)) > 1) + return NULL ; + + /* if any three is a true symbol in far space */ + if (IC_RESULT(dic) && + IS_TRUE_SYMOP(IC_RESULT(dic)) && + isOperandInFarSpace(IC_RESULT(dic))) + return NULL; + + if (IC_RIGHT(dic) && + IS_TRUE_SYMOP(IC_RIGHT(dic)) && + isOperandInFarSpace(IC_RIGHT(dic)) && + !isOperandEqual(IC_RIGHT(dic),IC_RESULT(ic))) + return NULL; + + if (IC_LEFT(dic) && + IS_TRUE_SYMOP(IC_LEFT(dic)) && + isOperandInFarSpace(IC_LEFT(dic)) && + !isOperandEqual(IC_LEFT(dic),IC_RESULT(ic))) + return NULL; + + if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(dic))) { + if ( (dic->op == LEFT_OP || + dic->op == RIGHT_OP || + dic->op == '-') && + IS_OP_LITERAL(IC_RIGHT(dic))) + return NULL; + else + return dic; + } + } + + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* packRegsForAssign - register reduction for assignment */ +/*-----------------------------------------------------------------*/ +int packRegsForAssign (iCode *ic,eBBlock *ebp) +{ + iCode *dic, *sic; + + if ( +/* !IS_TRUE_SYMOP(IC_RESULT(ic)) || */ + !IS_ITEMP(IC_RIGHT(ic)) || + OP_LIVETO(IC_RIGHT(ic)) > ic->seq || + OP_SYMBOL(IC_RIGHT(ic))->isind) + return 0; + + /* if the true symbol is defined in far space or on stack + then we should not since this will increase register pressure */ + if (isOperandInFarSpace(IC_RESULT(ic))) { + if ((dic = farSpacePackable(ic))) + goto pack; + else + return 0; + + } + /* find the definition of iTempNN scanning backwards if we find a + a use of the true symbol in before we find the definition then + we cannot */ + for ( dic = ic->prev ; dic ; dic = dic->prev) { + + /* if there is a function call and this is + a parameter & not my parameter then don't pack it */ + if ( (dic->op == CALL || dic->op == PCALL) && + (OP_SYMBOL(IC_RESULT(ic))->_isparm && + !OP_SYMBOL(IC_RESULT(ic))->ismyparm)) { + dic = NULL; + break; + } + + if (SKIP_IC2(dic)) + continue; + + if (IS_SYMOP(IC_RESULT(dic)) && + IC_RESULT(dic)->key == IC_RIGHT(ic)->key) { + if (POINTER_SET(dic)) + dic = NULL; + + break; + } + + if (IS_SYMOP(IC_RIGHT(dic)) && + (IC_RIGHT(dic)->key == IC_RESULT(ic)->key || + IC_RIGHT(dic)->key == IC_RIGHT(ic)->key)) { + dic = NULL; + break; + } + + if (IS_SYMOP(IC_LEFT(dic)) && + (IC_LEFT(dic)->key == IC_RESULT(ic)->key || + IC_LEFT(dic)->key == IC_RIGHT(ic)->key)) { + dic = NULL; + break; + } + + if (POINTER_SET(dic) && + IC_RESULT(dic)->key == IC_RESULT(ic)->key ) { + dic = NULL ; + break; + } + } + + if (!dic) + return 0 ; /* did not find */ + + /* if the result is on stack or iaccess then it must be + the same atleast one of the operands */ + if (OP_SYMBOL(IC_RESULT(ic))->onStack || + OP_SYMBOL(IC_RESULT(ic))->iaccess ) { + + /* the operation has only one symbol + operator then we can pack */ + if ((IC_LEFT(dic) && !IS_SYMOP(IC_LEFT(dic))) || + (IC_RIGHT(dic) && !IS_SYMOP(IC_RIGHT(dic)))) + goto pack; + + if (!((IC_LEFT(dic) && + IC_RESULT(ic)->key == IC_LEFT(dic)->key) || + (IC_RIGHT(dic) && + IC_RESULT(ic)->key == IC_RIGHT(dic)->key))) + return 0; + } +pack: + /* found the definition */ + /* replace the result with the result of */ + /* this assignment and remove this assignment */ + IC_RESULT(dic) = IC_RESULT(ic) ; + + if (IS_ITEMP(IC_RESULT(dic)) && OP_SYMBOL(IC_RESULT(dic))->liveFrom > dic->seq) { + OP_SYMBOL(IC_RESULT(dic))->liveFrom = dic->seq; + } + /* delete from liverange table also + delete from all the points inbetween and the new + one */ + for ( sic = dic; sic != ic ; sic = sic->next ) { + bitVectUnSetBit(sic->rlive,IC_RESULT(ic)->key); + if (IS_ITEMP(IC_RESULT(dic))) + bitVectSetBit(sic->rlive,IC_RESULT(dic)->key); + } + + remiCodeFromeBBlock(ebp,ic); + return 1; + +} + +/*-----------------------------------------------------------------*/ +/* findAssignToSym : scanning backwards looks for first assig found*/ +/*-----------------------------------------------------------------*/ +iCode *findAssignToSym (operand *op,iCode *ic) +{ + iCode *dic; + + for (dic = ic->prev ; dic ; dic = dic->prev) { + + /* if definition by assignment */ + if (dic->op == '=' && + !POINTER_SET(dic) && + IC_RESULT(dic)->key == op->key +/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ + ) { + + /* we are interested only if defined in far space */ + /* or in stack space in case of + & - */ + + /* if assigned to a non-symbol then return + true */ + if (!IS_SYMOP(IC_RIGHT(dic))) + break ; + + /* if the symbol is in far space then + we should not */ + if (isOperandInFarSpace(IC_RIGHT(dic))) + return NULL ; + + /* for + & - operations make sure that + if it is on the stack it is the same + as one of the three operands */ + if ((ic->op == '+' || ic->op == '-') && + OP_SYMBOL(IC_RIGHT(dic))->onStack) { + + if ( IC_RESULT(ic)->key != IC_RIGHT(dic)->key && + IC_LEFT(ic)->key != IC_RIGHT(dic)->key && + IC_RIGHT(ic)->key != IC_RIGHT(dic)->key) + return NULL; + } + + break ; + + } + + /* if we find an usage then we cannot delete it */ + if (IC_LEFT(dic) && IC_LEFT(dic)->key == op->key) + return NULL; + + if (IC_RIGHT(dic) && IC_RIGHT(dic)->key == op->key) + return NULL; + + if (POINTER_SET(dic) && IC_RESULT(dic)->key == op->key) + return NULL; + } + + /* now make sure that the right side of dic + is not defined between ic & dic */ + if (dic) { + iCode *sic = dic->next ; + + for (; sic != ic ; sic = sic->next) + if (IC_RESULT(sic) && + IC_RESULT(sic)->key == IC_RIGHT(dic)->key) + return NULL; + } + + return dic; + + +} + +/*-----------------------------------------------------------------*/ +/* packRegsForSupport :- reduce some registers for support calls */ +/*-----------------------------------------------------------------*/ +int packRegsForSupport (iCode *ic, eBBlock *ebp) +{ + int change = 0 ; + /* for the left & right operand :- look to see if the + left was assigned a true symbol in far space in that + case replace them */ + if (IS_ITEMP(IC_LEFT(ic)) && + OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) { + iCode *dic = findAssignToSym(IC_LEFT(ic),ic); + iCode *sic; + + if (!dic) + goto right ; + + /* found it we need to remove it from the + block */ + for ( sic = dic; sic != ic ; sic = sic->next ) + bitVectUnSetBit(sic->rlive,IC_LEFT(ic)->key); + + IC_LEFT(ic)->operand.symOperand = + IC_RIGHT(dic)->operand.symOperand; + IC_LEFT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key; + remiCodeFromeBBlock(ebp,dic); + change++; + } + + /* do the same for the right operand */ + right: + if (!change && + IS_ITEMP(IC_RIGHT(ic)) && + OP_SYMBOL(IC_RIGHT(ic))->liveTo <= ic->seq) { + iCode *dic = findAssignToSym(IC_RIGHT(ic),ic); + iCode *sic; + + if (!dic) + return change ; + + /* if this is a subtraction & the result + is a true symbol in far space then don't pack */ + if (ic->op == '-' && IS_TRUE_SYMOP(IC_RESULT(dic))) { + link *etype =getSpec(operandType(IC_RESULT(dic))); + if (IN_FARSPACE(SPEC_OCLS(etype))) + return change ; + } + /* found it we need to remove it from the + block */ + for ( sic = dic; sic != ic ; sic = sic->next ) + bitVectUnSetBit(sic->rlive,IC_RIGHT(ic)->key); + + IC_RIGHT(ic)->operand.symOperand = + IC_RIGHT(dic)->operand.symOperand; + IC_RIGHT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key; + + remiCodeFromeBBlock(ebp,dic); + change ++; + } + + return change ; +} + +#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly) + + +/*-----------------------------------------------------------------*/ +/* packRegsForOneuse : - will reduce some registers for single Use */ +/*-----------------------------------------------------------------*/ +static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp) +{ + bitVect *uses ; + iCode *dic, *sic; + + /* if returning a literal then do nothing */ + if (!IS_SYMOP(op)) + return NULL; + + /* only upto 2 bytes since we cannot predict + the usage of b, & acc */ + if (getSize(operandType(op)) > 2 && + ic->op != RETURN && + ic->op != SEND) + return NULL; + + /* this routine will mark the a symbol as used in one + instruction use only && if the defintion is local + (ie. within the basic block) && has only one definition && + that definiion is either a return value from a + function or does not contain any variables in + far space */ + uses = bitVectCopy(OP_USES(op)); + bitVectUnSetBit(uses,ic->key); /* take away this iCode */ + if (!bitVectIsZero(uses)) /* has other uses */ + return NULL ; + + /* if it has only one defintion */ + if (bitVectnBitsOn(OP_DEFS(op)) > 1) + return NULL ; /* has more than one definition */ + + /* get the that definition */ + if (!(dic = + hTabItemWithKey(iCodehTab, + bitVectFirstBit(OP_DEFS(op))))) + return NULL ; + + /* found the definition now check if it is local */ + if (dic->seq < ebp->fSeq || + dic->seq > ebp->lSeq) + return NULL ; /* non-local */ + + /* now check if it is the return from + a function call */ + if (dic->op == CALL || dic->op == PCALL ) { + if (ic->op != SEND && ic->op != RETURN) { + OP_SYMBOL(op)->ruonly = 1; + return dic; + } + dic = dic->next ; + } + + + /* otherwise check that the definition does + not contain any symbols in far space */ + if (isOperandInFarSpace(IC_LEFT(dic)) || + isOperandInFarSpace(IC_RIGHT(dic)) || + IS_OP_RUONLY(IC_LEFT(ic)) || + IS_OP_RUONLY(IC_RIGHT(ic)) ) { + return NULL; + } + + /* if pointer set then make sure the pointer + is one byte */ + if (POINTER_SET(dic) && + !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE))) + return NULL ; + + if (POINTER_GET(dic) && + !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE))) + return NULL ; + + sic = dic; + + /* also make sure the intervenening instructions + don't have any thing in far space */ + for (dic = dic->next ; dic && dic != ic ; dic = dic->next) { + + /* if there is an intervening function call then no */ + if (dic->op == CALL || dic->op == PCALL) + return NULL; + /* if pointer set then make sure the pointer + is one byte */ + if (POINTER_SET(dic) && + !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE))) + return NULL ; + + if (POINTER_GET(dic) && + !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE))) + return NULL ; + + /* if address of & the result is remat the okay */ + if (dic->op == ADDRESS_OF && + OP_SYMBOL(IC_RESULT(dic))->remat) + continue ; + + /* if operand has size of three or more & this + operation is a '*','/' or '%' then 'b' may + cause a problem */ + if (( dic->op == '%' || dic->op == '/' || dic->op == '*') && + getSize(aggrToPtr(operandType(op),FALSE)) >= 3) + return NULL; + + /* if left or right or result is in far space */ + if (isOperandInFarSpace(IC_LEFT(dic)) || + isOperandInFarSpace(IC_RIGHT(dic)) || + isOperandInFarSpace(IC_RESULT(dic)) || + IS_OP_RUONLY(IC_LEFT(dic)) || + IS_OP_RUONLY(IC_RIGHT(dic)) || + IS_OP_RUONLY(IC_RESULT(dic)) ) { + return NULL; + } + } + + OP_SYMBOL(op)->ruonly = 1; + return sic; + +} + +/*-----------------------------------------------------------------*/ +/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */ +/*-----------------------------------------------------------------*/ +static bool isBitwiseOptimizable (iCode *ic) +{ + link *ltype = getSpec(operandType(IC_LEFT(ic))); + link *rtype = getSpec(operandType(IC_RIGHT(ic))); + + /* bitwise operations are considered optimizable + under the following conditions (Jean-Louis VERN) + + x & lit + bit & bit + bit & x + bit ^ bit + bit ^ x + x ^ lit + x | lit + bit | bit + bit | x + */ + if ( IS_LITERAL(rtype) || + (IS_BITVAR(ltype) && IN_BITSPACE(SPEC_OCLS(ltype)))) + return TRUE ; + else + return FALSE ; +} + +/*-----------------------------------------------------------------*/ +/* packRegsForAccUse - pack registers for acc use */ +/*-----------------------------------------------------------------*/ +void packRegsForAccUse (iCode *ic) +{ + iCode *uic; + + /* if + or - then it has to be one byte result */ + if ((ic->op == '+' || ic->op == '-') + && getSize(operandType(IC_RESULT(ic))) > 1) + return ; + + /* if shift operation make sure right side is not a literal */ + if (ic->op == RIGHT_OP && + ( isOperandLiteral(IC_RIGHT(ic)) || + getSize(operandType(IC_RESULT(ic))) > 1)) + return ; + + if (ic->op == LEFT_OP && + ( isOperandLiteral(IC_RIGHT(ic)) || + getSize(operandType(IC_RESULT(ic))) > 1)) + return ; + + + /* has only one definition */ + if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1) + return ; + + /* has only one use */ + if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1) + return ; + + /* and the usage immediately follows this iCode */ + if (!(uic = hTabItemWithKey(iCodehTab, + bitVectFirstBit(OP_USES(IC_RESULT(ic)))))) + return ; + + if (ic->next != uic) + return ; + + /* if it is a conditional branch then we definitely can */ + if (uic->op == IFX ) + goto accuse; + + if ( uic->op == JUMPTABLE ) + return ; + + /* if the usage is not is an assignment + or an arithmetic / bitwise / shift operation then not */ + if (POINTER_SET(uic) && + getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1) + return; + + if (uic->op != '=' && + !IS_ARITHMETIC_OP(uic) && + !IS_BITWISE_OP(uic) && + uic->op != LEFT_OP && + uic->op != RIGHT_OP ) + return; + + /* if used in ^ operation then make sure right is not a + literl */ + if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic))) + return ; + + /* if shift operation make sure right side is not a literal */ + if (uic->op == RIGHT_OP && + ( isOperandLiteral(IC_RIGHT(uic)) || + getSize(operandType(IC_RESULT(uic))) > 1)) + return ; + + if (uic->op == LEFT_OP && + ( isOperandLiteral(IC_RIGHT(uic)) || + getSize(operandType(IC_RESULT(uic))) > 1)) + return ; + + /* make sure that the result of this icode is not on the + stack, since acc is used to compute stack offset */ + if (IS_TRUE_SYMOP(IC_RESULT(uic)) && + OP_SYMBOL(IC_RESULT(uic))->onStack) + return ; + + /* if either one of them in far space then we cannot */ + if ((IS_TRUE_SYMOP(IC_LEFT(uic)) && + isOperandInFarSpace(IC_LEFT(uic))) || + (IS_TRUE_SYMOP(IC_RIGHT(uic)) && + isOperandInFarSpace(IC_RIGHT(uic)))) + return ; + + /* if the usage has only one operand then we can */ + if (IC_LEFT(uic) == NULL || + IC_RIGHT(uic) == NULL) + goto accuse; + + /* make sure this is on the left side if not + a '+' since '+' is commutative */ + if (ic->op != '+' && + IC_LEFT(uic)->key != IC_RESULT(ic)->key) + return; + + /* if one of them is a literal then we can */ + if ((IC_LEFT(uic) && IS_OP_LITERAL(IC_LEFT(uic))) || + (IC_RIGHT(uic) && IS_OP_LITERAL(IC_RIGHT(uic)))) { + OP_SYMBOL(IC_RESULT(ic))->accuse = 1; + return ; + } + + /* if the other one is not on stack then we can */ + if (IC_LEFT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_RIGHT(uic)) || + (IS_TRUE_SYMOP(IC_RIGHT(uic)) && + !OP_SYMBOL(IC_RIGHT(uic))->onStack))) + goto accuse; + + if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && + (IS_ITEMP(IC_LEFT(uic)) || + (IS_TRUE_SYMOP(IC_LEFT(uic)) && + !OP_SYMBOL(IC_LEFT(uic))->onStack))) + goto accuse ; + + return ; + + accuse: + OP_SYMBOL(IC_RESULT(ic))->accuse = 1; + + +} + +/*-----------------------------------------------------------------*/ +/* packForPush - hueristics to reduce iCode for pushing */ +/*-----------------------------------------------------------------*/ +static void packForPush(iCode *ic, eBBlock *ebp) +{ + iCode *dic; + + if (ic->op != IPUSH || !IS_ITEMP(IC_LEFT(ic))) + return ; + + /* must have only definition & one usage */ + if (bitVectnBitsOn(OP_DEFS(IC_LEFT(ic))) != 1 || + bitVectnBitsOn(OP_USES(IC_LEFT(ic))) != 1 ) + return ; + + /* find the definition */ + if (!(dic = hTabItemWithKey(iCodehTab, + bitVectFirstBit(OP_DEFS(IC_LEFT(ic)))))) + return ; + + if (dic->op != '=' || POINTER_SET(dic)) + return; + + /* we now we know that it has one & only one def & use + and the that the definition is an assignment */ + IC_LEFT(ic) = IC_RIGHT(dic); + + remiCodeFromeBBlock(ebp,dic); +} + +/*-----------------------------------------------------------------*/ +/* packRegisters - does some transformations to reduce register */ +/* pressure */ +/*-----------------------------------------------------------------*/ +static void packRegisters (eBBlock *ebp) +{ + iCode *ic ; + int change = 0 ; + + while (1) { + + change = 0; + + /* look for assignments of the form */ + /* iTempNN = TRueSym (someoperation) SomeOperand */ + /* .... */ + /* TrueSym := iTempNN:1 */ + for ( ic = ebp->sch ; ic ; ic = ic->next ) { + + + /* find assignment of the form TrueSym := iTempNN:1 */ + if (ic->op == '=' && !POINTER_SET(ic)) + change += packRegsForAssign(ic,ebp); + } + + if (!change) + break; + } + + for ( ic = ebp->sch ; ic ; ic = ic->next ) { + + /* if this is an itemp & result of a address of a true sym + then mark this as rematerialisable */ + if (ic->op == ADDRESS_OF && + IS_ITEMP(IC_RESULT(ic)) && + IS_TRUE_SYMOP(IC_LEFT(ic)) && + bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) == 1 && + !OP_SYMBOL(IC_LEFT(ic))->onStack ) { + + OP_SYMBOL(IC_RESULT(ic))->remat = 1; + OP_SYMBOL(IC_RESULT(ic))->rematiCode = ic; + OP_SYMBOL(IC_RESULT(ic))->usl.spillLoc = NULL; + + } + + /* if straight assignment then carry remat flag if + this is the only definition */ + if (ic->op == '=' && + !POINTER_SET(ic) && + IS_SYMOP(IC_RIGHT(ic)) && + OP_SYMBOL(IC_RIGHT(ic))->remat && + bitVectnBitsOn(OP_SYMBOL(IC_RESULT(ic))->defs) <= 1) { + + OP_SYMBOL(IC_RESULT(ic))->remat = + OP_SYMBOL(IC_RIGHT(ic))->remat; + OP_SYMBOL(IC_RESULT(ic))->rematiCode = + OP_SYMBOL(IC_RIGHT(ic))->rematiCode ; + } + + /* if this is a +/- operation with a rematerizable + then mark this as rematerializable as well only + if the literal value is within the range -255 and + 255 + the assembler cannot handle it other wise */ + if ((ic->op == '+' || ic->op == '-') && + + (IS_SYMOP(IC_LEFT(ic)) && + IS_ITEMP(IC_RESULT(ic)) && + OP_SYMBOL(IC_LEFT(ic))->remat && + bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) == 1 && + IS_OP_LITERAL(IC_RIGHT(ic))) ) { + + int i = operandLitValue(IC_RIGHT(ic)); + if ( i < 255 && i > -255) { + OP_SYMBOL(IC_RESULT(ic))->remat = 1; + OP_SYMBOL(IC_RESULT(ic))->rematiCode = ic; + OP_SYMBOL(IC_RESULT(ic))->usl.spillLoc = NULL; + } + } + + /* mark the pointer usages */ + if (POINTER_SET(ic)) + OP_SYMBOL(IC_RESULT(ic))->uptr = 1; + + if (POINTER_GET(ic)) + OP_SYMBOL(IC_LEFT(ic))->uptr = 1; + + if (!SKIP_IC2(ic)) { + /* if we are using a symbol on the stack + then we should say ptrRegReq */ + if (ic->op == IFX && IS_SYMOP(IC_COND(ic))) + ptrRegReq += ((OP_SYMBOL(IC_COND(ic))->onStack || + OP_SYMBOL(IC_COND(ic))->iaccess) ? 1 : 0); + else + if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic))) + ptrRegReq += ((OP_SYMBOL(IC_JTCOND(ic))->onStack || + OP_SYMBOL(IC_JTCOND(ic))->iaccess) ? 1 : 0); + else { + if (IS_SYMOP(IC_LEFT(ic))) + ptrRegReq += ((OP_SYMBOL(IC_LEFT(ic))->onStack || + OP_SYMBOL(IC_LEFT(ic))->iaccess) ? 1 : 0); + if (IS_SYMOP(IC_RIGHT(ic))) + ptrRegReq += ((OP_SYMBOL(IC_RIGHT(ic))->onStack || + OP_SYMBOL(IC_RIGHT(ic))->iaccess) ? 1 : 0); + if (IS_SYMOP(IC_RESULT(ic))) + ptrRegReq += ((OP_SYMBOL(IC_RESULT(ic))->onStack || + OP_SYMBOL(IC_RESULT(ic))->iaccess) ? 1 : 0); + } + } + + /* if the condition of an if instruction + is defined in the previous instruction then + mark the itemp as a conditional */ + if ((IS_CONDITIONAL(ic) || + ( ( ic->op == BITWISEAND || + ic->op == '|' || + ic->op == '^' ) && + isBitwiseOptimizable(ic))) && + ic->next && ic->next->op == IFX && + isOperandEqual(IC_RESULT(ic),IC_COND(ic->next)) && + OP_SYMBOL(IC_RESULT(ic))->liveTo <= ic->next->seq) { + + OP_SYMBOL(IC_RESULT(ic))->regType = REG_CND; + continue ; + } + + /* reduce for support function calls */ + if (ic->supportRtn || ic->op == '+' || ic->op == '-' ) + packRegsForSupport (ic,ebp); + + /* some cases the redundant moves can + can be eliminated for return statements */ + if ((ic->op == RETURN || ic->op == SEND) && + !isOperandInFarSpace(IC_LEFT(ic)) && + !options.model) + packRegsForOneuse (ic,IC_LEFT(ic),ebp); + + /* if pointer set & left has a size more than + one and right is not in far space */ + if (POINTER_SET(ic) && + !isOperandInFarSpace(IC_RIGHT(ic)) && + !OP_SYMBOL(IC_RESULT(ic))->remat && + !IS_OP_RUONLY(IC_RIGHT(ic)) && + getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 ) + + packRegsForOneuse (ic,IC_RESULT(ic),ebp); + + /* if pointer get */ + if (POINTER_GET(ic) && + !isOperandInFarSpace(IC_RESULT(ic))&& + !OP_SYMBOL(IC_LEFT(ic))->remat && + !IS_OP_RUONLY(IC_RESULT(ic)) && + getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 ) + + packRegsForOneuse (ic,IC_LEFT(ic),ebp); + + + /* if this is cast for intergral promotion then + check if only use of the definition of the + operand being casted/ if yes then replace + the result of that arithmetic operation with + this result and get rid of the cast */ + if (ic->op == CAST) { + link *fromType = operandType(IC_RIGHT(ic)); + link *toType = operandType(IC_LEFT(ic)); + + if (IS_INTEGRAL(fromType) && IS_INTEGRAL(toType) && + getSize(fromType) != getSize(toType) ) { + + iCode *dic = packRegsForOneuse(ic,IC_RIGHT(ic),ebp); + if (dic) { + if (IS_ARITHMETIC_OP(dic)) { + IC_RESULT(dic) = IC_RESULT(ic); + remiCodeFromeBBlock(ebp,ic); + ic = ic->prev; + } else + OP_SYMBOL(IC_RIGHT(ic))->ruonly = 0; + } + } else { + + /* if the type from and type to are the same + then if this is the only use then packit */ + if (checkType(operandType(IC_RIGHT(ic)), + operandType(IC_LEFT(ic))) == 1) { + iCode *dic = packRegsForOneuse (ic,IC_RIGHT(ic),ebp); + if (dic) { + IC_RESULT(dic) = IC_RESULT(ic); + remiCodeFromeBBlock(ebp,ic); + ic = ic->prev; + } + } + } + } + + /* pack for PUSH + iTempNN := (some variable in farspace) V1 + push iTempNN ; + ------------- + push V1 + */ + if (ic->op == IPUSH ) { + packForPush(ic,ebp); + } + + + /* pack registers for accumulator use, when the + result of an arithmetic or bit wise operation + has only one use, that use is immediately following + the defintion and the using iCode has only one + operand or has two operands but one is literal & + the result of that operation is not on stack then + we can leave the result of this operation in acc:b + combination */ + if ((IS_ARITHMETIC_OP(ic) + + || IS_BITWISE_OP(ic) + + || ic->op == LEFT_OP || ic->op == RIGHT_OP + + ) && + IS_ITEMP(IC_RESULT(ic)) && + getSize(operandType(IC_RESULT(ic))) <= 2) + + packRegsForAccUse (ic); + + } +} + +/*-----------------------------------------------------------------*/ +/* assignRegisters - assigns registers to each live range as need */ +/*-----------------------------------------------------------------*/ +void assignRegisters (eBBlock **ebbs, int count) +{ + iCode *ic; + int i ; + + setToNull((void *)&funcrUsed); + ptrRegReq = stackExtend = dataExtend = 0; + /* if not register extentions then reduce number + of registers */ + if (options.regExtend) + nRegs = 13; + else + nRegs = 8; + + /* change assignments this will remove some + live ranges reducing some register pressure */ + for (i = 0 ; i < count ;i++ ) + packRegisters (ebbs[i]); + + if (options.dump_pack) + dumpEbbsToFileExt(".dumppack",ebbs,count); + + /* first determine for each live range the number of + registers & the type of registers required for each */ + regTypeNum (); + + /* and serially allocate registers */ + serialRegAssign(ebbs,count); + + /* if stack was extended then tell the user */ + if (stackExtend) { +/* werror(W_TOOMANY_SPILS,"stack", */ +/* stackExtend,currFunc->name,""); */ + stackExtend = 0 ; + } + + if (dataExtend) { +/* werror(W_TOOMANY_SPILS,"data space", */ +/* dataExtend,currFunc->name,""); */ + dataExtend = 0 ; + } + + /* after that create the register mask + for each of the instruction */ + createRegMask (ebbs,count); + + /* redo that offsets for stacked automatic variables */ + redoStackOffsets (); + + if (options.dump_rassgn) + dumpEbbsToFileExt(".dumprassgn",ebbs,count); + + /* now get back the chain */ + ic = iCodeLabelOptimize(iCodeFromeBBlock (ebbs,count)); + + + gen51Code(ic); + + /* free up any stackSpil locations allocated */ + applyToSet(stackSpil,deallocStackSpil); + slocNum = 0; + setToNull((void **)&stackSpil); + setToNull((void **)&spiltSet); + /* mark all registers as free */ + freeAllRegs(); + + return ; +} diff --git a/src/mcs51/ralloc.h b/src/mcs51/ralloc.h new file mode 100644 index 00000000..4db755fb --- /dev/null +++ b/src/mcs51/ralloc.h @@ -0,0 +1,58 @@ +/*------------------------------------------------------------------------- + + SDCCralloc.h - header file register allocation + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ +#include "SDCCicode.h" +#include "SDCCBBlock.h" +#ifndef SDCCRALLOC_H +#define SDCCRALLOC_H 1 + +enum { R2_IDX = 0, R3_IDX , R4_IDX , + R5_IDX ,R6_IDX , R7_IDX , + R0_IDX ,R1_IDX , X8_IDX , + X9_IDX ,X10_IDX , X11_IDX , + X12_IDX ,CND_IDX }; + + +#define REG_PTR 0x01 +#define REG_GPR 0x02 +#define REG_CND 0x04 +/* definition for the registers */ +typedef struct regs +{ + short type; /* can have value + REG_GPR, REG_PTR or REG_CND */ + short rIdx ; /* index into register table */ + short otype; + char *name ; /* name */ + char *dname; /* name when direct access needed */ + char *base ; /* base address */ + short offset; /* offset from the base */ + unsigned isFree :1; /* is currently unassigned */ +} regs; +extern regs regs8051[]; + +void assignRegisters (eBBlock **, int ); +regs *regWithIdx (int); + +#endif diff --git a/support/cpp/Makefile.dep b/support/cpp/Makefile.dep deleted file mode 100644 index 4b674457..00000000 --- a/support/cpp/Makefile.dep +++ /dev/null @@ -1,7 +0,0 @@ -cppalloc.o: cppalloc.c config.h i386/i386.h i386/xm-linux.h -cpperror.o: cpperror.c cpplib.h -cppexp.o: cppexp.c config.h i386/i386.h i386/xm-linux.h cpplib.h -cpphash.o: cpphash.c cpplib.h cpphash.h -cpplib.o: cpplib.c ../../sdccconf.h config.h i386/i386.h \ - i386/xm-linux.h cpplib.h cpphash.h -cppmain.o: cppmain.c cpplib.h diff --git a/support/gc/Makefile b/support/gc/Makefile deleted file mode 100644 index 7f708715..00000000 --- a/support/gc/Makefile +++ /dev/null @@ -1,417 +0,0 @@ -# Generated automatically from Makefile.in by configure. -# Primary targets: -# gc.a - builds basic library -# libgc.a - builds library for use with g++ "-fgc-keyword" extension -# c++ - adds C++ interface to library -# cords - adds cords (heavyweight strings) to library -# test - prints porting information, then builds basic version of gc.a, -# and runs some tests of collector and cords. Does not add cords or -# c++ interface to gc.a -# cord/de - builds dumb editor based on cords. -ABI_FLAG= -CC = gcc $(ABI_FLAG) -CXX = c++ $(ABI_FLAG) -AS = as $(ABI_FLAG) -PRJDIR = ../.. -srcdir = . -# The above doesn't work with gas, which doesn't run cpp. -# Define AS as `gcc -c -x assembler-with-cpp' instead. -# Under Irix 6, you will have to specify the ABI for as if you specify -# it for the C compiler. - -CFLAGS= -O2 -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION -DSILENT -I /usr/local/include - -# For dynamic library builds, it may be necessary to add flags to generate -# PIC code, e.g. -fPIC on Linux. - -# Setjmp_test may yield overly optimistic results when compiled -# without optimization. -# -DSILENT disables statistics printing, and improves performance. -# -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly -# altered stubborn objects, at substantial performance cost. -# Use only for incremental collector debugging. -# -DFIND_LEAK causes the collector to assume that all inaccessible -# objects should have been explicitly deallocated, and reports exceptions. -# Finalization and the test program are not usable in this mode. -# -DSOLARIS_THREADS enables support for Solaris (thr_) threads. -# (Clients should also define SOLARIS_THREADS and then include -# gc.h before performing thr_ or dl* or GC_ operations.) -# Must also define -D_REENTRANT. -# -D_SOLARIS_PTHREADS enables support for Solaris pthreads. -# Define SOLARIS_THREADS as well. -# -DIRIX_THREADS enables support for Irix pthreads. See README.irix. -# _DLINUX_THREADS enables support for Xavier Leroy's Linux threads. -# see README.linux. -D_REENTRANT may also be required. -# -DALL_INTERIOR_POINTERS allows all pointers to the interior -# of objects to be recognized. (See gc_priv.h for consequences.) -# -DSMALL_CONFIG tries to tune the collector for small heap sizes, -# usually causing it to use less space in such situations. -# Incremental collection no longer works in this case. -# -DLARGE_CONFIG tunes the collector for unusually large heaps. -# Necessary for heaps larger than about 500 MB on most machines. -# Recommended for heaps larger than about 64 MB. -# -DDONT_ADD_BYTE_AT_END is meaningful only with -# -DALL_INTERIOR_POINTERS. Normally -DALL_INTERIOR_POINTERS -# causes all objects to be padded so that pointers just past the end of -# an object can be recognized. This can be expensive. (The padding -# is normally more than one byte due to alignment constraints.) -# -DDONT_ADD_BYTE_AT_END disables the padding. -# -DNO_SIGNALS does not disable signals during critical parts of -# the GC process. This is no less correct than many malloc -# implementations, and it sometimes has a significant performance -# impact. However, it is dangerous for many not-quite-ANSI C -# programs that call things like printf in asynchronous signal handlers. -# -DNO_EXECUTE_PERMISSION may cause some or all of the heap to not -# have execute permission, i.e. it may be impossible to execute -# code from the heap. Currently this only affects the incremental -# collector on UNIX machines. It may greatly improve its performance, -# since this may avoid some expensive cache synchronization. -# -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the -# new syntax "operator new[]" for allocating and deleting arrays. -# See gc_cpp.h for details. No effect on the C part of the collector. -# This is defined implicitly in a few environments. -# -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined -# as aliases for X, GC_realloc, and GC_free, respectively. -# Calloc is redefined in terms of the new malloc. X should -# be either GC_malloc or GC_malloc_uncollectable. -# The former is occasionally useful for working around leaks in code -# you don't want to (or can't) look at. It may not work for -# existing code, but it often does. Neither works on all platforms, -# since some ports use malloc or calloc to obtain system memory. -# (Probably works for UNIX, and win32.) -# -DIGNORE_FREE turns calls to free into a noop. Only useful with -# -DREDIRECT_MALLOC. -# -DNO_DEBUGGING removes GC_dump and the debugging routines it calls. -# Reduces code size slightly at the expense of debuggability. -# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of -# order by specifying a nonstandard finalization mark procedure (see -# finalize.c). Objects reachable from finalizable objects will be marked -# in a sepearte postpass, and hence their memory won't be reclaimed. -# Not recommended unless you are implementing a language that specifies -# these semantics. -# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response -# to explicit GC_invoke_finalizers() calls. -# -DATOMIC_UNCOLLECTABLE includes code for GC_malloc_atomic_uncollectable. -# This is useful if either the vendor malloc implementation is poor, -# or if REDIRECT_MALLOC is used. -# -DHBLKSIZE=ddd, where ddd is a power of 2 between 512 and 16384, explicitly -# sets the heap block size. Each heap block is devoted to a single size and -# kind of object. For the incremental collector it makes sense to match -# the most likely page size. Otherwise large values result in more -# fragmentation, but generally better performance for large heaps. -# -DUSE_MMAP use MMAP instead of sbrk to get new memory. -# Works for Solaris and Irix. -# -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than -# GC_scratch_alloc() to get stack memory. -# -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever -# the garbage collector detects a value that looks almost, but not quite, -# like a pointer, print both the address containing the value, and the -# value of the near-bogus-pointer. Can be used to identifiy regions of -# memory that are likely to contribute misidentified pointers. -# -DOLD_BLOCK_ALLOC Use the old, possibly faster, large block -# allocation strategy. The new strategy tries harder to minimize -# fragmentation, sometimes at the expense of spending more time in the -# large block allocator and/or collecting more frequently. -# If you expect the allocator to promtly use an explicitly expanded -# heap, this is highly recommended. -# - - - -LIBGC_CFLAGS= -O -DNO_SIGNALS -DSILENT \ - -DREDIRECT_MALLOC=GC_malloc_uncollectable \ - -DDONT_ADD_BYTE_AT_END -DALL_INTERIOR_POINTERS -# Flags for building libgc.a -- the last two are required. - -CXXFLAGS= $(CFLAGS) -AR= ar -RANLIB= ranlib - - -# Redefining srcdir allows object code for the nonPCR version of the collector -# to be generated in different directories. In this case, the destination directory -# should contain a copy of the original include directory. -srcdir = . - -OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o - -CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c - -CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c cord/cord.h cord/ec.h cord/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC cord/SCOPTIONS.amiga cord/SMakefile.amiga - -CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o - -SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \ - sparc_mach_dep.s gc.h gc_typed.h gc_hdrs.h gc_priv.h gc_private.h \ - gcconfig.h gc_mark.h include/gc_inl.h include/gc_inline.h gc.man \ - threadlibs.c if_mach.c if_not_there.c gc_cpp.cc gc_cpp.h weakpointer.h \ - gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h gc_alloc.h \ - include/new_gc_alloc.h include/javaxfc.h sparc_sunos4_mach_dep.s \ - solaris_threads.h $(CORD_SRCS) - -OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \ - README test.c test_cpp.cc setjmp_t.c SMakefile.amiga \ - SCoptions.amiga README.amiga README.win32 cord/README \ - cord/gc.h include/gc.h include/gc_typed.h include/cord.h \ - include/ec.h include/private/cord_pos.h include/private/gcconfig.h \ - include/private/gc_hdrs.h include/private/gc_priv.h \ - include/gc_cpp.h README.rs6000 \ - include/weakpointer.h README.QUICK callprocs pc_excludes \ - barrett_diagram README.OS2 README.Mac MacProjects.sit.hqx \ - MacOS.c EMX_MAKEFILE makefile.depend README.debugging \ - include/gc_cpp.h Mac_files/datastart.c Mac_files/dataend.c \ - Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \ - add_gc_prefix.c README.solaris2 README.sgi README.hp README.uts \ - win32_threads.c NT_THREADS_MAKEFILE gc.mak README.dj Makefile.dj \ - README.alpha README.linux version.h Makefile.DLLs gc_watcom.asm \ - WCC_MAKEFILE - -CORD_INCLUDE_FILES= $(srcdir)/gc.h $(srcdir)/cord/cord.h $(srcdir)/cord/ec.h \ - $(srcdir)/cord/private/cord_pos.h - -UTILS= if_mach if_not_there threadlibs - -# Libraries needed for curses applications. Only needed for de. -CURSES= -lcurses -ltermlib - -# The following is irrelevant on most systems. But a few -# versions of make otherwise fork the shell specified in -# the SHELL environment variable. -SHELL= /bin/sh - -SPECIALCFLAGS = -# Alternative flags to the C compiler for mach_dep.c. -# Mach_dep.c often doesn't like optimization, and it's -# not time-critical anyway. -# Set SPECIALCFLAGS to -q nodirect_code on Encore. - -#all: checkconf libgc.a gctest -all: checkconf libgc.a - -pcr: PCR-Makefile gc_private.h gc_hdrs.h gc.h gcconfig.h mach_dep.o $(SRCS) - make -f PCR-Makefile depend - make -f PCR-Makefile - -$(OBJS) test.o dyn_load.o dyn_load_sunos53.o: $(srcdir)/gc_priv.h $(srcdir)/gc_hdrs.h $(srcdir)/gc.h \ - $(srcdir)/gcconfig.h $(srcdir)/gc_typed.h Makefile -# The dependency on Makefile is needed. Changing -# options such as -DSILENT affects the size of GC_arrays, -# invalidating all .o files that rely on gc_priv.h - -mark.o typd_mlc.o finalize.o: $(srcdir)/gc_mark.h - -base_lib libgc.a: $(OBJS) dyn_load.o $(UTILS) - echo > base_lib - rm -f on_sparc_sunos5_1 - ./if_mach SPARC SUNOS5 touch on_sparc_sunos5_1 - ./if_mach SPARC SUNOS5 $(AR) rus libgc.a $(OBJS) dyn_load.o - ./if_not_there on_sparc_sunos5_1 $(AR) ru libgc.a $(OBJS) dyn_load.o - ./if_not_there on_sparc_sunos5_1 $(RANLIB) libgc.a || cat /dev/null -# ignore ranlib failure; that usually means it doesn't exist, and isn't needed - -cords: $(CORD_OBJS) cord/cordtest $(UTILS) - rm -f on_sparc_sunos5_3 - ./if_mach SPARC SUNOS5 touch on_sparc_sunos5_3 - ./if_mach SPARC SUNOS5 $(AR) rus libgc.a $(CORD_OBJS) - ./if_not_there on_sparc_sunos5_3 $(AR) ru libgc.a $(CORD_OBJS) - ./if_not_there on_sparc_sunos5_3 $(RANLIB) libgc.a || cat /dev/null - -gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/gc_cpp.h $(srcdir)/gc.h Makefile - $(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc - -test_cpp: $(srcdir)/test_cpp.cc $(srcdir)/gc_cpp.h gc_cpp.o $(srcdir)/gc.h \ -base_lib $(UTILS) - rm -f test_cpp - ./if_mach HP_PA "" $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o libgc.a -ldld - ./if_not_there test_cpp $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o libgc.a `./threadlibs` - -c++: gc_cpp.o $(srcdir)/gc_cpp.h test_cpp - rm -f on_sparc_sunos5_4 - ./if_mach SPARC SUNOS5 touch on_sparc_sunos5_4 - ./if_mach SPARC SUNOS5 $(AR) rus libgc.a gc_cpp.o - ./if_not_there on_sparc_sunos5_4 $(AR) ru libgc.a gc_cpp.o - ./if_not_there on_sparc_sunos5_4 $(RANLIB) libgc.a || cat /dev/null - ./test_cpp 1 - echo > c++ - -dyn_load_sunos53.o: dyn_load.c - $(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@ - -# SunOS5 shared library version of the collector -sunos5gc.so: $(OBJS) dyn_load_sunos53.o - $(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o -ldl - ln sunos5gc.so libgc.so - -# Alpha/OSF shared library version of the collector -libalphagc.so: $(OBJS) - ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc - ln libalphagc.so libgc.so - -# IRIX shared library version of the collector -libirixgc.so: $(OBJS) dyn_load.o - ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc - ln libirixgc.so libgc.so - -# Linux shared library version of the collector -liblinuxgc.so: $(OBJS) dyn_load.o - gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo - ln liblinuxgc.so libgc.so - -mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s $(srcdir)/rs6000_mach_dep.s $(UTILS) - rm -f mach_dep.o - ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s - ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s - ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s - ./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s - ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.s - ./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.s - ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s - ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c - -mark_rts.o: $(srcdir)/mark_rts.c if_mach if_not_there $(UTILS) - rm -f mark_rts.o - -./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c - ./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c -# Work-around for DEC optimizer tail recursion elimination bug. -# The ALPHA-specific line should be removed if gcc is used. - -alloc.o: version.h - -cord/cordbscs.o: $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES) - $(CC) $(CFLAGS) -c $(srcdir)/cord/cordbscs.c - mv cordbscs.o cord/cordbscs.o -# not all compilers understand -o filename - -cord/cordxtra.o: $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES) - $(CC) $(CFLAGS) -c $(srcdir)/cord/cordxtra.c - mv cordxtra.o cord/cordxtra.o - -cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES) - $(CC) $(CFLAGS) -c $(srcdir)/cord/cordprnt.c - mv cordprnt.o cord/cordprnt.o - -cord/cordtest: $(srcdir)/cord/cordtest.c $(CORD_OBJS) libgc.a $(UTILS) - rm -f cord/cordtest - ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) libgc.a -lucb - ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) libgc.a -ldld - ./if_not_there cord/cordtest $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) libgc.a `./threadlibs` - -cord/de: $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a $(UTILS) - rm -f cord/de - ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a $(CURSES) -lucb `./threadlibs` - ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a $(CURSES) -ldld - ./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a -lcurses - ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a -lcurses `./threadlibs` - ./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a -lcurses - ./if_not_there cord/de $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o libgc.a $(CURSES) `./threadlibs` - -if_mach: $(srcdir)/if_mach.c $(srcdir)/gcconfig.h - $(CC) $(CFLAGS) -o if_mach $(srcdir)/if_mach.c - -threadlibs: $(srcdir)/threadlibs.c $(srcdir)/gcconfig.h Makefile - $(CC) $(CFLAGS) -o threadlibs $(srcdir)/threadlibs.c - -if_not_there: $(srcdir)/if_not_there.c - $(CC) $(CFLAGS) -o if_not_there $(srcdir)/if_not_there.c - -clean: - rm -f libgc.a *.o gctest gctest_dyn_link test_cpp \ - setjmp_test mon.out gmon.out a.out core if_not_there if_mach \ - threadlibs $(CORD_OBJS) cord/cordtest cord/de - -rm -f *~ - -gctest: test.o libgc.a if_mach if_not_there - rm -f gctest - ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest test.o libgc.a -lucb - ./if_mach HP_PA "" $(CC) $(CFLAGS) -o gctest test.o libgc.a -ldld - ./if_not_there gctest $(CC) $(CFLAGS) -o gctest test.o libgc.a `./threadlibs` - -# If an optimized setjmp_test generates a segmentation fault, -# odds are your compiler is broken. Gctest may still work. -# Try compiling setjmp_t.c unoptimized. -setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/gc.h if_mach if_not_there - $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c - -test: KandRtest cord/cordtest - cord/cordtest - -# Those tests that work even with a K&R C compiler: -KandRtest: setjmp_test gctest - ./setjmp_test - ./gctest - -add_gc_prefix: add_gc_prefix.c - $(CC) -o add_gc_prefix $(srcdir)/add_gc_prefix.c - -gc.tar: $(SRCS) $(OTHER_FILES) add_gc_prefix - ./add_gc_prefix $(SRCS) $(OTHER_FILES) > /tmp/gc.tar-files - (cd $(srcdir)/.. ; tar cvfh - `cat /tmp/gc.tar-files`) > gc.tar - -pc_gc.tar: $(SRCS) $(OTHER_FILES) - tar cvfX pc_gc.tar pc_excludes $(SRCS) $(OTHER_FILES) - -floppy: pc_gc.tar - -mmd a:/cord - -mmd a:/cord/private - -mmd a:/include - -mmd a:/include/private - mkdir /tmp/pc_gc - cat pc_gc.tar | (cd /tmp/pc_gc; tar xvf -) - -mcopy -tmn /tmp/pc_gc/* a: - -mcopy -tmn /tmp/pc_gc/cord/* a:/cord - -mcopy -mn /tmp/pc_gc/cord/de_win.ICO a:/cord - -mcopy -tmn /tmp/pc_gc/cord/private/* a:/cord/private - -mcopy -tmn /tmp/pc_gc/include/* a:/include - -mcopy -tmn /tmp/pc_gc/include/private/* a:/include/private - rm -r /tmp/pc_gc - -gc.tar.Z: gc.tar - compress gc.tar - -gc.tar.gz: gc.tar - gzip gc.tar - -lint: $(CSRCS) test.c - lint -DLINT $(CSRCS) test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall" - -# BTL: added to test shared library version of collector. -# Currently works only under SunOS5. Requires GC_INIT call from statically -# loaded client code. -ABSDIR = `pwd` -gctest_dyn_link: test.o libgc.so - $(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link test.o -lgc -ldl -lthread - -gctest_irix_dyn_link: test.o libirixgc.so - $(CC) -L$(ABSDIR) -o gctest_irix_dyn_link test.o -lirixgc - -test_dll.o: test.c libgc_globals.h - $(CC) $(CFLAGS) -DGC_USE_DLL -c test.c -o test_dll.o - -test_dll: test_dll.o libgc_dll.a libgc.dll - $(CC) test_dll.o -L$(ABSDIR) -lgc_dll -o test_dll - -SYM_PREFIX-libgc=GC - -# Uncomment the following line to build a GNU win32 DLL -# include Makefile.DLLs - -reserved_namespace: $(SRCS) - for file in $(SRCS) test.c test_cpp.cc; do \ - sed s/GC_/_GC_/g < $$file > tmp; \ - cp tmp $$file; \ - done - -user_namespace: $(SRCS) - for file in $(SRCS) test.c test_cpp.cc; do \ - sed s/_GC_/GC_/g < $$file > tmp; \ - cp tmp $$file; \ - done - -# Remake configuration -checkconf: - @if [ -f $(srcdir)/../devel ]; then \ - $(MAKE) -f $(srcdir)/conf.mk freshconf \ - srcdir="$(srcdir)" PRJDIR="$(PRJDIR)"; \ - fi - -# End of Makefile -- 2.30.2