summaryrefslogtreecommitdiff
path: root/src/cuda-sim/instructions.cc
diff options
context:
space:
mode:
authorWilson Fung <[email protected]>2012-07-05 07:33:54 -0800
committerAndrew Boktor <[email protected]>2014-08-14 13:47:33 -0700
commit6f99ffb9b171495df7ef0725f8a8cbffb8d9591c (patch)
tree2915c2e1da7dbac024fcb5da6f845f6d47092629 /src/cuda-sim/instructions.cc
parent3d2d74e5e876e10c207756fa9b3b7508a6a92f8a (diff)
Adding the madp instruction, which does multiply add with carry-in. Still need to modify carry and overflow flags.
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 13317]
Diffstat (limited to 'src/cuda-sim/instructions.cc')
-rw-r--r--src/cuda-sim/instructions.cc52
1 files changed, 35 insertions, 17 deletions
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;