/*============================================================================================================================================================================*/
#define  out_device TRACEfp
#define  DEBUG
/*===========================================================================================================================================================================
#define  out_device stdout
#define  out_device OU
                C8051F320  Disassembler
                Embedded Systems Lab. / Honam University  1999-2008.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

#include        <stdio.h>
#include        <dos.h>
#include        <ctype.h>
#include        <string.h>
#include        <alloc.h>
#include        "D51.H"
#include        "F320.TBL"                                                                      // Get Global Tables 
#include        "OPCODE.TBL"

#define         EITHERFILE      0
#define         HEXFILE         1
#define         BINFILE         2


struct  sym     *ptr;

byte  _ATTB;
word            maxRAM=0x800;
byte            view_binBUF=1;
byte            view_binFLG=1;
int             HEXflag  = 0;                                                                   // Append HEX Flag             
byte            ASCII_flag=1;                                                                   // Use ASCII string flag        
word            _PC, _EA;

char            string_buf[20+64];

int             ocnt=0;
char            i51cfg_fname[]= {"i51.CFG"};
char            debug_fname[] = {"DEBUG.DBG"};
char            trace_fname[] = {"TRACE.CAP"};
char            dump_fname[]  = {"DUMP.MEM"};
char            symbol_fname[]= {"SYMBOL.TBL"};
char            label_fname[] = {"LABEL.TBL"};
FILE            *IN;
FILE            *DEBfp, *i51CFG, *SYMfp, *LBLfp, *DMPfp, *TRACEfp;
char            cfgf[32];

struct  sym     *nptr, *tbl_ptr;
struct  sym     *xptr;
struct  sym     *sptr;
struct  sym     *_ptr;

SYM_PTR  *xTBL;
SYM_PTR  *sTBL;
SYM_PTR *Symbol_vIDX0;                                                                          // Array of pointers            
SYM_PTR *Label_vIDX0;

int             fileflag = 2;                                                                   // File type Flag  .BIN .HEX 0  

byte            far *_binBUF;                                                                   // Program Data Pointer         
byte            far *_binFLG;                                                                   // Pointer to program flags     



void            putHEX(word j);
void            putHEX2(word j);

/*============================================================================================================================================================================================================== ===============================
                                                D51P1.C
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------*/
                                C8051F320  Disassembler

                Embedded Systems Lab. / Honam University  1997-2008.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*
#include        <stdio.h>
#include        <dos.h>
#include        <ctype.h>
#include        <alloc.h>
#include        <string.h>
#include        "D51.H"

#define         SYMBOL  0
#define         LABEL   1

/*============================================================================================================================================================================
                Prototypes
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

char            *get_adrs(char *text, word *val);
void            dump_ASCII(word adrs);
void            dump_bytes(word adrs);

struct  sym     *sort(struct sym *list, SYM_PTR *array, word count);
struct  sym     *sort_by_name (struct sym *list);
struct  sym     *sort_by_value(struct sym *list);
struct  sym     *merge_by_name (struct sym *a, struct sym *b);
struct  sym     *merge_by_value(struct sym *a, struct sym *b);
void            chk_dup_name (struct sym *list, word count);
void            chk_dup_value(struct sym *list, word count);

#if     0
extern  char    *_find_Entry(word val, struct sym *ptr);
#else
extern  char    *_find_Entry(word val, word count, SYM_PTR *_LS_TBL);
#endif

extern  void    _add_Entry(word val, char *symbol, int type);

#ifdef  DEBUG
void            dump__binFLG(void);

extern  void    dump_SYMBOL(void);
extern  void    dump_LABEL(void);
#endif

/*============================================================================================================================================================================
        Global Variables
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

SYM_PTR *Symbol_vIDX;                                           // Array of pointers         
SYM_PTR *Label_vIDX;                                            // for binary search         
struct sym      *tail_ptr, *head_ptr;                           // Sort pointers             

extern FILE   *fp;                                              // DOS file struct           
extern int    HEXflag;                                          // Append HEX flag           
extern int    kcnt;                                             // Output char counter       
extern word   _maxBIN;                                          // Highest data adrs         
extern word   offset;                                           // Program offset            
extern byte   far *_binBUF;                                     // Program data pointer      
extern byte   far *_binFLG;                                     // Pointer to program flags  
extern char   string[ASCLIMIT];                                 // ASCII data for defb       
extern word   asccount;                                         // Count for string data     
extern word   byte_cnt;                                         // Count for byte binary data
extern byte   dump;                                             // Dump just done flag       
extern char   DBstr[8];                                         // String for defined bytes  
extern char   ASCstr[8];                                        // String for defined ASCII  
extern byte   optTBL[256];                                      // Code option bit flags     
extern char   ctl[32];                                          // Control file name         
extern char   _lineBUF[128];                                    // Input line buffer         
// ern struct sfrent SFR[256];  SFR names                      
/*extern struct sfrent SFRbits[128];                            // SFR bit names             
/*extern struct sfrent RB_name[32];                             // Register bank names       
extern struct sym       *Symbol_TBL;                            // Symbol table pointer      
extern struct sym       *Label_TBL;                             // Label table pointer       
extern struct sym       *Symbol_TBL_last;                       // Last symbol table pointer 
extern struct sym       *Label_TBL_last;                        // Last label table pointer  
extern word   symbol_count;                                     // Number of symbols         
extern word   label_count;                                      // Number of labels          


/*============================================================================================================================================================================
      Output Hexadecimal Operand                                 ----
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
static char stringBUF[8 + 1] = { '0', };

char *__uINT2Binary(unsigned int i) {
int  count = 8;

        do { stringBUF[--count] = '0' + (char)(i & 1);  i = i >> 1;}
        while (count);
        return stringBUF;
}
/*============================================================================================================================================================================
        Put Binary
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void putBIN(byte j){

        __uINT2Binary( j & 0xFF ); kcnt +=  fprintf(fp,"%sB", stringBUF);
        }

/*============================================================================================================================================================================
        Put Binary [device]
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void _putBIN(byte j){

        __uINT2Binary( j & 0xFF ); kcnt +=  fprintf(out_device,"%s", stringBUF);
        }


/*============================================================================================================================================================================
        E N T R Y - P O S T
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void post_label(){
word index;
word val;
                if (label_count || symbol_count){                                                              // Set up Tail Node for Sort
                        tail_ptr = (struct sym *) malloc(sizeof(struct sym) + 12);
                        tail_ptr->next = tail_ptr;
                        tail_ptr->label[0] = 0xFE;                                                         // Set Max Values for sort
                        tail_ptr->label[1] = 0;
                        tail_ptr->adrs = 0xFFFF;
                }
                if (label_count){                                                                              // If Labels Encountered...
                        Label_TBL_last->next = tail_ptr;                                                   // Set up Pointer array for Sort
                        Label_vIDX = malloc(sizeof(SYM_PTR)   *label_count);
                        if ( Label_vIDX == NULL){ printf("\nI N T E R N A L   E R R O R ! - No Memory for Label Pointers"); exit(MEM_ERROR);}

                        fprintf(LBLfp, "\n---- Unsorted Label Table ------------------------------?n");
                        fprintf(LBLfp, "\n T  SEQ adrs cnt CL Label\n");
                        _ptr=Label_TBL;
                        for (index=0; index<label_count; index++){
                             fprintf (LBLfp, "\n L %4d  %04X%4d %c %s", index, _ptr->adrs, _ptr->count, _ptr->attb, _ptr->label);
                             _ptr = _ptr->next;
                        }
                        fprintf(LBLfp, "\n\n - %dGlobal Labels\n", label_count);
                        fprintf(LBLfp, "\n========================================================\n");
                                        Label_TBL = sort(Label_TBL, Label_vIDX, label_count);

                        fprintf(LBLfp, "\n---- Sorted Label Table --------------------------------?n");
                        printf( "\n Sorting      Label Table\n");
                        _ptr=Label_TBL;
                        for (index=0; index<label_count; index++){
                             fprintf (LBLfp, "\n L %4d  %04X%4d %c %s", index, _ptr->adrs, _ptr->count, _ptr->attb, _ptr->label);
                             _ptr = _ptr->next;
                        }
                        fprintf(LBLfp, "\n\n - %dGlobal Labels\n", label_count);
                        fprintf(LBLfp, "\n========================================================\n");


                }
                if (symbol_count){                                                                               // If symbols encountered...
                        Symbol_TBL_last->next = tail_ptr;
                        Symbol_vIDX = malloc(sizeof(SYM_PTR)   *symbol_count);
                        if (Symbol_vIDX == NULL){ printf("\n I N T E R N A L   E R R O R ! - No Memory for Symbol Pointers"); exit(MEM_ERROR);}
                        fprintf(LBLfp, "\n== Unsorted Symbol Table =============================\n");
                        _ptr=Symbol_TBL;
                        for (index=0; index<symbol_count; index++){
                             fprintf (LBLfp, "\n   %4d  %04X%4d %c %s", index, _ptr->adrs, _ptr->count, _ptr->attb, _ptr->label);
                             _ptr = _ptr->next;
                        }
                        fprintf(LBLfp, "\n\n - %d Symbols\n", symbol_count);
                        fprintf(LBLfp, "\n========================================================\n");


                                        Symbol_TBL = sort(Symbol_TBL, Symbol_vIDX, symbol_count);

                        fprintf(LBLfp, "\n== Sorted Symbol Table ================================\n");
                        printf( "\n Sorting     Symbol Table\n");
                        _ptr=Symbol_TBL;
                        for (index=0; index<symbol_count; index++){
                             fprintf (LBLfp, "\n   %4d  %04X%4d %c %s", index, _ptr->adrs, _ptr->count, _ptr->attb, _ptr->label);
                             _ptr = _ptr->next;
                        }
                        fprintf(LBLfp, "\n\n - %d Symbols\n", symbol_count);
                        fprintf(LBLfp, "\n========================================================\n");
                }
        }


/*===============  P A S S - 0  ==================================================================================================

        Read Control File, if it exists, and Flag Areas as Code, Text, or whatever.
        Also handle SFR Name changes, Labels, etc.

----------------------------------------------------------------------------------------------------------------------------------*/

