v6m virtual machine

Dependents:  

Import programemu812

mbed LPC812 emulator pre-alpha version

Import programemu1114

mbed LPC1114 emulator pre-alpha version

Committer:
va009039
Date:
Fri Apr 01 11:12:29 2016 +0900
Revision:
5:65d77b2e6bc7
Parent:
4:1c7b72bcfc4d
remove assert code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 5:65d77b2e6bc7 1 // BaseV6M.cpp 2016/3/28
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 2:078d2e512ba4 21 static 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 2:078d2e512ba4 25 static 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 2:078d2e512ba4 33 static 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 2:078d2e512ba4 37 static 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 2:078d2e512ba4 41 static uint32_t not32(uint32_t data) {
va009039 1:5fa0120a6169 42 return (~data)&0xffffffff;
va009039 1:5fa0120a6169 43 }
va009039 1:5fa0120a6169 44
va009039 2:078d2e512ba4 45 static uint32_t align32(uint32_t addr) {
va009039 1:5fa0120a6169 46 return addr & 0xfffffffc;
va009039 1:5fa0120a6169 47 }
va009039 1:5fa0120a6169 48
va009039 2:078d2e512ba4 49 static 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 3:fe333683e8f7 132 R[_PC] = align16(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 4:1c7b72bcfc4d 250 void BaseV6M::d32_Rd_SYSm(uint32_t code, uint32_t code2nd) { // MRS
va009039 4:1c7b72bcfc4d 251 Rd = &R[immed(code2nd, 4, 8)];
va009039 4:1c7b72bcfc4d 252 int m = immed(code2nd, 7, 0);
va009039 4:1c7b72bcfc4d 253 }
va009039 4:1c7b72bcfc4d 254
va009039 4:1c7b72bcfc4d 255 void BaseV6M::d32_Rn_SYSm(uint32_t code, uint32_t code2nd) { // MSR
va009039 4:1c7b72bcfc4d 256 Rn = &R[immed(code, 4, 0)];
va009039 4:1c7b72bcfc4d 257 int m = immed(code2nd, 7, 0);
va009039 4:1c7b72bcfc4d 258 }
va009039 4:1c7b72bcfc4d 259
va009039 1:5fa0120a6169 260 void BaseV6M::e_adc() { // ADC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 261 uint32_t n = *Rn;
va009039 1:5fa0120a6169 262 uint32_t m = *Rm;
va009039 1:5fa0120a6169 263 uint32_t d = add32(n, m + C());
va009039 1:5fa0120a6169 264 *Rd = d;
va009039 1:5fa0120a6169 265 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 266 }
va009039 1:5fa0120a6169 267
va009039 1:5fa0120a6169 268 void BaseV6M::e_sbc() { // SBC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 269 uint32_t n = *Rn;
va009039 1:5fa0120a6169 270 uint32_t m = not32(*Rm);
va009039 1:5fa0120a6169 271 uint32_t d = add32(n, m + C());
va009039 1:5fa0120a6169 272 *Rd = d;
va009039 1:5fa0120a6169 273 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 274 }
va009039 1:5fa0120a6169 275
va009039 1:5fa0120a6169 276 void BaseV6M::e_add() { // ADD Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 277 uint32_t n = *Rn;
va009039 1:5fa0120a6169 278 uint32_t m = *Rm;
va009039 1:5fa0120a6169 279 uint32_t d = add32(n, m);
va009039 1:5fa0120a6169 280 *Rd = d;
va009039 1:5fa0120a6169 281 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 282 }
va009039 1:5fa0120a6169 283
va009039 1:5fa0120a6169 284 void BaseV6M::e_sub() { // SUB Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 285 uint32_t n = *Rn;
va009039 1:5fa0120a6169 286 uint32_t m = not32(*Rm);
va009039 1:5fa0120a6169 287 uint32_t d = add32(n, m + 1);
va009039 1:5fa0120a6169 288 *Rd = d;
va009039 1:5fa0120a6169 289 NZCVupdate(d, n, m);
va009039 1:5fa0120a6169 290 }
va009039 1:5fa0120a6169 291
va009039 1:5fa0120a6169 292 void BaseV6M::e_cmp() { // CMP Rn,Rm|imm
va009039 1:5fa0120a6169 293 Rd = &R[_NL];
va009039 1:5fa0120a6169 294 e_sub();
va009039 1:5fa0120a6169 295 }
va009039 1:5fa0120a6169 296
va009039 1:5fa0120a6169 297 void BaseV6M::e_cmn() { // CMN Rn,Rm|imm
va009039 1:5fa0120a6169 298 Rd = &R[_NL];
va009039 1:5fa0120a6169 299 e_add();
va009039 1:5fa0120a6169 300 }
va009039 1:5fa0120a6169 301
va009039 1:5fa0120a6169 302 void BaseV6M::e_and() { // AND Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 303 uint32_t data = *Rn & *Rm;
va009039 1:5fa0120a6169 304 *Rd = data;
va009039 1:5fa0120a6169 305 NZupdate(data);
va009039 1:5fa0120a6169 306 }
va009039 1:5fa0120a6169 307
va009039 1:5fa0120a6169 308 void BaseV6M::e_tst() { // TST Rn,Rm|imm
va009039 1:5fa0120a6169 309 Rd = &R[_NL];
va009039 1:5fa0120a6169 310 e_and();
va009039 1:5fa0120a6169 311 }
va009039 1:5fa0120a6169 312
va009039 1:5fa0120a6169 313 void BaseV6M::e_lsl() { // LSL Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 314 uint32_t data = *Rn;
va009039 1:5fa0120a6169 315 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 316 if (shift <= 32) {
va009039 1:5fa0120a6169 317 Cin((data>>(32-shift))&1);
va009039 1:5fa0120a6169 318 data <<= shift;
va009039 1:5fa0120a6169 319 data &= 0xffffffff;
va009039 1:5fa0120a6169 320 } else {
va009039 1:5fa0120a6169 321 Cin(0);
va009039 1:5fa0120a6169 322 data = 0;
va009039 1:5fa0120a6169 323 }
va009039 1:5fa0120a6169 324 *Rd = data;
va009039 1:5fa0120a6169 325 NZupdate(data);
va009039 1:5fa0120a6169 326 }
va009039 1:5fa0120a6169 327
va009039 1:5fa0120a6169 328 void BaseV6M::e_lsr() { // LSR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 329 uint32_t data = *Rn;
va009039 1:5fa0120a6169 330 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 331 if (shift >= 1) {
va009039 1:5fa0120a6169 332 if (shift <= 32) {
va009039 1:5fa0120a6169 333 Cin((data>>(shift-1))&1);
va009039 1:5fa0120a6169 334 data >>= shift;
va009039 1:5fa0120a6169 335 } else {
va009039 1:5fa0120a6169 336 Cin(0);
va009039 1:5fa0120a6169 337 data = 0;
va009039 1:5fa0120a6169 338 }
va009039 1:5fa0120a6169 339 }
va009039 1:5fa0120a6169 340 *Rd = data;
va009039 1:5fa0120a6169 341 NZupdate(data);
va009039 1:5fa0120a6169 342 }
va009039 1:5fa0120a6169 343
va009039 1:5fa0120a6169 344 void BaseV6M::e_asr() { // ASR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 345 uint32_t data = *Rn;
va009039 1:5fa0120a6169 346 if ((data & 0x80000000) == 0) {
va009039 1:5fa0120a6169 347 e_lsr();
va009039 1:5fa0120a6169 348 return;
va009039 1:5fa0120a6169 349 }
va009039 1:5fa0120a6169 350 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 351 if (shift >= 1) {
va009039 1:5fa0120a6169 352 if (shift <= 31) {
va009039 1:5fa0120a6169 353 Cin((data>>(shift-1))&1);
va009039 1:5fa0120a6169 354 data >>= shift;
va009039 1:5fa0120a6169 355 data |= ~(0x7fffffff>>(shift-1));
va009039 1:5fa0120a6169 356 data &= 0xffffffff;
va009039 1:5fa0120a6169 357 } else {
va009039 1:5fa0120a6169 358 Cin(1);
va009039 1:5fa0120a6169 359 data = 0xffffffff;
va009039 1:5fa0120a6169 360 }
va009039 1:5fa0120a6169 361 }
va009039 1:5fa0120a6169 362 *Rd = data;
va009039 1:5fa0120a6169 363 NZupdate(data);
va009039 1:5fa0120a6169 364 }
va009039 1:5fa0120a6169 365
va009039 1:5fa0120a6169 366 void BaseV6M::e_ror() { // ROR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 367 uint32_t data = *Rn;
va009039 1:5fa0120a6169 368 int shift = *Rm & 0xff;
va009039 1:5fa0120a6169 369 if (shift >= 1) {
va009039 1:5fa0120a6169 370 int k = shift % 32;
va009039 1:5fa0120a6169 371 if (k == 0) {
va009039 1:5fa0120a6169 372 Cin(data>>31);
va009039 1:5fa0120a6169 373 } else {
va009039 1:5fa0120a6169 374 for (int i = 0; i < k; i++) {
va009039 1:5fa0120a6169 375 if (data & 1) {
va009039 1:5fa0120a6169 376 Cin(1);
va009039 1:5fa0120a6169 377 data >>= 1;
va009039 1:5fa0120a6169 378 data |= 0x80000000;
va009039 1:5fa0120a6169 379 } else {
va009039 1:5fa0120a6169 380 Cin(0);
va009039 1:5fa0120a6169 381 data >>= 1;
va009039 1:5fa0120a6169 382 }
va009039 1:5fa0120a6169 383 }
va009039 1:5fa0120a6169 384 }
va009039 1:5fa0120a6169 385 }
va009039 1:5fa0120a6169 386 *Rd = data;
va009039 1:5fa0120a6169 387 NZupdate(data);
va009039 1:5fa0120a6169 388 }
va009039 1:5fa0120a6169 389
va009039 1:5fa0120a6169 390 void BaseV6M::e_orr() { // ORR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 391 uint32_t data = *Rn | *Rm;
va009039 1:5fa0120a6169 392 *Rd = data;
va009039 1:5fa0120a6169 393 NZupdate(data);
va009039 1:5fa0120a6169 394 }
va009039 1:5fa0120a6169 395
va009039 1:5fa0120a6169 396 void BaseV6M::e_eor() { // EOR Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 397 uint32_t data = *Rn ^ *Rm;
va009039 1:5fa0120a6169 398 *Rd = data;
va009039 1:5fa0120a6169 399 NZupdate(data);
va009039 1:5fa0120a6169 400 }
va009039 1:5fa0120a6169 401
va009039 1:5fa0120a6169 402 void BaseV6M::e_mul() { // MUL Rd,Rn,Rm
va009039 1:5fa0120a6169 403 uint32_t data = mul32(*Rn, *Rm);
va009039 1:5fa0120a6169 404 *Rd = data;
va009039 1:5fa0120a6169 405 NZupdate(data);
va009039 1:5fa0120a6169 406 }
va009039 1:5fa0120a6169 407
va009039 1:5fa0120a6169 408 void BaseV6M::e_bic() { // BIC Rd,Rn,Rm|imm
va009039 1:5fa0120a6169 409 uint32_t data = *Rn & not32(*Rm);
va009039 1:5fa0120a6169 410 *Rd = data;
va009039 1:5fa0120a6169 411 NZupdate(data);
va009039 1:5fa0120a6169 412 }
va009039 1:5fa0120a6169 413
va009039 1:5fa0120a6169 414 void BaseV6M::e_mov() { // MOV Rd,Rm|imm
va009039 1:5fa0120a6169 415 uint32_t data = *Rm;
va009039 1:5fa0120a6169 416 *Rd = data;
va009039 1:5fa0120a6169 417 NZupdate(data);
va009039 1:5fa0120a6169 418 }
va009039 1:5fa0120a6169 419
va009039 1:5fa0120a6169 420 void BaseV6M::e_neg() { // NEG
va009039 1:5fa0120a6169 421 Rn = &R[_IM];
va009039 1:5fa0120a6169 422 R[_IM] = 0;
va009039 1:5fa0120a6169 423 e_sub();
va009039 1:5fa0120a6169 424 }
va009039 1:5fa0120a6169 425
va009039 1:5fa0120a6169 426 void BaseV6M::e_mvn() { // MVN
va009039 1:5fa0120a6169 427 uint32_t data = not32(*Rm);
va009039 1:5fa0120a6169 428 *Rd = data;
va009039 1:5fa0120a6169 429 NZupdate(data);
va009039 1:5fa0120a6169 430 }
va009039 1:5fa0120a6169 431
va009039 3:fe333683e8f7 432 void BaseV6M::c_beq(uint32_t code) { // BEQ 0xd000-0xd0ff
va009039 1:5fa0120a6169 433 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 434 if (Z() == 1) {
va009039 1:5fa0120a6169 435 jump(addr);
va009039 1:5fa0120a6169 436 }
va009039 1:5fa0120a6169 437 V6M_INFO("I: BEQ 0x%08x", addr);
va009039 1:5fa0120a6169 438 }
va009039 1:5fa0120a6169 439
va009039 1:5fa0120a6169 440 void BaseV6M::c_bne(uint32_t code) { // BNE 0xd100-0xd1ff
va009039 1:5fa0120a6169 441 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 442 if (Z() == 0) {
va009039 1:5fa0120a6169 443 jump(addr);
va009039 1:5fa0120a6169 444 }
va009039 1:5fa0120a6169 445 V6M_INFO("I: BNE 0x%08x", addr);
va009039 1:5fa0120a6169 446 }
va009039 1:5fa0120a6169 447
va009039 3:fe333683e8f7 448 void BaseV6M::c_bcs(uint32_t code) { // BCS 0xd200-0xd2ff
va009039 1:5fa0120a6169 449 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 450 if (C() == 1) {
va009039 1:5fa0120a6169 451 jump(addr);
va009039 1:5fa0120a6169 452 }
va009039 1:5fa0120a6169 453 V6M_INFO("I: BCS 0x%08x", addr);
va009039 1:5fa0120a6169 454 }
va009039 1:5fa0120a6169 455
va009039 3:fe333683e8f7 456 void BaseV6M::c_bcc(uint32_t code) { // BCC 0xd300-0xd3ff
va009039 1:5fa0120a6169 457 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 458 if (C() == 0) {
va009039 1:5fa0120a6169 459 jump(addr);
va009039 1:5fa0120a6169 460 }
va009039 1:5fa0120a6169 461 V6M_INFO("I: BCC 0x%08x", addr);
va009039 1:5fa0120a6169 462 }
va009039 1:5fa0120a6169 463
va009039 1:5fa0120a6169 464 void BaseV6M::c_bmi(uint32_t code) { // BMI 0xd400-0xd4ff
va009039 1:5fa0120a6169 465 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 466 if (N() == 1) {
va009039 1:5fa0120a6169 467 jump(addr);
va009039 1:5fa0120a6169 468 }
va009039 1:5fa0120a6169 469 V6M_INFO("I: BMI 0x%08x", addr);
va009039 1:5fa0120a6169 470 }
va009039 1:5fa0120a6169 471
va009039 1:5fa0120a6169 472 void BaseV6M::c_bpl(uint32_t code) { // BMI 0xd500-0xd5ff
va009039 1:5fa0120a6169 473 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 474 if (N() == 0) {
va009039 1:5fa0120a6169 475 jump(addr);
va009039 1:5fa0120a6169 476 }
va009039 1:5fa0120a6169 477 V6M_INFO("I: BPL 0x%08x", addr);
va009039 1:5fa0120a6169 478 }
va009039 1:5fa0120a6169 479
va009039 1:5fa0120a6169 480 void BaseV6M::c_bvs(uint32_t code) { // BVS 0xd600-0xd6ff
va009039 1:5fa0120a6169 481 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 482 if (V() == 1) {
va009039 1:5fa0120a6169 483 jump(addr);
va009039 1:5fa0120a6169 484 }
va009039 1:5fa0120a6169 485 V6M_INFO("I: BVS 0x%08x", addr);
va009039 1:5fa0120a6169 486 V6M_ASSERT(0);
va009039 1:5fa0120a6169 487 }
va009039 1:5fa0120a6169 488
va009039 1:5fa0120a6169 489 void BaseV6M::c_bvc(uint32_t code) { // BVC 0xd700-0xd7ff
va009039 1:5fa0120a6169 490 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 491 if (V() == 0) {
va009039 1:5fa0120a6169 492 jump(addr);
va009039 1:5fa0120a6169 493 }
va009039 1:5fa0120a6169 494 V6M_INFO("I: BVC 0x%08x", addr);
va009039 1:5fa0120a6169 495 V6M_ASSERT(0);
va009039 1:5fa0120a6169 496 }
va009039 1:5fa0120a6169 497
va009039 1:5fa0120a6169 498 void BaseV6M::c_bhi(uint32_t code) { // BHI 0xd800-0xd8ff
va009039 1:5fa0120a6169 499 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 500 if (C() == 1 && Z() == 0) {
va009039 1:5fa0120a6169 501 jump(addr);
va009039 1:5fa0120a6169 502 }
va009039 1:5fa0120a6169 503 V6M_INFO("I: BHI 0x%08x", addr);
va009039 1:5fa0120a6169 504 }
va009039 1:5fa0120a6169 505
va009039 1:5fa0120a6169 506 void BaseV6M::c_bls(uint32_t code) { // BLS 0xd900-0xd9ff
va009039 1:5fa0120a6169 507 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 508 if (C() == 0 || Z() == 1) {
va009039 1:5fa0120a6169 509 jump(addr);
va009039 1:5fa0120a6169 510 }
va009039 1:5fa0120a6169 511 V6M_INFO("I: BLS 0x%08x", addr);
va009039 1:5fa0120a6169 512 }
va009039 1:5fa0120a6169 513
va009039 1:5fa0120a6169 514 void BaseV6M::c_bge(uint32_t code) { // BGE 0xda00-0xdaff
va009039 1:5fa0120a6169 515 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 516 if (N() == V()) {
va009039 1:5fa0120a6169 517 jump(addr);
va009039 1:5fa0120a6169 518 }
va009039 1:5fa0120a6169 519 V6M_INFO("I: BGE 0x%08x", addr);
va009039 1:5fa0120a6169 520 }
va009039 1:5fa0120a6169 521
va009039 1:5fa0120a6169 522 void BaseV6M::c_blt(uint32_t code) { // BLT 0xdb00-0xdbff
va009039 1:5fa0120a6169 523 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 524 if (N() != V()) {
va009039 1:5fa0120a6169 525 jump(addr);
va009039 1:5fa0120a6169 526 }
va009039 1:5fa0120a6169 527 V6M_INFO("I: BLT 0x%08x", addr);
va009039 1:5fa0120a6169 528 }
va009039 1:5fa0120a6169 529
va009039 1:5fa0120a6169 530 void BaseV6M::c_bgt(uint32_t code) { // BGT 0xdc00-0xdcff
va009039 1:5fa0120a6169 531 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 532 if (Z() == 0 && N() == V()) {
va009039 1:5fa0120a6169 533 jump(addr);
va009039 1:5fa0120a6169 534 }
va009039 1:5fa0120a6169 535 V6M_INFO("I: BGT 0x%08x", addr);
va009039 1:5fa0120a6169 536 }
va009039 1:5fa0120a6169 537
va009039 1:5fa0120a6169 538 void BaseV6M::c_ble(uint32_t code) { // BLE 0xdd00-0xddff
va009039 1:5fa0120a6169 539 uint32_t addr = R[_PC] + signed_immed(code, 8) * 2;
va009039 1:5fa0120a6169 540 if (Z() == 1 || N() != V()) {
va009039 1:5fa0120a6169 541 jump(addr);
va009039 1:5fa0120a6169 542 }
va009039 1:5fa0120a6169 543 V6M_INFO("I: BLE 0x%08x", addr);
va009039 1:5fa0120a6169 544 }
va009039 1:5fa0120a6169 545
va009039 1:5fa0120a6169 546 void BaseV6M::c_b_forward(uint32_t code) { // B 0xe000-0xe3ff
va009039 1:5fa0120a6169 547 uint32_t addr = R[_PC] + ((code&0x3ff)<<1);
va009039 1:5fa0120a6169 548 jump(addr);
va009039 1:5fa0120a6169 549 V6M_INFO("I: B 0x%08x ; forward", addr);
va009039 1:5fa0120a6169 550 }
va009039 1:5fa0120a6169 551
va009039 1:5fa0120a6169 552 void BaseV6M::c_b_backward(uint32_t code) { // B 0xe400-0xe7ff
va009039 1:5fa0120a6169 553 uint32_t addr = R[_PC] + ((code|~0x7ff)<<1);
va009039 1:5fa0120a6169 554 jump(addr);
va009039 1:5fa0120a6169 555 V6M_INFO("I: B 0x%08x ; backward", addr);
va009039 1:5fa0120a6169 556 }
va009039 1:5fa0120a6169 557
va009039 4:1c7b72bcfc4d 558 void BaseV6M::c32_bl_forward(uint32_t code) { // BL 0xf000-0xf2ff
va009039 1:5fa0120a6169 559 R[_LR] = R[_PC] | 1;
va009039 4:1c7b72bcfc4d 560 uint32_t imm32 = immed(code, 10)<<12|immed(code2nd, 11)<<1;
va009039 4:1c7b72bcfc4d 561 if ((code2nd & (1<<13)) == 0) { // J1
va009039 4:1c7b72bcfc4d 562 imm32 |= (1<<23);
va009039 4:1c7b72bcfc4d 563 }
va009039 4:1c7b72bcfc4d 564 if ((code2nd & (1<<11)) == 0) { // J2
va009039 4:1c7b72bcfc4d 565 imm32 |= (1<<22);
va009039 4:1c7b72bcfc4d 566 }
va009039 4:1c7b72bcfc4d 567 uint32_t addr = R[_PC] + imm32;
va009039 4:1c7b72bcfc4d 568 V6M_ASSERT((code2nd&0xd000) == 0xd000);
va009039 1:5fa0120a6169 569 jump(addr);
va009039 4:1c7b72bcfc4d 570 V6M_INFO("I: BL 0x%08x ; forward", addr);
va009039 4:1c7b72bcfc4d 571 }
va009039 4:1c7b72bcfc4d 572
va009039 4:1c7b72bcfc4d 573 void BaseV6M::c32_bl_forward3(uint32_t code) { // BL 0xf300-0xf3ff
va009039 4:1c7b72bcfc4d 574 if ((code2nd&0xd000) == 0xd000) {
va009039 4:1c7b72bcfc4d 575 c32_bl_forward(code);
va009039 4:1c7b72bcfc4d 576 return;
va009039 4:1c7b72bcfc4d 577 }
va009039 4:1c7b72bcfc4d 578 if ((code&0xf0) == 0x80) {
va009039 4:1c7b72bcfc4d 579 c32_msr(code, code2nd);
va009039 4:1c7b72bcfc4d 580 } else if ((code&0xff) == 0xbf) {
va009039 4:1c7b72bcfc4d 581 c32_dsb_dmb_isb(code, code2nd);
va009039 4:1c7b72bcfc4d 582 } else if ((code&0xff) == 0xef) {
va009039 4:1c7b72bcfc4d 583 c32_mrs(code, code2nd);
va009039 4:1c7b72bcfc4d 584 } else {
va009039 4:1c7b72bcfc4d 585 V6M_ASSERT(0);
va009039 4:1c7b72bcfc4d 586 }
va009039 4:1c7b72bcfc4d 587 }
va009039 4:1c7b72bcfc4d 588
va009039 4:1c7b72bcfc4d 589 void BaseV6M::c32_mrs(uint32_t code, uint32_t code2nd) {
va009039 4:1c7b72bcfc4d 590 d32_Rd_SYSm(code, code2nd);
va009039 4:1c7b72bcfc4d 591 jump(R[_PC]);
va009039 4:1c7b72bcfc4d 592 V6M_INFO("I: MRS %s,%s", GetRegName(Rd), GetSysName(Rm));
va009039 4:1c7b72bcfc4d 593 }
va009039 4:1c7b72bcfc4d 594
va009039 4:1c7b72bcfc4d 595 void BaseV6M::c32_msr(uint32_t code, uint32_t code2nd) {
va009039 4:1c7b72bcfc4d 596 d32_Rn_SYSm(code, code2nd);
va009039 4:1c7b72bcfc4d 597 jump(R[_PC]);
va009039 4:1c7b72bcfc4d 598 V6M_INFO("I: MSR %s,%s", GetSysName(Rm), GetRegName(Rn));
va009039 4:1c7b72bcfc4d 599 }
va009039 4:1c7b72bcfc4d 600
va009039 4:1c7b72bcfc4d 601 void BaseV6M::c32_dsb_dmb_isb(uint32_t code, uint32_t code2nd) {
va009039 4:1c7b72bcfc4d 602 if (code2nd == 0x8f4f) {
va009039 4:1c7b72bcfc4d 603 jump(R[_PC]);
va009039 4:1c7b72bcfc4d 604 V6M_INFO("I: DSB.W");
va009039 4:1c7b72bcfc4d 605 } else if (code2nd == 0x8f5f) {
va009039 4:1c7b72bcfc4d 606 jump(R[_PC]);
va009039 4:1c7b72bcfc4d 607 V6M_INFO("I: DMB.W");
va009039 4:1c7b72bcfc4d 608 } else if (code2nd == 0x8f6f) {
va009039 4:1c7b72bcfc4d 609 jump(R[_PC]);
va009039 4:1c7b72bcfc4d 610 V6M_INFO("I: ISB.W");
va009039 4:1c7b72bcfc4d 611 } else {
va009039 4:1c7b72bcfc4d 612 V6M_ASSERT(0);
va009039 4:1c7b72bcfc4d 613 }
va009039 4:1c7b72bcfc4d 614 }
va009039 4:1c7b72bcfc4d 615
va009039 4:1c7b72bcfc4d 616 void BaseV6M::c32_bl_backward(uint32_t code) { // BL 0xf400-0xf7ff
va009039 4:1c7b72bcfc4d 617 R[_LR] = R[_PC] | 1;
va009039 4:1c7b72bcfc4d 618 uint32_t imm32 = 0xff000000|immed(code, 10)<<12|immed(code2nd, 11)<<1;
va009039 4:1c7b72bcfc4d 619 if (code2nd & (1<<13)) { // J1
va009039 4:1c7b72bcfc4d 620 imm32 |= (1<<23);
va009039 4:1c7b72bcfc4d 621 }
va009039 4:1c7b72bcfc4d 622 if (code2nd & (1<<11)) { // J2
va009039 4:1c7b72bcfc4d 623 imm32 |= (1<<22);
va009039 4:1c7b72bcfc4d 624 }
va009039 4:1c7b72bcfc4d 625 uint32_t addr = R[_PC] + imm32;
va009039 4:1c7b72bcfc4d 626 V6M_ASSERT((code2nd&0xd000) == 0xd000);
va009039 4:1c7b72bcfc4d 627 jump(addr);
va009039 4:1c7b72bcfc4d 628 V6M_INFO("I: BL 0x%08x ; backward", addr);
va009039 1:5fa0120a6169 629 }
va009039 1:5fa0120a6169 630
va009039 1:5fa0120a6169 631 void BaseV6M::c_bx(uint32_t code) { // BX BLX 0x4770
va009039 1:5fa0120a6169 632 d_Op_H_Rm(code);
va009039 1:5fa0120a6169 633 if (op == 1) {
va009039 1:5fa0120a6169 634 R[_LR] = (R[_PC] - 2) | 1;
va009039 1:5fa0120a6169 635 }
va009039 1:5fa0120a6169 636 uint32_t addr = *Rm & 0xfffffffe;
va009039 1:5fa0120a6169 637 jump(addr);
va009039 1:5fa0120a6169 638 const char* name[] = {"BX", "BLX"};
va009039 1:5fa0120a6169 639 V6M_INFO("I: %s %s ; =0x%x", name[op], GetRegName(Rm), addr);
va009039 1:5fa0120a6169 640 exception_return();
va009039 1:5fa0120a6169 641 }
va009039 1:5fa0120a6169 642
va009039 1:5fa0120a6169 643 void BaseV6M::c_add(uint32_t code) { // ADDS Rd,Rn,Rm 0x1800-0x19ff
va009039 1:5fa0120a6169 644 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 645 e_add();
va009039 1:5fa0120a6169 646 V6M_INFO("I: ADDS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 647 }
va009039 1:5fa0120a6169 648
va009039 1:5fa0120a6169 649 void BaseV6M::c_sub(uint32_t code) { // SUBS Rd,Rn,Rm 0x1a00-0x1bff
va009039 1:5fa0120a6169 650 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 651 e_sub();
va009039 1:5fa0120a6169 652 V6M_INFO("I: SUBS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 653 }
va009039 1:5fa0120a6169 654
va009039 1:5fa0120a6169 655 void BaseV6M::c_add1(uint32_t code) { // ADD Rd,Rn,#imm3 / MOV Rd,Rn 0x1c00-0x1dff
va009039 1:5fa0120a6169 656 d_imm3_Rn_Rd(code);
va009039 1:5fa0120a6169 657 e_add();
va009039 1:5fa0120a6169 658 if ((code&0x01c0) == 0x0000) {
va009039 1:5fa0120a6169 659 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rn));
va009039 1:5fa0120a6169 660 V6M_ASSERT((code&0xffc0) == 0x1c00);
va009039 1:5fa0120a6169 661 } else {
va009039 1:5fa0120a6169 662 V6M_INFO("I: ADD %s,%s,#0x%02x", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 663 }
va009039 1:5fa0120a6169 664 }
va009039 1:5fa0120a6169 665
va009039 1:5fa0120a6169 666 void BaseV6M::c_sub1(uint32_t code) { // SUB Rd,Rn,#imm3 0x1e00-1fff
va009039 1:5fa0120a6169 667 d_imm3_Rn_Rd(code);
va009039 1:5fa0120a6169 668 e_sub();
va009039 1:5fa0120a6169 669 V6M_INFO("I: SUB %s,%s,#0x%02x", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 670 }
va009039 1:5fa0120a6169 671
va009039 1:5fa0120a6169 672 void BaseV6M::c_add2(uint32_t code) { // ADD Rd,#imm8 0x3000-0x37ff
va009039 1:5fa0120a6169 673 d_Rd_imm8(code);
va009039 1:5fa0120a6169 674 e_add();
va009039 1:5fa0120a6169 675 V6M_INFO("I: ADD %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 676 }
va009039 1:5fa0120a6169 677
va009039 1:5fa0120a6169 678 void BaseV6M::c_sub2(uint32_t code) { // SUB Rd,#imm8 0x3800-0x3fff
va009039 1:5fa0120a6169 679 d_Rd_imm8(code);
va009039 1:5fa0120a6169 680 e_sub();
va009039 1:5fa0120a6169 681 V6M_INFO("I: SUB %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 682 }
va009039 1:5fa0120a6169 683
va009039 1:5fa0120a6169 684 void BaseV6M::c_mov(uint32_t code) { // MOVS Rd,#imm8 0x2000-0x27ff
va009039 1:5fa0120a6169 685 d_Rd_imm8(code);
va009039 1:5fa0120a6169 686 e_mov();
va009039 1:5fa0120a6169 687 V6M_INFO("I: MOVS %s,#0x%02x", GetRegName(Rd), R[_IM]);
va009039 1:5fa0120a6169 688 }
va009039 1:5fa0120a6169 689
va009039 1:5fa0120a6169 690 void BaseV6M::c_cmp(uint32_t code) { // CMP Rn,#imm8 0x2800-0x2fff
va009039 1:5fa0120a6169 691 d_Rn_imm8(code);
va009039 1:5fa0120a6169 692 e_cmp();
va009039 1:5fa0120a6169 693 V6M_INFO("I: CMP %s,#0x%02x", GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 694 }
va009039 1:5fa0120a6169 695
va009039 1:5fa0120a6169 696 void BaseV6M::c_lsl(uint32_t code) { // LSLS Rd,Rn,#imm5 0x0000-0x07ff
va009039 1:5fa0120a6169 697 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 698 e_lsl();
va009039 1:5fa0120a6169 699 V6M_INFO("I: LSLS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 700 }
va009039 1:5fa0120a6169 701
va009039 1:5fa0120a6169 702 void BaseV6M::c_lsr(uint32_t code) { // LSRS Rd,Rn,#imm5 0x0800-0x0fff
va009039 1:5fa0120a6169 703 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 704 if (R[_IM] == 0) {
va009039 1:5fa0120a6169 705 R[_IM] = 32;
va009039 1:5fa0120a6169 706 }
va009039 1:5fa0120a6169 707 e_lsr();
va009039 1:5fa0120a6169 708 V6M_INFO("I: LSRS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 709 }
va009039 1:5fa0120a6169 710
va009039 1:5fa0120a6169 711 void BaseV6M::c_asr(uint32_t code) { // ASRS Rd,Rn,#imm5 0x1000-0x17ff
va009039 1:5fa0120a6169 712 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 713 if (R[_IM] == 0) {
va009039 1:5fa0120a6169 714 R[_IM] = 32;
va009039 1:5fa0120a6169 715 }
va009039 1:5fa0120a6169 716 e_asr();
va009039 1:5fa0120a6169 717 V6M_INFO("I: ASRS %s,%s,#%d", GetRegName(Rd), GetRegName(Rn), R[_IM]);
va009039 1:5fa0120a6169 718 }
va009039 1:5fa0120a6169 719
va009039 1:5fa0120a6169 720 void BaseV6M::c_and_eor_lsl_lsr(uint32_t code) { // ANDS|EORS|LSLS|LSRS Rd,Rm 0x4000-0x40ff
va009039 1:5fa0120a6169 721 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 722 if (op == 0) {
va009039 1:5fa0120a6169 723 e_and();
va009039 1:5fa0120a6169 724 V6M_INFO("I: ANDS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 725 } else if (op == 1) {
va009039 1:5fa0120a6169 726 e_eor();
va009039 1:5fa0120a6169 727 V6M_INFO("I: EORS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 728 } else if (op == 2) {
va009039 1:5fa0120a6169 729 e_lsl();
va009039 1:5fa0120a6169 730 V6M_INFO("I: LSLS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 731 } else {
va009039 1:5fa0120a6169 732 e_lsr();
va009039 1:5fa0120a6169 733 V6M_INFO("I: LSRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 734 }
va009039 1:5fa0120a6169 735 }
va009039 1:5fa0120a6169 736
va009039 1:5fa0120a6169 737 void BaseV6M::c_asr_adc_sbc_ror(uint32_t code) { // ASRS|ADCS|SBCS|RORS Rd,Rm 0x4100-0x41ff
va009039 1:5fa0120a6169 738 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 739 if (op == 4) {
va009039 1:5fa0120a6169 740 e_asr();
va009039 1:5fa0120a6169 741 V6M_INFO("I: ASRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 742 } else if (op == 5) {
va009039 1:5fa0120a6169 743 e_adc();
va009039 1:5fa0120a6169 744 V6M_INFO("I: ADCS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 745 } else if (op == 6) {
va009039 1:5fa0120a6169 746 e_sbc();
va009039 1:5fa0120a6169 747 V6M_INFO("I: SBCS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 748 } else {
va009039 1:5fa0120a6169 749 e_ror();
va009039 1:5fa0120a6169 750 V6M_INFO("I: RORS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 751 }
va009039 1:5fa0120a6169 752 }
va009039 1:5fa0120a6169 753
va009039 1:5fa0120a6169 754 void BaseV6M::c_tst_neg_cmp_cmn(uint32_t code) { // TST|NEGS|CMP|CMN Rd,Rm 0x4200-0x42ff
va009039 1:5fa0120a6169 755 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 756 if (op == 8) {
va009039 1:5fa0120a6169 757 e_tst();
va009039 1:5fa0120a6169 758 V6M_INFO("I: TST %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 759 } else if (op == 9) {
va009039 1:5fa0120a6169 760 e_neg();
va009039 1:5fa0120a6169 761 V6M_INFO("I: NEG %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 762 } else if (op == 10) {
va009039 1:5fa0120a6169 763 e_cmp();
va009039 1:5fa0120a6169 764 V6M_INFO("I: CMP %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 765 } else {
va009039 1:5fa0120a6169 766 e_cmn();
va009039 1:5fa0120a6169 767 V6M_INFO("I: CMN %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 768 }
va009039 1:5fa0120a6169 769 }
va009039 1:5fa0120a6169 770
va009039 1:5fa0120a6169 771 void BaseV6M::c_orr_mul_bic_mvn(uint32_t code) { // ORRS|MULS|BICS|MVNS Rd,Rm 0x4300-0x43ff
va009039 1:5fa0120a6169 772 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 773 if (op == 12) {
va009039 1:5fa0120a6169 774 e_orr();
va009039 1:5fa0120a6169 775 V6M_INFO("I: ORRS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 776 } else if (op == 13) {
va009039 1:5fa0120a6169 777 e_mul();
va009039 1:5fa0120a6169 778 V6M_INFO("I: MULS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 779 } else if (op == 14) {
va009039 1:5fa0120a6169 780 e_bic();
va009039 1:5fa0120a6169 781 V6M_INFO("I: BICS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 782 } else {
va009039 1:5fa0120a6169 783 e_mvn();
va009039 1:5fa0120a6169 784 V6M_INFO("I: MVNS %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 785 }
va009039 1:5fa0120a6169 786 }
va009039 1:5fa0120a6169 787
va009039 1:5fa0120a6169 788 void BaseV6M::c_add_hr(uint32_t code) { // ADD Rd,Rm (high reg) 0x4400-0x44ff
va009039 1:5fa0120a6169 789 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 790 *Rd = add32(*Rn, *Rm);
va009039 3:fe333683e8f7 791 if (Rd == &R[_PC]) {
va009039 3:fe333683e8f7 792 jump(R[_PC]);
va009039 3:fe333683e8f7 793 V6M_INFO("I: ADD pc,pc,%s ; pc=0x%08x", GetRegName(Rn), R[_PC]);
va009039 3:fe333683e8f7 794 exception_return();
va009039 3:fe333683e8f7 795 } else {
va009039 3:fe333683e8f7 796 V6M_INFO("I: ADD %s,%s,%s", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm));
va009039 3:fe333683e8f7 797 }
va009039 1:5fa0120a6169 798 }
va009039 1:5fa0120a6169 799
va009039 1:5fa0120a6169 800 void BaseV6M::c_cmp_hr(uint32_t code) { // CMP Rd,Rm (high reg) 0x4500-0x45ff
va009039 1:5fa0120a6169 801 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 802 V6M_ASSERT(Rd != &R[_PC]);
va009039 1:5fa0120a6169 803 Rd = &R[_NL];
va009039 1:5fa0120a6169 804 e_cmp();
va009039 1:5fa0120a6169 805 V6M_INFO("I: CMP %s,%s", GetRegName(Rn), GetRegName(Rm));
va009039 1:5fa0120a6169 806 }
va009039 1:5fa0120a6169 807
va009039 1:5fa0120a6169 808 void BaseV6M::c_mov_hr(uint32_t code) { // MOV Rd,Rm (high reg) 0x4600-0x46ff
va009039 1:5fa0120a6169 809 d_D_M_Rm_Rd(code);
va009039 1:5fa0120a6169 810 *Rd = *Rm;
va009039 1:5fa0120a6169 811 if (Rd == &R[_PC]) {
va009039 1:5fa0120a6169 812 jump(R[_PC]);
va009039 1:5fa0120a6169 813 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 814 exception_return();
va009039 1:5fa0120a6169 815 } else {
va009039 1:5fa0120a6169 816 V6M_INFO("I: MOV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 817 }
va009039 1:5fa0120a6169 818 }
va009039 1:5fa0120a6169 819
va009039 1:5fa0120a6169 820 void BaseV6M::c_add_r_pc(uint32_t code) { // ADD Rd,pc,#imm8 0xa000-0xa7ff
va009039 1:5fa0120a6169 821 d_Rd_imm8(code);
va009039 1:5fa0120a6169 822 uint32_t off = R[_IM] * 4;
va009039 1:5fa0120a6169 823 uint32_t addr = align32(R[_PC]) + off;
va009039 1:5fa0120a6169 824 *Rd = addr;
va009039 1:5fa0120a6169 825 V6M_INFO("I: ADD %s,pc,#0x%02x ; @0x%08x", GetRegName(Rd), off, addr);
va009039 1:5fa0120a6169 826 }
va009039 1:5fa0120a6169 827
va009039 1:5fa0120a6169 828 void BaseV6M::c_add_r_sp(uint32_t code) { // ADD Rd,sp,#imm8 0xa800-0xafff
va009039 1:5fa0120a6169 829 d_Rd_imm8(code);
va009039 1:5fa0120a6169 830 uint32_t off = R[_IM] * 4;
va009039 1:5fa0120a6169 831 uint32_t addr = *Rd = R[_SP] + off;
va009039 1:5fa0120a6169 832 *Rd = addr;
va009039 1:5fa0120a6169 833 V6M_INFO("I: ADD %s,sp,#0x%02x ; @0x%08x", GetRegName(Rd), off, addr);
va009039 1:5fa0120a6169 834 V6M_ASSERT(addr%4 == 0);
va009039 1:5fa0120a6169 835 }
va009039 1:5fa0120a6169 836
va009039 1:5fa0120a6169 837 void BaseV6M::c_add_sp(uint32_t code) { // ADD|SUB sp,sp,#imm 0xb000-0xb0ff
va009039 1:5fa0120a6169 838 d_Op_imm7(code);
va009039 1:5fa0120a6169 839 uint32_t data = R[_IM] * 4;
va009039 1:5fa0120a6169 840 if (op == 0) {
va009039 1:5fa0120a6169 841 R[_SP] += data;
va009039 1:5fa0120a6169 842 } else {
va009039 1:5fa0120a6169 843 R[_SP] -= data;
va009039 1:5fa0120a6169 844 }
va009039 1:5fa0120a6169 845 const char* name[] = {"ADD", "SUB"};
va009039 1:5fa0120a6169 846 V6M_INFO("I: %s sp,sp,#0x%x", name[op], data);
va009039 1:5fa0120a6169 847 }
va009039 1:5fa0120a6169 848
va009039 1:5fa0120a6169 849 void BaseV6M::c_ldr1(uint32_t code) { // LDR Rd,[Rn,#imm5] 0x6800-0x6fff
va009039 1:5fa0120a6169 850 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 851 e_ldr<uint32_t>(true);
va009039 1:5fa0120a6169 852 V6M_INFO("I: LDR %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 853 }
va009039 1:5fa0120a6169 854
va009039 1:5fa0120a6169 855 void BaseV6M::c_str1(uint32_t code) { // STR Rd,[Rn,#imm5] 0x6000-0x67ff
va009039 1:5fa0120a6169 856 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 857 e_str<uint32_t>(true);
va009039 1:5fa0120a6169 858 V6M_INFO("I: STR %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 859 }
va009039 1:5fa0120a6169 860
va009039 1:5fa0120a6169 861 void BaseV6M::c_ldrb(uint32_t code) { // LDRB Rd,[Rn,#imm5] 0x7800-0x7fff
va009039 1:5fa0120a6169 862 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 863 e_ldr<uint8_t>(true);
va009039 1:5fa0120a6169 864 V6M_INFO("I: LDRB %s,[%s,#0x%02x] ; =0x%02x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 865 }
va009039 1:5fa0120a6169 866
va009039 1:5fa0120a6169 867 void BaseV6M::c_strb(uint32_t code) { // STRB Rd,[Rn,#imm5] 0x7000-0x77ff
va009039 1:5fa0120a6169 868 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 869 e_str<uint8_t>(true);
va009039 1:5fa0120a6169 870 V6M_INFO("I: STRB %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 871 }
va009039 1:5fa0120a6169 872
va009039 1:5fa0120a6169 873 void BaseV6M::c_ldrh(uint32_t code) { // LDRH Rd,[Rn,#imm5] 0x8800-0x8fff
va009039 1:5fa0120a6169 874 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 875 e_ldr<uint16_t>(true);
va009039 1:5fa0120a6169 876 V6M_INFO("I: LDRH %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 877 }
va009039 1:5fa0120a6169 878
va009039 1:5fa0120a6169 879 void BaseV6M::c_strh(uint32_t code) { // STRH Rd,[Rn,#imm5] 0x8000-0x87ff
va009039 1:5fa0120a6169 880 d_imm5_Rn_Rd(code);
va009039 1:5fa0120a6169 881 e_str<uint16_t>(true);
va009039 1:5fa0120a6169 882 V6M_INFO("I: STRH %s,[%s,#0x%02x] ; =0x%x @0x%x", GetRegName(Rd), GetRegName(Rn), R[_IM], data, addr);
va009039 1:5fa0120a6169 883 }
va009039 1:5fa0120a6169 884
va009039 1:5fa0120a6169 885 void BaseV6M::c_ldr2(uint32_t code) { // LDR Rd,[Rn,Rm] 0x5800-0x59ff
va009039 1:5fa0120a6169 886 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 887 e_ldr<uint32_t>();
va009039 1:5fa0120a6169 888 V6M_INFO("I: LDR %s,[%s,%s] ; =0x%08x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 889 }
va009039 1:5fa0120a6169 890
va009039 1:5fa0120a6169 891 void BaseV6M::c_str2(uint32_t code) { // STR Rd,[Rn,Rm] 0x5000-0x51ff
va009039 1:5fa0120a6169 892 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 893 e_str<uint32_t>();
va009039 1:5fa0120a6169 894 V6M_INFO("I: STR %s,[%s,%s] ; =0x%08x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 895 }
va009039 1:5fa0120a6169 896
va009039 1:5fa0120a6169 897 void BaseV6M::c_ldrh2(uint32_t code) { // LDRH Rd,[Rn,Rm] 0x5a00-0x5bff
va009039 1:5fa0120a6169 898 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 899 e_ldr<uint16_t>();
va009039 1:5fa0120a6169 900 V6M_INFO("I: LDRH %s,[%s,%s] ; =0x%04x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 901 }
va009039 1:5fa0120a6169 902
va009039 1:5fa0120a6169 903 void BaseV6M::c_strh2(uint32_t code) { // STRH Rd,[Rn,Rm] 0x5200-0x53ff
va009039 1:5fa0120a6169 904 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 905 e_str<uint16_t>();
va009039 1:5fa0120a6169 906 V6M_INFO("I: STRH %s,[%s,%s] ; =0x%04x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 907 }
va009039 1:5fa0120a6169 908
va009039 1:5fa0120a6169 909 void BaseV6M::c_ldrsh(uint32_t code) { // LDRSH Rd,[Rn,Rm] 0x5e00-0x5fff
va009039 1:5fa0120a6169 910 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 911 e_ldr<uint16_t>();
va009039 1:5fa0120a6169 912 uint32_t data = signed_immed(*Rd, 16) & 0xffffffff;
va009039 1:5fa0120a6169 913 *Rd = data;
va009039 1:5fa0120a6169 914 V6M_INFO("I: LDRSH %s,[%s,%s] ; =0x%x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 915 }
va009039 1:5fa0120a6169 916
va009039 1:5fa0120a6169 917 void BaseV6M::c_ldrb2(uint32_t code) { // LDRB Rd,[Rn,Rm] 0x5c00-0x5dff
va009039 1:5fa0120a6169 918 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 919 e_ldr<uint8_t>();
va009039 1:5fa0120a6169 920 V6M_INFO("I: LDRB %s,[%s,%s] ; =0x%02x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 921 }
va009039 1:5fa0120a6169 922
va009039 1:5fa0120a6169 923 void BaseV6M::c_strb2(uint32_t code) { // STRB Rd,[Rn,Rm] 0x5400-0x55ff
va009039 1:5fa0120a6169 924 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 925 e_str<uint8_t>();
va009039 1:5fa0120a6169 926 V6M_INFO("I: STRB %s,[%s,%s] ; =0x%02x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 927 }
va009039 1:5fa0120a6169 928
va009039 1:5fa0120a6169 929 void BaseV6M::c_ldrsb(uint32_t code) { // LDRSB Rd,[Rn,Rm] 0x5600-0x57ff
va009039 1:5fa0120a6169 930 d_Rm_Rn_Rd(code);
va009039 1:5fa0120a6169 931 e_ldr<uint8_t>();
va009039 1:5fa0120a6169 932 uint32_t data = signed_immed(*Rd, 8) & 0xffffffff;
va009039 1:5fa0120a6169 933 *Rd = data;
va009039 1:5fa0120a6169 934 V6M_INFO("I: LDRSB %s,[%s,%s] ; =0x%x @0x%08x", GetRegName(Rd), GetRegName(Rn), GetRegName(Rm), data, addr);
va009039 1:5fa0120a6169 935 }
va009039 1:5fa0120a6169 936
va009039 1:5fa0120a6169 937 void BaseV6M::c_ldr_pc(uint32_t code) { // LDR Rd,[pc,#imm8] 0x4800-0x4fff
va009039 1:5fa0120a6169 938 d_Rd_imm8(code);
va009039 1:5fa0120a6169 939 uint32_t off = *Rm * 4;
va009039 1:5fa0120a6169 940 uint32_t addr = align32(R[_PC]) + off;
va009039 1:5fa0120a6169 941 uint32_t data = peek32(addr);
va009039 1:5fa0120a6169 942 *Rd = data;
va009039 1:5fa0120a6169 943 V6M_INFO("I: LDR %s,[pc,#%d] ; =0x%x @0x%08x", GetRegName(Rd), off, data, addr);
va009039 1:5fa0120a6169 944 }
va009039 1:5fa0120a6169 945
va009039 1:5fa0120a6169 946 void BaseV6M::c_ldr_sp(uint32_t code) { // LDR Rd,[sp,#imm8] 0x9800-0x9fff
va009039 1:5fa0120a6169 947 d_Rd_imm8(code);
va009039 1:5fa0120a6169 948 Rn = &R[_SP];
va009039 1:5fa0120a6169 949 e_ldr<uint32_t>(true);
va009039 1:5fa0120a6169 950 V6M_INFO("I: LDR %s,[sp,#0x%x] ; =0x%08x @0x%08x", GetRegName(Rd), R[_IM], data, addr);
va009039 1:5fa0120a6169 951 }
va009039 1:5fa0120a6169 952
va009039 1:5fa0120a6169 953 void BaseV6M::c_str_sp(uint32_t code) { // STR Rd,[sp,#imm8] 0x9000-0x97ff
va009039 1:5fa0120a6169 954 d_Rd_imm8(code);
va009039 1:5fa0120a6169 955 Rn = &R[_SP];
va009039 1:5fa0120a6169 956 e_str<uint32_t>(true);
va009039 1:5fa0120a6169 957 V6M_INFO("I: STR %s,[sp,#0x%x] ; =0x08%x @0x%08x", GetRegName(Rd), R[_IM], data, addr);
va009039 1:5fa0120a6169 958 }
va009039 1:5fa0120a6169 959
va009039 1:5fa0120a6169 960 void BaseV6M::e_ldm() { // LDM / POP
va009039 1:5fa0120a6169 961 uint32_t addr = *Rn;
va009039 1:5fa0120a6169 962 for (int k = 0; k <= 7; k++) {
va009039 1:5fa0120a6169 963 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 964 R[k] = peek32(addr);
va009039 1:5fa0120a6169 965 addr += 4;
va009039 1:5fa0120a6169 966 }
va009039 1:5fa0120a6169 967 }
va009039 1:5fa0120a6169 968 if (! (reg_list & (1<<GetRegIndex(Rn)))) {
va009039 1:5fa0120a6169 969 *Rn = addr;
va009039 1:5fa0120a6169 970 }
va009039 1:5fa0120a6169 971 }
va009039 1:5fa0120a6169 972
va009039 1:5fa0120a6169 973 void BaseV6M::e_stm() { // STM
va009039 1:5fa0120a6169 974 uint32_t addr = *Rn;
va009039 1:5fa0120a6169 975 for (int k = 0; k <= 7; k++) {
va009039 1:5fa0120a6169 976 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 977 poke32(addr, R[k]);
va009039 1:5fa0120a6169 978 addr += 4;
va009039 1:5fa0120a6169 979 }
va009039 1:5fa0120a6169 980 }
va009039 1:5fa0120a6169 981 *Rn = addr;
va009039 1:5fa0120a6169 982 }
va009039 1:5fa0120a6169 983
va009039 1:5fa0120a6169 984 void BaseV6M::e_push() { // PUSH
va009039 1:5fa0120a6169 985 for (int k = 7; k >= 0; k--) {
va009039 1:5fa0120a6169 986 if (reg_list & (1<<k)) {
va009039 1:5fa0120a6169 987 push(R[k]);
va009039 1:5fa0120a6169 988 }
va009039 1:5fa0120a6169 989 }
va009039 1:5fa0120a6169 990 }
va009039 1:5fa0120a6169 991
va009039 1:5fa0120a6169 992 void BaseV6M::c_ldm(uint32_t code) { // LDM Rn!,{reg_list} 0xc800-0xcfff
va009039 1:5fa0120a6169 993 d_Rn_reg_list(code);
va009039 1:5fa0120a6169 994 e_ldm();
va009039 1:5fa0120a6169 995 V6M_INFO("I: LDMIA %s!,{%s}", GetRegName(Rn), StrRegLists());
va009039 1:5fa0120a6169 996 }
va009039 1:5fa0120a6169 997
va009039 1:5fa0120a6169 998 void BaseV6M::c_stm(uint32_t code) { // STM Rn!,{reg_list} 0xc000-0xc7ff
va009039 1:5fa0120a6169 999 d_Rn_reg_list(code);
va009039 1:5fa0120a6169 1000 e_stm();
va009039 1:5fa0120a6169 1001 V6M_INFO("I: STMIA %s!,{%s}", GetRegName(Rn), StrRegLists());
va009039 1:5fa0120a6169 1002 }
va009039 1:5fa0120a6169 1003
va009039 1:5fa0120a6169 1004 void BaseV6M::c_pop(uint32_t code) { // POP {reg_list} 0xbc00-0xbcff
va009039 1:5fa0120a6169 1005 d_reg_list(code);
va009039 1:5fa0120a6169 1006 Rn = &R[_SP];
va009039 1:5fa0120a6169 1007 e_ldm();
va009039 1:5fa0120a6169 1008 V6M_INFO("I: POP {%s}", StrRegLists());
va009039 1:5fa0120a6169 1009 }
va009039 1:5fa0120a6169 1010
va009039 1:5fa0120a6169 1011 void BaseV6M::c_pop_pc(uint32_t code) { // POP {reg_list,pc} 0xbd00-0xbdff
va009039 1:5fa0120a6169 1012 d_reg_list(code);
va009039 1:5fa0120a6169 1013 Rn = &R[_SP];
va009039 1:5fa0120a6169 1014 e_ldm();
va009039 1:5fa0120a6169 1015 jump(pop());
va009039 1:5fa0120a6169 1016 V6M_INFO("I: POP {%s,pc}", StrRegLists());
va009039 1:5fa0120a6169 1017 }
va009039 1:5fa0120a6169 1018
va009039 1:5fa0120a6169 1019 void BaseV6M::c_push(uint32_t code) { // PUSH {reg_list} 0xb400-0xb4ff
va009039 1:5fa0120a6169 1020 d_reg_list(code);
va009039 1:5fa0120a6169 1021 e_push();
va009039 1:5fa0120a6169 1022 V6M_INFO("I: PUSH {%s}", StrRegLists());
va009039 1:5fa0120a6169 1023 }
va009039 1:5fa0120a6169 1024
va009039 1:5fa0120a6169 1025 void BaseV6M::c_push_lr(uint32_t code) { // PUSH {reg_list,lr} 0xb500-0xb5ff
va009039 1:5fa0120a6169 1026 d_reg_list(code);
va009039 1:5fa0120a6169 1027 push(R[_LR]);
va009039 1:5fa0120a6169 1028 e_push();
va009039 1:5fa0120a6169 1029 V6M_INFO("I: PUSH {%s,lr}", StrRegLists());
va009039 1:5fa0120a6169 1030 }
va009039 1:5fa0120a6169 1031
va009039 1:5fa0120a6169 1032 void BaseV6M::c_uxt(uint32_t code) { // UXTH|UXTB Rd,Rm 0xb200-0xb2ff
va009039 1:5fa0120a6169 1033 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 1034 if (op == 10) {
va009039 1:5fa0120a6169 1035 *Rd = *Rm & 0xffff;
va009039 1:5fa0120a6169 1036 V6M_INFO("I: UXTH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1037 V6M_ASSERT((code&0xffc0) == 0xb280);
va009039 1:5fa0120a6169 1038 } else if (op == 11) {
va009039 1:5fa0120a6169 1039 *Rd = *Rm & 0xff;
va009039 1:5fa0120a6169 1040 V6M_INFO("I: UXTB %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1041 V6M_ASSERT((code&0xffc0) == 0xb2c0);
va009039 1:5fa0120a6169 1042 } else if (op == 8) {
va009039 1:5fa0120a6169 1043 *Rd = signed_immed(*Rm, 16) & 0xffffffff;
va009039 1:5fa0120a6169 1044 V6M_INFO("I: SXTH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1045 V6M_ASSERT((code&0xffc0) == 0xb200);
va009039 1:5fa0120a6169 1046 } else if (op == 9) {
va009039 1:5fa0120a6169 1047 *Rd = signed_immed(*Rm, 8) & 0xffffffff;
va009039 1:5fa0120a6169 1048 V6M_INFO("I: SXTB %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1049 V6M_ASSERT((code&0xffc0) == 0xb240);
va009039 1:5fa0120a6169 1050 } else {
va009039 1:5fa0120a6169 1051 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1052 }
va009039 1:5fa0120a6169 1053 }
va009039 1:5fa0120a6169 1054
va009039 1:5fa0120a6169 1055 void BaseV6M::c_rev(uint32_t code) { // REV|REV16|REVSH Rd,Rm 0xba00-0xba3f
va009039 1:5fa0120a6169 1056 d_Op_Rm_Rd(code);
va009039 1:5fa0120a6169 1057 if (op == 8) {
va009039 1:5fa0120a6169 1058 uint32_t data = *Rm;
va009039 1:5fa0120a6169 1059 *Rd = ((data<<24)&0xff000000)|((data<<8)&0xff0000)|((data>>8)&0xff00)|data>>24;
va009039 1:5fa0120a6169 1060 V6M_INFO("I: REV %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1061 }
va009039 1:5fa0120a6169 1062 if (op == 9) {
va009039 1:5fa0120a6169 1063 uint32_t data = *Rm;
va009039 1:5fa0120a6169 1064 *Rd = ((data<<8)&0xff00ff00)|((data>>8)&0x00ff00ff);
va009039 1:5fa0120a6169 1065 V6M_INFO("I: REV16 %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1066 }
va009039 1:5fa0120a6169 1067 if (op == 11) {
va009039 1:5fa0120a6169 1068 uint32_t data = *Rm;
va009039 1:5fa0120a6169 1069 *Rd = ((data<<8)&0xff00)|((data>>8)&0x00ff);
va009039 1:5fa0120a6169 1070 if (*Rd & 0x8000) {
va009039 1:5fa0120a6169 1071 *Rd |= 0xffff0000;
va009039 1:5fa0120a6169 1072 }
va009039 1:5fa0120a6169 1073 V6M_INFO("I: REVSH %s,%s", GetRegName(Rd), GetRegName(Rm));
va009039 1:5fa0120a6169 1074 } else {
va009039 1:5fa0120a6169 1075 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1076 }
va009039 1:5fa0120a6169 1077 }
va009039 1:5fa0120a6169 1078
va009039 1:5fa0120a6169 1079 void BaseV6M::c_nop(uint32_t code) { // NOP 0xbf00
va009039 1:5fa0120a6169 1080 V6M_ASSERT(code == 0xbf00);
va009039 1:5fa0120a6169 1081 V6M_INFO("I: NOP");
va009039 1:5fa0120a6169 1082 }
va009039 1:5fa0120a6169 1083
va009039 1:5fa0120a6169 1084 void BaseV6M::c_bkpt(uint32_t code) { // BKPT #imm8 0xbe00-0xbeff
va009039 1:5fa0120a6169 1085 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1086 }
va009039 1:5fa0120a6169 1087
va009039 1:5fa0120a6169 1088 void BaseV6M::c_swi(uint32_t code) { // SWI #imm8 0xdf00-0xdfff
va009039 1:5fa0120a6169 1089 V6M_INFO("I: SWI #%d", immed(code, 8, 0));
va009039 1:5fa0120a6169 1090 exception_entry(11);
va009039 1:5fa0120a6169 1091 }
va009039 1:5fa0120a6169 1092
va009039 1:5fa0120a6169 1093 void BaseV6M::c_cps(uint32_t code) { // CPSIE|CPSID A|I|F 0xb6c0-0xb6e7
va009039 1:5fa0120a6169 1094 uint32_t i = immed(code, 1,4);
va009039 1:5fa0120a6169 1095 uint32_t f = immed(code, 3,0);
va009039 1:5fa0120a6169 1096 V6M_ASSERT(f != 0);
va009039 1:5fa0120a6169 1097 const char* i_name[] = {"CPSIE", "CPSID"};
va009039 1:5fa0120a6169 1098 const char* f_name[] = {"", "F", "I", "IF", "A", "AF", "AI", "AIF"};
va009039 1:5fa0120a6169 1099 V6M_INFO("I: %s %s", i_name[i], f_name[f]);
va009039 1:5fa0120a6169 1100 }
va009039 1:5fa0120a6169 1101
va009039 1:5fa0120a6169 1102 void BaseV6M::c_todo(uint32_t code) { // undefined code
va009039 1:5fa0120a6169 1103 V6M_ERROR("I: ASSERT!!! %04x %04x", code, code2nd);
va009039 1:5fa0120a6169 1104 V6M_ASSERT(0);
va009039 1:5fa0120a6169 1105 }
va009039 1:5fa0120a6169 1106
va009039 1:5fa0120a6169 1107 void BaseV6M::fetch() {
va009039 3:fe333683e8f7 1108 V6M_ASSERT((R[_PC]&1) == 0);
va009039 1:5fa0120a6169 1109 if (cache) {
va009039 1:5fa0120a6169 1110 code = code2nd;
va009039 3:fe333683e8f7 1111 code2nd = peek16(R[_PC]);
va009039 1:5fa0120a6169 1112 R[_PC] += 2;
va009039 1:5fa0120a6169 1113 } else {
va009039 3:fe333683e8f7 1114 uint32_t d = peek32(R[_PC]);
va009039 1:5fa0120a6169 1115 code = d & 0xffff;
va009039 1:5fa0120a6169 1116 code2nd = d>>16;
va009039 1:5fa0120a6169 1117 R[_PC] += 4;
va009039 1:5fa0120a6169 1118 cache = true;
va009039 1:5fa0120a6169 1119 }
va009039 1:5fa0120a6169 1120 }
va009039 1:5fa0120a6169 1121
va009039 1:5fa0120a6169 1122 void BaseV6M::execute() {
va009039 1:5fa0120a6169 1123 switch(code>>8) {
va009039 1:5fa0120a6169 1124 case 0xd0: c_beq(code); break;
va009039 1:5fa0120a6169 1125 case 0xd1: c_bne(code); break;
va009039 1:5fa0120a6169 1126 case 0xd2: c_bcs(code); break;
va009039 1:5fa0120a6169 1127 case 0xd3: c_bcc(code); break;
va009039 1:5fa0120a6169 1128 case 0xd4: c_bmi(code); break;
va009039 1:5fa0120a6169 1129 case 0xd5: c_bpl(code); break;
va009039 1:5fa0120a6169 1130 case 0xd6: c_bvs(code); break;
va009039 1:5fa0120a6169 1131 case 0xd7: c_bvc(code); break;
va009039 1:5fa0120a6169 1132 case 0xd8: c_bhi(code); break;
va009039 1:5fa0120a6169 1133 case 0xd9: c_bls(code); break;
va009039 1:5fa0120a6169 1134 case 0xda: c_bge(code); break;
va009039 1:5fa0120a6169 1135 case 0xdb: c_blt(code); break;
va009039 1:5fa0120a6169 1136 case 0xdc: c_bgt(code); break;
va009039 1:5fa0120a6169 1137 case 0xdd: c_ble(code); break;
va009039 1:5fa0120a6169 1138 case 0xe0 ... 0xe3: c_b_forward(code); break;
va009039 1:5fa0120a6169 1139 case 0xe4 ... 0xe7: c_b_backward(code); break;
va009039 4:1c7b72bcfc4d 1140 case 0xf0 ... 0xf2: c32_bl_forward(code); break;
va009039 4:1c7b72bcfc4d 1141 case 0xf3: c32_bl_forward3(code); break;
va009039 4:1c7b72bcfc4d 1142 case 0xf4 ... 0xf7: c32_bl_backward(code); break;
va009039 1:5fa0120a6169 1143 case 0x47: c_bx(code); break;
va009039 1:5fa0120a6169 1144 case 0x18 ... 0x19: c_add(code); break;
va009039 1:5fa0120a6169 1145 case 0x1a ... 0x1b: c_sub(code); break;
va009039 1:5fa0120a6169 1146 case 0x1c ... 0x1d: c_add1(code); break;
va009039 1:5fa0120a6169 1147 case 0x1e ... 0x1f: c_sub1(code); break;
va009039 1:5fa0120a6169 1148 case 0x30 ... 0x37: c_add2(code); break;
va009039 1:5fa0120a6169 1149 case 0x38 ... 0x3f: c_sub2(code); break;
va009039 1:5fa0120a6169 1150 case 0x20 ... 0x27: c_mov(code); break;
va009039 1:5fa0120a6169 1151 case 0x28 ... 0x2f: c_cmp(code); break;
va009039 1:5fa0120a6169 1152 case 0x00 ... 0x07: c_lsl(code); break;
va009039 1:5fa0120a6169 1153 case 0x08 ... 0x0f: c_lsr(code); break;
va009039 1:5fa0120a6169 1154 case 0x10 ... 0x17: c_asr(code); break;
va009039 1:5fa0120a6169 1155 case 0x40: c_and_eor_lsl_lsr(code); break;
va009039 1:5fa0120a6169 1156 case 0x41: c_asr_adc_sbc_ror(code); break;
va009039 1:5fa0120a6169 1157 case 0x42: c_tst_neg_cmp_cmn(code); break;
va009039 1:5fa0120a6169 1158 case 0x43: c_orr_mul_bic_mvn(code); break;
va009039 1:5fa0120a6169 1159 case 0x44: c_add_hr(code); break;
va009039 1:5fa0120a6169 1160 case 0x45: c_cmp_hr(code); break;
va009039 1:5fa0120a6169 1161 case 0x46: c_mov_hr(code); break;
va009039 1:5fa0120a6169 1162 case 0xa0 ... 0xa7: c_add_r_pc(code); break;
va009039 1:5fa0120a6169 1163 case 0xa8 ... 0xaf: c_add_r_sp(code); break;
va009039 1:5fa0120a6169 1164 case 0xb0: c_add_sp(code); break;
va009039 1:5fa0120a6169 1165 case 0x68 ... 0x6f: c_ldr1(code); break;
va009039 1:5fa0120a6169 1166 case 0x60 ... 0x67: c_str1(code); break;
va009039 1:5fa0120a6169 1167 case 0x78 ... 0x7f: c_ldrb(code); break;
va009039 1:5fa0120a6169 1168 case 0x70 ... 0x77: c_strb(code); break;
va009039 1:5fa0120a6169 1169 case 0x88 ... 0x8f: c_ldrh(code); break;
va009039 1:5fa0120a6169 1170 case 0x80 ... 0x87: c_strh(code); break;
va009039 1:5fa0120a6169 1171 case 0x58 ... 0x59: c_ldr2(code); break;
va009039 1:5fa0120a6169 1172 case 0x50 ... 0x51: c_str2(code); break;
va009039 1:5fa0120a6169 1173 case 0x5a ... 0x5b: c_ldrh2(code); break;
va009039 1:5fa0120a6169 1174 case 0x52 ... 0x53: c_strh2(code); break;
va009039 1:5fa0120a6169 1175 case 0x5e ... 0x5f: c_ldrsh(code); break;
va009039 1:5fa0120a6169 1176 case 0x5c ... 0x5d: c_ldrb2(code); break;
va009039 1:5fa0120a6169 1177 case 0x54 ... 0x55: c_strb2(code); break;
va009039 1:5fa0120a6169 1178 case 0x56 ... 0x57: c_ldrsb(code); break;
va009039 1:5fa0120a6169 1179 case 0x48 ... 0x4f: c_ldr_pc(code); break;
va009039 1:5fa0120a6169 1180 case 0x98 ... 0x9f: c_ldr_sp(code); break;
va009039 1:5fa0120a6169 1181 case 0x90 ... 0x97: c_str_sp(code); break;
va009039 1:5fa0120a6169 1182 case 0xc8 ... 0xcf: c_ldm(code); break;
va009039 1:5fa0120a6169 1183 case 0xc0 ... 0xc7: c_stm(code); break;
va009039 1:5fa0120a6169 1184 case 0xbc: c_pop(code); break;
va009039 1:5fa0120a6169 1185 case 0xbd: c_pop_pc(code); break;
va009039 1:5fa0120a6169 1186 case 0xb4: c_push(code); break;
va009039 1:5fa0120a6169 1187 case 0xb5: c_push_lr(code); break;
va009039 1:5fa0120a6169 1188 case 0xb2: c_uxt(code); break;
va009039 1:5fa0120a6169 1189 case 0xba: c_rev(code); break;
va009039 1:5fa0120a6169 1190 case 0xbf: c_nop(code); break;
va009039 1:5fa0120a6169 1191 case 0xbe: c_bkpt(code); break;
va009039 1:5fa0120a6169 1192 case 0xdf: c_swi(code); break;
va009039 1:5fa0120a6169 1193 case 0xb6: c_cps(code); break;
va009039 1:5fa0120a6169 1194 default: c_todo(code); break;
va009039 1:5fa0120a6169 1195 }
va009039 1:5fa0120a6169 1196 cycle++;
va009039 1:5fa0120a6169 1197 }
va009039 1:5fa0120a6169 1198
va009039 1:5fa0120a6169 1199 void BaseV6M::reset() {
va009039 1:5fa0120a6169 1200 R[_SP] = peek32(0x00000000);
va009039 1:5fa0120a6169 1201 R[_PC] = peek32(0x00000004);
va009039 3:fe333683e8f7 1202 jump(R[_PC]);
va009039 1:5fa0120a6169 1203 }
va009039 1:5fa0120a6169 1204
va009039 1:5fa0120a6169 1205 void BaseV6M::run(int step) {
va009039 1:5fa0120a6169 1206 while(step-- > 0) {
va009039 1:5fa0120a6169 1207 fetch();
va009039 1:5fa0120a6169 1208 execute();
va009039 1:5fa0120a6169 1209 }
va009039 1:5fa0120a6169 1210 }