v6m virtual machine

Dependents:  

Import programemu812

mbed LPC812 emulator pre-alpha version

Import programemu1114

mbed LPC1114 emulator pre-alpha version

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Thu Aug 27 13:24:50 2015 +0900
Parent:
3:fe333683e8f7
Child:
5:65d77b2e6bc7
Commit message:
fix BL branch range.

Changed in this revision

BaseV6M.cpp Show annotated file Show diff for this revision Revisions of this file
BaseV6M.h Show annotated file Show diff for this revision Revisions of this file
--- a/BaseV6M.cpp	Thu Aug 20 18:08:34 2015 +0900
+++ b/BaseV6M.cpp	Thu Aug 27 13:24:50 2015 +0900
@@ -1,4 +1,4 @@
-// BaseV6M.cpp 2015/8/20
+// BaseV6M.cpp 2015/8/27
 #pragma Otime
 
 #include "BaseV6M.h"
@@ -247,6 +247,16 @@
     Rn = &R[immed(code, 3, 8)];
 }
 
+void BaseV6M::d32_Rd_SYSm(uint32_t code, uint32_t code2nd) { // MRS
+    Rd = &R[immed(code2nd, 4, 8)];
+    int m = immed(code2nd, 7, 0);
+}
+
+void BaseV6M::d32_Rn_SYSm(uint32_t code, uint32_t code2nd) { // MSR
+    Rn = &R[immed(code, 4, 0)];
+    int m = immed(code2nd, 7, 0);
+}
+
 void BaseV6M::e_adc() { // ADC Rd,Rn,Rm|imm
     uint32_t n = *Rn;
     uint32_t m = *Rm;
@@ -545,13 +555,77 @@
     V6M_INFO("I: B 0x%08x ; backward", addr);
 }
 
