v6m virtual machine
Import programemu812
mbed LPC812 emulator pre-alpha version
Import programemu1114
mbed LPC1114 emulator pre-alpha version
Revision 4:1c7b72bcfc4d, committed 2015-08-27
- 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 - };