/* ---------------------------------------------------------------------- */ /* 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 #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(); }