v6m virtual machine

Dependents:  

Import programemu812

mbed LPC812 emulator pre-alpha version

Import programemu1114

mbed LPC1114 emulator pre-alpha version

Committer:
va009039
Date:
Mon Aug 10 22:39:26 2015 +0900
Revision:
1:5fa0120a6169
Parent:
0:c2ad7f15d6a8
Child:
2:078d2e512ba4
add files.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 1:5fa0120a6169 1 // BaseV6M.cpp 2015/8/9
va009039 1:5fa0120a6169 2 #pragma Otime
va009039 1:5fa0120a6169 3
va009039 1:5fa0120a6169 4 #include "BaseV6M.h"
va009039 1:5fa0120a6169 5 #include "v6m_log.h"
va009039 1:5fa0120a6169 6
va009039 1:5fa0120a6169 7 const char* RegName[] = {
va009039 1:5fa0120a6169 8 "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","sp","lr","pc",
va009039 1:5fa0120a6169 9 "_xPSR","_IM","_NL"};
va009039 1:5fa0120a6169 10
va009039 1:5fa0120a6169 11 const uint32_t NZCVlookup[] = { // (d,m,n): (N,Z,C,V)
va009039 1:5fa0120a6169 12 /* (0,0,0): */ 0UL<<31|0<<30|0<<29|0<<28,
va009039 1:5fa0120a6169 13 /* (1,0,0): */ 1UL<<31|0<<30|0<<29|1<<28,
va009039 1:5fa0120a6169 14 /* (0,1,0): */ 0UL<<31|0<<30|1<<29|0<<28,
va009039 1:5fa0120a6169 15 /* (1,1,0): */ 1UL<<31|0<<30|0<<29|0<<28,
va009039 1:5fa0120a6169 16 /* (0,0,1): */ 0UL<<31|0<<30|1<<29|0<<28,
va009039 1:5fa0120a6169 17 /* (1,0,1): */ 1UL<<31|0<<30|0<<29|0<<28,
va009039 1:5fa0120a6169 18 /* (0,1,1): */ 0UL<<31|0<<30|1<<29|1<<28,
va009039 1:5fa0120a6169 19 /* (1,1,1): */ 1UL<<31|0<<30|1<<29|0<<28,};
va009039 1:5fa0120a6169 20
va009039 1:5fa0120a6169 21 static inline uint32_t immed(uint32_t code, int width, int base = 0) { // unsigned immed
va009039 1:5fa0120a6169 22 return (code>>base) & ((1<<width)-1);
va009039 1:5fa0120a6169 23 }
va009039 1:5fa0120a6169 24
va009039 1:5fa0120a6169 25 static inline int32_t signed_immed(uint32_t code, int width, int base = 0) { // signed immed
va009039 1:5fa0120a6169 26 int32_t i = immed(code, width, base);
va009039 1:5fa0120a6169 27 if (i & (1<<(width-1))) {
va009039 1:5fa0120a6169 28 return i - (1<<width);
va009039 1:5fa0120a6169 29 }
va009039 1:5fa0120a6169 30 return i;
va009039 1:5fa0120a6169 31 }
va009039 1:5fa0120a6169 32
va009039 1:5fa0120a6169 33 static inline uint32_t add32(uint32_t a, uint32_t b) {
va009039 1:5fa0120a6169 34 return (a + b) & 0xffffffff;
va009039 1:5fa0120a6169 35 }
va009039 1:5fa0120a6169 36
va009039 1:5fa0120a6169 37 static inline uint32_t mul32(uint32_t a, uint32_t b) {
va009039 1:5fa0120a6169 38 return (a * b) & 0xffffffff;
va009039 1:5fa0120a6169 39 }
va009039 1:5fa0120a6169 40
va009039 1:5fa0120a6169 41 static inline uint32_t not32(uint32_t data) {
va009039 1:5fa0120a6169 42 return (~data)&0xffffffff;
va009039 1:5fa0120a6169 43 }
va009039 1:5fa0120a6169 44
va009039 1:5fa0120a6169 45 static inline uint32_t align32(uint32_t addr) {
va009039 1:5fa0120a6169 46 return addr & 0xfffffffc;
va009039 1:5fa0120a6169 47 }
va009039 1:5fa0120a6169 48
va009039 1:5fa0120a6169 49 static inline uint32_t align16(uint32_t addr) {
va009039 1:5fa0120a6169 50 return addr & 0xfffffffe;
va009039 1:5fa0120a6169 51 }
va009039 1:5fa0120a6169 52
va009039 1:5fa0120a6169 53 BaseV6M::BaseV6M() {
va009039 1:5fa0120a6169 54 Rd = Rn = Rm = &R[0];
va009039 1:5fa0120a6169 55 cycle = 0;
va009039 1:5fa0120a6169 56 R[8] = R[9] = R[10] = R[11] = R[12] = 0xffffffff;
va009039 1:5fa0120a6169 57 }
va009039 1:5fa0120a6169 58
va009039 1:5fa0120a6169 59 const char* BaseV6M::GetRegName(uint32_t* pR) {
va009039 1:5fa0120a6169 60 return RegName[GetRegIndex(pR)];
va009039 1:5fa0120a6169 61 }
va009039 1:5fa0120a6169 62
va009039 1:5fa0120a6169 63 int BaseV6M::GetRegIndex(uint32_t* pR) {
va009039 1:5fa0120a6169 64 if (pR == &R[0]) return 0;
va009039 1:5fa0120a6169 65 if (pR == &R[1]) return 1;
va009039 1:5fa0120a6169 66 if (pR == &R[2]) return 2;
va009039 1:5fa0120a6169 67 if (pR == &R[3]) return 3;
va009039 1:5fa0120a6169 68 if (pR == &R[4]) return 4;
va009039 1:5fa0120a6169 69 if (pR == &R[5]) return 5;
va009039 1:5fa0120a6169 70 if (pR == &R[6]) return 6;
va009039 1:5fa0120a6169 71 if (pR == &R[7]) return 7;
va009039 1:5fa0120a6169 72 if (pR == &R[8]) return 8;
va009039 1:5fa0120a6169 73 if (pR == &R[9]) return 9;
va009039 1:5fa0120a6169 74 if (pR == &R[10]) return 10;
va009039 1:5fa0120a6169 75 if (pR == &R[11]) return 11;
va009039 1:5fa0120a6169 76 if (pR == &R[12]) return 12;
va009039 1:5fa0120a6169 77 if (pR == &R[13]) return 13;
va009039 1:5fa0120a6169 78 if (pR == &R[14]) return 14;
va009039 1:5fa0120a6169 79 if (pR == &R[15]) return 15;
va009039 1:5fa0120a6169 80 if (pR == &R[16]) return 16;
va009039 1:5fa0120a6169 81 if (pR == &R[17]) return 17;
va009039 1:5fa0120a6169 82 if (pR == &R[18]) return 18;
va009039 1:5fa0120a6169 83 MBED_ASSERT(0);
va009039 1:5fa0120a6169 84 //return (pR - R) / sizeof(uint32_t);
va009039 1:5fa0120a6169 85 /* NOTREACHED */
va009039 1:5fa0120a6169 86 }
va009039 1:5fa0120a6169 87
va009039 1:5fa0120a6169 88 uint32_t BaseV6M::N() {
va009039 1:5fa0120a6169 89 return immed(R[_xPSR], 1, 31);
va009039 1:5fa0120a6169 90 }
va009039 1:5fa0120a6169 91
va009039 1:5fa0120a6169 92 uint32_t BaseV6M::Z() {
va009039 1:5fa0120a6169 93 return immed(R[_xPSR], 1, 30);
va009039 1:5fa0120a6169 94 }
va009039 1:5fa0120a6169 95
va009039 1:5fa0120a6169 96 uint32_t BaseV6M::C() {
va009039 1:5fa0120a6169 97 return immed(R[_xPSR], 1, 29);
va009039 1:5fa0120a6169 98 }
va009039 1:5fa0120a6169 99
va009039 1:5fa0120a6169 100 uint32_t BaseV6M::V() {
va009039 1:5fa0120a6169 101 return immed(R[_xPSR], 1, 28);
va009039 1:5fa0120a6169 102 }
va009039 1:5fa0120a6169 103
va009039 1:5fa0120a6169 104 void BaseV6M::Cin(uint32_t c) {
va009039 1:5fa0120a6169 105 R[_xPSR] &= ~(1<<29);
va009039 1:5fa0120a6169 106 R[_xPSR] |= c<<29;
va009039 1:5fa0120a6169 107 }
va009039 1:5fa0120a6169 108
va009039 1:5fa0120a6169 109 void BaseV6M::NZupdate(uint32_t d) {
va009039 1:5fa0120a6169 110 uint32_t mask;
va009039 1:5fa0120a6169 111 if (d & (1UL<<31)) { // N
va009039 1:5fa0120a6169 112 mask = 1UL<<31|0<<30;
va009039 1:5fa0120a6169 113 } else if (d == 0) { // Z
va009039 1:5fa0120a6169 114 mask = 0UL<<31|1<<30;
va009039 1:5fa0120a6169 115 } else {
va009039 1:5fa0120a6169 116 mask = 0UL<<31|0<<30;
va009039 1:5fa0120a6169 117 }
va009039 1:5fa0120a6169 118 R[_xPSR] &= ~(1UL<<31|1<<30);
va009039 1:5fa0120a6169 119 R[_xPSR] |= mask;
va009039 1:5fa0120a6169 120 }
va009039 1:5fa0120a6169 121
va009039 1:5fa0120a6169 122 void BaseV6M::NZCVupdate(uint32_t d, uint32_t n, uint32_t m) {
va009039 1:5fa0120a6169 123 uint32_t mask = NZCVlookup[d>>31|(n>>31)<<1|(m>>31)<<2];
va009039 1:5fa0120a6169 124 if (d == 0) {
va009039 1:5fa0120a6169 125 mask |= 1<<30; // Z=1
va009039 1:5fa0120a6169 126 }
va009039 1:5fa0120a6169 127 R[_xPSR] &= ~(1UL<<31|1<<30|1<<29|1<<28);
va009039 1:5fa0120a6169 128 R[_xPSR] |= mask;
va009039 1:5fa0120a6169 129 }
va009039 1:5fa0120a6169 130
va009039 1:5fa0120a6169 131 void BaseV6M::jump(uint32_t addr) {
va009039 1:5fa0120a6169 132 R[_PC] = addr;
va009039 1:5fa0120a6169 133 cache = false;
va009039 1:5fa0120a6169 134 }
va009039 1:5fa0120a6169 135
va009039 1:5fa0120a6169 136 void BaseV6M::exception_entry(uint32_t num) {
va009039 1:5fa0120a6169 137 push(R[_xPSR]);
va009039 1:5fa0120a6169 138 push(R[_PC] - 2);
va009039 1:5fa0120a6169 139 push(R[_LR]);
va009039 1:5fa0120a6169 140 push(R[13]);
va009039 1:5fa0120a6169 141 push(R[3]);
va009039 1:5fa0120a6169 142 push(R[2]);
va009039 1:5fa0120a6169 143 push(R[1]);
va009039 1:5fa0120a6169 144 push(R[0]);
va009039 1:5fa0120a6169 145 R[_LR] = 0xfffffff9;
va009039 1:5fa0120a6169 146 uint32_t addr = peek32(num * 4);
va009039 1:5fa0120a6169 147 V6M_ASSERT(addr&1);
va009039 1:5fa0120a6169 148 jump(addr);
va009039 1:5fa0120a6169 149 V6M_INFO("I: Exception entry %d", num);
va009039 1:5fa0120a6169 150 }
va009039 1:5fa0120a6169 151
va009039 1:5fa0120a6169 152 void BaseV6M::exception_return() {
va009039 1:5fa0120a6169 153 if ((R[_PC]&0xfffffff0) == 0xfffffff0) {
va009039 1:5fa0120a6169 154 V6M_ASSERT((R[_PC]&0x0e) == 8);
va009039 1:5fa0120a6169 155 R[0] = pop();
va009039 1:5fa0120a6169 156 R[1] = pop();
va009039 1:5fa0120a6169 157 R[2] = pop();
va009039 1:5fa0120a6169 158 R[3] = pop();
va009039 1:5fa0120a6169 159 R[12] = pop();
va009039 1:5fa0120a6169 160 R[_LR] = pop();
va009039 1:5fa0120a6169 161 uint32_t addr = pop();
va009039 1:5fa0120a6169 162 R[_xPSR] = pop();
va009039 1:5fa0120a6169 163 jump(addr);
va009039 1:5fa0120a6169 164 V6M_INFO("I: Exception return ; =0x%08x", addr);
va009039 1:5fa0120a6169 165 }
va009039 1:5fa0120a6169 166 }
va009039 1:5fa0120a6169 167
va009039 1:5fa0120a6169 168 void BaseV6M::push(uint32_t d) {
va009039 1:5fa0120a6169 169 R[_SP] -= 4;
va009039 1:5fa0120a6169 170 poke32(R[_SP], d);
va009039 1:5fa0120a6169 171 }
va009039 1:5fa0120a6169 172
va009039 1:5fa0120a6169 173 uint32_t BaseV6M::pop() {
va009039 1:5fa0120a6169 174 uint32_t d = peek32(R[_SP]);
va009039 1:5fa0120a6169 175 R[_SP] += 4;
va009039 1:5fa0120a6169 176 return d;
va009039 1:5fa0120a6169 177 }
va009039 1:5fa0120a6169 178
va009039 1:5fa0120a6169 179 void BaseV6M::d_Rn_Rd(uint32_t code) { // decode leaf
va009039 1:5fa0120a6169 180 Rd = &R[immed(code, 3, 0)];
va009039 1:5fa0120a6169 181 Rn = &R[immed(code, 3, 3)];
va009039 1:5fa0120a6169 182 }
va009039 1:5fa0120a6169 183
va009039 1:5fa0120a6169 184 void BaseV6M::d_Op_H_Rm(uint32_t code) { // BX Rm / BLX Rm
va009039 1:5fa0120a6169 185 Rm = &R[immed(code, 4, 3)];
va009039 1:5fa0120a6169 186 op = immed(code, 1, 7);
va009039 1:5fa0120a6169 187 }
va009039 1:5fa0120a6169 188
va009039 1:5fa0120a6169 189 void BaseV6M::d_imm3_Rn_Rd(uint32_t code) { // ADD Rd,Rn,#imm3
va009039 1:5fa0120a6169 190 d_Rn_Rd(code);
va009039 1:5fa0120a6169 191 R[_IM] = immed(code, 3, 6);
va009039 1:5fa0120a6169 192 Rm = &R[_IM];
va009039 1:5fa0120a6169 193 }
va009039 1:5fa0120a6169 194
va009039 1:5fa0120a6169 195 void BaseV6M::d_Rd_imm8(uint32_t code) { // <Op> Rd,#imm8 / LDR rd,[pc,#imm8]
va009039 1:5fa0120a6169 196 Rd = &R[immed(code, 3, 8)];
va009039 1:5fa0120a6169 197 Rn = Rd;
va009039 1:5fa0120a6169 198 R[_IM] = immed(code, 8, 0);
va009039 1:5fa0120a6169 199 Rm = &R[_IM];
va009039 1:5fa0120a6169 200 }
va009039 1:5fa0120a6169 201
va009039 1:5fa0120a6169 202 void BaseV6M::d_Rn_imm8(uint32_t code) { // <Op> Rn,#imm8
va009039 1:5fa0120a6169 203 Rn = &R[immed(code, 3, 8)];
va009039 1:5fa0120a6169 204 R[_IM] = immed(code, 8, 0);
va009039 1:5fa0120a6169 205 Rm = &R[_IM];
va009039 1:5fa0120a6169 206 }
va009039 1:5fa0120a6169 207
va009039 1:5fa0120a6169 208 void BaseV6M::d_imm5_Rn_Rd(uint32_t code) { // LSL Rd,Rn,#imm5 / LDR Rd,[Rn,#imm5]
va009039 1:5fa0120a6169 209 d_Rn_Rd(code);
va009039 1:5fa0120a6169 210 R[_IM] = immed(code, 5, 6);
va009039 1:5fa0120a6169 211 Rm = &R[_IM];
va009039 1:5fa0120a6169 212 }
va009039 1:5fa0120a6169 213
va009039 1:5fa0120a6169 214 void BaseV6M::d_Op_Rm_Rd(uint32_t code) { // <Op> Rd,Rm
va009039 1:5fa0120a6169 215 Rd = &R[immed(code, 3, 0)];
va009039 1:5fa0120a6169 216 Rn = Rd;
va009039 1:5fa0120a6169 217 Rm = &R[immed(code, 3, 3)];
va009039 1:5fa0120a6169 218 op = immed(code, 4, 6);
va009039 1:5fa0120a6169 219 }
va009039 1:5fa0120a6169 220
va009039 1:5fa0120a6169 221 void BaseV6M::d_Op_imm7(uint32_t code) { // ADD|SUB sp,sp,#imm7
va009039 1:5fa0120a6169 222 R[_IM] = immed(code, 7, 0);
va009039 1:5fa0120a6169 223 Rm = &R[_IM];
va009039 1:5fa0120a6169 224 op = immed(code, 1, 7);
va009039 1:5fa0120a6169 225 }
va009039 1:5fa0120a6169 226
va009039 1:5fa0120a6169 227 void BaseV6M::d_D_M_Rm_Rd(uint32_t code) { // ADD|CMP|MOV Rd,Rm
va009039 1:5fa0120a6169 228 Rm = &R[immed(code, 4, 3)];
va009039 1:5fa0120a6169 229 Rd = &R[immed(code, 3, 0)];
va009039 1:5fa0120a6169 230 if (code & 0x80) {
va009039 1:5fa0120a6169 231 Rd += 8;
va009039 1:5fa0120a6169 232 }
va009039 1:5fa0120a6169 233 Rn = Rd;
va009039 1:5fa0120a6169 234 }
va009039 1:5fa0120a6169 235
va009039 1:5fa0120a6169 236 void BaseV6M::d_Rm_Rn_Rd(uint32_t code) { // LDR Rd,[Rn,Rm]
va009039 1:5fa0120a6169 237 d_Rn_Rd(code);
va009039 1:5fa0120a6169 238 Rm = &R[immed(code, 3, 6)];
va009039 1:5fa0120a6169 239 }
va009039 1:5fa0120a6169 240
va009039 1:5fa0120a6169 241 void BaseV6M::d_reg_list(uint32_t code) { // PUSH / POP
va009039 1:5fa0120a6169 242 reg_list = immed(code, 8, 0);
va009039 1:5fa0120a6169 243 }
va009039 1:5fa0120a6169 244
va009039 1:5fa0120a6169 245 void BaseV6M::d_Rn_reg_list(uint32_t code) { // LDM / STM
va009039 1:5fa0120a6169 246 d_reg_list(code);
va009039 1:5fa0120a6169 247 Rn = &R[immed(code, 3, 8)];
va009039 1:5fa0120a6169 248 }
va009039 1:5fa0120a6169 249
va009039 1:5fa0120a6169 250 void BaseV6M::e_adc() { // ADC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 251 uint32_t n = *Rn;
va009039 1:5fa0120a6169 252 uint32_t m = *Rm;
va009039 1:5fa0120a6169 253 uint32_t d = add32(n, m + C());
va009039 1:5fa0120a6169 254 *Rd = d;
va009039 1:5fa0120a6169 255 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 256 }
va009039 1:5fa0120a6169 257
va009039 1:5fa0120a6169 258 void BaseV6M::e_sbc() { // SBC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 259 uint32_t n = *Rn;
va009039 1:5fa0120a6169 260 uint32_t m = not32(*Rm);
va009039 1:5fa0120a6169 261 uint32_t d = add32(n, m + C());
va009039 1:5fa0120a6169 262 *Rd = d;
va009039 1:5fa0120a6169 263 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 264 }
va009039 1:5fa0120a6169 265
va009039 1:5fa0120a6169 266 void BaseV6M::e_add() { // ADD Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 267 uint32_t n = *Rn;
va009039 1:5fa0120a6169 268 uint32_t m = *Rm;
va009039 1:5fa0120a6169 269 uint32_t d = add32(n, m);
va009039 1:5fa0120a6169 270 *Rd = d;
va009039 1:5fa0120a6169 271 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 272 }
va009039 1:5fa0120a6169 273
va009039 1:5fa0120a6169 274 void BaseV6M::e_sub() { // SUB Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 275 uint32_t n = *Rn;
va009039 1:5fa0120a6169 276 uint32_t m = not32(*Rm);
va009039 1:5fa0120a6169 277 uint32_t d = add32(n, m + 1);
va009039 1:5fa0120a6169 278 *Rd = d;
va009039 1:5fa0120a6169 279 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 280 }
va009039 1:5fa0120a6169 281
va009039 1:5fa0120a6169 282 void BaseV6M::e_cmp() { // CMP Rn,Rm|imm
va009039 1:5fa0120a6169 283 Rd = &R[_NL];
va009039 1:5fa0120a6169 284 e_sub();
va009039 1:5fa0120a6169 285 }
va009039 1:5fa0120a6169 286
va009039 1:5fa0120a6169 287 void BaseV6M::e_cmn() { // CMN Rn,Rm|imm
va009039 1:5fa0120a6169 288 Rd = &R[_NL];
va009039 1:5fa0120a6169 289 e_add();
va009039 1:5fa0120a6169 290 }
va009039 1:5fa0120a6169 291
va009039 1:5fa0120a6169 292 void BaseV6M::e_and() { // AND Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 293 uint32_t data = *Rn & *Rm;
va009039 1:5fa0120a6169 294 *Rd = data;
va009039 1:5fa0120a6169 295 NZupdate(data);
va009039 1:5fa0120a6169 296 }
va009039 1:5fa0120a6169 297
va009039 1:5fa0120a6169 298 void BaseV6M::e_tst() { // TST Rn,Rm|imm
va009039 1:5fa0120a6169 299 Rd = &R[_NL];
va009039 1:5fa0120a6169 300 e_and();
va009039 1:5fa0120a6169 301 }
va009039 1:5fa0120a6169 302
va009039 1:5fa0120a6169 303 void BaseV6M::e_lsl() { // LSL Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 304 uint32_t data = *Rn;
va009039 1:5fa0120a6169 305 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 306 if (shift <= 32) {
va009039 1:5fa0120a6169 307 Cin((data>>(32-shift))&1);
va009039 1:5fa0120a6169 308 data <<= shift;
va009039 1:5fa0120a6169 309 data &= 0xffffffff;
va009039 1:5fa0120a6169 310 } else {
va009039 1:5fa0120a6169 311 Cin(0);
va009039 1:5fa0120a6169 312 data = 0;
va009039 1:5fa0120a6169 313 }
va009039 1:5fa0120a6169 314 *Rd = data;
va009039 1:5fa0120a6169 315 NZupdate(data);
va009039 1:5fa0120a6169 316 }
va009039 1:5fa0120a6169 317
va009039 1:5fa0120a6169 318 void BaseV6M::e_lsr() { // LSR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 319 uint32_t data = *Rn;
va009039 1:5fa0120a6169 320 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 321 if (shift >= 1) {
va009039 1:5fa0120a6169 322 if (shift <= 32) {
va009039 1:5fa0120a6169 323 Cin((data>>(shift-1))&1);
va009039 1:5fa0120a6169 324 data >>= shift;
va009039 1:5fa0120a6169 325 } else {
va009039 1:5fa0120a6169 326 Cin(0);
va009039 1:5fa0120a6169 327 data = 0;
va009039 1:5fa0120a6169 328 }
va009039 1:5fa0120a6169 329 }
va009039 1:5fa0120a6169 330 *Rd = data;
va009039 1:5fa0120a6169 331 NZupdate(data);
va009039 1:5fa0120a6169 332 }
va009039 1:5fa0120a6169 333
va009039 1:5fa0120a6169 334 void BaseV6M::e_asr() { // ASR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 335 uint32_t data = *Rn;
va009039 1:5fa0120a6169 336 if ((data & 0x80000000) == 0) {
va009039 1:5fa0120a6169 337 e_lsr();
va009039 1:5fa0120a6169 338 return;
va009039 1:5fa0120a6169 339 }
va009039 1:5fa0120a6169 340 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 341 if (shift >= 1) {
va009039 1:5fa0120a6169 342 if (shift <= 31) {
va009039 1:5fa0120a6169 343 Cin((data>>(shift-1))&1);
va009039 1:5fa0120a6169 344 data >>= shift;
va009039 1:5fa0120a6169 345 data |= ~(0x7fffffff>>(shift-1));
va009039 1:5fa0120a6169 346 data &= 0xffffffff;
va009039 1:5fa0120a6169 347 } else {
va009039 1:5fa0120a6169 348 Cin(1);
va009039 1:5fa0120a6169 349 data = 0xffffffff;
va009039 1:5fa0120a6169 350 }
va009039 1:5fa0120a6169 351 }
va009039 1:5fa0120a6169 352 *Rd = data;
va009039 1:5fa0120a6169 353 NZupdate(data);
va009039 1:5fa0120a6169 354 }
va009039 1:5fa0120a6169 355
va009039 1:5fa0120a6169 356 void BaseV6M::e_ror() { // ROR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 357 uint32_t data = *Rn;
va009039 1:5fa0120a6169 358 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 359 if (shift >= 1) {
va009039 1:5fa0120a6169 360 int k = shift % 32;
va009039 1:5fa0120a6169 361 if (k == 0) {
va009039 1:5fa0120a6169 362 Cin(data>>31);
va009039 1:5fa0120a6169 363 } else {
va009039 1:5fa0120a6169 364 for (int i = 0; i < k; i++) {
va009039 1:5fa0120a6169 365 if (data & 1) {
va009039 1:5fa0120a6169 366 Cin(1);
va009039 1:5fa0120a6169 367 data >>= 1;
va009039 1:5fa0120a6169 368 data |= 0x80000000;
va009039 1:5fa0120a6169 369 } else {
va009039 1:5fa0120a6169 370 Cin(0);
va009039 1:5fa0120a6169 371 data >>= 1;
va009039 1:5fa0120a6169 372 }
va009039 1:5fa0120a6169 373 }
va009039 1:5fa0120a6169 374 }
va009039 1:5fa0120a6169 375 }
va009039 1:5fa0120a6169 376 *Rd = data;
va009039 1:5fa0120a6169 377 NZupdate(data);
va009039 1:5fa0120a6169 378 }
va009039 1:5fa0120a6169 379
va009039 1:5fa0120a6169 380 void BaseV6M::e_orr() { // ORR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 381 uint32_t data = *Rn | *Rm;
va009039 1:5fa0120a6169 382 *Rd = data;
va009039 1:5fa0120a6169 383 NZupdate(data);
va009039 1:5fa0120a6169 384 }
va009039 1:5fa0120a6169 385
va009039 1:5fa0120a6169 386 void BaseV6M::e_eor() { // EOR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 387 uint32_t data = *Rn ^ *Rm;
va009039 1:5fa0120a6169 388 *Rd = data;
va009039 1:5fa0120a6169 389 NZupdate(data);
va009039 1:5fa0120a6169 390 }
va009039 1:5fa0120a6169 391
va009039 1:5fa0120a6169 392 void BaseV6M::e_mul() { // MUL Rd,Rn,Rm
va009039 1:5fa0120a6169 393 uint32_t data = mul32(*Rn, *Rm);
va009039 1:5fa0120a6169 394 *Rd = data;
va009039 1:5fa0120a6169 395 NZupdate(data);
va009039 1:5fa0120a6169 396 }
va009039 1:5fa0120a6169 397
va009039 1:5fa0120a6169 398 void BaseV6M::e_bic() { // BIC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 399 uint32_t data = *Rn & not32(*Rm);
va009039 1:5fa0120a6169 400 *Rd = data;
va009039 1:5fa0120a6169 401 NZupdate(data);
va009039 1:5fa0120a6169 402 }
va009039 1:5fa0120a6169 403
va009039 1:5fa0120a6169 404 void BaseV6M::e_mov() { // MOV Rd,Rm|imm
va009039 1:5fa0120a6169 405 uint32_t data = *Rm;
va009039 1:5fa0120a6169 406 *Rd = data;
va009039 1:5fa0120a6169 407 NZupdate(data);
va009039 1:5fa0120a6169 408 }
va009039 1:5fa0120a6169 409
va009039 1:5fa0120a6169 410 void BaseV6M::e_neg() { // NEG
va009039 1:5fa0120a6169 411 Rn = &R[_IM];
va009039 1:5fa0120a6169 412 R[_IM] = 0;
va009039 1:5fa0120a6169 413 e_sub();
va009039 1:5fa0120a6169 414 }
va009039 1:5fa0120a6169 415
va009039 1:5fa0120a6169 416 void BaseV6M::e_mvn() { // MVN
va009039 1:5fa0120a6169 417 uint32_t data = not32(*Rm);
va009039 1:5fa0120a6169 418 *Rd = data;
va009039 1:5fa0120a6169 419 NZupdate(data);
va009039 1:5fa0120a6169 420 }
va009039 1:5fa0120a6169 421
va009039 1:5fa0120a6169 422 void BaseV6M::c_beq(uint32_t code) { // BEQ #0xd000-0xd0ff
va009039 1:5fa0120a6169 423 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 424 if (Z() == 1) {
va009039 1:5fa0120a6169 425 jump(addr);
va009039 1:5fa0120a6169 426 }
va009039 1:5fa0120a6169 427 V6M_INFO("I: BEQ 0x%08x", addr);
va009039 1:5fa0120a6169 428 }
va009039 1:5fa0120a6169 429
va009039 1:5fa0120a6169 430 void BaseV6M::c_bne(uint32_t code) { // BNE 0xd100-0xd1ff
va009039 1:5fa0120a6169 431 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 432 if (Z() == 0) {
va009039 1:5fa0120a6169 433 jump(addr);
va009039 1:5fa0120a6169 434 }
va009039 1:5fa0120a6169 435 V6M_INFO("I: BNE 0x%08x", addr);
va009039 1:5fa0120a6169 436 }
va009039 1:5fa0120a6169 437
va009039 1:5fa0120a6169 438 void BaseV6M::c_bcs(uint32_t code) { // BCS #0xd200-0xd2ff
va009039 1:5fa0120a6169 439 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 440 if (C() == 1) {
va009039 1:5fa0120a6169 441 jump(addr);
va009039 1:5fa0120a6169 442 }
va009039 1:5fa0120a6169 443 V6M_INFO("I: BCS 0x%08x", addr);
va009039 1:5fa0120a6169 444 }
va009039 1:5fa0120a6169 445
va009039 1:5fa0120a6169 446 void BaseV6M::c_bcc(uint32_t code) { // BCC #0xd300-0xd3ff
va009039 1:5fa0120a6169 447 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 448 if (C() == 0) {
va009039 1:5fa0120a6169 449 jump(addr);
va009039 1:5fa0120a6169 450 }
va009039 1:5fa0120a6169 451 V6M_INFO("I: BCC 0x%08x", addr);
va009039 1:5fa0120a6169 452 }
va009039 1:5fa0120a6169 453
va009039 1:5fa0120a6169 454 void BaseV6M::c_bmi(uint32_t code) { // BMI 0xd400-0xd4ff
va009039 1:5fa0120a6169 455 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 456 if (N() == 1) {
va009039 1:5fa0120a6169 457 jump(addr);
va009039 1:5fa0120a6169 458 }
va009039 1:5fa0120a6169 459 V6M_INFO("I: BMI 0x%08x", addr);
va009039 1:5fa0120a6169 460 }
va009039 1:5fa0120a6169 461
va009039 1:5fa0120a6169 462 void BaseV6M::c_bpl(uint32_t code) { // BMI 0xd500-0xd5ff
va009039 1:5fa0120a6169 463 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 464 if (N() == 0) {
va009039 1:5fa0120a6169 465 jump(addr);
va009039 1:5fa0120a6169 466 }
va009039 1:5fa0120a6169 467 V6M_INFO("I: BPL 0x%08x", addr);
va009039 1:5fa0120a6169 468 }
va009039 1:5fa0120a6169 469
va009039 1:5fa0120a6169 470 void BaseV6M::c_bvs(uint32_t code) { // BVS 0xd600-0xd6ff
va009039 1:5fa0120a6169 471 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 472 if (V() == 1) {
va009039 1:5fa0120a6169 473 jump(addr);
va009039 1:5fa0120a6169 474 }
va009039 1:5fa0120a6169 475 V6M_INFO("I: BVS 0x%08x", addr);
va009039 1:5fa0120a6169 476 V6M_ASSERT(0);
va009039 1:5fa0120a6169 477 }
va009039 1:5fa0120a6169 478
va009039 1:5fa0120a6169 479 void BaseV6M::c_bvc(uint32_t code) { // BVC 0xd700-0xd7ff
va009039 1:5fa0120a6169 480 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 481 if (V() == 0) {
va009039 1:5fa0120a6169 482 jump(addr);
va009039 1:5fa0120a6169 483 }
va009039 1:5fa0120a6169 484 V6M_INFO("I: BVC 0x%08x", addr);
va009039 1:5fa0120a6169 485 V6M_ASSERT(0);
va009039 1:5fa0120a6169 486 }
va009039 1:5fa0120a6169 487
va009039 1:5fa0120a6169 488 void BaseV6M::c_bhi(uint32_t code) { // BHI 0xd800-0xd8ff
va009039 1:5fa0120a6169 489 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 490 if (C() == 1 && Z() == 0) {
va009039 1:5fa0120a6169 491 jump(addr);
va009039 1:5fa0120a6169 492 }
va009039 1:5fa0120a6169 493 V6M_INFO("I: BHI 0x%08x", addr);
va009039 1:5fa0120a6169 494 }
va009039 1:5fa0120a6169 495
va009039 1:5fa0120a6169 496 void BaseV6M::c_bls(uint32_t code) { // BLS 0xd900-0xd9ff
va009039 1:5fa0120a6169 497 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 498 if (C() == 0 || Z() == 1) {
va009039 1:5fa0120a6169 499 jump(addr);
va009039 1:5fa0120a6169 500 }
va009039 1:5fa0120a6169 501 V6M_INFO("I: BLS 0x%08x", addr);
va009039 1:5fa0120a6169 502 }
va009039 1:5fa0120a6169 503
va009039 1:5fa0120a6169 504 void BaseV6M::c_bge(uint32_t code) { // BGE 0xda00-0xdaff
va009039 1:5fa0120a6169 505 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 506 if (N() == V()) {
va009039 1:5fa0120a6169 507 jump(addr);
va009039 1:5fa0120a6169 508 }
va009039 1:5fa0120a6169 509 V6M_INFO("I: BGE 0x%08x", addr);
va009039 1:5fa0120a6169 510 }
va009039 1:5fa0120a6169 511
va009039 1:5fa0120a6169 512 void BaseV6M::c_blt(uint32_t code) { // BLT 0xdb00-0xdbff
va009039 1:5fa0120a6169 513 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 514 if (N() != V()) {
va009039 1:5fa0120a6169 515 jump(addr);
va009039 1:5fa0120a6169 516 }
va009039 1:5fa0120a6169 517 V6M_INFO("I: BLT 0x%08x", addr);
va009039 1:5fa0120a6169 518 }
va009039 1:5fa0120a6169 519
va009039 1:5fa0120a6169 520 void BaseV6M::c_bgt(uint32_t code) { // BGT 0xdc00-0xdcff
va009039 1:5fa0120a6169 521 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 522 if (Z() == 0 && N() == V()) {
va009039 1:5fa0120a6169 523 jump(addr);
va009039 1:5fa0120a6169 524 }
va009039 1:5fa0120a6169 525 V6M_INFO("I: BGT 0x%08x", addr);
va009039 1:5fa0120a6169 526 }
va009039 1:5fa0120a6169 527
va009039 1:5fa0120a6169 528 void BaseV6M::c_ble(uint32_t code) { // BLE 0xdd00-0xddff
va009039 1:5fa0120a6169 529 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 530 if (Z() == 1 || N() != V()) {
va009039 1:5fa0120a6169 531 jump(addr);
va009039 1:5fa0120a6169 532 }
va009039 1:5fa0120a6169 533 V6M_INFO("I: BLE 0x%08x", addr);
va009039 1:5fa0120a6169 534 }
va009039 1:5fa0120a6169 535
va009039 1:5fa0120a6169 536 void BaseV6M::c_b_forward(uint32_t code) { // B 0xe000-0xe3ff
va009039 1:5fa0120a6169 537 uint32_t addr = R[_PC] + ((code&0x3ff)<<1);
va009039 1:5fa0120a6169 538 jump(addr);
va009039 1:5fa0120a6169 539 V6M_INFO("I: B 0x%08x ; forward", addr);
va009039 1:5fa0120a6169 540 }
va009039 1:5fa0120a6169 541
va009039 1:5fa0120a6169 542 void BaseV6M::c_b_backward(uint32_t code) { // B 0xe400-0xe7ff
va009039 1:5fa0120a6169 543 uint32_t addr = R[_PC] + ((code|~0x7ff)<<1);
va009039 1:5fa0120a6169 544 jump(addr);
va009039 1:5fa0120a6169 545 V6M_INFO("I: B 0x%08x ; backward", addr);
va009039 1:5fa0120a6169 546 }
va009039 1:5fa0120a6169 547
va009039 1:5fa0120a6169 548 void BaseV6M::c_bl(uint32_t code) { // BL 0xf000-0xf7ff
va009039 1:5fa0120a6169 549 uint32_t addr = R[_PC] + (signed_immed(code, 11) * 2048*2);
va009039 1:5fa0120a6169 550 R[_LR] = R[_PC] | 1;
va009039 1:5fa0120a6169 551 V6M_ASSERT((code2nd&0xe000) == 0xe000);
va009039 1:5fa0120a6169 552 addr += (immed(code2nd, 11) * 2);
va009039 1:5fa0120a6169 553 jump(addr);
va009039 1:5fa0120a6169 554 V6M_INFO("I: BL 0x%08x", addr);
va009039 1:5fa0120a6169 555 }
va009039 1:5fa0120a6169 556
va009039 1:5fa0120a6169 557 void BaseV6M::c_bx(uint32_t code) { // BX BLX 0x4770
va009039 1:5fa0120a6169 558 d_Op_H_Rm(code);
va009039 1:5fa0120a6169 559 if (op == 1) {
va009039 1:5fa0120a6169 560 R[_LR] = (R[_PC] - 2) | 1;
va009039 1:5fa0120a6169 561 }
va009039 1:5fa0120a6169 562 uint32_t addr = *Rm & 0xfffffffe;
va009039 1:5fa0120a6169 563 jump(addr);
va009039 1:5fa0120a6169 564 const char* name[] = {"BX", "BLX"};
va009039 1:5fa0120a6169 565 V6M_INFO("I: %s %s ; =0x%x", name[op], GetRegName(Rm), addr);
va009039 1:5fa0120a6169 566 exception_return();
va009039 1:5fa0120a6169 567 }
va009039 1:5fa0120a6169 568
va009039 1:5fa0120a6169 569 void BaseV6M::c_add(uint32_t code) { // ADDS Rd,Rn,Rm 0x1800-0x19ff
va009039 1:5fa0120a6169 570 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 571 e_add();
va009039 1:5fa0120a6169 572 V6M_INFO("I: ADDS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 573 }
va009039 1:5fa0120a6169 574
va009039 1:5fa0120a6169 575 void BaseV6M::c_sub(uint32_t code) { // SUBS Rd,Rn,Rm 0x1a00-0x1bff
va009039 1:5fa0120a6169 576 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 577 e_sub();
va009039 1:5fa0120a6169 578 V6M_INFO("I: SUBS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 579 }
va009039 1:5fa0120a6169 580
va009039 1:5fa0120a6169 581 void BaseV6M::c_add1(uint32_t code) { // ADD Rd,Rn,#imm3 / MOV Rd,Rn 0x1c00-0x1dff
va009039 1:5fa0120a6169 582 d_imm3_Rn_Rd(code);
va009039 1:5fa0120a6169 583 e_add();
va009039 1:5fa0120a6169 584 if ((code&0x01c0) == 0x0000) {
va009039 1:5fa0120a6169 585 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rn));
va009039 1:5fa0120a6169 586 V6M_ASSERT((code&0xffc0) == 0x1c00);
va009039 1:5fa0120a6169 587 } else {
va009039 1:5fa0120a6169 588 V6M_INFO("I: ADD %s,%s,#0x%02x", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 589 }
va009039 1:5fa0120a6169 590 }
va009039 1:5fa0120a6169 591
va009039 1:5fa0120a6169 592 void BaseV6M::c_sub1(uint32_t code) { // SUB Rd,Rn,#imm3 0x1e00-1fff
va009039 1:5fa0120a6169 593 d_imm3_Rn_Rd(code);
va009039 1:5fa0120a6169 594 V6M_ASSERT(R[_IM] != 0);
va009039 1:5fa0120a6169 595 e_sub();
va009039 1:5fa0120a6169 596 V6M_INFO("I: SUB %s,%s,#0x%02x", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 597 }
va009039 1:5fa0120a6169 598
va009039 1:5fa0120a6169 599 void BaseV6M::c_add2(uint32_t code) { // ADD Rd,#imm8 0x3000-0x37ff
va009039 1:5fa0120a6169 600 d_Rd_imm8(code);
va009039 1:5fa0120a6169 601 e_add();
va009039 1:5fa0120a6169 602 V6M_INFO("I: ADD %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 603 }
va009039 1:5fa0120a6169 604
va009039 1:5fa0120a6169 605 void BaseV6M::c_sub2(uint32_t code) { // SUB Rd,#imm8 0x3800-0x3fff
va009039 1:5fa0120a6169 606 d_Rd_imm8(code);
va009039 1:5fa0120a6169 607 e_sub();
va009039 1:5fa0120a6169 608 V6M_INFO("I: SUB %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 609 }
va009039 1:5fa0120a6169 610
va009039 1:5fa0120a6169 611 void BaseV6M::c_mov(uint32_t code) { // MOVS Rd,#imm8 0x2000-0x27ff
va009039 1:5fa0120a6169 612 d_Rd_imm8(code);
va009039 1:5fa0120a6169 613 e_mov();
va009039 1:5fa0120a6169 614 V6M_INFO("I: MOVS %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 615 }
va009039 1:5fa0120a6169 616
va009039 1:5fa0120a6169 617 void BaseV6M::c_cmp(uint32_t code) { // CMP Rn,#imm8 0x2800-0x2fff
va009039 1:5fa0120a6169 618 d_Rn_imm8(code);
va009039 1:5fa0120a6169 619 e_cmp();
va009039 1:5fa0120a6169 620 V6M_INFO("I: CMP %s,#0x%02x", GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 621 }
va009039 1:5fa0120a6169 622
va009039 1:5fa0120a6169 623 void BaseV6M::c_lsl(uint32_t code) { // LSLS Rd,Rn,#imm5 0x0000-0x07ff
va009039 1:5fa0120a6169 624 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 625 e_lsl();
va009039 1:5fa0120a6169 626 V6M_INFO("I: LSLS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 627 }
va009039 1:5fa0120a6169 628
va009039 1:5fa0120a6169 629 void BaseV6M::c_lsr(uint32_t code) { // LSRS Rd,Rn,#imm5 0x0800-0x0fff
va009039 1:5fa0120a6169 630 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 631 if (R[_IM] == 0) {
va009039 1:5fa0120a6169 632 R[_IM] = 32;
va009039 1:5fa0120a6169 633 }
va009039 1:5fa0120a6169 634 e_lsr();
va009039 1:5fa0120a6169 635 V6M_INFO("I: LSRS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 636 }
va009039 1:5fa0120a6169 637
va009039 1:5fa0120a6169 638 void BaseV6M::c_asr(uint32_t code) { // ASRS Rd,Rn,#imm5 0x1000-0x17ff
va009039 1:5fa0120a6169 639 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 640 if (R[_IM] == 0) {
va009039 1:5fa0120a6169 641 R[_IM] = 32;
va009039 1:5fa0120a6169 642 }
va009039 1:5fa0120a6169 643 e_asr();
va009039 1:5fa0120a6169 644 V6M_INFO("I: ASRS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 645 }
va009039 1:5fa0120a6169 646
va009039 1:5fa0120a6169 647 void BaseV6M::c_and_eor_lsl_lsr(uint32_t code) { // ANDS|EORS|LSLS|LSRS Rd,Rm 0x4000-0x40ff
va009039 1:5fa0120a6169 648 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 649 if (op == 0) {
va009039 1:5fa0120a6169 650 e_and();
va009039 1:5fa0120a6169 651 V6M_INFO("I: ANDS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 652 } else if (op == 1) {
va009039 1:5fa0120a6169 653 e_eor();
va009039 1:5fa0120a6169 654 V6M_INFO("I: EORS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 655 } else if (op == 2) {
va009039 1:5fa0120a6169 656 e_lsl();
va009039 1:5fa0120a6169 657 V6M_INFO("I: LSLS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 658 } else {
va009039 1:5fa0120a6169 659 e_lsr();
va009039 1:5fa0120a6169 660 V6M_INFO("I: LSRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 661 }
va009039 1:5fa0120a6169 662 }
va009039 1:5fa0120a6169 663
va009039 1:5fa0120a6169 664 void BaseV6M::c_asr_adc_sbc_ror(uint32_t code) { // ASRS|ADCS|SBCS|RORS Rd,Rm 0x4100-0x41ff
va009039 1:5fa0120a6169 665 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 666 if (op == 4) {
va009039 1:5fa0120a6169 667 e_asr();
va009039 1:5fa0120a6169 668 V6M_INFO("I: ASRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 669 } else if (op == 5) {
va009039 1:5fa0120a6169 670 e_adc();
va009039 1:5fa0120a6169 671 V6M_INFO("I: ADCS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 672 } else if (op == 6) {
va009039 1:5fa0120a6169 673 e_sbc();
va009039 1:5fa0120a6169 674 V6M_INFO("I: SBCS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 675 } else {
va009039 1:5fa0120a6169 676 e_ror();
va009039 1:5fa0120a6169 677 V6M_INFO("I: RORS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 678 }
va009039 1:5fa0120a6169 679 }
va009039 1:5fa0120a6169 680
va009039 1:5fa0120a6169 681 void BaseV6M::c_tst_neg_cmp_cmn(uint32_t code) { // TST|NEGS|CMP|CMN Rd,Rm 0x4200-0x42ff
va009039 1:5fa0120a6169 682 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 683 if (op == 8) {
va009039 1:5fa0120a6169 684 e_tst();
va009039 1:5fa0120a6169 685 V6M_INFO("I: TST %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 686 } else if (op == 9) {
va009039 1:5fa0120a6169 687 e_neg();
va009039 1:5fa0120a6169 688 V6M_INFO("I: NEG %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 689 } else if (op == 10) {
va009039 1:5fa0120a6169 690 e_cmp();
va009039 1:5fa0120a6169 691 V6M_INFO("I: CMP %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 692 } else {
va009039 1:5fa0120a6169 693 e_cmn();
va009039 1:5fa0120a6169 694 V6M_INFO("I: CMN %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 695 }
va009039 1:5fa0120a6169 696 }
va009039 1:5fa0120a6169 697
va009039 1:5fa0120a6169 698 void BaseV6M::c_orr_mul_bic_mvn(uint32_t code) { // ORRS|MULS|BICS|MVNS Rd,Rm 0x4300-0x43ff
va009039 1:5fa0120a6169 699 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 700 if (op == 12) {
va009039 1:5fa0120a6169 701 e_orr();
va009039 1:5fa0120a6169 702 V6M_INFO("I: ORRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 703 } else if (op == 13) {
va009039 1:5fa0120a6169 704 e_mul();
va009039 1:5fa0120a6169 705 V6M_INFO("I: MULS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 706 } else if (op == 14) {
va009039 1:5fa0120a6169 707 e_bic();
va009039 1:5fa0120a6169 708 V6M_INFO("I: BICS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 709 } else {
va009039 1:5fa0120a6169 710 e_mvn();
va009039 1:5fa0120a6169 711 V6M_INFO("I: MVNS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 712 }
va009039 1:5fa0120a6169 713 }
va009039 1:5fa0120a6169 714
va009039 1:5fa0120a6169 715 void BaseV6M::c_add_hr(uint32_t code) { // ADD Rd,Rm (high reg) 0x4400-0x44ff
va009039 1:5fa0120a6169 716 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 717 *Rd = add32(*Rn, *Rm);
va009039 1:5fa0120a6169 718 V6M_INFO("I: ADD %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 719 }
va009039 1:5fa0120a6169 720
va009039 1:5fa0120a6169 721 void BaseV6M::c_cmp_hr(uint32_t code) { // CMP Rd,Rm (high reg) 0x4500-0x45ff
va009039 1:5fa0120a6169 722 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 723 V6M_ASSERT(Rd != &R[_PC]);
va009039 1:5fa0120a6169 724 Rd = &R[_NL];
va009039 1:5fa0120a6169 725 e_cmp();
va009039 1:5fa0120a6169 726 V6M_INFO("I: CMP %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 727 }
va009039 1:5fa0120a6169 728
va009039 1:5fa0120a6169 729 void BaseV6M::c_mov_hr(uint32_t code) { // MOV Rd,Rm (high reg) 0x4600-0x46ff
va009039 1:5fa0120a6169 730 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 731 *Rd = *Rm;
va009039 1:5fa0120a6169 732 if (Rd == &R[_PC]) {
va009039 1:5fa0120a6169 733 jump(R[_PC]);
va009039 1:5fa0120a6169 734 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 735 exception_return();
va009039 1:5fa0120a6169 736 } else {
va009039 1:5fa0120a6169 737 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 738 }
va009039 1:5fa0120a6169 739 }
va009039 1:5fa0120a6169 740
va009039 1:5fa0120a6169 741 void BaseV6M::c_add_r_pc(uint32_t code) { // ADD Rd,pc,#imm8 0xa000-0xa7ff
va009039 1:5fa0120a6169 742 d_Rd_imm8(code);
va009039 1:5fa0120a6169 743 uint32_t off = R[_IM] * 4;
va009039 1:5fa0120a6169 744 uint32_t addr = align32(R[_PC]) + off;
va009039 1:5fa0120a6169 745 *Rd = addr;
va009039 1:5fa0120a6169 746 V6M_INFO("I: ADD %s,pc,#0x%02x ; @0x%08x", GetRegName(Rd), off, addr);
va009039 1:5fa0120a6169 747 }
va009039 1:5fa0120a6169 748
va009039 1:5fa0120a6169 749 void BaseV6M::c_add_r_sp(uint32_t code) { // ADD Rd,sp,#imm8 0xa800-0xafff
va009039 1:5fa0120a6169 750 d_Rd_imm8(code);
va009039 1:5fa0120a6169 751 uint32_t off = R[_IM] * 4;
va009039 1:5fa0120a6169 752 uint32_t addr = *Rd = R[_SP] + off;
va009039 1:5fa0120a6169 753 *Rd = addr;
va009039 1:5fa0120a6169 754 V6M_INFO("I: ADD %s,sp,#0x%02x ; @0x%08x", GetRegName(Rd), off, addr);
va009039 1:5fa0120a6169 755 V6M_ASSERT(addr%4 == 0);
va009039 1:5fa0120a6169 756 }
va009039 1:5fa0120a6169 757
va009039 1:5fa0120a6169 758 void BaseV6M::c_add_sp(uint32_t code) { // ADD|SUB sp,sp,#imm 0xb000-0xb0ff
va009039 1:5fa0120a6169 759 d_Op_imm7(code);
va009039 1:5fa0120a6169 760 uint32_t data = R[_IM] * 4;
va009039 1:5fa0120a6169 761 if (op == 0) {
va009039 1:5fa0120a6169 762 R[_SP] += data;
va009039 1:5fa0120a6169 763 } else {
va009039 1:5fa0120a6169 764 R[_SP] -= data;
va009039 1:5fa0120a6169 765 }
va009039 1:5fa0120a6169 766 const char* name[] = {"ADD", "SUB"};
va009039 1:5fa0120a6169 767 V6M_INFO("I: %s sp,sp,#0x%x", name[op], data);
va009039 1:5fa0120a6169 768 }
va009039 1:5fa0120a6169 769
va009039 1:5fa0120a6169 770 void BaseV6M::c_ldr1(uint32_t code) { // LDR Rd,[Rn,#imm5] 0x6800-0x6fff
va009039 1:5fa0120a6169 771 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 772 e_ldr<uint32_t>(true);
va009039 1:5fa0120a6169 773 V6M_INFO("I: LDR %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 774 }
va009039 1:5fa0120a6169 775
va009039 1:5fa0120a6169 776 void BaseV6M::c_str1(uint32_t code) { // STR Rd,[Rn,#imm5] 0x6000-0x67ff
va009039 1:5fa0120a6169 777 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 778 e_str<uint32_t>(true);
va009039 1:5fa0120a6169 779 V6M_INFO("I: STR %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 780 }
va009039 1:5fa0120a6169 781
va009039 1:5fa0120a6169 782 void BaseV6M::c_ldrb(uint32_t code) { // LDRB Rd,[Rn,#imm5] 0x7800-0x7fff
va009039 1:5fa0120a6169 783 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 784 e_ldr<uint8_t>(true);
va009039 1:5fa0120a6169 785 V6M_INFO("I: LDRB %s,[%s,#0x%02x] ; =0x%02x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 786 }
va009039 1:5fa0120a6169 787
va009039 1:5fa0120a6169 788 void BaseV6M::c_strb(uint32_t code) { // STRB Rd,[Rn,#imm5] 0x7000-0x77ff
va009039 1:5fa0120a6169 789 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 790 e_str<uint8_t>(true);
va009039 1:5fa0120a6169 791 V6M_INFO("I: STRB %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 792 }
va009039 1:5fa0120a6169 793
va009039 1:5fa0120a6169 794 void BaseV6M::c_ldrh(uint32_t code) { // LDRH Rd,[Rn,#imm5] 0x8800-0x8fff
va009039 1:5fa0120a6169 795 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 796 e_ldr<uint16_t>(true);
va009039 1:5fa0120a6169 797 V6M_INFO("I: LDRH %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 798 }
va009039 1:5fa0120a6169 799
va009039 1:5fa0120a6169 800 void BaseV6M::c_strh(uint32_t code) { // STRH Rd,[Rn,#imm5] 0x8000-0x87ff
va009039 1:5fa0120a6169 801 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 802 e_str<uint16_t>(true);
va009039 1:5fa0120a6169 803 V6M_INFO("I: STRH %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 804 }
va009039 1:5fa0120a6169 805
va009039 1:5fa0120a6169 806 void BaseV6M::c_ldr2(uint32_t code) { // LDR Rd,[Rn,Rm] 0x5800-0x59ff
va009039 1:5fa0120a6169 807 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 808 e_ldr<uint32_t>();
va009039 1:5fa0120a6169 809 V6M_INFO("I: LDR %s,[%s,%s] ; =0x%08x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 810 }
va009039 1:5fa0120a6169 811
va009039 1:5fa0120a6169 812 void BaseV6M::c_str2(uint32_t code) { // STR Rd,[Rn,Rm] 0x5000-0x51ff
va009039 1:5fa0120a6169 813 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 814 e_str<uint32_t>();
va009039 1:5fa0120a6169 815 V6M_INFO("I: STR %s,[%s,%s] ; =0x%08x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 816 }
va009039 1:5fa0120a6169 817
va009039 1:5fa0120a6169 818 void BaseV6M::c_ldrh2(uint32_t code) { // LDRH Rd,[Rn,Rm] 0x5a00-0x5bff
va009039 1:5fa0120a6169 819 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 820 e_ldr<uint16_t>();
va009039 1:5fa0120a6169 821 V6M_INFO("I: LDRH %s,[%s,%s] ; =0x%04x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 822 }
va009039 1:5fa0120a6169 823
va009039 1:5fa0120a6169 824 void BaseV6M::c_strh2(uint32_t code) { // STRH Rd,[Rn,Rm] 0x5200-0x53ff
va009039 1:5fa0120a6169 825 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 826 e_str<uint16_t>();
va009039 1:5fa0120a6169 827 V6M_INFO("I: STRH %s,[%s,%s] ; =0x%04x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 828 }
va009039 1:5fa0120a6169 829
va009039 1:5fa0120a6169 830 void BaseV6M::c_ldrsh(uint32_t code) { // LDRSH Rd,[Rn,Rm] 0x5e00-0x5fff
va009039 1:5fa0120a6169 831 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 832 e_ldr<uint16_t>();
va009039 1:5fa0120a6169 833 uint32_t data = signed_immed(*Rd, 16) & 0xffffffff;
va009039 1:5fa0120a6169 834 *Rd = data;
va009039 1:5fa0120a6169 835 V6M_INFO("I: LDRSH %s,[%s,%s] ; =0x%x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 836 }
va009039 1:5fa0120a6169 837
va009039 1:5fa0120a6169 838 void BaseV6M::c_ldrb2(uint32_t code) { // LDRB Rd,[Rn,Rm] 0x5c00-0x5dff
va009039 1:5fa0120a6169 839 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 840 e_ldr<uint8_t>();
va009039 1:5fa0120a6169 841 V6M_INFO("I: LDRB %s,[%s,%s] ; =0x%02x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 842 }
va009039 1:5fa0120a6169 843
va009039 1:5fa0120a6169 844 void BaseV6M::c_strb2(uint32_t code) { // STRB Rd,[Rn,Rm] 0x5400-0x55ff
va009039 1:5fa0120a6169 845 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 846 e_str<uint8_t>();
va009039 1:5fa0120a6169 847 V6M_INFO("I: STRB %s,[%s,%s] ; =0x%02x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 848 }
va009039 1:5fa0120a6169 849
va009039 1:5fa0120a6169 850 void BaseV6M::c_ldrsb(uint32_t code) { // LDRSB Rd,[Rn,Rm] 0x5600-0x57ff
va009039 1:5fa0120a6169 851 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 852 e_ldr<uint8_t>();
va009039 1:5fa0120a6169 853 uint32_t data = signed_immed(*Rd, 8) & 0xffffffff;
va009039 1:5fa0120a6169 854 *Rd = data;
va009039 1:5fa0120a6169 855 V6M_INFO("I: LDRSB %s,[%s,%s] ; =0x%x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 856 }
va009039 1:5fa0120a6169 857
va009039 1:5fa0120a6169 858 void BaseV6M::c_ldr_pc(uint32_t code) { // LDR Rd,[pc,#imm8] 0x4800-0x4fff
va009039 1:5fa0120a6169 859 d_Rd_imm8(code);
va009039 1:5fa0120a6169 860 uint32_t off = *Rm * 4;
va009039 1:5fa0120a6169 861 uint32_t addr = align32(R[_PC]) + off;
va009039 1:5fa0120a6169 862 uint32_t data = peek32(addr);
va009039 1:5fa0120a6169 863 *Rd = data;
va009039 1:5fa0120a6169 864 V6M_INFO("I: LDR %s,[pc,#%d] ; =0x%x @0x%08x", GetRegName(Rd), off, data, addr);
va009039 1:5fa0120a6169 865 }
va009039 1:5fa0120a6169 866
va009039 1:5fa0120a6169 867 void BaseV6M::c_ldr_sp(uint32_t code) { // LDR Rd,[sp,#imm8] 0x9800-0x9fff
va009039 1:5fa0120a6169 868 d_Rd_imm8(code);
va009039 1:5fa0120a6169 869 Rn = &R[_SP];
va009039 1:5fa0120a6169 870 e_ldr<uint32_t>(true);
va009039 1:5fa0120a6169 871 V6M_INFO("I: LDR %s,[sp,#0x%x] ; =0x%08x @0x%08x", GetRegName(Rd), R[_IM], data, addr);
va009039 1:5fa0120a6169 872 }
va009039 1:5fa0120a6169 873
va009039 1:5fa0120a6169 874 void BaseV6M::c_str_sp(uint32_t code) { // STR Rd,[sp,#imm8] 0x9000-0x97ff
va009039 1:5fa0120a6169 875 d_Rd_imm8(code);
va009039 1:5fa0120a6169 876 Rn = &R[_SP];
va009039 1:5fa0120a6169 877 e_str<uint32_t>(true);
va009039 1:5fa0120a6169 878 V6M_INFO("I: STR %s,[sp,#0x%x] ; =0x08%x @0x%08x", GetRegName(Rd), R[_IM], data, addr);
va009039 1:5fa0120a6169 879 }
va009039 1:5fa0120a6169 880
va009039 1:5fa0120a6169 881 void BaseV6M::e_ldm() { // LDM / POP
va009039 1:5fa0120a6169 882 uint32_t addr = *Rn;
va009039 1:5fa0120a6169 883 for (int k = 0; k <= 7; k++) {
va009039 1:5fa0120a6169 884 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 885 R[k] = peek32(addr);
va009039 1:5fa0120a6169 886 addr += 4;
va009039 1:5fa0120a6169 887 }
va009039 1:5fa0120a6169 888 }
va009039 1:5fa0120a6169 889 if (! (reg_list & (1<<GetRegIndex(Rn)))) {
va009039 1:5fa0120a6169 890 *Rn = addr;
va009039 1:5fa0120a6169 891 }
va009039 1:5fa0120a6169 892 }
va009039 1:5fa0120a6169 893
va009039 1:5fa0120a6169 894 void BaseV6M::e_stm() { // STM
va009039 1:5fa0120a6169 895 uint32_t addr = *Rn;
va009039 1:5fa0120a6169 896 for (int k = 0; k <= 7; k++) {
va009039 1:5fa0120a6169 897 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 898 poke32(addr, R[k]);
va009039 1:5fa0120a6169 899 addr += 4;
va009039 1:5fa0120a6169 900 }
va009039 1:5fa0120a6169 901 }
va009039 1:5fa0120a6169 902 *Rn = addr;
va009039 1:5fa0120a6169 903 }
va009039 1:5fa0120a6169 904
va009039 1:5fa0120a6169 905 void BaseV6M::e_push() { // PUSH
va009039 1:5fa0120a6169 906 for (int k = 7; k >= 0; k--) {
va009039 1:5fa0120a6169 907 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 908 push(R[k]);
va009039 1:5fa0120a6169 909 }
va009039 1:5fa0120a6169 910 }
va009039 1:5fa0120a6169 911 }
va009039 1:5fa0120a6169 912
va009039 1:5fa0120a6169 913 void BaseV6M::c_ldm(uint32_t code) { // LDM Rn!,{reg_list} 0xc800-0xcfff
va009039 1:5fa0120a6169 914 d_Rn_reg_list(code);
va009039 1:5fa0120a6169 915 e_ldm();
va009039 1:5fa0120a6169 916 V6M_INFO("I: LDMIA %s!,{%s}", GetRegName(Rn), StrRegLists());
va009039 1:5fa0120a6169 917 }
va009039 1:5fa0120a6169 918
va009039 1:5fa0120a6169 919 void BaseV6M::c_stm(uint32_t code) { // STM Rn!,{reg_list} 0xc000-0xc7ff
va009039 1:5fa0120a6169 920 d_Rn_reg_list(code);
va009039 1:5fa0120a6169 921 e_stm();
va009039 1:5fa0120a6169 922 V6M_INFO("I: STMIA %s!,{%s}", GetRegName(Rn), StrRegLists());
va009039 1:5fa0120a6169 923 }
va009039 1:5fa0120a6169 924
va009039 1:5fa0120a6169 925 void BaseV6M::c_pop(uint32_t code) { // POP {reg_list} 0xbc00-0xbcff
va009039 1:5fa0120a6169 926 d_reg_list(code);
va009039 1:5fa0120a6169 927 Rn = &R[_SP];
va009039 1:5fa0120a6169 928 e_ldm();
va009039 1:5fa0120a6169 929 V6M_INFO("I: POP {%s}", StrRegLists());
va009039 1:5fa0120a6169 930 }
va009039 1:5fa0120a6169 931
va009039 1:5fa0120a6169 932 void BaseV6M::c_pop_pc(uint32_t code) { // POP {reg_list,pc} 0xbd00-0xbdff
va009039 1:5fa0120a6169 933 d_reg_list(code);
va009039 1:5fa0120a6169 934 Rn = &R[_SP];
va009039 1:5fa0120a6169 935 e_ldm();
va009039 1:5fa0120a6169 936 jump(pop());
va009039 1:5fa0120a6169 937 V6M_INFO("I: POP {%s,pc}", StrRegLists());
va009039 1:5fa0120a6169 938 }
va009039 1:5fa0120a6169 939
va009039 1:5fa0120a6169 940 void BaseV6M::c_push(uint32_t code) { // PUSH {reg_list} 0xb400-0xb4ff
va009039 1:5fa0120a6169 941 d_reg_list(code);
va009039 1:5fa0120a6169 942 e_push();
va009039 1:5fa0120a6169 943 V6M_INFO("I: PUSH {%s}", StrRegLists());
va009039 1:5fa0120a6169 944 }
va009039 1:5fa0120a6169 945
va009039 1:5fa0120a6169 946 void BaseV6M::c_push_lr(uint32_t code) { // PUSH {reg_list,lr} 0xb500-0xb5ff
va009039 1:5fa0120a6169 947 d_reg_list(code);
va009039 1:5fa0120a6169 948 push(R[_LR]);
va009039 1:5fa0120a6169 949 e_push();
va009039 1:5fa0120a6169 950 V6M_INFO("I: PUSH {%s,lr}", StrRegLists());
va009039 1:5fa0120a6169 951 }
va009039 1:5fa0120a6169 952
va009039 1:5fa0120a6169 953 void BaseV6M::c_uxt(uint32_t code) { // UXTH|UXTB Rd,Rm 0xb200-0xb2ff
va009039 1:5fa0120a6169 954 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 955 if (op == 10) {
va009039 1:5fa0120a6169 956 *Rd = *Rm & 0xffff;
va009039 1:5fa0120a6169 957 V6M_INFO("I: UXTH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 958 V6M_ASSERT((code&0xffc0) == 0xb280);
va009039 1:5fa0120a6169 959 } else if (op == 11) {
va009039 1:5fa0120a6169 960 *Rd = *Rm & 0xff;
va009039 1:5fa0120a6169 961 V6M_INFO("I: UXTB %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 962 V6M_ASSERT((code&0xffc0) == 0xb2c0);
va009039 1:5fa0120a6169 963 } else if (op == 8) {
va009039 1:5fa0120a6169 964 *Rd = signed_immed(*Rm, 16) & 0xffffffff;
va009039 1:5fa0120a6169 965 V6M_INFO("I: SXTH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 966 V6M_ASSERT((code&0xffc0) == 0xb200);
va009039 1:5fa0120a6169 967 } else if (op == 9) {
va009039 1:5fa0120a6169 968 *Rd = signed_immed(*Rm, 8) & 0xffffffff;
va009039 1:5fa0120a6169 969 V6M_INFO("I: SXTB %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 970 V6M_ASSERT((code&0xffc0) == 0xb240);
va009039 1:5fa0120a6169 971 } else {
va009039 1:5fa0120a6169 972 V6M_ASSERT(0);
va009039 1:5fa0120a6169 973 }
va009039 1:5fa0120a6169 974 }
va009039 1:5fa0120a6169 975
va009039 1:5fa0120a6169 976 void BaseV6M::c_rev(uint32_t code) { // REV|REV16|REVSH Rd,Rm 0xba00-0xba3f
va009039 1:5fa0120a6169 977 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 978 if (op == 8) {
va009039 1:5fa0120a6169 979 uint32_t data = *Rm;
va009039 1:5fa0120a6169 980 *Rd = ((data<<24)&0xff000000)|((data<<8)&0xff0000)|((data>>8)&0xff00)|data>>24;
va009039 1:5fa0120a6169 981 V6M_INFO("I: REV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 982 }
va009039 1:5fa0120a6169 983 if (op == 9) {
va009039 1:5fa0120a6169 984 uint32_t data = *Rm;
va009039 1:5fa0120a6169 985 *Rd = ((data<<8)&0xff00ff00)|((data>>8)&0x00ff00ff);
va009039 1:5fa0120a6169 986 V6M_INFO("I: REV16 %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 987 }
va009039 1:5fa0120a6169 988 if (op == 11) {
va009039 1:5fa0120a6169 989 uint32_t data = *Rm;
va009039 1:5fa0120a6169 990 *Rd = ((data<<8)&0xff00)|((data>>8)&0x00ff);
va009039 1:5fa0120a6169 991 if (*Rd & 0x8000) {
va009039 1:5fa0120a6169 992 *Rd |= 0xffff0000;
va009039 1:5fa0120a6169 993 }
va009039 1:5fa0120a6169 994 V6M_INFO("I: REVSH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 995 } else {
va009039 1:5fa0120a6169 996 V6M_ASSERT(0);
va009039 1:5fa0120a6169 997 }
va009039 1:5fa0120a6169 998 }
va009039 1:5fa0120a6169 999
va009039 1:5fa0120a6169 1000 void BaseV6M::c_nop(uint32_t code) { // NOP 0xbf00
va009039 1:5fa0120a6169 1001 V6M_ASSERT(code == 0xbf00);
va009039 1:5fa0120a6169 1002 V6M_INFO("I: NOP");
va009039 1:5fa0120a6169 1003 }
va009039 1:5fa0120a6169 1004
va009039 1:5fa0120a6169 1005 void BaseV6M::c_bkpt(uint32_t code) { // BKPT #imm8 0xbe00-0xbeff
va009039 1:5fa0120a6169 1006 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1007 }
va009039 1:5fa0120a6169 1008
va009039 1:5fa0120a6169 1009 void BaseV6M::c_swi(uint32_t code) { // SWI #imm8 0xdf00-0xdfff
va009039 1:5fa0120a6169 1010 V6M_INFO("I: SWI #%d", immed(code, 8, 0));
va009039 1:5fa0120a6169 1011 exception_entry(11);
va009039 1:5fa0120a6169 1012 }
va009039 1:5fa0120a6169 1013
va009039 1:5fa0120a6169 1014 void BaseV6M::c_cps(uint32_t code) { // CPSIE|CPSID A|I|F 0xb6c0-0xb6e7
va009039 1:5fa0120a6169 1015 uint32_t i = immed(code, 1,4);
va009039 1:5fa0120a6169 1016 uint32_t f = immed(code, 3,0);
va009039 1:5fa0120a6169 1017 V6M_ASSERT(f != 0);
va009039 1:5fa0120a6169 1018 const char* i_name[] = {"CPSIE", "CPSID"};
va009039 1:5fa0120a6169 1019 const char* f_name[] = {"", "F", "I", "IF", "A", "AF", "AI", "AIF"};
va009039 1:5fa0120a6169 1020 V6M_INFO("I: %s %s", i_name[i], f_name[f]);
va009039 1:5fa0120a6169 1021 }
va009039 1:5fa0120a6169 1022
va009039 1:5fa0120a6169 1023 void BaseV6M::c_todo(uint32_t code) { // undefined code
va009039 1:5fa0120a6169 1024 V6M_ERROR("I: ASSERT!!! %04x %04x", code, code2nd);
va009039 1:5fa0120a6169 1025 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1026 }
va009039 1:5fa0120a6169 1027
va009039 1:5fa0120a6169 1028 void BaseV6M::fetch() {
va009039 1:5fa0120a6169 1029 if (cache) {
va009039 1:5fa0120a6169 1030 code = code2nd;
va009039 1:5fa0120a6169 1031 code2nd = peek16(align16(R[_PC]));
va009039 1:5fa0120a6169 1032 R[_PC] += 2;
va009039 1:5fa0120a6169 1033 } else {
va009039 1:5fa0120a6169 1034 uint32_t d = peek32(align16(R[_PC]));
va009039 1:5fa0120a6169 1035 code = d & 0xffff;
va009039 1:5fa0120a6169 1036 code2nd = d>>16;
va009039 1:5fa0120a6169 1037 R[_PC] += 4;
va009039 1:5fa0120a6169 1038 cache = true;
va009039 1:5fa0120a6169 1039 }
va009039 1:5fa0120a6169 1040 }
va009039 1:5fa0120a6169 1041
va009039 1:5fa0120a6169 1042 void BaseV6M::execute() {
va009039 1:5fa0120a6169 1043 switch(code>>8) {
va009039 1:5fa0120a6169 1044 case 0xd0: c_beq(code); break;
va009039 1:5fa0120a6169 1045 case 0xd1: c_bne(code); break;
va009039 1:5fa0120a6169 1046 case 0xd2: c_bcs(code); break;
va009039 1:5fa0120a6169 1047 case 0xd3: c_bcc(code); break;
va009039 1:5fa0120a6169 1048 case 0xd4: c_bmi(code); break;
va009039 1:5fa0120a6169 1049 case 0xd5: c_bpl(code); break;
va009039 1:5fa0120a6169 1050 case 0xd6: c_bvs(code); break;
va009039 1:5fa0120a6169 1051 case 0xd7: c_bvc(code); break;
va009039 1:5fa0120a6169 1052 case 0xd8: c_bhi(code); break;
va009039 1:5fa0120a6169 1053 case 0xd9: c_bls(code); break;
va009039 1:5fa0120a6169 1054 case 0xda: c_bge(code); break;
va009039 1:5fa0120a6169 1055 case 0xdb: c_blt(code); break;
va009039 1:5fa0120a6169 1056 case 0xdc: c_bgt(code); break;
va009039 1:5fa0120a6169 1057 case 0xdd: c_ble(code); break;
va009039 1:5fa0120a6169 1058 case 0xe0 ... 0xe3: c_b_forward(code); break;
va009039 1:5fa0120a6169 1059 case 0xe4 ... 0xe7: c_b_backward(code); break;
va009039 1:5fa0120a6169 1060 case 0xf0 ... 0xf7: c_bl(code); break;
va009039 1:5fa0120a6169 1061 case 0x47: c_bx(code); break;
va009039 1:5fa0120a6169 1062 case 0x18 ... 0x19: c_add(code); break;
va009039 1:5fa0120a6169 1063 case 0x1a ... 0x1b: c_sub(code); break;
va009039 1:5fa0120a6169 1064 case 0x1c ... 0x1d: c_add1(code); break;
va009039 1:5fa0120a6169 1065 case 0x1e ... 0x1f: c_sub1(code); break;
va009039 1:5fa0120a6169 1066 case 0x30 ... 0x37: c_add2(code); break;
va009039 1:5fa0120a6169 1067 case 0x38 ... 0x3f: c_sub2(code); break;
va009039 1:5fa0120a6169 1068 case 0x20 ... 0x27: c_mov(code); break;
va009039 1:5fa0120a6169 1069 case 0x28 ... 0x2f: c_cmp(code); break;
va009039 1:5fa0120a6169 1070 case 0x00 ... 0x07: c_lsl(code); break;
va009039 1:5fa0120a6169 1071 case 0x08 ... 0x0f: c_lsr(code); break;
va009039 1:5fa0120a6169 1072 case 0x10 ... 0x17: c_asr(code); break;
va009039 1:5fa0120a6169 1073 case 0x40: c_and_eor_lsl_lsr(code); break;
va009039 1:5fa0120a6169 1074 case 0x41: c_asr_adc_sbc_ror(code); break;
va009039 1:5fa0120a6169 1075 case 0x42: c_tst_neg_cmp_cmn(code); break;
va009039 1:5fa0120a6169 1076 case 0x43: c_orr_mul_bic_mvn(code); break;
va009039 1:5fa0120a6169 1077 case 0x44: c_add_hr(code); break;
va009039 1:5fa0120a6169 1078 case 0x45: c_cmp_hr(code); break;
va009039 1:5fa0120a6169 1079 case 0x46: c_mov_hr(code); break;
va009039 1:5fa0120a6169 1080 case 0xa0 ... 0xa7: c_add_r_pc(code); break;
va009039 1:5fa0120a6169 1081 case 0xa8 ... 0xaf: c_add_r_sp(code); break;
va009039 1:5fa0120a6169 1082 case 0xb0: c_add_sp(code); break;
va009039 1:5fa0120a6169 1083 case 0x68 ... 0x6f: c_ldr1(code); break;
va009039 1:5fa0120a6169 1084 case 0x60 ... 0x67: c_str1(code); break;
va009039 1:5fa0120a6169 1085 case 0x78 ... 0x7f: c_ldrb(code); break;
va009039 1:5fa0120a6169 1086 case 0x70 ... 0x77: c_strb(code); break;
va009039 1:5fa0120a6169 1087 case 0x88 ... 0x8f: c_ldrh(code); break;
va009039 1:5fa0120a6169 1088 case 0x80 ... 0x87: c_strh(code); break;
va009039 1:5fa0120a6169 1089 case 0x58 ... 0x59: c_ldr2(code); break;
va009039 1:5fa0120a6169 1090 case 0x50 ... 0x51: c_str2(code); break;
va009039 1:5fa0120a6169 1091 case 0x5a ... 0x5b: c_ldrh2(code); break;
va009039 1:5fa0120a6169 1092 case 0x52 ... 0x53: c_strh2(code); break;
va009039 1:5fa0120a6169 1093 case 0x5e ... 0x5f: c_ldrsh(code); break;
va009039 1:5fa0120a6169 1094 case 0x5c ... 0x5d: c_ldrb2(code); break;
va009039 1:5fa0120a6169 1095 case 0x54 ... 0x55: c_strb2(code); break;
va009039 1:5fa0120a6169 1096 case 0x56 ... 0x57: c_ldrsb(code); break;
va009039 1:5fa0120a6169 1097 case 0x48 ... 0x4f: c_ldr_pc(code); break;
va009039 1:5fa0120a6169 1098 case 0x98 ... 0x9f: c_ldr_sp(code); break;
va009039 1:5fa0120a6169 1099 case 0x90 ... 0x97: c_str_sp(code); break;
va009039 1:5fa0120a6169 1100 case 0xc8 ... 0xcf: c_ldm(code); break;
va009039 1:5fa0120a6169 1101 case 0xc0 ... 0xc7: c_stm(code); break;
va009039 1:5fa0120a6169 1102 case 0xbc: c_pop(code); break;
va009039 1:5fa0120a6169 1103 case 0xbd: c_pop_pc(code); break;
va009039 1:5fa0120a6169 1104 case 0xb4: c_push(code); break;
va009039 1:5fa0120a6169 1105 case 0xb5: c_push_lr(code); break;
va009039 1:5fa0120a6169 1106 case 0xb2: c_uxt(code); break;
va009039 1:5fa0120a6169 1107 case 0xba: c_rev(code); break;
va009039 1:5fa0120a6169 1108 case 0xbf: c_nop(code); break;
va009039 1:5fa0120a6169 1109 case 0xbe: c_bkpt(code); break;
va009039 1:5fa0120a6169 1110 case 0xdf: c_swi(code); break;
va009039 1:5fa0120a6169 1111 case 0xb6: c_cps(code); break;
va009039 1:5fa0120a6169 1112 default: c_todo(code); break;
va009039 1:5fa0120a6169 1113 }
va009039 1:5fa0120a6169 1114 cycle++;
va009039 1:5fa0120a6169 1115 }
va009039 1:5fa0120a6169 1116
va009039 1:5fa0120a6169 1117 void BaseV6M::reset() {
va009039 1:5fa0120a6169 1118 R[_SP] = peek32(0x00000000);
va009039 1:5fa0120a6169 1119 R[_PC] = peek32(0x00000004);
va009039 1:5fa0120a6169 1120 cache = false;
va009039 1:5fa0120a6169 1121 }
va009039 1:5fa0120a6169 1122
va009039 1:5fa0120a6169 1123 void BaseV6M::run(int step) {
va009039 1:5fa0120a6169 1124 while(step-- > 0) {
va009039 1:5fa0120a6169 1125 fetch();
va009039 1:5fa0120a6169 1126 execute();
va009039 1:5fa0120a6169 1127 }
va009039 1:5fa0120a6169 1128 }