void pass_0(void)
{
        char    *text, func, c, *ltext;
        word    start, stop, code, temp;
        int     i;

        fp = fopen(ctl, "r");
        if (fp != NULL){                                                                                       // If control file exists...
                printf("\nReading Control File");
                while (!feof(fp)){                                                                             // Until end of file...
                        start = stop = 0;
                        *_lineBUF = '\0';                                                                      // Clear previous line
                        fgets(_lineBUF, 127, fp);                                                              // Read one line
                        text = &_lineBUF[1];
                        text = get_adrs(text, &start);
                        while (1){
                                c = *text++;
                                if (c != ' ' && c != '\t' ) break;                                             // Skip whitespace
                        }
                        if (c == '\n' || c == ';' ) --text;                                                    // If only one numeric...
                                                                                                               // Back up to newline
                        func = c;                                                                              // Save operator
                        ltext = text;
                        --ltext;
                        text = get_adrs(text, &stop);
                        if (func == '+')         stop += (start - 1);                                          // Check for valid operator
                        else if (func == '-' && !stop) stop = start;


_ATTB=(byte)toupper(_lineBUF[0]);
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                        switch (toupper(_lineBUF[0])){

                                case 'A':
                                        while(1){ c = *text;
                                                if (c != ' ' && c != '\t' ) break;                             // Skip whitespace
                                                text++;
                                        }
                                        if (c == '\n' || c == ';') --text;                                     // If only one numeric...
                                        else {_add_Entry(start, text, LABEL);}

                                        do{   code = ((word) _binBUF[start]) << 8;                     // Address
                                                temp = _binBUF[start + 1] & 0xFF;                              // Get Address to Reference
                                                code |= temp;
                                                _binFLG[code] |= bF_REF;                                       // Flag referenced address
                                                _binFLG[code] &= ~(bF_CLREF | bF_SPLIT);
                                                _binFLG[start++] = bF_ADRS;                                    // Set branch flags
                                                _binFLG[start]   = bF_ADRS;                                    // to address code
                                                start++;
                                        } while (start < stop); break;

                                case 'B':
                                        while (1){
                                                c = *text;
                                                if (c != ' ' && c != '\t' ) break;                             // Skip whitespace
                                                text++;
                                        }
                                        if (c == '\n' || c == ';') --text;                                     // If only one Numeric...
                                        else {_add_Entry(start, text, LABEL);}

                                        do{   _binFLG[start] |=  (bF_BYTE );
                                              _binFLG[start] &= ~(bF_NOINIT | bF_ADRS | bF_WORD | bF_ASCII | bF_SPLIT);
                                               start++;                                                                                                                 // chronous
                                         } while (start <= stop); break;

                                case 'C':  code = start;                                                        // Code
                                        do{
                                                if (_binFLG[start] == bF_INIT) _binFLG[start]  |=  bF_CLREF;    // Flag as Valid Code Data chronous
                                                else                           _binFLG[start] &= ~bF_NOINIT;
                                                start++;
                                        } while (start <= stop); break;

                                case 'D': /*--------------------------------------------*/                      // Data
                                      /*_binFLG[start] |= bF_REF;
                                        _binFLG[start] &= ~(bF_CLREF | bF_SPLIT);*/
                                                                                                                // fprintf (TRACEfp, "\n  %4d    -> %s  ",symbol_count, ltext); 
 _ATTB='X';
                                        if (isalnum(*ltext)) _add_Entry(start, ltext, SYMBOL);
                                        break;


                                case 'F': if (start < 0x80 || start > 0xFF){                            // Modify SFR name
                                                printf("\rInvalid SFR address: 0x%X in '%s'\n",
                                                _lineBUF[0], _lineBUF);
                                        }else{
                                                for (stop=0; stop<7; stop++){                               // Transfer new name
                                                        func = *ltext++;
                                                        if (isalnum(func)) SFR[start].dent[stop] = func;
                                                        else{              SFR[start].dent[stop] = '\0'; break;}// Terminate name
                                                }
                                        }
                                        if (stop >= 7)                 SFR[start].dent[7] = '\0'; break;


                                case 'I': do{   _binFLG[start] = bF_INIT; start++; }                            // Ignore initialized data
                                          while (start <= stop); break;

                                case 'K': if (start < 0x80 || start > 0xFF){                            // Modify SFR bit name
                                                printf("\rInvalid SFR bit address: 0x%X in '%s'\n",
                                                _lineBUF[0], _lineBUF);
                                        }else{
                                                for (stop=0; stop<7; stop++){                               // Transfer Name
                                                        func = *ltext++;
                                                        if (isalnum(func))
                                                                SFRbits[start].dent[stop] = func;
                                                        else{   SFRbits[start].dent[stop] = '\0'; break;}
                                                }
                                        }
                                        if (stop >= 7) SFRbits[start].dent[7] = '\0'; break;                // Null terminate name


                                case 'L':                                                                       // LABEL
                                          _binFLG[start] |= bF_REF;                                             // Flag Reference 
                                          _binFLG[start] &= ~(bF_CLREF | bF_SPLIT);                             // --- ++++
                                        if (isalnum(*ltext)) _add_Entry(start, ltext, LABEL);
                                        break;

                                case 'R':                                                                       // Modify Register name
                                        if (start > 31){
                                                printf("\rInvalid Register Address: 0x%X in '%s'\n",
                                                _lineBUF[0], _lineBUF);
                                        }else{
                                                for (stop=0; stop<7; stop++){                               // Transfer register name
                                                        func = *ltext++;
                                                        if (isalnum(func))
                                                                RB_name[start].dent[stop] = func;
                                                        else{   RB_name[start].dent[stop] = '\0'; break; }
                                                }
                                        }
                                        if (stop >= 7) RB_name[start].dent[7] = '\0';                       // Null terminate reg name
                                        break;

                                case 'S': _add_Entry(start, ltext, SYMBOL); break;                              // Symbol

                                case 'T': do{  _binFLG[start] |= bF_ASCII; start++;}                            // Text chronous
                                          while (start <= stop); break;

                                case 'W': do{                                                                   // Word binary
                                                _binFLG[start] |= bF_WORD;
                                                start++;       start++;  // chronous
                                          } while (start <= stop); break;


                                case '#':                                                                       // Word binary
                                case 0x00:                                                                      // Ignore empty lines
                                case '\n':
                                case '\r':
                                case '\t':
                                case ' ':
                                case ';':                                                                       // Ignore commented out lines
                                        _ATTB=' ';
                                        break;

                                default: printf("\rUnknown Control Code: 0x%02X in '%s'\n", _lineBUF[0], _lineBUF); _ATTB=' ';break;
                        }
                }
        }
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

/*        dump_LABEL();
          dump_SYMBOL();*/

        printf("\n\nPass-0 Reference Generation Complete\n");
}

