disbuild.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 874 行 · 第 1/2 页

C
874
字号

machine_data AMachine[] = {
#if DISCPU & DISCPU_axp
    TABLE( AXP ),
#endif
#if DISCPU & DISCPU_ppc
    TABLE( PPC ),
#endif
#if DISCPU & DISCPU_x86
    TABLE( X86 ),
#endif
#if DISCPU & DISCPU_x64
    TABLE( X64 ),
#endif
#if DISCPU & DISCPU_jvm
    TABLE( JVM ),
#endif
#if DISCPU & DISCPU_sparc
    TABLE( SPARC ),
#endif
#if DISCPU & DISCPU_mips
    TABLE( MIPS ),
#endif
};

typedef struct string_list string_list;

struct string_list {
    string_list         *next;
    string_data         *data;
    unsigned            len;
};

#define MAX_ENTRIES     96*1024
string_list     *Strings;
char            StringTable[MAX_ENTRIES];
unsigned        StringIndex;
dis_selector    SelTable[MAX_ENTRIES];
unsigned        SelIndex;

typedef struct range    range;
struct range {
    range       *next;
    unsigned_32 check;
    unsigned    idx;
    unsigned    num;
    unsigned    entry[1]; /* variable sized */
};

static unsigned AddString( string_data *data )
{
    unsigned    len;
    string_list **owner;
    string_list *curr;
    string_list *new;

    len = strlen( data->string );
    owner = &Strings;
    for( ;; ) {
        curr = *owner;
        if( curr == NULL ) break;
        if( curr->len < len ) break;
        owner = &curr->next;
    }
    new = malloc( sizeof( *new ) );
    if( new == NULL ) {
        fprintf( stderr, "Out of memory!\n" );
        exit( 1 );
    }
    *owner = new;
    new->next = curr;
    new->data = data;
    new->len = len;
    return( len );
}

static int StringMatch( unsigned idx, string_list *curr )
{
    unsigned            i;
    unsigned char       c;
    char                *str;

    str = curr->data->string;
    i = curr->len;
    for( ;; ) {
        if( i == 0 ) return( 1 );
        if( idx >= StringIndex ) return( 0 );
        c = StringTable[idx++];
        if( !(c & LENGTH_BIT) ) {
            if( c != *str ) return( 0 );
            ++str;
            --i;
        }
    }
}

static void BuildStringTable( void )
{
    string_list *curr;
    string_list *fix;
    string_list *next;
    unsigned    idx;

    for( curr = Strings; curr != NULL; curr = curr->next ) {
        idx = 0;
        for( ;; ) {
            if( idx >= StringIndex ) {
                curr->data->string_idx = StringIndex;
                StringTable[StringIndex++] = LENGTH_BIT | curr->len;
                memcpy( &StringTable[StringIndex], curr->data->string,
                                curr->len );
                StringIndex += curr->len;
                break;
            }
            if( StringMatch( idx, curr ) ) {
                if( (StringTable[idx]&~LENGTH_BIT) != curr->len ) {
                    memmove( &StringTable[idx+1], &StringTable[idx],
                            StringIndex - idx );
                    ++StringIndex;
                    StringTable[idx] = LENGTH_BIT | curr->len;
                    for( fix = Strings; fix != curr; fix = fix->next ) {
                        if( fix->data->string_idx >= idx ) {
                            fix->data->string_idx++;
                        }
                    }
                }
                curr->data->string_idx = idx;
                break;
            }
            ++idx;
        }
    }
    for( curr = Strings; curr != NULL; curr = next ) {
        next = curr->next;
        free( curr );
    }
}


