diff src/gba/thumb.h @ 19:5e8e5083da94

brought in common and gba, fixed problems with outdated Makefile.am files in both of these packages
author Robert McIntyre <rlm@mit.edu>
date Sun, 04 Mar 2012 14:33:52 -0600
parents f9f4f1b99eed
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/gba/thumb.h	Sun Mar 04 14:33:52 2012 -0600
     1.3 @@ -0,0 +1,2524 @@
     1.4 +#ifdef C_CORE
     1.5 +#define NEG(i) ((i) >> 31)
     1.6 +#define POS(i) ((~(i)) >> 31)
     1.7 +#define ADDCARRY(a, b, c) \
     1.8 +    C_FLAG = ((NEG(a) & NEG(b)) | \
     1.9 +              (NEG(a) & POS(c)) | \
    1.10 +              (NEG(b) & POS(c))) ? true : false;
    1.11 +#define ADDOVERFLOW(a, b, c) \
    1.12 +    V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \
    1.13 +              (POS(a) & POS(b) & NEG(c))) ? true : false;
    1.14 +#define SUBCARRY(a, b, c) \
    1.15 +    C_FLAG = ((NEG(a) & POS(b)) | \
    1.16 +              (NEG(a) & POS(c)) | \
    1.17 +              (POS(b) & POS(c))) ? true : false;
    1.18 +#define SUBOVERFLOW(a, b, c) \
    1.19 +    V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \
    1.20 +              (POS(a) & NEG(b) & NEG(c))) ? true : false;
    1.21 +#define ADD_RD_RS_RN \
    1.22 +	{ \
    1.23 +		u32 lhs = reg[source].I; \
    1.24 +		u32 rhs = value; \
    1.25 +		u32 res = lhs + rhs; \
    1.26 +		reg[dest].I = res; \
    1.27 +		Z_FLAG		= (res == 0) ? true : false; \
    1.28 +		N_FLAG		= NEG(res) ? true : false; \
    1.29 +		ADDCARRY(lhs, rhs, res); \
    1.30 +		ADDOVERFLOW(lhs, rhs, res); \
    1.31 +	}
    1.32 +#define ADD_RD_RS_O3 \
    1.33 +	{ \
    1.34 +		u32 lhs = reg[source].I; \
    1.35 +		u32 rhs = value; \
    1.36 +		u32 res = lhs + rhs; \
    1.37 +		reg[dest].I = res; \
    1.38 +		Z_FLAG		= (res == 0) ? true : false; \
    1.39 +		N_FLAG		= NEG(res) ? true : false; \
    1.40 +		ADDCARRY(lhs, rhs, res); \
    1.41 +		ADDOVERFLOW(lhs, rhs, res); \
    1.42 +	}
    1.43 +#define ADD_RN_O8(d) \
    1.44 +	{ \
    1.45 +		u32 lhs = reg[(d)].I; \
    1.46 +		u32 rhs = (opcode & 255); \
    1.47 +		u32 res = lhs + rhs; \
    1.48 +		reg[(d)].I = res; \
    1.49 +		Z_FLAG	   = (res == 0) ? true : false; \
    1.50 +		N_FLAG	   = NEG(res) ? true : false; \
    1.51 +		ADDCARRY(lhs, rhs, res); \
    1.52 +		ADDOVERFLOW(lhs, rhs, res); \
    1.53 +	}
    1.54 +#define CMN_RD_RS \
    1.55 +	{ \
    1.56 +		u32 lhs = reg[dest].I; \
    1.57 +		u32 rhs = value; \
    1.58 +		u32 res = lhs + rhs; \
    1.59 +		Z_FLAG = (res == 0) ? true : false; \
    1.60 +		N_FLAG = NEG(res) ? true : false; \
    1.61 +		ADDCARRY(lhs, rhs, res); \
    1.62 +		ADDOVERFLOW(lhs, rhs, res); \
    1.63 +	}
    1.64 +#define ADC_RD_RS \
    1.65 +	{ \
    1.66 +		u32 lhs = reg[dest].I; \
    1.67 +		u32 rhs = value; \
    1.68 +		u32 res = lhs + rhs + (u32)C_FLAG; \
    1.69 +		reg[dest].I = res; \
    1.70 +		Z_FLAG		= (res == 0) ? true : false; \
    1.71 +		N_FLAG		= NEG(res) ? true : false; \
    1.72 +		ADDCARRY(lhs, rhs, res); \
    1.73 +		ADDOVERFLOW(lhs, rhs, res); \
    1.74 +	}
    1.75 +#define SUB_RD_RS_RN \
    1.76 +	{ \
    1.77 +		u32 lhs = reg[source].I; \
    1.78 +		u32 rhs = value; \
    1.79 +		u32 res = lhs - rhs; \
    1.80 +		reg[dest].I = res; \
    1.81 +		Z_FLAG		= (res == 0) ? true : false; \
    1.82 +		N_FLAG		= NEG(res) ? true : false; \
    1.83 +		SUBCARRY(lhs, rhs, res); \
    1.84 +		SUBOVERFLOW(lhs, rhs, res); \
    1.85 +	}
    1.86 +#define SUB_RD_RS_O3 \
    1.87 +	{ \
    1.88 +		u32 lhs = reg[source].I; \
    1.89 +		u32 rhs = value; \
    1.90 +		u32 res = lhs - rhs; \
    1.91 +		reg[dest].I = res; \
    1.92 +		Z_FLAG		= (res == 0) ? true : false; \
    1.93 +		N_FLAG		= NEG(res) ? true : false; \
    1.94 +		SUBCARRY(lhs, rhs, res); \
    1.95 +		SUBOVERFLOW(lhs, rhs, res); \
    1.96 +	}
    1.97 +#define SUB_RN_O8(d) \
    1.98 +	{ \
    1.99 +		u32 lhs = reg[(d)].I; \
   1.100 +		u32 rhs = (opcode & 255); \
   1.101 +		u32 res = lhs - rhs; \
   1.102 +		reg[(d)].I = res; \
   1.103 +		Z_FLAG	   = (res == 0) ? true : false; \
   1.104 +		N_FLAG	   = NEG(res) ? true : false; \
   1.105 +		SUBCARRY(lhs, rhs, res); \
   1.106 +		SUBOVERFLOW(lhs, rhs, res); \
   1.107 +	}
   1.108 +#define CMP_RN_O8(d) \
   1.109 +	{ \
   1.110 +		u32 lhs = reg[(d)].I; \
   1.111 +		u32 rhs = (opcode & 255); \
   1.112 +		u32 res = lhs - rhs; \
   1.113 +		Z_FLAG = (res == 0) ? true : false; \
   1.114 +		N_FLAG = NEG(res) ? true : false; \
   1.115 +		SUBCARRY(lhs, rhs, res); \
   1.116 +		SUBOVERFLOW(lhs, rhs, res); \
   1.117 +	}
   1.118 +#define SBC_RD_RS \
   1.119 +	{ \
   1.120 +		u32 lhs = reg[dest].I; \
   1.121 +		u32 rhs = value; \
   1.122 +		u32 res = lhs - rhs - !((u32)C_FLAG); \
   1.123 +		reg[dest].I = res; \
   1.124 +		Z_FLAG		= (res == 0) ? true : false; \
   1.125 +		N_FLAG		= NEG(res) ? true : false; \
   1.126 +		SUBCARRY(lhs, rhs, res); \
   1.127 +		SUBOVERFLOW(lhs, rhs, res); \
   1.128 +	}
   1.129 +#define LSL_RD_RM_I5 \
   1.130 +	{ \
   1.131 +		C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \
   1.132 +		value  = reg[source].I << shift; \
   1.133 +	}
   1.134 +#define LSL_RD_RS \
   1.135 +	{ \
   1.136 +		C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \
   1.137 +		value  = reg[dest].I << value; \
   1.138 +	}
   1.139 +#define LSR_RD_RM_I5 \
   1.140 +	{ \
   1.141 +		C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \
   1.142 +		value  = reg[source].I >> shift; \
   1.143 +	}
   1.144 +#define LSR_RD_RS \
   1.145 +	{ \
   1.146 +		C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
   1.147 +		value  = reg[dest].I >> value; \
   1.148 +	}
   1.149 +#define ASR_RD_RM_I5 \
   1.150 +	{ \
   1.151 +		C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \
   1.152 +		value  = (s32)reg[source].I >> (int)shift; \
   1.153 +	}
   1.154 +#define ASR_RD_RS \
   1.155 +	{ \
   1.156 +		C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \
   1.157 +		value  = (s32)reg[dest].I >> (int)value; \
   1.158 +	}
   1.159 +#define ROR_RD_RS \
   1.160 +	{ \
   1.161 +		C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
   1.162 +		value  = ((reg[dest].I << (32 - value)) | \
   1.163 +		          (reg[dest].I >> value)); \
   1.164 +	}
   1.165 +#define NEG_RD_RS \
   1.166 +	{ \
   1.167 +		u32 lhs = reg[source].I; \
   1.168 +		u32 rhs = 0; \
   1.169 +		u32 res = rhs - lhs; \
   1.170 +		reg[dest].I = res; \
   1.171 +		Z_FLAG		= (res == 0) ? true : false; \
   1.172 +		N_FLAG		= NEG(res) ? true : false; \
   1.173 +		SUBCARRY(rhs, lhs, res); \
   1.174 +		SUBOVERFLOW(rhs, lhs, res); \
   1.175 +	}
   1.176 +#define CMP_RD_RS \
   1.177 +	{ \
   1.178 +		u32 lhs = reg[dest].I; \
   1.179 +		u32 rhs = value; \
   1.180 +		u32 res = lhs - rhs; \
   1.181 +		Z_FLAG = (res == 0) ? true : false; \
   1.182 +		N_FLAG = NEG(res) ? true : false; \
   1.183 +		SUBCARRY(lhs, rhs, res); \
   1.184 +		SUBOVERFLOW(lhs, rhs, res); \
   1.185 +	}
   1.186 +#else
   1.187 +#ifdef __GNUC__
   1.188 +#ifdef __POWERPC__
   1.189 +			#define ADD_RD_RS_RN \
   1.190 +	{                                       \
   1.191 +		register int Flags;                 \
   1.192 +		register int Result;                \
   1.193 +		asm volatile ("addco. %0, %2, %3\n"  \
   1.194 +		              "mcrxr cr1\n"           \
   1.195 +		              "mfcr %1\n"             \
   1.196 +					  : "=r" (Result),        \
   1.197 +		              "=r" (Flags)          \
   1.198 +					  : "r" (reg[source].I),  \
   1.199 +		              "r" (value)           \
   1.200 +		              );                      \
   1.201 +		reg[dest].I = Result;               \
   1.202 +		Z_FLAG		= (Flags >> 29) & 1;         \
   1.203 +		N_FLAG		= (Flags >> 31) & 1;         \
   1.204 +		C_FLAG		= (Flags >> 25) & 1;         \
   1.205 +		V_FLAG		= (Flags >> 26) & 1;         \
   1.206 +	}
   1.207 +			#define ADD_RD_RS_O3 ADD_RD_RS_RN
   1.208 +			#define ADD_RN_O8(d) \
   1.209 +	{ \
   1.210 +		register int Flags;                 \
   1.211 +		register int Result;                \
   1.212 +		asm volatile ("addco. %0, %2, %3\n"  \
   1.213 +		              "mcrxr cr1\n"           \
   1.214 +		              "mfcr %1\n"             \
   1.215 +					  : "=r" (Result),        \
   1.216 +		              "=r" (Flags)          \
   1.217 +					  : "r" (reg[(d)].I),     \
   1.218 +		              "r" (opcode & 255)    \
   1.219 +		              );                      \
   1.220 +		reg[(d)].I = Result;                \
   1.221 +		Z_FLAG	   = (Flags >> 29) & 1;         \
   1.222 +		N_FLAG	   = (Flags >> 31) & 1;         \
   1.223 +		C_FLAG	   = (Flags >> 25) & 1;         \
   1.224 +		V_FLAG	   = (Flags >> 26) & 1;         \
   1.225 +	}
   1.226 +			#define CMN_RD_RS \
   1.227 +	{ \
   1.228 +		register int Flags;                 \
   1.229 +		register int Result;                \
   1.230 +		asm volatile ("addco. %0, %2, %3\n"  \
   1.231 +		              "mcrxr cr1\n"           \
   1.232 +		              "mfcr %1\n"             \
   1.233 +					  : "=r" (Result),        \
   1.234 +		              "=r" (Flags)          \
   1.235 +					  : "r" (reg[dest].I),    \
   1.236 +		              "r" (value)           \
   1.237 +		              );                      \
   1.238 +		Z_FLAG = (Flags >> 29) & 1;         \
   1.239 +		N_FLAG = (Flags >> 31) & 1;         \
   1.240 +		C_FLAG = (Flags >> 25) & 1;         \
   1.241 +		V_FLAG = (Flags >> 26) & 1;         \
   1.242 +	}
   1.243 +			#define ADC_RD_RS \
   1.244 +	{ \
   1.245 +		register int Flags;                 \
   1.246 +		register int Result;                \
   1.247 +		asm volatile ("mtspr xer, %4\n"      \
   1.248 +		              "addeo. %0, %2, %3\n"  \
   1.249 +		              "mcrxr cr1\n"          \
   1.250 +		              "mfcr	%1\n"            \
   1.251 +					  : "=r" (Result),       \
   1.252 +		              "=r" (Flags)         \
   1.253 +					  : "r" (reg[dest].I),   \
   1.254 +		              "r" (value),         \
   1.255 +		              "r" (C_FLAG << 29)   \
   1.256 +		              );                     \
   1.257 +		reg[dest].I = Result;               \
   1.258 +		Z_FLAG		= (Flags >> 29) & 1;         \
   1.259 +		N_FLAG		= (Flags >> 31) & 1;         \
   1.260 +		C_FLAG		= (Flags >> 25) & 1;         \
   1.261 +		V_FLAG		= (Flags >> 26) & 1;         \
   1.262 +	}
   1.263 +			#define SUB_RD_RS_RN \
   1.264 +	{ \
   1.265 +		register int Flags;                 \
   1.266 +		register int Result;                \
   1.267 +		asm volatile ("subco. %0, %2, %3\n"  \
   1.268 +		              "mcrxr cr1\n"           \
   1.269 +		              "mfcr %1\n"             \
   1.270 +					  : "=r" (Result),        \
   1.271 +		              "=r" (Flags)          \
   1.272 +					  : "r" (reg[source].I),  \
   1.273 +		              "r" (value)           \
   1.274 +		              );                      \
   1.275 +		reg[dest].I = Result;               \
   1.276 +		Z_FLAG		= (Flags >> 29) & 1;         \
   1.277 +		N_FLAG		= (Flags >> 31) & 1;         \
   1.278 +		C_FLAG		= (Flags >> 25) & 1;         \
   1.279 +		V_FLAG		= (Flags >> 26) & 1;         \
   1.280 +	}
   1.281 +			#define SUB_RD_RS_O3 SUB_RD_RS_RN
   1.282 +			#define SUB_RN_O8(d) \
   1.283 +	{ \
   1.284 +		register int Flags;                 \
   1.285 +		register int Result;                \
   1.286 +		asm volatile ("subco. %0, %2, %3\n"  \
   1.287 +		              "mcrxr cr1\n"           \
   1.288 +		              "mfcr %1\n"             \
   1.289 +					  : "=r" (Result),        \
   1.290 +		              "=r" (Flags)          \
   1.291 +					  : "r" (reg[(d)].I),     \
   1.292 +		              "r" (opcode & 255)    \
   1.293 +		              );                      \
   1.294 +		reg[(d)].I = Result;                \
   1.295 +		Z_FLAG	   = (Flags >> 29) & 1;         \
   1.296 +		N_FLAG	   = (Flags >> 31) & 1;         \
   1.297 +		C_FLAG	   = (Flags >> 25) & 1;         \
   1.298 +		V_FLAG	   = (Flags >> 26) & 1;         \
   1.299 +	}
   1.300 +			#define CMP_RN_O8(d) \
   1.301 +	{ \
   1.302 +		register int Flags;                 \
   1.303 +		register int Result;                \
   1.304 +		asm volatile ("subco. %0, %2, %3\n"  \
   1.305 +		              "mcrxr cr1\n"           \
   1.306 +		              "mfcr %1\n"             \
   1.307 +					  : "=r" (Result),        \
   1.308 +		              "=r" (Flags)          \
   1.309 +					  : "r" (reg[(d)].I),     \
   1.310 +		              "r" (opcode & 255)    \
   1.311 +		              );                      \
   1.312 +		Z_FLAG = (Flags >> 29) & 1;         \
   1.313 +		N_FLAG = (Flags >> 31) & 1;         \
   1.314 +		C_FLAG = (Flags >> 25) & 1;         \
   1.315 +		V_FLAG = (Flags >> 26) & 1;         \
   1.316 +	}
   1.317 +			#define SBC_RD_RS \
   1.318 +	{ \
   1.319 +		register int Flags;                 \
   1.320 +		register int Result;                \
   1.321 +		asm volatile ("mtspr xer, %4\n"      \
   1.322 +		              "subfeo. %0, %3, %2\n" \
   1.323 +		              "mcrxr cr1\n"          \
   1.324 +		              "mfcr	%1\n"            \
   1.325 +					  : "=r" (Result),       \
   1.326 +		              "=r" (Flags)         \
   1.327 +					  : "r" (reg[dest].I),   \
   1.328 +		              "r" (value),         \
   1.329 +		              "r" (C_FLAG << 29)   \
   1.330 +		              );                     \
   1.331 +		reg[dest].I = Result;               \
   1.332 +		Z_FLAG		= (Flags >> 29) & 1;         \
   1.333 +		N_FLAG		= (Flags >> 31) & 1;         \
   1.334 +		C_FLAG		= (Flags >> 25) & 1;         \
   1.335 +		V_FLAG		= (Flags >> 26) & 1;         \
   1.336 +	}
   1.337 +			#define LSL_RD_RM_I5 \
   1.338 +	{ \
   1.339 +		C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \
   1.340 +		value  = reg[source].I << shift; \
   1.341 +	}
   1.342 +			#define LSL_RD_RS \
   1.343 +	{ \
   1.344 +		C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \
   1.345 +		value  = reg[dest].I << value; \
   1.346 +	}
   1.347 +			#define LSR_RD_RM_I5 \
   1.348 +	{ \
   1.349 +		C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \
   1.350 +		value  = reg[source].I >> shift; \
   1.351 +	}
   1.352 +			#define LSR_RD_RS \
   1.353 +	{ \
   1.354 +		C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
   1.355 +		value  = reg[dest].I >> value; \
   1.356 +	}
   1.357 +			#define ASR_RD_RM_I5 \
   1.358 +	{ \
   1.359 +		C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \
   1.360 +		value  = (s32)reg[source].I >> (int)shift; \
   1.361 +	}
   1.362 +			#define ASR_RD_RS \
   1.363 +	{ \
   1.364 +		C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \
   1.365 +		value  = (s32)reg[dest].I >> (int)value; \
   1.366 +	}
   1.367 +			#define ROR_RD_RS \
   1.368 +	{ \
   1.369 +		C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \
   1.370 +		value  = ((reg[dest].I << (32 - value)) | \
   1.371 +		          (reg[dest].I >> value)); \
   1.372 +	}
   1.373 +			#define NEG_RD_RS \
   1.374 +	{ \
   1.375 +		register int Flags;                 \
   1.376 +		register int Result;                \
   1.377 +		asm volatile ("subfco. %0, %2, %3\n" \
   1.378 +		              "mcrxr cr1\n"           \
   1.379 +		              "mfcr %1\n"             \
   1.380 +					  : "=r" (Result),        \
   1.381 +		              "=r" (Flags)          \
   1.382 +					  : "r" (reg[source].I),  \
   1.383 +		              "r" (0)               \
   1.384 +		              );                      \
   1.385 +		reg[dest].I = Result;               \
   1.386 +		Z_FLAG		= (Flags >> 29) & 1;         \
   1.387 +		N_FLAG		= (Flags >> 31) & 1;         \
   1.388 +		C_FLAG		= (Flags >> 25) & 1;         \
   1.389 +		V_FLAG		= (Flags >> 26) & 1;         \
   1.390 +	}
   1.391 +			#define CMP_RD_RS \
   1.392 +	{ \
   1.393 +		register int Flags;                 \
   1.394 +		register int Result;                \
   1.395 +		asm volatile ("subco. %0, %2, %3\n"  \
   1.396 +		              "mcrxr cr1\n"           \
   1.397 +		              "mfcr %1\n"             \
   1.398 +					  : "=r" (Result),        \
   1.399 +		              "=r" (Flags)          \
   1.400 +					  : "r" (reg[dest].I),    \
   1.401 +		              "r" (value)           \
   1.402 +		              );                      \
   1.403 +		Z_FLAG = (Flags >> 29) & 1;         \
   1.404 +		N_FLAG = (Flags >> 31) & 1;         \
   1.405 +		C_FLAG = (Flags >> 25) & 1;         \
   1.406 +		V_FLAG = (Flags >> 26) & 1;         \
   1.407 +	}
   1.408 +#else
   1.409 +#define ADD_RD_RS_RN \
   1.410 +    asm ("add %1, %%ebx;" \
   1.411 +         "setsb N_FLAG;" \
   1.412 +         "setzb Z_FLAG;" \
   1.413 +         "setcb C_FLAG;" \
   1.414 +         "setob V_FLAG;" \
   1.415 +		 : "=b" (reg[dest].I) \
   1.416 +		 : "r" (value), "b" (reg[source].I));
   1.417 +#define ADD_RD_RS_O3 \
   1.418 +    asm ("add %1, %%ebx;" \
   1.419 +         "setsb N_FLAG;" \
   1.420 +         "setzb Z_FLAG;" \
   1.421 +         "setcb C_FLAG;" \
   1.422 +         "setob V_FLAG;" \
   1.423 +		 : "=b" (reg[dest].I) \
   1.424 +		 : "r" (value), "b" (reg[source].I));
   1.425 +#define ADD_RN_O8(d) \
   1.426 +    asm ("add %1, %%ebx;" \
   1.427 +         "setsb N_FLAG;" \
   1.428 +         "setzb Z_FLAG;" \
   1.429 +         "setcb C_FLAG;" \
   1.430 +         "setob V_FLAG;" \
   1.431 +		 : "=b" (reg[(d)].I) \
   1.432 +		 : "r" (opcode & 255), "b" (reg[(d)].I));
   1.433 +#define CMN_RD_RS \
   1.434 +    asm ("add %0, %1;" \
   1.435 +         "setsb N_FLAG;" \
   1.436 +         "setzb Z_FLAG;" \
   1.437 +         "setcb C_FLAG;" \
   1.438 +         "setob V_FLAG;" \
   1.439 +		 : \
   1.440 +		 : "r" (value), "r" (reg[dest].I) : "1");
   1.441 +#define ADC_RD_RS \
   1.442 +    asm ("bt $0, C_FLAG;" \
   1.443 +         "adc %1, %%ebx;" \
   1.444 +         "setsb N_FLAG;" \
   1.445 +         "setzb Z_FLAG;" \
   1.446 +         "setcb C_FLAG;" \
   1.447 +         "setob V_FLAG;" \
   1.448 +		 : "=b" (reg[dest].I) \
   1.449 +		 : "r" (value), "b" (reg[dest].I));
   1.450 +#define SUB_RD_RS_RN \
   1.451 +    asm ("sub %1, %%ebx;" \
   1.452 +         "setsb N_FLAG;" \
   1.453 +         "setzb Z_FLAG;" \
   1.454 +         "setncb C_FLAG;" \
   1.455 +         "setob V_FLAG;" \
   1.456 +		 : "=b" (reg[dest].I) \
   1.457 +		 : "r" (value), "b" (reg[source].I));
   1.458 +#define SUB_RD_RS_O3 \
   1.459 +    asm ("sub %1, %%ebx;" \
   1.460 +         "setsb N_FLAG;" \
   1.461 +         "setzb Z_FLAG;" \
   1.462 +         "setncb C_FLAG;" \
   1.463 +         "setob V_FLAG;" \
   1.464 +		 : "=b" (reg[dest].I) \
   1.465 +		 : "r" (value), "b" (reg[source].I));
   1.466 +#define SUB_RN_O8(d) \
   1.467 +    asm ("sub %1, %%ebx;" \
   1.468 +         "setsb N_FLAG;" \
   1.469 +         "setzb Z_FLAG;" \
   1.470 +         "setncb C_FLAG;" \
   1.471 +         "setob V_FLAG;" \
   1.472 +		 : "=b" (reg[(d)].I) \
   1.473 +		 : "r" (opcode & 255), "b" (reg[(d)].I));
   1.474 +#define CMP_RN_O8(d) \
   1.475 +    asm ("sub %0, %1;" \
   1.476 +         "setsb N_FLAG;" \
   1.477 +         "setzb Z_FLAG;" \
   1.478 +         "setncb C_FLAG;" \
   1.479 +         "setob V_FLAG;" \
   1.480 +		 : \
   1.481 +		 : "r" (opcode & 255), "r" (reg[(d)].I) : "1");
   1.482 +#define SBC_RD_RS \
   1.483 +    asm volatile ("bt $0, C_FLAG;" \
   1.484 +                  "cmc;" \
   1.485 +                  "sbb %1, %%ebx;" \
   1.486 +                  "setsb N_FLAG;" \
   1.487 +                  "setzb Z_FLAG;" \
   1.488 +                  "setncb C_FLAG;" \
   1.489 +                  "setob V_FLAG;" \
   1.490 +				  : "=b" (reg[dest].I) \
   1.491 +				  : "r" (value), "b" (reg[dest].I) : "cc", "memory");
   1.492 +#define LSL_RD_RM_I5 \
   1.493 +    asm ("shl %%cl, %%eax;" \
   1.494 +         "setcb C_FLAG;" \
   1.495 +		 : "=a" (value) \
   1.496 +		 : "a" (reg[source].I), "c" (shift));
   1.497 +#define LSL_RD_RS \
   1.498 +    asm ("shl %%cl, %%eax;" \
   1.499 +         "setcb C_FLAG;" \
   1.500 +		 : "=a" (value) \
   1.501 +		 : "a" (reg[dest].I), "c" (value));
   1.502 +#define LSR_RD_RM_I5 \
   1.503 +    asm ("shr %%cl, %%eax;" \
   1.504 +         "setcb C_FLAG;" \
   1.505 +		 : "=a" (value) \
   1.506 +		 : "a" (reg[source].I), "c" (shift));
   1.507 +#define LSR_RD_RS \
   1.508 +    asm ("shr %%cl, %%eax;" \
   1.509 +         "setcb C_FLAG;" \
   1.510 +		 : "=a" (value) \
   1.511 +		 : "a" (reg[dest].I), "c" (value));
   1.512 +#define ASR_RD_RM_I5 \
   1.513 +    asm ("sar %%cl, %%eax;" \
   1.514 +         "setcb C_FLAG;" \
   1.515 +		 : "=a" (value) \
   1.516 +		 : "a" (reg[source].I), "c" (shift));
   1.517 +#define ASR_RD_RS \
   1.518 +    asm ("sar %%cl, %%eax;" \
   1.519 +         "setcb C_FLAG;" \
   1.520 +		 : "=a" (value) \
   1.521 +		 : "a" (reg[dest].I), "c" (value));
   1.522 +#define ROR_RD_RS \
   1.523 +    asm ("ror %%cl, %%eax;" \
   1.524 +         "setcb C_FLAG;" \
   1.525 +		 : "=a" (value) \
   1.526 +		 : "a" (reg[dest].I), "c" (value));
   1.527 +#define NEG_RD_RS \
   1.528 +    asm ("neg %%ebx;" \
   1.529 +         "setsb N_FLAG;" \
   1.530 +         "setzb Z_FLAG;" \
   1.531 +         "setncb C_FLAG;" \
   1.532 +         "setob V_FLAG;" \
   1.533 +		 : "=b" (reg[dest].I) \
   1.534 +		 : "b" (reg[source].I));
   1.535 +#define CMP_RD_RS \
   1.536 +    asm ("sub %0, %1;" \
   1.537 +         "setsb N_FLAG;" \
   1.538 +         "setzb Z_FLAG;" \
   1.539 +         "setncb C_FLAG;" \
   1.540 +         "setob V_FLAG;" \
   1.541 +		 : \
   1.542 +		 : "r" (value), "r" (reg[dest].I) : "1");
   1.543 +#endif
   1.544 +#else
   1.545 +#define ADD_RD_RS_RN \
   1.546 +	{ \
   1.547 +		__asm mov eax, source \
   1.548 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.549 +		__asm add ebx, value \
   1.550 +		__asm mov eax, dest \
   1.551 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.552 +		__asm sets byte ptr N_FLAG \
   1.553 +		__asm setz byte ptr Z_FLAG \
   1.554 +		__asm setc byte ptr C_FLAG \
   1.555 +		__asm seto byte ptr V_FLAG \
   1.556 +	}
   1.557 +#define ADD_RD_RS_O3 \
   1.558 +	{ \
   1.559 +		__asm mov eax, source \
   1.560 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.561 +		__asm add ebx, value \
   1.562 +		__asm mov eax, dest \
   1.563 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.564 +		__asm sets byte ptr N_FLAG \
   1.565 +		__asm setz byte ptr Z_FLAG \
   1.566 +		__asm setc byte ptr C_FLAG \
   1.567 +		__asm seto byte ptr V_FLAG \
   1.568 +	}
   1.569 +#define ADD_RN_O8(d) \
   1.570 +	{ \
   1.571 +		__asm mov ebx, opcode \
   1.572 +		          __asm and ebx, 255 \
   1.573 +		__asm add dword ptr [OFFSET reg + 4 * (d)], ebx \
   1.574 +		__asm sets byte ptr N_FLAG \
   1.575 +		__asm setz byte ptr Z_FLAG \
   1.576 +		__asm setc byte ptr C_FLAG \
   1.577 +		__asm seto byte ptr V_FLAG \
   1.578 +	}
   1.579 +#define CMN_RD_RS \
   1.580 +	{ \
   1.581 +		__asm mov eax, dest \
   1.582 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.583 +		__asm add ebx, value \
   1.584 +		__asm sets byte ptr N_FLAG \
   1.585 +		__asm setz byte ptr Z_FLAG \
   1.586 +		__asm setc byte ptr C_FLAG \
   1.587 +		__asm seto byte ptr V_FLAG \
   1.588 +	}
   1.589 +#define ADC_RD_RS \
   1.590 +	{ \
   1.591 +		__asm mov ebx, dest \
   1.592 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
   1.593 +		__asm bt word ptr C_FLAG, 0 \
   1.594 +		__asm adc ebx, value \
   1.595 +		__asm mov eax, dest \
   1.596 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.597 +		__asm sets byte ptr N_FLAG \
   1.598 +		__asm setz byte ptr Z_FLAG \
   1.599 +		__asm setc byte ptr C_FLAG \
   1.600 +		__asm seto byte ptr V_FLAG \
   1.601 +	}
   1.602 +#define SUB_RD_RS_RN \
   1.603 +	{ \
   1.604 +		__asm mov eax, source \
   1.605 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.606 +		__asm sub ebx, value \
   1.607 +		__asm mov eax, dest \
   1.608 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.609 +		__asm sets byte ptr N_FLAG \
   1.610 +		__asm setz byte ptr Z_FLAG \
   1.611 +		__asm setnc byte ptr C_FLAG \
   1.612 +		__asm seto byte ptr V_FLAG \
   1.613 +	}
   1.614 +#define SUB_RD_RS_O3 \
   1.615 +	{ \
   1.616 +		__asm mov eax, source \
   1.617 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.618 +		__asm sub ebx, value \
   1.619 +		__asm mov eax, dest \
   1.620 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.621 +		__asm sets byte ptr N_FLAG \
   1.622 +		__asm setz byte ptr Z_FLAG \
   1.623 +		__asm setnc byte ptr C_FLAG \
   1.624 +		__asm seto byte ptr V_FLAG \
   1.625 +	}
   1.626 +#define SUB_RN_O8(d) \
   1.627 +	{ \
   1.628 +		__asm mov ebx, opcode \
   1.629 +		          __asm and ebx, 255 \
   1.630 +		__asm sub dword ptr [OFFSET reg + 4 * (d)], ebx \
   1.631 +		__asm sets byte ptr N_FLAG \
   1.632 +		__asm setz byte ptr Z_FLAG \
   1.633 +		__asm setnc byte ptr C_FLAG \
   1.634 +		__asm seto byte ptr V_FLAG \
   1.635 +	}
   1.636 +#define CMP_RN_O8(d) \
   1.637 +	{ \
   1.638 +		__asm mov eax, dword ptr [OFFSET reg + 4 * (d)] \
   1.639 +		__asm mov ebx, opcode \
   1.640 +		          __asm and ebx, 255 \
   1.641 +		__asm sub eax, ebx \
   1.642 +		__asm sets byte ptr N_FLAG \
   1.643 +		__asm setz byte ptr Z_FLAG \
   1.644 +		__asm setnc byte ptr C_FLAG \
   1.645 +		__asm seto byte ptr V_FLAG \
   1.646 +	}
   1.647 +#define SBC_RD_RS \
   1.648 +	{ \
   1.649 +		__asm mov ebx, dest \
   1.650 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
   1.651 +		__asm mov eax, value \
   1.652 +		__asm bt word ptr C_FLAG, 0 \
   1.653 +		__asm cmc \
   1.654 +		__asm sbb ebx, eax \
   1.655 +		__asm mov eax, dest \
   1.656 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.657 +		__asm sets byte ptr N_FLAG \
   1.658 +		__asm setz byte ptr Z_FLAG \
   1.659 +		__asm setnc byte ptr C_FLAG \
   1.660 +		__asm seto byte ptr V_FLAG \
   1.661 +	}
   1.662 +#define LSL_RD_RM_I5 \
   1.663 +	{ \
   1.664 +		__asm mov eax, source \
   1.665 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.666 +		__asm mov cl, byte ptr shift \
   1.667 +		__asm shl eax, cl \
   1.668 +		__asm mov value, eax \
   1.669 +		__asm setc byte ptr C_FLAG \
   1.670 +	}
   1.671 +#define LSL_RD_RS \
   1.672 +	{ \
   1.673 +		__asm mov eax, dest \
   1.674 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.675 +		__asm mov cl, byte ptr value \
   1.676 +		__asm shl eax, cl \
   1.677 +		__asm mov value, eax \
   1.678 +		__asm setc byte ptr C_FLAG \
   1.679 +	}
   1.680 +#define LSR_RD_RM_I5 \
   1.681 +	{ \
   1.682 +		__asm mov eax, source \
   1.683 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.684 +		__asm mov cl, byte ptr shift \
   1.685 +		__asm shr eax, cl \
   1.686 +		__asm mov value, eax \
   1.687 +		__asm setc byte ptr C_FLAG \
   1.688 +	}
   1.689 +#define LSR_RD_RS \
   1.690 +	{ \
   1.691 +		__asm mov eax, dest \
   1.692 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.693 +		__asm mov cl, byte ptr value \
   1.694 +		__asm shr eax, cl \
   1.695 +		__asm mov value, eax \
   1.696 +		__asm setc byte ptr C_FLAG \
   1.697 +	}
   1.698 +#define ASR_RD_RM_I5 \
   1.699 +	{ \
   1.700 +		__asm mov eax, source \
   1.701 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.702 +		__asm mov cl, byte ptr shift \
   1.703 +		__asm sar eax, cl \
   1.704 +		__asm mov value, eax \
   1.705 +		__asm setc byte ptr C_FLAG \
   1.706 +	}
   1.707 +#define ASR_RD_RS \
   1.708 +	{ \
   1.709 +		__asm mov eax, dest \
   1.710 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.711 +		__asm mov cl, byte ptr value \
   1.712 +		__asm sar eax, cl \
   1.713 +		__asm mov value, eax \
   1.714 +		__asm setc byte ptr C_FLAG \
   1.715 +	}
   1.716 +#define ROR_RD_RS \
   1.717 +	{ \
   1.718 +		__asm mov eax, dest \
   1.719 +		__asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
   1.720 +		__asm mov cl, byte ptr value \
   1.721 +		__asm ror eax, cl \
   1.722 +		__asm mov value, eax \
   1.723 +		__asm setc byte ptr C_FLAG \
   1.724 +	}
   1.725 +#define NEG_RD_RS \
   1.726 +	{ \
   1.727 +		__asm mov ebx, source \
   1.728 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
   1.729 +		__asm neg ebx \
   1.730 +		__asm mov eax, dest \
   1.731 +		__asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
   1.732 +		__asm sets byte ptr N_FLAG \
   1.733 +		__asm setz byte ptr Z_FLAG \
   1.734 +		__asm setnc byte ptr C_FLAG \
   1.735 +		__asm seto byte ptr V_FLAG \
   1.736 +	}
   1.737 +#define CMP_RD_RS \
   1.738 +	{ \
   1.739 +		__asm mov eax, dest \
   1.740 +		__asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
   1.741 +		__asm sub ebx, value \
   1.742 +		__asm sets byte ptr N_FLAG \
   1.743 +		__asm setz byte ptr Z_FLAG \
   1.744 +		__asm setnc byte ptr C_FLAG \
   1.745 +		__asm seto byte ptr V_FLAG \
   1.746 +	}
   1.747 +#endif
   1.748 +#endif
   1.749 +
   1.750 +u32 opcode = CPUReadHalfWordQuick(armNextPC);
   1.751 +clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15];
   1.752 +#ifndef FINAL_VERSION
   1.753 +if (armNextPC == stop)
   1.754 +{
   1.755 +	armNextPC = armNextPC++;
   1.756 +}
   1.757 +#endif
   1.758 +
   1.759 +armNextPC  = reg[15].I;
   1.760 +reg[15].I += 2;
   1.761 +
   1.762 +switch (opcode >> 8)
   1.763 +{
   1.764 +case 0x00:
   1.765 +case 0x01:
   1.766 +case 0x02:
   1.767 +case 0x03:
   1.768 +case 0x04:
   1.769 +case 0x05:
   1.770 +case 0x06:
   1.771 +case 0x07:
   1.772 +{
   1.773 +	// LSL Rd, Rm, #Imm 5
   1.774 +	int dest   = opcode & 0x07;
   1.775 +	int source = (opcode >> 3) & 0x07;
   1.776 +	int shift  = (opcode >> 6) & 0x1f;
   1.777 +	u32 value;
   1.778 +
   1.779 +	if (shift)
   1.780 +	{
   1.781 +		LSL_RD_RM_I5;
   1.782 +	}
   1.783 +	else
   1.784 +	{
   1.785 +		value = reg[source].I;
   1.786 +	}
   1.787 +	reg[dest].I = value;
   1.788 +	// C_FLAG set above
   1.789 +	N_FLAG = (value & 0x80000000 ? true : false);
   1.790 +	Z_FLAG = (value ? false : true);
   1.791 +}
   1.792 +break;
   1.793 +case 0x08:
   1.794 +case 0x09:
   1.795 +case 0x0a:
   1.796 +case 0x0b:
   1.797 +case 0x0c:
   1.798 +case 0x0d:
   1.799 +case 0x0e:
   1.800 +case 0x0f:
   1.801 +{
   1.802 +	// LSR Rd, Rm, #Imm 5
   1.803 +	int dest   = opcode & 0x07;
   1.804 +	int source = (opcode >> 3) & 0x07;
   1.805 +	int shift  = (opcode >> 6) & 0x1f;
   1.806 +	u32 value;
   1.807 +
   1.808 +	if (shift)
   1.809 +	{
   1.810 +		LSR_RD_RM_I5;
   1.811 +	}
   1.812 +	else
   1.813 +	{
   1.814 +		C_FLAG = reg[source].I & 0x80000000 ? true : false;
   1.815 +		value  = 0;
   1.816 +	}
   1.817 +	reg[dest].I = value;
   1.818 +	// C_FLAG set above
   1.819 +	N_FLAG = (value & 0x80000000 ? true : false);
   1.820 +	Z_FLAG = (value ? false : true);
   1.821 +}
   1.822 +break;
   1.823 +case 0x10:
   1.824 +case 0x11:
   1.825 +case 0x12:
   1.826 +case 0x13:
   1.827 +case 0x14:
   1.828 +case 0x15:
   1.829 +case 0x16:
   1.830 +case 0x17:
   1.831 +{
   1.832 +	// ASR Rd, Rm, #Imm 5
   1.833 +	int dest   = opcode & 0x07;
   1.834 +	int source = (opcode >> 3) & 0x07;
   1.835 +	int shift  = (opcode >> 6) & 0x1f;
   1.836 +	u32 value;
   1.837 +
   1.838 +	if (shift)
   1.839 +	{
   1.840 +		ASR_RD_RM_I5;
   1.841 +	}
   1.842 +	else
   1.843 +	{
   1.844 +		if (reg[source].I & 0x80000000)
   1.845 +		{
   1.846 +			value  = 0xFFFFFFFF;
   1.847 +			C_FLAG = true;
   1.848 +		}
   1.849 +		else
   1.850 +		{
   1.851 +			value  = 0;
   1.852 +			C_FLAG = false;
   1.853 +		}
   1.854 +	}
   1.855 +	reg[dest].I = value;
   1.856 +	// C_FLAG set above
   1.857 +	N_FLAG = (value & 0x80000000 ? true : false);
   1.858 +	Z_FLAG = (value ? false : true);
   1.859 +}
   1.860 +break;
   1.861 +case 0x18:
   1.862 +case 0x19:
   1.863 +{
   1.864 +	// ADD Rd, Rs, Rn
   1.865 +	int dest   = opcode & 0x07;
   1.866 +	int source = (opcode >> 3) & 0x07;
   1.867 +	u32 value  = reg[(opcode >> 6) & 0x07].I;
   1.868 +	ADD_RD_RS_RN;
   1.869 +}
   1.870 +break;
   1.871 +case 0x1a:
   1.872 +case 0x1b:
   1.873 +{
   1.874 +	// SUB Rd, Rs, Rn
   1.875 +	int dest   = opcode & 0x07;
   1.876 +	int source = (opcode >> 3) & 0x07;
   1.877 +	u32 value  = reg[(opcode >> 6) & 0x07].I;
   1.878 +	SUB_RD_RS_RN;
   1.879 +}
   1.880 +break;
   1.881 +case 0x1c:
   1.882 +case 0x1d:
   1.883 +{
   1.884 +	// ADD Rd, Rs, #Offset3
   1.885 +	int dest   = opcode & 0x07;
   1.886 +	int source = (opcode >> 3) & 0x07;
   1.887 +	u32 value  = (opcode >> 6) & 7;
   1.888 +	ADD_RD_RS_O3;
   1.889 +}
   1.890 +break;
   1.891 +case 0x1e:
   1.892 +case 0x1f:
   1.893 +{
   1.894 +	// SUB Rd, Rs, #Offset3
   1.895 +	int dest   = opcode & 0x07;
   1.896 +	int source = (opcode >> 3) & 0x07;
   1.897 +	u32 value  = (opcode >> 6) & 7;
   1.898 +	SUB_RD_RS_O3;
   1.899 +}
   1.900 +break;
   1.901 +case 0x20:
   1.902 +	// MOV R0, #Offset8
   1.903 +	reg[0].I = opcode & 255;
   1.904 +	N_FLAG	 = false;
   1.905 +	Z_FLAG	 = (reg[0].I ? false : true);
   1.906 +	break;
   1.907 +case 0x21:
   1.908 +	// MOV R1, #Offset8
   1.909 +	reg[1].I = opcode & 255;
   1.910 +	N_FLAG	 = false;
   1.911 +	Z_FLAG	 = (reg[1].I ? false : true);
   1.912 +	break;
   1.913 +case 0x22:
   1.914 +	// MOV R2, #Offset8
   1.915 +	reg[2].I = opcode & 255;
   1.916 +	N_FLAG	 = false;
   1.917 +	Z_FLAG	 = (reg[2].I ? false : true);
   1.918 +	break;
   1.919 +case 0x23:
   1.920 +	// MOV R3, #Offset8
   1.921 +	reg[3].I = opcode & 255;
   1.922 +	N_FLAG	 = false;
   1.923 +	Z_FLAG	 = (reg[3].I ? false : true);
   1.924 +	break;
   1.925 +case 0x24:
   1.926 +	// MOV R4, #Offset8
   1.927 +	reg[4].I = opcode & 255;
   1.928 +	N_FLAG	 = false;
   1.929 +	Z_FLAG	 = (reg[4].I ? false : true);
   1.930 +	break;
   1.931 +case 0x25:
   1.932 +	// MOV R5, #Offset8
   1.933 +	reg[5].I = opcode & 255;
   1.934 +	N_FLAG	 = false;
   1.935 +	Z_FLAG	 = (reg[5].I ? false : true);
   1.936 +	break;
   1.937 +case 0x26:
   1.938 +	// MOV R6, #Offset8
   1.939 +	reg[6].I = opcode & 255;
   1.940 +	N_FLAG	 = false;
   1.941 +	Z_FLAG	 = (reg[6].I ? false : true);
   1.942 +	break;
   1.943 +case 0x27:
   1.944 +	// MOV R7, #Offset8
   1.945 +	reg[7].I = opcode & 255;
   1.946 +	N_FLAG	 = false;
   1.947 +	Z_FLAG	 = (reg[7].I ? false : true);
   1.948 +	break;
   1.949 +case 0x28:
   1.950 +	// CMP R0, #Offset8
   1.951 +	CMP_RN_O8(0);
   1.952 +	break;
   1.953 +case 0x29:
   1.954 +	// CMP R1, #Offset8
   1.955 +	CMP_RN_O8(1);
   1.956 +	break;
   1.957 +case 0x2a:
   1.958 +	// CMP R2, #Offset8
   1.959 +	CMP_RN_O8(2);
   1.960 +	break;
   1.961 +case 0x2b:
   1.962 +	// CMP R3, #Offset8
   1.963 +	CMP_RN_O8(3);
   1.964 +	break;
   1.965 +case 0x2c:
   1.966 +	// CMP R4, #Offset8
   1.967 +	CMP_RN_O8(4);
   1.968 +	break;
   1.969 +case 0x2d:
   1.970 +	// CMP R5, #Offset8
   1.971 +	CMP_RN_O8(5);
   1.972 +	break;
   1.973 +case 0x2e:
   1.974 +	// CMP R6, #Offset8
   1.975 +	CMP_RN_O8(6);
   1.976 +	break;
   1.977 +case 0x2f:
   1.978 +	// CMP R7, #Offset8
   1.979 +	CMP_RN_O8(7);
   1.980 +	break;
   1.981 +case 0x30:
   1.982 +	// ADD R0,#Offset8
   1.983 +	ADD_RN_O8(0);
   1.984 +	break;
   1.985 +case 0x31:
   1.986 +	// ADD R1,#Offset8
   1.987 +	ADD_RN_O8(1);
   1.988 +	break;
   1.989 +case 0x32:
   1.990 +	// ADD R2,#Offset8
   1.991 +	ADD_RN_O8(2);
   1.992 +	break;
   1.993 +case 0x33:
   1.994 +	// ADD R3,#Offset8
   1.995 +	ADD_RN_O8(3);
   1.996 +	break;
   1.997 +case 0x34:
   1.998 +	// ADD R4,#Offset8
   1.999 +	ADD_RN_O8(4);
  1.1000 +	break;
  1.1001 +case 0x35:
  1.1002 +	// ADD R5,#Offset8
  1.1003 +	ADD_RN_O8(5);
  1.1004 +	break;
  1.1005 +case 0x36:
  1.1006 +	// ADD R6,#Offset8
  1.1007 +	ADD_RN_O8(6);
  1.1008 +	break;
  1.1009 +case 0x37:
  1.1010 +	// ADD R7,#Offset8
  1.1011 +	ADD_RN_O8(7);
  1.1012 +	break;
  1.1013 +case 0x38:
  1.1014 +	// SUB R0,#Offset8
  1.1015 +	SUB_RN_O8(0);
  1.1016 +	break;
  1.1017 +case 0x39:
  1.1018 +	// SUB R1,#Offset8
  1.1019 +	SUB_RN_O8(1);
  1.1020 +	break;
  1.1021 +case 0x3a:
  1.1022 +	// SUB R2,#Offset8
  1.1023 +	SUB_RN_O8(2);
  1.1024 +	break;
  1.1025 +case 0x3b:
  1.1026 +	// SUB R3,#Offset8
  1.1027 +	SUB_RN_O8(3);
  1.1028 +	break;
  1.1029 +case 0x3c:
  1.1030 +	// SUB R4,#Offset8
  1.1031 +	SUB_RN_O8(4);
  1.1032 +	break;
  1.1033 +case 0x3d:
  1.1034 +	// SUB R5,#Offset8
  1.1035 +	SUB_RN_O8(5);
  1.1036 +	break;
  1.1037 +case 0x3e:
  1.1038 +	// SUB R6,#Offset8
  1.1039 +	SUB_RN_O8(6);
  1.1040 +	break;
  1.1041 +case 0x3f:
  1.1042 +	// SUB R7,#Offset8
  1.1043 +	SUB_RN_O8(7);
  1.1044 +	break;
  1.1045 +case 0x40:
  1.1046 +	switch ((opcode >> 6) & 3)
  1.1047 +	{
  1.1048 +	case 0x00:
  1.1049 +	{
  1.1050 +		// AND Rd, Rs
  1.1051 +		int dest = opcode & 7;
  1.1052 +		reg[dest].I &= reg[(opcode >> 3) & 7].I;
  1.1053 +		N_FLAG		 = reg[dest].I & 0x80000000 ? true : false;
  1.1054 +		Z_FLAG		 = reg[dest].I ? false : true;
  1.1055 +#ifdef BKPT_SUPPORT
  1.1056 +#define THUMB_CONSOLE_OUTPUT(a, b) \
  1.1057 +	if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \
  1.1058 +		extern void (*dbgOutput)(char *, u32); \
  1.1059 +		dbgOutput((a), (b)); \
  1.1060 +	}
  1.1061 +#else
  1.1062 +#define THUMB_CONSOLE_OUTPUT(a, b)
  1.1063 +#endif
  1.1064 +		THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
  1.1065 +	}
  1.1066 +	break;
  1.1067 +	case 0x01:
  1.1068 +		// EOR Rd, Rs
  1.1069 +	{
  1.1070 +		int dest = opcode & 7;
  1.1071 +		reg[dest].I ^= reg[(opcode >> 3) & 7].I;
  1.1072 +		N_FLAG		 = reg[dest].I & 0x80000000 ? true : false;
  1.1073 +		Z_FLAG		 = reg[dest].I ? false : true;
  1.1074 +	}
  1.1075 +	break;
  1.1076 +	case 0x02:
  1.1077 +		// LSL Rd, Rs
  1.1078 +	{
  1.1079 +		int dest  = opcode & 7;
  1.1080 +		u32 value = reg[(opcode >> 3) & 7].B.B0;
  1.1081 +		if (value)
  1.1082 +		{
  1.1083 +			if (value == 32)
  1.1084 +			{
  1.1085 +				value  = 0;
  1.1086 +				C_FLAG = (reg[dest].I & 1 ? true : false);
  1.1087 +			}
  1.1088 +			else if (value < 32)
  1.1089 +			{
  1.1090 +				LSL_RD_RS;
  1.1091 +			}
  1.1092 +			else
  1.1093 +			{
  1.1094 +				value  = 0;
  1.1095 +				C_FLAG = false;
  1.1096 +			}
  1.1097 +			reg[dest].I = value;
  1.1098 +		}
  1.1099 +		N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1.1100 +		Z_FLAG = reg[dest].I ? false : true;
  1.1101 +		clockTicks++;
  1.1102 +	}
  1.1103 +	break;
  1.1104 +	case 0x03:
  1.1105 +	{
  1.1106 +		// LSR Rd, Rs
  1.1107 +		int dest  = opcode & 7;
  1.1108 +		u32 value = reg[(opcode >> 3) & 7].B.B0;
  1.1109 +		if (value)
  1.1110 +		{
  1.1111 +			if (value == 32)
  1.1112 +			{
  1.1113 +				value  = 0;
  1.1114 +				C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
  1.1115 +			}
  1.1116 +			else if (value < 32)
  1.1117 +			{
  1.1118 +				LSR_RD_RS;
  1.1119 +			}
  1.1120 +			else
  1.1121 +			{
  1.1122 +				value  = 0;
  1.1123 +				C_FLAG = false;
  1.1124 +			}
  1.1125 +			reg[dest].I = value;
  1.1126 +		}
  1.1127 +		N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1.1128 +		Z_FLAG = reg[dest].I ? false : true;
  1.1129 +		clockTicks++;
  1.1130 +	}
  1.1131 +	break;
  1.1132 +	}
  1.1133 +	break;
  1.1134 +case 0x41:
  1.1135 +	switch ((opcode >> 6) & 3)
  1.1136 +	{
  1.1137 +	case 0x00:
  1.1138 +	{
  1.1139 +		// ASR Rd, Rs
  1.1140 +		int dest  = opcode & 7;
  1.1141 +		u32 value = reg[(opcode >> 3) & 7].B.B0;
  1.1142 +		// ASR
  1.1143 +		if (value)
  1.1144 +		{
  1.1145 +			if (value < 32)
  1.1146 +			{
  1.1147 +				ASR_RD_RS;
  1.1148 +				reg[dest].I = value;
  1.1149 +			}
  1.1150 +			else
  1.1151 +			{
  1.1152 +				if (reg[dest].I & 0x80000000)
  1.1153 +				{
  1.1154 +					reg[dest].I = 0xFFFFFFFF;
  1.1155 +					C_FLAG		= true;
  1.1156 +				}
  1.1157 +				else
  1.1158 +				{
  1.1159 +					reg[dest].I = 0x00000000;
  1.1160 +					C_FLAG		= false;
  1.1161 +				}
  1.1162 +			}
  1.1163 +		}
  1.1164 +		N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1.1165 +		Z_FLAG = reg[dest].I ? false : true;
  1.1166 +		clockTicks++;
  1.1167 +	}
  1.1168 +	break;
  1.1169 +	case 0x01:
  1.1170 +	{
  1.1171 +		// ADC Rd, Rs
  1.1172 +		int dest  = opcode & 0x07;
  1.1173 +		u32 value = reg[(opcode >> 3) & 7].I;
  1.1174 +		// ADC
  1.1175 +		ADC_RD_RS;
  1.1176 +	}
  1.1177 +	break;
  1.1178 +	case 0x02:
  1.1179 +	{
  1.1180 +		// SBC Rd, Rs
  1.1181 +		int dest  = opcode & 0x07;
  1.1182 +		u32 value = reg[(opcode >> 3) & 7].I;
  1.1183 +
  1.1184 +		// SBC
  1.1185 +		SBC_RD_RS;
  1.1186 +	}
  1.1187 +	break;
  1.1188 +	case 0x03:
  1.1189 +		// ROR Rd, Rs
  1.1190 +	{
  1.1191 +		int dest  = opcode & 7;
  1.1192 +		u32 value = reg[(opcode >> 3) & 7].B.B0;
  1.1193 +
  1.1194 +		if (value)
  1.1195 +		{
  1.1196 +			value = value & 0x1f;
  1.1197 +			if (value == 0)
  1.1198 +			{
  1.1199 +				C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
  1.1200 +			}
  1.1201 +			else
  1.1202 +			{
  1.1203 +				ROR_RD_RS;
  1.1204 +				reg[dest].I = value;
  1.1205 +			}
  1.1206 +		}
  1.1207 +		clockTicks++;
  1.1208 +		N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1.1209 +		Z_FLAG = reg[dest].I ? false : true;
  1.1210 +	}
  1.1211 +	break;
  1.1212 +	}
  1.1213 +	break;
  1.1214 +case 0x42:
  1.1215 +	switch ((opcode >> 6) & 3)
  1.1216 +	{
  1.1217 +	case 0x00:
  1.1218 +	{
  1.1219 +		// TST Rd, Rs
  1.1220 +		u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
  1.1221 +		N_FLAG = value & 0x80000000 ? true : false;
  1.1222 +		Z_FLAG = value ? false : true;
  1.1223 +	}
  1.1224 +	break;
  1.1225 +	case 0x01:
  1.1226 +	{
  1.1227 +		// NEG Rd, Rs
  1.1228 +		int dest   = opcode & 7;
  1.1229 +		int source = (opcode >> 3) & 7;
  1.1230 +		NEG_RD_RS;
  1.1231 +	}
  1.1232 +	break;
  1.1233 +	case 0x02:
  1.1234 +	{
  1.1235 +		// CMP Rd, Rs
  1.1236 +		int dest  = opcode & 7;
  1.1237 +		u32 value = reg[(opcode >> 3) & 7].I;
  1.1238 +		CMP_RD_RS;
  1.1239 +	}
  1.1240 +	break;
  1.1241 +	case 0x03:
  1.1242 +	{
  1.1243 +		// CMN Rd, Rs
  1.1244 +		int dest  = opcode & 7;
  1.1245 +		u32 value = reg[(opcode >> 3) & 7].I;
  1.1246 +		// CMN
  1.1247 +		CMN_RD_RS;
  1.1248 +	}
  1.1249 +	break;
  1.1250 +	}
  1.1251 +	break;
  1.1252 +case 0x43:
  1.1253 +	switch ((opcode >> 6) & 3)
  1.1254 +	{
  1.1255 +	case 0x00:
  1.1256 +	{
  1.1257 +		// ORR Rd, Rs
  1.1258 +		int dest = opcode & 7;
  1.1259 +		reg[dest].I |= reg[(opcode >> 3) & 7].I;
  1.1260 +		Z_FLAG		 = reg[dest].I ? false : true;
  1.1261 +		N_FLAG		 = reg[dest].I & 0x80000000 ? true : false;
  1.1262 +	}
  1.1263 +	break;
  1.1264 +	case 0x01:
  1.1265 +	{
  1.1266 +		// MUL Rd, Rs
  1.1267 +		int dest = opcode & 7;
  1.1268 +		u32 rm	 = reg[(opcode >> 3) & 7].I;
  1.1269 +		reg[dest].I = reg[dest].I * rm;
  1.1270 +		if (((s32)rm) < 0)
  1.1271 +			rm = ~rm;
  1.1272 +		if ((rm & 0xFFFFFF00) == 0)
  1.1273 +			clockTicks += 1;
  1.1274 +		else if ((rm & 0xFFFF0000) == 0)
  1.1275 +			clockTicks += 2;
  1.1276 +		else if ((rm & 0xFF000000) == 0)
  1.1277 +			clockTicks += 3;
  1.1278 +		else
  1.1279 +			clockTicks += 4;
  1.1280 +		Z_FLAG = reg[dest].I ? false : true;
  1.1281 +		N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1.1282 +	}
  1.1283 +	break;
  1.1284 +	case 0x02:
  1.1285 +	{
  1.1286 +		// BIC Rd, Rs
  1.1287 +		int dest = opcode & 7;
  1.1288 +		reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
  1.1289 +		Z_FLAG		 = reg[dest].I ? false : true;
  1.1290 +		N_FLAG		 = reg[dest].I & 0x80000000 ? true : false;
  1.1291 +	}
  1.1292 +	break;
  1.1293 +	case 0x03:
  1.1294 +	{
  1.1295 +		// MVN Rd, Rs
  1.1296 +		int dest = opcode & 7;
  1.1297 +		reg[dest].I = ~reg[(opcode >> 3) & 7].I;
  1.1298 +		Z_FLAG		= reg[dest].I ? false : true;
  1.1299 +		N_FLAG		= reg[dest].I & 0x80000000 ? true : false;
  1.1300 +	}
  1.1301 +	break;
  1.1302 +	}
  1.1303 +	break;
  1.1304 +case 0x44:
  1.1305 +{
  1.1306 +	int dest = opcode & 7;
  1.1307 +	int base = (opcode >> 3) & 7;
  1.1308 +	switch ((opcode >> 6) & 3)
  1.1309 +	{
  1.1310 +	default:
  1.1311 +		goto unknown_thumb;
  1.1312 +	case 1:
  1.1313 +		// ADD Rd, Hs
  1.1314 +		reg[dest].I += reg[base + 8].I;
  1.1315 +		break;
  1.1316 +	case 2:
  1.1317 +		// ADD Hd, Rs
  1.1318 +		reg[dest + 8].I += reg[base].I;
  1.1319 +		if (dest == 7)
  1.1320 +		{
  1.1321 +			reg[15].I &= 0xFFFFFFFE;
  1.1322 +			armNextPC  = reg[15].I;
  1.1323 +			reg[15].I += 2;
  1.1324 +			clockTicks++;
  1.1325 +		}
  1.1326 +		break;
  1.1327 +	case 3:
  1.1328 +		// ADD Hd, Hs
  1.1329 +		reg[dest + 8].I += reg[base + 8].I;
  1.1330 +		if (dest == 7)
  1.1331 +		{
  1.1332 +			reg[15].I &= 0xFFFFFFFE;
  1.1333 +			armNextPC  = reg[15].I;
  1.1334 +			reg[15].I += 2;
  1.1335 +			clockTicks++;
  1.1336 +		}
  1.1337 +		break;
  1.1338 +	}
  1.1339 +}
  1.1340 +break;
  1.1341 +case 0x45:
  1.1342 +{
  1.1343 +	int dest = opcode & 7;
  1.1344 +	int base = (opcode >> 3) & 7;
  1.1345 +	u32 value;
  1.1346 +	switch ((opcode >> 6) & 3)
  1.1347 +	{
  1.1348 +	case 0:
  1.1349 +		// CMP Rd, Hs
  1.1350 +		value = reg[base].I;
  1.1351 +		CMP_RD_RS;
  1.1352 +		break;
  1.1353 +	case 1:
  1.1354 +		// CMP Rd, Hs
  1.1355 +		value = reg[base + 8].I;
  1.1356 +		CMP_RD_RS;
  1.1357 +		break;
  1.1358 +	case 2:
  1.1359 +		// CMP Hd, Rs
  1.1360 +		value = reg[base].I;
  1.1361 +		dest += 8;
  1.1362 +		CMP_RD_RS;
  1.1363 +		break;
  1.1364 +	case 3:
  1.1365 +		// CMP Hd, Hs
  1.1366 +		value = reg[base + 8].I;
  1.1367 +		dest += 8;
  1.1368 +		CMP_RD_RS;
  1.1369 +		break;
  1.1370 +	}
  1.1371 +}
  1.1372 +break;
  1.1373 +case 0x46:
  1.1374 +{
  1.1375 +	int dest = opcode & 7;
  1.1376 +	int base = (opcode >> 3) & 7;
  1.1377 +	switch ((opcode >> 6) & 3)
  1.1378 +	{
  1.1379 +	case 0:
  1.1380 +		// this form should not be used...
  1.1381 +		// MOV Rd, Rs
  1.1382 +		reg[dest].I = reg[base].I;
  1.1383 +		break;
  1.1384 +	case 1:
  1.1385 +		// MOV Rd, Hs
  1.1386 +		reg[dest].I = reg[base + 8].I;
  1.1387 +		break;
  1.1388 +	case 2:
  1.1389 +		// MOV Hd, Rs
  1.1390 +		reg[dest + 8].I = reg[base].I;
  1.1391 +		if (dest == 7)
  1.1392 +		{
  1.1393 +			reg[15].I &= 0xFFFFFFFE;
  1.1394 +			armNextPC  = reg[15].I;
  1.1395 +			reg[15].I += 2;
  1.1396 +			clockTicks++;
  1.1397 +		}
  1.1398 +		break;
  1.1399 +	case 3:
  1.1400 +		// MOV Hd, Hs
  1.1401 +		reg[dest + 8].I = reg[base + 8].I;
  1.1402 +		if (dest == 7)
  1.1403 +		{
  1.1404 +			reg[15].I &= 0xFFFFFFFE;
  1.1405 +			armNextPC  = reg[15].I;
  1.1406 +			reg[15].I += 2;
  1.1407 +			clockTicks++;
  1.1408 +		}
  1.1409 +		break;
  1.1410 +	}
  1.1411 +}
  1.1412 +break;
  1.1413 +case 0x47:
  1.1414 +{
  1.1415 +	int base = (opcode >> 3) & 7;
  1.1416 +	switch ((opcode >> 6) & 3)
  1.1417 +	{
  1.1418 +	case 0:
  1.1419 +		// BX Rs
  1.1420 +		reg[15].I = (reg[base].I) & 0xFFFFFFFE;
  1.1421 +		if (reg[base].I & 1)
  1.1422 +		{
  1.1423 +			armState   = false;
  1.1424 +			armNextPC  = reg[15].I;
  1.1425 +			reg[15].I += 2;
  1.1426 +		}
  1.1427 +		else
  1.1428 +		{
  1.1429 +			armState   = true;
  1.1430 +			reg[15].I &= 0xFFFFFFFC;
  1.1431 +			armNextPC  = reg[15].I;
  1.1432 +			reg[15].I += 4;
  1.1433 +		}
  1.1434 +		break;
  1.1435 +	case 1:
  1.1436 +		// BX Hs
  1.1437 +		reg[15].I = (reg[8 + base].I) & 0xFFFFFFFE;
  1.1438 +		if (reg[8 + base].I & 1)
  1.1439 +		{
  1.1440 +			armState   = false;
  1.1441 +			armNextPC  = reg[15].I;
  1.1442 +			reg[15].I += 2;
  1.1443 +		}
  1.1444 +		else
  1.1445 +		{
  1.1446 +			armState   = true;
  1.1447 +			reg[15].I &= 0xFFFFFFFC;
  1.1448 +			armNextPC  = reg[15].I;
  1.1449 +			reg[15].I += 4;
  1.1450 +		}
  1.1451 +		break;
  1.1452 +	default:
  1.1453 +		goto unknown_thumb;
  1.1454 +	}
  1.1455 +}
  1.1456 +break;
  1.1457 +case 0x48:
  1.1458 +	// LDR R0,[PC, #Imm]
  1.1459 +{
  1.1460 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1461 +	reg[0].I	= CPUReadMemoryQuick(address);
  1.1462 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1463 +}
  1.1464 +break;
  1.1465 +case 0x49:
  1.1466 +	// LDR R1,[PC, #Imm]
  1.1467 +{
  1.1468 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1469 +	reg[1].I	= CPUReadMemoryQuick(address);
  1.1470 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1471 +}
  1.1472 +break;
  1.1473 +case 0x4a:
  1.1474 +	// LDR R2,[PC, #Imm]
  1.1475 +{
  1.1476 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1477 +	reg[2].I	= CPUReadMemoryQuick(address);
  1.1478 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1479 +}
  1.1480 +break;
  1.1481 +case 0x4b:
  1.1482 +	// LDR R3,[PC, #Imm]
  1.1483 +{
  1.1484 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1485 +	reg[3].I	= CPUReadMemoryQuick(address);
  1.1486 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1487 +}
  1.1488 +break;
  1.1489 +case 0x4c:
  1.1490 +	// LDR R4,[PC, #Imm]
  1.1491 +{
  1.1492 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1493 +	reg[4].I	= CPUReadMemoryQuick(address);
  1.1494 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1495 +}
  1.1496 +break;
  1.1497 +case 0x4d:
  1.1498 +	// LDR R5,[PC, #Imm]
  1.1499 +{
  1.1500 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1501 +	reg[5].I	= CPUReadMemoryQuick(address);
  1.1502 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1503 +}
  1.1504 +break;
  1.1505 +case 0x4e:
  1.1506 +	// LDR R6,[PC, #Imm]
  1.1507 +{
  1.1508 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1509 +	reg[6].I	= CPUReadMemoryQuick(address);
  1.1510 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1511 +}
  1.1512 +break;
  1.1513 +case 0x4f:
  1.1514 +	// LDR R7,[PC, #Imm]
  1.1515 +{
  1.1516 +	u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1.1517 +	reg[7].I	= CPUReadMemoryQuick(address);
  1.1518 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1519 +}
  1.1520 +break;
  1.1521 +case 0x50:
  1.1522 +case 0x51:
  1.1523 +	// STR Rd, [Rs, Rn]
  1.1524 +{
  1.1525 +	u32
  1.1526 +	    address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1527 +	CPUWriteMemory(address,
  1.1528 +	               reg[opcode & 7].I);
  1.1529 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1530 +}
  1.1531 +break;
  1.1532 +case 0x52:
  1.1533 +case 0x53:
  1.1534 +	// STRH Rd, [Rs, Rn]
  1.1535 +{
  1.1536 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1537 +	CPUWriteHalfWord(address,
  1.1538 +	                 reg[opcode & 7].W.W0);
  1.1539 +	clockTicks += CPUUpdateTicksAccess16(address);
  1.1540 +}
  1.1541 +break;
  1.1542 +case 0x54:
  1.1543 +case 0x55:
  1.1544 +	// STRB Rd, [Rs, Rn]
  1.1545 +{
  1.1546 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1547 +	CPUWriteByte(address,
  1.1548 +	             reg[opcode & 7].B.B0);
  1.1549 +	clockTicks += CPUUpdateTicksAccess16(address);
  1.1550 +}
  1.1551 +break;
  1.1552 +case 0x56:
  1.1553 +case 0x57:
  1.1554 +	// LDSB Rd, [Rs, Rn]
  1.1555 +{
  1.1556 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1557 +	reg[opcode & 7].I = (s8)CPUReadByte(address);
  1.1558 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1559 +}
  1.1560 +break;
  1.1561 +case 0x58:
  1.1562 +case 0x59:
  1.1563 +	// LDR Rd, [Rs, Rn]
  1.1564 +{
  1.1565 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1566 +	reg[opcode & 7].I = CPUReadMemory(address);
  1.1567 +	clockTicks		 += CPUUpdateTicksAccess32(address);
  1.1568 +}
  1.1569 +break;
  1.1570 +case 0x5a:
  1.1571 +case 0x5b:
  1.1572 +	// LDRH Rd, [Rs, Rn]
  1.1573 +{
  1.1574 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1575 +	reg[opcode & 7].I = CPUReadHalfWord(address);
  1.1576 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1577 +}
  1.1578 +break;
  1.1579 +case 0x5c:
  1.1580 +case 0x5d:
  1.1581 +	// LDRB Rd, [Rs, Rn]
  1.1582 +{
  1.1583 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1584 +	reg[opcode & 7].I = CPUReadByte(address);
  1.1585 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1586 +}
  1.1587 +break;
  1.1588 +case 0x5e:
  1.1589 +case 0x5f:
  1.1590 +	// LDSH Rd, [Rs, Rn]
  1.1591 +{
  1.1592 +	u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
  1.1593 +	reg[opcode & 7].I = (s16)CPUReadHalfWordSigned(address);
  1.1594 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1595 +}
  1.1596 +break;
  1.1597 +case 0x60:
  1.1598 +case 0x61:
  1.1599 +case 0x62:
  1.1600 +case 0x63:
  1.1601 +case 0x64:
  1.1602 +case 0x65:
  1.1603 +case 0x66:
  1.1604 +case 0x67:
  1.1605 +	// STR Rd, [Rs, #Imm]
  1.1606 +{
  1.1607 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
  1.1608 +	CPUWriteMemory(address,
  1.1609 +	               reg[opcode & 7].I);
  1.1610 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1611 +}
  1.1612 +break;
  1.1613 +case 0x68:
  1.1614 +case 0x69:
  1.1615 +case 0x6a:
  1.1616 +case 0x6b:
  1.1617 +case 0x6c:
  1.1618 +case 0x6d:
  1.1619 +case 0x6e:
  1.1620 +case 0x6f:
  1.1621 +	// LDR Rd, [Rs, #Imm]
  1.1622 +{
  1.1623 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
  1.1624 +	reg[opcode & 7].I = CPUReadMemory(address);
  1.1625 +	clockTicks		 += CPUUpdateTicksAccess32(address);
  1.1626 +}
  1.1627 +break;
  1.1628 +case 0x70:
  1.1629 +case 0x71:
  1.1630 +case 0x72:
  1.1631 +case 0x73:
  1.1632 +case 0x74:
  1.1633 +case 0x75:
  1.1634 +case 0x76:
  1.1635 +case 0x77:
  1.1636 +	// STRB Rd, [Rs, #Imm]
  1.1637 +{
  1.1638 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31));
  1.1639 +	CPUWriteByte(address,
  1.1640 +	             reg[opcode & 7].B.B0);
  1.1641 +	clockTicks += CPUUpdateTicksAccess16(address);
  1.1642 +}
  1.1643 +break;
  1.1644 +case 0x78:
  1.1645 +case 0x79:
  1.1646 +case 0x7a:
  1.1647 +case 0x7b:
  1.1648 +case 0x7c:
  1.1649 +case 0x7d:
  1.1650 +case 0x7e:
  1.1651 +case 0x7f:
  1.1652 +	// LDRB Rd, [Rs, #Imm]
  1.1653 +{
  1.1654 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31));
  1.1655 +	reg[opcode & 7].I = CPUReadByte(address);
  1.1656 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1657 +}
  1.1658 +break;
  1.1659 +case 0x80:
  1.1660 +case 0x81:
  1.1661 +case 0x82:
  1.1662 +case 0x83:
  1.1663 +case 0x84:
  1.1664 +case 0x85:
  1.1665 +case 0x86:
  1.1666 +case 0x87:
  1.1667 +	// STRH Rd, [Rs, #Imm]
  1.1668 +{
  1.1669 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
  1.1670 +	CPUWriteHalfWord(address,
  1.1671 +	                 reg[opcode & 7].W.W0);
  1.1672 +	clockTicks += CPUUpdateTicksAccess16(address);
  1.1673 +}
  1.1674 +break;
  1.1675 +case 0x88:
  1.1676 +case 0x89:
  1.1677 +case 0x8a:
  1.1678 +case 0x8b:
  1.1679 +case 0x8c:
  1.1680 +case 0x8d:
  1.1681 +case 0x8e:
  1.1682 +case 0x8f:
  1.1683 +	// LDRH Rd, [Rs, #Imm]
  1.1684 +{
  1.1685 +	u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
  1.1686 +	reg[opcode & 7].I = CPUReadHalfWord(address);
  1.1687 +	clockTicks		 += CPUUpdateTicksAccess16(address);
  1.1688 +}
  1.1689 +break;
  1.1690 +case 0x90:
  1.1691 +	// STR R0, [SP, #Imm]
  1.1692 +{
  1.1693 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1694 +	CPUWriteMemory(address, reg[0].I);
  1.1695 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1696 +}
  1.1697 +break;
  1.1698 +case 0x91:
  1.1699 +	// STR R1, [SP, #Imm]
  1.1700 +{
  1.1701 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1702 +	CPUWriteMemory(address, reg[1].I);
  1.1703 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1704 +}
  1.1705 +break;
  1.1706 +case 0x92:
  1.1707 +	// STR R2, [SP, #Imm]
  1.1708 +{
  1.1709 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1710 +	CPUWriteMemory(address, reg[2].I);
  1.1711 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1712 +}
  1.1713 +break;
  1.1714 +case 0x93:
  1.1715 +	// STR R3, [SP, #Imm]
  1.1716 +{
  1.1717 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1718 +	CPUWriteMemory(address, reg[3].I);
  1.1719 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1720 +}
  1.1721 +break;
  1.1722 +case 0x94:
  1.1723 +	// STR R4, [SP, #Imm]
  1.1724 +{
  1.1725 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1726 +	CPUWriteMemory(address, reg[4].I);
  1.1727 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1728 +}
  1.1729 +break;
  1.1730 +case 0x95:
  1.1731 +	// STR R5, [SP, #Imm]
  1.1732 +{
  1.1733 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1734 +	CPUWriteMemory(address, reg[5].I);
  1.1735 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1736 +}
  1.1737 +break;
  1.1738 +case 0x96:
  1.1739 +	// STR R6, [SP, #Imm]
  1.1740 +{
  1.1741 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1742 +	CPUWriteMemory(address, reg[6].I);
  1.1743 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1744 +}
  1.1745 +break;
  1.1746 +case 0x97:
  1.1747 +	// STR R7, [SP, #Imm]
  1.1748 +{
  1.1749 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1750 +	CPUWriteMemory(address, reg[7].I);
  1.1751 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1752 +}
  1.1753 +break;
  1.1754 +case 0x98:
  1.1755 +	// LDR R0, [SP, #Imm]
  1.1756 +{
  1.1757 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1758 +	reg[0].I	= CPUReadMemoryQuick(address);
  1.1759 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1760 +}
  1.1761 +break;
  1.1762 +case 0x99:
  1.1763 +	// LDR R1, [SP, #Imm]
  1.1764 +{
  1.1765 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1766 +	reg[1].I	= CPUReadMemoryQuick(address);
  1.1767 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1768 +}
  1.1769 +break;
  1.1770 +case 0x9a:
  1.1771 +	// LDR R2, [SP, #Imm]
  1.1772 +{
  1.1773 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1774 +	reg[2].I	= CPUReadMemoryQuick(address);
  1.1775 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1776 +}
  1.1777 +break;
  1.1778 +case 0x9b:
  1.1779 +	// LDR R3, [SP, #Imm]
  1.1780 +{
  1.1781 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1782 +	reg[3].I	= CPUReadMemoryQuick(address);
  1.1783 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1784 +}
  1.1785 +break;
  1.1786 +case 0x9c:
  1.1787 +	// LDR R4, [SP, #Imm]
  1.1788 +{
  1.1789 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1790 +	reg[4].I	= CPUReadMemoryQuick(address);
  1.1791 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1792 +}
  1.1793 +break;
  1.1794 +case 0x9d:
  1.1795 +	// LDR R5, [SP, #Imm]
  1.1796 +{
  1.1797 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1798 +	reg[5].I	= CPUReadMemoryQuick(address);
  1.1799 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1800 +}
  1.1801 +break;
  1.1802 +case 0x9e:
  1.1803 +	// LDR R6, [SP, #Imm]
  1.1804 +{
  1.1805 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1806 +	reg[6].I	= CPUReadMemoryQuick(address);
  1.1807 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1808 +}
  1.1809 +break;
  1.1810 +case 0x9f:
  1.1811 +	// LDR R7, [SP, #Imm]
  1.1812 +{
  1.1813 +	u32 address = reg[13].I + ((opcode & 255) << 2);
  1.1814 +	reg[7].I	= CPUReadMemoryQuick(address);
  1.1815 +	clockTicks += CPUUpdateTicksAccess32(address);
  1.1816 +}
  1.1817 +break;
  1.1818 +case 0xa0:
  1.1819 +	// ADD R0, PC, Imm
  1.1820 +	reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1821 +	break;
  1.1822 +case 0xa1:
  1.1823 +	// ADD R1, PC, Imm
  1.1824 +	reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1825 +	break;
  1.1826 +case 0xa2:
  1.1827 +	// ADD R2, PC, Imm
  1.1828 +	reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1829 +	break;
  1.1830 +case 0xa3:
  1.1831 +	// ADD R3, PC, Imm
  1.1832 +	reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1833 +	break;
  1.1834 +case 0xa4:
  1.1835 +	// ADD R4, PC, Imm
  1.1836 +	reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1837 +	break;
  1.1838 +case 0xa5:
  1.1839 +	// ADD R5, PC, Imm
  1.1840 +	reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1841 +	break;
  1.1842 +case 0xa6:
  1.1843 +	// ADD R6, PC, Imm
  1.1844 +	reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1845 +	break;
  1.1846 +case 0xa7:
  1.1847 +	// ADD R7, PC, Imm
  1.1848 +	reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
  1.1849 +	break;
  1.1850 +case 0xa8:
  1.1851 +	// ADD R0, SP, Imm
  1.1852 +	reg[0].I = reg[13].I + ((opcode & 255) << 2);
  1.1853 +	break;
  1.1854 +case 0xa9:
  1.1855 +	// ADD R1, SP, Imm
  1.1856 +	reg[1].I = reg[13].I + ((opcode & 255) << 2);
  1.1857 +	break;
  1.1858 +case 0xaa:
  1.1859 +	// ADD R2, SP, Imm
  1.1860 +	reg[2].I = reg[13].I + ((opcode & 255) << 2);
  1.1861 +	break;
  1.1862 +case 0xab:
  1.1863 +	// ADD R3, SP, Imm
  1.1864 +	reg[3].I = reg[13].I + ((opcode & 255) << 2);
  1.1865 +	break;
  1.1866 +case 0xac:
  1.1867 +	// ADD R4, SP, Imm
  1.1868 +	reg[4].I = reg[13].I + ((opcode & 255) << 2);
  1.1869 +	break;
  1.1870 +case 0xad:
  1.1871 +	// ADD R5, SP, Imm
  1.1872 +	reg[5].I = reg[13].I + ((opcode & 255) << 2);
  1.1873 +	break;
  1.1874 +case 0xae:
  1.1875 +	// ADD R6, SP, Imm
  1.1876 +	reg[6].I = reg[13].I + ((opcode & 255) << 2);
  1.1877 +	break;
  1.1878 +case 0xaf:
  1.1879 +	// ADD R7, SP, Imm
  1.1880 +	reg[7].I = reg[13].I + ((opcode & 255) << 2);
  1.1881 +	break;
  1.1882 +case 0xb0:
  1.1883 +{
  1.1884 +	// ADD SP, Imm
  1.1885 +	int offset = (opcode & 127) << 2;
  1.1886 +	if (opcode & 0x80)
  1.1887 +		offset = -offset;
  1.1888 +	reg[13].I += offset;
  1.1889 +}
  1.1890 +break;
  1.1891 +#define PUSH_REG(val, r) \
  1.1892 +	if (opcode & (val)) { \
  1.1893 +		CPUWriteMemory(address, reg[(r)].I); \
  1.1894 +		if (offset) \
  1.1895 +			clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
  1.1896 +		else \
  1.1897 +			clockTicks += 1 + CPUUpdateTicksAccess32(address); \
  1.1898 +		offset	 = 1; \
  1.1899 +		address += 4; \
  1.1900 +	}
  1.1901 +case 0xb4:
  1.1902 +	// PUSH {Rlist}
  1.1903 +{
  1.1904 +	int offset	= 0;
  1.1905 +	u32 temp	= reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
  1.1906 +	u32 address = temp & 0xFFFFFFFC;
  1.1907 +	PUSH_REG(1, 0);
  1.1908 +	PUSH_REG(2, 1);
  1.1909 +	PUSH_REG(4, 2);
  1.1910 +	PUSH_REG(8, 3);
  1.1911 +	PUSH_REG(16, 4);
  1.1912 +	PUSH_REG(32, 5);
  1.1913 +	PUSH_REG(64, 6);
  1.1914 +	PUSH_REG(128, 7);
  1.1915 +	reg[13].I = temp;
  1.1916 +}
  1.1917 +break;
  1.1918 +case 0xb5:
  1.1919 +	// PUSH {Rlist, LR}
  1.1920 +{
  1.1921 +	int offset	= 0;
  1.1922 +	u32 temp	= reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
  1.1923 +	u32 address = temp & 0xFFFFFFFC;
  1.1924 +	PUSH_REG(1, 0);
  1.1925 +	PUSH_REG(2, 1);
  1.1926 +	PUSH_REG(4, 2);
  1.1927 +	PUSH_REG(8, 3);
  1.1928 +	PUSH_REG(16, 4);
  1.1929 +	PUSH_REG(32, 5);
  1.1930 +	PUSH_REG(64, 6);
  1.1931 +	PUSH_REG(128, 7);
  1.1932 +	PUSH_REG(256, 14);
  1.1933 +	reg[13].I = temp;
  1.1934 +}
  1.1935 +break;
  1.1936 +#define POP_REG(val, r) \
  1.1937 +	if (opcode & (val)) { \
  1.1938 +		reg[(r)].I = CPUReadMemory(address); \
  1.1939 +		if (offset) \
  1.1940 +			clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \
  1.1941 +		else \
  1.1942 +			clockTicks += 2 + CPUUpdateTicksAccess32(address); \
  1.1943 +		offset	 = 1; \
  1.1944 +		address += 4; \
  1.1945 +	}
  1.1946 +case 0xbc:
  1.1947 +	// POP {Rlist}
  1.1948 +{
  1.1949 +	int offset	= 0;
  1.1950 +	u32 address = reg[13].I & 0xFFFFFFFC;
  1.1951 +	u32 temp	= reg[13].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.1952 +	POP_REG(1, 0);
  1.1953 +	POP_REG(2, 1);
  1.1954 +	POP_REG(4, 2);
  1.1955 +	POP_REG(8, 3);
  1.1956 +	POP_REG(16, 4);
  1.1957 +	POP_REG(32, 5);
  1.1958 +	POP_REG(64, 6);
  1.1959 +	POP_REG(128, 7);
  1.1960 +	reg[13].I = temp;
  1.1961 +}
  1.1962 +break;
  1.1963 +case 0xbd:
  1.1964 +	// POP {Rlist, PC}
  1.1965 +{
  1.1966 +	int offset	= 0;
  1.1967 +	u32 address = reg[13].I & 0xFFFFFFFC;
  1.1968 +	u32 temp	= reg[13].I + 4 + 4 * cpuBitsSet[opcode & 0xFF];
  1.1969 +	POP_REG(1, 0);
  1.1970 +	POP_REG(2, 1);
  1.1971 +	POP_REG(4, 2);
  1.1972 +	POP_REG(8, 3);
  1.1973 +	POP_REG(16, 4);
  1.1974 +	POP_REG(32, 5);
  1.1975 +	POP_REG(64, 6);
  1.1976 +	POP_REG(128, 7);
  1.1977 +	reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
  1.1978 +	if (offset)
  1.1979 +		clockTicks += CPUUpdateTicksAccessSeq32(address);
  1.1980 +	else
  1.1981 +		clockTicks += CPUUpdateTicksAccess32(address);
  1.1982 +	armNextPC  = reg[15].I;
  1.1983 +	reg[15].I += 2;
  1.1984 +	reg[13].I  = temp;
  1.1985 +}
  1.1986 +break;
  1.1987 +#define THUMB_STM_REG(val, r, b) \
  1.1988 +	if (opcode & (val)) { \
  1.1989 +		CPUWriteMemory(address, reg[(r)].I); \
  1.1990 +		if (!offset) { \
  1.1991 +			reg[(b)].I	= temp; \
  1.1992 +			clockTicks += 1 + CPUUpdateTicksAccess32(address); \
  1.1993 +		} else \
  1.1994 +			clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
  1.1995 +		offset	 = 1; \
  1.1996 +		address += 4; \
  1.1997 +	}
  1.1998 +case 0xc0:
  1.1999 +{
  1.2000 +	// STM R0!, {Rlist}
  1.2001 +	u32 address = reg[0].I & 0xFFFFFFFC;
  1.2002 +	u32 temp	= reg[0].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2003 +	int offset	= 0;
  1.2004 +	// store
  1.2005 +	THUMB_STM_REG(1, 0, 0);
  1.2006 +	THUMB_STM_REG(2, 1, 0);
  1.2007 +	THUMB_STM_REG(4, 2, 0);
  1.2008 +	THUMB_STM_REG(8, 3, 0);
  1.2009 +	THUMB_STM_REG(16, 4, 0);
  1.2010 +	THUMB_STM_REG(32, 5, 0);
  1.2011 +	THUMB_STM_REG(64, 6, 0);
  1.2012 +	THUMB_STM_REG(128, 7, 0);
  1.2013 +}
  1.2014 +break;
  1.2015 +case 0xc1:
  1.2016 +{
  1.2017 +	// STM R1!, {Rlist}
  1.2018 +	u32 address = reg[1].I & 0xFFFFFFFC;
  1.2019 +	u32 temp	= reg[1].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2020 +	int offset	= 0;
  1.2021 +	// store
  1.2022 +	THUMB_STM_REG(1, 0, 1);
  1.2023 +	THUMB_STM_REG(2, 1, 1);
  1.2024 +	THUMB_STM_REG(4, 2, 1);
  1.2025 +	THUMB_STM_REG(8, 3, 1);
  1.2026 +	THUMB_STM_REG(16, 4, 1);
  1.2027 +	THUMB_STM_REG(32, 5, 1);
  1.2028 +	THUMB_STM_REG(64, 6, 1);
  1.2029 +	THUMB_STM_REG(128, 7, 1);
  1.2030 +}
  1.2031 +break;
  1.2032 +case 0xc2:
  1.2033 +{
  1.2034 +	// STM R2!, {Rlist}
  1.2035 +	u32 address = reg[2].I & 0xFFFFFFFC;
  1.2036 +	u32 temp	= reg[2].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2037 +	int offset	= 0;
  1.2038 +	// store
  1.2039 +	THUMB_STM_REG(1, 0, 2);
  1.2040 +	THUMB_STM_REG(2, 1, 2);
  1.2041 +	THUMB_STM_REG(4, 2, 2);
  1.2042 +	THUMB_STM_REG(8, 3, 2);
  1.2043 +	THUMB_STM_REG(16, 4, 2);
  1.2044 +	THUMB_STM_REG(32, 5, 2);
  1.2045 +	THUMB_STM_REG(64, 6, 2);
  1.2046 +	THUMB_STM_REG(128, 7, 2);
  1.2047 +}
  1.2048 +break;
  1.2049 +case 0xc3:
  1.2050 +{
  1.2051 +	// STM R3!, {Rlist}
  1.2052 +	u32 address = reg[3].I & 0xFFFFFFFC;
  1.2053 +	u32 temp	= reg[3].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2054 +	int offset	= 0;
  1.2055 +	// store
  1.2056 +	THUMB_STM_REG(1, 0, 3);
  1.2057 +	THUMB_STM_REG(2, 1, 3);
  1.2058 +	THUMB_STM_REG(4, 2, 3);
  1.2059 +	THUMB_STM_REG(8, 3, 3);
  1.2060 +	THUMB_STM_REG(16, 4, 3);
  1.2061 +	THUMB_STM_REG(32, 5, 3);
  1.2062 +	THUMB_STM_REG(64, 6, 3);
  1.2063 +	THUMB_STM_REG(128, 7, 3);
  1.2064 +}
  1.2065 +break;
  1.2066 +case 0xc4:
  1.2067 +{
  1.2068 +	// STM R4!, {Rlist}
  1.2069 +	u32 address = reg[4].I & 0xFFFFFFFC;
  1.2070 +	u32 temp	= reg[4].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2071 +	int offset	= 0;
  1.2072 +	// store
  1.2073 +	THUMB_STM_REG(1, 0, 4);
  1.2074 +	THUMB_STM_REG(2, 1, 4);
  1.2075 +	THUMB_STM_REG(4, 2, 4);
  1.2076 +	THUMB_STM_REG(8, 3, 4);
  1.2077 +	THUMB_STM_REG(16, 4, 4);
  1.2078 +	THUMB_STM_REG(32, 5, 4);
  1.2079 +	THUMB_STM_REG(64, 6, 4);
  1.2080 +	THUMB_STM_REG(128, 7, 4);
  1.2081 +}
  1.2082 +break;
  1.2083 +case 0xc5:
  1.2084 +{
  1.2085 +	// STM R5!, {Rlist}
  1.2086 +	u32 address = reg[5].I & 0xFFFFFFFC;
  1.2087 +	u32 temp	= reg[5].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2088 +	int offset	= 0;
  1.2089 +	// store
  1.2090 +	THUMB_STM_REG(1, 0, 5);
  1.2091 +	THUMB_STM_REG(2, 1, 5);
  1.2092 +	THUMB_STM_REG(4, 2, 5);
  1.2093 +	THUMB_STM_REG(8, 3, 5);
  1.2094 +	THUMB_STM_REG(16, 4, 5);
  1.2095 +	THUMB_STM_REG(32, 5, 5);
  1.2096 +	THUMB_STM_REG(64, 6, 5);
  1.2097 +	THUMB_STM_REG(128, 7, 5);
  1.2098 +}
  1.2099 +break;
  1.2100 +case 0xc6:
  1.2101 +{
  1.2102 +	// STM R6!, {Rlist}
  1.2103 +	u32 address = reg[6].I & 0xFFFFFFFC;
  1.2104 +	u32 temp	= reg[6].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2105 +	int offset	= 0;
  1.2106 +	// store
  1.2107 +	THUMB_STM_REG(1, 0, 6);
  1.2108 +	THUMB_STM_REG(2, 1, 6);
  1.2109 +	THUMB_STM_REG(4, 2, 6);
  1.2110 +	THUMB_STM_REG(8, 3, 6);
  1.2111 +	THUMB_STM_REG(16, 4, 6);
  1.2112 +	THUMB_STM_REG(32, 5, 6);
  1.2113 +	THUMB_STM_REG(64, 6, 6);
  1.2114 +	THUMB_STM_REG(128, 7, 6);
  1.2115 +}
  1.2116 +break;
  1.2117 +case 0xc7:
  1.2118 +{
  1.2119 +	// STM R7!, {Rlist}
  1.2120 +	u32 address = reg[7].I & 0xFFFFFFFC;
  1.2121 +	u32 temp	= reg[7].I + 4 * cpuBitsSet[opcode & 0xff];
  1.2122 +	int offset	= 0;
  1.2123 +	// store
  1.2124 +	THUMB_STM_REG(1, 0, 7);
  1.2125 +	THUMB_STM_REG(2, 1, 7);
  1.2126 +	THUMB_STM_REG(4, 2, 7);
  1.2127 +	THUMB_STM_REG(8, 3, 7);
  1.2128 +	THUMB_STM_REG(16, 4, 7);
  1.2129 +	THUMB_STM_REG(32, 5, 7);
  1.2130 +	THUMB_STM_REG(64, 6, 7);
  1.2131 +	THUMB_STM_REG(128, 7, 7);
  1.2132 +}
  1.2133 +break;
  1.2134 +#define THUMB_LDM_REG(val, r) \
  1.2135 +	if (opcode & (val)) { \
  1.2136 +		reg[(r)].I = CPUReadMemory(address); \
  1.2137 +		if (offset) \
  1.2138 +			clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \
  1.2139 +		else \
  1.2140 +			clockTicks += 2 + CPUUpdateTicksAccess32(address); \
  1.2141 +		offset	 = 1; \
  1.2142 +		address += 4; \
  1.2143 +	}
  1.2144 +case 0xc8:
  1.2145 +{
  1.2146 +	// LDM R0!, {Rlist}
  1.2147 +	u32 address = reg[0].I & 0xFFFFFFFC;
  1.2148 +	u32 temp	= reg[0].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2149 +	int offset	= 0;
  1.2150 +	// load
  1.2151 +	THUMB_LDM_REG(1, 0);
  1.2152 +	THUMB_LDM_REG(2, 1);
  1.2153 +	THUMB_LDM_REG(4, 2);
  1.2154 +	THUMB_LDM_REG(8, 3);
  1.2155 +	THUMB_LDM_REG(16, 4);
  1.2156 +	THUMB_LDM_REG(32, 5);
  1.2157 +	THUMB_LDM_REG(64, 6);
  1.2158 +	THUMB_LDM_REG(128, 7);
  1.2159 +	if (!(opcode & 1))
  1.2160 +		reg[0].I = temp;
  1.2161 +}
  1.2162 +break;
  1.2163 +case 0xc9:
  1.2164 +{
  1.2165 +	// LDM R1!, {Rlist}
  1.2166 +	u32 address = reg[1].I & 0xFFFFFFFC;
  1.2167 +	u32 temp	= reg[1].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2168 +	int offset	= 0;
  1.2169 +	// load
  1.2170 +	THUMB_LDM_REG(1, 0);
  1.2171 +	THUMB_LDM_REG(2, 1);
  1.2172 +	THUMB_LDM_REG(4, 2);
  1.2173 +	THUMB_LDM_REG(8, 3);
  1.2174 +	THUMB_LDM_REG(16, 4);
  1.2175 +	THUMB_LDM_REG(32, 5);
  1.2176 +	THUMB_LDM_REG(64, 6);
  1.2177 +	THUMB_LDM_REG(128, 7);
  1.2178 +	if (!(opcode & 2))
  1.2179 +		reg[1].I = temp;
  1.2180 +}
  1.2181 +break;
  1.2182 +case 0xca:
  1.2183 +{
  1.2184 +	// LDM R2!, {Rlist}
  1.2185 +	u32 address = reg[2].I & 0xFFFFFFFC;
  1.2186 +	u32 temp	= reg[2].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2187 +	int offset	= 0;
  1.2188 +	// load
  1.2189 +	THUMB_LDM_REG(1, 0);
  1.2190 +	THUMB_LDM_REG(2, 1);
  1.2191 +	THUMB_LDM_REG(4, 2);
  1.2192 +	THUMB_LDM_REG(8, 3);
  1.2193 +	THUMB_LDM_REG(16, 4);
  1.2194 +	THUMB_LDM_REG(32, 5);
  1.2195 +	THUMB_LDM_REG(64, 6);
  1.2196 +	THUMB_LDM_REG(128, 7);
  1.2197 +	if (!(opcode & 4))
  1.2198 +		reg[2].I = temp;
  1.2199 +}
  1.2200 +break;
  1.2201 +case 0xcb:
  1.2202 +{
  1.2203 +	// LDM R3!, {Rlist}
  1.2204 +	u32 address = reg[3].I & 0xFFFFFFFC;
  1.2205 +	u32 temp	= reg[3].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2206 +	int offset	= 0;
  1.2207 +	// load
  1.2208 +	THUMB_LDM_REG(1, 0);
  1.2209 +	THUMB_LDM_REG(2, 1);
  1.2210 +	THUMB_LDM_REG(4, 2);
  1.2211 +	THUMB_LDM_REG(8, 3);
  1.2212 +	THUMB_LDM_REG(16, 4);
  1.2213 +	THUMB_LDM_REG(32, 5);
  1.2214 +	THUMB_LDM_REG(64, 6);
  1.2215 +	THUMB_LDM_REG(128, 7);
  1.2216 +	if (!(opcode & 8))
  1.2217 +		reg[3].I = temp;
  1.2218 +}
  1.2219 +break;
  1.2220 +case 0xcc:
  1.2221 +{
  1.2222 +	// LDM R4!, {Rlist}
  1.2223 +	u32 address = reg[4].I & 0xFFFFFFFC;
  1.2224 +	u32 temp	= reg[4].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2225 +	int offset	= 0;
  1.2226 +	// load
  1.2227 +	THUMB_LDM_REG(1, 0);
  1.2228 +	THUMB_LDM_REG(2, 1);
  1.2229 +	THUMB_LDM_REG(4, 2);
  1.2230 +	THUMB_LDM_REG(8, 3);
  1.2231 +	THUMB_LDM_REG(16, 4);
  1.2232 +	THUMB_LDM_REG(32, 5);
  1.2233 +	THUMB_LDM_REG(64, 6);
  1.2234 +	THUMB_LDM_REG(128, 7);
  1.2235 +	if (!(opcode & 16))
  1.2236 +		reg[4].I = temp;
  1.2237 +}
  1.2238 +break;
  1.2239 +case 0xcd:
  1.2240 +{
  1.2241 +	// LDM R5!, {Rlist}
  1.2242 +	u32 address = reg[5].I & 0xFFFFFFFC;
  1.2243 +	u32 temp	= reg[5].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2244 +	int offset	= 0;
  1.2245 +	// load
  1.2246 +	THUMB_LDM_REG(1, 0);
  1.2247 +	THUMB_LDM_REG(2, 1);
  1.2248 +	THUMB_LDM_REG(4, 2);
  1.2249 +	THUMB_LDM_REG(8, 3);
  1.2250 +	THUMB_LDM_REG(16, 4);
  1.2251 +	THUMB_LDM_REG(32, 5);
  1.2252 +	THUMB_LDM_REG(64, 6);
  1.2253 +	THUMB_LDM_REG(128, 7);
  1.2254 +	if (!(opcode & 32))
  1.2255 +		reg[5].I = temp;
  1.2256 +}
  1.2257 +break;
  1.2258 +case 0xce:
  1.2259 +{
  1.2260 +	// LDM R6!, {Rlist}
  1.2261 +	u32 address = reg[6].I & 0xFFFFFFFC;
  1.2262 +	u32 temp	= reg[6].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2263 +	int offset	= 0;
  1.2264 +	// load
  1.2265 +	THUMB_LDM_REG(1, 0);
  1.2266 +	THUMB_LDM_REG(2, 1);
  1.2267 +	THUMB_LDM_REG(4, 2);
  1.2268 +	THUMB_LDM_REG(8, 3);
  1.2269 +	THUMB_LDM_REG(16, 4);
  1.2270 +	THUMB_LDM_REG(32, 5);
  1.2271 +	THUMB_LDM_REG(64, 6);
  1.2272 +	THUMB_LDM_REG(128, 7);
  1.2273 +	if (!(opcode & 64))
  1.2274 +		reg[6].I = temp;
  1.2275 +}
  1.2276 +break;
  1.2277 +case 0xcf:
  1.2278 +{
  1.2279 +	// LDM R7!, {Rlist}
  1.2280 +	u32 address = reg[7].I & 0xFFFFFFFC;
  1.2281 +	u32 temp	= reg[7].I + 4 * cpuBitsSet[opcode & 0xFF];
  1.2282 +	int offset	= 0;
  1.2283 +	// load
  1.2284 +	THUMB_LDM_REG(1, 0);
  1.2285 +	THUMB_LDM_REG(2, 1);
  1.2286 +	THUMB_LDM_REG(4, 2);
  1.2287 +	THUMB_LDM_REG(8, 3);
  1.2288 +	THUMB_LDM_REG(16, 4);
  1.2289 +	THUMB_LDM_REG(32, 5);
  1.2290 +	THUMB_LDM_REG(64, 6);
  1.2291 +	THUMB_LDM_REG(128, 7);
  1.2292 +	if (!(opcode & 128))
  1.2293 +		reg[7].I = temp;
  1.2294 +}
  1.2295 +break;
  1.2296 +case 0xd0:
  1.2297 +	// BEQ offset
  1.2298 +	if (Z_FLAG)
  1.2299 +	{
  1.2300 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2301 +		armNextPC  = reg[15].I;
  1.2302 +		reg[15].I += 2;
  1.2303 +		clockTicks = 3;
  1.2304 +	}
  1.2305 +	break;
  1.2306 +case 0xd1:
  1.2307 +	// BNE offset
  1.2308 +	if (!Z_FLAG)
  1.2309 +	{
  1.2310 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2311 +		armNextPC  = reg[15].I;
  1.2312 +		reg[15].I += 2;
  1.2313 +		clockTicks = 3;
  1.2314 +	}
  1.2315 +	break;
  1.2316 +case 0xd2:
  1.2317 +	// BCS offset
  1.2318 +	if (C_FLAG)
  1.2319 +	{
  1.2320 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2321 +		armNextPC  = reg[15].I;
  1.2322 +		reg[15].I += 2;
  1.2323 +		clockTicks = 3;
  1.2324 +	}
  1.2325 +	break;
  1.2326 +case 0xd3:
  1.2327 +	// BCC offset
  1.2328 +	if (!C_FLAG)
  1.2329 +	{
  1.2330 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2331 +		armNextPC  = reg[15].I;
  1.2332 +		reg[15].I += 2;
  1.2333 +		clockTicks = 3;
  1.2334 +	}
  1.2335 +	break;
  1.2336 +case 0xd4:
  1.2337 +	// BMI offset
  1.2338 +	if (N_FLAG)
  1.2339 +	{
  1.2340 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2341 +		armNextPC  = reg[15].I;
  1.2342 +		reg[15].I += 2;
  1.2343 +		clockTicks = 3;
  1.2344 +	}
  1.2345 +	break;
  1.2346 +case 0xd5:
  1.2347 +	// BPL offset
  1.2348 +	if (!N_FLAG)
  1.2349 +	{
  1.2350 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2351 +		armNextPC  = reg[15].I;
  1.2352 +		reg[15].I += 2;
  1.2353 +		clockTicks = 3;
  1.2354 +	}
  1.2355 +	break;
  1.2356 +case 0xd6:
  1.2357 +	// BVS offset
  1.2358 +	if (V_FLAG)
  1.2359 +	{
  1.2360 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2361 +		armNextPC  = reg[15].I;
  1.2362 +		reg[15].I += 2;
  1.2363 +		clockTicks = 3;
  1.2364 +	}
  1.2365 +	break;
  1.2366 +case 0xd7:
  1.2367 +	// BVC offset
  1.2368 +	if (!V_FLAG)
  1.2369 +	{
  1.2370 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2371 +		armNextPC  = reg[15].I;
  1.2372 +		reg[15].I += 2;
  1.2373 +		clockTicks = 3;
  1.2374 +	}
  1.2375 +	break;
  1.2376 +case 0xd8:
  1.2377 +	// BHI offset
  1.2378 +	if (C_FLAG && !Z_FLAG)
  1.2379 +	{
  1.2380 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2381 +		armNextPC  = reg[15].I;
  1.2382 +		reg[15].I += 2;
  1.2383 +		clockTicks = 3;
  1.2384 +	}
  1.2385 +	break;
  1.2386 +case 0xd9:
  1.2387 +	// BLS offset
  1.2388 +	if (!C_FLAG || Z_FLAG)
  1.2389 +	{
  1.2390 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2391 +		armNextPC  = reg[15].I;
  1.2392 +		reg[15].I += 2;
  1.2393 +		clockTicks = 3;
  1.2394 +	}
  1.2395 +	break;
  1.2396 +case 0xda:
  1.2397 +	// BGE offset
  1.2398 +	if (N_FLAG == V_FLAG)
  1.2399 +	{
  1.2400 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2401 +		armNextPC  = reg[15].I;
  1.2402 +		reg[15].I += 2;
  1.2403 +		clockTicks = 3;
  1.2404 +	}
  1.2405 +	break;
  1.2406 +case 0xdb:
  1.2407 +	// BLT offset
  1.2408 +	if (N_FLAG != V_FLAG)
  1.2409 +	{
  1.2410 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2411 +		armNextPC  = reg[15].I;
  1.2412 +		reg[15].I += 2;
  1.2413 +		clockTicks = 3;
  1.2414 +	}
  1.2415 +	break;
  1.2416 +case 0xdc:
  1.2417 +	// BGT offset
  1.2418 +	if (!Z_FLAG && (N_FLAG == V_FLAG))
  1.2419 +	{
  1.2420 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2421 +		armNextPC  = reg[15].I;
  1.2422 +		reg[15].I += 2;
  1.2423 +		clockTicks = 3;
  1.2424 +	}
  1.2425 +	break;
  1.2426 +case 0xdd:
  1.2427 +	// BLE offset
  1.2428 +	if (Z_FLAG || (N_FLAG != V_FLAG))
  1.2429 +	{
  1.2430 +		reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1.2431 +		armNextPC  = reg[15].I;
  1.2432 +		reg[15].I += 2;
  1.2433 +		clockTicks = 3;
  1.2434 +	}
  1.2435 +	break;
  1.2436 +case 0xdf:
  1.2437 +	// SWI #comment
  1.2438 +	CPUSoftwareInterrupt(opcode & 0xFF);
  1.2439 +	break;
  1.2440 +case 0xe0:
  1.2441 +case 0xe1:
  1.2442 +case 0xe2:
  1.2443 +case 0xe3:
  1.2444 +case 0xe4:
  1.2445 +case 0xe5:
  1.2446 +case 0xe6:
  1.2447 +case 0xe7:
  1.2448 +{
  1.2449 +	// B offset
  1.2450 +	int offset = (opcode & 0x3FF) << 1;
  1.2451 +	if (opcode & 0x0400)
  1.2452 +		offset |= 0xFFFFF800;
  1.2453 +	reg[15].I += offset;
  1.2454 +	armNextPC  = reg[15].I;
  1.2455 +	reg[15].I += 2;
  1.2456 +}
  1.2457 +break;
  1.2458 +case 0xf0:
  1.2459 +case 0xf1:
  1.2460 +case 0xf2:
  1.2461 +case 0xf3:
  1.2462 +{
  1.2463 +	// BLL #offset
  1.2464 +	int offset = (opcode & 0x7FF);
  1.2465 +	reg[14].I = reg[15].I + (offset << 12);
  1.2466 +}
  1.2467 +break;
  1.2468 +case 0xf4:
  1.2469 +case 0xf5:
  1.2470 +case 0xf6:
  1.2471 +case 0xf7:
  1.2472 +{
  1.2473 +	// BLL #offset
  1.2474 +	int offset = (opcode & 0x7FF);
  1.2475 +	reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
  1.2476 +}
  1.2477 +break;
  1.2478 +case 0xf8:
  1.2479 +case 0xf9:
  1.2480 +case 0xfa:
  1.2481 +case 0xfb:
  1.2482 +case 0xfc:
  1.2483 +case 0xfd:
  1.2484 +case 0xfe:
  1.2485 +case 0xff:
  1.2486 +{
  1.2487 +	// BLH #offset
  1.2488 +	int offset = (opcode & 0x7FF);
  1.2489 +	u32 temp   = reg[15].I - 2;
  1.2490 +	reg[15].I  = (reg[14].I + (offset << 1)) & 0xFFFFFFFE;
  1.2491 +	armNextPC  = reg[15].I;
  1.2492 +	reg[15].I += 2;
  1.2493 +	reg[14].I  = temp | 1;
  1.2494 +}
  1.2495 +break;
  1.2496 +#ifdef BKPT_SUPPORT
  1.2497 +case 0xbe:
  1.2498 +	// BKPT #comment
  1.2499 +	extern void (*dbgSignal)(int, int);
  1.2500 +	reg[15].I -= 2;
  1.2501 +	armNextPC -= 2;
  1.2502 +	dbgSignal(5, opcode & 255);
  1.2503 +	return;
  1.2504 +#endif
  1.2505 +case 0xb1:
  1.2506 +case 0xb2:
  1.2507 +case 0xb3:
  1.2508 +case 0xb6:
  1.2509 +case 0xb7:
  1.2510 +case 0xb8:
  1.2511 +case 0xb9:
  1.2512 +case 0xba:
  1.2513 +case 0xbb:
  1.2514 +#ifndef BKPT_SUPPORT
  1.2515 +case 0xbe:
  1.2516 +#endif
  1.2517 +case 0xbf:
  1.2518 +case 0xde:
  1.2519 +default:
  1.2520 +unknown_thumb:
  1.2521 +#ifdef GBA_LOGGING
  1.2522 +	if (systemVerbose & VERBOSE_UNDEFINED)
  1.2523 +		log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC - 2);
  1.2524 +#endif
  1.2525 +	CPUUndefinedException();
  1.2526 +	break;
  1.2527 +}