#include        "SORT.INC"
/*============================================================================================================================================================================
                Check for Redefinitions of Label/ Symbol Names  >>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void chk_dup_name(struct sym *list, word count){
        word    i;
        printf("\n Searching... Label  Address [ %d ]",count);
        for (i=0; i<count; i++){
                if (!stricmp(list->label, list->next->label)){
                        printf("\n - redefine : %s  %04X ", list->label, list->adrs);
                }list = list->next;
        }
}
/*============================================================================================================================================================================
                Check for Redefinitions of Values  >>> BUG
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void chk_dup_value(struct sym *list, word count){
word    i;
        printf("\n Searching... Value  Address [ %d ]",count);
        for (i=0; i<count; i++){
                if (list->adrs == list->next->adrs){
                        printf("\n%4d Redefinition Value %04X [ %s ]", i, list->adrs, list->label);
                }
                list = list->next;
        }
}
/*============================================================================================================================================================================
                Get Hexadecimal Number from Line in Control File.
                Return : Updated Character Pointer.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
char *get_adrs(char *text, word *val){

word    result, start;
char    c;

        result = start = 0;
        while (c = toupper(*text)){
                if (c == ';')  break;                            // Beginning of Comment, Ignore all else
                if (c == '\n') break;                            // Necessary because isspace() includes \n
                if (isspace(c)){
                        text++;
                        if (start) break;                        // If result already begun...
                }
                else
                if (!isxdigit(c)) break;                         // Done if not Hexadecimal character
                else {
                        start = 1;                               // Flag beginning of result conversion
                        c = (c>'9') ? c-0x37 : c-0x30;
                        result <<= 4;
                        result |= ((word) c&0xF);
                        text++;
                }
        }
        *val = result;                                           // Pass number back to caller
        return(text);                                            // And return updated text pointer
}

/*===============  P A S S - 1  ==================================================================================================

        Pass-1 of Disassembly. Examine Opcodes for Internal References to other Memory Locations.
        If such References are Found, Flag the Referenced Location so that a Label can be Generated in the Output File during Pass-2.

        [  Make Label :  Reference Search }
----------------------------------------------------------------------------------------------------------------------------------*/
void pass_1(void){

word    rel, q, uu;
byte    jx, k, mask, dir;
char    *inp;
int     line;
word    xx, temp;

        printf("Pass-1 0000H");
        for (_PC=offset; _PC<_maxBIN;){
                jx= _PC & 0xFF;
                k = _binBUF[_PC];                                                                  // Get Stored Opcode
                if (_binFLG[_PC] & bF_NOINIT) _PC++;                                               // Ignore Un-initialized Data
                else if ( !(_binFLG[_PC] & (bF_ADRS | bF_WORD | bF_BYTE | bF_ASCII))){
                        mask = (byte) (bF_CLREF | bF_SPLIT); jx = OPcode_TBL[k]._mod;              // if Code... , get Option Byte

_ATTB=OPcode_TBL[_binBUF[_PC]].bx;                                                                 //   printf("\n%d \t%s\t%04X",symbol_count,  string_buf,  dir );
                        if ((jx & EA_MASK) == EA_LREF){                                            // [ LJMP, LCALL,  MOV DPTR  ]
                                _EA = ((_binBUF[_PC+1] & 0xFF) << 8) | (_binBUF[_PC+2] & 0xFF);

                                if(_binBUF[_PC] ==0x90 & _EA <maxRAM ){                        // DPTR Address
                                         sprintf(string_buf, "DT_%04X", _EA );
                                         _add_Entry( _EA, string_buf, SYMBOL);
                                }else{

                                if (_EA >= offset && _EA <= _maxBIN) mask |= bF_NOINIT;
                                _binFLG[_EA] = _binFLG[_EA] & ~mask | bF_REF;
                                         sprintf(string_buf, "_%04X", _EA );
                                         _add_Entry( _EA, string_buf, LABEL);
                                }
                        }
                        /*--------------------------------------------------------------------------------------*/
                        if (jx & EA_11){                                                           // [ AJMP & ACALL] 11 bit Address
                                _EA = (_PC & 0xF800) | ((k & 0xE0) << 3) | (_binBUF[_PC+1] & 0xFF);
                                 if (_EA >= offset && _EA <= _maxBIN) mask |= bF_NOINIT;
                                _binFLG[_EA] = _binFLG[_EA] & ~mask | bF_REF;

                                sprintf(string_buf,"_%04X", _EA);                                  // ACALL D1 "__" +++ chronous
                                _add_Entry( _EA, string_buf, LABEL);
                                _binFLG[_PC] |=  bF_REF;
                        }
                        /*-------------------------------------------------------------------------------------*/
                        if (jx & EA_DIR2){  /*RAM_ Bitif (jx & EA_DIR)

                                dir = _binBUF[_PC+1];
                                dir &= 0xFF;
                                if      (dir < 0x20){ }
                                else if (dir < 0x80){
                                        sprintf(string_buf, "RAM_%02XH", dir );
_ATTB='m';                                                                                                                                                                                                              //   printf("\n%d \t%s\t%04X",symbol_count,  string_buf,  dir );
                                        _add_Entry( dir, string_buf,  SYMBOL);
                               }
                        }
                        /*-------------------------------------------------------------------------------------*/

                        if (jx & EA_REL){                                                         // Relative Reference     
                            if(_binBUF[_PC+2] !=0xFD){                                            // $ Currrent PC  
                                if (jx & EA_3){                                                   // REL 3 
                                        jx  = _binBUF[_PC+2];
                                        rel = (jx > 0x7F) ? jx | 0xFF00 : jx & 0xFF;
                                        _EA = _PC + 3;
                                }else{                                                            // REL 2 
                                        jx  = _binBUF[_PC+1];
                                        rel = (jx > 0x7F) ? jx | 0xFF00 : jx & 0xFF;
                                        _EA = _PC + 2;
                                }
                                _EA += rel;
                                if (_EA >= offset && _EA <= _maxBIN) mask |= bF_NOINIT;
                                _binFLG[_EA] = _binFLG[_EA] & ~mask | bF_REF;
                            }
                        }
                        _PC = _PC + (OPcode_TBL[k]._mod & EA_SIZE) + 1;                           // Update Location Pointer
                }
                else    _PC++;                                                                    // Not Code
        }

        post_label();  /*move here chronous


#ifdef  DEBUG2  /*------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        dump_LABEL();
        dump_SYMBOL();
        dump__binFLG();
#endif
        fprintf(out_device, "\n;===============================================================================================================================================");
        fprintf(out_device, "\rPass-1 Reference Search Complete\n");
        fprintf(out_device, "\nProcedure  : [ Key  ] adrs  Label");

        printf("\n\rPass-1 Reference Search Complete");
}                                                                                                  // End of Pass 1

/*============================================================================================================================================================================
               Output ASCII Data Accumulated in Buffer
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
word adrs;
void dump_ASCII(word adrs)
{
        word    padrs, off, cnt, k;
        char    *cptr;

        padrs = adrs - asccount;                                                                   // Print address for comment field
        adrs  = padrs;                                                                             // Address in program array
        cnt   = off = 0;                                                                           // Cnt = char count, off = buffer offset
        while (asccount)                                                                           // While data in ASCII buffer...
        {
                if (_binFLG[adrs] & bF_REF){                                                       // If addresss is referenced...
                        if (cnt){
                                putc('\'', fp); kcnt++;                                            // Terminate line
                                if (HEXflag){                                                      // If comment field requested...
                                        do { putc('\t', fp); kcnt = (kcnt + 8) & 0x78;}            // Show HEX address
                                        while (kcnt < xstop);
                                        kcnt =fprintf(fp, ";< %04X", padrs) &0xF8;
                                }                                                                  // Update print address, Clear char count for this line
                                padrs += cnt; cnt = 0;
                        }
                        cptr = _find_Entry(adrs, label_count, Label_vIDX);

                        if (cptr == NULL) kcnt =fprintf(fp, "\nx%04X:", adrs)&0xF8;
                        else              kcnt =fprintf(fp, "\n%s:",    cptr)&0xF8;
                        do { kcnt+= putc('\t',fp);} while(kcnt < 16);
                        kcnt +=fprintf(fp, "%s\t'",  ASCstr);

                }else if (!cnt){

                        fprintf(fp, "\n"); kcnt=0;
                do{ putc('\t', fp); kcnt = (kcnt + 8) & 0x78;} while (kcnt < 16);
                                                                                                   // fprintf(fp, "[%d]",  kcnt);
                        kcnt+=fprintf(fp, "%s\t'", ASCstr);                                        // chronous 'c'
                }

                                                                                                   /* kcnt +=*/ putc(string[off], fp);   // Output data in ASCII
                putc('\'', fp);
                kcnt = (kcnt+7) &0xF8;

                                                                                                   // fprintf(fp, "[%d]",  kcnt);
                cnt++;                                                                             // Increment char in this line
                off++;                                                                             // Increment offset into ascii buffer
                adrs++;                                                                            // Offset into program memory
                if (cnt >= ASCLINE){                                                           // If max characters per line...
                        kcnt +=putc('\'', fp);               // kcnt++;                            // Terminate line

                        if (HEXflag){                                                              // If Comment Field requested
                                do{ putc('\t', fp); kcnt = (kcnt+8) & 0xF8;} while (kcnt<xstop);// Show HEX Address
                                kcnt +=fprintf(fp, "; %04X", padrs);
                        }
                        padrs += cnt;                                                              // Update Print Address
                        cnt = 0;
                }
                --asccount;
        }
                                                                                                   // if (HEXflag && cnt),   If Comment Field Requested...
        {
                do{ putc('\t', fp); kcnt = (kcnt+8) & 0xF8;} while (kcnt < xstop);             // Show HEX Address
                fprintf(fp, "; %04X ", padrs);                                                     // HEX Address

/*fprintf(fp, "<[%d]",  kcnt);*/
        for (k=0; k<off; k++)
             putc(ASCII(_binBUF[padrs + k]), fp);
        }
        dump = 1;
}

/*============================================================================================================================================================================
                Output Binary Data Accumulated in Buffer
                Define Byte Processing
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void dump_bytes(word adrs){
word    padrs, bcnt, off, k;
char    *cptr;

        padrs = adrs - byte_cnt;                                                                   // Compute adrs to print in ASCII part
        adrs = padrs;
        bcnt = off = 0;                                                                            // No Bytes output yet           

        while (byte_cnt){                                                                          // While Data in binary buffer...
                if (_binFLG[adrs] & bF_REF){                                                       // If data adrs is referenced... 
                        if (off && HEXflag){                                                       // Dump any Remaining ASCII first
                                do{ putc('\t', fp);  kcnt = (kcnt + 8) & 0xF8; } while (kcnt < xstop);
                                fprintf(fp, "; +>%04X ", padrs);
                                for (k=0; k<off; k++)  putc(ASCII(_binBUF[padrs + k]), fp);
                                padrs += k;                                                         // Update Print Address
                                off = 0;
                        }
                        cptr = _find_Entry(adrs, label_count, Label_vIDX);                          // Then do a Label
                        kcnt=-1;
                        if (cptr == NULL)  kcnt+=fprintf(fp, "\nx%04X:", adrs);
                        else               kcnt+=fprintf(fp, "\n%s:"   , cptr);
                        do{ putc('\t', fp);  kcnt=(kcnt+8) & 0xF8;} while(kcnt<16);
                        kcnt +=fprintf(fp, "%s", DBstr);
                        do{ putc('\t', fp);  kcnt=(kcnt+8) & 0xF8;} while(kcnt<24);
                        bcnt = 0;
                }

                else if (!bcnt){
/*-----------------------------------------------------------------------------------*/
                        fprintf (fp, "\n");  kcnt=0;
                        do{ putc('\t', fp);  kcnt=(kcnt+8) & 0xF8; } while(kcnt<16);
                        kcnt+=8; fprintf(fp, "%s\t", DBstr);
                        }
                else{   putc(',', fp); kcnt++; }                                                    // Else Separate Bytes
/*-----------------------------------------------------------------------------------*/
                putHEX(_binBUF[adrs]);
                bcnt++;

                if (bcnt >= BYTELINE){                                                          // If Max Bytes Per Line...
                        bcnt = 0;
                        do{ putc('\t', fp);  kcnt = (kcnt+8) & 0xF8;} while(kcnt < xstop);
                        {       // Do ASCII Dump of Previous Bytes
                                for (k=0; k<BYTELINE; k++) if (HEXflag)  putc(ASCII(_binBUF[padrs + k]), fp);
                                padrs += k;
                                off = 0;
                        }
                                                                                                    //  fprintf(fp, "[%d]",  kcnt);
                }else   off++;
                --byte_cnt;
                adrs++;
                                                                                                    // KCnt+=fprintf(fp, "[%d]",  kcnt);
                }
                { do{  putc('\t', fp); kcnt = (kcnt + 8) & 0xF8;}  while (kcnt < xstop);
                fprintf(fp, "; %04X", padrs);}                                                      // Show Address and ASCII for data
        dump = 1;
        }

/*============================================================================================================================================================================

                                                D51P2.C

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*
#include        <stdio.h>
#include        <dos.h>
#include        <ctype.h>
#include        <alloc.h>
#include        <errno.h>
#include        "D51.H"
/*#include      "MSG.TBL"*/
/*#include      "opcode.TBL"*/

/*============================================================================================================================================================================

     Prototypes

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

/*============================================================================================================================================================================
      Separator print
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void sp_print(void){
              fprintf(fp, "\n;=============================================\n");
              fprintf(fp, "\n;----------------------------------------------");
}

void sjmp_print(void){
              fprintf(fp, "\n;----------------------------------------------");
}

/*
void    pass_2(void);
void    pass_3(void);
void    process_OPcode(char *mnem);
void    do_DIRECT(FILE *fp, word dir);
void    do_BIT(FILE *fp, word bit);
void    check_REF(word i);
void    splitcheck(int i);
/*void    putHEX(word j);*/

int     ASCII(int i);
int     is_ASCII(byte data);

extern char     *_find_Entry(word val, word count, SYM_PTR *_LS_TBL);
extern void     dump_ASCII(word adrs);
extern void     dump_bytes(word adrs);

#ifdef  DEBUG /*------------------------------------------------------------------------------------------------------------------------------------------------------------*/

extern void     dump_SYMBOL(void);
extern void     dump_LABEL(void);

#endif

