예제 #1
0
static void getAsmLine( VBUF *buff )
{
    char line[256];

    if( endOfAsmStmt() )
        return;
    /* reserve at least MAX_INSTR_SIZE bytes in the buffer */
    VbufReqd( buff, ((AsmCodeAddress+MAX_INSTR_SIZE) + (MAX_INSTR_SIZE-1)) & ~(MAX_INSTR_SIZE-1) );
    AsmCodeBuffer = VbufBuffer( buff );
    ensureBufferReflectsCurToken();
    if( isId( CurToken ) && strcmp( Buffer, "__emit" ) == 0 ) {
        strcpy( line, AsmSysDefineByte() );
        strcat( line, " " );
        NextToken();
        ensureBufferReflectsCurToken();
    } else {
        line[0] = '\0';
    }
    for(;;) {
        if( endOfAsmStmt() ) break;
        strncat( line, Buffer, sizeof(line)-1 );
        switch( CurToken ) {
        case T_ALT_XOR:
        case T_ALT_EXCLAMATION:
        case T_ALT_AND_AND:
        case T_ALT_OR_OR:
            strncat( line, " ", sizeof(line)-1 );
            break;
        default:
            if( isId( CurToken ) )
                strncat( line, " ", sizeof(line)-1 );
            break;
        }
        NextToken();
        ensureBufferReflectsCurToken();
    }
    if( line[0] != '\0' ) {
        AsmLine( line );
    }
    VbufSetLen( buff, AsmCodeAddress );
    if( CurToken == T_SEMI_COLON ) {
        // ; .ASM comment
        for(;;) {
            NextToken();
            if( CurToken == T_EOF ) break;
            if( CurToken == T_NULL ) break;
        }
    }
}
예제 #2
0
static int insertFixups( VBUF *src_code )
{
    struct asmfixup     *fix;
    struct asmfixup     *head;
    struct asmfixup     *chk;
    struct asmfixup     *next;
    struct asmfixup     **owner;
    unsigned char       *src;
    unsigned char       *src_start;
    unsigned char       *src_end;
    unsigned char       cg_fix;
    bool                perform_fixups;
    byte_seq            *seq;
    SYMBOL              sym;
    NAME                name;
    unsigned char       *dst;
    byte_seq_len        len;
    unsigned            skip;
    int                 mutate_to_segment;
    bool                uses_auto;
#if _CPU == 8086
    int                 fixup_padding;
#endif
    VBUF                out_code;

    uses_auto = FALSE;
    perform_fixups = FALSE;
    head = FixupHead;
    if( head == NULL ) {
        out_code = *src_code;
    } else {
        VbufInit( &out_code );
        FixupHead = NULL;
        /* sort the fixup list in increasing fixup_loc's */
        for( fix = head; fix != NULL; fix = next ) {
            owner = &FixupHead;
            for( ;; ) {
                chk = *owner;
                if( chk == NULL ) break;
                if( chk->fixup_loc > fix->fixup_loc ) break;
                owner = &chk->next;
            }
            next = fix->next;
            fix->next = *owner;
            *owner = fix;
        }
        len = 0;
        cg_fix = 0;
        sym = NULL;
        src_start = VbufBuffer( src_code );
        src_end = src_start + VbufLen( src_code );
        fix = FixupHead;
        owner = &FixupHead;
        /* insert fixup escape sequences */
        for( src = src_start; src < src_end; ) {
            /* reserve at least ASM_BLOCK bytes in the buffer */
            VbufReqd( &out_code, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) );
            dst = VbufBuffer( &out_code );
            if( fix != NULL && fix->fixup_loc == (src - src_start) ) {
                name = NULL;
                if( fix->name != NULL ) {
                    name = NameCreateNoLen( fix->name );
                    sym = ScopeASMUseSymbol( name, &uses_auto );
                    if( sym == NULL ) {
                        return( 0 );
                    }
                }
                /* insert fixup information */
                skip = 0;
                dst[len++] = FLOATING_FIXUP_BYTE;
                mutate_to_segment = 0;
#if _CPU == 8086
                fixup_padding = 0;
#endif
                switch( fix->fixup_type ) {
                case FIX_FPPATCH:
                    dst[len++] = fix->offset;
                    break;
                case FIX_SEG:
                    if( name == NULL ) {
                        // special case for floating point fixup
                        if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) {
                           // inline assembler FWAIT instruction 0x90, 0x9b
                            dst[len++] = FIX_FPP_WAIT;
                        } else if( src[0] == 0x9b && (src[1] & 0xd8) == 0xd8 ) {
                           // FWAIT as first byte and FPU instruction opcode as second byte
                            dst[len++] = FIX_FPP_NORMAL;
                        } else if( src[0] == 0x9b && (src[2] & 0xd8) == 0xd8 ) {
                           // FWAIT as first byte and FPU instruction opcode as third byte
                           // second byte should be segment override prefix
                            switch( src[1] ) {
                            case PREFIX_ES: dst[len++] = FIX_FPP_ES;    break;
                            case PREFIX_CS: dst[len++] = FIX_FPP_CS;    break;
                            case PREFIX_SS: dst[len++] = FIX_FPP_SS;    break;
                            case PREFIX_DS: dst[len++] = FIX_FPP_DS;    break;
                            case PREFIX_GS: dst[len++] = FIX_FPP_GS;    break;
                            case PREFIX_FS: dst[len++] = FIX_FPP_FS;    break;
                            default: --len; break;  // skip FP patch
                            }
                        } else {
                            // skip FP patch
                            --len;
                        }
                    } else {
                        skip = 2;
                        cg_fix = FIX_SYM_SEGMENT;
                    }
                    break;
                case FIX_RELOFF16:
                    skip = 2;
                    cg_fix = FIX_SYM_RELOFF;
                    break;
                case FIX_RELOFF32:
                    skip = 4;
                    cg_fix = FIX_SYM_RELOFF;
#if _CPU == 8086
                    fixup_padding = 1;
#endif
                    break;
                case FIX_PTR16:
                    mutate_to_segment = 1;
                    /* fall through */
                case FIX_OFF16:
                    skip = 2;
                    cg_fix = FIX_SYM_OFFSET;
                    break;
                case FIX_PTR32:
                    mutate_to_segment = 1;
                    /* fall through */
                case FIX_OFF32:
                    skip = 4;
                    cg_fix = FIX_SYM_OFFSET;
#if _CPU == 8086
                    fixup_padding = 1;
#endif
                    break;
                default:
                    CErr2p( ERR_ASSEMBLER_ERROR, "cannot reach label" );
                    break;
                }
                if( skip != 0 ) {
                    dst[len++] = cg_fix;
                    *((BYTE_SEQ_SYM *)&dst[len]) = sym;
                    len += sizeof( BYTE_SEQ_SYM );
                    *((BYTE_SEQ_OFF *)&dst[len]) = fix->offset;
                    len += sizeof( BYTE_SEQ_OFF );
                    src += skip;
                }
#if _CPU == 8086
                if( fixup_padding ) {
                    // add offset fixup padding to 32-bit
                    // cg create only 16-bit offset fixup
                    dst[len++] = 0;
                    dst[len++] = 0;
                    //
                }
#endif
                if( mutate_to_segment ) {
                    /*
                        Since the CG escape sequences don't allow for
                        FAR pointer fixups, we have to split them into two.
                        This is done by doing the offset fixup first, then
                        mutating the fixup structure to look like a segment
                        fixup one near pointer size later.
                    */
                    fix->fixup_type = FIX_SEG;
                    fix->fixup_loc += skip;
                    fix->offset = 0;
                } else {
                    head = fix;
                    fix = fix->next;
                    if( head->external ) {
                        *owner = fix;
                        CMemFree( head->name );
                        CMemFree( head );
                    } else {
                        owner = &head->next;
                    }
                }
            } else {
                if( *src == FLOATING_FIXUP_BYTE ) {
                    dst[len++] = FLOATING_FIXUP_BYTE;
                }
                dst[len++] = *src++;
            }
            VbufSetLen( &out_code, len );
        }
        perform_fixups = TRUE;
    }
    len = VbufLen( &out_code );
    seq = CMemAlloc( offsetof( byte_seq, data ) + len );
    seq->relocs = perform_fixups;
    seq->length = len;
    memcpy( seq->data, VbufBuffer( &out_code ), len );
    CurrInfo->code = seq;
    if( VbufBuffer( &out_code ) != VbufBuffer( src_code ) )
        VbufFree( &out_code );
    return( uses_auto );
}
예제 #3
0
static int GetByteSeq( void )
{
    int             len;
    char            *name;
    unsigned        offset;
    unsigned        fixword;
    int             uses_auto;
    VBUF            code_buffer;
#if _CPU == 8086
    bool            use_fpu_emu = FALSE;
#endif

    VbufInit( &code_buffer );
    AsmSysInit();
    PPCTL_ENABLE_MACROS();
    NextToken();
    len = 0;
    offset = 0;
    name = NULL;
    for( ;; ) {
        /* reserve at least ASM_BLOCK bytes in the buffer */
        VbufReqd( &code_buffer, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) );
        if( CurToken == T_STRING ) {
            AsmCodeAddress = len;
            AsmCodeBuffer = VbufBuffer( &code_buffer );
#if _CPU == 8086
            AsmLine( Buffer, use_fpu_emu );
            use_fpu_emu = FALSE;
#else
            AsmLine( Buffer, FALSE );
#endif
            len = AsmCodeAddress;
            NextToken();
            if( CurToken == T_COMMA ) {
                NextToken();
            }
        } else if( CurToken == T_CONSTANT ) {
#if _CPU == 8086
            if( use_fpu_emu ) {
                AddAFix( len, NULL, FIX_SEG, 0 );
                use_fpu_emu = FALSE;
            }
#endif
            VbufBuffer( &code_buffer )[ len++ ] = U32Fetch( Constant64 );
            NextToken();
        } else {
#if _CPU == 8086
            use_fpu_emu = FALSE;
#endif
            fixword = FixupKeyword();
            if( fixword == FIXWORD_NONE )
                break;
            if( fixword == FIXWORD_FLOAT ) {
#if _CPU == 8086
                if( GET_FPU_EMU( CpuSwitches ) ) {
                    use_fpu_emu = TRUE;
                }
#endif
            } else { /* seg or offset */
                if( !IS_ID_OR_KEYWORD( CurToken ) ) {
                    CErr1( ERR_EXPECTING_ID );
                } else {
                    name = strsave( Buffer );
                    offset = 0;
                    NextToken();
                    if( CurToken == T_PLUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = U32Fetch( Constant64 );
                            NextToken();
                        }
                    } else if( CurToken == T_MINUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = - U32Fetch( Constant64 );
                            NextToken();
                        }
                    }
                }
                switch( fixword ) {
                case FIXWORD_RELOFF:
#if _CPU == 8086
                    AddAFix( len, name, FIX_RELOFF16, offset );
                    len += 2;
#else
                    AddAFix( len, name, FIX_RELOFF32, offset );
                    len += 4;
#endif
                    break;
                case FIXWORD_OFFSET:
#if _CPU == 8086
                    AddAFix( len, name, FIX_OFF16, offset );
                    len += 2;
#else
                    AddAFix( len, name, FIX_OFF32, offset );
                    len += 4;
#endif
                    break;
                case FIXWORD_SEGMENT:
                    AddAFix( len, name, FIX_SEG, 0 );
                    len += 2;
                    break;
                }
            }
        }
        VbufSetLen( &code_buffer, len );
    }
    PPCTL_DISABLE_MACROS();
    uses_auto = AsmSysInsertFixups( &code_buffer );
    AsmSysFini();
    VbufFree( &code_buffer );
    return( uses_auto );
}