home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------- */
- /* Copyright (C) 1991 by Natürlich! */
- /* This file is copyrighted! */
- /* Refer to the documentation for details. */
- /* ---------------------------------------------------------------------- */
- #define __BIG_GENERATOR__
- #include "defines.h"
- #include "nasm.h"
- #include OSBIND
- #include "labels.h"
- #include "seg.h"
- #include NMALLOC_H
- #include "object.h"
- #include "fix.h"
- #include "process.h"
- #include "code.h"
- #include "op.h"
-
- /*#if DEBUG*/
- #include <stdio.h>
- #include "debug.h"
- /*#endif*/
-
- #if ! DORECLAIM
- # define expr_tryfree( x)
- #endif
-
- extern byte scrtab[];
- extern int runnable, better, show_open;
- extern seg huge *h_seg, huge *sp;
- extern imm huge *cip;
- byte huge *__program, huge *__p, huge *ptohead;
- byte __c;
- word __pc, __x;
- lword __lx;
-
-
- static char
- invadr[] = "Instruction can't use that addressing mode",
- data_loss[] = "Something's amiss after instruction",
- modi_loss[] = "No forward references in the modifier",
- org_loss[] = "Can't set * with a forward reference",
- ds_loss[] = "No fwd reference with a reserve-memory directive";
-
-
- void pro_init()
- {
- ENTER("pro_init");
- __p = __program = nmalloc( MAXMODULE + 6 + MAX_SAFETY);
- __pc = DEFORG; /* default org */
- if( runnable)
- {
- dpoke( __p, 0xFFFF);
- _advance( 2);
- dpoke( __p, __pc);
- _advance( 4);
- }
- build_rseg( S_UNKNOWN, 0);
- LEAVE();
- }
-
- void pro_exit()
- {
- ENTER("pro_exit");
- if( h_seg == sp && sis_unknown( sp))
- nerror("Not a single byte was generated");
- if( runnable)
- if( sis_unknown( sp))
- _retreat( 4);
- else
- {
- register byte huge *p = &__program[ sp->index - 2];
-
- dpoke( p, __pc - 1);
- }
- else
- if( sis_code( sp))
- sp->size = calc_index();
- LEAVE();
- }
-
- #if ! VERSION
- void do_patch( p)
- register expr huge *p;
- {
- if( ! runnable)
- if( e_pcrel( p))
- if( unvalued( p))
- {
- save_patch( calc_index(), p->op, 0);
- }
- else
- save_patch( calc_index(), p->op & O_BITS, p->aux);
- }
- #else
- # define do_patch( p) \
- if( ! runnable) \
- if( e_pcrel( p)) \
- if( unvalued( p)) \
- { \
- save_patch( calc_index(), p->op, 0); \
- } \
- else \
- save_patch( calc_index(), p->op & O_BITS, p->aux)
- #endif
-
-
- static void wgen_error()
- {
- nerror( data_loss);
- wdeposit( 0);
- }
-
- static void gen_error()
- {
- nerror( data_loss);
- deposit( 0);
- }
-
-
- void generate( tab, mode, ex)
- register byte huge *tab;
- register int mode;
- register expr huge *ex;
- {
- register int flag = 0;
-
- ENTER("generate");
- IMESS("ex = $%lX", (lword) ex, 4);
- check_fseg( sp, S_RCODE);
- if( mode == C_ABS && tab[ mode] == 255)
- mode = C_RELA;
- if( ex)
- if( ((flag = valued( ex)) && ex->val < 0x100) || ex->op & O_ZEROP)
- if( mode >= C_ABS && mode <= C_RELY)
- mode -= (C_ABS - C_ABS0);
-
- switch( mode)
- {
- case C_IMPL :
- case C_ACCU :
- if( tab[ mode] == 255)
- {
- deposit( 0); /* is a BRK */
- }
- else
- {
- cmddeposit( tab, mode);
- }
- break;
-
- case C_IMM :
- cmddeposit( tab, C_IMM);
- ex_chk( ex);
- do_patch( ex);
- ex_deposit( ex, cip, flag);
- break;
-
- case C_RELA :
- cmddeposit( tab, mode);
- if( flag)
- {
- if( (mode = ex->val - __pc - 1) < -127)
- nerror("Backward branch out of range");
- deposit( mode);
- expr_tryfree( ex);
- break;
- }
- ex_chk( ex);
- fix_up( ex, (imm huge *) 0, FIX_BRANCH);
- deposit( 0);
- ex->aux = __pc;
- break;
-
- case C_INDX :
- if( tab[ mode] == 124)
- {
- deposit( 124);
- wex_chk( ex);
- wex_deposit( ex, flag);
- break;
- }
-
- case C_INDY :
- cmddeposit( tab, mode);
- ex_chk( ex);
- ex_deposit( ex, 0, flag);
- if( ex->val >= 0x100)
- nerror("(adr),y or (adr,x) adr was not ZEROPAGE.");
- /* might have been a warning as well */
- break;
-
- case C_RELX0 :
- case C_RELY0 :
- case C_ABS0 :
- if( __c = tab[mode])
- {
- deposit( __c);
- ex_chk( ex);
- ex_deposit( ex, 0, flag);
- break;
- }
- mode += (C_ABS - C_ABS0); /* and fall thru */
-
- case C_RELX :
- case C_RELY :
- case C_ABS :
- there:
- cmddeposit( tab, mode);
- wex_chk( ex);
- wex_deposit( ex, flag);
- break;
-
- case C_IND :
- if( tab[ mode] == 108) /* is it a jump */
- goto there;
- cmddeposit( tab, mode);
- ex_chk( ex);
- ex_deposit( ex, 0, flag);
- if( ex->val >= 0x100)
- nerror("(adr) - 65C02 BTW - was not ZEROPAGE.");
-
- }
- LEAVE();
- return;
- }
-
-
- void dropbytes( ex, l, cflag)
- expr huge *ex;
- register lexpr huge *l;
- int cflag;
- {
- register word i,
- offset = 0;
- register byte huge *p;
-
- ENTER("dropbytes");
- if( ex)
- if( valued( ex))
- offset = ex->val;
- else
- {
- nerror( modi_loss);
- LEAVE();
- return;
- }
-
- check_fseg( sp, S_SDATA);
- while( l)
- {
- if( p = (byte huge *) l->string)
- {
- i = pdbeek( p);
- IMESS("dropping string of size %d", (lword) i, 2);
- if( i)
- {
- while( i-- > 1)
- {
- deposit( *p++ + offset);
- }
- if( cflag)
- {
- deposit( (*p++ ^ 0x80) + offset);
- }
- else
- {
- deposit( *p++ + offset);
- }
- }
- else
- nwarning("empty string");
- }
- else
- {
- register expr huge *p;
-
- p = l->expr;
- do_patch( p);
- if( valued( p))
- {
- deposit( p->val + offset);
- expr_tryfree( p);
- }
- else
- {
- fix_up( p, cip, FIX_ZCODE);
- deposit( offset);
- }
- }
- l = l->next;
- }
- LEAVE();
- }
-
- void dropsbytes( ex, l)
- expr huge *ex;
- register lexpr huge *l;
- {
- register word i,
- offset = 0;
- register byte huge *p;
-
- ENTER("dropsbytes");
- if( ex)
- if( valued( ex))
- offset = ex->val;
- else
- {
- nerror( modi_loss);
- LEAVE();
- return;
- }
-
- check_fseg( sp, S_SDATA);
- while( l)
- {
- if( p = (byte *) l->string)
- {
- i = pdbeek( p);
- IMESS("dropping string of size %d", (lword) i, 2);
- if( i)
- do
- {
- deposit( scrtab[*p++] + offset);
- }
- while( --i);
- else
- nwarning("empty string");
- }
- else
- {
- register expr huge *p;
-
- p = l->expr;
- MESS("was expr");
- do_patch( p);
- if( valued( p)) /* get rid of switch */
- {
- deposit( scrtab[ p->val] + offset);
- expr_tryfree( p);
- }
- else
- {
- check_fseg( sp, e_pcrel( p) ? S_RDATA : S_SDATA);
- fix_up( p, cip, FIX_SZCODE);
- deposit( offset);
- }
- }
- l = l->next;
- }
- LEAVE();
- }
-
-
- void dropwords( l)
- register lexpr huge *l;
- {
- register expr huge *p;
-
- ENTER("dropwords");
- while( l)
- {
- p = l->expr;
- MESS("cheking expr");
- if( valued( p)) /* get rid of switch */
- {
- if( e_pcrel( p))
- {
- check_fseg( sp, S_RDATA);
- }
- else
- {
- check_fseg( sp, S_SDATA);
- }
- wdeposit( p->val);
- expr_tryfree( p);
- }
- else
- {
- check_fseg( sp, e_pcrel( p) ? S_RDATA : S_SDATA);
- fix_up( p, (imm *) 0, FIX_WCODE);
- IMESS("FIX_WCODE @$%8.8lX", (lword) __p, 4);
- wdeposit( 0);
- }
- l = l->next;
- }
- LEAVE();
- }
-
-
- void dropdbytes( l)
- register lexpr huge *l;
- {
- register expr huge *p;
-
- ENTER("dropdbytes");
- IMESS("Got lexpr @$%8.8X", (lword) l, 4);
- while( l)
- {
- p = l->expr;
- IMESS("Got expr @$%8.8X", (lword) p, 4);
- if( valued( p)) /* get rid of switch */
- {
- MESS("wddepositing value");
- if( e_pcrel( p))
- {
- check_fseg( sp, S_TDATA);
- }
- else
- {
- check_fseg( sp, S_SDATA);
- }
- wddeposit( p->val);
- expr_tryfree( p);
- }
- else
- {
- MESS("needs fixup");
- check_fseg( sp, e_pcrel( p) ? S_TDATA : S_SDATA);
- fix_up( p, (imm *) 0, FIX_DCODE);
- IMESS("FIX_DCODE @$%8.8lX", (lword) __p, 4);
- wdeposit( 0);
- }
- l = l->next;
- }
- LEAVE();
- }
-
- static warnflag;
-
- void dropfloat( s)
- char *s;
- {
- extern char page0[];
- int i;
-
- ENTER("dropfloat");
- if( ! warnflag++)
- nwarning("Floats are for losers");
- check_fseg( sp, S_SDATA);
- if( ab_ascin( s))
- nserror("Floating point value malformed", s);
- else
- for( i = 0; i != 6; i++)
- deposit( page0[ 0xD4 + i]);
- LEAVE();
- }
-
-
- void real_setorg( newpc)
- register word newpc;
- {
- ENTER("real_setorg");
- if( sis_unknown( sp)) /* if old *= didn't do anything */
- {
- register byte huge *p = &__program[ sp->index - 4];
-
- __pc = newpc; /* reset START */
- dpoke( p, __pc);
- }
- else
- if( better)
- {
- register word diff;
-
- if( (diff = newpc - __pc) < DS_THRESHOLD)
- {
- check_fseg( sp, S_SDATA);
- advance( diff);
- LEAVE();
- return;
- }
- }
- else
- {
- register byte huge *p = &__program[ sp->index - 2];
-
- dpoke( p, __pc - 1);
- __pc = newpc;
- dpoke( __p, __pc);
- _advance(4);
- build_rseg( S_UNKNOWN, 0);
- }
- LEAVE();
- }
-
-
- void setorg( ex, offset)
- register expr *ex;
- register word offset;
- {
- ENTER("setorg");
- if( runnable)
- if( valued( ex)) /* get rid of switch */
- {
- real_setorg( ex->val + offset);
- expr_tryfree( ex);
- }
- else
- nerror( org_loss);
- else
- nerror("You can't use origins in relocatable code");
- LEAVE();
- }
-
-
- void reserve( ex)
- register expr *ex;
- {
- ENTER("reserve");
- if( valued( ex))
- {
- register word val = ex->val;
-
- if( runnable)
- {
- real_setorg( val + __pc);
- expr_tryfree( ex);
- }
- else
- {
- check_dseg( sp, S_DS, val);
- __pc += val;
- /* advance( val); */
- }
- }
- else
- nerror( ds_loss);
- LEAVE();
- }
-
- static obj_h header;
- #if ! VERSION
- extern char x1[], x2[], x3[], x4[], x5[], x6[];
- #endif
- extern word alignment;
-
- void write_results( fd)
- {
- lword bytes = calc_ind( __p);
- static char err[] = "Write to output file failed (Disk full??)";
-
- ENTER("write_results");
- if( runnable)
- {
- if( Fwrite( fd, bytes, __program) != bytes)
- nferror( err);
- }
- else
- {
- register byte huge *p = (byte *) &header;
- lword max = MAXMODULE,
- ebytes, ibytes, rbytes, sbytes, ybytes, fbytes;
-
- plbyte( p, OBJMAGIC); /* sort of stupid */
- fpdbyte( p, DVERSION);
- fpdbyte( p, ASMREVISION);
- fpdbyte( p, alignment);
- fpdbyte( p, bytes);
- clean_labels();
- if( (sbytes = seg_size()) > max)
- max = sbytes;
- plbyte( p, sbytes);
- if( (ibytes = imm_size()) > max)
- max = ibytes;
- plbyte( p, ibytes);
- if( (rbytes = rel_size()) > max)
- max = rbytes;
- plbyte( p, rbytes);
- if( (ebytes = exp_size()) > max)
- max = ebytes;
- plbyte( p, ebytes);
- if( (ybytes = sym_size()) > max)
- max = ybytes;
- plbyte( p, ybytes);
- if( (fbytes = fix_size()) > max)
- max = fbytes;
- plbyte( p, fbytes);
-
- if( Fwrite( fd, sizeof( obj_h), &header) != sizeof( obj_h) ||
- Fwrite( fd, bytes, __program) != bytes)
- nferror( err);
- if( max != MAXMODULE)
- {
- nfree( (void *) __program);
- __program = nmalloc( max);
- }
- if(
- #if ! VERSION
- Fwrite( fd, 10L, x1) != 10 ||
- #endif
- ( seg_makbuf(), Fwrite( fd, sbytes, __program) != sbytes) ||
- #if ! VERSION
- Fwrite( fd, 10L, x2) != 10 ||
- #endif
- ( ibytes &&
- (imm_makbuf(), Fwrite( fd, ibytes, __program) != ibytes)) ||
- #if ! VERSION
- Fwrite( fd, 10L, x3) != 10 ||
- #endif
- ( rbytes &&
- (rel_makbuf(), Fwrite( fd, rbytes, __program) != rbytes)) ||
- #if ! VERSION
- Fwrite( fd, 10L, x4) != 10 ||
- #endif
- ( ebytes &&
- (exp_makbuf(), Fwrite( fd, ebytes, __program) != ebytes)) ||
- #if ! VERSION
- Fwrite( fd, 10L, x5) != 10 ||
- #endif
- ( ybytes &&
- (sym_makbuf(), Fwrite( fd, ybytes, __program) != ybytes)) ||
- #if ! VERSION
- Fwrite( fd, 10L, x6) != 10 ||
- #endif
- ( fbytes &&
- (fix_makbuf(), Fwrite( fd, fbytes, __program) != fbytes)))
- nferror( err);
- }
- Fclose( fd);
- if( show_open)
- dump_open();
- LEAVE();
- }
-