/*==========================================================================================================================================================================

       Global variables

 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

int     newline;                                         // Just Output newline Flag    

extern  char     src[32], dst[32], cfgf[32];             // File name Buffers           
extern  struct   date     date;                          // Disassembly date            
extern  struct   time     time;                          // Disassembly time            
extern  FILE     *fp;                                    // Dos file struct             
extern  int      HEXflag;                                // Append HEX flag             
extern  int      kcnt;                                   // Output char counter         
extern  word     _maxBIN;                                // Highest data adrs           
extern  word     offset;                                 // Program offset              
extern  byte     far *_binBUF;                           // Program data pointer        
extern  byte     far *_binFLG;                           // Pointer to program flags    
extern  char     string[ASCLIMIT];                       // ASCII data for defb         
extern  word     asccount;                               // Count for string data       
extern  byte     byte_data[BYTELIMIT];                   // Binary data for defb        
extern  word     byte_cnt;                               // Count for binary data       
extern  byte     dump;                                   // Dump just done flag         
extern  byte     ASCII_flag;                             // Use ASCII string flag       
extern  char     DBstr[8];                               // String for defined bytes    
extern  char     DWstr[8];                               // String for defined words    
extern  byte     dirregs[32];                            // Access flags for dir reg    
extern  word     symbol_count;                           // Number of symbols           
extern  word     label_count;                            // Number of labels            
extern  SYM_PTR  *Symbol_vIDX;                           // Symbol table pointer array  
extern  SYM_PTR  *Label_vIDX;                            // Label table pointer array   

/*extern  struct mnementry mnemtbl[256];*/
extern  byte     optTBL[256];
/*tern  struct sfrent SFR[256];*/
/*extern  struct sfrent SFRbits[128];*/
/*extern  struct sfrent RB_name[32]; 

byte    jj;
byte    _OP;


char post_flg  =       0;
int post_code  =       0;
char    comment_buf[160];


/*===============  P A S S - 2  ===============================================================================================================================================

  Pass two of disassembly. Rescan data array & generate output file.
  Generate label if location flagged as referenced by some other opcode.

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
word    ip;
void pass_2(void){
        char    c, *cptr;
        int     skip = 1;
        word    l, pc, q, temp, rn;

        _OP = 0;
        jj= 0xFF;
        dump = 0;
        byte_cnt =0;
        asccount = 0;
        newline  = 0;

        printf("\nPass-2 0000");

        if ((fp = fopen(dst, "w")) == NULL){                        // Open Output Source File
                printf("\n* Can't open file %s *\n",  dst);
                exit(FILE_ERROR);
        }
        fprintf(fp, "$include \t(KEIL.CFG)"
                    "\n\r; C8051F320  Disassembler V%d.%d"
                    "\n; (c)Honam University  Dept. of Computer Engineering 1997-2008.\n",  verno, revno);
        fprintf(fp, "\n; %s -> %s",  src, dst);					// Output Header
        getdate(&date);
        gettime(&time);
        fprintf(fp, "\n; Disassembled date : %d/%d/%d %d:%02d chronous", date.da_year, date.da_mon, date.da_day, time.ti_hour, time.ti_min);

//      fprintf(fp, "\#include  F320.inc\n");
        fprintf(fp, "\n\n$include\t(F320.INC)\n");
        fprintf(fp, "\nBus_A\t\tEQU\tP1");
        fprintf(fp, "\nBus_B\t\tEQU\tP0");

//      fprintf(fp,     "$include\t(RAM.DEF)\n"); 
        if (ASCII_flag){											// If user specified A on Command Line...
                fprintf(fp, "\n\nASCII\t\macro\tx");				// Generate Macro for Text
                fprintf(fp, "\n\t\t%s\t'\#x\#'", DBstr);
                fprintf(fp, "\n\t\tendm");
        }

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
;        O R G
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//  Generate Output File

        for (ip=offset; ip<_maxBIN; ){
                l = ip & 0xFF;
                if (_binFLG[ip] == bF_INIT){                                                                 // Ignore un-initialized data
                        if (byte_cnt)  dump_bytes(ip);                                                       // If Binary or ASCII data in Buffers...  Output them now
                        if (asccount)  dump_ASCII(ip);
                        if (dump){dump = 0; sp_print(); newline++;
        }        // If we had to Flush Buffers...*/
                        ip++;                                                                                // Next program location
                        skip = 1;                                                                            // Flag skip for ORG statement
                        jj = -1;

                }else if (_binFLG[ip] & (bF_ADRS | bF_WORD | bF_BYTE | bF_ASCII)){

                        switch (_binFLG[ip] & ~bF_REF){                                                      // Ignore reference bit  
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                if ASCII Text...
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                                case bF_ASCII:
                                        if (byte_cnt)   dump_bytes(ip);                                      // Dump any pending binary

                                        if (skip){                                                           // Insert ORG statement
                                                if (!newline)  sp_print();
                                                fprintf(fp, "\n\t\tORG\t"); putHEX2(ip);
                                                newline++;
                                                skip = 0;                                                    // Reset skip flag
                                        }if (is_ASCII(_binBUF[ip])){                                         // If it really is ASCII...
                                                string[asccount] = _binBUF[ip];
                                                asccount++;
                                                if (asccount >= ASCLIMIT) dump_ASCII(ip);
                                        }else{                                                               // Else treat it as binary data
                                                _binFLG[ip] &= ~bF_ASCII;
                                                _binFLG[ip] |=  bF_BYTE;
                                                if (asccount)  dump_ASCII(ip);                               // Dump any accumulated ASCII
                                                byte_data[byte_cnt] = _binBUF[ip];                           // [ Add Data to Buffer ]
                                                byte_cnt++;
                                        } break;
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                if Word Data...                                                              [  Add Comment Field ]
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                                case bF_WORD:
                                        if (byte_cnt) dump_bytes(ip);                                        // Dump any binary or ASCII in Buffers
                                        if (asccount) dump_ASCII(ip);
                                        if (skip){                                                           // Insert ORG statement
                                                if (!newline) sp_print();
                                                fprintf(fp, "\n\t\tORG\t");
                                                putHEX2(ip);
                                                newline++;
                                                skip = 0;                                                    // Reset skip flag
                                        }
                                        check_REF(ip);                                                       // Add Label if Referenced
                                        q = ((word) _binBUF[ip]) << 8;                                       // Get Word Value
                                        temp = _binBUF[ip + 1] & 0xFF;
                                        q |= temp;
                                        fprintf(fp, "%s\t",  DWstr);
                                        cptr = _find_Entry(q, symbol_count, Symbol_vIDX);                    // See if Symbol Exists
                                        if (cptr == NULL) putHEX(q);                                         // If not, do HEX Value  +++
                                        else    fprintf(fp, "%s",  cptr);                                    // Else Output Symbol   >>>
                                        if (HEXflag) fprintf(fp, "\t\t; %04X %02X %02X  %c%c", ip, _binBUF[ip], _binBUF[ip+1], ASCII(_binBUF[ip]), ASCII(_binBUF[ip+1])); // Add Comment Field

//    printf(fp, "\t\t; %04X   %02X %02X      %c%c", i, _binBUF[i], _binBUF[ip+1], ASCII(_binBUF[ip]), ASCII(_binBUF[ip+1]));
                                        ip++;
                                        if (_binFLG[ip + 2] != bF_ADRS && _binFLG[ip + 2] != bF_WORD){
                                                sp_print();
                                                newline++;
                                        } break;

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                                case bF_ADRS:                                                                // If address data...
                                        if (byte_cnt) dump_bytes(ip);                                        // Output any pending binary or  ASCII data from Buffers
                                        if (asccount) dump_ASCII(ip);
                                        if (skip){                                                           // Insert ORG statement
                                                if (!newline)
                                                sp_print();
                                                fprintf(fp, "\n\t\tORG\t");
                                                putHEX2(ip);
//                                              fprintf(fp, "\n;");
                                                newline++;
                                                skip = 0;                                                    // Reset skip flag
                                        }
                                        check_REF(ip);                                                       // Add label if referenced
                                        q = ((word) _binBUF[ip]) << 8;                               // Get address value
                                        temp = _binBUF[ip + 1] & 0xFF;
                                        q |= temp;
                                        fprintf(fp, "%s\t",  DWstr);
                                        cptr = _find_Entry(q, label_count, Label_vIDX);                      // See if label exists
                                        if (cptr == NULL) {                                                  // If not, output HEX
                                                cptr = _find_Entry(q, symbol_count, Symbol_vIDX);
                                                if (cptr == NULL) fprintf(fp, "x%04X",  q);
                                                else              fprintf(fp, "%s",  cptr);
                                        }
                                        else  fprintf(fp, "%s", cptr);                                      // else output label text
                                        if (HEXflag) fprintf(fp, "\t\t; %04X   %02X %02X     %c%c", ip, _binBUF[ip], _binBUF[ip+1], ASCII(_binBUF[ip]), ASCII(_binBUF[ip+1]));
                                        ip++;
                                        if (_binFLG[ip + 2] != bF_ADRS){
                                                sp_print();
                                                newline++;
                                        } break;

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                Default = Binary Data...
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                                default:
                                        if (asccount) dump_ASCII(ip);           // Output any Pending ASCII Data
                                        if (skip){                              // Insert ORG Statement
                                                if (!newline)
                                                sp_print();
                                                fprintf(fp, "\n\t\tORG\t");
                                                putHEX2(ip);
                                                newline++;
                                                skip = 0;                       // Reset skip Flag
                                        }
                                        byte_data[byte_cnt] = _binBUF[ip];      // Add Data to Buffer
                                        byte_cnt++;
                                        if (byte_cnt >= BYTELIMIT)          // If End of Buffer... 
                                                dump_bytes(ip);                 // Dump Accumulated Data
                        }
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                        Next Program Location
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                        ip++;
                        if (_binFLG[ip] != bF_INIT && _binFLG[ip] & bF_ASCII){   // if next Byte is Flagged as
                                if (!is_ASCII(_binBUF[ip])){                     // ASCII, but is not...
                                        _binFLG[ip] |=  bF_BYTE;                 // then Flag it as
                                        _binFLG[ip] &= ~bF_ASCII;                // Binary Data    
                                }
                        }
                }

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        If Previous Data was an Unconditional Transfer, & Current
        Location is not Referenced by some other opcode, & Current
        byte is 0 or 0FFH, Then treat this Byte as Un-initialized Data.
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/***************
                else if ((j & 0x80) && (!(_binFLG[ip] & bF_REF)) && ((_binBUF[ip] == 0) || (_binBUF[ip] == NO_DATA))) {
                        if (byte_cnt) dump_bytes(ip);                           / * Since we're going to Skip some  Data, Output any Pending ASCII * /
                        if (asccount) dump_ASCII(ip);                           / * or Binary Data Remaining in Buffers * /
                        if (dump){                                              / * if ASCII or Binary Output was Done, * /
                                sp_print();
                                dump = 0;
                                newline++;
                        }
                        _binFLG[ip] = bF_INIT;                                   / * Flag as Uninitialized Data * /
                        i++;
                        skip = 1;
                        byte_cnt = 0;
                }
****************/
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        If Previous Code was 0 or 0FFH, & Current Location is not referenced,
        & current opcode is 0 or 0FFH, un-initialize it.
        This avoids disassembling line after line after line of NOP or
        MOV R7,A.
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

                else if ((_OP==0 || _OP==0xFF) && (!(_binFLG[ip] & bF_REF)) && (_binBUF[ip]==0 || _binBUF[ip]==0xFF) && (_binFLG[ip] != bF_CLREF)){
                        _binFLG[ip] = '\xFF';
                        ip++;
                        skip = 1;
if( ip<10 )   fprintf(fp, ".");      // fprintf(fp, "\t Data Truncated");

                        jj = -1;
                }else{                                                                                        // It's Executable Code! **** If any ASCII or Binary Data Remains
                        if (byte_cnt)  dump_bytes(ip);                                                        // In the Buffers, Output them Now
                        if (asccount)  dump_ASCII(ip);
                        if (dump){
                                sp_print();
                                dump = 0;
                                newline++;
                        }
                        byte_cnt = 0;
                        if (skip){                                                                            // Insert ORG Statement   << O R G
                                if (!newline)

                                sp_print();
                                fprintf(fp, "\n\t\tORG\t");
                                putHEX2(ip);
                                newline++;
                                skip = 0;                                                                     // Reset Skip Flag  
                        }
                        _OP  = _binBUF[ip];                                                                   // Get Opcode +++   

_PC=ip;
                        if (_OP == 0xA5 && !newline)  { sp_print();  newline++;}                              // If Invalid Opcode

                        check_REF(ip);                                                                        // Add Label if Referenced
                        kcnt = 8+8;
                        jj = OPcode_TBL[_OP]._mod;                                                            // Get Options    

                        process_OPcode(OPcode_TBL[_OP].Mnemonic);                                             // Output Mnemonic

/*====================================================================================================================================================================
                Generate Operands                      cptr TBL string ptr
 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

                switch (jj & EA_MASK){
                               case EA_NONE: break;                            // Single Byte - no Options

/*====================================================================================================================================================================
     [05]              2 Byte Immediate Data            B I N A R Y ?  Bit Addressing
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_IMM2:
                               q = (word) _binBUF[ip + 1] & 0xFF;
                               putHEX(_binBUF[ip + 1]);
                               splitcheck(ip+1);
                               break;

/*====================================================================================================================================================================
     [06]              3 Byte Immediate Data
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_LREF:
                               q = ((_binBUF[ip+1] & 0xFF) << 8) | (_binBUF[ip+2] & 0xFF);
                                       cptr = _find_Entry(q, symbol_count, Symbol_vIDX);
                               if (cptr == NULL){
                               cptr = _find_Entry(q, label_count, Label_vIDX);
                                       if (cptr == NULL) kcnt += fprintf(fp, "-x%04X",  q);
                               }
                               if (cptr != NULL) kcnt += fprintf(fp, "%s",  cptr);
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [09]              2 Byte Direct Addressing         R A M
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_DIR2:
                               do_DIRECT(fp, _binBUF[ip+1]);
                               if ((_OP & 0xF)==2 || _OP==0xF5)  kcnt += fprintf(fp, ", A");
                               else if   ((_OP & 0xF0)  ==0x80){ kcnt += fprintf(fp, ", ");
                                       if (_OP < 0x88)       kcnt += fprintf(fp, "@R%d",  _OP & 1);
                                       else{                     kcnt += fprintf(fp,  "R%d",  _OP & 7);}
                               }
                               splitcheck(ip+1);
                               break;

/*====================================================================================================================================================================
     [0A]              MOV     dir, dir
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_DIR3:
                               do_DIRECT(fp, _binBUF[ip+2]);
                               kcnt += fprintf(fp, ", ");
                               do_DIRECT(fp, _binBUF[ip+1]);
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [0E]             3 byte Direct & Immediate Addressing
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_DMM3:
                               do_DIRECT(fp, _binBUF[ip+1]);
                               kcnt += fprintf(fp, ", #");
                               q = (word) _binBUF[ip + 2] & 0xFF;
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [11]             2 Byte Bit Addressing             RAM
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_BIT2:
                               do_BIT(fp, _binBUF[ip+1]);
                               if (_OP == 0x92) kcnt += fprintf(fp, ", C");
                               else{}

                               splitcheck(ip+1);
                               break;

/*====================================================================================================================================================================
     [21]              2 Byte Relative Addressing
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_REL2:
                               q = _binBUF[ip+1] & 0xFF;
                               q = (q > 0x7F) ? q | 0xFF00 : q;
                               q = ip + 2 + q;

                               cptr = _find_Entry(q, label_count, Label_vIDX);
                               if (cptr == NULL) kcnt += fprintf(fp, "x%04X", q);
                               else              kcnt += fprintf(fp, "%s",  cptr);   // Symbolic Label
                               splitcheck(ip+1);
                               break;

/*====================================================================================================================================================================
     [26]              3 Byte Immediate & Relative Addressing             R E L
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_IR3:
                               q = (word)_binBUF[ip+1] & 0xFF;
                               cptr = _find_Entry(q, symbol_count, Symbol_vIDX);
                               if (cptr == NULL) putHEX(_binBUF[ip + 1]);
                               else      kcnt += fprintf(fp, "%s",  cptr);
                               q = _binBUF[ip+2] & 0xFF;
                               q = (q > 0x7F) ? q | 0xFF00 : q;
                               q = ip + 3 + q;
                               cptr = _find_Entry(q, label_count, Label_vIDX);
                               if (cptr == NULL)
                                       if ( _binBUF[ip+2] ==0xFD)   kcnt += fprintf(fp, ", $");
                                       else   kcnt += fprintf(fp, ", x%04X",  q);
                               else           kcnt += fprintf(fp, ", %s",  cptr);
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [30]              3 Byte Direct & Relative Addressing
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_DR3:
                               do_DIRECT(fp, _binBUF[ip+1]);
                               q = _binBUF[ip+2] & 0xFF;
                               q = (q > 0x7F) ? q | 0xFF00 : q;
                               q = ip + 3 + q;
                               cptr = _find_Entry(q, label_count, Label_vIDX);
                               if (cptr == NULL)
                                       if ( _binBUF[ip+2] ==0xFD)   kcnt += fprintf(fp, ", $");
                                       else   kcnt += fprintf(fp, ", x%04X",  q);
                               else           kcnt += fprintf(fp, ", %s",  cptr);
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [32]              3 Byte Bit & Relative Addressing       REL
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_RELB:
                               do_BIT(fp, _binBUF[ip+1]);
                               q = _binBUF[ip+2] & 0xFF;
                               q = (q > 0x7F) ? q | 0xFF00 : q;
                               q = ip + 3 + q;
                               if ( _binBUF[ip+2] ==0xFD)   kcnt += fprintf(fp, ", $");
                               else{   cptr = _find_Entry(q, label_count, Label_vIDX);
                                       if (cptr != NULL) kcnt += fprintf(fp, ", %s",  cptr);
                                       else              kcnt += fprintf(fp, ", x%04X", q);
                               }
                               splitcheck(ip+1);
                               splitcheck(ip+2);
                               break;

/*====================================================================================================================================================================
     [41] [C1]         2 Byte 11 Bit Adrs (AJMP & ACALL)         [  AJMP:C1,  ACALL:41 ]
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                       case EA_112:
                               q = ((_OP & 0xE0) << 3) | ((ip+2) & 0xF800);
                               q = q | (_binBUF[ip+1] & 0xFF);
                               cptr = _find_Entry(q, label_count, Label_vIDX);
                               if (cptr==NULL) kcnt += fprintf(fp, "x%04X", q);
                               else            kcnt += fprintf(fp, "%s",  cptr);
                               splitcheck(ip+1);
                               break;
               }
/*====================================================================================================================================================================
     [  ]      Invalid Opcode = HEX DB
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
               if (_OP == 0xA5)  putHEX(_OP);

/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*
     [  ]      do Comment Field
     HEX address code ...
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------?/
                if (kcnt > xstop){ fputc( '\t', fp); }
                else  while(kcnt < xstop){ fputc( '\t', fp);  kcnt = (kcnt + 8) & 0xF8;}
                fprintf(fp,"; ", kcnt);

        if (view_binBUF==1){
                fprintf(fp,"%04X %02X",  ip, _binBUF[ip] & 0xFF);               // Address  Instruction 
                switch (OPcode_TBL[_OP]._mod & EA_SIZE){
                       case 0: fprintf(fp, "       "); break;
                       case 1: fprintf(fp, " %02X    ",   _binBUF[ip+1] & 0xFF); break;
                       case 2: fprintf(fp, " %02X %02X ", _binBUF[ip+1] & 0xFF, _binBUF[ip+2] & 0xFF);
                }
        }
        if (view_binFLG==1){
                fprintf(fp,"%02X",  _binFLG[ip] & 0xFF);
                switch (OPcode_TBL[_OP]._mod & EA_SIZE){
                       case 0: fprintf(fp, "       "); break;
                       case 1: fprintf(fp, " %02X    ",   _binFLG[ip+1] & 0xFF); break;
                       case 2: fprintf(fp, " %02X %02X ", _binFLG[ip+1] & 0xFF, _binFLG[ip+2] & 0xFF);
                }
                fprintf(fp, " [%02X] ", jj  );                                  // Addressing Mode
        }
        if (HEXflag){
                       fprintf(fp, "   %c",  ASCII(_binBUF[ip]));
                       switch (OPcode_TBL[_OP]._mod & EA_SIZE)                  // Additional ASCII
                       {      case 1: fprintf(fp,  "%c\t", ASCII(_binBUF[ip+1])); break;
                              case 2: fprintf(fp,"%c%c\t", ASCII(_binBUF[ip+1]),  ASCII(_binBUF[ip+2]));
                       }
        }

        if (post_flg) { fprintf(fp, "%s", comment_buf);  post_flg=0;}

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//    P A S S - 2     Source  Generation ..           <<   EA_XFER  SJMP JUMP CALL   ...*/
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                newline = 0;
                ip = ip + (OPcode_TBL[_OP]._mod & EA_SIZE) + 1;                 // Update Location Counter

                if (jj & EA_XFER || _OP == 0xA5){
                        if (_OP == 0x80  ) {sjmp_print();}
                        else {if ( OPcode_TBL[_binBUF[_PC]].bx!='S' ){sp_print();}
                             }
                        newline++;
                }
                if ((ip & 0xFF) < l) printf("\rPass-2 %04X", ip & 0xFF00);
        }
}
        if (byte_cnt)  dump_bytes(ip);                                          // if any Remaining ASCII or Binary,  Output it Now
        if (asccount)  dump_ASCII(ip);
        printf("\rPass-2 Source Generation Complete");

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Add Equates for Register Names
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        jj = 0;
        for (rn=0; rn<32; rn++){
                if (dirregs[rn]){
                        if (!jj){
                                if (!newline || dump)  sp_print();
                                fprintf(fp, "\n;\tRegister Equates\t\t\t; Access\n;");
                                newline = 0;
                        }fprintf(fp, "\n%s\t\tEQU\t",  &RB_name[rn].dent[0]);  putHEX(rn);  jj = 1;
                         fprintf(fp, "\t\t\t; %d", RB_name[rn].bcnt);
                }
        }

