instruction *rMOVOP1TEMP( instruction *ins ) /**********************************************/ { instruction *new_ins; type_class_def type_class; name *name; type_class = _OpClass( ins ); name = AllocTemp( type_class ); new_ins = MakeMove( ins->operands[0], name, type_class ); ins->operands[0] = name; MoveSegOp( ins, new_ins, 0 ); PrefixIns( ins, new_ins ); return( new_ins ); }
instruction *rOP2REG( instruction *ins ) /*******************************************/ { instruction *new_ins; name *name1; type_class_def type_class; type_class = _OpClass( ins ); name1 = AllocTemp( type_class ); new_ins = MakeMove( ins->operands[1], name1, type_class ); ins->operands[1] = name1; MoveSegOp( ins, new_ins, 0 ); PrefixIns( ins, new_ins ); MarkPossible( ins, name1, Op1Possible( ins ) ); ins->u.gen_table = NULL; GiveRegister( NameConflict( ins, name1 ), true ); return( new_ins ); }
instruction *rOP1RESREG( instruction *ins ) /**********************************************/ { instruction *new_ins; instruction *ins2; name *name1; name *name2; name1 = AllocRegName( Op1Reg( ins ) ); new_ins = MakeMove( ins->operands[0], name1, _OpClass( ins ) ); ins->operands[0] = name1; MoveSegOp( ins, new_ins, 0 ); PrefixIns( ins, new_ins ); name2 = AllocRegName( ResultReg( ins ) ); ins2 = MakeMove( name2, ins->result, ins->type_class ); ins->result = name2; MoveSegRes( ins, ins2 ); SuffixIns( ins, ins2 ); return( new_ins ); }
static instruction *FoldAbsolute( instruction *ins ) { /********************************************************* See below. */ instruction *new_ins; opcnt num_operands; name *result; tn fold; type_def *tipe; type_def *left_tipe; type_def *rite_tipe; type_def *fold_tipe; pointer left; pointer rite; name *tmp; name *new_const; float_handle value; tipe = ClassType( ins->type_class ); left_tipe = ClassType( _OpClass( ins ) ); num_operands = OpcodeNumOperands( ins ); left = NULL; rite = NULL; if( num_operands != 0 ) { left = TName( ins->operands[0], left_tipe ); if( num_operands > 1 ) { if( ins->operands[1]->n.type_class == XX ) { rite_tipe = tipe; } else { rite_tipe = ClassType( ins->operands[1]->n.type_class ); } rite = TName( ins->operands[1], rite_tipe ); } } fold = NULL; switch( ins->head.opcode ) { case OP_ADD: fold = FoldPlus( left, rite, tipe ); break; case OP_SUB: fold = FoldMinus( left, rite, tipe ); break; case OP_MUL: fold = FoldTimes( left, rite, tipe ); break; case OP_DIV: fold = FoldDiv( left, rite, tipe ); break; case OP_MOD: fold = FoldMod( left, rite, tipe ); break; case OP_AND: fold = FoldAnd( left, rite, tipe ); break; case OP_OR: fold = FoldOr( left, rite, tipe ); break; case OP_XOR: fold = FoldXor( left, rite, tipe ); break; case OP_RSHIFT: fold = FoldRShift( left, rite, tipe ); break; case OP_LSHIFT: fold = FoldLShift( left, rite, tipe ); break; case OP_NEGATE: fold = FoldUMinus( left, tipe ); break; case OP_COMPLEMENT: fold = Fold1sComp( left, tipe ); break; case OP_CONVERT: // look out for CNV PT U2 t1 type instructions; if sizeof( PT ) is greater // than sizeof( U2 ), we don't want to fold or we'll screw up based pointers if( IsTrickyPointerConv( ins ) ) return( NULL ); // fall through! case OP_ROUND: fold = FoldCnvRnd( (cg_op)ins->head.opcode, left, tipe ); break; case OP_CMP_EQUAL: case OP_CMP_NOT_EQUAL: case OP_CMP_GREATER: case OP_CMP_LESS_EQUAL: case OP_CMP_LESS: case OP_CMP_GREATER_EQUAL: if( ActiveCompare( ins ) ) { fold = FoldCompare( (cg_op)ins->head.opcode, left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, true ) ); } } break; case OP_BIT_TEST_TRUE: if( ActiveCompare( ins ) ) { fold = FoldAnd( left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, true ) ); } } break; case OP_BIT_TEST_FALSE: if( ActiveCompare( ins ) ) { fold = FoldAnd( left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, false ) ); } } break; default: fold = NULL; break; } if( fold != NULL ) { fold_tipe = fold->tipe; result = TGetName( fold ); if( result != NULL && !NeedConvert( fold_tipe, tipe ) ) { ins->table = NULL; // look out for scary DIV U4 EDX:EAX, c1 -> t1 type instructions if( result->n.class != N_CONSTANT && result->n.size != TypeClassSize[ins->type_class] ) return( NULL ); // look out for scary MUL U4 EDX:EAX, c1 -> t1 type instructions if( result->n.class != N_CONSTANT && ins->result->n.size != TypeClassSize[ins->type_class] ) return( NULL ); new_ins = MakeMove( result, ins->result, ins->type_class ); SetCSEBits( ins, new_ins ); DupSeg( ins, new_ins ); ReplIns( ins, new_ins ); return( new_ins ); }
static void ExpandTlsOp( instruction *ins, name **pop ) /********************************************************** If *pop is a ref to a piece of thread-local data, replace it by a ref to an index [t1] and prepend the magic sequence to get the address of a piece of tls data to the instruction. Here is the sequence to access variable foo: mov fs:__tls_array -> t1 mov __tls_index -> t2 mov t2 * 4 -> t2 add t1, t2 -> t1 mov [ t1 ] -> t3 mov foo[ t3 ] -> result */ { fe_attr attr; name *op; name *temp; name *tls_data; name *index; name *base; instruction *new_ins; op = *pop; switch( op->n.class ) { case N_MEMORY: if( op->m.memory_type == CG_FE ) { attr = FEAttr( op->v.symbol ); if( ( attr & FE_THREAD_DATA ) != 0 ) { *pop = GetTLSDataRef( ins, op, _OpClass(ins) ); } } break; case N_INDEXED: // gotta check for the base being one of these stupid TLS things if( op->i.base != NULL && ( op->i.index_flags & X_FAKE_BASE ) == 0 ) { base = op->i.base; if( base->n.class != N_MEMORY || base->m.memory_type != CG_FE ) break; attr = FEAttr( base->v.symbol ); if( ( attr & FE_THREAD_DATA ) == 0 ) break; tls_data = GetTLSDataRef( ins, base, _OpClass(ins) ); temp = AllocTemp( WD ); new_ins = MakeUnary( OP_LA, tls_data, temp, WD ); PrefixIns( ins, new_ins ); index = op->i.index; if( op->i.scale != 0 ) { const signed_32 values[] = { 1, 2, 4, 8, 16 }; if( op->i.scale > 4 ) _Zoiks( ZOIKS_134 ); index = AllocTemp( WD ); new_ins = MakeBinary( OP_MUL, op->i.index, AllocS32Const( values[ op->i.scale ] ), index, WD ); PrefixIns( ins, new_ins ); } new_ins = MakeBinary( OP_ADD, temp, index, temp, WD ); PrefixIns( ins, new_ins ); *pop = ScaleIndex( temp, NULL, 0, _OpClass(ins), TypeClassSize[ _OpClass(ins) ], 0, 0 ); } break; }