summaryrefslogtreecommitdiff
path: root/src/cuda-sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuda-sim')
-rw-r--r--src/cuda-sim/instructions.cc71
-rw-r--r--src/cuda-sim/opcodes.def1
-rw-r--r--src/cuda-sim/ptx.l1
3 files changed, 73 insertions, 0 deletions
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index 4537bd0..fd9a9ac 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -674,6 +674,77 @@ void abs_impl( const ptx_instruction *pI, ptx_thread_info *thread )
thread->set_operand_value(dst,d, i_type, thread, pI);
}
+void addp_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ //PTXPlus add instruction with carry (carry is kept in a predicate) register
+ ptx_reg_t src1_data, src2_data, src3_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();
+ const operand_info &src3 = pI->src3();
+
+ 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);
+ src3_data = thread->get_operand_value(src3, dst, i_type, thread, 1);
+
+ unsigned rounding_mode = pI->rounding_mode();
+ int orig_rm = fegetround();
+ switch ( rounding_mode ) {
+ case RN_OPTION: break;
+ case RZ_OPTION: fesetround( FE_TOWARDZERO ); break;
+ default: assert(0); break;
+ }
+
+ //performs addition. Sets carry and overflow if needed.
+ //src3_data.pred&0x4 is the carry flag
+ switch ( i_type ) {
+ case S8_TYPE:
+ data.s64 = (src1_data.s64 & 0x0000000FF) + (src2_data.s64 & 0x0000000FF) + (src3_data.pred & 0x4);
+ 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) + (src3_data.pred & 0x4);
+ 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) + (src3_data.pred & 0x4);
+ 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 + (src3_data.pred & 0x4);
+ break;
+ case U8_TYPE:
+ data.u64 = (src1_data.u64 & 0xFF) + (src2_data.u64 & 0xFF) + (src3_data.pred & 0x4);
+ carry = (data.u64 & 0x100)>>8;
+ break;
+ case U16_TYPE:
+ data.u64 = (src1_data.u64 & 0xFFFF) + (src2_data.u64 & 0xFFFF) + (src3_data.pred & 0x4);
+ carry = (data.u64 & 0x10000)>>16;
+ break;
+ case U32_TYPE:
+ data.u64 = (src1_data.u64 & 0xFFFFFFFF) + (src2_data.u64 & 0xFFFFFFFF) + (src3_data.pred & 0x4);
+ carry = (data.u64 & 0x100000000)>>32;
+ break;
+ case U64_TYPE:
+ data.s64 = src1_data.s64 + src2_data.s64 + (src3_data.pred & 0x4);
+ break;
+ case F16_TYPE: assert(0); break;
+ case F32_TYPE: data.f32 = src1_data.f32 + src2_data.f32; break;
+ case F64_TYPE: case FF64_TYPE: data.f64 = src1_data.f64 + src2_data.f64; break;
+ default: assert(0); break;
+ }
+ fesetround( orig_rm );
+
+ thread->set_operand_value(dst, data, i_type, thread, pI, overflow, carry );
+}
+
void add_impl( const ptx_instruction *pI, ptx_thread_info *thread )
{
ptx_reg_t src1_data, src2_data, data;
diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def
index 0963fa6..adeea86 100644
--- a/src/cuda-sim/opcodes.def
+++ b/src/cuda-sim/opcodes.def
@@ -39,6 +39,7 @@ Other 10
*/
OP_DEF(ABS_OP,abs_impl,"abs",1,1)
OP_DEF(ADD_OP,add_impl,"add",1,1)
+OP_DEF(ADDP_OP,addp_impl,"addp",1,1)
OP_DEF(ADDC_OP,addc_impl,"addc",1,1)
OP_DEF(AND_OP,and_impl,"and",1,1)
OP_DEF(ANDN_OP,andn_impl,"andn",1,1)
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 8c330fc..1d50a8d 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -53,6 +53,7 @@ int ptx_error( const char *s );
abs TC; ptx_lval.int_value = ABS_OP; return OPCODE;
add TC; ptx_lval.int_value = ADD_OP; return OPCODE;
+addp TC; ptx_lval.int_value = ADDP_OP; return OPCODE;
addc TC; ptx_lval.int_value = ADDC_OP; return OPCODE;
and TC; ptx_lval.int_value = AND_OP; return OPCODE;
andn TC; ptx_lval.int_value = ANDN_OP; return OPCODE;