#ifdef  DEBUG2 /*------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
        dump_LABEL();    dump_SYMBOL();
}
/*==================================================     End of Pass 2     =============================================================================================*/

                Check if Data is Printable ASCII Other than the String Delimiter
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

int is_ASCII(byte data){
        if (data < ' ' || data > 0x7E || data == '\'')  return(0);
        return(1);
}

/*============================================================================================================================================================================
        Add Label to Output Line if Current Location Marked as Referenced             L A B E L
        near referenced Label
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void check_REF(word i){
int     cnt;
char   *cptr;
kcnt = 0;

        if(_binFLG[i] & bF_REF){
                cptr = _find_Entry( i, label_count, Label_vIDX);                        // make Label
                if (cptr == NULL)  kcnt  = fprintf(fp, "\nx%04X:", i);
                else{              kcnt  = fprintf(fp, "\n%s:", cptr);}                 // Exist Label 
                if      (kcnt < 9) kcnt += fprintf(fp, "\t\t");
                else if (kcnt >17) kcnt  = fprintf(fp, "\n\t\t");
                else if (kcnt <17) kcnt += fprintf(fp, "\t");
        }else{
                kcnt=fprintf(fp, "\n\t\t");
                kcnt=16;
        }
}

/*===============  P A S S - 3  ==================================================================================================/

 [P-3]  Un Mapped Label

 P A S S - 3

 Search for References to Un-initialized Data or Split References and, if Found, Generate EQU Statements for Them.
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void pass_3(void){
word    i;
word    ccnt;
int        j, l;
word    index;
char            *cptr;

        printf("\nPass-3 0000H");
        j = 0;
        for (i=0; ; ){
                l = i & 0xFFF;
                if (_binFLG[i] & bF_REF){                                                             // If Is Un-initialized or is Referenced
                        if (!(_binFLG[i] & bF_CLREF) && (_binFLG[i] & (bF_SPLIT | bF_NOINIT))){       // If Referenced & (split Opcode or Not Init)...
                                if (j++==0){ if (!newline || dump)  sp_print(); fprintf(fp, "\n;\tMiscellaneous Equates\t\t\t;  CL Access\n");  newline = 0;}

                cptr = _find_Entry( i, label_count, Label_vIDX);                                      // if Label Exists +++
                if (cptr == NULL) ccnt=fprintf(fp, "\nx%04X", i) & 0xF8;
                else              ccnt=fprintf(fp, "\n%s", cptr) & 0xF8;                              // chronous TAB
                do { ccnt+= putc('\t',fp);} while(ccnt < 16);
                fprintf(fp, "EQU\t"); putHEX(i);  fprintf(fp, "\t\t\t; [%c] %d", ptr->attb  , ptr->count);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                        }
                }
                i++;
                if (!i) break;
                  if ((i & 0xFFF) < l) printf("\rPass 3 %04X",  i);
        }

        fprintf(fp, "\n\n;\t%6d \tGlobal Labels",  label_count );
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Equates for Symbol Table     <>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        j = 0;
        for (index=0; index<symbol_count; index++){
                if(j++==0){ if (!newline || dump)  sp_print(); fprintf(fp, "\n;\t Symbol Equates\t\t\t\t;  CL Access\n");}    // Do Header If First One
                ptr = Symbol_vIDX[index];


 
                ccnt=fprintf(fp, "\n%s", ptr->label);
                ccnt = --ccnt&0xF8;                                                            // new TAB
                do { ccnt+= putc('\t', fp);} while(ccnt <16);
                ccnt+=fprintf(fp    , "EQU\t");
                putHEX(ptr->adrs); fprintf(fp, "\t\t\t; [%c] %d", ptr->attb, ptr->count );newline = 0;

        }
        fprintf(fp, "\n\n;\t %6d\tSymbols", symbol_count);
        printf("\rPass-3 Equate Generation Complete");
        if (!newline || dump)  fprintf(fp, "\n");
        fprintf(fp, "\n\t\tEND\n");
        fflush(fp);
        close(fp);
}                                                                                              //  End of Pass 3  

/*============================================================================================================================================================================
    Output OPCODE for Current Code
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void process_OPcode(char *mnem){
char    c;
        while (c = *mnem++){																// Output Text from OPCODE Table
                if (c == ' '){ putc('\t', fp); kcnt = (kcnt + 8) & 0xF8;}					// Convert Spaces to Tabs ++++
                else         { putc(c, fp);    kcnt++;}
        }
// fprintf(fp, " %d", kcnt);*/
}
/*============================================================================================================================================================================
        Output Operand for Direct Addressing            R A M     09      __       MOV     R2,#RAM_2EH
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 char   sp[]=" ";
void do_DIRECT(FILE *fp, word dir){
        char    *cptr;
signed int     i;
        dir &= 0xFF;
        if      (dir < 0x20){ kcnt += fprintf(fp, RB_name[dir].dent); dirregs[dir] = 1; // Register
                            RB_name[dir].bcnt++;                                            // Access Count
                            }
        else if (dir < 0x80){                                                           // iRAM
              cptr = _find_Entry(dir, symbol_count, Symbol_vIDX);
              if (cptr != NULL) kcnt += fprintf(fp, "%s",  cptr);
              else              kcnt += fprintf(fp, "__%02XH",  dir);
              }
              else{               kcnt += fprintf(fp, "%s", SFR[dir & 0x7F].dent);          // SFR++++
                  strcpy(comment_buf, SFR[dir & 0x7F].dent);
                  strcpy(comment_buf, SFR[dir & 0x7F]._MSG); post_flg++;
                  SFR[dir & 0x7F].bcnt++;
        /*---------------------------------------------------------------------------------------*/

                  if (!(dir & 0x07)){
                        if( SFR[dir & 0x7F].vu==1){
                             strcat(comment_buf, " : ");
                             for (i=7; i>=0; i--){
                                  if( SFRbits[dir+i & 0x7F].vu==1)
                                  strcat(comment_buf, SFRbits[dir+i & 0x7F].dent);
                                  strcat(comment_buf, " ");
                                  SFRbits[dir+i & 0x7F].bcnt++;
                             }                                                               // Access Count
                        }
              }else{ }
        }
}

