ppcenc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 973 行 · 第 1/3 页
C
973 行
code = code;
sym = ins->operands[CALL_OP_ADDR]->v.symbol;
code = FEAuxInfo( sym, CALL_BYTES );
if( code != NULL ) {
ObjBytes( code->data, code->length );
} else {
lbl = symLabel( ins->operands[CALL_OP_ADDR] );
lbl = GetWeirdPPCDotDotLabel( lbl );
GenBRANCH( 18, lbl, TRUE, FALSE );
encoding = 0x60000000; // ..znop for linker thunk
OutReloc( lbl, PPC_RELOC_GLUE, 0 );
ObjBytes( (char *)&encoding, sizeof( ppc_ins ) );
}
}
static void getMemEncoding( name *mem, reg_index *index, int_16 *offset )
/***************************************************************************/
{
switch( mem->n.class ) {
case N_INDEXED:
assert( mem->i.index->n.class == N_REGISTER );
assert( mem->i.scale == 0 );
assert( mem->i.constant == (type_length)((signed_16)mem->i.constant) );
assert( ( mem->i.index_flags & X_LOW_ADDR_BASE ) == 0 );
*index = RegTrans( mem->i.index->r.reg );
*offset = (int_16)mem->i.constant;
break;
case N_TEMP:
*index = RegTrans( FrameReg() );
*offset = TempLocation( mem );
break;
case N_MEMORY:
default:
*index = ZERO_SINK;
*offset = 0;
_Zoiks( ZOIKS_119 );
break;
}
}
static opcode loadOpcodes[] = {
34, /* U1 */
34, /* I1 */
40, /* U2 */
42, /* I2 */
32, /* U4 */
32, /* I4 */
00, /* U8 */
00, /* I8 */
32, /* CP */
32, /* PT */
48, /* FS */
50, /* FD */
50, /* FL */
};
static opcode storeOpcodes[] = {
38, /* U1 */
38, /* I1 */
44, /* U2 */
44, /* I2 */
36, /* U4 */
36, /* I4 */
00, /* U8 */
00, /* I8 */
36, /* CP */
36, /* PT */
52, /* FS */
54, /* FD */
54, /* FL */
};
static void doLoadStore( instruction *ins, bool load )
/********************************************************/
{
name *mem;
name *reg;
opcode op;
reg_index index;
int_16 offset;
if( load ) {
mem = ins->operands[0];
reg = ins->result;
op = loadOpcodes[ins->type_class];
} else {
reg = ins->operands[0];
mem = ins->result;
op = storeOpcodes[ins->type_class];
}
assert( op != 0 );
assert( reg->n.class == N_REGISTER );
getMemEncoding( mem, &index, &offset );
GenMEMINS( op, RegTrans( reg->r.reg ), index, offset );
}
static void doSign( instruction *ins )
/****************************************/
{
switch( ins->base_type_class ) {
case U1:
case I1:
// extsb
GenOPINS( 31, 954, _NameReg( ins->result ), 0, _NameReg( ins->operands[0] ) );
break;
case U2:
case I2:
// extsh
GenOPINS( 31, 922, _NameReg( ins->result ), 0, _NameReg( ins->operands[0] ) );
break;
default:
_Zoiks( ZOIKS_091 );
}
}
static void doZero( instruction *ins )
/****************************************/
{
switch( ins->base_type_class ) {
case U1:
case I1:
// andi op1,0x00ff -> res
GenOPIMM( 28, _NameReg( ins->operands[0] ), _NameReg( ins->result ), 0x00ff );
break;
case U2:
case I2:
// andi op1,0xffff -> res
GenOPIMM( 28, _NameReg( ins->operands[0] ), _NameReg( ins->result ), 0xffff );
break;
default:
_Zoiks( ZOIKS_091 );
}
}
static void GenCallIndirect( instruction *call )
/**************************************************/
{
reg_index src;
reg_index reg;
reg_index mem_index;
int_16 mem_offset;
name *addr;
opcode ldw;
opcode stw;
reg = VOLATILE_REG; /* use the volatile scratch reg if possible */
src = VOLATILE_REG;
addr = call->operands[CALL_OP_ADDR];
ldw = loadOpcodes[U4];
stw = storeOpcodes[U4];
GenMEMINS( stw, TOC_REG, STACK_REG, 4 );
switch( addr->n.class ) {
case N_REGISTER:
src = _NameReg( addr );
break;
case N_TEMP:
case N_INDEXED:
getMemEncoding( addr, &mem_index, &mem_offset );
GenMEMINS( ldw, src, mem_index, mem_offset );
break;
}
GenMEMINS( ldw, TOC_REG, src, 4 ); // careful - src, reg could be same reg
GenMEMINS( ldw, reg, src, 0 );
GenMTSPR( reg, SPR_CTR, FALSE );
GenRAWINS( 0x4e9e0421 );
GenMEMINS( ldw, TOC_REG, STACK_REG, 4 );
}
static void GenVaStart( instruction *ins )
/********************************************/
{
opcode stb;
opcode stw;
opcode li;
reg_index reg;
reg_index tmp;
reg_index stack;
assert( ins->operands[0]->n.class == N_REGISTER );
reg = _NameReg( ins->operands[0] );
tmp = VOLATILE_REG;
stack = RegTrans( FrameReg() );
stb = storeOpcodes[U1];
stw = storeOpcodes[U4];
li = 14; // addi
GenOPIMM( li, tmp, ZERO_SINK, CurrProc->state.parm.gr );
GenMEMINS( stb, tmp, reg, 0 );
GenOPIMM( li, tmp, ZERO_SINK, CurrProc->state.parm.fr );
GenMEMINS( stb, tmp, reg, 1 );
GenOPIMM( li, tmp, stack, CurrProc->state.parm.offset + CurrProc->targ.frame_size + STACK_HEADER_SIZE );
GenMEMINS( stw, tmp, reg, 4 );
GenOPIMM( li, tmp, stack, CurrProc->targ.stack_map.saved_regs.start );
GenMEMINS( stw, tmp, reg, 8 );
}
static void DbgBlkInfo( instruction *ins )
/********************************************/
{
offset lc;
lc = AskLocation();
if( ins->flags.nop_flags & NOP_DBGINFO_START ) {
DbgBlkBeg( (dbg_block *)ins->operands[0], lc );
} else {
DbgBlkEnd( (dbg_block *)ins->operands[0], lc );
}
}
extern void GenRET( void )
/****************************/
{
ppc_ins encoding;
encoding = 0x4e800020; // FIXME - need linkage docs
_Emit( encoding );
}
static void Encode( instruction *ins )
/****************************************/
{
reg_index a; // usually used for the result
reg_index b;
reg_index s;
reg_index temp;
opcode op1;
opcode op2;
opcode *ops;
signed_16 mem_offset;
reg_index mem_index;
switch( ins->u.gen_table->generate ) {
case G_MOVE_FP:
assert( ins->result->n.class == N_REGISTER );
assert( ins->operands[0]->n.class == N_REGISTER );
GenOPINS( 63, 72, 0, _NameReg( ins->operands[0] ), _NameReg( ins->result ) );
break;
case G_MOVE:
// or op, op -> dst
assert( ins->result->n.class == N_REGISTER );
assert( ins->operands[0]->n.class == N_REGISTER );
b = _NameReg( ins->operands[0] );
GenOPINS( 31, 444, _NameReg( ins->result ), b, b );
break;
case G_LOAD:
case G_STORE:
doLoadStore( ins, ins->u.gen_table->generate == G_LOAD );
break;
case G_CALL:
doCall( ins );
break;
case G_LEA_HIGH:
assert( ins->operands[0]->n.class == N_CONSTANT );
assert( ins->operands[0]->c.const_type == CONS_HIGH_ADDR );
assert( ins->result->n.class == N_REGISTER );
/* addis k(r0) -> rn */
GenOPIMM( 15, _NameReg( ins->result ), ZERO_SINK, ins->operands[0]->c.int_value & 0xffff );
break;
case G_MOVE_UI:
/* a load of an unsigned 16-bit immediate */
/* use or rd, imm(r0) */
GenOPIMM( 24, _NameReg( ins->result ), ZERO_SINK, ins->operands[0]->c.int_value );
break;
case G_LEA:
assert( ins->operands[0]->n.class == N_CONSTANT );
assert( ins->result->n.class == N_REGISTER );
switch( ins->operands[0]->c.const_type ) {
case CONS_ABSOLUTE:
// addi rd, imm(r0)
GenOPIMM( 14, _NameReg( ins->result ), ZERO_SINK, ins->operands[0]->c.int_value );
break;
case CONS_LOW_ADDR:
case CONS_HIGH_ADDR:
case CONS_OFFSET:
case CONS_ADDRESS:
_Zoiks( ZOIKS_028 );
break;
}
break;
case G_LOAD_ADDR:
switch( ins->operands[0]->n.class ) {
case N_INDEXED:
case N_TEMP:
assert( ins->result->n.class == N_REGISTER );
getMemEncoding( ins->operands[0], &mem_index, &mem_offset );
// addi rd,off(ri|sp)
GenOPIMM( 14, _NameReg( ins->result ), mem_index, mem_offset );
break;
case N_MEMORY:
assert( ins->result->n.class == N_REGISTER );
OutReloc( symLabel( ins->operands[0] ), PPC_RELOC_TOC_OFFSET, 2 );
GenMEMINS( 32, _NameReg( ins->result ), TOC_REG, 0 );
break;
default:
_Zoiks( ZOIKS_119 );
}
break;
case G_BINARY_FP:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->operands[1]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
if( ins->head.opcode == OP_MUL ) {
ops = FindOpcodes( ins );
GenFPOPINS( ops[0], ops[1],
_NameReg( ins->operands[0] ),
_NameReg( ins->operands[1] ),
_NameReg( ins->result ) );
break;
}
/* fall through */
case G_BINARY:
assert( ins->operands[0]->n.class == N_REGISTER );
assert( ins->operands[1]->n.class == N_REGISTER );
assert( ins->result->n.class == N_REGISTER );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?