ppcenc.c

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

C
973
字号
/****************************************************************************
*
*                            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:  PowerPC instruction encoding.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "pattern.h"
#include "symdbg.h"
#include "vergen.h"
#include "reloc.h"
#include "offset.h"
#include "optopts.h"
#include "optlbl.h"
#include "zoiks.h"
#include "model.h"
#include "coff.h"
#include "procdef.h"
#include "cgaux.h"
#include "ppcenc.h"
#include "ppcgen.h"
#include <assert.h>
#include <stdio.h>

extern void DumpInsOnly( instruction * );
extern void DumpString( char * );
extern void DumpPtr( pointer );
extern void DumpInt( int );
extern void DumpNL( void );
extern void DumpGen( struct opcode_entry * );
extern void DumpPtr( void *ptr );

extern void             ObjBytes( char *buffer, int size );
extern uint_8           RegTrans( hw_reg_set );
extern void             OutLabel( label_handle );
extern void             OutReloc( label_handle, ppc_reloc, unsigned );
extern pointer          AskForSymLabel( pointer, cg_class );
extern hw_reg_set       StackReg( void );
extern hw_reg_set       FrameReg( void );
extern name             *DeAlias( name * );
extern void             TryScrapLabel( code_lbl * );
extern void             DbgBlkBeg( dbg_block *blk, offset lc );
extern void             DbgBlkEnd( dbg_block *blk, offset lc );
extern offset           AskLocation( void );
extern void             OutLineNum( unsigned_16 line, bool label_line );
extern void             EmitDbgInfo( instruction * );
extern pointer          FEAuxInfo( pointer *, aux_class );
extern code_lbl         *GetWeirdPPCDotDotLabel( code_lbl * );

extern type_class_def   Unsigned[];
extern type_length      TypeClassSize[];
extern proc_def         *CurrProc;

#define _NameReg( op )                  ( (op)->r.arch_index )
#define _IsSigned( type )               ( Unsigned[type] != type )
#define _Emit( ins )                    ObjBytes( (char *)&(ins), sizeof( ppc_ins ) )

#define ZERO_SINK       0
#define STACK_REG       1
#define TOC_REG         2
#define VOLATILE_REG    12

#pragma off (unreferenced);

#define _BinaryOpcode( a, b )           { { a, b }, { a, b } }
#define _SignedOpcode( a, b, c, d )     { { a, b }, { c, d } }

// Our table for opcode values is really a list of pairs of
// primary opcode / function code pairs. Their is two entries
// for each opcode in case the sign of the instruction matters;
// for example, for OP_RSHIFT we need to generate either srw or
// sraw. If the sign of the type of the instruction doesn't
// matter, we can just use the _BinaryOpcode macro to create
// identical cases, otherwise we give each pair explicitly.

static  opcode  BinaryOpcodes[][2][2] = {
        _BinaryOpcode( 31, 266 ),                       /* OP_ADD */
        _BinaryOpcode( 31, 266 ),                       /* OP_EXT_ADD */
        _BinaryOpcode( 31, 8 ),                         /* OP_SUB */
        _BinaryOpcode( 31, 8 ),                         /* OP_EXT_SUB */
        _BinaryOpcode( 31, 235 ),                       /* OP_MUL */
        _BinaryOpcode( 31, 235 ),                       /* OP_EXT_MUL */
        _SignedOpcode( 31, 459, 31, 491 ),              /* OP_DIV */
        _BinaryOpcode( 0, 0 ),                          /* OP_MOD */
        _BinaryOpcode( 31, 28 ),                        /* OP_AND */
        _BinaryOpcode( 31, 444 ),                       /* OP_OR */
        _BinaryOpcode( 31, 316 ),                       /* OP_XOR */
        _SignedOpcode( 31, 536, 31, 792 ),              /* OP_RSHIFT */
        _BinaryOpcode( 31, 24 ),                        /* OP_LSHIFT */
        _BinaryOpcode( 0, 0 ),                          /* OP_POW */
        _BinaryOpcode( 0, 0 ),                          /* OP_ATAN2 */
        _BinaryOpcode( 0, 0 ),                          /* OP_FMOD */
};

static  opcode  FPOpcodes[][2] = {
        { 63, 21 },                                     /* OP_ADD */
        { 63, 21 },                                     /* OP_EXT_ADD */
        { 63, 20 },                                     /* OP_SUB */
        { 63, 20 },                                     /* OP_EXT_SUB */
        { 63, 25 },                                     /* OP_MUL */
        { 63, 25 },                                     /* OP_EXT_MUL */
        { 63, 18 },                                     /* OP_DIV */
        { 0, 0 },                                       /* OP_MOD */
        { 0, 0 },                                       /* OP_AND */
        { 0, 0 },                                       /* OP_OR */
        { 0, 0 },                                       /* OP_XOR */
        { 0, 0 },                                       /* OP_RSHIFT */
        { 0, 0 },                                       /* OP_LSHIFT */
        { 0, 0 },                                       /* OP_POW */
        { 0, 0 },                                       /* OP_ATAN2 */
        { 0, 0 },                                       /* OP_FMOD */
};