/*============================================================================================================================================================================
      Output SFR Bit Name   -    Bit Test Bit Addressing          11 24 32
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void do_BIT(FILE *fp, word bit){

char    *cptr;
int     i;
        bit &= 0xFF;
        if (bit < 0x80){ i = (bit >> 3) + 0x20;
        /*---------------------------------------------------------------------------------------*/
              cptr = _find_Entry( i , symbol_count, Symbol_vIDX);
              if (cptr != NULL) kcnt += fprintf(fp, "%s.%d",  cptr, bit&7);
              else
        /*---------------------------------------------------------------------------------------*/
              kcnt += fprintf(fp, "___%02XH.%d",  i, bit & 7);
        }else { kcnt += fprintf(fp, "%s", SFRbits[bit & 0x7F].dent);
//              strcpy(comment_buf,     SFRb[bit & 0x7F]._MSG); post_flg++;}*/
                strcpy(comment_buf,  SFRbits[bit & 0x7F]._MSG); post_flg++;}
}
/*============================================================================================================================================================================
       Check for Reference to Address in Middle of Code & Flag Split Reference if True
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void splitcheck(int i){

        if (!(_binFLG[i] & bF_CLREF)) _binFLG[i] |= bF_SPLIT;               // Ignore if not Referenced  Else Flag Split Ref     
}
/*============================================================================================================================================================================
        Put HEX / Binary
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void putHEX(word j){

        if ( OPcode_TBL[_OP].bx =='L'){ __uINT2Binary( j & 0xFF ); kcnt +=  fprintf(fp,"%sB", stringBUF);
        }else{ putHEX2(j); }
}
/*============================================================================================================================================================================
        Put HEX
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void putHEX2(word j){

/*      if (j < 10)            kcnt += fprintf(fp, "_%X",  j);
        else*/
             if (j < 16)       kcnt += fprintf(fp, "0%XH", j);
        else if (j < 0xA0)     kcnt += fprintf(fp, "%XH" , j);
        else if (j < 0x100)    kcnt += fprintf(fp, "0%XH", j);
        else if (j < 0xA00)    kcnt += fprintf(fp, "0%XH", j);
        else if (j < 0x1000)   kcnt += fprintf(fp, "0%XH", j);
        else if (j < 0xA000)   kcnt += fprintf(fp, "%XH",  j);
        else                   kcnt += fprintf(fp, "0%XH", j);
}
/*============================================================================================================================================================================
        Put Char : Convert Code to Printable ASCII
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
int ASCII(int i){
        i = i & 0x7F;
        if     (i == 0x7F)  return ('.');
        else if (i < 0x20)  return ('.');
        else                return (i);
}


// End of D51P2.C

/*============================================================================================================================================================================

        D51.C
        Prototypes
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void    usage(void);
void    main(int argc, char *argv[]);
word    atox(char *str);
void    _getCODE(char *from, byte far *loc);
char    *_find_Entry(word val, word count, SYM_PTR *_LS_TBL);
void    _add_Entry(word val, char *symbol, int type);
struct sym      *get_SMEM(int type, int size);

#ifdef  DEBUG /*------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void    dump_SYMBOL(void);                              // Diagnostic Routines
void    dump_LABEL(void);

#endif

/*===========================================================================================================================================================================

      Global Variables

 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

char            src[32], dst[32];                       // File name buffers           
char            ctl[32];                                // Control file name           
struct          date     date;                          // Disassembly date            
struct          time     time;                          // Disassembly time            
char            _lineBUF[128];                          // Input line buffer           
FILE            *fp;                                    // Dos file struct             
/*int             HEXflag  = 0;                         // Append HEX Flag             
/*int           fileflag = 2;                            * File type Flag  .BIN .HEX 0 
int             kcnt;                                   // Output char counter         
word            pc;                                     // Current Program Counter     
word            _maxBIN;                                // Highest Data adrs           
word            offset;                                 // Program Offset              
/*byte          far *_binBUF;                           // Program Data Pointer        
/*byte          far *_binFLG;                           // Pointer to Program Flags    
char            string[ASCLIMIT];                       // ASCII data for DEFB         
word            asccount;                               // Count for string data       
byte            byte_data[BYTELIMIT];                   // Binary data for defb        
word            byte_cnt;                               // Count for binary data       
word            word_data[WORDLIMIT];                   // Binary data for defw        
word            word_cnt;                               // Count for word data         
byte            dump;                                   // Dump just done flag         
/*byte            ASCII_flag;                           // Use ASCII string flag       
struct          sym      *Symbol_TBL;                   // Symbol table pointer        
struct          sym      *Label_TBL;                    // Label table pointer         
struct          sym      *Symbol_TBL_last;              // Last symbol table pointer   
struct          sym      *Label_TBL_last;               // Lastlabel table pointer     
char            DBstr[8];                               // String for defined bytes    
char            DWstr[8];                               // String for defined words    
char            ASCstr[8];                              // String for defined ASCII    
byte            dirregs[32];                            // Access flags for dir reg    
word            symbol_count;                           // Number of symbols           
word            label_count;                            // Number of labels            

extern          SYM_PTR  *Symbol_vIDX;                  // Symbol Table Pointer Array  
extern          SYM_PTR   *Label_vIDX;                  // Label  Table Pointer Array  

/*============================================================================================================================================================================
     Code
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void usage(void){

        printf("\nUsage: D51 <filename> [options]\n"
                "Options may be entered UNIX Style (-d) or DOS style (/b)\n"
                "\t-a use ASCII Macro instead of DB/DEFB for Text.\n"
                "\t-d Include Address and Data in the Comment Field.\n"
                "\t-b Force .BIN Extension on input file.\n"
                "\t-h Force .HEX Extension on input file.\n"
                "\t   If neither 'b' nor 'h' is specified, D51 will first search\n"
                "\t   for a .HEX file, and if not found, then a .bin file\n"
                "\t-s Use 'DEFB' and 'DEFW' instead of 'DB' and 'DW' for binary data.\n"
                "\t-x Add a Hexadecimal offset to file addresses.\n\n"
                "\t-y dump machine code\n\n"
                "\t-t Trace mode\n\n"
                "Options may be entered in a freeform fashion as long "
                "as a dash (-) or\n"
                "a slash (/) preceeds any option that preceeds the filename."
                "\nExamples:\n"
                "\tD51 filename bd\n"
                "\tD51 -d filename x100\n"
                "\tD51 /h filename d -x100\n");
        exit(GOOD_EXIT);
}

/*============================================================================================================================================================================

   Diagnostic Routines

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

#ifdef  DEBUG

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

        - Output Label Table
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void    dump_LABEL(void){
        word    i;
        struct  sym     *ptr;

        fprintf( i51CFG , "\n.default F320");
        /*fprintf(i51CFG ,"\n.Bootloader35");*/
        fprintf(i51CFG , "\n.%s\n", cfgf);


        fprintf(i51CFG, "\n; Memory Map\r\n");
        fprintf(i51CFG, "area \tCODE \CODE 0x%04X:0x%04X\n", 0,_maxBIN);
        fprintf(i51CFG, "area \tDATA \RAM  0x%04X:0x%04X\n", 0, maxRAM);
        fprintf(i51CFG, "area \tDATA \FSR  0x%04X:0x0100\n", 0        );

        fprintf(i51CFG, "\n;==============================================================");
        fprintf(i51CFG, "\n; Label Table : %d", label_count);
        fprintf(i51CFG, "\n;--------------------------------------------------------------");

        ptr = Label_TBL;
        for (i=0; i<label_count; i++){
        ocnt=-1;        // \n TAB
                ocnt +=fprintf(i51CFG, "\nentry   %s", ptr->label );
                do { putc('\t',i51CFG); ocnt = (ocnt + 8) & 0xF8;} while(ocnt < 32);
                fprintf(i51CFG, "0x%04X\t; %c %d ", ptr->adrs, ptr->attb, ptr->count);
                ptr = ptr->next;
        }
        fprintf(i51CFG, "\n\n; Labels  : %d\n\n",  label_count );

        fprintf(i51CFG, "\n;==============================================================");
        fprintf(i51CFG, "\n; SFR Access ");
        fprintf(i51CFG, "\n;--------------------------------------------------------------");

        for (i=128; i<256; i++){
        ocnt=-1;        // \n TAB
        ocnt += fprintf(i51CFG, "\n%s", SFR[i & 0x7F].dent);
                do { putc('\t',i51CFG); ocnt = (ocnt + 8) & 0xF8;} while(ocnt < 16);
                fprintf(i51CFG, "0x%04X\t; %d",i , SFR[i & 0x7F].bcnt);
        }

        fprintf(i51CFG, "\n;==============================================================");
        fprintf(i51CFG, "\n; IO Port Define ");
        fprintf(i51CFG, "\n;--------------------------------------------------------------");

        for (i=128; i<256; i++){
        ocnt=-1;        // \n TAB
        ocnt += fprintf(i51CFG, "\n%s", SFRbits[i & 0x7F].dent);
                do { putc('\t',i51CFG); ocnt = (ocnt + 8) & 0xF8;} while(ocnt < 16);
        fprintf(i51CFG, "0x%04X\t; %d",i , SFRbits[i & 0x7F].bcnt);
        }
        printf(    "\n\n dump labels  : %d",  label_count );
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

        - Output Symbol Table
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