static int BuildRanges( FILE *fp, ins_decode_data **_data, unsigned *_num,
                char *prefix )
{
    unsigned            i;
    unsigned            j;
    unsigned            idx;
    unsigned            bit_count[32];
    unsigned long       opcode_or;
    unsigned long       bits;
    unsigned long       curr_mask;
    unsigned            idx_mask;
    unsigned            shift;
    unsigned            best_bit;
    unsigned            shifted_mask;
    range               *head;
    range               *tail;
    range               *new;
    unsigned            first_sel;
    int                 dumped_entries;

    unsigned            num = *_num;
    ins_decode_data     *data = *_data;

    dumped_entries = 0;
    first_sel = SelIndex;
    head = malloc( sizeof( *head ) + num * sizeof( head->entry[0] ) );
    if( head == NULL ) {
        fprintf( stderr, "out of memory!\n" );
        exit( 1 );
    }
    tail = head;
    idx = 0;
    for( i = 0; i < num; ++i ) {
        /* Mask of zero is an instruction synonym */
        if( data[i].mask != 0 ) {
            head->entry[idx++] = i;
        }
    }
    head->num = idx;
    head->idx = 0;
    head->next = NULL;
    head->check = ~0;
    for( ;; ) {
        memset( bit_count, 0, sizeof( bit_count ) );
        opcode_or = 0;
        for( i = 0; i < head->num; ++i ) {
            opcode_or |= data[head->entry[i]].opcode & head->check;
        }
        for( i = 0; i < head->num; ++i ) {
            bits = data[head->entry[i]].mask & opcode_or;
            for( j = 0; j < 32; ++j ) {
                if( bits & (1UL << j) ) {
                    bit_count[j]++;
                }
            }
        }
        best_bit = 0;
        for( i = 0; i < 32; ++i ) {
            /* find the bit position that occurs in the most masks */
            if( bit_count[i] > bit_count[best_bit] ) best_bit = i;
        }
        shift = best_bit;
        if( bit_count[shift] != 0 ) {
            shifted_mask = 0;
            i = shift;
            for( ;; ) {
                if( i >= 32 ) break;
                /*
                    Don't include in range if less than 3/4ths of the
                    masks use the bit.
                */
                if( (head->check & (1UL << i))
                 && (bit_count[i] < (3*bit_count[best_bit]) / 4) ) break;
                shifted_mask <<= 1;
                shifted_mask |= 1;
                if( shifted_mask == 0xff ) break;
                ++i;
            }
            // now try to grow it the other way
            if( shift != 0 && shifted_mask != 0xff ) {
                i = shift - 1;
                for( ;; ) {
                    if( i == 0 ) break;
                    if( (head->check & (1UL << i))
                        && (bit_count[i] < (3*bit_count[best_bit]) / 4) ) break;
                    shifted_mask <<= 1;
                    shifted_mask |= 1;
                    --shift;
                    if( shifted_mask == 0xff ) break;
                    --i;
                }
            }
            dumped_entries++;
            fprintf( fp, "    { 0x%2.2x, 0x%2.2x, 0x%4.4x },\n", shifted_mask, shift, SelIndex );
            curr_mask = (unsigned long) shifted_mask << shift;
            for( i = 0; i <= shifted_mask; ++i ) {
                for( j = 0; j < head->num; ++j ) {
                    idx = (data[head->entry[j]].opcode >> shift) & shifted_mask;
                    idx_mask = (data[head->entry[j]].mask >> shift) & shifted_mask;
                    if( (i & idx_mask) == idx ) {
                        if( SelTable[SelIndex + i] == 0 ) {
                            SelTable[SelIndex + i] = head->entry[ j ] + 1;
                        } else {
                            if( SelTable[SelIndex + i] > 0 ) {
                                new = malloc( sizeof( *new ) + num * sizeof( new->entry[0] ) );
                                if( new == NULL ) {
                                    fprintf( stderr, "out of memory!\n" );
                                    exit( 1 );
                                }
                                new->next = NULL;
                                new->check = head->check &= ~curr_mask;
                                new->idx = tail->idx + 1;
                                new->num = 1;
                                new->entry[0] = SelTable[SelIndex + i] - 1;
                                SelTable[SelIndex + i] = -new->idx;
                                tail->next = new;
                                tail = new;
                            }
                            tail->entry[tail->num++] = head->entry[ j ];
                        }
                    }
                }
            }
            SelIndex += shifted_mask + 1;
            if( SelIndex >= MAX_ENTRIES ) {
                fprintf( stderr, "internal error (MAX_ENTRIES may need increasing)\n" );
                exit( 1 );
            }
        } else {
            /* multiple opcode/mask pairs going to same bit pattern */
            fprintf( stderr, "internal error constructing range table\n" );
            for( i = 0; i < head->num; ++i ) {
                fprintf( stderr, "    machine:%s, opcode:%8.8lx, mask:%8.8lx, idx:%s\n",
                        prefix, data[head->entry[i]].opcode,
                                data[head->entry[i]].mask ,
                                data[head->entry[i]].idx_name );
            }
            exit( 1 );
        }
        new = head->next;
        free( head );
        head = new;
        if( head == NULL ) break;
    }
    if( !dumped_entries ) {
        dumped_entries++;
        fprintf( fp, "    { 0x00, 0x00, 0x0000 },\n" );
    }
    for( ; first_sel < SelIndex; ++first_sel ) {
        if( SelTable[first_sel] > 0 ) {
            SelTable[first_sel] = data[ SelTable[first_sel] - 1 ].idx;
        }
    }
    return( dumped_entries );
}

#define INVALID_INS     "????"
string_data InvalidIns = { INVALID_INS, 0 };
string_data NullString = { "", 0 };

