i86splt2.c

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

C
1,063
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "pattern.h"
#include "regset.h"
#include "model.h"
#include "vergen.h"
#include "system.h"
#include "zoiks.h"
#include "cfloat.h"

typedef struct eight_byte_name {
        union name     *low;
        union name     *mid_low;
        union name     *mid_high;
        union name     *high;
} eight_byte_name;

extern  void            ChangeType(instruction*,type_class_def);
extern  name            *IntEquivalent(name*);
extern  void            DupSegOp(instruction*,instruction*,int);
extern  name            *AllocTemp(type_class_def);
extern  opcode_entry    *CodeTable(instruction*);
extern  bool            SameThing(name*,name*);
extern  instruction     *MakeConvert(name*,name*,type_class_def,type_class_def);
extern  instruction     *MoveConst(unsigned_32,name*,type_class_def);
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  constant_defn   *GetFloat(name*,type_class_def);
extern  void            UpdateLive(instruction*,instruction*);
extern  void            DupSegRes(instruction*,instruction*);
extern  void            MoveSegOp(instruction*,instruction*,int);
extern  instruction     *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern  void            SuffixIns(instruction*,instruction*);
extern  instruction     *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern  void            HalfType(instruction*);
extern  hw_reg_set      High32Reg(hw_reg_set);
extern  hw_reg_set      High16Reg(hw_reg_set);
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  name            *TempOffset(name*,type_length,type_class_def);
extern  hw_reg_set      Low32Reg(hw_reg_set);
extern  name            *AllocRegName(hw_reg_set);
extern  hw_reg_set      Low16Reg(hw_reg_set);
extern  name            *AddrConst(name*,int,constant_class);
extern  name            *AllocIntConst(int);
extern  name            *AllocUIntConst(uint);
extern  name            *AllocConst(pointer);
extern  instruction     *MakeCondition(opcode_defs,name*,name*,int,int,type_class_def);
extern  void            ReplIns(instruction*,instruction*);
extern  void            PrefixIns(instruction*,instruction*);
extern  void            DupSeg(instruction*,instruction*);
extern  void            DoNothing(instruction*);
extern  name            *SegName(name*);
extern  void            DelSeg(instruction*);
extern  name            *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern  name            *AllocIntConst(int);
extern  bool            Overlaps( name *, name * );
extern  instruction     *MakeNop(void);

/*forward declaration*/
static  void            Split8Name( instruction *ins, name *tosplit, eight_byte_name *out );

extern    type_class_def        HalfClass[];
extern    type_class_def        Unsigned[];

extern  name    *LowPart( name *tosplit, type_class_def class ) {
/************************************************************/

    name                *new = NULL;
    name                *new_cons;
    signed_8            s8;
    unsigned_8          u8;
    signed_16           s16;
    unsigned_16         u16;
    unsigned_32         u32;
    constant_defn       *floatval;

    switch( tosplit->n.class ) {
    case N_CONSTANT:
        if( tosplit->c.const_type == CONS_ABSOLUTE ) {
            if( class == U1 ) {
                u8 = tosplit->c.int_value & 0xff;
                new = AllocUIntConst( u8 );
            } else if( class == I1 ) {
                s8 = tosplit->c.int_value & 0xff;
                new = AllocIntConst( s8 );
            } else if( class == U2 ) {
                u16 = tosplit->c.int_value & 0xffff;
                new = AllocUIntConst( u16 );
            } else if( class == I2 ) {
                s16 = tosplit->c.int_value & 0xffff;
                new = AllocIntConst( s16 );
            } else if( class == FL ) {
                _Zoiks( ZOIKS_125 );
            } else { /* FD */
                floatval = GetFloat( tosplit, FD );
                u32 = (unsigned_32)floatval->value[ 1 ] << 16;
                u32 += floatval->value[ 0 ];
                new = AllocConst( CFCnvU32F( _TargetLongInt( u32 ) ) );
            }
        } else if( tosplit->c.const_type == CONS_ADDRESS ) {
            new = AddrConst( tosplit->c.value,
                                   tosplit->c.int_value, CONS_OFFSET );
        } else {
            _Zoiks( ZOIKS_044 );
        }
        break;
    case N_REGISTER:
        if( class == U1 || class == I1 ) {
            new = AllocRegName( Low16Reg( tosplit->r.reg ) );
        } else {
            new = AllocRegName( Low32Reg( tosplit->r.reg ) );
        }
        break;
    case N_TEMP:
        new = TempOffset( tosplit, 0, class );
        if( new->t.temp_flags & CONST_TEMP ) {
            if( tosplit->n.name_class == FS ) {
                new_cons = IntEquivalent( tosplit->v.symbol );
            } else {
                new_cons = tosplit->v.symbol;
            }
            new->v.symbol = LowPart( new_cons, class );
        }
        break;
    case N_MEMORY:
        new = AllocMemory( tosplit->v.symbol, tosplit->v.offset,
                                tosplit->m.memory_type, class );
        new->v.usage = tosplit->v.usage;
        break;
    case N_INDEXED:
        new = ScaleIndex( tosplit->i.index, tosplit->i.base,
                                tosplit->i.constant, class, 0, tosplit->i.scale,
                                tosplit->i.index_flags );
        break;
    default:
        break;
    }
    return( new );
}