void    dump_SYMBOL(void){
        word    i;
        struct  sym     *ptr;
ocnt=0;
        fprintf(i51CFG, "\n;=============================================================");
        fprintf(i51CFG, "\n; Symbol Table : %d", symbol_count);
        fprintf(i51CFG, "\n;--------------------------------------------------------------");
        ptr = Symbol_TBL;
        for (i=0; i<symbol_count; i++) {
                ocnt=fprintf(i51CFG, "\n%s", ptr->label    ); //  &0xF8;*/
                ocnt = --ocnt&0xF8;
                do { ocnt+= putc('\t', i51CFG);} while(ocnt <16 );

                fprintf(i51CFG, "0x%04X\t; %d", ptr->adrs, ptr->count );
//              fprintf(i51CFG, "\t%d",        ocnt );*/
                ptr = ptr->next;
        }
        fprintf(i51CFG, "\n\n; Symbols : %d\n", symbol_count );
         printf(    "\n dump symbols : %d\n", symbol_count );
}

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

        - Output Program Flag Table
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void dump__binFLG(void){
word    i, j, k, t;

        printf("\nProgram flags:\n0000: ");
        for (i=0, j=0, k=0; i<0xFFFF; i++){ printf("%02X ", _binFLG[i]);
                j++;
                if (j == 16){ j = 0; k++;
                        if (k == 20){ k = 0; t = getch(); if (t == 0x1B) return;}
                        printf("\n%04X: ", i + 1);
                }
        }
}


#endif /*----------------------------------------------------------------------------------------------------------------------------------------------------------*/

/*===============  M A I N  ==================================================================================================


        The Main Program
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void    main(int argc, char *argv[]){
        char    c;
        word    count;
        word    i, l;
        char    *inp;
        int     line;

        printf("\n C8051F320 Disassembler Ver %d.%d\n (c)Honam University dept. of Computer Engineering 1997-2008.\n http://www.systembus.com  e-mail:chronous@empal.com\n\n", verno, revno);

        if (argc < 2) usage();

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        find filename in command line
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

        for (line=1; line<argc; line++){                                                                 // find first non option string
                inp = argv[line];
                c = *inp;
                if (c == '?') usage();                                                                       // '?' without preceeding '-' or '/'
                if (c == '-' || c == '/'){
                        if (*(++inp) == '?') usage();                                                        // '?' following '-' or '/'
                }else{
                        strcpy(src, argv[line]); strcat(src, ".B");                                          // Init filenames
                        strcpy(dst, argv[line]); strcat(dst, ".A51");
                        strcpy(ctl, argv[line]); strcat(ctl, ".CTL");
                        strcpy(cfgf,argv[line]);
                        break;
                }
        }
        strcpy(DBstr, "DB");                                                                                 // Init define byte and word strings
        strcpy(ASCstr,"DB");                                                                                 // Init define ASCII string
        strcpy(DWstr, "DW");

        Symbol_TBL = NULL;                                                                                   // No symbols or labels yet
        Label_TBL  = NULL;
        fp = NULL;
        offset = 0;                                                                                          // Default Start at Address 0

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Process Command Line Options
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

        if (argc > 2){
                for (count=1; count<argc; count++){
                        inp = argv[count];                                                                   // To avoid modifying pointer in argv
                        while (c = toupper(*inp++)){
                                if (c == '-' || c == '/') c = toupper(*inp++);                               // Skip over Option Specifier
                                if (c == '?') usage();
                                if (count == line) break;                                                    // Skip if already identified
                                if (c == 'X'){ offset = atox(inp); break;}                                   // Add HEX offset to program
                                else if(c == 'D')  HEXflag = 1;                                              // Add Data in Comment Field
                                else if(c == 'B'){ fileflag = BINFILE; strcpy(src, argv[line]); strcat(src, ".BIN");}
                                else if(c == 'H'){ fileflag = HEXFILE; strcpy(src, argv[line]); strcat(src, ".HEX");}
                                else if(c == 'S'){ strcpy(DBstr , "DEFB" ); strcpy(DWstr, "DEFW");}
                                else if(c == 'A'){ strcpy(ASCstr, "ASCII"); ASCII_flag = 1;}                 // Use ASCII Macro
/*                              else if(c == 'T'){ !view_binBUF; }
                                else if(c == 'Y'){ !view_binFLG; }*/
                                else if(c == 'N'){ view_binFLG=0; }

                                else if(c == 'T'){ view_binBUF=1; }
                                else if(c == 'Y'){ view_binFLG=1; }

                        }
                }
        }
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Open Source File
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        switch (fileflag){
                case EITHERFILE:                                                            // If no type specified...  
                        fp = fopen(src, "r");                                               // Search for HEX file first
                        if (fp == NULL){                                                    // If not found, search for BIN File
                                fileflag = BINFILE;
                                strcpy(src, argv[line]);
                                strcat(src, ".HEX");
                                fp = fopen(src, "rb");
                                if (fp == NULL){ printf("Can't open either '%s.HEX' nor '%s. BIN'\n", argv[line], argv[line]); exit(FILE_ERROR);}
                                else  fileflag = BINFILE;
                        }break;

                case BINFILE: fp = fopen(src, "rb");       // .B > .BIN > .HEX 

                              if (fp != NULL){ break;}
                                        strcat(src, "IN"); fp = fopen(src, "rb");
                              if (fp != NULL){ break;}
                                        strcpy(src, argv[line]); strcat(src, ".HEX"); fileflag = HEXFILE;
                case HEXFILE: fp = fopen(src, "r");  break;
        }
        if (fp == NULL){ printf("* Can't open file '%s' *\n", src); exit(FILE_ERROR);
}

// ------------------------------------------------------------------------------
if ((i51CFG  = fopen(i51cfg_fname, "w")) == NULL) { printf("Unable to Open File  -  %s\n", i51cfg_fname);exit(1);}
if ((DEBfp   = fopen(debug_fname,  "w")) == NULL) { printf("Unable to Open File  -  %s\n",  debug_fname);exit(1);}
if ((SYMfp   = fopen(symbol_fname, "w")) == NULL) { printf("Unable to Open File  -  %s\n", symbol_fname);exit(1);}
if ((LBLfp   = fopen(label_fname,  "w")) == NULL) { printf("Unable to Open File  -  %s\n",  label_fname);exit(1);}
if ((DMPfp   = fopen(dump_fname,   "w")) == NULL) { printf("Unable to Open File  -  %s\n",   dump_fname);exit(1);}
if ((TRACEfp = fopen(trace_fname,  "w")) == NULL) { printf("Unable to Open File  -  %s\n",  trace_fname);exit(1);}
fprintf (TRACEfp, "\n Label/Symbol Table Entry Log   \n L  NO  adrs Access CL  Label\n");
/*fprintf (DEBfp,   "\n LS-Table Duplicated Entry Check\n L  NO SQ adrs Find Label\t\tStored Label\n");*/
fprintf (DEBfp,   "\n LS-Table Duplicated Entry Check\n L  NO SQ  adrs Access CL Find Label\t\tStored Label\n");


