summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspeverel <[email protected]>2016-06-06 14:48:13 -0700
committerspeverel <[email protected]>2016-06-06 14:48:13 -0700
commit8ed1522aede92bcafc60f69d7e03e6d48c44a86c (patch)
tree485de2040c6de040c4a71d7ff0985c801c3940bf
parentd68b2883629d4804737ce0501251ac88bdf4bea9 (diff)
Added support for BFE (Bit field extract) instruction.
-rw-r--r--src/cuda-sim/instructions.cc77
1 files changed, 76 insertions, 1 deletions
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index 4dd5ed8..02ce01c 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -1336,7 +1336,82 @@ void bar_impl( const ptx_instruction *pIin, ptx_thread_info *thread )
thread->m_last_dram_callback.instruction = pIin;
}
-void bfe_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); }
+void bfe_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ unsigned i_type = pI->get_type();
+ unsigned msb = (i_type == U32_TYPE || i_type == S32_TYPE) ? 31 : 63;
+ const operand_info &dst = pI->dst();
+ const operand_info &src1 = pI->src1();
+ const operand_info &src2 = pI->src2();
+ const operand_info &src3 = pI->src3();
+ 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 pos = b.u32 & 0xFF;
+ unsigned len = c.u32 & 0xFF;
+ unsigned d = 0;
+ switch (i_type)
+ {
+ case U32_TYPE:
+ {
+ unsigned mask;
+ d = a.u32 >> pos;
+ mask = 0xFFFFFFFF >> (32 - len);
+ d &= mask;
+ break;
+ }
+ case U64_TYPE:
+ {
+ unsigned long mask;
+ d = a.u64 >> pos;
+ mask = 0xFFFFFFFFFFFFFFFF >> (64 - len);
+ d &= mask;
+ break;
+ }
+ case S32_TYPE:
+ {
+ unsigned mask;
+ unsigned min = MY_MIN_I(pos + len - 1, msb);
+ unsigned sbit = len == 0 ? 0 : (a.s32 >> min) & 0x1;
+ d = a.s32 >> pos;
+ if (sbit > 0)
+ {
+ mask = 0xFFFFFFFF << len;
+ d |= mask;
+ }
+ else
+ {
+ mask = 0xFFFFFFFF >> (32 - len);
+ d &= mask;
+ }
+ break;
+ }
+ case S64_TYPE:
+ {
+ unsigned long mask;
+ unsigned min = MY_MIN_I(pos + len - 1, msb);
+ unsigned sbit = len == 0 ? 0 : (a.s64 >> min) & 0x1;
+ d = a.s64 >> pos;
+ if (sbit > 0)
+ {
+ mask = 0xFFFFFFFFFFFFFFFF << len;
+ d |= mask;
+ }
+ else
+ {
+ mask = 0xFFFFFFFFFFFFFFFF >> (64 - len);
+ d &= mask;
+ }
+ break;
+ }
+ default:
+ printf("Operand type not supported for BFE instruction.\n");
+ abort();
+ return;
+ }
+ thread->set_operand_value(dst,d, i_type, thread, pI);
+}
+
void bfi_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); }
void bfind_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); }