-void BaseV6M::c_bl(uint32_t code) { // BL 0xf000-0xf7ff
-    uint32_t addr = R[_PC] + (signed_immed(code, 11) * 2048*2);
+void BaseV6M::c32_bl_forward(uint32_t code) { // BL 0xf000-0xf2ff
     R[_LR] = R[_PC] | 1;
-    V6M_ASSERT((code2nd&0xe000) == 0xe000);
-    addr += (immed(code2nd, 11) * 2);
+    uint32_t imm32 = immed(code, 10)<<12|immed(code2nd, 11)<<1;
+    if ((code2nd & (1<<13)) == 0) { // J1
+        imm32 |= (1<<23);
+    }
+    if ((code2nd & (1<<11)) == 0) { // J2
+        imm32 |= (1<<22);
+    }
+    uint32_t addr = R[_PC] + imm32;
+    V6M_ASSERT((code2nd&0xd000) == 0xd000);
     jump(addr);
-    V6M_INFO("I: BL 0x%08x", addr);
+    V6M_INFO("I: BL 0x%08x ; forward", addr);
+}
+
+void BaseV6M::c32_bl_forward3(uint32_t code) { // BL 0xf300-0xf3ff
+    if ((code2nd&0xd000) == 0xd000) {
+        c32_bl_forward(code);
+        return;
+    }
+    if ((code&0xf0) == 0x80) {
+        c32_msr(code, code2nd);
+    } else if ((code&0xff) == 0xbf) {
+        c32_dsb_dmb_isb(code, code2nd);
+    } else if ((code&0xff) == 0xef) {
+        c32_mrs(code, code2nd);
+    } else {
+        V6M_ASSERT(0);
+    }
+}
+
+void BaseV6M::c32_mrs(uint32_t code, uint32_t code2nd) {
+    d32_Rd_SYSm(code, code2nd);
+    jump(R[_PC]);
+    V6M_INFO("I: MRS %s,%s", GetRegName(Rd), GetSysName(Rm));
+}
+
+void BaseV6M::c32_msr(uint32_t code, uint32_t code2nd) {
+    d32_Rn_SYSm(code, code2nd);
+    jump(R[_PC]);
+    V6M_INFO("I: MSR %s,%s", GetSysName(Rm), GetRegName(Rn));
+}
+
+void BaseV6M::c32_dsb_dmb_isb(uint32_t code, uint32_t code2nd) {
+    if (code2nd == 0x8f4f) {
+        jump(R[_PC]);
+        V6M_INFO("I: DSB.W");
+    } else if (code2nd == 0x8f5f) {
+        jump(R[_PC]);
+        V6M_INFO("I: DMB.W");
+    } else if (code2nd == 0x8f6f) {
+        jump(R[_PC]);
+        V6M_INFO("I: ISB.W");
+    } else {
+        V6M_ASSERT(0);
+    }
+}
+
+void BaseV6M::c32_bl_backward(uint32_t code) { // BL 0xf400-0xf7ff
+    R[_LR] = R[_PC] | 1;
+    uint32_t imm32 = 0xff000000|immed(code, 10)<<12|immed(code2nd, 11)<<1;
+    if (code2nd & (1<<13)) { // J1
+        imm32 |= (1<<23);
+    }
+    if (code2nd & (1<<11)) { // J2
+        imm32 |= (1<<22);
+    }
+    uint32_t addr = R[_PC] + imm32;
+    V6M_ASSERT((code2nd&0xd000) == 0xd000);
+    jump(addr);
+    V6M_INFO("I: BL 0x%08x ; backward", addr);
 }
 
 void BaseV6M::c_bx(uint32_t code) { // BX BLX 0x4770
@@ -1064,7 +1138,9 @@
         case 0xdd: c_ble(code); break;
         case 0xe0 ... 0xe3: c_b_forward(code); break;
         case 0xe4 ... 0xe7: c_b_backward(code); break;
-        case 0xf0 ... 0xf7: c_bl(code); break;
+        case 0xf0 ... 0xf2: c32_bl_forward(code); break;
+        case 0xf3: c32_bl_forward3(code); break;
+        case 0xf4 ... 0xf7: c32_bl_backward(code); break;
         case 0x47: c_bx(code); break;
         case 0x18 ... 0x19: c_add(code); break;
         case 0x1a ... 0x1b: c_sub(code); break;
--- a/BaseV6M.h	Thu Aug 20 18:08:34 2015 +0900
+++ b/BaseV6M.h	Thu Aug 27 13:24:50 2015 +0900
@@ -1,4 +1,4 @@
-// BaseV6M.h 2015/8/9
+// BaseV6M.h 2015/8/27
 #pragma once
 #include <stdint.h>
 
@@ -90,6 +90,8 @@
     void d_Rm_Rn_Rd(uint32_t code); // LDR Rd,[Rn,Rm]
     void d_reg_list(uint32_t code); // PUSH / POP
     void d_Rn_reg_list(uint32_t code); // LDM / STM
+    void d32_Rd_SYSm(uint32_t code, uint32_t code2nd); // MRS
+    void d32_Rn_SYSm(uint32_t code, uint32_t code2nd); // MSR
     void e_adc(); // ADC Rd,Rn,Rm|imm
     void e_sbc(); // SBC Rd,Rn,Rm|imm
     void e_add(); // ADD Rd,Rn,Rm|imm
@@ -125,7 +127,12 @@
     void c_ble(uint32_t code); // BLE 0xdd00-0xddff
     void c_b_forward(uint32_t code); // B 0xe000-0xe3ff
     void c_b_backward(uint32_t code); // B 0xe400-0xe7ff
-    void c_bl(uint32_t code); // BL 0xf000-0xf7ff
+    void c32_bl_forward(uint32_t code); // BL 0xf000-0xf2ff
+    void c32_bl_forward3(uint32_t code); // BL 0xf300-0xf3ff
+    void c32_mrs(uint32_t code, uint32_t code2nd);
+    void c32_msr(uint32_t code, uint32_t code2nd);
+    void c32_dsb_dmb_isb(uint32_t code, uint32_t code2nd);
+    void c32_bl_backward(uint32_t code); // BL 0xf400-0xf7ff
     void c_bx(uint32_t code); // BX BLX 0x4770
     void c_add(uint32_t code); // ADDS Rd,Rn,Rm 0x1800-0x19ff
     void c_sub(uint32_t code); // SUBS Rd,Rn,Rm 0x1a00-0x1bff
@@ -195,7 +202,6 @@
     void c_swi(uint32_t code); // SWI #imm8 0xdf00-0xdfff
     void c_cps(uint32_t code); // CPSIE|CPSID A|I|F 0xb6c0-0xb6e7
     void c_todo(uint32_t code); // undefined code
-
 };