static  opcode  BinaryImmedOpcodes[] = {
        14,                     /* OP_ADD */
        14,                     /* OP_EXT_ADD */
        8,                      /* OP_SUB */
        8,                      /* OP_EXT_SUB */
        7,                      /* OP_MUL */
        7,                      /* OP_EXT_MUL */
        0,                      /* OP_DIV */
        0,                      /* OP_MOD */
        28,                     /* OP_AND */
        24,                     /* OP_OR */
        26,                     /* OP_XOR */
        0,                      /* OP_RSHIFT */
        0,                      /* OP_LSHIFT */
        0,                      /* OP_POW */
        0,                      /* OP_ATAN2 */
        0,                      /* OP_FMOD */
};


static  opcode  *FindOpcodes( instruction *ins )
/**********************************************/
{
    opcode      *opcodes;

    if( _IsFloating( ins->type_class ) ) {
        opcodes = &FPOpcodes[ins->head.opcode - FIRST_BINARY_OP][0];
    } else {
        opcodes = &BinaryOpcodes[ins->head.opcode - FIRST_BINARY_OP][_IsSigned( ins->type_class )][0];
    }
    return( opcodes );
}


static  opcode  *FindImmedOpcodes( instruction *ins )
/***************************************************/
{
    opcode      *opcodes;

    opcodes = &BinaryImmedOpcodes[ins->head.opcode - FIRST_BINARY_OP];
    if( *opcodes == 0 ) {
        _Zoiks( ZOIKS_091 );
    }
    return( opcodes );
}


extern  void    GenFPOPINS( opcode op1, opcode op2, reg_index a, reg_index c, reg_index d )
//*****************************************************************************************
{
    ppc_ins             encoding;

    encoding = _Op1( op1 ) | _A( a ) | _C( c ) | _D( d ) | _Op2( op2 );
    _Emit( encoding );
}


extern  void    GenOPINS( opcode op1, opcode op2, reg_index a, reg_index b, reg_index s )
//***************************************************************************************
{
    ppc_ins             encoding;

    encoding = _Op1( op1 ) | _A( a ) | _B( b ) | _S( s ) | _Op2( op2 );
    _Emit( encoding );
}


extern  void    GenOPIMM( opcode op1, reg_index d, reg_index a, signed_16 immed )
//*******************************************************************************
{
    ppc_ins             encoding;

    encoding = _Op1( op1 ) | _D( d ) | _A( a ) | _SignedImmed( immed );
    _Emit( encoding );
}


extern  void    GenMTSPR( reg_index d, uint_32 spr, bool from )
//*************************************************************
{
    ppc_ins             encoding;

    encoding = _Op1( 31 ) | _Op2( 467 );
    if( from ) {
        encoding = _Op1( 31 ) | _Op2( 339 );
    }
    encoding |= _D( d ) | _SPR( spr );
    _Emit( encoding );
}


extern  void    GenMEMINS( opcode op, reg_index d, reg_index i, signed_16 displacement )
/**************************************************************************************/
{
    ppc_ins             encoding;

    encoding = _Op1( op ) | _D( d ) | _A( i ) | _SignedImmed( displacement );
    _Emit( encoding );
}


extern  void    GenBRANCH( opcode op, pointer label, bool link, bool absolute )
/*****************************************************************************/
{
    ppc_ins             encoding;
    int_32              loc;

    loc = AskLocation();
    encoding = _Op1( op ) | _AA( absolute ) | _LK( link ) | _BranchImmed( -loc );
    OutReloc( label, PPC_RELOC_BRANCH, 0 );
    _Emit( encoding );
}


extern  void    GenCONDBR( opcode op, opcode bo, opcode bi, pointer label )
/*************************************************************************/
{
    ppc_ins             encoding;

    encoding = _Op1( op ) | _S( bo ) | _A( bi );
    OutReloc( label, PPC_RELOC_BRANCH_COND, 0 );
    _Emit( encoding );
}


extern  void    GenCMP( opcode op, opcode op2, reg_index a, reg_index b )
/***********************************************************************/
{
    ppc_ins             encoding;

    encoding = _Op1( op ) | _A( a ) | _B( b ) | _Op2( op2 );
    _Emit( encoding );
}


extern  void    GenCMPIMM( opcode op, reg_index a, signed_16 imm )
/****************************************************************/
{
    ppc_ins             encoding;

    encoding = _Op1( op ) | _A( a ) | _SignedImmed( imm );
    _Emit( encoding );
}


extern  void    GenRAWINS( uint_32 encoding )
/*******************************************/
{
    _Emit( encoding );
}


static  pointer symLabel( name *mem )
/***********************************/
{
    return( AskForSymLabel( mem->v.symbol, mem->m.memory_type ) );
}


extern  type_length     TempLocation( name *temp )
/************************************************/
{
    name                *base;
    type_length         offset;

    assert( temp->n.class == N_TEMP );
    base = DeAlias( temp );
    if( base->t.location == NO_LOCATION ) {
        _Zoiks( ZOIKS_030 );
    }
    offset = CurrProc->targ.stack_map.locals.start;
    if( temp->t.temp_flags & STACK_PARM ) {
        offset = CurrProc->targ.frame_size + STACK_HEADER_SIZE;
    }
    return( offset + temp->t.location + temp->v.offset - base->v.offset );
}


static  void    doCall( instruction *ins )
/****************************************/
{
    pointer         sym;
    risc_byte_seq   *code;
    ppc_ins         encoding;
    code_lbl        *lbl;

⌨️ 快捷键说明

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