sim: added shift
authorMartin Perner <martin@perner.cc>
Mon, 1 Nov 2010 21:28:14 +0000 (22:28 +0100)
committerMartin Perner <martin@perner.cc>
Mon, 1 Nov 2010 21:29:23 +0000 (22:29 +0100)
not extensiv tested

3a_asm/tst/shift.s [new file with mode: 0644]
3b_sim/ccpu.cpp
3b_sim/ccpu.hpp
3c_disasm/instr/shift.cpp [new file with mode: 0644]

diff --git a/3a_asm/tst/shift.s b/3a_asm/tst/shift.s
new file mode 100644 (file)
index 0000000..86f61e9
--- /dev/null
@@ -0,0 +1,9 @@
+ldis r0, 1
+lls r0, r0, 1
+llsc r0, r0, 1
+lls r1, r0, 29
+lls r1, r1, 1
+llsc r0, r0, 30
+lrsc r2, r2, 5
+ars  r2, r2, 5
+ars  r1, r1, 5
index 4974fcc64d78dfbf4fc7b30f7bc9d1eef1748e90..fb480f48fec4843aa2f9121f199d9a27023c0f10 100644 (file)
@@ -124,6 +124,16 @@ void CCpu::updateFlags(CDatd val, CDat a, CDat b) {
        this->m_O = (this->m_S != v);
 }
 
+void CCpu::updateCarry(bool c)
+{
+       this->m_C = c;
+}
+
+bool CCpu::getCarry()
+{
+       return this->m_C;
+}
+
 void CCpu::updateFlags(bool z, bool o, bool c, bool s)
 {
        this->m_Z = z;
index 24f6f31b073da00fe23c1c1adfa35ee70a4323f4..0dd8b1bde760d5942aaabeae35ac1b8fe33afd91 100644 (file)
@@ -45,7 +45,10 @@ class CCpu {
                void updateFlags(CDatd, CDat, CDat);
                /* will change all flags */
                void updateFlags(bool z, bool o, bool c, bool s);
-       
+               /* will change carry */
+               void updateCarry(bool c);
+
+               bool getCarry();
 
                bool conditionMet(short);
 
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();
+}