xref: /netbsd-src/external/gpl3/gdb/dist/sim/arm/thumbemu.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*  thumbemu.c -- Thumb instruction emulation.
2     Copyright (C) 1996, Cygnus Software Technologies Ltd.
3 
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.
8 
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.
13 
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. */
17 
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.  */
21 
22 #ifndef MODET			/* required for the Thumb instruction support */
23 #if 1
24 #error "MODET needs to be defined for the Thumb world to work"
25 #else
26 #define MODET (1)
27 #endif
28 #endif
29 
30 #include "armdefs.h"
31 #include "armemu.h"
32 #include "armos.h"
33 
34 /* Attempt to emulate an ARMv6 instruction.
35    Stores t_branch into PVALUE upon success or t_undefined otherwise.  */
36 
37 static void
38 handle_v6_thumb_insn (ARMul_State * state,
39 		      ARMword       tinstr,
40 		      tdstate *     pvalid)
41 {
42   ARMword Rd;
43   ARMword Rm;
44 
45   if (! state->is_v6)
46     {
47       * pvalid = t_undefined;
48       return;
49     }
50 
51   switch (tinstr & 0xFFC0)
52     {
53     case 0xb660: /* cpsie */
54     case 0xb670: /* cpsid */
55     case 0x4600: /* cpy */
56     case 0xba00: /* rev */
57     case 0xba40: /* rev16 */
58     case 0xbac0: /* revsh */
59     case 0xb650: /* setend */
60     default:
61       printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
62       * pvalid = t_undefined;
63       return;
64 
65     case 0xb200: /* sxth */
66       Rm = state->Reg [(tinstr & 0x38) >> 3];
67       if (Rm & 0x8000)
68 	state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
69       else
70 	state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
71       break;
72     case 0xb240: /* sxtb */
73       Rm = state->Reg [(tinstr & 0x38) >> 3];
74       if (Rm & 0x80)
75 	state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
76       else
77 	state->Reg [(tinstr & 0x7)] = Rm & 0xff;
78       break;
79     case 0xb280: /* uxth */
80       Rm = state->Reg [(tinstr & 0x38) >> 3];
81       state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
82       break;
83     case 0xb2c0: /* uxtb */
84       Rm = state->Reg [(tinstr & 0x38) >> 3];
85       state->Reg [(tinstr & 0x7)] = Rm & 0xff;
86       break;
87     }
88   /* Indicate that the instruction has been processed.  */
89   * pvalid = t_branch;
90 }
91 
92 /* Decode a 16bit Thumb instruction.  The instruction is in the low
93    16-bits of the tinstr field, with the following Thumb instruction
94    held in the high 16-bits.  Passing in two Thumb instructions allows
95    easier simulation of the special dual BL instruction.  */
96 
97 tdstate
98 ARMul_ThumbDecode (ARMul_State * state,
99 		   ARMword       pc,
100 		   ARMword       tinstr,
101 		   ARMword *     ainstr)
102 {
103   tdstate valid = t_decoded;	/* default assumes a valid instruction */
104   ARMword next_instr;
105 
106   if (state->bigendSig)
107     {
108       next_instr = tinstr & 0xFFFF;
109       tinstr >>= 16;
110     }
111   else
112     {
113       next_instr = tinstr >> 16;
114       tinstr &= 0xFFFF;
115     }
116 
117 #if 1				/* debugging to catch non updates */
118   *ainstr = 0xDEADC0DE;
119 #endif
120 
121   switch ((tinstr & 0xF800) >> 11)
122     {
123     case 0:			/* LSL */
124     case 1:			/* LSR */
125     case 2:			/* ASR */
126       /* Format 1 */
127       *ainstr = 0xE1B00000	/* base opcode */
128 	| ((tinstr & 0x1800) >> (11 - 5))	/* shift type */
129 	| ((tinstr & 0x07C0) << (7 - 6))	/* imm5 */
130 	| ((tinstr & 0x0038) >> 3)	/* Rs */
131 	| ((tinstr & 0x0007) << 12);	/* Rd */
132       break;
133     case 3:			/* ADD/SUB */
134       /* Format 2 */
135       {
136 	ARMword subset[4] = {
137 	  0xE0900000,		/* ADDS Rd,Rs,Rn    */
138 	  0xE0500000,		/* SUBS Rd,Rs,Rn    */
139 	  0xE2900000,		/* ADDS Rd,Rs,#imm3 */
140 	  0xE2500000		/* SUBS Rd,Rs,#imm3 */
141 	};
142 	/* It is quicker indexing into a table, than performing switch
143 	   or conditionals: */
144 	*ainstr = subset[(tinstr & 0x0600) >> 9]	/* base opcode */
145 	  | ((tinstr & 0x01C0) >> 6)	/* Rn or imm3 */
146 	  | ((tinstr & 0x0038) << (16 - 3))	/* Rs */
147 	  | ((tinstr & 0x0007) << (12 - 0));	/* Rd */
148       }
149       break;
150     case 4:			/* MOV */
151     case 5:			/* CMP */
152     case 6:			/* ADD */
153     case 7:			/* SUB */
154       /* Format 3 */
155       {
156 	ARMword subset[4] = {
157 	  0xE3B00000,		/* MOVS Rd,#imm8    */
158 	  0xE3500000,		/* CMP  Rd,#imm8    */
159 	  0xE2900000,		/* ADDS Rd,Rd,#imm8 */
160 	  0xE2500000,		/* SUBS Rd,Rd,#imm8 */
161 	};
162 	*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base opcode */
163 	  | ((tinstr & 0x00FF) >> 0)	/* imm8 */
164 	  | ((tinstr & 0x0700) << (16 - 8))	/* Rn */
165 	  | ((tinstr & 0x0700) << (12 - 8));	/* Rd */
166       }
167       break;
168     case 8:			/* Arithmetic and high register transfers */
169       /* TODO: Since the subsets for both Format 4 and Format 5
170          instructions are made up of different ARM encodings, we could
171          save the following conditional, and just have one large
172          subset. */
173       if ((tinstr & (1 << 10)) == 0)
174 	{
175 	  /* Format 4 */
176 	  struct
177 	  {
178 	    ARMword opcode;
179 	    enum
180 	    { t_norm, t_shift, t_neg, t_mul }
181 	    otype;
182 	  }
183 	  subset[16] =
184 	  {
185 	    { 0xE0100000, t_norm},			/* ANDS Rd,Rd,Rs     */
186 	    { 0xE0300000, t_norm},			/* EORS Rd,Rd,Rs     */
187 	    { 0xE1B00010, t_shift},			/* MOVS Rd,Rd,LSL Rs */
188 	    { 0xE1B00030, t_shift},			/* MOVS Rd,Rd,LSR Rs */
189 	    { 0xE1B00050, t_shift},			/* MOVS Rd,Rd,ASR Rs */
190 	    { 0xE0B00000, t_norm},			/* ADCS Rd,Rd,Rs     */
191 	    { 0xE0D00000, t_norm},			/* SBCS Rd,Rd,Rs     */
192 	    { 0xE1B00070, t_shift},			/* MOVS Rd,Rd,ROR Rs */
193 	    { 0xE1100000, t_norm},			/* TST  Rd,Rs        */
194 	    { 0xE2700000, t_neg},			/* RSBS Rd,Rs,#0     */
195 	    { 0xE1500000, t_norm},			/* CMP  Rd,Rs        */
196 	    { 0xE1700000, t_norm},			/* CMN  Rd,Rs        */
197 	    { 0xE1900000, t_norm},			/* ORRS Rd,Rd,Rs     */
198 	    { 0xE0100090, t_mul} ,			/* MULS Rd,Rd,Rs     */
199 	    { 0xE1D00000, t_norm},			/* BICS Rd,Rd,Rs     */
200 	    { 0xE1F00000, t_norm}	/* MVNS Rd,Rs        */
201 	  };
202 	  *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;	/* base */
203 	  switch (subset[(tinstr & 0x03C0) >> 6].otype)
204 	    {
205 	    case t_norm:
206 	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rn */
207 		| ((tinstr & 0x0007) << 12)	/* Rd */
208 		| ((tinstr & 0x0038) >> 3);	/* Rs */
209 	      break;
210 	    case t_shift:
211 	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
212 		| ((tinstr & 0x0007) >> 0)	/* Rm */
213 		| ((tinstr & 0x0038) << (8 - 3));	/* Rs */
214 	      break;
215 	    case t_neg:
216 	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
217 		| ((tinstr & 0x0038) << (16 - 3));	/* Rn */
218 	      break;
219 	    case t_mul:
220 	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rd */
221 		| ((tinstr & 0x0007) << 8)	/* Rs */
222 		| ((tinstr & 0x0038) >> 3);	/* Rm */
223 	      break;
224 	    }
225 	}
226       else
227 	{
228 	  /* Format 5 */
229 	  ARMword Rd = ((tinstr & 0x0007) >> 0);
230 	  ARMword Rs = ((tinstr & 0x0038) >> 3);
231 	  if (tinstr & (1 << 7))
232 	    Rd += 8;
233 	  if (tinstr & (1 << 6))
234 	    Rs += 8;
235 	  switch ((tinstr & 0x03C0) >> 6)
236 	    {
237 	    case 0x1:		/* ADD Rd,Rd,Hs */
238 	    case 0x2:		/* ADD Hd,Hd,Rs */
239 	    case 0x3:		/* ADD Hd,Hd,Hs */
240 	      *ainstr = 0xE0800000	/* base */
241 		| (Rd << 16)	/* Rn */
242 		| (Rd << 12)	/* Rd */
243 		| (Rs << 0);	/* Rm */
244 	      break;
245 	    case 0x5:		/* CMP Rd,Hs */
246 	    case 0x6:		/* CMP Hd,Rs */
247 	    case 0x7:		/* CMP Hd,Hs */
248 	      *ainstr = 0xE1500000	/* base */
249 		| (Rd << 16)	/* Rn */
250 		| (Rd << 12)	/* Rd */
251 		| (Rs << 0);	/* Rm */
252 	      break;
253 	    case 0x9:		/* MOV Rd,Hs */
254 	    case 0xA:		/* MOV Hd,Rs */
255 	    case 0xB:		/* MOV Hd,Hs */
256 	      *ainstr = 0xE1A00000	/* base */
257 		| (Rd << 16)	/* Rn */
258 		| (Rd << 12)	/* Rd */
259 		| (Rs << 0);	/* Rm */
260 	      break;
261 	    case 0xC:		/* BX Rs */
262 	    case 0xD:		/* BX Hs */
263 	      *ainstr = 0xE12FFF10	/* base */
264 		| ((tinstr & 0x0078) >> 3);	/* Rd */
265 	      break;
266 	    case 0xE:		/* UNDEFINED */
267 	    case 0xF:		/* UNDEFINED */
268 	      if (state->is_v5)
269 		{
270 		  /* BLX Rs; BLX Hs */
271 		  *ainstr = 0xE12FFF30	/* base */
272 		    | ((tinstr & 0x0078) >> 3);	/* Rd */
273 		  break;
274 		}
275 	      /* Drop through.  */
276 	    case 0x0:		/* UNDEFINED */
277 	    case 0x4:		/* UNDEFINED */
278 	    case 0x8:		/* UNDEFINED */
279 	      handle_v6_thumb_insn (state, tinstr, & valid);
280 	      break;
281 	    }
282 	}
283       break;
284     case 9:			/* LDR Rd,[PC,#imm8] */
285       /* Format 6 */
286       *ainstr = 0xE59F0000	/* base */
287 	| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
288 	| ((tinstr & 0x00FF) << (2 - 0));	/* off8 */
289       break;
290     case 10:
291     case 11:
292       /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
293          the following could be merged into a single subset, saving on
294          the following boolean: */
295       if ((tinstr & (1 << 9)) == 0)
296 	{
297 	  /* Format 7 */
298 	  ARMword subset[4] = {
299 	    0xE7800000,		/* STR  Rd,[Rb,Ro] */
300 	    0xE7C00000,		/* STRB Rd,[Rb,Ro] */
301 	    0xE7900000,		/* LDR  Rd,[Rb,Ro] */
302 	    0xE7D00000		/* LDRB Rd,[Rb,Ro] */
303 	  };
304 	  *ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
305 	    | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
306 	    | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
307 	    | ((tinstr & 0x01C0) >> 6);	/* Ro */
308 	}
309       else
310 	{
311 	  /* Format 8 */
312 	  ARMword subset[4] = {
313 	    0xE18000B0,		/* STRH  Rd,[Rb,Ro] */
314 	    0xE19000D0,		/* LDRSB Rd,[Rb,Ro] */
315 	    0xE19000B0,		/* LDRH  Rd,[Rb,Ro] */
316 	    0xE19000F0		/* LDRSH Rd,[Rb,Ro] */
317 	  };
318 	  *ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
319 	    | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
320 	    | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
321 	    | ((tinstr & 0x01C0) >> 6);	/* Ro */
322 	}
323       break;
324     case 12:			/* STR Rd,[Rb,#imm5] */
325     case 13:			/* LDR Rd,[Rb,#imm5] */
326     case 14:			/* STRB Rd,[Rb,#imm5] */
327     case 15:			/* LDRB Rd,[Rb,#imm5] */
328       /* Format 9 */
329       {
330 	ARMword subset[4] = {
331 	  0xE5800000,		/* STR  Rd,[Rb,#imm5] */
332 	  0xE5900000,		/* LDR  Rd,[Rb,#imm5] */
333 	  0xE5C00000,		/* STRB Rd,[Rb,#imm5] */
334 	  0xE5D00000		/* LDRB Rd,[Rb,#imm5] */
335 	};
336 	/* The offset range defends on whether we are transferring a
337 	   byte or word value: */
338 	*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base */
339 	  | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
340 	  | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
341 	  | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2)));	/* off5 */
342       }
343       break;
344     case 16:			/* STRH Rd,[Rb,#imm5] */
345     case 17:			/* LDRH Rd,[Rb,#imm5] */
346       /* Format 10 */
347       *ainstr = ((tinstr & (1 << 11))	/* base */
348 		 ? 0xE1D000B0	/* LDRH */
349 		 : 0xE1C000B0)	/* STRH */
350 	| ((tinstr & 0x0007) << (12 - 0))	/* Rd */
351 	| ((tinstr & 0x0038) << (16 - 3))	/* Rb */
352 	| ((tinstr & 0x01C0) >> (6 - 1))	/* off5, low nibble */
353 	| ((tinstr & 0x0600) >> (9 - 8));	/* off5, high nibble */
354       break;
355     case 18:			/* STR Rd,[SP,#imm8] */
356     case 19:			/* LDR Rd,[SP,#imm8] */
357       /* Format 11 */
358       *ainstr = ((tinstr & (1 << 11))	/* base */
359 		 ? 0xE59D0000	/* LDR */
360 		 : 0xE58D0000)	/* STR */
361 	| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
362 	| ((tinstr & 0x00FF) << 2);	/* off8 */
363       break;
364     case 20:			/* ADD Rd,PC,#imm8 */
365     case 21:			/* ADD Rd,SP,#imm8 */
366       /* Format 12 */
367       if ((tinstr & (1 << 11)) == 0)
368 	{
369 	  /* NOTE: The PC value used here should by word aligned */
370 	  /* We encode shift-left-by-2 in the rotate immediate field,
371 	     so no shift of off8 is needed.  */
372 	  *ainstr = 0xE28F0F00	/* base */
373 	    | ((tinstr & 0x0700) << (12 - 8))	/* Rd */
374 	    | (tinstr & 0x00FF);	/* off8 */
375 	}
376       else
377 	{
378 	  /* We encode shift-left-by-2 in the rotate immediate field,
379 	     so no shift of off8 is needed.  */
380 	  *ainstr = 0xE28D0F00	/* base */
381 	    | ((tinstr & 0x0700) << (12 - 8))	/* Rd */
382 	    | (tinstr & 0x00FF);	/* off8 */
383 	}
384       break;
385     case 22:
386     case 23:
387       switch (tinstr & 0x0F00)
388 	{
389 	case 0x0000:
390 	  /* Format 13 */
391 	  /* NOTE: The instruction contains a shift left of 2
392 	     equivalent (implemented as ROR #30):  */
393 	  *ainstr = ((tinstr & (1 << 7))	/* base */
394 		     ? 0xE24DDF00	/* SUB */
395 		     : 0xE28DDF00)	/* ADD */
396 	    | (tinstr & 0x007F);	/* off7 */
397 	  break;
398 	case 0x0400:
399 	  /* Format 14 - Push */
400 	  * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
401 	  break;
402 	case 0x0500:
403 	  /* Format 14 - Push + LR */
404 	  * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
405 	  break;
406 	case 0x0c00:
407 	  /* Format 14 - Pop */
408 	  * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
409 	  break;
410 	case 0x0d00:
411 	  /* Format 14 - Pop + PC */
412 	  * ainstr = 0xE8BD8000 | (tinstr & 0x00FF);
413 	  break;
414 	case 0x0e00:
415 	  if (state->is_v5)
416 	    {
417 	      /* This is normally an undefined instruction.  The v5t architecture
418 		 defines this particular pattern as a BKPT instruction, for
419 		 hardware assisted debugging.  We map onto the arm BKPT
420 		 instruction.  */
421 	      * ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
422 	      break;
423 	    }
424 	  /* Drop through.  */
425 	default:
426 	  /* Everything else is an undefined instruction.  */
427 	  handle_v6_thumb_insn (state, tinstr, & valid);
428 	  break;
429 	}
430       break;
431     case 24:			/* STMIA */
432     case 25:			/* LDMIA */
433       /* Format 15 */
434       *ainstr = ((tinstr & (1 << 11))	/* base */
435 		 ? 0xE8B00000	/* LDMIA */
436 		 : 0xE8A00000)	/* STMIA */
437 	| ((tinstr & 0x0700) << (16 - 8))	/* Rb */
438 	| (tinstr & 0x00FF);	/* mask8 */
439       break;
440     case 26:			/* Bcc */
441     case 27:			/* Bcc/SWI */
442       if ((tinstr & 0x0F00) == 0x0F00)
443 	{
444 	  /* Format 17 : SWI */
445 	  *ainstr = 0xEF000000;
446 	  /* Breakpoint must be handled specially.  */
447 	  if ((tinstr & 0x00FF) == 0x18)
448 	    *ainstr |= ((tinstr & 0x00FF) << 16);
449 	  /* New breakpoint value.  See gdb/arm-tdep.c  */
450 	  else if ((tinstr & 0x00FF) == 0xFE)
451 	    *ainstr |= SWI_Breakpoint;
452 	  else
453 	    *ainstr |= (tinstr & 0x00FF);
454 	}
455       else if ((tinstr & 0x0F00) != 0x0E00)
456 	{
457 	  /* Format 16 */
458 	  int doit = FALSE;
459 	  /* TODO: Since we are doing a switch here, we could just add
460 	     the SWI and undefined instruction checks into this
461 	     switch to same on a couple of conditionals: */
462 	  switch ((tinstr & 0x0F00) >> 8)
463 	    {
464 	    case EQ:
465 	      doit = ZFLAG;
466 	      break;
467 	    case NE:
468 	      doit = !ZFLAG;
469 	      break;
470 	    case VS:
471 	      doit = VFLAG;
472 	      break;
473 	    case VC:
474 	      doit = !VFLAG;
475 	      break;
476 	    case MI:
477 	      doit = NFLAG;
478 	      break;
479 	    case PL:
480 	      doit = !NFLAG;
481 	      break;
482 	    case CS:
483 	      doit = CFLAG;
484 	      break;
485 	    case CC:
486 	      doit = !CFLAG;
487 	      break;
488 	    case HI:
489 	      doit = (CFLAG && !ZFLAG);
490 	      break;
491 	    case LS:
492 	      doit = (!CFLAG || ZFLAG);
493 	      break;
494 	    case GE:
495 	      doit = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
496 	      break;
497 	    case LT:
498 	      doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
499 	      break;
500 	    case GT:
501 	      doit = ((!NFLAG && !VFLAG && !ZFLAG)
502 		      || (NFLAG && VFLAG && !ZFLAG));
503 	      break;
504 	    case LE:
505 	      doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
506 	      break;
507 	    }
508 	  if (doit)
509 	    {
510 	      state->Reg[15] = (pc + 4
511 				+ (((tinstr & 0x7F) << 1)
512 				   | ((tinstr & (1 << 7)) ? 0xFFFFFF00 : 0)));
513 	      FLUSHPIPE;
514 	    }
515 	  valid = t_branch;
516 	}
517       else
518 	/* UNDEFINED : cc=1110(AL) uses different format.  */
519 	handle_v6_thumb_insn (state, tinstr, & valid);
520       break;
521     case 28:			/* B */
522       /* Format 18 */
523       state->Reg[15] = (pc + 4
524 			+ (((tinstr & 0x3FF) << 1)
525 			   | ((tinstr & (1 << 10)) ? 0xFFFFF800 : 0)));
526       FLUSHPIPE;
527       valid = t_branch;
528       break;
529     case 29:			/* UNDEFINED */
530       if (state->is_v5)
531 	{
532 	  if (tinstr & 1)
533 	    {
534 	      handle_v6_thumb_insn (state, tinstr, & valid);
535 	      break;
536 	    }
537 	  /* Drop through.  */
538 
539 	  /* Format 19 */
540 	  /* There is no single ARM instruction equivalent for this
541 	     instruction. Also, it should only ever be matched with the
542 	     fmt19 "BL/BLX instruction 1" instruction.  However, we do
543 	     allow the simulation of it on its own, with undefined results
544 	     if r14 is not suitably initialised.  */
545 	  {
546 	    ARMword tmp = (pc + 2);
547 
548 	    state->Reg[15] = ((state->Reg[14] + ((tinstr & 0x07FF) << 1))
549 			      & 0xFFFFFFFC);
550 	    CLEART;
551 	    state->Reg[14] = (tmp | 1);
552 	    valid = t_branch;
553 	    FLUSHPIPE;
554 	    break;
555 	  }
556 	}
557 
558       handle_v6_thumb_insn (state, tinstr, & valid);
559       break;
560 
561     case 30:			/* BL instruction 1 */
562       /* Format 19 */
563       /* There is no single ARM instruction equivalent for this Thumb
564          instruction. To keep the simulation simple (from the user
565          perspective) we check if the following instruction is the
566          second half of this BL, and if it is we simulate it
567          immediately.  */
568       state->Reg[14] = state->Reg[15] \
569 	+ (((tinstr & 0x07FF) << 12) \
570 	   | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
571 
572       valid = t_branch;		/* in-case we don't have the 2nd half */
573       tinstr = next_instr;	/* move the instruction down */
574       pc += 2;			/* point the pc at the 2nd half */
575       if (((tinstr & 0xF800) >> 11) != 31)
576 	{
577 	  if (((tinstr & 0xF800) >> 11) == 29)
578 	    {
579 	      ARMword tmp = (pc + 2);
580 
581 	      state->Reg[15] = ((state->Reg[14]
582 				 + ((tinstr & 0x07FE) << 1))
583 				& 0xFFFFFFFC);
584 	      CLEART;
585 	      state->Reg[14] = (tmp | 1);
586 	      valid = t_branch;
587 	      FLUSHPIPE;
588 	    }
589 	  else
590 	    /* Exit, since not correct instruction. */
591 	    pc -= 2;
592 	  break;
593 	}
594       /* else we fall through to process the second half of the BL */
595       pc += 2;			/* point the pc at the 2nd half */
596     case 31:			/* BL instruction 2 */
597       /* Format 19 */
598       /* There is no single ARM instruction equivalent for this
599          instruction. Also, it should only ever be matched with the
600          fmt19 "BL instruction 1" instruction. However, we do allow
601          the simulation of it on its own, with undefined results if
602          r14 is not suitably initialised.  */
603       {
604 	ARMword tmp = pc;
605 
606 	state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1));
607 	state->Reg[14] = (tmp | 1);
608 	valid = t_branch;
609 	FLUSHPIPE;
610       }
611       break;
612     }
613 
614   return valid;
615 }
616