/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Allocate Memory for Program and Flags  ? BUG : Memory Allocation Error (TC 3)
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

        if ((_binBUF = (byte far *) farmalloc(_binBUFsz)) == NULL) {printf(" Internal Error! - Can't Allocate Program Space!\n"); exit(MEM_ERROR);}
        if ((_binFLG = (byte far *) farmalloc(_binBUFsz)) == NULL) {printf(" Internal Error! - Can't Allocate Flag Space!\n");    exit(MEM_ERROR);}

        printf("Initializing Program Spaces...");

        for (count=0xFFFF; count; --count) {                                                // Fill code space with 
                _binBUF[count] = NO_DATA; _binFLG[count] = bF_INIT;                         // Invalidate data   Invalidate flags
        }       _binBUF[0]     = NO_DATA;     _binFLG[0] = bF_INIT;                         // Include first location

        for (count=0; count<32; count++) dirregs[count] = 0;                            // No register references yet

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Read Input File and Set up Data Array
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        _maxBIN = 0;
        line = 0;
        pc = offset;
        printf("\nreading %s\n", src);

        if (fileflag == BINFILE) {                                                                 // If binary file...    
                while (!feof(fp)){                                                                 // Until end of file... 
                        i = fread(_lineBUF, 1, 128, fp);                                           // Read a block of data 
                        for (l=0; l<i; l++){
                                _binBUF[pc] = _lineBUF[l];                                         // Copy to program space
                                _binFLG[pc] = bF_DATA;
                                pc++;
                                if ((pc & 0xFF) == 0)
                                        printf("\r%04X", pc);                                      // Show progress        
                        } _maxBIN = pc;                                                            // Flag highest location
                }
        }else{                                                                                     // Else HEX file...     
                while (!feof(fp)) {                                                                // Until end of file... 
                        *_lineBUF = '\0';                                                          // Clear Previous Line  
                        fgets(_lineBUF, 127, fp);                                                  // Read one line        
                        line++;
                        inp = _lineBUF;                                                            // Local copy of pointer
                        if (sscanf(inp, "%*c%2x%4x", &i, &pc) != EOF){
                                                                                                   // Get count and address
                                pc += offset;                                                      // Add offset to address
                                if (i == 0) break;
                                                                                                   // Done if end of HEX record
                                if (i > 64){                                                   // Oops! line too long  
                                        printf(" Invalid Count (%d) in line %d:\n", i, line);
                                        printf("%s", _lineBUF);
                                        exit(FILE_ERROR);
                                }
                                for (l=0; l<i ; l++){                                          // Now move data to program area
                                        _getCODE(inp+9+l*2, & _binBUF[pc]);                        // Code to program space
                                        _binFLG[pc] = bF_DATA;                                     // Flag valid data
                                        pc++;
                                        if ((pc & 0xFF) == 0)                                      // Show progress
                                        printf("\r%04X", pc);
                                }
                        } _maxBIN = (_maxBIN > pc) ? _maxBIN : pc;                             // Update last address
                }
        }
        close(fp);                                                                                 // Done reading input file 
        if (!_maxBIN) _maxBIN = 0xFFFF;                                                            // If wrapped around to 0... Is 64K program (binary?)
        printf("\rHighest Location = %04XH\n", _maxBIN);                                           // Show last location      

/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Got the Program in Data Array, Now let's go to Work...
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
        symbol_count = 0;
        label_count  = 0;

        pass_0();                                                                                   // Read Control File                   
        pass_1();                                                                                   // Find Internal References            
        pass_2();                                                                                   // Disassemble to Output File          
        pass_3();                                                                                   // Generate EQU's for References       
        printf("\n\nDisassembled  %s -> %s  %XH bytes\n", src, dst, _maxBIN);                   // Output Header                       

        fcloseall();
        exit(GOOD_EXIT);
}
                                /*****  End of Main  *****/
/*============================================================================================================================================================================
    Convert ASCII HEX to Hexadecimal for X Option
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
word atox(char *str){
        char    c;
        word    i;

        i = 0;
        while (c = toupper(*str++)){
                if (isxdigit(c)){
                        c = (c > '9') ? c - 0x37 : c & 0xF;
                        i = (i << 4) | c;
                } else  break;

        } return(i);
}
/*============================================================================================================================================================================
      Put ASCII HEX Data into Binary Far Array
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void _getCODE(char *from, byte far *loc){
byte    c, i;

        c = *from++ - 0x30;
        c = (c > 10) ? c - 7 : c;
        i = c << 4;
        c = *from++ - 0x30;
        c = (c > 10) ? c - 7 : c;
        *loc = i | c;
}

/*============================================================================================================================================================================
  [1]  Allocate New Entry in Symbol Table or Label Table
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
struct  sym *get_SMEM(int type, int size){

struct  sym     *ptr;
        ptr = malloc(sizeof(struct sym) + size + 1);
        if (ptr == NULL){
                printf("\n I N T E R N A L  E R R O R ! - No Memory for ");
                if(type)    printf("Label");
                else        printf("Symbol");
                printf(" Table!\n");
                exit(MEM_ERROR);
        }
        ptr->adrs = 0;                                                                      // Initialize the New Entry
        ptr->next = NULL;
        return(ptr);                                                                            // Then give Caller the Address
}

/*============================================================================================================================================================================
    [3] Find Symbol or Label

        Binary search using Table of Pointers to List Nodes.
        This Search is based on the Fact that: list[first-1] ?key < list[last+1] is an Invariant.
        This allows the while loop to involve only one boolean expression, rather than two.
        The 'if' Statement also Involves only one Boolean Expression.
        The Test for Equality (has it been Found?) is not done until the Loop is Complete.
        This Significantly Speeds up the Search Compared to a Standard Binary Search.
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

char *_find_Entry(word val, word count, SYM_PTR *_LS_TBL){

word            first, mid, last;
char            *ret;

fprintf(TRACEfp , "\n Find Entry : [ %04X ]", val);
        first = 1;
        last = count;
        while (first <= last){                                                    // While more to Search...
                mid = (first + last) >> 1;                                    // Begin in Middle of Remaining Array
                ptr = _LS_TBL[mid - 1];                                               // Get Pointer to Node 
                if (ptr->adrs > val) last  = mid - 1;                         // Determine which way to go.  Search before Midpoint
                else                 first = mid + 1;                                 // Search after Midpoint
        }
        ret = NULL;                                                                   // Assume not found
        if (last > 0){                                                            // Are we still within the Array?
                ptr = _LS_TBL[last - 1];                                              // If so, get Last Pointer
                if (val == ptr->adrs) {ret = ptr->label;                      // Is it what we're Searching for?
                                                                                      // If so, Return Pointer to Caller
                fprintf(TRACEfp, " %04X= %s", ptr->adrs, ret);
                }
        }
fprintf(TRACEfp, " %04X=>%s", ptr->adrs, ret);
        return(ret);
}
/*============================================================================================================================================================================*/
char display_LABEL(cptr){
                        if (cptr == NULL) fprintf(fp, "\nx%04X:\t%s\t'", adrs, ASCstr); // ADDRESS
                        else              fprintf(fp, "\n%s:-++\t%s\t'", cptr, ASCstr); // LABEL  
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
fill_boder(){ fputs(";==============================================\n", out_device);}

/*============================================================================================================================================================================
   [2] Add Symbol / Label

   0 : Symbol
   x : Label.
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void _add_Entry(word val, char *symbol, int type){

/*struct  sym   *nptr, *tbl_ptr;*/
char            *cptr;
char            tbl_name[8];
word            i, index;
char            *ret;
char            duplicated;
word            kcnt;

        cptr = symbol;                                                                        // Ensure That Input String is NULL Terminated
        while (*cptr){
                if (!isgraph(*cptr)) break;
                cptr++;
        } *cptr = '\0';

        duplicated=0;
        if (type){tbl_ptr = Label_TBL; strcpy(tbl_name, "Label" );}                           // Get Pointer to Correct Table
        else{     tbl_ptr =Symbol_TBL; strcpy(tbl_name, "Symbol");}

        if (tbl_ptr == NULL){                                                                 // If first Symbol or Label...
               nptr = get_SMEM(type, strlen(symbol));
               if (type)   {  Label_TBL = nptr;}                                              // Initialize Head Pointer
               else        { Symbol_TBL = nptr;}
        }else{
               if(type){
                      xptr=Label_TBL;
                      for (index=0; index<label_count; index++){
                      fprintf (DEBfp, "\n L%4d%4d %04X %6d %c  %s\t\t%s", label_count, index, val, xptr->count, xptr->attb, symbol, xptr->label);
                             if (val == xptr->adrs){ fprintf(DEBfp, "\t<--- dup"); duplicated++; xptr->count++;
                             fprintf(DEBfp, "\n----------------------------------------------------------------------");
                             break;  }
                      xptr = xptr->next;
                      }
                      nptr = get_SMEM(type, strlen(symbol));
                      Label_TBL_last->next = nptr;

               }else{
                      xptr=Symbol_TBL;
                      for (index=0; index<symbol_count; index++){
                      fprintf (DEBfp, "\n  %4d%4d %04X %6d %c  %s\t\t%s", symbol_count, index, val, xptr->count, xptr->attb, symbol, xptr->label);
                             if (!stricmp(symbol, xptr->label)){ fprintf(DEBfp, "\t<=== dup"); duplicated++; xptr->count++;
                             fprintf(DEBfp, "\n=====================================================================");
                             break;}
                      xptr = xptr->next;
                      }
                      nptr = get_SMEM(type, strlen(symbol));
                      Symbol_TBL_last->next = nptr;
               }
        }
        if (duplicated==0){
               if (type){ Label_TBL_last = nptr;  label_count++; xptr=nptr;}
               else     {Symbol_TBL_last = nptr; symbol_count++; sptr=nptr;}

               nptr->adrs = val;
               strcpy(nptr->label, symbol);
               nptr->attb = _ATTB;
               nptr->count=1;

               if (type){
               fprintf  (TRACEfp,  "\n L%4d  %04X %6d %c  %s", label_count, nptr->adrs, nptr->count, nptr->attb,  nptr->label);
                      kcnt = fprintf (DEBfp,  "\n L%4d%4d %04X        %c  %s\t\t=====, label_count, index, val, _ATTB, symbol, xptr->label);
                      fprintf (DEBfp,   "\n----------------------------------------------------------------------");

               }else{ fprintf (TRACEfp, "\n  %4d  %04X %6d %c  %s", symbol_count, nptr->adrs, nptr->count, nptr->attb, nptr->label);
                      kcnt += fprintf (DEBfp, "\n  %4d%4d %04X        %s\t\t=====, symbol_count, index, val, symbol, xptr->label);
                      fprintf (DEBfp,   "\n=====================================================================");
               }
        }
}

//=========================================================================================================================