extern  name    *HighPart( name *tosplit, type_class_def class ) {
/*************************************************************/

    name                *new = NULL;
    name                *new_cons;
    name                *op;
    signed_8            s8;
    unsigned_8          u8;
    signed_16           s16;
    unsigned_16         u16;
    unsigned_32         u32;
    constant_defn       *floatval;

    switch( tosplit->n.class ) {
    case N_CONSTANT:
        if( tosplit->c.const_type == CONS_ABSOLUTE ) {
            if( class == U1 ) {
                u8 = ( tosplit->c.int_value >> 8 ) & 0xff;
                new = AllocUIntConst( u8 );
            } else if( class == I1 ) {
                s8 = ( tosplit->c.int_value >> 8 ) & 0xff;
                new = AllocIntConst( s8 );
            } else if( class == U2 ) {
                u16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
                new = AllocUIntConst( u16 );
            } else if( class == I2 ) {
                s16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
                new = AllocIntConst( s16 );
            } else if( class == FL ) {
                _Zoiks( ZOIKS_125 );
            } else { /* FD */
                floatval = GetFloat( tosplit, FD );
                u32 = (unsigned_32)floatval->value[ 3 ] << 16;
                u32 += floatval->value[ 2 ];
                new = AllocConst( CFCnvU32F( _TargetLongInt( u32 ) ) );
            }
        } else if( tosplit->c.const_type == CONS_ADDRESS ) {
            new = AddrConst( tosplit->c.value,
                                   tosplit->c.int_value, CONS_SEGMENT );
        } else {
            _Zoiks( ZOIKS_044 );
        }
        break;
    case N_REGISTER:
        if( class == U1 || class == I1 ) {
            new = AllocRegName( High16Reg( tosplit->r.reg ) );
        } else {
            new = AllocRegName( High32Reg( tosplit->r.reg ) );
        }
        break;
    case N_TEMP:
        new = TempOffset( tosplit, tosplit->n.size/2, class );
        if( new->t.temp_flags & CONST_TEMP ) {
            if( tosplit->n.name_class == FS ) {
                new_cons = IntEquivalent( tosplit->v.symbol );
            } else {
                new_cons = tosplit->v.symbol;
            }
            op = HighPart( new_cons, class );
            if( op->n.class == N_REGISTER ) return( op );
            new->v.symbol = op;
        }
        break;
    case N_MEMORY:
        new = AllocMemory( tosplit->v.symbol,
                                tosplit->v.offset + tosplit->n.size/2,
                                tosplit->m.memory_type, class );
        new->v.usage = tosplit->v.usage;
        break;
    case N_INDEXED:
        new = ScaleIndex( tosplit->i.index, tosplit->i.base,
                tosplit->i.constant+ tosplit->n.size/2, class, 0,
                tosplit->i.scale, tosplit->i.index_flags );
        break;
    default:
        break;
    }
    return( new );
}


extern  name    *OffsetPart( name *tosplit ) {
/********************************************/

    return( LowPart( tosplit, U2 ) );
}


extern  name    *SegmentPart( name *tosplit ) {
/********************************************/

    return( HighPart( tosplit, U2 ) );
}


extern  instruction     *SplitUnary( instruction *ins ) {
/*******************************************************/

    instruction *new_ins;
    name        *high_res;
    name        *low_res;

    HalfType( ins );
    if( ins->result == NULL ) {
        high_res = NULL;
        low_res = NULL;
    } else {
        high_res = HighPart( ins->result, ins->type_class );
        low_res  = LowPart( ins->result, ins->type_class );
    }
    new_ins = MakeUnary( ins->head.opcode,
                         LowPart( ins->operands[ 0 ], ins->type_class ),
                         low_res, ins->type_class );
    ins->operands[ 0 ] = HighPart( ins->operands[ 0 ],ins->type_class );
    ins->result = high_res;
    if( ins->head.opcode == OP_PUSH ) {
        DupSeg( ins, new_ins );
        SuffixIns( ins, new_ins );
        new_ins = ins;
    } else {
        DupSeg( ins, new_ins );
        PrefixIns( ins, new_ins );
    }
    return( new_ins );
}

static  instruction     *SplitOverlapped( instruction *ins, int op ) {
/********************************************************************/

/* Used to split 8 byte operation because of overlap problems */

    instruction         *move;
    name                *tmp;

    tmp = AllocTemp( ins->type_class );
    move = MakeMove( ins->operands[op], tmp, ins->type_class );
    MoveSegOp( ins, move, op );
    ins->operands[op] = tmp;
    PrefixIns( ins, move );
    UpdateLive( move, ins );
    return( move );
}

extern  instruction     *rMOVE8LOW( instruction *ins ) {
/*****************************************************/

/*   Move low 4 bytes of 8 byte thingy */

    instruction         *lo_ins;
    instruction         *mid_lo_ins;
    eight_byte_name     result;
    eight_byte_name     left;

    if( Overlaps( ins->result, ins->operands[ 0 ] ) ) {
        return( SplitOverlapped( ins, 0 ) );
    }
    Split8Name( ins, ins->operands[ 0 ], &left );
    Split8Name( ins, ins->result, &result );
    lo_ins = MakeUnary( ins->head.opcode, left.low, result.low, U2 );
    mid_lo_ins = MakeUnary( ins->head.opcode, left.mid_low, result.mid_low, U2 );
    DupSeg( ins, lo_ins );
    DupSeg( ins, mid_lo_ins );
    PrefixIns( ins, lo_ins );
    ReplIns( ins, mid_lo_ins );
    UpdateLive( lo_ins, mid_lo_ins );
    return( lo_ins );
}

extern  instruction     *rSPLIT8( instruction *ins ) {
/***************************************************/

/*   Used to split 8 byte push, pop and move*/

    opcode_defs         op;
    instruction         *lo_ins;
    instruction         *mid_lo_ins;
    instruction         *mid_hi_ins;
    instruction         *hi_ins;
    instruction         *first_ins;
    instruction         *last_ins;
    eight_byte_name     result;
    eight_byte_name     left;

⌨️ 快捷键说明

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