parent
332f9e4d2e
commit
e846560010
@ -1,50 +1,77 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
lifter_callback_t addq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = rtn->pop( 8 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 8, t3 );
|
||||
|
||||
// TODO: compute and update RFLAGS...
|
||||
// do the updating here on rtn->flags before we push it...
|
||||
//
|
||||
//
|
||||
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
lifter_callback_t adddw = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 4 );
|
||||
auto t2 = rtn->pop( 4 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 4, t3 );
|
||||
|
||||
// TODO: compute and update RFLAGS...
|
||||
// do the updating here on rtn->flags before we push it...
|
||||
//
|
||||
//
|
||||
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
lifter_callback_t addw = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 2 );
|
||||
auto t2 = rtn->pop( 2 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 2, t3 );
|
||||
|
||||
// TODO: compute and update RFLAGS...
|
||||
// do the updating here on rtn->flags before we push it...
|
||||
//
|
||||
//
|
||||
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
} // namespace vmp2::lifters
|
||||
vm::llvm_value_t *lifters_t::add_flags( vm::vmp_rtn_t *rtn, std::uint8_t byte_size, vm::llvm_value_t *lhs,
|
||||
vm::llvm_value_t *rhs )
|
||||
{
|
||||
auto op_size = llvm::IntegerType::get( *rtn->llvm_ctx, byte_size * 8 );
|
||||
std::vector< llvm::Type * > intrinsic_arg_types;
|
||||
intrinsic_arg_types.push_back( op_size );
|
||||
intrinsic_arg_types.push_back( op_size );
|
||||
|
||||
auto sadd_with_overflow = llvm::Intrinsic::getDeclaration(
|
||||
rtn->llvm_module, llvm::Intrinsic::sadd_with_overflow, intrinsic_arg_types );
|
||||
auto uadd_with_overflow = llvm::Intrinsic::getDeclaration(
|
||||
rtn->llvm_module, llvm::Intrinsic::uadd_with_overflow, intrinsic_arg_types );
|
||||
|
||||
auto u_add = rtn->ir_builder->CreateCall( uadd_with_overflow, { lhs, rhs } );
|
||||
auto u_sum = rtn->ir_builder->CreateExtractValue( u_add, { 0 } );
|
||||
auto u_of_bit = rtn->ir_builder->CreateExtractValue( u_add, { 1 } );
|
||||
auto cf = rtn->ir_builder->CreateZExt( u_of_bit, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ) );
|
||||
|
||||
auto s_add = rtn->ir_builder->CreateCall( sadd_with_overflow, { lhs, rhs } );
|
||||
auto s_sum = rtn->ir_builder->CreateExtractValue( s_add, { 0 } );
|
||||
auto s_of_bit = rtn->ir_builder->CreateExtractValue( s_add, { 1 } );
|
||||
auto of = rtn->ir_builder->CreateZExt( s_of_bit, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ) );
|
||||
|
||||
auto sf = rtn->compute_sf( byte_size, u_sum );
|
||||
auto zf = rtn->compute_zf( byte_size, u_sum );
|
||||
auto pf = rtn->compute_pf( byte_size, u_sum );
|
||||
|
||||
auto flags_calc = rtn->combine_flags(
|
||||
cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ), zf, sf, of );
|
||||
|
||||
return flags_calc;
|
||||
}
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::addq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = rtn->pop( 8 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 8, t3 );
|
||||
|
||||
auto flags = lifters_t::add_flags( rtn, 8, t1, t2 );
|
||||
ir_builder->CreateStore( flags, rtn->flags );
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::adddw =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 4 );
|
||||
auto t2 = rtn->pop( 4 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 4, t3 );
|
||||
|
||||
auto flags = lifters_t::add_flags( rtn, 4, t1, t2 );
|
||||
ir_builder->CreateStore( flags, rtn->flags );
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::addw =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 2 );
|
||||
auto t2 = rtn->pop( 2 );
|
||||
auto t3 = ir_builder->CreateAdd( t1, t2 );
|
||||
rtn->push( 2, t3 );
|
||||
|
||||
auto flags = lifters_t::add_flags( rtn, 2, t1, t2 );
|
||||
ir_builder->CreateStore( flags, rtn->flags );
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
|
||||
} // namespace vm
|
@ -1,19 +1,34 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
lifter_callback_t lconstq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
lifters_t::lifter_callback_t lifters_t::lconstq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
|
||||
lifter_callback_t lconstdwsxq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
lifters_t::lifter_callback_t lifters_t::lconstdwsxq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
|
||||
lifter_callback_t lconstwsxq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
} // namespace vmp2::lifters
|
||||
lifters_t::lifter_callback_t lifters_t::lconstwsxq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::lconstbsxq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 8, llvm::ConstantInt::get( ir_builder->getInt64Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::lconstbzxw =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
rtn->push( 2, llvm::ConstantInt::get( ir_builder->getInt16Ty(), vinstr.operand.imm.u ) );
|
||||
};
|
||||
} // namespace vm
|
@ -1,10 +1,18 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
lifter_callback_t lregq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
rtn->push( 8, rtn->load_value( 8, vreg ) );
|
||||
};
|
||||
}
|
||||
lifters_t::lifter_callback_t lifters_t::lregq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
rtn->push( 8, rtn->load_value( 8, vreg ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::lregdw =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
rtn->push( 4, rtn->load_value( 4, vreg ) );
|
||||
};
|
||||
} // namespace vm
|
@ -0,0 +1,36 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vm
|
||||
{
|
||||
vm::llvm_value_t *lifters_t::and_flags( vm::vmp_rtn_t *rtn, std::uint8_t byte_size, vm::llvm_value_t *lhs,
|
||||
vm::llvm_value_t *rhs )
|
||||
{
|
||||
auto t0 = rtn->ir_builder->CreateAnd( lhs, rhs );
|
||||
auto cf = llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, byte_size * 8 ), 0 );
|
||||
auto of = llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, byte_size * 8 ), 0 );
|
||||
|
||||
auto sf = rtn->compute_sf( byte_size, t0 );
|
||||
auto zf = rtn->compute_zf( byte_size, t0 );
|
||||
auto pf = rtn->compute_pf( byte_size, t0 );
|
||||
|
||||
return rtn->combine_flags( cf, pf, llvm::ConstantInt::get( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), 0 ),
|
||||
zf, sf, of );
|
||||
}
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::nandq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = rtn->pop( 8 );
|
||||
|
||||
auto t1_not = ir_builder->CreateNot( t1 );
|
||||
auto t2_not = ir_builder->CreateNot( t2 );
|
||||
|
||||
auto t3 = ir_builder->CreateAnd( { t1_not, t2_not } );
|
||||
rtn->push( 8, t3 );
|
||||
|
||||
auto flags = and_flags( rtn, 8, t1, t2 );
|
||||
ir_builder->CreateStore( flags, rtn->flags );
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
} // namespace vm
|
@ -1,20 +1,19 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
lifter_callback_t pushvsp = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
// Load the current stack index into a temporary variable
|
||||
auto current_stack_index =
|
||||
ir_builder->CreateLoad( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), rtn->stack_ptr, false );
|
||||
lifters_t::lifter_callback_t lifters_t::pushvsp =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto current_spi =
|
||||
ir_builder->CreateLoad( llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), rtn->stack_ptr, false );
|
||||
|
||||
// Get a pointer to the top byte of the stack
|
||||
llvm::Value *i64_zero = llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) );
|
||||
llvm::Value *indices[ 2 ] = { i64_zero, current_stack_index };
|
||||
auto stack_ptr =
|
||||
ir_builder->CreateInBoundsGEP( rtn->virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
||||
auto *i64_zero = llvm::ConstantInt::get( *rtn->llvm_ctx, llvm::APInt( 64, 0 ) );
|
||||
llvm_value_t *indices[ 2 ] = { i64_zero, current_spi };
|
||||
auto stack_ptr =
|
||||
ir_builder->CreateInBoundsGEP( rtn->virtual_stack, llvm::ArrayRef< llvm::Value * >( indices, 2 ) );
|
||||
|
||||
auto stack_ptr_val = ir_builder->CreatePtrToInt( stack_ptr, ir_builder->getInt64Ty() );
|
||||
rtn->push( 8, stack_ptr_val );
|
||||
};
|
||||
auto stack_ptr_val = ir_builder->CreatePtrToInt( stack_ptr, ir_builder->getInt64Ty() );
|
||||
rtn->push( 8, stack_ptr_val );
|
||||
};
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
lifter_callback_t readq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt64Ty(), 0ull ) );
|
||||
auto t3 = ir_builder->CreateLoad( ir_builder->getInt64Ty(), t2 );
|
||||
rtn->push( 8, t3 );
|
||||
};
|
||||
lifters_t::lifter_callback_t lifters_t::readq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = ir_builder->CreateIntToPtr( t1, llvm::PointerType::get( ir_builder->getInt64Ty(), 0ull ) );
|
||||
auto t3 = ir_builder->CreateLoad( ir_builder->getInt64Ty(), t2 );
|
||||
rtn->push( 8, t3 );
|
||||
};
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vm
|
||||
{
|
||||
lifters_t::lifter_callback_t lifters_t::shrq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto t2 = rtn->pop( 2 );
|
||||
auto t3 = ir_builder->CreateIntCast( t2, llvm::IntegerType::get( *rtn->llvm_ctx, 64 ), false );
|
||||
auto t4 = ir_builder->CreateLShr( t1, t3 );
|
||||
|
||||
// TODO: Compute flags
|
||||
//
|
||||
//
|
||||
|
||||
rtn->push( 8, t4 );
|
||||
rtn->push( 8, rtn->load_value( 8, rtn->flags ) );
|
||||
};
|
||||
}
|
@ -1,14 +1,22 @@
|
||||
#include <vm_lifters.hpp>
|
||||
|
||||
namespace vmp2::lifters
|
||||
namespace vm
|
||||
{
|
||||
// %t1 = %stack[%sp]
|
||||
// add %sp, 8
|
||||
// %vregX = %1
|
||||
lifter_callback_t sregq = [ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
ir_builder->CreateStore( t1, vreg )->setAlignment( llvm::Align( 8 ) );
|
||||
};
|
||||
} // namespace vmp2::lifters
|
||||
lifters_t::lifter_callback_t lifters_t::sregq =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 8 );
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
ir_builder->CreateStore( t1, vreg )->setAlignment( llvm::Align( 8 ) );
|
||||
};
|
||||
|
||||
lifters_t::lifter_callback_t lifters_t::sregdw =
|
||||
[ & ]( vm::vmp_rtn_t *rtn, const vm::instrs::code_block_t &vm_code_block,
|
||||
const vm::instrs::virt_instr_t &vinstr, llvm::IRBuilder<> *ir_builder ) {
|
||||
auto t1 = rtn->pop( 4 );
|
||||
auto vreg = rtn->virtual_registers[ vinstr.operand.imm.u ? vinstr.operand.imm.u / 8 : 0 ];
|
||||
auto vregdw = ir_builder->CreatePointerCast(
|
||||
vreg, llvm::PointerType::get( llvm::IntegerType::get( *rtn->llvm_ctx, 32 ), 0 ) );
|
||||
ir_builder->CreateStore( t1, vregdw );
|
||||
};
|
||||
} // namespace vm
|
Loading…
Reference in new issue