disppc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,470 行 · 第 1/3 页
C
1,470 行
/****************************************************************************
*
* 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: Instruction decoding for PowerPC architecture.
*
****************************************************************************/
#include <string.h>
#include <ctype.h>
#include "distypes.h"
#include "dis.h"
extern long SEX( unsigned long v, unsigned bit );
extern const dis_range PPCRangeTable[];
extern const int PPCRangeTablePos[];
extern const unsigned char PPCMaxInsName;
extern const unsigned short DisRegisterTable[];
#define MK_SPR(a,b) (((a)<<5)|(b))
// Macro to sort out operand position depending on endianness (needed to
// get disassembler to correctly process relocations - in big endian object
// files, 16-bit relocs are located two bytes past instruction start)
#ifdef __BIG_ENDIAN__
#define OP_POS( l, b ) (h->need_bswap ? l : b)
#else
#define OP_POS( l, b ) (h->need_bswap ? b : l)
#endif
#ifdef __BIG_ENDIAN__
typedef union {
struct {
unsigned_16 rB : 5;
// ---
unsigned_16 OE : 1;
unsigned_16 type1 : 3;
unsigned_16 mem : 4;
// reference types - only valid if memory = ?101
unsigned_16 type2 : 2;
unsigned_16 Rc : 1;
} math;
struct {
unsigned_16 third : 5;
unsigned_16 second : 5;
unsigned_16 first : 5;
unsigned_16 Rc : 1;
} general;
unsigned_16 immediate;
struct {
unsigned_16 BD : 14;
unsigned_16 AA : 1;
unsigned_16 LK : 1;
} branch;
struct {
unsigned_16 IMM : 4;
unsigned_16 morezero : 1;
unsigned_16 subcode : 10;
unsigned_16 zero : 1;
} condition;
struct {
unsigned_16 sh : 5;
unsigned_16 XO : 9;
unsigned_16 sh_5 : 1;
unsigned_16 Rc : 1;
} xs_form;
struct {
unsigned_16 sh : 5;
unsigned_16 mb : 6;
unsigned_16 XO : 3;
unsigned_16 sh_5 : 1;
unsigned_16 Rc : 1;
} md_form;
struct {
unsigned_16 first : 5;
unsigned_16 mb : 6;
unsigned_16 XO : 4;
unsigned_16 Rc : 1;
} mds_form;
} ppc_ins_lo;
typedef union {
struct {
unsigned_16 memory : 1;
unsigned_16 floating : 1;
// reference types - only valid if memory=1
unsigned_16 type : 3;
unsigned_16 update : 1;
unsigned_16 second : 5;
unsigned_16 first : 5;
// ---
} general;
struct {
unsigned_16 opcode : 6;
unsigned_16 morezero : 1;
unsigned_16 FM : 8;
unsigned_16 zero : 1;
} math;
struct {
unsigned_16 opcode : 6;
unsigned_16 crfD : 3;
unsigned_16 zero : 1;
unsigned_16 L : 1;
unsigned_16 rA : 5;
} compare;
struct {
unsigned_16 opcode : 6;
unsigned_16 crfD : 3;
unsigned_16 morezero : 2;
unsigned_16 crfS : 3;
unsigned_16 zero : 2;
} condition;
} ppc_ins_hi;
typedef union {
unsigned_32 full;
struct {
ppc_ins_hi hi;
ppc_ins_lo lo;
};
struct {
unsigned_32 opcode : 6;
unsigned_32 LI : 24;
unsigned_32 AA : 1;
unsigned_32 LK : 1;
} b;
struct {
unsigned_32 opcode : 6;
unsigned_32 rD : 5;
unsigned_32 lastzero : 1;
unsigned_32 CRM : 8;
unsigned_32 morezero : 1;
unsigned_32 subcode : 10;
unsigned_32 zero : 1;
} CRM;
} ppc_ins;
#else
typedef union {
struct {
unsigned_16 Rc : 1;
// reference types - only valid if memory = ?101
unsigned_16 type2 : 2;
unsigned_16 mem : 4;
unsigned_16 type1 : 3;
// ---
unsigned_16 OE : 1;
unsigned_16 rB : 5;
} math;
struct {
unsigned_16 Rc : 1;
unsigned_16 first : 5;
unsigned_16 second : 5;
unsigned_16 third : 5;
} general;
unsigned_16 immediate;
struct {
unsigned_16 LK : 1;
unsigned_16 AA : 1;
unsigned_16 BD : 14;
} branch;
struct {
unsigned_16 zero : 1;
unsigned_16 subcode : 10;
unsigned_16 morezero : 1;
unsigned_16 IMM : 4;
} condition;
struct {
unsigned_16 Rc : 1;
unsigned_16 sh_5 : 1;
unsigned_16 XO : 9;
unsigned_16 sh : 5;
} xs_form;
struct {
unsigned_16 Rc : 1;
unsigned_16 sh_5 : 1;
unsigned_16 XO : 3;
unsigned_16 mb : 6;
unsigned_16 sh : 5;
} md_form;
struct {
unsigned_16 Rc : 1;
unsigned_16 XO : 4;
unsigned_16 mb : 6;
unsigned_16 first : 5;
} mds_form;
} ppc_ins_lo;
typedef union {
struct {
unsigned_16 first : 5;
unsigned_16 second : 5;
// reference types - only valid if memory=1
unsigned_16 update : 1;
unsigned_16 type : 3;
unsigned_16 floating : 1;
unsigned_16 memory : 1;
// ---
} general;
struct {
unsigned_16 zero : 1;
unsigned_16 FM : 8;
unsigned_16 morezero : 1;
unsigned_16 opcode : 6;
} math;
struct {
unsigned_16 rA : 5;
unsigned_16 L : 1;
unsigned_16 zero : 1;
unsigned_16 crfD : 3;
unsigned_16 opcode : 6;
} compare;
struct {
unsigned_16 zero : 2;
unsigned_16 crfS : 3;
unsigned_16 morezero : 2;
unsigned_16 crfD : 3;
unsigned_16 opcode : 6;
} condition;
} ppc_ins_hi;
typedef union {
unsigned_32 full;
struct {
ppc_ins_lo lo;
ppc_ins_hi hi;
};
struct {
unsigned_32 LK : 1;
unsigned_32 AA : 1;
unsigned_32 LI : 24;
unsigned_32 opcode : 6;
} b;
struct {
unsigned_32 zero : 1;
unsigned_32 subcode : 10;
unsigned_32 morezero : 1;
unsigned_32 CRM : 8;
unsigned_32 lastzero : 1;
unsigned_32 rD : 5;
unsigned_32 opcode : 6;
} CRM;
} ppc_ins;
#endif
dis_handler_return PPCMath( dis_handle *h, void *d, dis_dec_ins *ins )
{
ppc_ins code;
code.full = ins->opcode;
ins->num_ops = 3;
ins->op[0].type = DO_REG;
ins->op[0].base = code.hi.general.second + DR_PPC_r0;
ins->op[1].type = DO_REG;
ins->op[1].base = code.hi.general.first + DR_PPC_r0;
ins->op[2].type = DO_REG;
ins->op[2].base = code.lo.math.rB + DR_PPC_r0;
if( code.lo.math.Rc ) {
ins->flags |= DIF_PPC_RC;
}
if( code.lo.math.OE ) {
ins->flags |= DIF_PPC_OE;
}
return( DHR_DONE );
}
dis_handler_return PPCMathb( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath( h, d, ins );
ins->num_ops = 1;
ins->op[0] = ins->op[2];
return( DHR_DONE );
}
dis_handler_return PPCMathd( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath( h, d, ins );
ins->num_ops = 1;
return( DHR_DONE );
}
dis_handler_return PPCMathab( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath( h, d, ins );
ins->num_ops = 2;
ins->op[0] = ins->op[1];
ins->op[1] = ins->op[2];
ins->flags &= ~DIF_PPC_OE;
return( DHR_DONE );
}
dis_handler_return PPCMathda( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath( h, d, ins );
ins->num_ops = 2;
if( ins->type == DI_PPC_clcs ) {
ins->flags &= ~DIF_PPC_OE;
}
return( DHR_DONE );
}
dis_handler_return PPCMathdb( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath( h, d, ins );
ins->num_ops = 2;
ins->op[1] = ins->op[2];
ins->flags &= ~DIF_PPC_OE;
return( DHR_DONE );
}
dis_handler_return PPCMath2( dis_handle *h, void *d, dis_dec_ins *ins )
// messy parameter ordering
{
dis_operand temp;
PPCMath( h, d, ins );
temp = ins->op[0];
ins->op[0] = ins->op[1];
ins->op[1] = temp;
ins->flags &= ~DIF_PPC_OE;
return( DHR_DONE );
}
dis_handler_return PPCMathsa( dis_handle *h, void *d, dis_dec_ins *ins )
{
PPCMath2( h, d, ins );
ins->num_ops = 2;
return( DHR_DONE );
}
dis_handler_return PPCImmediate( dis_handle *h, void *d, dis_dec_ins *ins )
{
ppc_ins code;
code.full = ins->opcode;
ins->num_ops = 3;
ins->op[0].type = DO_REG;
ins->op[0].base = code.hi.general.second + DR_PPC_r0;
ins->op[1].type = DO_REG;
ins->op[1].base = code.hi.general.first + DR_PPC_r0;
ins->op[2].type = DO_IMMED;
ins->op[2].op_position = OP_POS( 0, 2 );
switch( ins->type ) {
case DI_PPC_andi_dot:
case DI_PPC_andis_dot:
case DI_PPC_ori:
case DI_PPC_oris:
case DI_PPC_xori:
case DI_PPC_xoris: // These take unsigned values.
ins->op[2].value = code.lo.immediate;
break;
default:
ins->op[2].value = SEX(code.lo.immediate, 15 );
break;
}
return( DHR_DONE );
}
dis_handler_return PPCImmed2( dis_handle *h, void *d, dis_dec_ins *ins )
// messy parameter ordering
{
dis_operand temp;
PPCImmediate( h, d, ins );
temp = ins->op[0];
ins->op[0] = ins->op[1];
ins->op[1] = temp;
return( DHR_DONE );
}
static void PPCDoFloat( dis_dec_ins *ins, const int *order )
// extract float operands. order is null terminated array of integers as
// follows: (instruction format as numbered in the book)
// 0 15 31
// +-----+----+----+----+----+----++
// | | 1 | 2 | 3 | 4 | ||
// +-----+----+----+----+----+----++
{
ppc_ins code;
int operand;
code.full = ins->opcode;
for( operand=0; operand<4; operand++ ) {
if( order[operand] == 0 ) break;
ins->op[operand].type = DO_REG;
switch( order[operand] ) {
case 1:
ins->op[operand].base = code.hi.general.second + DR_PPC_f0;
break;
case 2:
ins->op[operand].base = code.hi.general.first + DR_PPC_f0;
break;
case 3:
ins->op[operand].base = code.lo.general.third + DR_PPC_f0;
break;
case 4:
ins->op[operand].base = code.lo.general.second + DR_PPC_f0;
break;
}
}
ins->num_ops = operand;
if( code.lo.general.Rc ) {
ins->flags |= DIF_PPC_RC;
}
}
dis_handler_return PPCFloat( dis_handle *h, void *d, dis_dec_ins *ins )
{
// note silly ordering of operands
const int order[5] = {1, 2, 4, 3, 0};
PPCDoFloat( ins, order );
return( DHR_DONE );
}
dis_handler_return PPCFloatdab( dis_handle *h, void *d, dis_dec_ins *ins )
{
const int order[4] = {1, 2, 3, 0};
PPCDoFloat( ins, order );
return( DHR_DONE );
}
dis_handler_return PPCFloatdac( dis_handle *h, void *d, dis_dec_ins *ins )
{
const int order[4] = {1, 2, 4, 0};
PPCDoFloat( ins, order );
return( DHR_DONE );
}
dis_handler_return PPCFloatCmpab( dis_handle *h, void *d, dis_dec_ins *ins )
{
const int order[4] = {1, 2, 3, 0};
ppc_ins code;
PPCDoFloat( ins, order );
code.full = ins->opcode;
ins->op[0].base = code.hi.compare.crfD + DR_PPC_cr0;
return( DHR_DONE );
}
dis_handler_return PPCFloatdb( dis_handle *h, void *d, dis_dec_ins *ins )
{
const int order[3] = {1, 3, 0};
PPCDoFloat( ins, order );
return( DHR_DONE );
}
dis_handler_return PPCFloato( dis_handle *h, void *d, dis_dec_ins *ins )
// Two obscure float instructions.
{
ppc_ins code;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?