sim: added shift
[calu.git] / 3c_disasm / instr / shift.cpp
diff --git a/3c_disasm/instr/shift.cpp b/3c_disasm/instr/shift.cpp
new file mode 100644 (file)
index 0000000..e5a5245
--- /dev/null
@@ -0,0 +1,151 @@
+#include "../Iinstr.hpp"
+
+class Cshift : public Iinstr {
+               char m_typ;
+       public:
+               Cshift();
+               void evalInstr();
+               void execInstr();
+               std::string toString();
+               Iinstr* getNew();
+};
+
+/**
+ * Name:      create_instruction
+ * Purpose:   if compiled as shared library, this functions creates the 
+              instruction object
+
+ * Returns:   pointer to instruction object
+ */
+extern "C" Iinstr* create_instruction() {
+    return new Cshift();
+}
+
+Iinstr* Cshift::getNew()
+{
+       return new Cshift();
+}
+/**
+ * Name:      destroy_instruction
+ * Purpose:   if compiled as shared library, this functions destoys the 
+              instruction object
+
+ * Parameter: IInstruction - the instruction object to delete
+ */
+extern "C" void destroy_instruction(Iinstr* p) {
+    delete p;
+}
+
+Cshift::Cshift() : m_typ(0)
+{
+       opcode = B5(01010);
+       name = "shift";
+}
+
+void Cshift::evalInstr()
+{
+       this->m_d = argbits[0];
+       this->m_c = argbits[1];
+       argbits >>= 2;
+
+       dynamic_bitset<> type = argbits;
+       type.resize(2);
+       this->m_typ = type.to_ulong();
+
+       switch(this->m_typ) {
+               case 1:
+                       cerr << "INVALID shift type, using logic left shift!" << endl;
+                       this->m_typ = 0;
+               case 0:
+                       this->name = "lls";
+                       break;
+               case 2:
+                       this->name = "lrs";
+                       break;
+               case 3:
+                       this->name = "ars";
+                       break;
+               default:
+                       cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
+       }
+
+       argbits >>= 8;
+       dynamic_bitset<> immb = argbits;
+       immb.resize(5);
+       this->m_imm = immb.to_ulong();
+       argbits >>= 5;
+       m_ra = this->getRegister(argbits);
+       argbits >>= 4;
+       m_rd = this->getRegister(argbits);
+}
+
+void Cshift::execInstr()
+{
+       CDatd val = this->m_cpu->getRegister(m_ra);
+       switch(this->m_typ) {
+               case 0:
+               case 1:
+//                     this->name = "lls";
+                       for(unsigned int i = 0; i < m_imm; i++) {
+                               val = val << 1;
+                       }
+                       //carry
+                       if(m_c) {
+                               this->m_cpu->updateCarry(((val >> BIT_LEN) & 0x1) != 0);
+                       }
+                       break;
+               case 2:
+//                     this->name = "lrs";
+                       {
+                               bool carry = this->m_cpu->getCarry();
+                               for(unsigned int i = 0; i < m_imm; i++) {
+                                       val = val >> 1;
+
+                                       //carry!
+                                       //if user wants carry, and carry is set
+                                       if(this->m_c && carry) {
+                                               //set highest bit 1
+                                               val |= (CDat)(1<<(BIT_LEN-1));
+                                       }
+                                       else {
+                                               //set highest bit 0
+                                               val &= (~(1<<(BIT_LEN-1)));
+                                       }
+                               }
+                       }
+                       break;
+               case 3:
+//                     this->name = "ars";
+                       //>> is a ars, but val is CDatd => we have to set the MSB manually
+                       {
+                               bool msb = (val & (1<<(BIT_LEN-1)) >> (BIT_LEN-1));
+                               for(unsigned int i = 0; i < m_imm; i++) {
+                                       val = val >> 1;
+                                       if(msb) {
+                                               //set highest bit 1
+                                               val |= (CDat)(1<<(BIT_LEN-1));
+                                       }
+                                       else {
+                                       //set highest bit 0
+                                       val &= (~(1<<(BIT_LEN-1)));
+                                       }
+                               }
+                       }
+                       break;
+               default:
+                       cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
+       }
+       this->m_cpu->setRegister(m_rd, val);
+}
+
+std::string Cshift::toString()
+{
+       stringstream op;
+       op << this->getName();
+       if(m_c) op << "C";
+       if(m_d) op << "D";
+
+       op << this->getConditionFlag();
+       op << " r" << m_rd << ", r" << m_ra << ", " << m_imm;
+       return op.str();
+}