v6m virtual machine

Dependents:  

Import programemu812

mbed LPC812 emulator pre-alpha version

Import programemu1114

mbed LPC1114 emulator pre-alpha version

Revision:
3:fe333683e8f7
Parent:
2:078d2e512ba4
Child:
4:1c7b72bcfc4d
--- a/BaseV6M.cpp	Wed Aug 19 16:50:07 2015 +0900
+++ b/BaseV6M.cpp	Thu Aug 20 18:08:34 2015 +0900
@@ -1,4 +1,4 @@
-// BaseV6M.cpp 2015/8/19
+// BaseV6M.cpp 2015/8/20
 #pragma Otime
 
 #include "BaseV6M.h"
@@ -129,7 +129,7 @@
 }
 
 void BaseV6M::jump(uint32_t addr) {
-    R[_PC] = addr;
+    R[_PC] = align16(addr);
     cache = false;
 }
 
@@ -419,7 +419,7 @@
     NZupdate(data);
 }
 
-void BaseV6M::c_beq(uint32_t code) { // BEQ #0xd000-0xd0ff
+void BaseV6M::c_beq(uint32_t code) { // BEQ 0xd000-0xd0ff
     uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
     if (Z() == 1) {
         jump(addr);
@@ -435,7 +435,7 @@
     V6M_INFO("I: BNE 0x%08x", addr);
 }
 
-void BaseV6M::c_bcs(uint32_t code) { // BCS #0xd200-0xd2ff
+void BaseV6M::c_bcs(uint32_t code) { // BCS 0xd200-0xd2ff
     uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
     if (C() == 1) {
         jump(addr);
@@ -443,7 +443,7 @@
     V6M_INFO("I: BCS 0x%08x", addr);
 }
 
-void BaseV6M::c_bcc(uint32_t code) { // BCC #0xd300-0xd3ff
+void BaseV6M::c_bcc(uint32_t code) { // BCC 0xd300-0xd3ff
     uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
     if (C() == 0) {
         jump(addr);
@@ -715,7 +715,13 @@
 void BaseV6M::c_add_hr(uint32_t code) { // ADD Rd,Rm (high reg) 0x4400-0x44ff
     d_D_M_Rm_Rd(code);
     *Rd = add32(*Rn, *Rm);
-    V6M_INFO("I: ADD %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
+    if (Rd == &R[_PC]) {
+        jump(R[_PC]);
+        V6M_INFO("I: ADD pc,pc,%s ; pc=0x%08x", GetRegName(Rn), R[_PC]);
+        exception_return();
+    } else {
+        V6M_INFO("I: ADD %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
+    }
 }
 
 void BaseV6M::c_cmp_hr(uint32_t code) { // CMP Rd,Rm (high reg) 0x4500-0x45ff
@@ -1026,12 +1032,13 @@
 }
 
 void BaseV6M::fetch() {
+    V6M_ASSERT((R[_PC]&1) == 0);
     if (cache) {
         code = code2nd;
-        code2nd = peek16(align16(R[_PC]));
+        code2nd = peek16(R[_PC]);
         R[_PC] += 2;
     } else {
-        uint32_t d = peek32(align16(R[_PC]));
+        uint32_t d = peek32(R[_PC]);
         code = d & 0xffff;
         code2nd = d>>16;
         R[_PC] += 4;
@@ -1117,7 +1124,7 @@
 void BaseV6M::reset() {
     R[_SP] = peek32(0x00000000);
     R[_PC] = peek32(0x00000004);
-    cache = false;
+    jump(R[_PC]);
 }
 
 void BaseV6M::run(int step) {