1 /* thumbemu.c -- Thumb instruction emulation.
2 Copyright (C) 1996, Cygnus Software Technologies Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* We can provide simple Thumb simulation by decoding the Thumb
19 instruction into its corresponding ARM instruction, and using the
20 existing ARM simulator. */
22 #ifndef MODET /* required for the Thumb instruction support */
24 #error "MODET needs to be defined for the Thumb world to work"
34 /* Decode a 16bit Thumb instruction. The instruction is in the low
35 16-bits of the tinstr field, with the following Thumb instruction
36 held in the high 16-bits. Passing in two Thumb instructions allows
37 easier simulation of the special dual BL instruction. */
39 tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
49 tdstate valid = t_decoded; /* default assumes a valid instruction */
54 next_instr = tinstr & 0xFFFF;
59 next_instr = tinstr >> 16;
63 #if 1 /* debugging to catch non updates */
67 switch ((tinstr & 0xF800) >> 11)
73 *ainstr = 0xE1B00000 /* base opcode */
74 | ((tinstr & 0x1800) >> (11 - 5)) /* shift type */
75 | ((tinstr & 0x07C0) << (7 - 6)) /* imm5 */
76 | ((tinstr & 0x0038) >> 3) /* Rs */
77 | ((tinstr & 0x0007) << 12); /* Rd */
83 0xE0900000, /* ADDS Rd,Rs,Rn */
84 0xE0500000, /* SUBS Rd,Rs,Rn */
85 0xE2900000, /* ADDS Rd,Rs,#imm3 */
86 0xE2500000 /* SUBS Rd,Rs,#imm3 */
88 /* It is quicker indexing into a table, than performing switch
90 *ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */
91 | ((tinstr & 0x01C0) >> 6) /* Rn or imm3 */
92 | ((tinstr & 0x0038) << (16 - 3)) /* Rs */
93 | ((tinstr & 0x0007) << (12 - 0)); /* Rd */
102 ARMword subset[4] = {
103 0xE3B00000, /* MOVS Rd,#imm8 */
104 0xE3500000, /* CMP Rd,#imm8 */
105 0xE2900000, /* ADDS Rd,Rd,#imm8 */
106 0xE2500000, /* SUBS Rd,Rd,#imm8 */
108 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */
109 | ((tinstr & 0x00FF) >> 0) /* imm8 */
110 | ((tinstr & 0x0700) << (16 - 8)) /* Rn */
111 | ((tinstr & 0x0700) << (12 - 8)); /* Rd */
114 case 8: /* Arithmetic and high register transfers */
115 /* TODO: Since the subsets for both Format 4 and Format 5
116 instructions are made up of different ARM encodings, we could
117 save the following conditional, and just have one large
119 if ((tinstr & (1 << 10)) == 0)
126 { t_norm, t_shift, t_neg, t_mul }
131 { 0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */
132 { 0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */
133 { 0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */
134 { 0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */
135 { 0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */
136 { 0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */
137 { 0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */
138 { 0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */
139 { 0xE1100000, t_norm}, /* TST Rd,Rs */
140 { 0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */
141 { 0xE1500000, t_norm}, /* CMP Rd,Rs */
142 { 0xE1700000, t_norm}, /* CMN Rd,Rs */
143 { 0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */
144 { 0xE0100090, t_mul} , /* MULS Rd,Rd,Rs */
145 { 0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */
146 { 0xE1F00000, t_norm} /* MVNS Rd,Rs */
148 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
149 switch (subset[(tinstr & 0x03C0) >> 6].otype)
152 *ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
153 | ((tinstr & 0x0007) << 12) /* Rd */
154 | ((tinstr & 0x0038) >> 3); /* Rs */
157 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
158 | ((tinstr & 0x0007) >> 0) /* Rm */
159 | ((tinstr & 0x0038) << (8 - 3)); /* Rs */
162 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
163 | ((tinstr & 0x0038) << (16 - 3)); /* Rn */
166 *ainstr |= ((tinstr & 0x0007) << 16) /* Rd */
167 | ((tinstr & 0x0007) << 8) /* Rs */
168 | ((tinstr & 0x0038) >> 3); /* Rm */
175 ARMword Rd = ((tinstr & 0x0007) >> 0);
176 ARMword Rs = ((tinstr & 0x0038) >> 3);
177 if (tinstr & (1 << 7))
179 if (tinstr & (1 << 6))
181 switch ((tinstr & 0x03C0) >> 6)
183 case 0x1: /* ADD Rd,Rd,Hs */
184 case 0x2: /* ADD Hd,Hd,Rs */
185 case 0x3: /* ADD Hd,Hd,Hs */
186 *ainstr = 0xE0800000 /* base */
187 | (Rd << 16) /* Rn */
188 | (Rd << 12) /* Rd */
189 | (Rs << 0); /* Rm */
191 case 0x5: /* CMP Rd,Hs */
192 case 0x6: /* CMP Hd,Rs */
193 case 0x7: /* CMP Hd,Hs */
194 *ainstr = 0xE1500000 /* base */
195 | (Rd << 16) /* Rn */
196 | (Rd << 12) /* Rd */
197 | (Rs << 0); /* Rm */
199 case 0x9: /* MOV Rd,Hs */
200 case 0xA: /* MOV Hd,Rs */
201 case 0xB: /* MOV Hd,Hs */
202 *ainstr = 0xE1A00000 /* base */
203 | (Rd << 16) /* Rn */
204 | (Rd << 12) /* Rd */
205 | (Rs << 0); /* Rm */
207 case 0xC: /* BX Rs */
208 case 0xD: /* BX Hs */
209 *ainstr = 0xE12FFF10 /* base */
210 | ((tinstr & 0x0078) >> 3); /* Rd */
212 case 0xE: /* UNDEFINED */
213 case 0xF: /* UNDEFINED */
217 *ainstr = 0xE12FFF30 /* base */
218 | ((tinstr & 0x0078) >> 3); /* Rd */
222 case 0x0: /* UNDEFINED */
223 case 0x4: /* UNDEFINED */
224 case 0x8: /* UNDEFINED */
230 case 9: /* LDR Rd,[PC,#imm8] */
232 *ainstr = 0xE59F0000 /* base */
233 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
234 | ((tinstr & 0x00FF) << (2 - 0)); /* off8 */
238 /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
239 the following could be merged into a single subset, saving on
240 the following boolean: */
241 if ((tinstr & (1 << 9)) == 0)
244 ARMword subset[4] = {
245 0xE7800000, /* STR Rd,[Rb,Ro] */
246 0xE7C00000, /* STRB Rd,[Rb,Ro] */
247 0xE7900000, /* LDR Rd,[Rb,Ro] */
248 0xE7D00000 /* LDRB Rd,[Rb,Ro] */
250 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
251 | ((tinstr & 0x0007) << (12 - 0)) /* Rd */
252 | ((tinstr & 0x0038) << (16 - 3)) /* Rb */
253 | ((tinstr & 0x01C0) >> 6); /* Ro */
258 ARMword subset[4] = {
259 0xE18000B0, /* STRH Rd,[Rb,Ro] */
260 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
261 0xE19000B0, /* LDRH Rd,[Rb,Ro] */
262 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
264 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
265 | ((tinstr & 0x0007) << (12 - 0)) /* Rd */
266 | ((tinstr & 0x0038) << (16 - 3)) /* Rb */
267 | ((tinstr & 0x01C0) >> 6); /* Ro */
270 case 12: /* STR Rd,[Rb,#imm5] */
271 case 13: /* LDR Rd,[Rb,#imm5] */
272 case 14: /* STRB Rd,[Rb,#imm5] */
273 case 15: /* LDRB Rd,[Rb,#imm5] */
276 ARMword subset[4] = {
277 0xE5800000, /* STR Rd,[Rb,#imm5] */
278 0xE5900000, /* LDR Rd,[Rb,#imm5] */
279 0xE5C00000, /* STRB Rd,[Rb,#imm5] */
280 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
282 /* The offset range defends on whether we are transferring a
283 byte or word value: */
284 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
285 | ((tinstr & 0x0007) << (12 - 0)) /* Rd */
286 | ((tinstr & 0x0038) << (16 - 3)) /* Rb */
287 | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
290 case 16: /* STRH Rd,[Rb,#imm5] */
291 case 17: /* LDRH Rd,[Rb,#imm5] */
293 *ainstr = ((tinstr & (1 << 11)) /* base */
294 ? 0xE1D000B0 /* LDRH */
295 : 0xE1C000B0) /* STRH */
296 | ((tinstr & 0x0007) << (12 - 0)) /* Rd */
297 | ((tinstr & 0x0038) << (16 - 3)) /* Rb */
298 | ((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
299 | ((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
301 case 18: /* STR Rd,[SP,#imm8] */
302 case 19: /* LDR Rd,[SP,#imm8] */
304 *ainstr = ((tinstr & (1 << 11)) /* base */
305 ? 0xE59D0000 /* LDR */
306 : 0xE58D0000) /* STR */
307 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
308 | ((tinstr & 0x00FF) << 2); /* off8 */
310 case 20: /* ADD Rd,PC,#imm8 */
311 case 21: /* ADD Rd,SP,#imm8 */
313 if ((tinstr & (1 << 11)) == 0)
315 /* NOTE: The PC value used here should by word aligned */
316 /* We encode shift-left-by-2 in the rotate immediate field,
317 so no shift of off8 is needed. */
318 *ainstr = 0xE28F0F00 /* base */
319 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
320 | (tinstr & 0x00FF); /* off8 */
324 /* We encode shift-left-by-2 in the rotate immediate field,
325 so no shift of off8 is needed. */
326 *ainstr = 0xE28D0F00 /* base */
327 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
328 | (tinstr & 0x00FF); /* off8 */
333 switch (tinstr & 0x0F00)
337 /* NOTE: The instruction contains a shift left of 2
338 equivalent (implemented as ROR #30): */
339 *ainstr = ((tinstr & (1 << 7)) /* base */
340 ? 0xE24DDF00 /* SUB */
341 : 0xE28DDF00) /* ADD */
342 | (tinstr & 0x007F); /* off7 */
345 /* Format 14 - Push */
346 * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
349 /* Format 14 - Push + LR */
350 * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
353 /* Format 14 - Pop */
354 * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
357 /* Format 14 - Pop + PC */
358 * ainstr = 0xE8BD8000 | (tinstr & 0x00FF);
363 /* This is normally an undefined instruction. The v5t architecture
364 defines this particular pattern as a BKPT instruction, for
365 hardware assisted debugging. We map onto the arm BKPT
367 * ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
372 /* Everything else is an undefined instruction. */
380 *ainstr = ((tinstr & (1 << 11)) /* base */
381 ? 0xE8B00000 /* LDMIA */
382 : 0xE8A00000) /* STMIA */
383 | ((tinstr & 0x0700) << (16 - 8)) /* Rb */
384 | (tinstr & 0x00FF); /* mask8 */
387 case 27: /* Bcc/SWI */
388 if ((tinstr & 0x0F00) == 0x0F00)
390 /* Format 17 : SWI */
391 *ainstr = 0xEF000000;
392 /* Breakpoint must be handled specially. */
393 if ((tinstr & 0x00FF) == 0x18)
394 *ainstr |= ((tinstr & 0x00FF) << 16);
395 /* New breakpoint value. See gdb/arm-tdep.c */
396 else if ((tinstr & 0x00FF) == 0xFE)
397 *ainstr |= SWI_Breakpoint;
399 *ainstr |= (tinstr & 0x00FF);
401 else if ((tinstr & 0x0F00) != 0x0E00)
405 /* TODO: Since we are doing a switch here, we could just add
406 the SWI and undefined instruction checks into this
407 switch to same on a couple of conditionals: */
408 switch ((tinstr & 0x0F00) >> 8)
435 doit = (CFLAG && !ZFLAG);
438 doit = (!CFLAG || ZFLAG);
441 doit = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
444 doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
447 doit = ((!NFLAG && !VFLAG && !ZFLAG)
448 || (NFLAG && VFLAG && !ZFLAG));
451 doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
456 state->Reg[15] = (pc + 4
457 + (((tinstr & 0x7F) << 1)
458 | ((tinstr & (1 << 7)) ? 0xFFFFFF00 : 0)));
463 else /* UNDEFINED : cc=1110(AL) uses different format */
468 state->Reg[15] = (pc + 4
469 + (((tinstr & 0x3FF) << 1)
470 | ((tinstr & (1 << 10)) ? 0xFFFFF800 : 0)));
474 case 29: /* UNDEFINED */
485 /* There is no single ARM instruction equivalent for this
486 instruction. Also, it should only ever be matched with the
487 fmt19 "BL/BLX instruction 1" instruction. However, we do
488 allow the simulation of it on its own, with undefined results
489 if r14 is not suitably initialised. */
491 ARMword tmp = (pc + 2);
493 state->Reg[15] = ((state->Reg[14] + ((tinstr & 0x07FF) << 1))
496 state->Reg[14] = (tmp | 1);
504 case 30: /* BL instruction 1 */
506 /* There is no single ARM instruction equivalent for this Thumb
507 instruction. To keep the simulation simple (from the user
508 perspective) we check if the following instruction is the
509 second half of this BL, and if it is we simulate it
511 state->Reg[14] = state->Reg[15] \
512 + (((tinstr & 0x07FF) << 12) \
513 | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
515 valid = t_branch; /* in-case we don't have the 2nd half */
516 tinstr = next_instr; /* move the instruction down */
517 pc += 2; /* point the pc at the 2nd half */
518 if (((tinstr & 0xF800) >> 11) != 31)
520 if (((tinstr & 0xF800) >> 11) == 29)
522 ARMword tmp = (pc + 2);
524 state->Reg[15] = ((state->Reg[14]
525 + ((tinstr & 0x07FE) << 1))
528 state->Reg[14] = (tmp | 1);
533 /* Exit, since not correct instruction. */
537 /* else we fall through to process the second half of the BL */
538 pc += 2; /* point the pc at the 2nd half */
539 case 31: /* BL instruction 2 */
541 /* There is no single ARM instruction equivalent for this
542 instruction. Also, it should only ever be matched with the
543 fmt19 "BL instruction 1" instruction. However, we do allow
544 the simulation of it on its own, with undefined results if
545 r14 is not suitably initialised. */
549 state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1));
550 state->Reg[14] = (tmp | 1);