int main( void )
{
    FILE            *fp;
    unsigned        i;
    unsigned        j;
    unsigned        max_name;
    unsigned        len;
    machine_data    *mach;
    string_data     **insnames;
    ins_decode_data **decode;
    unsigned        *num_ins;
    int             *listl;

    fp = fopen( "distbls.gh", "w" );
    if( fp == NULL ) {
        fprintf( stderr, "can't open output file\n" );
        exit( 1 );
    }
    fprintf( fp, "#include <stddef.h>\n" );
    fprintf( fp, "/* file created by DISBUILD.C */\n\n" );
    AddString( &InvalidIns );
    AddString( &NullString );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        insnames = mach->ins_names;
        num_ins = mach->num_ins;
        max_name = sizeof( INVALID_INS ) - 1;
        for( ; *insnames != NULL ; ++insnames ) {
            for( j = 0; j < *num_ins; ++j ) {
                len = AddString( &(*insnames)[j] );
                if( len > max_name ) max_name = len;
            }
            ++num_ins;
        }
        fprintf( fp, "const unsigned char %sMaxInsName = %u;\n\n",
            mach->prefix, max_name );
        for( j = 0; j < mach->num_reg_names; ++j ) {
            AddString( &mach->reg_names[j] );
        }
        for( j = 0; j < mach->num_ref_names; ++j ) {
            AddString( &mach->ref_names[j] );
        }
    }
    BuildStringTable();
    fprintf( fp, "\nconst char DisStringTable[] = {\n" );
    for( i = 0; i < StringIndex; ++i ) {
        if( (i % 16) == 0 ) fprintf( fp, "/*%4.4x*/ ", i );
        if( StringTable[i] < ' ' || (StringTable[i] & LENGTH_BIT) ) {
            fprintf( fp, "%-3u,", StringTable[i] );
        } else {
            fprintf( fp, "'%c',", StringTable[i] );
        }
        if( (i % 16) == 15 ) fprintf( fp, "\n" );
    }
    fprintf( fp, "};\n\n" );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        num_ins = mach->num_ins;
        for( decode = mach->decode; *decode != NULL ; ++decode ) {
            for( j = 0; j < *num_ins; ++j ) {
                if( strcmp( (*decode)[j].handler, "NULL" ) != 0 ) {
                    fprintf( fp, "extern dis_handler_return %s( dis_handle *, void *, dis_dec_ins * );\n",
                        (*decode)[j].handler );
                }
            }
            ++num_ins;
        }
    }
    fprintf( fp, "\nconst dis_ins_descript DisInstructionTable[] = {\n" );
    fprintf( fp, "    { 0x%4.4x, 0x00000001, 0x00000000, NULL },\n", InvalidIns.string_idx );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        fprintf( fp, "\n    /* Machine:%s */\n\n", mach->prefix );
        insnames = mach->ins_names;
        num_ins = mach->num_ins;
        len = 1;
        for( decode = mach->decode; *decode != NULL ; ++decode ) {
            fprintf( fp, "    /* Table_%d */\n\n", len++ );
            for( j = 0; j < *num_ins; ++j ) {
                fprintf( fp, "    { 0x%4.4x, 0x%8.8lx, 0x%8.8lx, %s }, /* %s */\n",
                    (*insnames)[j].string_idx,
                    (*decode)[j].opcode,
                    (*decode)[j].mask,
                    (*decode)[j].handler,
                    (*decode)[j].idx_name );
            }
            fprintf( fp, "\n" );
            ++insnames;
            ++num_ins;
        }
    }
    fprintf( fp, "};\n" );
    fprintf( fp, "\nconst unsigned short DisRegisterTable[] = {\n" );
    fprintf( fp, "    0x%4.4x,\n", NullString.string_idx );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        for( j = 0; j < mach->num_reg_names; ++j ) {
            fprintf( fp, "    0x%4.4x,\n", mach->reg_names[j].string_idx );
        }
    }
    fprintf( fp, "};\n" );
    fprintf( fp, "\nconst unsigned short DisRefTypeTable[] = {\n" );
    fprintf( fp, "    0x%4.4x,\n", NullString.string_idx );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        for( j = 0; j < mach->num_ref_names; ++j ) {
            fprintf( fp, "    0x%4.4x,\n", mach->ref_names[j].string_idx );
        }
    }
    fprintf( fp, "};\n" );
    for( i = 0, mach = AMachine ; i < NUM_ELTS( AMachine ); ++i, ++mach ) {
        num_ins = mach->num_ins;
        j = 0;
        len = 0;
        listl = NULL;
        fprintf( fp, "\nconst dis_range %sRangeTable[] = {\n", mach->prefix );
        for( decode = mach->decode; *decode != NULL; ++decode ) {
            fprintf( fp, "\n    /* Table_%d */\n\n", ( len + 1 ) );
            listl = realloc( listl, ( len + 1 ) * sizeof( int ) );
            listl[ len++ ] = j;
            j += BuildRanges( fp, decode, num_ins, mach->prefix );
            ++num_ins;
        }
        fprintf( fp, "};\n" );
        fprintf( fp, "\nconst int %sRangeTablePos[] = {\n", mach->prefix );
        for( j = 0; j < len; ++j ) {
            fprintf( fp, "    %d,\n", listl[ j ] );
        }
        fprintf( fp, "    -1\n" );
        fprintf( fp, "};\n" );
        free( listl );
    }
    fprintf( fp, "\nconst dis_selector DisSelectorTable[] = {\n" );
    for( i = 0; i < SelIndex; ++i ) {
        if( (i % 16) == 0 ) fprintf( fp, "/*%4.4x*/", i );
        fprintf( fp, "%4d,", SelTable[i] );
        if( (i % 16) == 15 ) fprintf( fp, "\n" );
    }
    fprintf( fp, "};\n" );
    fclose( fp );
    return( 0 );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?