diff options
Diffstat (limited to 'src/cuda-sim/instructions.cc')
| -rw-r--r-- | src/cuda-sim/instructions.cc | 1185 |
1 files changed, 969 insertions, 216 deletions
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index cbf4c44..d9a9630 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -95,11 +95,27 @@ extern std::map<struct textureReference*,struct textureInfo*> TextureToInfoMap; extern std::map<std::string, struct textureReference*> NameToTextureMap; void inst_not_implemented( const ptx_instruction * pI ) ; +ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo, operand_info dstInfo, unsigned type, ptx_thread_info *thread); unsigned unfound_register_warned = 0; -ptx_reg_t ptx_thread_info::get_operand_value( const symbol *reg ) +void sign_extend( ptx_reg_t &data, unsigned src_size, const operand_info &dst ); + +void ptx_thread_info::set_reg( const symbol *reg, const ptx_reg_t &value ) +{ + assert( reg != NULL ); + if( reg->name() == "_" ) return; + assert( !m_regs.empty() ); + assert( reg->uid() > 0 ); + m_regs.back()[ reg ] = value; + if (m_enable_debug_trace ) + m_debug_trace_regs_modified.back()[ reg ] = value; + m_last_set_operand_value = value; +} + +ptx_reg_t ptx_thread_info::get_reg( const symbol *reg ) { - // assume that the given symbol is a register and try to find it in the register hash map + assert( reg != NULL ); + assert( !m_regs.empty() ); reg_map_t::iterator regs_iter = m_regs.back().find(reg); if (regs_iter == m_regs.back().end()) { assert( reg->type()->get_key().is_reg() ); @@ -107,7 +123,7 @@ ptx_reg_t ptx_thread_info::get_operand_value( const symbol *reg ) unsigned call_uid = m_callstack.back().m_call_uid; ptx_reg_t uninit_reg; uninit_reg.u32 = 0xDEADBEEF; - set_operand_value(reg, uninit_reg); // give it a value since we are going to warn the user anyway + set_reg(reg, uninit_reg); // give it a value since we are going to warn the user anyway std::string file_loc = get_location(); if( !unfound_register_warned ) { printf("GPGPU-Sim PTX: WARNING (%s) ** reading undefined register \'%s\' (cuid:%u). Setting to 0XDEADBEEF.\n", @@ -116,67 +132,203 @@ ptx_reg_t ptx_thread_info::get_operand_value( const symbol *reg ) } regs_iter = m_regs.back().find(reg); } + if (m_enable_debug_trace ) + m_debug_trace_regs_read.back()[ reg ] = regs_iter->second; return regs_iter->second; } -ptx_reg_t ptx_thread_info::get_operand_value( const operand_info &op ) +ptx_reg_t ptx_thread_info::get_operand_value( const operand_info &op, operand_info dstInfo, unsigned opType, ptx_thread_info *thread, int derefFlag ) { - ptx_reg_t result; - const char *name = NULL; - if ( op.is_reg() ) { - result = get_operand_value( op.get_symbol() ); - } else if ( op.is_builtin()) { - result = get_builtin( op.get_int(), op.get_addr_offset() ); - } else if ( op.is_memory_operand() ) { - // a few options here... - const symbol *sym = op.get_symbol(); - const type_info *type = sym->type(); - const type_info_key &info = type->get_key(); + ptx_reg_t result, tmp; + + if(op.get_double_operand_type() == 0) { + if(((opType != BB128_TYPE) && (opType != BB64_TYPE)) || (op.get_addr_space() != 0)) { + if ( op.is_reg() ) { + result = get_reg( op.get_symbol() ); + } else if ( op.is_builtin()) { + result = get_builtin( op.get_int(), op.get_addr_offset() ); + } else if ( op.is_memory_operand() ) { + // a few options here... + const symbol *sym = op.get_symbol(); + const type_info *type = sym->type(); + const type_info_key &info = type->get_key(); + + if ( info.is_reg() ) { + const symbol *name = op.get_symbol(); + result.u64 = get_reg(name).u64 + op.get_addr_offset(); + } else if ( info.is_param_kernel() ) { + result = sym->get_address() + op.get_addr_offset(); + } else if ( info.is_param_local() ) { + result = sym->get_address() + op.get_addr_offset(); + } else if ( info.is_global() ) { + assert( op.get_addr_offset() == 0 ); + result = sym->get_address(); + } else if ( info.is_local() ) { + result = sym->get_address() + op.get_addr_offset(); + } else if ( info.is_const() ) { + result = sym->get_address() + op.get_addr_offset(); + } else if ( op.is_shared() ) { + result = op.get_symbol()->get_address() + op.get_addr_offset(); + } else { + const char *name = op.name().c_str(); + printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown memory operand type for %s\n", name ); + abort(); + } - if ( info.is_reg() ) { - name = op.name().c_str(); - reg_map_t::iterator regs_iter = m_regs.back().find(sym); - assert( regs_iter != m_regs.back().end() ); - ptx_reg_t baseaddr = regs_iter->second; - result.u64 = baseaddr.u64 + op.get_addr_offset(); - } else if ( info.is_param_kernel() ) { - result = sym->get_address() + op.get_addr_offset(); - } else if ( info.is_param_local() ) { - result = sym->get_address() + op.get_addr_offset(); - } else if ( info.is_global() ) { - assert( op.get_addr_offset() == 0 ); - result = sym->get_address(); - } else if ( info.is_local() ) { - result = sym->get_address() + op.get_addr_offset(); - } else if ( info.is_const() ) { - result = sym->get_address() + op.get_addr_offset(); - } else if ( op.is_shared() ) { - result = op.get_symbol()->get_address() + op.get_addr_offset(); + } else if ( op.is_literal() ) { + result = op.get_literal_value(); + } else if ( op.is_label() ) { + result = op.get_symbol()->get_address(); + } else if ( op.is_shared() ) { + result = op.get_symbol()->get_address(); + } else if ( op.is_const() ) { + result = op.get_symbol()->get_address(); + } else if ( op.is_global() ) { + result = op.get_symbol()->get_address(); + } else if ( op.is_local() ) { + result = op.get_symbol()->get_address(); + } else { + const char *name = op.name().c_str(); + printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown operand type for %s\n", name ); + assert(0); + } + + if(op.get_operand_lohi() == 1) + result.u64 = result.u64 & 0xFFFF; + else if(op.get_operand_lohi() == 2) + result.u64 = (result.u64>>16) & 0xFFFF; + } else if (opType == BB128_TYPE) { + // b128 + result.u128.lowest = get_reg( op.vec_symbol(0) ).u32; + result.u128.low = get_reg( op.vec_symbol(1) ).u32; + result.u128.high = get_reg( op.vec_symbol(2) ).u32; + result.u128.highest = get_reg( op.vec_symbol(3) ).u32; } else { - name = op.name().c_str(); - printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown memory operand type for %s\n", name ); - abort(); + // bb64 + result.bits.ls = get_reg( op.vec_symbol(0) ).u32; + result.bits.ms = get_reg( op.vec_symbol(1) ).u32; } + } else if (op.get_double_operand_type() == 1) { + ptx_reg_t firstHalf, secondHalf; + firstHalf = get_reg( op.vec_symbol(0) ).u64; + secondHalf = get_reg( op.vec_symbol(1) ).u64; + if(op.get_operand_lohi() == 1) + secondHalf.u64 = secondHalf.u64 & 0xFFFF; + else if(op.get_operand_lohi() == 2) + secondHalf.u64 = (secondHalf.u64>>16) & 0xFFFF; + result = firstHalf.u64 + secondHalf.u64; + } else if (op.get_double_operand_type() == 2) { + // s[reg1 += reg2] + // reg1 is incremented after value is returned: the value returned is s[reg1] + ptx_reg_t firstHalf, secondHalf; + firstHalf = get_reg(op.vec_symbol(0)).u64; + secondHalf = get_reg(op.vec_symbol(1)).u64; + if(op.get_operand_lohi() == 1) + secondHalf.u64 = secondHalf.u64 & 0xFFFF; + else if(op.get_operand_lohi() == 2) + secondHalf.u64 = (secondHalf.u64>>16) & 0xFFFF; + result = firstHalf.u64; + firstHalf = firstHalf.u64 + secondHalf.u64; + set_reg(op.vec_symbol(0),firstHalf); + } else if (op.get_double_operand_type() == 3) { + // s[reg += immediate] + // reg is incremented after value is returned: the value returned is s[reg] + ptx_reg_t firstHalf; + firstHalf = get_reg(op.get_symbol()).u64; + result = firstHalf.u64; + firstHalf = firstHalf.u64 + op.get_addr_offset(); + set_reg(op.get_symbol(),firstHalf); + } + + ptx_reg_t finalResult; + memory_space *mem = NULL; + size_t size; + int t; + finalResult.u64=0; + + //complete other cases for reading from memory, such as reading from other const memory + if((op.get_addr_space() == 1)&&(derefFlag)) { + // global memory - g[4], g[$r0] + mem = g_global_mem; + type_info_key::type_decode(opType,size,t); + mem->read(result.u32,size/8,&finalResult.u128); + thread->m_last_effective_address = result.u32; + thread->m_last_memory_space = global_space; + + if( opType == S16_TYPE || opType == S32_TYPE ) + sign_extend(finalResult,size,dstInfo); + } else if((op.get_addr_space() == 2)&&(derefFlag)) { + // shared memory - s[4], s[$r0] + mem = thread->m_shared_mem; + type_info_key::type_decode(opType,size,t); + mem->read(result.u32,size/8,&finalResult.u128); + thread->m_last_effective_address = result.u32; + thread->m_last_memory_space = shared_space; - } else if ( op.is_literal() ) { - result = op.get_literal_value(); - } else if ( op.is_label() ) { - result = op.get_symbol()->get_address(); - } else if ( op.is_shared() ) { - result = op.get_symbol()->get_address(); - } else if ( op.is_const() ) { - result = op.get_symbol()->get_address(); - } else if ( op.is_global() ) { - result = op.get_symbol()->get_address(); - } else if ( op.is_local() ) { - result = op.get_symbol()->get_address(); + if( opType == S16_TYPE || opType == S32_TYPE ) + sign_extend(finalResult,size,dstInfo); + } else if((op.get_addr_space() == 3)&&(derefFlag)) { + // const memory - ce0c1[4], ce0c1[$r0] + mem = g_global_mem; + type_info_key::type_decode(opType,size,t); + mem->read((result.u32 + op.get_const_mem_offset()),size/8,&finalResult.u128); + thread->m_last_effective_address = result.u32; + thread->m_last_memory_space = const_space; + if( opType == S16_TYPE || opType == S32_TYPE ) + sign_extend(finalResult,size,dstInfo); + } else if((op.get_addr_space() == 4)&&(derefFlag)) { + // local memory - l0[4], l0[$r0] + mem = thread->m_local_mem; + type_info_key::type_decode(opType,size,t); + mem->read(result.u32,size/8,&finalResult.u128); + thread->m_last_effective_address = result.u32; + thread->m_last_memory_space = local_space; + if( opType == S16_TYPE || opType == S32_TYPE ) + sign_extend(finalResult,size,dstInfo); } else { - name = op.name().c_str(); - printf("GPGPU-Sim PTX: ERROR ** get_operand_value : unknown operand type for %s\n", name ); - assert(0); + finalResult = result; } - return result; + if((op.get_operand_neg() == true)&&(derefFlag)) { + switch( opType ) { + // Default to f32 for now, need to add support for others + case S8_TYPE: + case U8_TYPE: + case B8_TYPE: + finalResult.s8 = -finalResult.s8; + break; + case S16_TYPE: + case U16_TYPE: + case B16_TYPE: + finalResult.s16 = -finalResult.s16; + break; + case S32_TYPE: + case U32_TYPE: + case B32_TYPE: + finalResult.s32 = -finalResult.s32; + break; + case S64_TYPE: + case U64_TYPE: + case B64_TYPE: + finalResult.s64 = -finalResult.s64; + break; + case F16_TYPE: + finalResult.f16 = -finalResult.f16; + break; + case F32_TYPE: + finalResult.f32 = -finalResult.f32; + break; + case F64_TYPE: + finalResult.f64 = -finalResult.f64; + break; + default: + assert(0); + } + + } + + return finalResult; + } unsigned get_operand_nbits( const operand_info &op ) @@ -218,9 +370,11 @@ void ptx_thread_info::get_vector_operand_values( const operand_info &op, ptx_reg for (int idx = num_elements - 1; idx >= 0; --idx) { const symbol *sym = NULL; sym = op.vec_symbol(idx); - reg_map_t::iterator reg_iter = m_regs.back().find(sym); - assert( reg_iter != m_regs.back().end() ); - ptx_regs[idx] = reg_iter->second; + if( strcmp(sym->name().c_str(),"_") != 0) { + reg_map_t::iterator reg_iter = m_regs.back().find(sym); + assert( reg_iter != m_regs.back().end() ); + ptx_regs[idx] = reg_iter->second; + } } } @@ -246,22 +400,251 @@ void sign_extend( ptx_reg_t &data, unsigned src_size, const operand_info &dst ) data.u64 |= mask; } -void ptx_thread_info::set_operand_value( const operand_info &dst, const ptx_reg_t &data ) +void ptx_thread_info::set_operand_value( const operand_info &dst, const ptx_reg_t &data, unsigned type, ptx_thread_info *thread, const ptx_instruction *pI, int overflow, int carry ) { - m_regs.back()[ dst.get_symbol() ] = data; - if (m_enable_debug_trace ) { - m_debug_trace_regs_modified[ dst.get_symbol() ] = data; - } - m_last_set_operand_value = data; + thread->set_operand_value( dst, data, type, thread, pI ); + + if (dst.get_double_operand_type() == -2) + { + ptx_reg_t predValue; + + const symbol *sym = dst.vec_symbol(0); + predValue.u64 = (m_regs.back()[ sym ].u64) & ~(0x0C); + predValue.u64 |= ((overflow & 0x01)<<3); + predValue.u64 |= ((carry & 0x01)<<2); + + set_reg(sym,predValue); + } + else if (dst.get_double_operand_type() == 0) + { + //intentionally do nothing + } + else + { + printf("Unexpected double destination\n"); + assert(0); + } + } -void ptx_thread_info::set_operand_value( const symbol *dst, const ptx_reg_t &data ) +void ptx_thread_info::set_operand_value( const operand_info &dst, const ptx_reg_t &data, unsigned type, ptx_thread_info *thread, const ptx_instruction *pI ) { - m_regs.back()[ dst ] = data; - if (m_enable_debug_trace ) { - m_debug_trace_regs_modified[ dst ] = data; + ptx_reg_t dstData; + memory_space *mem = NULL; + size_t size; + int t; + + type_info_key::type_decode(type,size,t); + + /*complete this section for other cases*/ + if(dst.get_addr_space() == 0) + { + ptx_reg_t setValue; + setValue.u64 = data.u64; + + // Double destination in set instruction ($p0|$p1) - second is negation of first + if (dst.get_double_operand_type() == -1) + { + ptx_reg_t setValue2; + const symbol *name1 = dst.vec_symbol(0); + const symbol *name2 = dst.vec_symbol(1); + + if ( (type==F16_TYPE)||(type==F32_TYPE)||(type==F64_TYPE) ) { + setValue2.f32 = (setValue.u64==0)?1.0f:0.0f; + } else { + setValue2.u32 = (setValue.u64==0)?0xFFFFFFFF:0; + } + + set_reg(name1,setValue); + set_reg(name2,setValue2); + } + + // Double destination in cvt,shr,mul,etc. instruction ($p0|$r4) - second register operand receives data, first predicate operand + // is set as $p0=($r4!=0) + // Also for Double destination in set instruction ($p0/$r1) + else if ((dst.get_double_operand_type() == -2)||(dst.get_double_operand_type() == -3)) + { + ptx_reg_t predValue; + const symbol *predName = dst.vec_symbol(0); + const symbol *regName = dst.vec_symbol(1); + predValue.u64 = 0; + + switch ( type ) { + case S8_TYPE: + if((setValue.s8 & 0x7F) == 0) + predValue.u64 |= 1; + break; + case S16_TYPE: + if((setValue.s16 & 0x7FFF) == 0) + predValue.u64 |= 1; + break; + case S32_TYPE: + if((setValue.s32 & 0x7FFFFFFF) == 0) + predValue.u64 |= 1; + break; + case S64_TYPE: + if((setValue.s64 & 0x7FFFFFFFFFFFFFFF) == 0) + predValue.u64 |= 1; + break; + case U8_TYPE: + case B8_TYPE: + if(setValue.u8 == 0) + predValue.u64 |= 1; + break; + case U16_TYPE: + case B16_TYPE: + if(setValue.u16 == 0) + predValue.u64 |= 1; + break; + case U32_TYPE: + case B32_TYPE: + if(setValue.u32 == 0) + predValue.u64 |= 1; + break; + case U64_TYPE: + case B64_TYPE: + if(setValue.u64 == 0) + predValue.u64 |= 1; + break; + case F16_TYPE: + if(setValue.f16 == 0) + predValue.u64 |= 1; + break; + case F32_TYPE: + if(setValue.f32 == 0) + predValue.u64 |= 1; + break; + case F64_TYPE: + if(setValue.f64 == 0) + predValue.u64 |= 1; + break; + default: assert(0); break; + } + + + if ( (type==S8_TYPE)||(type==S16_TYPE)||(type==S32_TYPE)||(type==S64_TYPE)|| + (type==U8_TYPE)||(type==U16_TYPE)||(type==U32_TYPE)||(type==U64_TYPE)|| + (type==B8_TYPE)||(type==B16_TYPE)||(type==B32_TYPE)||(type==B64_TYPE)) { + if((setValue.u32 & (1<<(size-1))) != 0) + predValue.u64 |= 1<<1; + } + if ( type==F32_TYPE ) { + if(setValue.f32 < 0) + predValue.u64 |= 1<<1; + } + + if(dst.get_operand_lohi() == 1) + { + setValue.u64 = ((m_regs.back()[ regName ].u64) & (~(0xFFFF))) + (data.u64 & 0xFFFF); + } + else if(dst.get_operand_lohi() == 2) + { + setValue.u64 = ((m_regs.back()[ regName ].u64) & (~(0xFFFF0000))) + ((data.u64<<16) & 0xFFFF0000); + } + + set_reg(predName,predValue); + set_reg(regName,setValue); + } + else if (type == BB128_TYPE) + { + //b128 stuff here. + ptx_reg_t setValue2, setValue3, setValue4; + setValue.u64 = 0; + setValue2.u64 = 0; + setValue3.u64 = 0; + setValue4.u64 = 0; + setValue.u32 = data.u128.lowest; + setValue2.u32 = data.u128.low; + setValue3.u32 = data.u128.high; + setValue4.u32 = data.u128.highest; + + const symbol *name1, *name2, *name3, *name4 = NULL; + + name1 = dst.vec_symbol(0); + name2 = dst.vec_symbol(1); + name3 = dst.vec_symbol(2); + name4 = dst.vec_symbol(3); + + set_reg(name1,setValue); + set_reg(name2,setValue2); + set_reg(name3,setValue3); + set_reg(name4,setValue4); + } + else if (type == BB64_TYPE) + { + //ptxplus version of storing 64 bit values to registers stores to two adjacent registers + ptx_reg_t setValue2; + setValue.u32 = 0; + setValue2.u32 = 0; + + setValue.u32 = data.bits.ls; + setValue2.u32 = data.bits.ms; + + const symbol *name1, *name2 = NULL; + + name1 = dst.vec_symbol(0); + name2 = dst.vec_symbol(1); + + set_reg(name1,setValue); + set_reg(name2,setValue2); + } + else + { + if(dst.get_operand_lohi() == 1) + { + setValue.u64 = ((m_regs.back()[ dst.get_symbol() ].u64) & (~(0xFFFF))) + (data.u64 & 0xFFFF); + } + else if(dst.get_operand_lohi() == 2) + { + setValue.u64 = ((m_regs.back()[ dst.get_symbol() ].u64) & (~(0xFFFF0000))) + ((data.u64<<16) & 0xFFFF0000); + } + set_reg(dst.get_symbol(),setValue); + } + } + + // global memory - g[4], g[$r0] + else if(dst.get_addr_space() == 1) + { + dstData = thread->get_operand_value(dst, dst, type, thread, 0); + mem = g_global_mem; + type_info_key::type_decode(type,size,t); + + mem->write(dstData.u32,size/8,&data.u128,thread,pI); + thread->m_last_effective_address = dstData.u32; + thread->m_last_memory_space = global_space; + } + + // shared memory - s[4], s[$r0] + else if(dst.get_addr_space() == 2) + { + dstData = thread->get_operand_value(dst, dst, type, thread, 0); + mem = thread->m_shared_mem; + type_info_key::type_decode(type,size,t); + + mem->write(dstData.u32,size/8,&data.u128,thread,pI); + thread->m_last_effective_address = dstData.u32; + thread->m_last_memory_space = shared_space; } - m_last_set_operand_value = data; + + // local memory - l0[4], l0[$r0] + else if(dst.get_addr_space() == 4) + { + dstData = thread->get_operand_value(dst, dst, type, thread, 0); + mem = thread->m_local_mem; + type_info_key::type_decode(type,size,t); + + mem->write(dstData.u32,size/8,&data.u128,thread,pI); + thread->m_last_effective_address = dstData.u32; + thread->m_last_memory_space = local_space; + } + + else + { + printf("Destination stores to unknown location."); + assert(0); + } + + } void ptx_thread_info::set_vector_operand_values( const operand_info &dst, @@ -271,12 +654,12 @@ void ptx_thread_info::set_vector_operand_values( const operand_info &dst, const ptx_reg_t &data4, unsigned num_elements ) { - set_operand_value(dst.vec_symbol(0), data1); - set_operand_value(dst.vec_symbol(1), data2); + set_reg(dst.vec_symbol(0), data1); + set_reg(dst.vec_symbol(1), data2); if (num_elements > 2) { - set_operand_value(dst.vec_symbol(2), data3); + set_reg(dst.vec_symbol(2), data3); if (num_elements > 3) { - set_operand_value(dst.vec_symbol(3), data4); + set_reg(dst.vec_symbol(3), data4); } } @@ -303,13 +686,18 @@ void abs_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case S16_TYPE: d.s16 = my_abs(a.s16); break; case S32_TYPE: d.s32 = my_abs(a.s32); break; case S64_TYPE: d.s64 = my_abs(a.s64); break; + case U16_TYPE: d.s16 = my_abs(a.u16); break; + case U32_TYPE: d.s32 = my_abs(a.u32); break; + case U64_TYPE: d.s64 = my_abs(a.u64); break; case F32_TYPE: d.f32 = my_abs(a.f32); break; case F64_TYPE: d.f64 = my_abs(a.f64); break; default: @@ -318,18 +706,22 @@ void abs_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void add_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { ptx_reg_t src1_data, src2_data, data; + int overflow = 0; + int carry = 0; const operand_info &dst = pI->dst(); //get operand info of sources and destination const operand_info &src1 = pI->src1(); //use them to determine that they are of type 'register' const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); //get values from the operand infos - src2_data = thread->get_operand_value(src2); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); unsigned rounding_mode = pI->rounding_mode(); int orig_rm = fegetround(); @@ -339,25 +731,49 @@ void add_impl( const ptx_instruction *pI, ptx_thread_info *thread ) default: assert(0); break; } - unsigned to_type = pI->get_type(); - - switch ( to_type ) { + //performs addition. Sets carry and overflow if needed. + switch ( i_type ) { case S8_TYPE: + data.s64 = (src1_data.s64 & 0x0000000FF) + (src2_data.s64 & 0x0000000FF); + if(((src1_data.s64 & 0x80)-(src2_data.s64 & 0x80)) == 0) {overflow=((src1_data.s64 & 0x80)-(data.s64 & 0x80))==0?0:1; } + carry = (data.u64 & 0x000000100)>>8; + break; case S16_TYPE: + data.s64 = (src1_data.s64 & 0x00000FFFF) + (src2_data.s64 & 0x00000FFFF); + if(((src1_data.s64 & 0x8000)-(src2_data.s64 & 0x8000)) == 0) {overflow=((src1_data.s64 & 0x8000)-(data.s64 & 0x8000))==0?0:1; } + carry = (data.u64 & 0x000010000)>>16; + break; case S32_TYPE: + data.s64 = (src1_data.s64 & 0x0FFFFFFFF) + (src2_data.s64 & 0x0FFFFFFFF); + if(((src1_data.s64 & 0x80000000)-(src2_data.s64 & 0x80000000)) == 0) {overflow=((src1_data.s64 & 0x80000000)-(data.s64 & 0x80000000))==0?0:1; } + carry = (data.u64 & 0x100000000)>>32; + break; case S64_TYPE: + data.s64 = src1_data.s64 + src2_data.s64; + break; case U8_TYPE: + data.u64 = (src1_data.u64 & 0xFF) + (src2_data.u64 & 0xFF); + carry = (data.u64 & 0x100)>>8; + break; case U16_TYPE: + data.u64 = (src1_data.u64 & 0xFFFF) + (src2_data.u64 & 0xFFFF); + carry = (data.u64 & 0x10000)>>16; + break; case U32_TYPE: + data.u64 = (src1_data.u64 & 0xFFFFFFFF) + (src2_data.u64 & 0xFFFFFFFF); + carry = (data.u64 & 0x100000000)>>32; + break; case U64_TYPE: - data.s64 = src1_data.s64 + src2_data.s64; break; + data.s64 = src1_data.s64 + src2_data.s64; + break; case F16_TYPE: assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 + src2_data.f32; break; case F64_TYPE: data.f64 = src1_data.f64 + src2_data.f64; break; default: assert(0); break; } fesetround( orig_rm ); - thread->set_operand_value(dst,data); + + thread->set_operand_value(dst, data, i_type, thread, pI, overflow, carry ); } void addc_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -370,12 +786,45 @@ void and_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); - src2_data = thread->get_operand_value(src2); + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = ~(~(src1_data.pred) & ~(src2_data.pred)); + else + data.u64 = src1_data.u64 & src2_data.u64; + + thread->set_operand_value(dst,data, i_type, thread, pI); +} + +void andn_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + ptx_reg_t src1_data, src2_data, data; + + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const operand_info &src2 = pI->src2(); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + switch ( i_type ) { + case B16_TYPE: src2_data.u16 = ~src2_data.u16; break; + case B32_TYPE: src2_data.u32 = ~src2_data.u32; break; + case B64_TYPE: src2_data.u64 = ~src2_data.u64; break; + default: + printf("Execution error: type mismatch with instruction\n"); + assert(0); + break; + } data.u64 = src1_data.u64 & src2_data.u64; - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI); } void atom_callback( void* ptx_inst, void* thd ) @@ -406,13 +855,13 @@ void atom_callback( void* ptx_inst, void* thd ) const operand_info &src2 = pI->src2(); // b // Get operand values - src1_data = thread->get_operand_value(src1); // a - src2_data = thread->get_operand_value(src2); // b + src1_data = thread->get_operand_value(src1, dst, to_type, thread, 1); // a + src2_data = thread->get_operand_value(src2, dst, to_type, thread, 1); // b // Copy value pointed to in operand 'a' into register 'd' // (i.e. copy src1_data to dst) g_global_mem->read(src1_data.u32,size/8,&data.s64); - thread->set_operand_value(dst, data); // Write value into register 'd' + thread->set_operand_value(dst, data, to_type, thread, pI); // Write value into register 'd' // Get the atomic operation to be performed unsigned m_atomic_spec = pI->get_atomic(); @@ -490,7 +939,7 @@ void atom_callback( void* ptx_inst, void* thd ) ptx_reg_t src3_data; const operand_info &src3 = pI->src3(); - src3_data = thread->get_operand_value(src3); + src3_data = thread->get_operand_value(src3, dst, to_type, thread, 1); switch ( to_type ) { case B32_TYPE: @@ -648,7 +1097,9 @@ void atom_impl( const ptx_instruction *pI, ptx_thread_info *thread ) // get the memory address const operand_info &src1 = pI->src1(); - ptx_reg_t src1_data = thread->get_operand_value(src1); + const operand_info &dst = pI->dst(); + unsigned i_type = pI->get_type(); + ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); memory_space_t space = pI->get_space(); @@ -661,7 +1112,7 @@ void atom_impl( const ptx_instruction *pI, ptx_thread_info *thread ) void bar_sync_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { const operand_info &dst = pI->dst(); - ptx_reg_t b = thread->get_operand_value(dst); + ptx_reg_t b = thread->get_operand_value(dst, dst, U32_TYPE, thread, 1); assert( b.u32 == 0 ); // not clear what should happen if this is not zero } @@ -672,12 +1123,28 @@ void bfind_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not void bra_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { const operand_info &target = pI->dst(); - ptx_reg_t target_pc = thread->get_operand_value(target); + ptx_reg_t target_pc = thread->get_operand_value(target, target, U32_TYPE, thread, 1); thread->m_branch_taken = true; thread->set_npc(target_pc); } +void break_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + const operand_info &target = thread->pop_breakaddr(); + ptx_reg_t target_pc = thread->get_operand_value(target, target, U32_TYPE, thread, 1); + + thread->m_branch_taken = true; + thread->set_npc(target_pc); +} + +void breakaddr_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + const operand_info &target = pI->dst(); + thread->push_breakaddr(target); + assert(pI->has_pred() == false); // pdom analysis cannot handle if this instruction is predicated +} + void brev_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } void brkpt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -747,21 +1214,22 @@ void cnot_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, b, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + switch ( i_type ) { - case PRED_TYPE: d.pred = (a.pred == 0)?1:0; break; + case PRED_TYPE: d.pred = ((a.pred & 0x0001) == 0)?1:0; break; case B16_TYPE: d.u16 = (a.u16 == 0)?1:0; break; case B32_TYPE: d.u32 = (a.u32 == 0)?1:0; break; case B64_TYPE: d.u64 = (a.u64 == 0)?1:0; break; default: printf("Execution error: type mismatch with instruction\n"); - assert(0); // TODO: add more typechecking like this + assert(0); break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void cos_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -769,9 +1237,11 @@ void cos_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: d.f32 = cos(a.f32); @@ -782,7 +1252,7 @@ void cos_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } ptx_reg_t chop( ptx_reg_t x, unsigned from_width, unsigned to_width, int to_sign, int rounding_mode, int saturation_mode ) @@ -1270,13 +1740,54 @@ void cvt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) unsigned src_fmt = type_info_key::type_decode(from_type, from_width, from_sign); unsigned dst_fmt = type_info_key::type_decode(to_type, to_width, to_sign); - ptx_reg_t data = thread->get_operand_value(src1); + ptx_reg_t data = thread->get_operand_value(src1, dst, from_type, thread, 1); + + if(pI->is_neg()){ + + switch( from_type ) { + // Default to f32 for now, need to add support for others + case S8_TYPE: + case U8_TYPE: + case B8_TYPE: + data.s8 = -data.s8; + break; + case S16_TYPE: + case U16_TYPE: + case B16_TYPE: + data.s16 = -data.s16; + break; + case S32_TYPE: + case U32_TYPE: + case B32_TYPE: + data.s32 = -data.s32; + break; + case S64_TYPE: + case U64_TYPE: + case B64_TYPE: + data.s64 = -data.s64; + break; + case F16_TYPE: + data.f16 = -data.f16; + break; + case F32_TYPE: + data.f32 = -data.f32; + break; + case F64_TYPE: + data.f64 = -data.f64; + break; + default: + assert(0); + } + + } + + if ( g_cvt_fn[src_fmt][dst_fmt] != NULL ) { ptx_reg_t result = g_cvt_fn[src_fmt][dst_fmt](data,from_width,to_width,to_sign, rounding_mode, saturation_mode); data = result; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst, data, to_type, thread, pI ); } void cvta_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1288,7 +1799,8 @@ void cvta_impl( const ptx_instruction *pI, ptx_thread_info *thread ) memory_space_t space = pI->get_space(); bool to_non_generic = pI->is_to(); - ptx_reg_t from_addr = thread->get_operand_value(src1); + unsigned i_type = pI->get_type(); + ptx_reg_t from_addr = thread->get_operand_value(src1,dst,i_type,thread,1); addr_t from_addr_hw = (addr_t)from_addr.u64; addr_t to_addr_hw = 0; unsigned smid = thread->get_hw_sid(); @@ -1312,7 +1824,7 @@ void cvta_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t to_addr; to_addr.u64 = to_addr_hw; - thread->set_operand_value(dst,to_addr); + thread->set_reg(dst.get_symbol(),to_addr); } void div_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1323,11 +1835,12 @@ void div_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - ptx_reg_t src1_data = thread->get_operand_value(src1); - ptx_reg_t src2_data = thread->get_operand_value(src2); - unsigned i_type = pI->get_type(); + ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + ptx_reg_t src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + switch ( i_type ) { case S8_TYPE: case S16_TYPE: @@ -1348,7 +1861,7 @@ void div_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case F64_TYPE: data.f64 = src1_data.f64 / src2_data.f64; break; default: assert(0); break; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread,pI); } void ex2_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1356,9 +1869,12 @@ void ex2_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t src1_data, src2_data, data; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - src1_data = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: data.f32 = cuda_math::__powf(2.0, src1_data.f32); @@ -1369,7 +1885,7 @@ void ex2_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread,pI); } void exit_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1398,7 +1914,7 @@ void isspacep_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); memory_space_t space = pI->get_space(); - a = thread->get_operand_value(src1); + a = thread->get_reg(src1.get_symbol()); addr_t addr = (addr_t)a.u64; unsigned smid = thread->get_hw_sid(); unsigned hwtid = thread->get_hw_tid(); @@ -1413,7 +1929,7 @@ void isspacep_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t p; p.pred = t?1:0; - thread->set_operand_value(dst,p); + thread->set_reg(dst.get_symbol(),p); } void decode_space( memory_space_t &space, const ptx_thread_info *thread, const operand_info &op, memory_space *&mem, addr_t &addr) @@ -1472,11 +1988,14 @@ void ld_exec( const ptx_instruction *pI, ptx_thread_info *thread ) { const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - ptx_reg_t src1_data = thread->get_operand_value(src1); + + unsigned type = pI->get_type(); + + ptx_reg_t src1_data = thread->get_operand_value(src1, dst, type, thread, 1); ptx_reg_t data; memory_space_t space = pI->get_space(); unsigned vector_spec = pI->get_vector(); - unsigned type = pI->get_type(); + memory_space *mem = NULL; addr_t addr = src1_data.u32; @@ -1490,7 +2009,7 @@ void ld_exec( const ptx_instruction *pI, ptx_thread_info *thread ) mem->read(addr,size/8,&data.s64); if( type == S16_TYPE || type == S32_TYPE ) sign_extend(data,size,dst); - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, type, thread, pI); } else { ptx_reg_t data1, data2, data3, data4; mem->read(addr,size/8,&data1.s64); @@ -1523,9 +2042,12 @@ void lg2_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: d.f32 = log(a.f32)/log(2); @@ -1536,7 +2058,7 @@ void lg2_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void mad24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1546,11 +2068,12 @@ void mad24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src2 = pI->src2(); const operand_info &src3 = pI->src3(); ptx_reg_t d, t; - ptx_reg_t a = thread->get_operand_value(src1); - ptx_reg_t b = thread->get_operand_value(src2); - ptx_reg_t c = thread->get_operand_value(src3); unsigned i_type = pI->get_type(); + ptx_reg_t a = thread->get_operand_value(src1, dst, i_type, thread, 1); + ptx_reg_t b = thread->get_operand_value(src2, dst, i_type, thread, 1); + ptx_reg_t c = thread->get_operand_value(src3, dst, i_type, thread, 1); + unsigned sat_mode = pI->saturation_mode(); assert( !pI->is_wide() ); @@ -1579,7 +2102,8 @@ void mad24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) assert(0); break; } - thread->set_operand_value(dst,d); + + thread->set_operand_value(dst, d, i_type, thread, pI); } void mad_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1594,11 +2118,12 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src2 = pI->src2(); const operand_info &src3 = pI->src3(); ptx_reg_t d, t; - ptx_reg_t a = thread->get_operand_value(src1); - ptx_reg_t b = thread->get_operand_value(src2); - ptx_reg_t c = thread->get_operand_value(src3); unsigned i_type = pI->get_type(); + ptx_reg_t a = thread->get_operand_value(src1, dst, i_type, thread, 1); + ptx_reg_t b = thread->get_operand_value(src2, dst, i_type, thread, 1); + ptx_reg_t c = thread->get_operand_value(src3, dst, i_type, thread, 1); + unsigned rounding_mode = pI->rounding_mode(); switch ( i_type ) { @@ -1681,7 +2206,7 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ) assert(0); break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst, d, i_type, thread, pI); } bool isNaN(float x) @@ -1700,10 +2225,12 @@ void max_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + + switch ( i_type ) { case U16_TYPE: d.u16 = MY_MAX_I(a.u16,b.u16); break; case U32_TYPE: d.u32 = MY_MAX_I(a.u32,b.u32); break; @@ -1719,7 +2246,7 @@ void max_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void membar_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -1730,10 +2257,12 @@ void min_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + + switch ( i_type ) { case U16_TYPE: d.u16 = MY_MIN_I(a.u16,b.u16); break; case U32_TYPE: d.u32 = MY_MIN_I(a.u32,b.u32); break; @@ -1749,7 +2278,7 @@ void min_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void mov_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1758,8 +2287,9 @@ void mov_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); + unsigned i_type = pI->get_type(); - if( src1.is_vector() || dst.is_vector() ) { + if( (src1.is_vector() || dst.is_vector()) && (i_type != BB64_TYPE) && (i_type != BB128_TYPE) ) { // pack or unpack operation unsigned nbits_to_move; ptx_reg_t tmp_bits; @@ -1786,7 +2316,7 @@ void mov_impl( const ptx_instruction *pI, ptx_thread_info *thread ) } } } else { - data = thread->get_operand_value(src1); + data = thread->get_operand_value(src1, dst, i_type, thread, 1); switch( pI->get_type() ) { case B16_TYPE: tmp_bits.u16 = data.u16; break; @@ -1813,11 +2343,14 @@ void mov_impl( const ptx_instruction *pI, ptx_thread_info *thread ) } thread->set_vector_operand_values(dst,v[0],v[1],v[2],v[3],nelem); } else { - thread->set_operand_value(dst,tmp_bits); + thread->set_operand_value(dst,tmp_bits, i_type, thread, pI); } } else { - data = thread->get_operand_value(src1); - thread->set_operand_value(dst,data); + + data = thread->get_operand_value(src1, dst, i_type, thread, 1); + + thread->set_operand_value(dst, data, i_type, thread, pI); + } } @@ -1829,13 +2362,17 @@ void mul24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); - src2_data = thread->get_operand_value(src2); + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + + //src1_data = srcOperandModifiers(src1_data, src1, dst, i_type, thread); + //src2_data = srcOperandModifiers(src2_data, src2, dst, i_type, thread); + src1_data.mask_and(0,0x00FFFFFF); src2_data.mask_and(0,0x00FFFFFF); - unsigned i_type = pI->get_type(); - switch ( i_type ) { case S32_TYPE: if( src1_data.get_bit(23) ) @@ -1860,7 +2397,7 @@ void mul24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) data.mask_and(0,0xFFFFFFFF); } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst, data, i_type, thread, pI); } void mul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1871,10 +2408,11 @@ void mul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); ptx_reg_t d, t; - ptx_reg_t a = thread->get_operand_value(src1); - ptx_reg_t b = thread->get_operand_value(src2); unsigned i_type = pI->get_type(); + ptx_reg_t a = thread->get_operand_value(src1, dst, i_type, thread, 1); + ptx_reg_t b = thread->get_operand_value(src2, dst, i_type, thread, 1); + unsigned rounding_mode = pI->rounding_mode(); switch ( i_type ) { @@ -1930,7 +2468,9 @@ void mul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case RZ_OPTION: fesetround( FE_TOWARDZERO ); break; default: assert(0); break; } + d.f32 = a.f32 * b.f32; + if ( pI->saturation_mode() ) { if ( d.f32 < 0 ) d.f32 = 0; else if ( d.f32 > 1.0f ) d.f32 = 1.0f; @@ -1957,7 +2497,8 @@ void mul_impl( const ptx_instruction *pI, ptx_thread_info *thread ) assert(0); break; } - thread->set_operand_value(dst,d); + + thread->set_operand_value(dst, d, i_type, thread, pI); } void neg_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1967,9 +2508,10 @@ void neg_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - src1_data = thread->get_operand_value(src1); - unsigned to_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, to_type, thread, 1); + + switch ( to_type ) { case S8_TYPE: case S16_TYPE: @@ -1987,7 +2529,55 @@ void neg_impl( const ptx_instruction *pI, ptx_thread_info *thread ) default: assert(0); break; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, to_type, thread, pI); +} + +//nandn bitwise negates second operand then bitwise nands with the first operand +void nandn_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + ptx_reg_t src1_data, src2_data, data; + + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const operand_info &src2 = pI->src2(); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = (~src1_data.pred & src2_data.pred); + else + data.u64 = ~(src1_data.u64 & ~src2_data.u64); + + thread->set_operand_value(dst,data, i_type, thread, pI); + +} + +//norn bitwise negates first operand then bitwise ands with the second operand +void norn_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + ptx_reg_t src1_data, src2_data, data; + + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const operand_info &src2 = pI->src2(); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = ~(src1_data.pred & ~(src2_data.pred)); + else + data.u64 = ~(src1_data.u64) & src2_data.u64; + + thread->set_operand_value(dst,data, i_type, thread, pI); + } void not_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -1995,11 +2585,13 @@ void not_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, b, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { - case PRED_TYPE: d.pred = ~a.pred; break; + case PRED_TYPE: d.pred = (~(a.pred) & 0x000F); break; case B16_TYPE: d.u16 = ~a.u16; break; case B32_TYPE: d.u32 = ~a.u32; break; case B64_TYPE: d.u64 = ~a.u64; break; @@ -2009,7 +2601,7 @@ void not_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void or_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2018,12 +2610,38 @@ void or_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); - src2_data = thread->get_operand_value(src2); - data.u64 = src1_data.u64 | src2_data.u64; + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = ~(~(src1_data.pred) | ~(src2_data.pred)); + else + data.u64 = src1_data.u64 | src2_data.u64; + + thread->set_operand_value(dst,data, i_type, thread, pI); +} + +void orn_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + ptx_reg_t src1_data, src2_data, data; + const operand_info &dst = pI->dst(); + const operand_info &src1 = pI->src1(); + const operand_info &src2 = pI->src2(); + + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = ~(~(src1_data.pred) | (src2_data.pred)); + else + data.u64 = src1_data.u64 | ~src2_data.u64; - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI); } void pmevent_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -2037,9 +2655,11 @@ void rcp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t src1_data, src2_data, data; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - src1_data = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: data.f32 = 1.0f / src1_data.f32; @@ -2053,7 +2673,7 @@ void rcp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI); } void red_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -2066,12 +2686,13 @@ void rem_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); - src2_data = thread->get_operand_value(src2); + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); data.u64 = src1_data.u64 % src2_data.u64; - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI); } void ret_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2091,9 +2712,11 @@ void rsqrt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: if ( a.f32 < 0 ) { @@ -2125,7 +2748,7 @@ void rsqrt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } #define SAD(d,a,b,c) d = c + ((a<b) ? (b-a) : (a-b)) @@ -2137,11 +2760,13 @@ void sad_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src1(); const operand_info &src3 = pI->src1(); - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - c = thread->get_operand_value(src3); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + c = thread->get_operand_value(src3, dst, i_type, thread, 1); + + switch ( i_type ) { case U16_TYPE: SAD(d.u16,a.u16,b.u16,c.u16); break; case U32_TYPE: SAD(d.u32,a.u32,b.u32,c.u32); break; @@ -2157,7 +2782,7 @@ void sad_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void selp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2169,13 +2794,16 @@ void selp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, b, c, d; - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - c = thread->get_operand_value(src3); + unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + c = thread->get_operand_value(src3, dst, i_type, thread, 1); - d = (c.pred)?a:b; + //predicate value was changed so the lowest bit being set means the zero flag is set. + //As a result, the value of c.pred must be inverted to get proper behavior + d = (!(c.pred & 0x0001))?a:b; - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, PRED_TYPE, thread, pI); } bool isFloat(int type) @@ -2362,18 +2990,19 @@ void setp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) assert( pI->get_num_operands() < 4 ); // or need to deal with "c" operand / boolOp - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - unsigned type = pI->get_type(); unsigned cmpop = pI->get_cmpop(); + a = thread->get_operand_value(src1, dst, type, thread, 1); + b = thread->get_operand_value(src2, dst, type, thread, 1); t = CmpOp(type,a,b,cmpop); ptx_reg_t data; - data.pred = (t!=0); - thread->set_operand_value(dst,data); + //the way ptxplus handles the zero flag, 1 = false and 0 = true + data.pred = (t==0); //inverting predicate since ptxplus uses "1" for a set zero flag + + thread->set_operand_value(dst,data, PRED_TYPE, thread, pI); } void set_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2387,12 +3016,30 @@ void set_impl( const ptx_instruction *pI, ptx_thread_info *thread ) assert( pI->get_num_operands() < 4 ); // or need to deal with "c" operand / boolOp - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - unsigned src_type = pI->get_type2(); unsigned cmpop = pI->get_cmpop(); + a = thread->get_operand_value(src1, dst, src_type, thread, 1); + b = thread->get_operand_value(src2, dst, src_type, thread, 1); + + // Take abs of first operand if needed + if(pI->is_abs()) { + switch ( src_type ) { + case S16_TYPE: a.s16 = my_abs(a.s16); break; + case S32_TYPE: a.s32 = my_abs(a.s32); break; + case S64_TYPE: a.s64 = my_abs(a.s64); break; + case U16_TYPE: a.u16 = a.u16; break; + case U32_TYPE: a.u32 = my_abs(a.u32); break; + case U64_TYPE: a.u64 = my_abs(a.u64); break; + case F32_TYPE: a.f32 = my_abs(a.f32); break; + case F64_TYPE: a.f64 = my_abs(a.f64); break; + default: + printf("Execution error: type mismatch with instruction\n"); + assert(0); + break; + } + } + t = CmpOp(src_type,a,b,cmpop); ptx_reg_t data; @@ -2402,7 +3049,7 @@ void set_impl( const ptx_instruction *pI, ptx_thread_info *thread ) data.u32 = (t!=0)?0xFFFFFFFF:0; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst, data, pI->get_type(), thread, pI); } @@ -2412,26 +3059,28 @@ void shl_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - - unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + switch ( i_type ) { case B16_TYPE: + case U16_TYPE: if ( b.u16 >= 16 ) d.u16 = 0; else d.u16 = (unsigned short) ((a.u16 << b.u16) & 0xFFFF); break; case B32_TYPE: + case U32_TYPE: if ( b.u32 >= 32 ) d.u32 = 0; else d.u32 = (unsigned) ((a.u32 << b.u32) & 0xFFFFFFFF); break; case B64_TYPE: + case U64_TYPE: if ( b.u32 >= 64 ) d.u64 = 0; else @@ -2443,7 +3092,7 @@ void shl_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst, d, i_type, thread, pI); } void shr_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2452,10 +3101,12 @@ void shr_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + + switch ( i_type ) { case U16_TYPE: case B16_TYPE: @@ -2522,7 +3173,7 @@ void shr_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void sin_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2530,9 +3181,11 @@ void sin_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: d.f32 = sin(a.f32); @@ -2543,7 +3196,7 @@ void sin_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void slct_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2555,20 +3208,19 @@ void slct_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, b, c, d; - a = thread->get_operand_value(src1); - b = thread->get_operand_value(src2); - c = thread->get_operand_value(src3); - - bool t = false; + unsigned i_type = pI->get_type(); unsigned c_type = pI->get_type2(); + bool t = false; + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + b = thread->get_operand_value(src2, dst, i_type, thread, 1); + c = thread->get_operand_value(src3, dst, c_type, thread, 1); + switch ( c_type ) { case S32_TYPE: t = c.s32 >= 0; break; case F32_TYPE: t = c.f32 >= 0; break; default: assert(0); } - unsigned i_type = pI->get_type(); - switch ( i_type ) { case B16_TYPE: case U16_TYPE: d.u16 = t?a.u16:b.u16; break; @@ -2581,7 +3233,7 @@ void slct_impl( const ptx_instruction *pI, ptx_thread_info *thread ) default: assert(0); } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void sqrt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) @@ -2589,9 +3241,11 @@ void sqrt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t a, d; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); - a = thread->get_operand_value(src1); unsigned i_type = pI->get_type(); + a = thread->get_operand_value(src1, dst, i_type, thread, 1); + + switch ( i_type ) { case F32_TYPE: if ( a.f32 < 0 ) @@ -2609,18 +3263,19 @@ void sqrt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) break; } - thread->set_operand_value(dst,d); + thread->set_operand_value(dst,d, i_type, thread, pI); } void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); //may be scalar or vector of regs - ptx_reg_t addr_reg = thread->get_operand_value(dst); + unsigned type = pI->get_type(); + ptx_reg_t addr_reg = thread->get_operand_value(dst, dst, type, thread, 1); ptx_reg_t data; memory_space_t space = pI->get_space(); unsigned vector_spec = pI->get_vector(); - unsigned type = pI->get_type(); + memory_space *mem = NULL; addr_t addr = addr_reg.u32; @@ -2631,7 +3286,7 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) type_info_key::type_decode(type,size,t); if (!vector_spec) { - data = thread->get_operand_value(src1); + data = thread->get_operand_value(src1, dst, type, thread, 1); mem->write(addr,size/8,&data.s64,thread,pI); } else { if (vector_spec == V2_TYPE) { @@ -2666,30 +3321,54 @@ void st_impl( const ptx_instruction *pI, ptx_thread_info *thread ) void sub_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { ptx_reg_t data; + int overflow = 0; + int carry = 0; const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - ptx_reg_t src1_data = thread->get_operand_value(src1); - ptx_reg_t src2_data = thread->get_operand_value(src2); - unsigned i_type = pI->get_type(); + ptx_reg_t src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + ptx_reg_t src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); + //performs addition. Sets carry and overflow if needed. + //the constant is added in during subtraction so the carry bit is set properly. switch ( i_type ) { case S8_TYPE: + data.s64 = (src1_data.s64 & 0xFF) - (src2_data.s64 & 0xFF) + 0x100; + if(((src1_data.s64 & 0x80)-(src2_data.s64 & 0x80)) != 0) {overflow=((src1_data.s64 & 0x80)-(data.s64 & 0x80))==0?0:1; } + carry = (data.s32 & 0x100)>>8; + break; case S16_TYPE: + data.s64 = (src1_data.s64 & 0xFFFF) - (src2_data.s64 & 0xFFFF) + 0x10000; + if(((src1_data.s64 & 0x8000)-(src2_data.s64 & 0x8000)) != 0) {overflow=((src1_data.s64 & 0x8000)-(data.s64 & 0x8000))==0?0:1; } + carry = (data.s32 & 0x10000)>>16; + break; case S32_TYPE: + data.s64 = (src1_data.s64 & 0xFFFFFFFF) - (src2_data.s64 & 0xFFFFFFFF) + 0x100000000; + if(((src1_data.s64 & 0x80000000)-(src2_data.s64 & 0x80000000)) != 0) {overflow=((src1_data.s64 & 0x80000000)-(data.s64 & 0x80000000))==0?0:1; } + carry = ((data.u64)>>32) & 0x0001; + break; case S64_TYPE: data.s64 = src1_data.s64 - src2_data.s64; break; - case U8_TYPE: - case U16_TYPE: - case U32_TYPE: - case U64_TYPE: case B8_TYPE: + case U8_TYPE: + data.u64 = (src1_data.u64 & 0xFF) - (src2_data.u64 & 0xFF) + 0x100; + carry = (data.u64 & 0x100)>>8; + break; case B16_TYPE: + case U16_TYPE: + data.u64 = (src1_data.u64 & 0xFFFF) - (src2_data.u64 & 0xFFFF) + 0x10000; + carry = (data.u64 & 0x10000)>>16; + break; case B32_TYPE: + case U32_TYPE: + data.u64 = (src1_data.u64 & 0xFFFFFFFF) - (src2_data.u64 & 0xFFFFFFFF) + 0x100000000; + carry = (data.u64 & 0x100000000)>>32; + break; case B64_TYPE: + case U64_TYPE: data.u64 = src1_data.u64 - src2_data.u64; break; case F16_TYPE: assert(0); break; case F32_TYPE: data.f32 = src1_data.f32 - src2_data.f32; break; @@ -2697,7 +3376,12 @@ void sub_impl( const ptx_instruction *pI, ptx_thread_info *thread ) default: assert(0); break; } - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI, overflow, carry); +} + +void nop_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + // Do nothing } void subc_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); } @@ -2777,7 +3461,8 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) fflush(stdout); ptx_reg_t data1, data2, data3, data4; if (!ptx_tex_regs) ptx_tex_regs = new ptx_reg_t[4]; - thread->get_vector_operand_values(src2, ptx_tex_regs, 4); //ptx_reg should be 4 entry vector type...coordinates into texture + unsigned nelem = src2.get_vect_nelem(); + thread->get_vector_operand_values(src2, ptx_tex_regs, nelem); //ptx_reg should be 4 entry vector type...coordinates into texture assert(NameToTextureMap.find(texname) != NameToTextureMap.end());//use map to find texturerefence, then use map to find pointer to array struct textureReference* texref = NameToTextureMap[texname]; @@ -2905,6 +3590,9 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) case U8_TYPE: case U16_TYPE: case U32_TYPE: + case B8_TYPE: + case B16_TYPE: + case B32_TYPE: case S8_TYPE: case S16_TYPE: case S32_TYPE: @@ -2918,6 +3606,7 @@ void tex_impl( const ptx_instruction *pI, ptx_thread_info *thread ) } } break; + case B64_TYPE: case U64_TYPE: case S64_TYPE: mem->read( tex_array_index, 8, &data1.u64); @@ -3041,16 +3730,17 @@ void vote_impl( const ptx_instruction *pI, ptx_thread_info *thread ) ptx_reg_t src1_data; const operand_info &src1 = pI->src1(); - src1_data = thread->get_operand_value(src1); + src1_data = thread->get_operand_value(src1, pI->dst(), PRED_TYPE, thread, 1); - bool pred_value = src1_data.pred; + //predicate value was changed so the lowest bit being set means the zero flag is set. + //As a result, the value of src1_data.pred must be inverted to get proper behavior + bool pred_value = !(src1_data.pred & 0x0001); bool invert = src1.is_neg_pred(); threads_in_warp.push_back(thread); and_all &= (invert ^ pred_value); or_all |= (invert ^ pred_value); - // TODO: determine last active thread in warp... if( thread->get_hw_tid() == last_tid ) { bool pred_value = false; @@ -3062,11 +3752,11 @@ void vote_impl( const ptx_instruction *pI, ptx_thread_info *thread ) abort(); } ptx_reg_t data; - data.pred = pred_value?1:0; + data.pred = pred_value?0:1; //the way ptxplus handles the zero flag, 1 = false and 0 = true for( std::list<ptx_thread_info*>::iterator t=threads_in_warp.begin(); t!=threads_in_warp.end(); ++t ) { const operand_info &dst = pI->dst(); - (*t)->set_operand_value(dst,data); + (*t)->set_operand_value(dst,data, PRED_TYPE, (*t), pI); } first_in_warp = true; } @@ -3080,12 +3770,17 @@ void xor_impl( const ptx_instruction *pI, ptx_thread_info *thread ) const operand_info &src1 = pI->src1(); const operand_info &src2 = pI->src2(); - src1_data = thread->get_operand_value(src1); - src2_data = thread->get_operand_value(src2); + unsigned i_type = pI->get_type(); + src1_data = thread->get_operand_value(src1, dst, i_type, thread, 1); + src2_data = thread->get_operand_value(src2, dst, i_type, thread, 1); - data.u64 = src1_data.u64 ^ src2_data.u64; + //the way ptxplus handles predicates: 1 = false and 0 = true + if(i_type == PRED_TYPE) + data.pred = ~(~(src1_data.pred) ^ ~(src2_data.pred)); + else + data.u64 = src1_data.u64 ^ src2_data.u64; - thread->set_operand_value(dst,data); + thread->set_operand_value(dst,data, i_type, thread, pI); } void inst_not_implemented( const ptx_instruction * pI ) @@ -3101,3 +3796,61 @@ void print_instruction(const ptx_instruction *instruction) { } +ptx_reg_t srcOperandModifiers(ptx_reg_t opData, operand_info opInfo, operand_info dstInfo, unsigned type, ptx_thread_info *thread) +{ + ptx_reg_t result; + memory_space *mem = NULL; + size_t size; + int t; + result.u64=0; + + //complete other cases for reading from memory, such as reading from other const memory + if(opInfo.get_addr_space() == 1) + { + mem = g_global_mem; + type_info_key::type_decode(type,size,t); + mem->read(opData.u32,size/8,&result.u64); + if( type == S16_TYPE || type == S32_TYPE ) + sign_extend(result,size,dstInfo); + } + else if(opInfo.get_addr_space() == 2) + { + mem = thread->m_shared_mem; + type_info_key::type_decode(type,size,t); + mem->read(opData.u32,size/8,&result.u64); + + if( type == S16_TYPE || type == S32_TYPE ) + sign_extend(result,size,dstInfo); + + } + else if(opInfo.get_addr_space() == 3) + { + mem = g_global_mem; + type_info_key::type_decode(type,size,t); + + mem->read((opData.u32 + opInfo.get_const_mem_offset()),size/8,&result.u64); + + if( type == S16_TYPE || type == S32_TYPE ) + sign_extend(result,size,dstInfo); + } + else + { + result = opData; + } + + if(opInfo.get_operand_lohi() == 1) + { + result.u64 = result.u64 & 0xFFFF; + } + else if(opInfo.get_operand_lohi() == 2) + { + result.u64 = (result.u64>>16) & 0xFFFF; + } + + if(opInfo.get_operand_neg() == true) { + result.f32 = -result.f32; + } + + return result; +} + |
