/* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ /* Code that tokenizes and differentiates between MACRO calls and */ /* real life 6502 assembler mnemos. Also tokenizes directives */ #if OS == MSDOS # define _brk xbrk #endif /* These are all the characters that happen to appear in 6502 mnemos */ extern byte _adc[],_and[],_asl[],_bcc[],_bcs[],_beq[],_bit[],_bmi[],_bne[], _bpl[],_bra[],_brk[],_bvc[],_bvs[],_clc[],_cld[],_cli[],_clv[], _cmp[],_cpx[],_cpy[],_dea[],_dec[],_dex[],_dey[],_eor[],_ina[], _inc[],_inx[],_iny[],_jmp[],_jsr[],_lda[],_ldx[],_ldy[],_lsr[], _nop[],_ora[],_pha[],_php[],_phx[],_phy[],_pla[],_plp[],_plx[], _ply[],_rol[],_ror[],_rti[],_rts[],_sbc[],_sec[],_sed[],_sei[], _sta[],_stx[],_sty[],_stz[],_tax[],_tay[],_trb[],_tsb[],_tsx[], _txa[],_txs[],_tya[]; /* -------------------------------------------------------------- */ /* We use the first character of the instruction (or macro call) */ /* to decide on a (struct instr) that happens to keep the remain- */ /* ing two letters. If a match is made, a alphabetically index is */ /* sent over. */ /* [this looked pretty fast in the beginning, but...] */ /* -------------------------------------------------------------- */ #if BIGENDIAN # define drop( b, a) ( ((word) (a) << 8) | (word) (b)) #else # define drop( a, b) ( ((word) (a) << 8) | (word) (b)) #endif #define EOA { 0, 0 } struct instr { word d; byte huge *tab; }; static struct instr a_[] = { { drop('D','C'), _adc }, { drop('N','D'), _and }, { drop('S','L'), _asl }, EOA }, b_[] = { { drop('C','C'), _bcc }, { drop('C','S'), _bcs }, { drop('E','Q'), _beq }, { drop('I','T'), _bit }, { drop('M','I'), _bmi }, { drop('N','E'), _bne }, { drop('P','L'), _bpl }, { drop('R','K'), _brk }, { drop('R','A'), _bra }, { drop('V','C'), _bvc }, { drop('V','S'), _bvs }, EOA }, c_[] = { { drop('L','C'), _clc }, { drop('L','D'), _cld }, { drop('L','I'), _cli }, { drop('L','V'), _clv }, { drop('M','P'), _cmp }, { drop('P','X'), _cpx }, { drop('P','Y'), _cpy }, EOA }, d_[] = { { drop('E','A'), _dea }, { drop('E','C'), _dec }, { drop('E','X'), _dex }, { drop('E','Y'), _dey }, EOA }, e_[] = { { drop('O','R'), _eor }, EOA }, i_[] = { { drop('N','A'), _ina }, { drop('N','C'), _inc }, { drop('N','X'), _inx }, { drop('N','Y'), _iny }, EOA }, j_[] = { { drop('M','P'), _jmp }, { drop('S','R'), _jsr }, EOA }, l_[] = { { drop('D','A'), _lda }, { drop('D','X'), _ldx }, { drop('D','Y'), _ldy }, { drop('S','R'), _lsr }, EOA }, n_[] = { { drop('O','P'), _nop }, EOA }, o_[] = { { drop('R','A'), _ora }, EOA }, p_[] = { { drop('H','A'), _pha }, { drop('H','P'), _php }, { drop('H','X'), _phx }, { drop('H','Y'), _phy }, { drop('L','A'), _pla }, { drop('L','P'), _plp }, { drop('L','X'), _plx }, { drop('L','Y'), _ply }, EOA }, r_[] = { { drop('O','L'), _rol }, { drop('O','R'), _ror }, { drop('T','I'), _rti }, { drop('T','S'), _rts }, EOA }, s_[] = { { drop('B','C'), _sbc }, { drop('E','C'), _sec }, { drop('E','D'), _sed }, { drop('E','I'), _sei }, { drop('T','A'), _sta }, { drop('T','X'), _stx }, { drop('T','Y'), _sty }, { drop('T','Z'), _stz }, EOA }, t_[] = { { drop('A','X'), _tax }, { drop('A','Y'), _tay }, { drop('R','B'), _trb }, { drop('S','B'), _tsb }, { drop('S','X'), _tsx }, { drop('X','A'), _txa }, { drop('X','S'), _txs }, { drop('Y','A'), _tya }, EOA }, *i_arr[] = { (struct instr *) 0, a_, b_, c_, d_, e_, i_, j_, l_, n_, o_, p_, r_, s_, t_ }; /* Indexes for the Instruction_ARRay, note that i_arr[0] = 0 */ static int starters[] = { /* 0 1 2 3 4 5 6 7 8 9 : ? @ */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */ 1,2,3,4,5,0,0,0,6,7,0,8,0,9,10,11,0,12,13,14,0,0,0,0,0,0, /* _ */ 0,0,0,0,0 }; macro_suckin() { register byte *p = (byte *) yytext, c_ = c, *p_table = is_what; register word i = 1; ENTER("macro_suckin"); #if VERSION && FINPUT_IO && QINPUT_IO && QMACRO { register byte huge *pt = bp->p; register byte *tab = _uptable; register lword rem = bp->remain; while( tis_ident( c_)) { *p++ = c_; c_ = quinput( rem, pt, tab); i++; } if( bp) { bp->remain = rem; bp->p = pt; } } #else while( tis_ident(c_)) /* Suck in macro call or */ { /* instruction */ *p++ = c_; /* convert to upper & save */ c_ = uinput(); /* get fresh input */ i++; } #endif *p = 0; c = c_; p = (byte *) yytext; /* (*) */ IMESS("Macro/Instr.: %s", (lword) p, 4); if( i == 4) { register struct instr huge *q; if( q = i_arr[ starters[ *p - '0']]) /* instr ? */ { #if WORD_EVEN p++; c_ = p[1]; /* looks very possible al- */ i = ((word) *p << 8) | c_; /* beit not certain */ #else i = *(word *) &yytext[ 1]; #endif IMESS("two chars together %4lX", (lword) i, 4); do if( i == q->d) { yylval = (lword) q->tab; /* Yup. Send index & token */ LEAVE(); return( T_INSTR); } while( (++q)->d); i = 4; } } yy_txt2val( i); state = AFTERELSE; LEAVE(); return( T_IDENT); /* It's a MACRO call */ } /* -------------------------------------------------------------------- */ /* There are only that few people who use directives often. So here */ /* speed isn't of that much importance. */ /* -------------------------------------------------------------------- */ #define AF AFTERFLOAT #define AI AFTERINCLUDE #define AO AFTEROPTION #undef EOA #define EOA { "", 0, 0 } struct direc { char *string; int token, state; }; static struct direc da_[] = { { "AND", T_AND, 0 }, EOA }, db_[] = { { "BYTE", T_BYTE, 0 }, EOA }, dc_[] = { { "CALL", T_CALL, 0 }, { "CBYTE", T_CBYTE, 0 }, EOA }, dd_[] = { { "DBYTE", T_DBYTE, 0 }, { "DEF", T_DEF, 0 }, { "DS", T_DS, 0 }, EOA }, de_[] = { { "ELSE", T_ELSE, 0 }, { "END", T_END, 0 }, { "ENDIF", T_ENDIF, 0 }, { "ENDM", T_ENDM, 0 }, { "EQU", '=', 0 }, { "ERROR", T_ERROR, 0 }, EOA }, df_[] = { { "FLOAT", T_FLOAT, AF }, EOA }, di_[] = { { "IF", T_IF, 0 }, { "INCLUDE",T_INCLUDE, AI }, EOA }, dl_[] = { { "LOCAL", T_LOCAL, 0 }, EOA }, dm_[] = { { "MACRO", T_MACRO, 0 }, EOA }, dn_[] = { { "NOT", T_NOT, 0 }, EOA }, do_[] = { { "OPT", T_OPT, AO}, { "OR", T_OR, 0 }, { "ORG", T_ORG, 0 }, EOA }, dp_[] = { { "PAGE", T_PAGE, 0 }, EOA }, dr_[] = { { "REF", T_REF, 0 }, { "REPT", T_REPT, 0 }, EOA }, ds_[] = { { "SBYTE", T_SBYTE, 0 }, { "SET", T_SET, 0 }, EOA }, dt_[] = { { "TAB", T_TAB, 0 }, { "TITLE", T_TITLE, 0 }, EOA }, du_[] = { { "UNDEF", T_UNDEF, 0 }, EOA }, dv_[] = { { "VFL_BOCHUM", T_ZEXT, 0},EOA }, dw_[] = { { "WARNING", T_WARN, 0 }, { "WORD", T_WORD, 0 }, EOA }, dz_[] = { { "ZEXT", T_ZEXT, 0 }, EOA }, *d_arr[] = { (struct direc *) 0, da_, db_, dc_, dd_, de_, df_, di_, dl_, dm_, dn_, do_, dp_, dr_, ds_, dt_, du_, dv_, dw_, dz_ }; /* Indexes for the Instruction_ARRay, note that i_arr[0] = 0 */ static int dstarters[] = { /* 0 1 2 3 4 5 6 7 8 9 : ? @ */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */ 1,2,3,4,5,6,0,0,7,0,0,8,9,10,11,12,0,13,14,15,16,17,18,0,0,19, /* _ */ 0,0,0,0,0 }; directive_suckin() { register char *p = yytext, c_ = c, *p_table = (char *) is_what; ENTER("directive_suckin"); if( (c_ = uinput()) == '=') /* is .= ?? */ fdreturn( T_DOTEQ); *p++ = '.'; #if VERSION && FINPUT_IO && QINPUT_IO && QDIRECT { register byte huge *pt = bp->p; registe byte *tab = _uptable; register lword rem = bp->remain; do *p++ = c_; while( tis_ident( c_ = quinput( rem, pt, tab))); if( bp) { bp->remain = rem; bp->p = pt; } } #else do *p++ = c_; /* convert to upper & save */ while( tis_ident(c_ = uinput())); #endif c = c_; *p = 0; p = yytext + 1; { register struct direc *q; if( q = d_arr[ dstarters[ *p - '0']]) /* get directive start */ do if( ! strcmp( q->string, p)) { if( q->state) state = q->state; dreturn( q->token); } while( (++q)->string); } lsyntax("unknown directive"); } struct opt { char *name; int token; }; static struct opt options[] = { { "NO", T_NO }, { "OBJ", T_OBJ }, { "LIST", T_LIST }, { "MLIST", T_MLIST }, { "CLIST", T_CLIST }, { "EJECT", T_EJECT }, { "ERR", T_ERR }, { "NUM", T_NUM }, { "XREF", T_XREF }, { "", 0 } }; option_suckin() { register struct opt huge *q = options; register char *p = yytext; while( is_letter(c)) { *p++ = c; c = uinput(); } *p = 0; while( q->token) { if( ! strcmp( yytext, q->name)) return( q->token); q++; } lsyntax("unknown option"); } /* (*) Turbo-C very cleverly (no irony this time) compiles the "-'0'" as a negative offset for the LEA. Therefore this isn't wasting any time at least on the ST. Else a 256 word array would be better */