diff options
| -rw-r--r-- | src/cuda-sim/cuda-sim.cc | 2 | ||||
| -rw-r--r-- | src/cuda-sim/instructions.cc | 52 | ||||
| -rw-r--r-- | src/cuda-sim/opcodes.def | 1 | ||||
| -rw-r--r-- | src/cuda-sim/ptx.l | 1 |
4 files changed, 38 insertions, 18 deletions
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc index 7fa13b2..752985c 100644 --- a/src/cuda-sim/cuda-sim.cc +++ b/src/cuda-sim/cuda-sim.cc @@ -565,7 +565,7 @@ void ptx_instruction::set_opcode_and_latency() break; } break; - case MAD_OP: + case MAD_OP: case MADP_OP: //MAD latency switch(get_type()){ case F32_TYPE: diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc index fd9a9ac..def0c55 100644 --- a/src/cuda-sim/instructions.cc +++ b/src/cuda-sim/instructions.cc @@ -2035,7 +2035,7 @@ void exit_impl( const ptx_instruction *pI, ptx_thread_info *thread ) thread->registerExit(); } -void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ); +void mad_def( const ptx_instruction *pI, ptx_thread_info *thread, bool use_carry = false ); void fma_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { @@ -2245,10 +2245,15 @@ void mad24_impl( const ptx_instruction *pI, ptx_thread_info *thread ) void mad_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { - mad_def(pI,thread); + mad_def(pI, thread, false); +} + +void madp_impl( const ptx_instruction *pI, ptx_thread_info *thread ) +{ + mad_def(pI, thread, true); } -void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ) +void mad_def( const ptx_instruction *pI, ptx_thread_info *thread, bool use_carry ) { const operand_info &dst = pI->dst(); const operand_info &src1 = pI->src1(); @@ -2261,55 +2266,67 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ) 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); + // take the carry bit, it should be the 4th operand + ptx_reg_t carry_bit; + carry_bit.u64 = 0; + if (use_carry) { + const operand_info &carry = pI->operand_lookup(4); + carry_bit = thread->get_operand_value(carry, dst, PRED_TYPE, thread, 0); + carry_bit.pred &= 0x4; + } + unsigned rounding_mode = pI->rounding_mode(); switch ( i_type ) { case S16_TYPE: t.s32 = a.s16 * b.s16; - if ( pI->is_wide() ) d.s32 = t.s32 + c.s32; - else if ( pI->is_hi() ) d.s16 = (t.s32>>16) + c.s16; - else if ( pI->is_lo() ) d.s16 = t.s16 + c.s16; + if ( pI->is_wide() ) d.s32 = t.s32 + c.s32 + carry_bit.pred; + else if ( pI->is_hi() ) d.s16 = (t.s32>>16) + c.s16 + carry_bit.pred; + else if ( pI->is_lo() ) d.s16 = t.s16 + c.s16 + carry_bit.pred; else assert(0); break; case S32_TYPE: t.s64 = a.s32 * b.s32; - if ( pI->is_wide() ) d.s64 = t.s64 + c.s64; - else if ( pI->is_hi() ) d.s32 = (t.s64>>32) + c.s32; - else if ( pI->is_lo() ) d.s32 = t.s32 + c.s32; + if ( pI->is_wide() ) d.s64 = t.s64 + c.s64 + carry_bit.pred; + else if ( pI->is_hi() ) d.s32 = (t.s64>>32) + c.s32 + carry_bit.pred; + else if ( pI->is_lo() ) d.s32 = t.s32 + c.s32 + carry_bit.pred; else assert(0); break; case S64_TYPE: t.s64 = a.s64 * b.s64; assert( !pI->is_wide() ); assert( !pI->is_hi() ); - if ( pI->is_lo() ) d.s64 = t.s64 + c.s64; + assert( use_carry == false); + if ( pI->is_lo() ) d.s64 = t.s64 + c.s64 + carry_bit.pred; else assert(0); break; case U16_TYPE: t.u32 = a.u16 * b.u16; - if ( pI->is_wide() ) d.u32 = t.u32 + c.u32; - else if ( pI->is_hi() ) d.u16 = (t.u32>>16) + c.u16; - else if ( pI->is_lo() ) d.u16 = t.u16 + c.u16; + if ( pI->is_wide() ) d.u32 = t.u32 + c.u32 + carry_bit.pred; + else if ( pI->is_hi() ) d.u16 = (t.u32 + c.u16 + carry_bit.pred)>>16; + else if ( pI->is_lo() ) d.u16 = t.u16 + c.u16 + carry_bit.pred; else assert(0); break; case U32_TYPE: t.u64 = a.u32 * b.u32; - if ( pI->is_wide() ) d.u64 = t.u64 + c.u64; - else if ( pI->is_hi() ) d.u32 = (t.u64>>32) + c.u32; - else if ( pI->is_lo() ) d.u32 = t.u32 + c.u32; + if ( pI->is_wide() ) d.u64 = t.u64 + c.u64 + carry_bit.pred; + else if ( pI->is_hi() ) d.u32 = (t.u64 + c.u32 + carry_bit.pred)>>32; + else if ( pI->is_lo() ) d.u32 = t.u32 + c.u32 + carry_bit.pred; else assert(0); break; case U64_TYPE: t.u64 = a.u64 * b.u64; assert( !pI->is_wide() ); assert( !pI->is_hi() ); - if ( pI->is_lo() ) d.u64 = t.u64 + c.u64; + assert( use_carry == false); + if ( pI->is_lo() ) d.u64 = t.u64 + c.u64 + carry_bit.pred; else assert(0); break; case F16_TYPE: assert(0); break; case F32_TYPE: { + assert( use_carry == false); int orig_rm = fegetround(); switch ( rounding_mode ) { case RN_OPTION: break; @@ -2325,6 +2342,7 @@ void mad_def( const ptx_instruction *pI, ptx_thread_info *thread ) break; } case F64_TYPE: case FF64_TYPE: { + assert( use_carry == false); int orig_rm = fegetround(); switch ( rounding_mode ) { case RN_OPTION: break; diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def index adeea86..46e6d94 100644 --- a/src/cuda-sim/opcodes.def +++ b/src/cuda-sim/opcodes.def @@ -68,6 +68,7 @@ OP_DEF(LDU_OP,ldu_impl,"ldu",1,5) OP_DEF(LG2_OP,lg2_impl,"lg2",1,4) OP_DEF(MAD24_OP,mad24_impl,"mad24",1,2) OP_DEF(MAD_OP,mad_impl,"mad",1,2) +OP_DEF(MADP_OP,mad_impl,"mad",1,2) OP_DEF(MAX_OP,max_impl,"max",1,1) OP_DEF(MEMBAR_OP,membar_impl,"membar",1,3) OP_DEF(MIN_OP,min_impl,"min",1,1) diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l index 648de30..4747181 100644 --- a/src/cuda-sim/ptx.l +++ b/src/cuda-sim/ptx.l @@ -84,6 +84,7 @@ ldu TC; ptx_lval.int_value = LDU_OP; return OPCODE; lg2 TC; ptx_lval.int_value = LG2_OP; return OPCODE; mad24 TC; ptx_lval.int_value = MAD24_OP; return OPCODE; mad TC; ptx_lval.int_value = MAD_OP; return OPCODE; +madp TC; ptx_lval.int_value = MADP_OP; return OPCODE; max TC; ptx_lval.int_value = MAX_OP; return OPCODE; membar TC; ptx_lval.int_value = MEMBAR_OP; return OPCODE; min TC; ptx_lval.int_value = MIN_OP; return OPCODE; |
