1a1ba9ba4Schristos /*  thumbemu.c -- Thumb instruction emulation.
2a1ba9ba4Schristos     Copyright (C) 1996, Cygnus Software Technologies Ltd.
3a1ba9ba4Schristos 
4a1ba9ba4Schristos     This program is free software; you can redistribute it and/or modify
5a1ba9ba4Schristos     it under the terms of the GNU General Public License as published by
6a1ba9ba4Schristos     the Free Software Foundation; either version 3 of the License, or
7a1ba9ba4Schristos     (at your option) any later version.
8a1ba9ba4Schristos 
9a1ba9ba4Schristos     This program is distributed in the hope that it will be useful,
10a1ba9ba4Schristos     but WITHOUT ANY WARRANTY; without even the implied warranty of
11a1ba9ba4Schristos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12a1ba9ba4Schristos     GNU General Public License for more details.
13a1ba9ba4Schristos 
14a1ba9ba4Schristos     You should have received a copy of the GNU General Public License
15a1ba9ba4Schristos     along with this program; if not, see <http://www.gnu.org/licenses/>. */
16a1ba9ba4Schristos 
17a1ba9ba4Schristos /* We can provide simple Thumb simulation by decoding the Thumb
18a1ba9ba4Schristos instruction into its corresponding ARM instruction, and using the
19a1ba9ba4Schristos existing ARM simulator.  */
20a1ba9ba4Schristos 
21a1ba9ba4Schristos #ifndef MODET			/* required for the Thumb instruction support */
22a1ba9ba4Schristos #if 1
23a1ba9ba4Schristos #error "MODET needs to be defined for the Thumb world to work"
24a1ba9ba4Schristos #else
25a1ba9ba4Schristos #define MODET (1)
26a1ba9ba4Schristos #endif
27a1ba9ba4Schristos #endif
28a1ba9ba4Schristos 
29a1ba9ba4Schristos #include "armdefs.h"
30a1ba9ba4Schristos #include "armemu.h"
31a1ba9ba4Schristos #include "armos.h"
32a1ba9ba4Schristos 
33a1ba9ba4Schristos #define tBIT(n)    ( (ARMword)(tinstr >> (n)) & 1)
34a1ba9ba4Schristos #define tBITS(m,n) ( (ARMword)(tinstr << (31 - (n))) >> ((31 - (n)) + (m)) )
35a1ba9ba4Schristos 
36a1ba9ba4Schristos #define ntBIT(n)    ( (ARMword)(next_instr >> (n)) & 1)
37a1ba9ba4Schristos #define ntBITS(m,n) ( (ARMword)(next_instr << (31 - (n))) >> ((31 - (n)) + (m)) )
38a1ba9ba4Schristos 
39a1ba9ba4Schristos static int
test_cond(int cond,ARMul_State * state)40a1ba9ba4Schristos test_cond (int cond, ARMul_State * state)
41a1ba9ba4Schristos {
42a1ba9ba4Schristos   switch (cond)
43a1ba9ba4Schristos     {
44a1ba9ba4Schristos     case EQ: return ZFLAG;
45a1ba9ba4Schristos     case NE: return !ZFLAG;
46a1ba9ba4Schristos     case VS: return VFLAG;
47a1ba9ba4Schristos     case VC: return !VFLAG;
48a1ba9ba4Schristos     case MI: return NFLAG;
49a1ba9ba4Schristos     case PL: return !NFLAG;
50a1ba9ba4Schristos     case CS: return CFLAG;
51a1ba9ba4Schristos     case CC: return !CFLAG;
52a1ba9ba4Schristos     case HI: return (CFLAG && !ZFLAG);
53a1ba9ba4Schristos     case LS: return (!CFLAG || ZFLAG);
54a1ba9ba4Schristos     case GE: return ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
55a1ba9ba4Schristos     case LT: return ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
56a1ba9ba4Schristos     case GT: return ((!NFLAG && !VFLAG && !ZFLAG)
57a1ba9ba4Schristos 		     || (NFLAG && VFLAG && !ZFLAG));
58a1ba9ba4Schristos     case LE: return ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
59a1ba9ba4Schristos     case AL: return TRUE;
60a1ba9ba4Schristos     case NV:
61a1ba9ba4Schristos     default: return FALSE;
62a1ba9ba4Schristos     }
63a1ba9ba4Schristos }
64a1ba9ba4Schristos 
65a1ba9ba4Schristos static ARMword skipping_32bit_thumb = 0;
66a1ba9ba4Schristos 
67a1ba9ba4Schristos static int     IT_block_cond = AL;
68a1ba9ba4Schristos static ARMword IT_block_mask = 0;
69a1ba9ba4Schristos static int     IT_block_first = FALSE;
70a1ba9ba4Schristos 
71a1ba9ba4Schristos static void
handle_IT_block(ARMul_State * state,ARMword tinstr,tdstate * pvalid)72a1ba9ba4Schristos handle_IT_block (ARMul_State * state,
73a1ba9ba4Schristos 		 ARMword       tinstr,
74a1ba9ba4Schristos 		 tdstate *     pvalid)
75a1ba9ba4Schristos {
76a1ba9ba4Schristos   * pvalid = t_branch;
77a1ba9ba4Schristos   IT_block_mask = tBITS (0, 3);
78a1ba9ba4Schristos 
79a1ba9ba4Schristos   if (IT_block_mask == 0)
80a1ba9ba4Schristos     // NOP or a HINT.
81a1ba9ba4Schristos     return;
82a1ba9ba4Schristos 
83a1ba9ba4Schristos   IT_block_cond = tBITS (4, 7);
84a1ba9ba4Schristos   IT_block_first = TRUE;
85a1ba9ba4Schristos }
86a1ba9ba4Schristos 
87a1ba9ba4Schristos static int
in_IT_block(void)88a1ba9ba4Schristos in_IT_block (void)
89a1ba9ba4Schristos {
90a1ba9ba4Schristos   return IT_block_mask != 0;
91a1ba9ba4Schristos }
92a1ba9ba4Schristos 
93a1ba9ba4Schristos static int
IT_block_allow(ARMul_State * state)94a1ba9ba4Schristos IT_block_allow (ARMul_State * state)
95a1ba9ba4Schristos {
96a1ba9ba4Schristos   int cond;
97a1ba9ba4Schristos 
98a1ba9ba4Schristos   if (IT_block_mask == 0)
99a1ba9ba4Schristos     return TRUE;
100a1ba9ba4Schristos 
101a1ba9ba4Schristos   cond = IT_block_cond;
102a1ba9ba4Schristos 
103a1ba9ba4Schristos   if (IT_block_first)
104a1ba9ba4Schristos     IT_block_first = FALSE;
105a1ba9ba4Schristos   else
106a1ba9ba4Schristos     {
107a1ba9ba4Schristos       if ((IT_block_mask & 8) == 0)
108a1ba9ba4Schristos 	cond &= 0xe;
109a1ba9ba4Schristos       else
110a1ba9ba4Schristos 	cond |= 1;
111a1ba9ba4Schristos       IT_block_mask <<= 1;
112a1ba9ba4Schristos       IT_block_mask &= 0xF;
113a1ba9ba4Schristos     }
114a1ba9ba4Schristos 
115a1ba9ba4Schristos   if (IT_block_mask == 0x8)
116a1ba9ba4Schristos     IT_block_mask = 0;
117a1ba9ba4Schristos 
118a1ba9ba4Schristos   return test_cond (cond, state);
119a1ba9ba4Schristos }
120a1ba9ba4Schristos 
121a1ba9ba4Schristos static ARMword
ThumbExpandImm(ARMword tinstr)122a1ba9ba4Schristos ThumbExpandImm (ARMword tinstr)
123a1ba9ba4Schristos {
124a1ba9ba4Schristos   ARMword val;
125a1ba9ba4Schristos 
126a1ba9ba4Schristos   if (tBITS (10, 11) == 0)
127a1ba9ba4Schristos     {
128a1ba9ba4Schristos       switch (tBITS (8, 9))
129a1ba9ba4Schristos 	{
130a1ba9ba4Schristos 	case 0:	 val = tBITS (0, 7); break;
131a1ba9ba4Schristos 	case 1:	 val = tBITS (0, 7) << 8; break;
132a1ba9ba4Schristos 	case 2:  val = (tBITS (0, 7) << 8) | (tBITS (0, 7) << 24); break;
133a1ba9ba4Schristos 	case 3:  val = tBITS (0, 7) * 0x01010101; break;
134a1ba9ba4Schristos 	default: val = 0;
135a1ba9ba4Schristos 	}
136a1ba9ba4Schristos     }
137a1ba9ba4Schristos   else
138a1ba9ba4Schristos     {
139a1ba9ba4Schristos       int ror = tBITS (7, 11);
140a1ba9ba4Schristos 
141a1ba9ba4Schristos       val = (1 << 7) | tBITS (0, 6);
142a1ba9ba4Schristos       val = (val >> ror) | (val << (32 - ror));
143a1ba9ba4Schristos     }
144a1ba9ba4Schristos 
145a1ba9ba4Schristos   return val;
146a1ba9ba4Schristos }
147a1ba9ba4Schristos 
148a1ba9ba4Schristos #define tASSERT(truth)							\
149a1ba9ba4Schristos   do									\
150a1ba9ba4Schristos     {									\
151a1ba9ba4Schristos       if (! (truth))							\
152a1ba9ba4Schristos 	{								\
153a1ba9ba4Schristos 	  fprintf (stderr, "unhandled T2 insn %04x|%04x detected at thumbemu.c:%d\n", \
154a1ba9ba4Schristos 		   tinstr, next_instr, __LINE__);			\
155a1ba9ba4Schristos 	  return ;							\
156a1ba9ba4Schristos 	}								\
157a1ba9ba4Schristos     }									\
158a1ba9ba4Schristos   while (0)
159a1ba9ba4Schristos 
160a1ba9ba4Schristos 
161a1ba9ba4Schristos /* Attempt to emulate a 32-bit ARMv7 Thumb instruction.
162a1ba9ba4Schristos    Stores t_branch into PVALUE upon success or t_undefined otherwise.  */
163a1ba9ba4Schristos 
164a1ba9ba4Schristos static void
handle_T2_insn(ARMul_State * state,ARMword tinstr,ARMword next_instr,ARMword pc,ARMword * ainstr,tdstate * pvalid)165a1ba9ba4Schristos handle_T2_insn (ARMul_State * state,
166a1ba9ba4Schristos 		ARMword       tinstr,
167a1ba9ba4Schristos 		ARMword       next_instr,
168a1ba9ba4Schristos 		ARMword       pc,
169a1ba9ba4Schristos 		ARMword *     ainstr,
170a1ba9ba4Schristos 		tdstate *     pvalid)
171a1ba9ba4Schristos {
172a1ba9ba4Schristos   * pvalid = t_undefined;
173a1ba9ba4Schristos 
174a1ba9ba4Schristos   if (! state->is_v6)
175a1ba9ba4Schristos     return;
176a1ba9ba4Schristos 
177a1ba9ba4Schristos   if (trace)
178a1ba9ba4Schristos     fprintf (stderr, "|%04x ", next_instr);
179a1ba9ba4Schristos 
180a1ba9ba4Schristos   if (tBITS (11, 15) == 0x1E && ntBIT (15) == 1)
181a1ba9ba4Schristos     {
182a1ba9ba4Schristos       ARMsword simm32 = 0;
183a1ba9ba4Schristos       int S = tBIT (10);
184a1ba9ba4Schristos 
185a1ba9ba4Schristos       * pvalid = t_branch;
186a1ba9ba4Schristos       switch ((ntBIT (14) << 1) | ntBIT (12))
187a1ba9ba4Schristos 	{
188a1ba9ba4Schristos 	case 0: /* B<c>.W  */
189a1ba9ba4Schristos 	  {
190a1ba9ba4Schristos 	    ARMword cond = tBITS (6, 9);
191a1ba9ba4Schristos 	    ARMword imm6;
192a1ba9ba4Schristos 	    ARMword imm11;
193a1ba9ba4Schristos 	    ARMword J1;
194a1ba9ba4Schristos 	    ARMword J2;
195a1ba9ba4Schristos 
196a1ba9ba4Schristos 	    tASSERT (cond != AL && cond != NV);
197a1ba9ba4Schristos 	    if (! test_cond (cond, state))
198a1ba9ba4Schristos 	      return;
199a1ba9ba4Schristos 
200a1ba9ba4Schristos 	    imm6 = tBITS (0, 5);
201a1ba9ba4Schristos 	    imm11 = ntBITS (0, 10);
202a1ba9ba4Schristos 	    J1 = ntBIT (13);
203a1ba9ba4Schristos 	    J2 = ntBIT (11);
204a1ba9ba4Schristos 
205a1ba9ba4Schristos 	    simm32 = (J1 << 19) | (J2 << 18) | (imm6 << 12) | (imm11 << 1);
206a1ba9ba4Schristos 	    if (S)
207*b2396a7bSchristos 	      simm32 |= -(1 << 20);
208a1ba9ba4Schristos 	    break;
209a1ba9ba4Schristos 	  }
210a1ba9ba4Schristos 
211a1ba9ba4Schristos 	case 1: /* B.W  */
212a1ba9ba4Schristos 	  {
213a1ba9ba4Schristos 	    ARMword imm10 = tBITS (0, 9);
214a1ba9ba4Schristos 	    ARMword imm11 = ntBITS (0, 10);
215a1ba9ba4Schristos 	    ARMword I1 = (ntBIT (13) ^ S) ? 0 : 1;
216a1ba9ba4Schristos 	    ARMword I2 = (ntBIT (11) ^ S) ? 0 : 1;
217a1ba9ba4Schristos 
218a1ba9ba4Schristos 	    simm32 = (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
219a1ba9ba4Schristos 	    if (S)
220*b2396a7bSchristos 	      simm32 |= -(1 << 24);
221a1ba9ba4Schristos 	    break;
222a1ba9ba4Schristos 	  }
223a1ba9ba4Schristos 
224a1ba9ba4Schristos 	case 2: /* BLX <label>  */
225a1ba9ba4Schristos 	  {
226a1ba9ba4Schristos 	    ARMword imm10h = tBITS (0, 9);
227a1ba9ba4Schristos 	    ARMword imm10l = ntBITS (1, 10);
228a1ba9ba4Schristos 	    ARMword I1 = (ntBIT (13) ^ S) ? 0 : 1;
229a1ba9ba4Schristos 	    ARMword I2 = (ntBIT (11) ^ S) ? 0 : 1;
230a1ba9ba4Schristos 
231a1ba9ba4Schristos 	    simm32 = (I1 << 23) | (I2 << 22) | (imm10h << 12) | (imm10l << 2);
232a1ba9ba4Schristos 	    if (S)
233*b2396a7bSchristos 	      simm32 |= -(1 << 24);
234a1ba9ba4Schristos 
235a1ba9ba4Schristos 	    CLEART;
236a1ba9ba4Schristos 	    state->Reg[14] = (pc + 4) | 1;
237a1ba9ba4Schristos 	    break;
238a1ba9ba4Schristos 	  }
239a1ba9ba4Schristos 
240a1ba9ba4Schristos 	case 3: /* BL <label>  */
241a1ba9ba4Schristos 	  {
242a1ba9ba4Schristos 	    ARMword imm10 = tBITS (0, 9);
243a1ba9ba4Schristos 	    ARMword imm11 = ntBITS (0, 10);
244a1ba9ba4Schristos 	    ARMword I1 = (ntBIT (13) ^ S) ? 0 : 1;
245a1ba9ba4Schristos 	    ARMword I2 = (ntBIT (11) ^ S) ? 0 : 1;
246a1ba9ba4Schristos 
247a1ba9ba4Schristos 	    simm32 = (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
248a1ba9ba4Schristos 	    if (S)
249*b2396a7bSchristos 	      simm32 |= -(1 << 24);
250a1ba9ba4Schristos 	    state->Reg[14] = (pc + 4) | 1;
251a1ba9ba4Schristos 	    break;
252a1ba9ba4Schristos 	  }
253a1ba9ba4Schristos 	}
254a1ba9ba4Schristos 
255a1ba9ba4Schristos       state->Reg[15] = (pc + 4 + simm32);
256a1ba9ba4Schristos       FLUSHPIPE;
257a1ba9ba4Schristos       if (trace_funcs)
258a1ba9ba4Schristos 	fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
259a1ba9ba4Schristos       return;
260a1ba9ba4Schristos     }
261a1ba9ba4Schristos 
262a1ba9ba4Schristos   switch (tBITS (5,12))
263a1ba9ba4Schristos     {
264a1ba9ba4Schristos     case 0x29:  // TST<c>.W <Rn>,<Rm>{,<shift>}
265a1ba9ba4Schristos       {
266a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
267a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
268a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
269a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
270a1ba9ba4Schristos 
271a1ba9ba4Schristos 	tASSERT (ntBITS (8, 11) == 0xF);
272a1ba9ba4Schristos 
273a1ba9ba4Schristos 	* ainstr = 0xE1100000;
274a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
275a1ba9ba4Schristos 	* ainstr |= (Rm);
276a1ba9ba4Schristos 	* ainstr |= (type << 5);
277a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
278a1ba9ba4Schristos 	* pvalid = t_decoded;
279a1ba9ba4Schristos 	break;
280a1ba9ba4Schristos       }
281a1ba9ba4Schristos 
282a1ba9ba4Schristos     case 0x46:
283a1ba9ba4Schristos       if (tBIT (4) && ntBITS (5, 15) == 0x780)
284a1ba9ba4Schristos 	{
285a1ba9ba4Schristos 	  // Table Branch
286a1ba9ba4Schristos 	  ARMword Rn = tBITS (0, 3);
287a1ba9ba4Schristos 	  ARMword Rm = ntBITS (0, 3);
288a1ba9ba4Schristos 	  ARMword address, dest;
289a1ba9ba4Schristos 
290a1ba9ba4Schristos 	  if (ntBIT (4))
291a1ba9ba4Schristos 	    {
292a1ba9ba4Schristos 	      // TBH
293a1ba9ba4Schristos 	      address = state->Reg[Rn] + state->Reg[Rm] * 2;
294a1ba9ba4Schristos 	      dest = ARMul_LoadHalfWord (state, address);
295a1ba9ba4Schristos 	    }
296a1ba9ba4Schristos 	  else
297a1ba9ba4Schristos 	    {
298a1ba9ba4Schristos 	      // TBB
299a1ba9ba4Schristos 	      address = state->Reg[Rn] + state->Reg[Rm];
300a1ba9ba4Schristos 	      dest = ARMul_LoadByte (state, address);
301a1ba9ba4Schristos 	    }
302a1ba9ba4Schristos 
303a1ba9ba4Schristos 	  state->Reg[15] = (pc + 4 + dest * 2);
304a1ba9ba4Schristos 	  FLUSHPIPE;
305a1ba9ba4Schristos 	  * pvalid = t_branch;
306a1ba9ba4Schristos 	  break;
307a1ba9ba4Schristos 	}
308a1ba9ba4Schristos       /* Fall through.  */
309a1ba9ba4Schristos     case 0x42:
310a1ba9ba4Schristos     case 0x43:
311a1ba9ba4Schristos     case 0x47:
312a1ba9ba4Schristos     case 0x4A:
313a1ba9ba4Schristos     case 0x4B:
314a1ba9ba4Schristos     case 0x4E: // STRD
315a1ba9ba4Schristos     case 0x4F: // LDRD
316a1ba9ba4Schristos       {
317a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
318a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
319a1ba9ba4Schristos 	ARMword Rt2 = ntBITS (8, 11);
320a1ba9ba4Schristos 	ARMword imm8 = ntBITS (0, 7);
321a1ba9ba4Schristos 	ARMword P = tBIT (8);
322a1ba9ba4Schristos 	ARMword U = tBIT (7);
323a1ba9ba4Schristos 	ARMword W = tBIT (5);
324a1ba9ba4Schristos 
325a1ba9ba4Schristos 	tASSERT (Rt2 == Rt + 1);
326a1ba9ba4Schristos 	imm8 <<= 2;
327a1ba9ba4Schristos 	tASSERT (imm8 <= 255);
328a1ba9ba4Schristos 	tASSERT (P != 0 || W != 0);
329a1ba9ba4Schristos 
330a1ba9ba4Schristos 	// Convert into an ARM A1 encoding.
331a1ba9ba4Schristos 	if (Rn == 15)
332a1ba9ba4Schristos 	  {
333a1ba9ba4Schristos 	    tASSERT (tBIT (4) == 1);
334a1ba9ba4Schristos 	    // LDRD (literal)
335a1ba9ba4Schristos 	    // Ignore W even if 1.
336a1ba9ba4Schristos 	    * ainstr = 0xE14F00D0;
337a1ba9ba4Schristos 	  }
338a1ba9ba4Schristos 	else
339a1ba9ba4Schristos 	  {
340a1ba9ba4Schristos 	    if (tBIT (4) == 1)
341a1ba9ba4Schristos 	      // LDRD (immediate)
342a1ba9ba4Schristos 	      * ainstr = 0xE04000D0;
343a1ba9ba4Schristos 	    else
344a1ba9ba4Schristos 	      {
345a1ba9ba4Schristos 		// STRD<c> <Rt>,<Rt2>,[<Rn>{,#+/-<imm8>}]
346a1ba9ba4Schristos 		// STRD<c> <Rt>,<Rt2>,[<Rn>],#+/-<imm8>
347a1ba9ba4Schristos 		// STRD<c> <Rt>,<Rt2>,[<Rn>,#+/-<imm8>]!
348a1ba9ba4Schristos 		* ainstr = 0xE04000F0;
349a1ba9ba4Schristos 	      }
350a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
351a1ba9ba4Schristos 	    * ainstr |= (P << 24);
352a1ba9ba4Schristos 	    * ainstr |= (W << 21);
353a1ba9ba4Schristos 	  }
354a1ba9ba4Schristos 
355a1ba9ba4Schristos 	* ainstr |= (U << 23);
356a1ba9ba4Schristos 	* ainstr |= (Rt << 12);
357a1ba9ba4Schristos 	* ainstr |= ((imm8 << 4) & 0xF00);
358a1ba9ba4Schristos 	* ainstr |= (imm8 & 0xF);
359a1ba9ba4Schristos 	* pvalid = t_decoded;
360a1ba9ba4Schristos 	break;
361a1ba9ba4Schristos       }
362a1ba9ba4Schristos 
363a1ba9ba4Schristos     case 0x44:
364a1ba9ba4Schristos     case 0x45: // LDMIA
365a1ba9ba4Schristos       {
366a1ba9ba4Schristos 	ARMword Rn   = tBITS (0, 3);
367a1ba9ba4Schristos 	int     W    = tBIT (5);
368a1ba9ba4Schristos 	ARMword list = (ntBIT (15) << 15) | (ntBIT (14) << 14) | ntBITS (0, 12);
369a1ba9ba4Schristos 
370a1ba9ba4Schristos 	if (Rn == 13)
371a1ba9ba4Schristos 	  * ainstr = 0xE8BD0000;
372a1ba9ba4Schristos 	else
373a1ba9ba4Schristos 	  {
374a1ba9ba4Schristos 	    * ainstr = 0xE8900000;
375a1ba9ba4Schristos 	    * ainstr |= (W << 21);
376a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
377a1ba9ba4Schristos 	  }
378a1ba9ba4Schristos 	* ainstr |= list;
379a1ba9ba4Schristos 	* pvalid = t_decoded;
380a1ba9ba4Schristos 	break;
381a1ba9ba4Schristos       }
382a1ba9ba4Schristos 
383a1ba9ba4Schristos     case 0x48:
384a1ba9ba4Schristos     case 0x49: // STMDB
385a1ba9ba4Schristos       {
386a1ba9ba4Schristos 	ARMword Rn   = tBITS (0, 3);
387a1ba9ba4Schristos 	int     W    = tBIT (5);
388a1ba9ba4Schristos 	ARMword list = (ntBIT (14) << 14) | ntBITS (0, 12);
389a1ba9ba4Schristos 
390a1ba9ba4Schristos 	if (Rn == 13 && W)
391a1ba9ba4Schristos 	  * ainstr = 0xE92D0000;
392a1ba9ba4Schristos 	else
393a1ba9ba4Schristos 	  {
394a1ba9ba4Schristos 	    * ainstr = 0xE9000000;
395a1ba9ba4Schristos 	    * ainstr |= (W << 21);
396a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
397a1ba9ba4Schristos 	  }
398a1ba9ba4Schristos 	* ainstr |= list;
399a1ba9ba4Schristos 	* pvalid = t_decoded;
400a1ba9ba4Schristos 	break;
401a1ba9ba4Schristos       }
402a1ba9ba4Schristos 
403a1ba9ba4Schristos     case 0x50:
404a1ba9ba4Schristos       {
405a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
406a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
407a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
408a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
409a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
410a1ba9ba4Schristos 
411a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
412a1ba9ba4Schristos 
413a1ba9ba4Schristos 	if (Rd == 15)
414a1ba9ba4Schristos 	  {
415a1ba9ba4Schristos 	    tASSERT (tBIT (4) == 1);
416a1ba9ba4Schristos 
417a1ba9ba4Schristos 	    // TST<c>.W <Rn>,<Rm>{,<shift>}
418a1ba9ba4Schristos 	    * ainstr = 0xE1100000;
419a1ba9ba4Schristos 	  }
420a1ba9ba4Schristos 	else
421a1ba9ba4Schristos 	  {
422a1ba9ba4Schristos 	    // AND{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
423a1ba9ba4Schristos 	    int S = tBIT (4);
424a1ba9ba4Schristos 
425a1ba9ba4Schristos 	    * ainstr = 0xE0000000;
426a1ba9ba4Schristos 
427a1ba9ba4Schristos 	    if (in_IT_block ())
428a1ba9ba4Schristos 	      S = 0;
429a1ba9ba4Schristos 	    * ainstr |= (S << 20);
430a1ba9ba4Schristos 	  }
431a1ba9ba4Schristos 
432a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
433a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
434a1ba9ba4Schristos 	* ainstr |= (type << 5);
435a1ba9ba4Schristos 	* ainstr |= (Rm << 0);
436a1ba9ba4Schristos 	* pvalid = t_decoded;
437a1ba9ba4Schristos 	break;
438a1ba9ba4Schristos       }
439a1ba9ba4Schristos 
440a1ba9ba4Schristos     case 0x51: // BIC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
441a1ba9ba4Schristos       {
442a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
443a1ba9ba4Schristos 	ARMword S  = tBIT(4);
444a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
445a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
446a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
447a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
448a1ba9ba4Schristos 
449a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
450a1ba9ba4Schristos 
451a1ba9ba4Schristos 	* ainstr = 0xE1C00000;
452a1ba9ba4Schristos 	* ainstr |= (S << 20);
453a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
454a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
455a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
456a1ba9ba4Schristos 	* ainstr |= (type << 5);
457a1ba9ba4Schristos 	* ainstr |= (Rm << 0);
458a1ba9ba4Schristos 	* pvalid = t_decoded;
459a1ba9ba4Schristos 	break;
460a1ba9ba4Schristos       }
461a1ba9ba4Schristos 
462a1ba9ba4Schristos     case 0x52:
463a1ba9ba4Schristos       {
464a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
465a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
466a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
467a1ba9ba4Schristos 	int S = tBIT (4);
468a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
469a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
470a1ba9ba4Schristos 
471a1ba9ba4Schristos 	tASSERT (Rd != 15);
472a1ba9ba4Schristos 
473a1ba9ba4Schristos 	if (in_IT_block ())
474a1ba9ba4Schristos 	  S = 0;
475a1ba9ba4Schristos 
476a1ba9ba4Schristos 	if (Rn == 15)
477a1ba9ba4Schristos 	  {
478a1ba9ba4Schristos 	    tASSERT (ntBIT (15) == 0);
479a1ba9ba4Schristos 
480a1ba9ba4Schristos 	    switch (ntBITS (4, 5))
481a1ba9ba4Schristos 	      {
482a1ba9ba4Schristos 	      case 0:
483a1ba9ba4Schristos 		// LSL{S}<c>.W <Rd>,<Rm>,#<imm5>
484a1ba9ba4Schristos 		* ainstr = 0xE1A00000;
485a1ba9ba4Schristos 		break;
486a1ba9ba4Schristos 	      case 1:
487a1ba9ba4Schristos 		// LSR{S}<c>.W <Rd>,<Rm>,#<imm>
488a1ba9ba4Schristos 		* ainstr = 0xE1A00020;
489a1ba9ba4Schristos 		break;
490a1ba9ba4Schristos 	      case 2:
491a1ba9ba4Schristos 		// ASR{S}<c>.W <Rd>,<Rm>,#<imm>
492a1ba9ba4Schristos 		* ainstr = 0xE1A00040;
493a1ba9ba4Schristos 		break;
494a1ba9ba4Schristos 	      case 3:
495a1ba9ba4Schristos 		// ROR{S}<c> <Rd>,<Rm>,#<imm>
496a1ba9ba4Schristos 		* ainstr = 0xE1A00060;
497a1ba9ba4Schristos 		break;
498a1ba9ba4Schristos 	      default:
499a1ba9ba4Schristos 		tASSERT (0);
500a1ba9ba4Schristos 		* ainstr = 0;
501a1ba9ba4Schristos 	      }
502a1ba9ba4Schristos 	  }
503a1ba9ba4Schristos 	else
504a1ba9ba4Schristos 	  {
505a1ba9ba4Schristos 	    // ORR{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
506a1ba9ba4Schristos 	    * ainstr = 0xE1800000;
507a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
508a1ba9ba4Schristos 	    * ainstr |= (type << 5);
509a1ba9ba4Schristos 	  }
510a1ba9ba4Schristos 
511a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
512a1ba9ba4Schristos 	* ainstr |= (S << 20);
513a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
514a1ba9ba4Schristos 	* ainstr |= (Rm <<  0);
515a1ba9ba4Schristos 	* pvalid = t_decoded;
516a1ba9ba4Schristos 	break;
517a1ba9ba4Schristos       }
518a1ba9ba4Schristos 
519a1ba9ba4Schristos     case 0x53: // MVN{S}<c>.W <Rd>,<Rm>{,<shift>}
520a1ba9ba4Schristos       {
521a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
522a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
523a1ba9ba4Schristos 	int S = tBIT (4);
524a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
525a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
526a1ba9ba4Schristos 
527a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
528a1ba9ba4Schristos 
529a1ba9ba4Schristos 	if (in_IT_block ())
530a1ba9ba4Schristos 	  S = 0;
531a1ba9ba4Schristos 
532a1ba9ba4Schristos 	* ainstr = 0xE1E00000;
533a1ba9ba4Schristos 	* ainstr |= (S << 20);
534a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
535a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
536a1ba9ba4Schristos 	* ainstr |= (type << 5);
537a1ba9ba4Schristos 	* ainstr |= (Rm <<  0);
538a1ba9ba4Schristos 	* pvalid = t_decoded;
539a1ba9ba4Schristos 	break;
540a1ba9ba4Schristos       }
541a1ba9ba4Schristos 
542a1ba9ba4Schristos     case 0x54:
543a1ba9ba4Schristos       {
544a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
545a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
546a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
547a1ba9ba4Schristos 	int S = tBIT (4);
548a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
549a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
550a1ba9ba4Schristos 
551a1ba9ba4Schristos 	if (Rd == 15 && S)
552a1ba9ba4Schristos 	  {
553a1ba9ba4Schristos 	    // TEQ<c> <Rn>,<Rm>{,<shift>}
554a1ba9ba4Schristos 	    tASSERT (ntBIT (15) == 0);
555a1ba9ba4Schristos 
556a1ba9ba4Schristos 	    * ainstr = 0xE1300000;
557a1ba9ba4Schristos 	  }
558a1ba9ba4Schristos 	else
559a1ba9ba4Schristos 	  {
560a1ba9ba4Schristos 	    // EOR{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
561a1ba9ba4Schristos 	    if (in_IT_block ())
562a1ba9ba4Schristos 	      S = 0;
563a1ba9ba4Schristos 
564a1ba9ba4Schristos 	    * ainstr = 0xE0200000;
565a1ba9ba4Schristos 	    * ainstr |= (S << 20);
566a1ba9ba4Schristos 	    * ainstr |= (Rd << 8);
567a1ba9ba4Schristos 	  }
568a1ba9ba4Schristos 
569a1ba9ba4Schristos 	* ainstr |= (Rn <<  16);
570a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
571a1ba9ba4Schristos 	* ainstr |= (type << 5);
572a1ba9ba4Schristos 	* ainstr |= (Rm <<  0);
573a1ba9ba4Schristos 	* pvalid = t_decoded;
574a1ba9ba4Schristos 	break;
575a1ba9ba4Schristos       }
576a1ba9ba4Schristos 
577a1ba9ba4Schristos     case 0x58: // ADD{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
578a1ba9ba4Schristos       {
579a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
580a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
581a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
582a1ba9ba4Schristos 	int S = tBIT (4);
583a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
584a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
585a1ba9ba4Schristos 
586a1ba9ba4Schristos 	tASSERT (! (Rd == 15 && S));
587a1ba9ba4Schristos 
588a1ba9ba4Schristos 	if (in_IT_block ())
589a1ba9ba4Schristos 	  S = 0;
590a1ba9ba4Schristos 
591a1ba9ba4Schristos 	* ainstr = 0xE0800000;
592a1ba9ba4Schristos 	* ainstr |= (S << 20);
593a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
594a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
595a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
596a1ba9ba4Schristos 	* ainstr |= (type << 5);
597a1ba9ba4Schristos 	* ainstr |= Rm;
598a1ba9ba4Schristos 	* pvalid = t_decoded;
599a1ba9ba4Schristos 	break;
600a1ba9ba4Schristos       }
601a1ba9ba4Schristos 
602a1ba9ba4Schristos     case 0x5A: // ADC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
603a1ba9ba4Schristos       tASSERT (ntBIT (15) == 0);
604a1ba9ba4Schristos       * ainstr = 0xE0A00000;
605a1ba9ba4Schristos       if (! in_IT_block ())
606a1ba9ba4Schristos 	* ainstr |= (tBIT (4) << 20); // S
607a1ba9ba4Schristos       * ainstr |= (tBITS (0, 3) << 16); // Rn
608a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 12); // Rd
609a1ba9ba4Schristos       * ainstr |= ((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7; // imm5
610a1ba9ba4Schristos       * ainstr |= (ntBITS (4, 5) << 5); // type
611a1ba9ba4Schristos       * ainstr |= ntBITS (0, 3); // Rm
612a1ba9ba4Schristos       * pvalid = t_decoded;
613a1ba9ba4Schristos       break;
614a1ba9ba4Schristos 
615a1ba9ba4Schristos     case 0x5B: // SBC{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
616a1ba9ba4Schristos       {
617a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
618a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
619a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
620a1ba9ba4Schristos 	int S = tBIT (4);
621a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
622a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
623a1ba9ba4Schristos 
624a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
625a1ba9ba4Schristos 
626a1ba9ba4Schristos 	if (in_IT_block ())
627a1ba9ba4Schristos 	  S = 0;
628a1ba9ba4Schristos 
629a1ba9ba4Schristos 	* ainstr = 0xE0C00000;
630a1ba9ba4Schristos 	* ainstr |= (S << 20);
631a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
632a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
633a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
634a1ba9ba4Schristos 	* ainstr |= (type << 5);
635a1ba9ba4Schristos 	* ainstr |= Rm;
636a1ba9ba4Schristos 	* pvalid = t_decoded;
637a1ba9ba4Schristos 	break;
638a1ba9ba4Schristos       }
639a1ba9ba4Schristos 
640a1ba9ba4Schristos     case 0x5E: // RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}
641a1ba9ba4Schristos     case 0x5D: // SUB{S}<c>.W <Rd>,<Rn>,<Rm>{,<shift>}
642a1ba9ba4Schristos       {
643a1ba9ba4Schristos 	ARMword Rn   = tBITS (0, 3);
644a1ba9ba4Schristos 	ARMword Rd   = ntBITS (8, 11);
645a1ba9ba4Schristos 	ARMword Rm   = ntBITS (0, 3);
646a1ba9ba4Schristos 	ARMword S    = tBIT (4);
647a1ba9ba4Schristos 	ARMword type = ntBITS (4, 5);
648a1ba9ba4Schristos 	ARMword imm5 = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
649a1ba9ba4Schristos 
650a1ba9ba4Schristos 	tASSERT (ntBIT(15) == 0);
651a1ba9ba4Schristos 
652a1ba9ba4Schristos 	if (Rd == 15)
653a1ba9ba4Schristos 	  {
654a1ba9ba4Schristos 	    // CMP<c>.W <Rn>, <Rm> {,<shift>}
655a1ba9ba4Schristos 	    * ainstr = 0xE1500000;
656a1ba9ba4Schristos 	    Rd = 0;
657a1ba9ba4Schristos 	  }
658a1ba9ba4Schristos 	else if (tBIT (5))
659a1ba9ba4Schristos 	  * ainstr = 0xE0400000;
660a1ba9ba4Schristos 	else
661a1ba9ba4Schristos 	  * ainstr = 0xE0600000;
662a1ba9ba4Schristos 
663a1ba9ba4Schristos 	* ainstr |= (S << 20);
664a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
665a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
666a1ba9ba4Schristos 	* ainstr |= (imm5 << 7);
667a1ba9ba4Schristos 	* ainstr |= (type << 5);
668a1ba9ba4Schristos 	* ainstr |= (Rm <<  0);
669a1ba9ba4Schristos 	* pvalid = t_decoded;
670a1ba9ba4Schristos 	break;
671a1ba9ba4Schristos       }
672a1ba9ba4Schristos 
673a1ba9ba4Schristos     case 0x9D: // NOP.W
674a1ba9ba4Schristos       tASSERT (tBITS (0, 15) == 0xF3AF);
675a1ba9ba4Schristos       tASSERT (ntBITS (0, 15) == 0x8000);
676a1ba9ba4Schristos       * pvalid = t_branch;
677a1ba9ba4Schristos       break;
678a1ba9ba4Schristos 
679a1ba9ba4Schristos     case 0x80: // AND
680a1ba9ba4Schristos     case 0xA0: // TST
681a1ba9ba4Schristos       {
682a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
683a1ba9ba4Schristos 	ARMword imm12 = (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
684a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
685a1ba9ba4Schristos 	ARMword val;
686a1ba9ba4Schristos 	int S = tBIT (4);
687a1ba9ba4Schristos 
688a1ba9ba4Schristos 	imm12 = ThumbExpandImm (imm12);
689a1ba9ba4Schristos 	val = state->Reg[Rn] & imm12;
690a1ba9ba4Schristos 
691a1ba9ba4Schristos 	if (Rd == 15)
692a1ba9ba4Schristos 	  {
693a1ba9ba4Schristos 	    // TST<c> <Rn>,#<const>
694a1ba9ba4Schristos 	    tASSERT (S == 1);
695a1ba9ba4Schristos 	  }
696a1ba9ba4Schristos 	else
697a1ba9ba4Schristos 	  {
698a1ba9ba4Schristos 	    // AND{S}<c> <Rd>,<Rn>,#<const>
699a1ba9ba4Schristos 	    if (in_IT_block ())
700a1ba9ba4Schristos 	      S = 0;
701a1ba9ba4Schristos 
702a1ba9ba4Schristos 	    state->Reg[Rd] = val;
703a1ba9ba4Schristos 	  }
704a1ba9ba4Schristos 
705a1ba9ba4Schristos 	if (S)
706a1ba9ba4Schristos 	  ARMul_NegZero (state, val);
707a1ba9ba4Schristos 	* pvalid = t_branch;
708a1ba9ba4Schristos 	break;
709a1ba9ba4Schristos       }
710a1ba9ba4Schristos 
711a1ba9ba4Schristos     case 0xA1:
712a1ba9ba4Schristos     case 0x81: // BIC.W
713a1ba9ba4Schristos       {
714a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
715a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
716a1ba9ba4Schristos 	ARMword S = tBIT (4);
717a1ba9ba4Schristos 	ARMword imm8 = (ntBITS (12, 14) << 8) | ntBITS (0, 7);
718a1ba9ba4Schristos 
719a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
720a1ba9ba4Schristos 
721a1ba9ba4Schristos 	imm8 = ThumbExpandImm (imm8);
722a1ba9ba4Schristos 	state->Reg[Rd] = state->Reg[Rn] & ~ imm8;
723a1ba9ba4Schristos 
724a1ba9ba4Schristos 	if (S && ! in_IT_block ())
725a1ba9ba4Schristos 	  ARMul_NegZero (state, state->Reg[Rd]);
726a1ba9ba4Schristos 	* pvalid = t_resolved;
727a1ba9ba4Schristos 	break;
728a1ba9ba4Schristos       }
729a1ba9ba4Schristos 
730a1ba9ba4Schristos     case 0xA2:
731a1ba9ba4Schristos     case 0x82: // MOV{S}<c>.W <Rd>,#<const>
732a1ba9ba4Schristos       {
733a1ba9ba4Schristos 	ARMword val = (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
734a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
735a1ba9ba4Schristos 
736a1ba9ba4Schristos 	val = ThumbExpandImm (val);
737a1ba9ba4Schristos 	state->Reg[Rd] = val;
738a1ba9ba4Schristos 
739a1ba9ba4Schristos 	if (tBIT (4) && ! in_IT_block ())
740a1ba9ba4Schristos 	  ARMul_NegZero (state, val);
741a1ba9ba4Schristos 	/* Indicate that the instruction has been processed.  */
742a1ba9ba4Schristos 	* pvalid = t_branch;
743a1ba9ba4Schristos 	break;
744a1ba9ba4Schristos       }
745a1ba9ba4Schristos 
746a1ba9ba4Schristos     case 0xA3:
747a1ba9ba4Schristos     case 0x83: // MVN{S}<c> <Rd>,#<const>
748a1ba9ba4Schristos       {
749a1ba9ba4Schristos 	ARMword val = (tBIT(10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
750a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
751a1ba9ba4Schristos 
752a1ba9ba4Schristos 	val = ThumbExpandImm (val);
753a1ba9ba4Schristos 	val = ~ val;
754a1ba9ba4Schristos 	state->Reg[Rd] = val;
755a1ba9ba4Schristos 
756a1ba9ba4Schristos 	if (tBIT (4) && ! in_IT_block ())
757a1ba9ba4Schristos 	  ARMul_NegZero (state, val);
758a1ba9ba4Schristos 	* pvalid = t_resolved;
759a1ba9ba4Schristos 	break;
760a1ba9ba4Schristos       }
761a1ba9ba4Schristos 
762a1ba9ba4Schristos     case 0xA4: // EOR
763a1ba9ba4Schristos     case 0x84: // TEQ
764a1ba9ba4Schristos       {
765a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
766a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
767a1ba9ba4Schristos 	ARMword S = tBIT (4);
768a1ba9ba4Schristos 	ARMword imm12 = ((tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7));
769a1ba9ba4Schristos 	ARMword result;
770a1ba9ba4Schristos 
771a1ba9ba4Schristos 	imm12 = ThumbExpandImm (imm12);
772a1ba9ba4Schristos 
773a1ba9ba4Schristos 	result = state->Reg[Rn] ^ imm12;
774a1ba9ba4Schristos 
775a1ba9ba4Schristos 	if (Rd == 15 && S)
776a1ba9ba4Schristos 	  // TEQ<c> <Rn>,#<const>
777a1ba9ba4Schristos 	  ;
778a1ba9ba4Schristos 	else
779a1ba9ba4Schristos 	  {
780a1ba9ba4Schristos 	    // EOR{S}<c> <Rd>,<Rn>,#<const>
781a1ba9ba4Schristos 	    state->Reg[Rd] = result;
782a1ba9ba4Schristos 
783a1ba9ba4Schristos 	    if (in_IT_block ())
784a1ba9ba4Schristos 	      S = 0;
785a1ba9ba4Schristos 	  }
786a1ba9ba4Schristos 
787a1ba9ba4Schristos 	if (S)
788a1ba9ba4Schristos 	  ARMul_NegZero (state, result);
789a1ba9ba4Schristos 	* pvalid = t_resolved;
790a1ba9ba4Schristos 	break;
791a1ba9ba4Schristos       }
792a1ba9ba4Schristos 
793a1ba9ba4Schristos     case 0xA8: // CMN
794a1ba9ba4Schristos     case 0x88: // ADD
795a1ba9ba4Schristos       {
796a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
797a1ba9ba4Schristos 	int S = tBIT (4);
798a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
799a1ba9ba4Schristos 	ARMword lhs = state->Reg[Rn];
800a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
801a1ba9ba4Schristos 	ARMword rhs = ThumbExpandImm (imm12);
802a1ba9ba4Schristos 	ARMword res = lhs + rhs;
803a1ba9ba4Schristos 
804a1ba9ba4Schristos 	if (Rd == 15 && S)
805a1ba9ba4Schristos 	  {
806a1ba9ba4Schristos 	    // CMN<c> <Rn>,#<const>
807a1ba9ba4Schristos 	    res = lhs - rhs;
808a1ba9ba4Schristos 	  }
809a1ba9ba4Schristos 	else
810a1ba9ba4Schristos 	  {
811a1ba9ba4Schristos 	    // ADD{S}<c>.W <Rd>,<Rn>,#<const>
812a1ba9ba4Schristos 	    res = lhs + rhs;
813a1ba9ba4Schristos 
814a1ba9ba4Schristos 	    if (in_IT_block ())
815a1ba9ba4Schristos 	      S = 0;
816a1ba9ba4Schristos 
817a1ba9ba4Schristos 	    state->Reg[Rd] = res;
818a1ba9ba4Schristos 	  }
819a1ba9ba4Schristos 
820a1ba9ba4Schristos 	if (S)
821a1ba9ba4Schristos 	  {
822a1ba9ba4Schristos 	    ARMul_NegZero (state, res);
823a1ba9ba4Schristos 
824a1ba9ba4Schristos 	    if ((lhs | rhs) >> 30)
825a1ba9ba4Schristos 	      {
826a1ba9ba4Schristos 		/* Possible C,V,N to set.  */
827a1ba9ba4Schristos 		ARMul_AddCarry (state, lhs, rhs, res);
828a1ba9ba4Schristos 		ARMul_AddOverflow (state, lhs, rhs, res);
829a1ba9ba4Schristos 	      }
830a1ba9ba4Schristos 	    else
831a1ba9ba4Schristos 	      {
832a1ba9ba4Schristos 		CLEARC;
833a1ba9ba4Schristos 		CLEARV;
834a1ba9ba4Schristos 	      }
835a1ba9ba4Schristos 	  }
836a1ba9ba4Schristos 
837a1ba9ba4Schristos 	* pvalid = t_branch;
838a1ba9ba4Schristos 	break;
839a1ba9ba4Schristos       }
840a1ba9ba4Schristos 
841a1ba9ba4Schristos     case 0xAA:
842a1ba9ba4Schristos     case 0x8A: // ADC{S}<c> <Rd>,<Rn>,#<const>
843a1ba9ba4Schristos       {
844a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
845a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
846a1ba9ba4Schristos 	int S = tBIT (4);
847a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
848a1ba9ba4Schristos 	ARMword lhs = state->Reg[Rn];
849a1ba9ba4Schristos 	ARMword rhs = ThumbExpandImm (imm12);
850a1ba9ba4Schristos 	ARMword res;
851a1ba9ba4Schristos 
852a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
853a1ba9ba4Schristos 
854a1ba9ba4Schristos 	if (CFLAG)
855a1ba9ba4Schristos 	  rhs += 1;
856a1ba9ba4Schristos 
857a1ba9ba4Schristos 	res = lhs + rhs;
858a1ba9ba4Schristos 	state->Reg[Rd] = res;
859a1ba9ba4Schristos 
860a1ba9ba4Schristos 	if (in_IT_block ())
861a1ba9ba4Schristos 	  S = 0;
862a1ba9ba4Schristos 
863a1ba9ba4Schristos 	if (S)
864a1ba9ba4Schristos 	  {
865a1ba9ba4Schristos 	    ARMul_NegZero (state, res);
866a1ba9ba4Schristos 
867a1ba9ba4Schristos 	    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
868a1ba9ba4Schristos 	      {
869a1ba9ba4Schristos 		ARMul_AddCarry (state, lhs, rhs, res);
870a1ba9ba4Schristos 		ARMul_AddOverflow (state, lhs, rhs, res);
871a1ba9ba4Schristos 	      }
872a1ba9ba4Schristos 	    else
873a1ba9ba4Schristos 	      {
874a1ba9ba4Schristos 		CLEARC;
875a1ba9ba4Schristos 		CLEARV;
876a1ba9ba4Schristos 	      }
877a1ba9ba4Schristos 	  }
878a1ba9ba4Schristos 
879a1ba9ba4Schristos 	* pvalid = t_branch;
880a1ba9ba4Schristos 	break;
881a1ba9ba4Schristos       }
882a1ba9ba4Schristos 
883a1ba9ba4Schristos     case 0xAB:
884a1ba9ba4Schristos     case 0x8B: // SBC{S}<c> <Rd>,<Rn>,#<const>
885a1ba9ba4Schristos       {
886a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
887a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
888a1ba9ba4Schristos 	int S = tBIT (4);
889a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
890a1ba9ba4Schristos 	ARMword lhs = state->Reg[Rn];
891a1ba9ba4Schristos 	ARMword rhs = ThumbExpandImm (imm12);
892a1ba9ba4Schristos 	ARMword res;
893a1ba9ba4Schristos 
894a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
895a1ba9ba4Schristos 
896a1ba9ba4Schristos 	if (! CFLAG)
897a1ba9ba4Schristos 	  rhs += 1;
898a1ba9ba4Schristos 
899a1ba9ba4Schristos 	res = lhs - rhs;
900a1ba9ba4Schristos 	state->Reg[Rd] = res;
901a1ba9ba4Schristos 
902a1ba9ba4Schristos 	if (in_IT_block ())
903a1ba9ba4Schristos 	  S = 0;
904a1ba9ba4Schristos 
905a1ba9ba4Schristos 	if (S)
906a1ba9ba4Schristos 	  {
907a1ba9ba4Schristos 	    ARMul_NegZero (state, res);
908a1ba9ba4Schristos 
909a1ba9ba4Schristos 	    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
910a1ba9ba4Schristos 	      {
911a1ba9ba4Schristos 		ARMul_SubCarry (state, lhs, rhs, res);
912a1ba9ba4Schristos 		ARMul_SubOverflow (state, lhs, rhs, res);
913a1ba9ba4Schristos 	      }
914a1ba9ba4Schristos 	    else
915a1ba9ba4Schristos 	      {
916a1ba9ba4Schristos 		CLEARC;
917a1ba9ba4Schristos 		CLEARV;
918a1ba9ba4Schristos 	      }
919a1ba9ba4Schristos 	  }
920a1ba9ba4Schristos 
921a1ba9ba4Schristos 	* pvalid = t_branch;
922a1ba9ba4Schristos 	break;
923a1ba9ba4Schristos       }
924a1ba9ba4Schristos 
925a1ba9ba4Schristos     case 0xAD:
926a1ba9ba4Schristos     case 0x8D: // SUB
927a1ba9ba4Schristos       {
928a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
929a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
930a1ba9ba4Schristos 	int S = tBIT (4);
931a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
932a1ba9ba4Schristos 	ARMword lhs = state->Reg[Rn];
933a1ba9ba4Schristos 	ARMword rhs = ThumbExpandImm (imm12);
934a1ba9ba4Schristos 	ARMword res = lhs - rhs;
935a1ba9ba4Schristos 
936a1ba9ba4Schristos 	if (Rd == 15 && S)
937a1ba9ba4Schristos 	  {
938a1ba9ba4Schristos 	    // CMP<c>.W <Rn>,#<const>
939a1ba9ba4Schristos 	    tASSERT (S);
940a1ba9ba4Schristos 	  }
941a1ba9ba4Schristos 	else
942a1ba9ba4Schristos 	  {
943a1ba9ba4Schristos 	    // SUB{S}<c>.W <Rd>,<Rn>,#<const>
944a1ba9ba4Schristos 	    if (in_IT_block ())
945a1ba9ba4Schristos 	      S = 0;
946a1ba9ba4Schristos 
947a1ba9ba4Schristos 	    state->Reg[Rd] = res;
948a1ba9ba4Schristos 	  }
949a1ba9ba4Schristos 
950a1ba9ba4Schristos 	if (S)
951a1ba9ba4Schristos 	  {
952a1ba9ba4Schristos 	    ARMul_NegZero (state, res);
953a1ba9ba4Schristos 
954a1ba9ba4Schristos 	    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
955a1ba9ba4Schristos 	      {
956a1ba9ba4Schristos 		ARMul_SubCarry (state, lhs, rhs, res);
957a1ba9ba4Schristos 		ARMul_SubOverflow (state, lhs, rhs, res);
958a1ba9ba4Schristos 	      }
959a1ba9ba4Schristos 	    else
960a1ba9ba4Schristos 	      {
961a1ba9ba4Schristos 		CLEARC;
962a1ba9ba4Schristos 		CLEARV;
963a1ba9ba4Schristos 	      }
964a1ba9ba4Schristos 	  }
965a1ba9ba4Schristos 
966a1ba9ba4Schristos 	* pvalid = t_branch;
967a1ba9ba4Schristos 	break;
968a1ba9ba4Schristos       }
969a1ba9ba4Schristos 
970a1ba9ba4Schristos     case 0xAE:
971a1ba9ba4Schristos     case 0x8E: // RSB{S}<c>.W <Rd>,<Rn>,#<const>
972a1ba9ba4Schristos       {
973a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
974a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
975a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
976a1ba9ba4Schristos 	int S = tBIT (4);
977a1ba9ba4Schristos 	ARMword lhs = imm12;
978a1ba9ba4Schristos 	ARMword rhs = state->Reg[Rn];
979a1ba9ba4Schristos 	ARMword res = lhs - rhs;
980a1ba9ba4Schristos 
981a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
982a1ba9ba4Schristos 
983a1ba9ba4Schristos 	state->Reg[Rd] = res;
984a1ba9ba4Schristos 
985a1ba9ba4Schristos 	if (S)
986a1ba9ba4Schristos 	  {
987a1ba9ba4Schristos 	    ARMul_NegZero (state, res);
988a1ba9ba4Schristos 
989a1ba9ba4Schristos 	    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
990a1ba9ba4Schristos 	      {
991a1ba9ba4Schristos 		ARMul_SubCarry (state, lhs, rhs, res);
992a1ba9ba4Schristos 		ARMul_SubOverflow (state, lhs, rhs, res);
993a1ba9ba4Schristos 	      }
994a1ba9ba4Schristos 	    else
995a1ba9ba4Schristos 	      {
996a1ba9ba4Schristos 		CLEARC;
997a1ba9ba4Schristos 		CLEARV;
998a1ba9ba4Schristos 	      }
999a1ba9ba4Schristos 	  }
1000a1ba9ba4Schristos 
1001a1ba9ba4Schristos 	* pvalid = t_branch;
1002a1ba9ba4Schristos 	break;
1003a1ba9ba4Schristos       }
1004a1ba9ba4Schristos 
1005a1ba9ba4Schristos     case 0xB0:
1006a1ba9ba4Schristos     case 0x90: // ADDW<c> <Rd>,<Rn>,#<imm12>
1007a1ba9ba4Schristos       {
1008a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1009a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1010a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1011a1ba9ba4Schristos 
1012a1ba9ba4Schristos 	tASSERT (tBIT (4) == 0);
1013a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
1014a1ba9ba4Schristos 
1015a1ba9ba4Schristos 	state->Reg[Rd] = state->Reg[Rn] + imm12;
1016a1ba9ba4Schristos 	* pvalid = t_branch;
1017a1ba9ba4Schristos 	break;
1018a1ba9ba4Schristos       }
1019a1ba9ba4Schristos 
1020a1ba9ba4Schristos     case 0xB2:
1021a1ba9ba4Schristos     case 0x92: // MOVW<c> <Rd>,#<imm16>
1022a1ba9ba4Schristos       {
1023a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1024a1ba9ba4Schristos 	ARMword imm = (tBITS (0, 3) << 12) | (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1025a1ba9ba4Schristos 
1026a1ba9ba4Schristos 	state->Reg[Rd] = imm;
1027a1ba9ba4Schristos 	/* Indicate that the instruction has been processed.  */
1028a1ba9ba4Schristos 	* pvalid = t_branch;
1029a1ba9ba4Schristos 	break;
1030a1ba9ba4Schristos       }
1031a1ba9ba4Schristos 
1032a1ba9ba4Schristos     case 0xb5:
1033a1ba9ba4Schristos     case 0x95:// SUBW<c> <Rd>,<Rn>,#<imm12>
1034a1ba9ba4Schristos       {
1035a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1036a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1037a1ba9ba4Schristos 	ARMword imm12 = (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1038a1ba9ba4Schristos 
1039a1ba9ba4Schristos 	tASSERT (tBIT (4) == 0);
1040a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
1041a1ba9ba4Schristos 
1042a1ba9ba4Schristos 	/* Note the ARM ARM indicates special cases for Rn == 15 (ADR)
1043a1ba9ba4Schristos 	   and Rn == 13 (SUB SP minus immediate), but these are implemented
1044a1ba9ba4Schristos 	   in exactly the same way as the normal SUBW insn.  */
1045a1ba9ba4Schristos 	state->Reg[Rd] = state->Reg[Rn] - imm12;
1046a1ba9ba4Schristos 
1047a1ba9ba4Schristos 	* pvalid = t_resolved;
1048a1ba9ba4Schristos 	break;
1049a1ba9ba4Schristos       }
1050a1ba9ba4Schristos 
1051a1ba9ba4Schristos     case 0xB6:
1052a1ba9ba4Schristos     case 0x96: // MOVT<c> <Rd>,#<imm16>
1053a1ba9ba4Schristos       {
1054a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1055a1ba9ba4Schristos 	ARMword imm = (tBITS (0, 3) << 12) | (tBIT (10) << 11) | (ntBITS (12, 14) << 8) | ntBITS (0, 7);
1056a1ba9ba4Schristos 
1057a1ba9ba4Schristos 	state->Reg[Rd] &= 0xFFFF;
1058a1ba9ba4Schristos 	state->Reg[Rd] |= (imm << 16);
1059a1ba9ba4Schristos 	* pvalid = t_resolved;
1060a1ba9ba4Schristos 	break;
1061a1ba9ba4Schristos       }
1062a1ba9ba4Schristos 
1063a1ba9ba4Schristos     case 0x9A: // SBFXc> <Rd>,<Rn>,#<lsb>,#<width>
1064a1ba9ba4Schristos       tASSERT (tBIT (4) == 0);
1065a1ba9ba4Schristos       tASSERT (ntBIT (15) == 0);
1066a1ba9ba4Schristos       tASSERT (ntBIT (5) == 0);
1067a1ba9ba4Schristos       * ainstr = 0xE7A00050;
1068a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 4) << 16); // widthm1
1069a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 12); // Rd
1070a1ba9ba4Schristos       * ainstr |= (((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7); // lsb
1071a1ba9ba4Schristos       * ainstr |= tBITS (0, 3); // Rn
1072a1ba9ba4Schristos       * pvalid = t_decoded;
1073a1ba9ba4Schristos       break;
1074a1ba9ba4Schristos 
1075a1ba9ba4Schristos     case 0x9B:
1076a1ba9ba4Schristos       {
1077a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1078a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1079a1ba9ba4Schristos 	ARMword msbit = ntBITS (0, 5);
1080a1ba9ba4Schristos 	ARMword lsbit = (ntBITS (12, 14) << 2) | ntBITS (6, 7);
1081*b2396a7bSchristos 	ARMword mask = -(1 << lsbit);
1082a1ba9ba4Schristos 
1083a1ba9ba4Schristos 	tASSERT (tBIT (4) == 0);
1084a1ba9ba4Schristos 	tASSERT (ntBIT (15) == 0);
1085a1ba9ba4Schristos 	tASSERT (ntBIT (5) == 0);
1086a1ba9ba4Schristos 
1087a1ba9ba4Schristos 	mask &= ((1 << (msbit + 1)) - 1);
1088a1ba9ba4Schristos 
1089a1ba9ba4Schristos 	if (lsbit > msbit)
1090a1ba9ba4Schristos 	  ; // UNPREDICTABLE
1091a1ba9ba4Schristos 	else if (Rn == 15)
1092a1ba9ba4Schristos 	  {
1093a1ba9ba4Schristos 	    // BFC<c> <Rd>,#<lsb>,#<width>
1094a1ba9ba4Schristos 	    state->Reg[Rd] &= ~ mask;
1095a1ba9ba4Schristos 	  }
1096a1ba9ba4Schristos 	else
1097a1ba9ba4Schristos 	  {
1098a1ba9ba4Schristos 	    // BFI<c> <Rd>,<Rn>,#<lsb>,#<width>
1099a1ba9ba4Schristos 	    ARMword val = state->Reg[Rn] & (mask >> lsbit);
1100a1ba9ba4Schristos 
1101a1ba9ba4Schristos 	    val <<= lsbit;
1102a1ba9ba4Schristos 	    state->Reg[Rd] &= ~ mask;
1103a1ba9ba4Schristos 	    state->Reg[Rd] |= val;
1104a1ba9ba4Schristos 	  }
1105a1ba9ba4Schristos 
1106a1ba9ba4Schristos 	* pvalid = t_resolved;
1107a1ba9ba4Schristos 	break;
1108a1ba9ba4Schristos       }
1109a1ba9ba4Schristos 
1110a1ba9ba4Schristos     case 0x9E: // UBFXc> <Rd>,<Rn>,#<lsb>,#<width>
1111a1ba9ba4Schristos       tASSERT (tBIT (4) == 0);
1112a1ba9ba4Schristos       tASSERT (ntBIT (15) == 0);
1113a1ba9ba4Schristos       tASSERT (ntBIT (5) == 0);
1114a1ba9ba4Schristos       * ainstr = 0xE7E00050;
1115a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 4) << 16); // widthm1
1116a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 12); // Rd
1117a1ba9ba4Schristos       * ainstr |= (((ntBITS (12, 14) << 2) | ntBITS (6, 7)) << 7); // lsb
1118a1ba9ba4Schristos       * ainstr |= tBITS (0, 3); // Rn
1119a1ba9ba4Schristos       * pvalid = t_decoded;
1120a1ba9ba4Schristos       break;
1121a1ba9ba4Schristos 
1122a1ba9ba4Schristos     case 0xC0: // STRB
1123a1ba9ba4Schristos     case 0xC4: // LDRB
1124a1ba9ba4Schristos       {
1125a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1126a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1127a1ba9ba4Schristos 
1128a1ba9ba4Schristos 	if (tBIT (4))
1129a1ba9ba4Schristos 	  {
1130a1ba9ba4Schristos 	    if (Rn == 15)
1131a1ba9ba4Schristos 	      {
1132a1ba9ba4Schristos 		tASSERT (Rt != 15);
1133a1ba9ba4Schristos 
1134a1ba9ba4Schristos 		/* LDRB<c> <Rt>,<label>                     => 1111 1000 U001 1111 */
1135a1ba9ba4Schristos 		* ainstr = 0xE55F0000;
1136a1ba9ba4Schristos 		* ainstr |= (tBIT (7) << 23);
1137a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 11);
1138a1ba9ba4Schristos 	      }
1139a1ba9ba4Schristos 	    else if (tBIT (7))
1140a1ba9ba4Schristos 	      {
1141a1ba9ba4Schristos 		/* LDRB<c>.W <Rt>,[<Rn>{,#<imm12>}]         => 1111 1000 1001 rrrr */
1142a1ba9ba4Schristos 		* ainstr = 0xE5D00000;
1143a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 11);
1144a1ba9ba4Schristos 	      }
1145a1ba9ba4Schristos 	    else if (ntBIT (11) == 0)
1146a1ba9ba4Schristos 	      {
1147a1ba9ba4Schristos 		/* LDRB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}] => 1111 1000 0001 rrrr */
1148a1ba9ba4Schristos 		* ainstr = 0xE7D00000;
1149a1ba9ba4Schristos 		* ainstr |= (ntBITS (4, 5) << 7);
1150a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 3);
1151a1ba9ba4Schristos 	      }
1152a1ba9ba4Schristos 	    else
1153a1ba9ba4Schristos 	      {
1154a1ba9ba4Schristos 		int P = ntBIT (10);
1155a1ba9ba4Schristos 		int U = ntBIT (9);
1156a1ba9ba4Schristos 		int W = ntBIT (8);
1157a1ba9ba4Schristos 
1158a1ba9ba4Schristos 		tASSERT (! (Rt == 15 && P && !U && !W));
1159a1ba9ba4Schristos 		tASSERT (! (P && U && !W));
1160a1ba9ba4Schristos 
1161a1ba9ba4Schristos 		/* LDRB<c> <Rt>,[<Rn>,#-<imm8>]             => 1111 1000 0001 rrrr
1162a1ba9ba4Schristos 		   LDRB<c> <Rt>,[<Rn>],#+/-<imm8>           => 1111 1000 0001 rrrr
1163a1ba9ba4Schristos 		   LDRB<c> <Rt>,[<Rn>,#+/-<imm8>]!          => 1111 1000 0001 rrrr */
1164a1ba9ba4Schristos 		* ainstr = 0xE4500000;
1165a1ba9ba4Schristos 		* ainstr |= (P << 24);
1166a1ba9ba4Schristos 		* ainstr |= (U << 23);
1167a1ba9ba4Schristos 		* ainstr |= (W << 21);
1168a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 7);
1169a1ba9ba4Schristos 	      }
1170a1ba9ba4Schristos 	  }
1171a1ba9ba4Schristos 	else
1172a1ba9ba4Schristos 	  {
1173a1ba9ba4Schristos 	    if (tBIT (7) == 1)
1174a1ba9ba4Schristos 	      {
1175a1ba9ba4Schristos 		// STRB<c>.W <Rt>,[<Rn>,#<imm12>]
1176a1ba9ba4Schristos 		ARMword imm12 = ntBITS (0, 11);
1177a1ba9ba4Schristos 
1178a1ba9ba4Schristos 		ARMul_StoreByte (state, state->Reg[Rn] + imm12, state->Reg [Rt]);
1179a1ba9ba4Schristos 		* pvalid = t_branch;
1180a1ba9ba4Schristos 		break;
1181a1ba9ba4Schristos 	      }
1182a1ba9ba4Schristos 	    else if (ntBIT (11))
1183a1ba9ba4Schristos 	      {
1184a1ba9ba4Schristos 		// STRB<c> <Rt>,[<Rn>,#-<imm8>]
1185a1ba9ba4Schristos 		// STRB<c> <Rt>,[<Rn>],#+/-<imm8>
1186a1ba9ba4Schristos 		// STRB<c> <Rt>,[<Rn>,#+/-<imm8>]!
1187a1ba9ba4Schristos 		int P = ntBIT (10);
1188a1ba9ba4Schristos 		int U = ntBIT (9);
1189a1ba9ba4Schristos 		int W = ntBIT (8);
1190a1ba9ba4Schristos 		ARMword imm8 = ntBITS (0, 7);
1191a1ba9ba4Schristos 
1192a1ba9ba4Schristos 		tASSERT (! (P && U && !W));
1193a1ba9ba4Schristos 		tASSERT (! (Rn == 13 && P && !U && W && imm8 == 4));
1194a1ba9ba4Schristos 
1195a1ba9ba4Schristos 		* ainstr = 0xE4000000;
1196a1ba9ba4Schristos 		* ainstr |= (P << 24);
1197a1ba9ba4Schristos 		* ainstr |= (U << 23);
1198a1ba9ba4Schristos 		* ainstr |= (W << 21);
1199a1ba9ba4Schristos 		* ainstr |= imm8;
1200a1ba9ba4Schristos 	      }
1201a1ba9ba4Schristos 	    else
1202a1ba9ba4Schristos 	      {
1203a1ba9ba4Schristos 		// STRB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1204a1ba9ba4Schristos 		tASSERT (ntBITS (6, 11) == 0);
1205a1ba9ba4Schristos 
1206a1ba9ba4Schristos 		* ainstr = 0xE7C00000;
1207a1ba9ba4Schristos 		* ainstr |= (ntBITS (4, 5) << 7);
1208a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 3);
1209a1ba9ba4Schristos 	      }
1210a1ba9ba4Schristos 	  }
1211a1ba9ba4Schristos 
1212a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
1213a1ba9ba4Schristos 	* ainstr |= (Rt << 12);
1214a1ba9ba4Schristos 	* pvalid = t_decoded;
1215a1ba9ba4Schristos 	break;
1216a1ba9ba4Schristos       }
1217a1ba9ba4Schristos 
1218a1ba9ba4Schristos     case 0xC2: // LDR, STR
1219a1ba9ba4Schristos       {
1220a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1221a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1222a1ba9ba4Schristos 	ARMword imm8 = ntBITS (0, 7);
1223a1ba9ba4Schristos 	ARMword P = ntBIT (10);
1224a1ba9ba4Schristos 	ARMword U = ntBIT (9);
1225a1ba9ba4Schristos 	ARMword W = ntBIT (8);
1226a1ba9ba4Schristos 
1227a1ba9ba4Schristos 	tASSERT (Rn != 15);
1228a1ba9ba4Schristos 
1229a1ba9ba4Schristos 	if (tBIT (4))
1230a1ba9ba4Schristos 	  {
1231a1ba9ba4Schristos 	    if (Rn == 15)
1232a1ba9ba4Schristos 	      {
1233a1ba9ba4Schristos 		// LDR<c>.W <Rt>,<label>
1234a1ba9ba4Schristos 		* ainstr = 0xE51F0000;
1235a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 11);
1236a1ba9ba4Schristos 	      }
1237a1ba9ba4Schristos 	    else if (ntBIT (11))
1238a1ba9ba4Schristos 	      {
1239a1ba9ba4Schristos 		tASSERT (! (P && U && ! W));
1240a1ba9ba4Schristos 		tASSERT (! (!P && U && W && Rn == 13 && imm8 == 4 && ntBIT (11) == 0));
1241a1ba9ba4Schristos 		tASSERT (! (P && !U && W && Rn == 13 && imm8 == 4 && ntBIT (11)));
1242a1ba9ba4Schristos 
1243a1ba9ba4Schristos 		// LDR<c> <Rt>,[<Rn>,#-<imm8>]
1244a1ba9ba4Schristos 		// LDR<c> <Rt>,[<Rn>],#+/-<imm8>
1245a1ba9ba4Schristos 		// LDR<c> <Rt>,[<Rn>,#+/-<imm8>]!
1246a1ba9ba4Schristos 		if (!P && W)
1247a1ba9ba4Schristos 		  W = 0;
1248a1ba9ba4Schristos 		* ainstr = 0xE4100000;
1249a1ba9ba4Schristos 		* ainstr |= (P << 24);
1250a1ba9ba4Schristos 		* ainstr |= (U << 23);
1251a1ba9ba4Schristos 		* ainstr |= (W << 21);
1252a1ba9ba4Schristos 		* ainstr |= imm8;
1253a1ba9ba4Schristos 	      }
1254a1ba9ba4Schristos 	    else
1255a1ba9ba4Schristos 	      {
1256a1ba9ba4Schristos 		// LDR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1257a1ba9ba4Schristos 
1258a1ba9ba4Schristos 		tASSERT (ntBITS (6, 11) == 0);
1259a1ba9ba4Schristos 
1260a1ba9ba4Schristos 		* ainstr = 0xE7900000;
1261a1ba9ba4Schristos 		* ainstr |= ntBITS (4, 5) << 7;
1262a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 3);
1263a1ba9ba4Schristos 	      }
1264a1ba9ba4Schristos 	  }
1265a1ba9ba4Schristos 	else
1266a1ba9ba4Schristos 	  {
1267a1ba9ba4Schristos 	    if (ntBIT (11))
1268a1ba9ba4Schristos 	      {
1269a1ba9ba4Schristos 		tASSERT (! (P && U && ! W));
1270a1ba9ba4Schristos 		if (Rn == 13 && P && !U && W && imm8 == 4)
1271a1ba9ba4Schristos 		  {
1272a1ba9ba4Schristos 		    // PUSH<c>.W <register>
1273a1ba9ba4Schristos 		    tASSERT (ntBITS (0, 11) == 0xD04);
1274a1ba9ba4Schristos 		    tASSERT (tBITS (0, 4) == 0x0D);
1275a1ba9ba4Schristos 
1276a1ba9ba4Schristos 		    * ainstr = 0xE92D0000;
1277a1ba9ba4Schristos 		    * ainstr |= (1 << Rt);
1278a1ba9ba4Schristos 
1279a1ba9ba4Schristos 		    Rt = Rn = 0;
1280a1ba9ba4Schristos 		  }
1281a1ba9ba4Schristos 		else
1282a1ba9ba4Schristos 		  {
1283a1ba9ba4Schristos 		    tASSERT (! (P && U && !W));
1284a1ba9ba4Schristos 		    if (!P && W)
1285a1ba9ba4Schristos 		      W = 0;
1286a1ba9ba4Schristos 		    // STR<c> <Rt>,[<Rn>,#-<imm8>]
1287a1ba9ba4Schristos 		    // STR<c> <Rt>,[<Rn>],#+/-<imm8>
1288a1ba9ba4Schristos 		    // STR<c> <Rt>,[<Rn>,#+/-<imm8>]!
1289a1ba9ba4Schristos 		    * ainstr = 0xE4000000;
1290a1ba9ba4Schristos 		    * ainstr |= (P << 24);
1291a1ba9ba4Schristos 		    * ainstr |= (U << 23);
1292a1ba9ba4Schristos 		    * ainstr |= (W << 21);
1293a1ba9ba4Schristos 		    * ainstr |= imm8;
1294a1ba9ba4Schristos 		  }
1295a1ba9ba4Schristos 	      }
1296a1ba9ba4Schristos 	    else
1297a1ba9ba4Schristos 	      {
1298a1ba9ba4Schristos 		// STR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1299a1ba9ba4Schristos 		tASSERT (ntBITS (6, 11) == 0);
1300a1ba9ba4Schristos 
1301a1ba9ba4Schristos 		* ainstr = 0xE7800000;
1302a1ba9ba4Schristos 		* ainstr |= ntBITS (4, 5) << 7;
1303a1ba9ba4Schristos 		* ainstr |= ntBITS (0, 3);
1304a1ba9ba4Schristos 	      }
1305a1ba9ba4Schristos 	  }
1306a1ba9ba4Schristos 
1307a1ba9ba4Schristos 	* ainstr |= (Rn << 16);
1308a1ba9ba4Schristos 	* ainstr |= (Rt << 12);
1309a1ba9ba4Schristos 	* pvalid = t_decoded;
1310a1ba9ba4Schristos 	break;
1311a1ba9ba4Schristos       }
1312a1ba9ba4Schristos 
1313a1ba9ba4Schristos     case 0xC1: // STRH
1314a1ba9ba4Schristos     case 0xC5: // LDRH
1315a1ba9ba4Schristos       {
1316a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1317a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1318a1ba9ba4Schristos 	ARMword address;
1319a1ba9ba4Schristos 
1320a1ba9ba4Schristos 	tASSERT (Rn != 15);
1321a1ba9ba4Schristos 
1322a1ba9ba4Schristos 	if (tBIT (4) == 1)
1323a1ba9ba4Schristos 	  {
1324a1ba9ba4Schristos 	    if (tBIT (7))
1325a1ba9ba4Schristos 	      {
1326a1ba9ba4Schristos 		// LDRH<c>.W <Rt>,[<Rn>{,#<imm12>}]
1327a1ba9ba4Schristos 		ARMword imm12 = ntBITS (0, 11);
1328a1ba9ba4Schristos 		address = state->Reg[Rn] + imm12;
1329a1ba9ba4Schristos 	      }
1330a1ba9ba4Schristos 	    else if (ntBIT (11))
1331a1ba9ba4Schristos 	      {
1332a1ba9ba4Schristos 		// LDRH<c> <Rt>,[<Rn>,#-<imm8>]
1333a1ba9ba4Schristos 		// LDRH<c> <Rt>,[<Rn>],#+/-<imm8>
1334a1ba9ba4Schristos 		// LDRH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1335a1ba9ba4Schristos 		ARMword P = ntBIT (10);
1336a1ba9ba4Schristos 		ARMword U = ntBIT (9);
1337a1ba9ba4Schristos 		ARMword W = ntBIT (8);
1338a1ba9ba4Schristos 		ARMword imm8 = ntBITS (0, 7);
1339a1ba9ba4Schristos 
1340a1ba9ba4Schristos 		tASSERT (Rn != 15);
1341a1ba9ba4Schristos 		tASSERT (! (P && U && !W));
1342a1ba9ba4Schristos 
1343a1ba9ba4Schristos 		* ainstr = 0xE05000B0;
1344a1ba9ba4Schristos 		* ainstr |= (P << 24);
1345a1ba9ba4Schristos 		* ainstr |= (U << 23);
1346a1ba9ba4Schristos 		* ainstr |= (W << 21);
1347a1ba9ba4Schristos 		* ainstr |= (Rn << 16);
1348a1ba9ba4Schristos 		* ainstr |= (Rt << 12);
1349a1ba9ba4Schristos 		* ainstr |= ((imm8 & 0xF0) << 4);
1350a1ba9ba4Schristos 		* ainstr |= (imm8 & 0xF);
1351a1ba9ba4Schristos 		* pvalid = t_decoded;
1352a1ba9ba4Schristos 		break;
1353a1ba9ba4Schristos 	      }
1354a1ba9ba4Schristos 	    else
1355a1ba9ba4Schristos 	      {
1356a1ba9ba4Schristos 		// LDRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1357a1ba9ba4Schristos 		ARMword Rm = ntBITS (0, 3);
1358a1ba9ba4Schristos 		ARMword imm2 = ntBITS (4, 5);
1359a1ba9ba4Schristos 
1360a1ba9ba4Schristos 		tASSERT (ntBITS (6, 10) == 0);
1361a1ba9ba4Schristos 
1362a1ba9ba4Schristos 		address = state->Reg[Rn] + (state->Reg[Rm] << imm2);
1363a1ba9ba4Schristos 	      }
1364a1ba9ba4Schristos 
1365a1ba9ba4Schristos 	    state->Reg[Rt] = ARMul_LoadHalfWord (state, address);
1366a1ba9ba4Schristos 	  }
1367a1ba9ba4Schristos 	else
1368a1ba9ba4Schristos 	  {
1369a1ba9ba4Schristos 	    if (tBIT (7))
1370a1ba9ba4Schristos 	      {
1371a1ba9ba4Schristos 		// STRH<c>.W <Rt>,[<Rn>{,#<imm12>}]
1372a1ba9ba4Schristos 		ARMword imm12 = ntBITS (0, 11);
1373a1ba9ba4Schristos 
1374a1ba9ba4Schristos 		address = state->Reg[Rn] + imm12;
1375a1ba9ba4Schristos 	      }
1376a1ba9ba4Schristos 	    else if (ntBIT (11))
1377a1ba9ba4Schristos 	      {
1378a1ba9ba4Schristos 		// STRH<c> <Rt>,[<Rn>,#-<imm8>]
1379a1ba9ba4Schristos 		// STRH<c> <Rt>,[<Rn>],#+/-<imm8>
1380a1ba9ba4Schristos 		// STRH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1381a1ba9ba4Schristos 		ARMword P = ntBIT (10);
1382a1ba9ba4Schristos 		ARMword U = ntBIT (9);
1383a1ba9ba4Schristos 		ARMword W = ntBIT (8);
1384a1ba9ba4Schristos 		ARMword imm8 = ntBITS (0, 7);
1385a1ba9ba4Schristos 
1386a1ba9ba4Schristos 		tASSERT (! (P && U && !W));
1387a1ba9ba4Schristos 
1388a1ba9ba4Schristos 		* ainstr = 0xE04000B0;
1389a1ba9ba4Schristos 		* ainstr |= (P << 24);
1390a1ba9ba4Schristos 		* ainstr |= (U << 23);
1391a1ba9ba4Schristos 		* ainstr |= (W << 21);
1392a1ba9ba4Schristos 		* ainstr |= (Rn << 16);
1393a1ba9ba4Schristos 		* ainstr |= (Rt << 12);
1394a1ba9ba4Schristos 		* ainstr |= ((imm8 & 0xF0) << 4);
1395a1ba9ba4Schristos 		* ainstr |= (imm8 & 0xF);
1396a1ba9ba4Schristos 		* pvalid = t_decoded;
1397a1ba9ba4Schristos 		break;
1398a1ba9ba4Schristos 	      }
1399a1ba9ba4Schristos 	    else
1400a1ba9ba4Schristos 	      {
1401a1ba9ba4Schristos 		// STRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1402a1ba9ba4Schristos 		ARMword Rm = ntBITS (0, 3);
1403a1ba9ba4Schristos 		ARMword imm2 = ntBITS (4, 5);
1404a1ba9ba4Schristos 
1405a1ba9ba4Schristos 		tASSERT (ntBITS (6, 10) == 0);
1406a1ba9ba4Schristos 
1407a1ba9ba4Schristos 		address = state->Reg[Rn] + (state->Reg[Rm] << imm2);
1408a1ba9ba4Schristos 	      }
1409a1ba9ba4Schristos 
1410a1ba9ba4Schristos 	    ARMul_StoreHalfWord (state, address, state->Reg [Rt]);
1411a1ba9ba4Schristos 	  }
1412a1ba9ba4Schristos 	* pvalid = t_branch;
1413a1ba9ba4Schristos 	break;
1414a1ba9ba4Schristos       }
1415a1ba9ba4Schristos 
1416a1ba9ba4Schristos     case 0xC6: // LDR.W/STR.W
1417a1ba9ba4Schristos       {
1418a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1419a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1420a1ba9ba4Schristos 	ARMword imm12 = ntBITS (0, 11);
1421a1ba9ba4Schristos 	ARMword address = state->Reg[Rn];
1422a1ba9ba4Schristos 
1423a1ba9ba4Schristos 	if (Rn == 15)
1424a1ba9ba4Schristos 	  {
1425a1ba9ba4Schristos 	    // LDR<c>.W <Rt>,<label>
1426a1ba9ba4Schristos 	    tASSERT (tBIT (4) == 1);
1427a1ba9ba4Schristos 	    // tASSERT (tBIT (7) == 1)
1428a1ba9ba4Schristos 	  }
1429a1ba9ba4Schristos 
1430a1ba9ba4Schristos 	address += imm12;
1431a1ba9ba4Schristos 	if (tBIT (4) == 1)
1432a1ba9ba4Schristos 	  state->Reg[Rt] = ARMul_LoadWordN (state, address);
1433a1ba9ba4Schristos 	else
1434a1ba9ba4Schristos 	  ARMul_StoreWordN (state, address, state->Reg [Rt]);
1435a1ba9ba4Schristos 
1436a1ba9ba4Schristos 	* pvalid = t_resolved;
1437a1ba9ba4Schristos 	break;
1438a1ba9ba4Schristos       }
1439a1ba9ba4Schristos 
1440a1ba9ba4Schristos     case 0xC8:
1441a1ba9ba4Schristos     case 0xCC: // LDRSB
1442a1ba9ba4Schristos       {
1443a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1444a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1445a1ba9ba4Schristos 	ARMword U = tBIT (7);
1446a1ba9ba4Schristos 	ARMword address = state->Reg[Rn];
1447a1ba9ba4Schristos 
1448a1ba9ba4Schristos 	tASSERT (tBIT (4) == 1);
1449a1ba9ba4Schristos 	tASSERT (Rt != 15); // PLI
1450a1ba9ba4Schristos 
1451a1ba9ba4Schristos 	if (Rn == 15)
1452a1ba9ba4Schristos 	  {
1453a1ba9ba4Schristos 	    // LDRSB<c> <Rt>,<label>
1454a1ba9ba4Schristos 	    ARMword imm12 = ntBITS (0, 11);
1455a1ba9ba4Schristos 	    address += (U ? imm12 : - imm12);
1456a1ba9ba4Schristos 	  }
1457a1ba9ba4Schristos 	else if (U)
1458a1ba9ba4Schristos 	  {
1459a1ba9ba4Schristos 	    // LDRSB<c> <Rt>,[<Rn>,#<imm12>]
1460a1ba9ba4Schristos 	    ARMword imm12 = ntBITS (0, 11);
1461a1ba9ba4Schristos 	    address += imm12;
1462a1ba9ba4Schristos 	  }
1463a1ba9ba4Schristos 	else if (ntBIT (11))
1464a1ba9ba4Schristos 	  {
1465a1ba9ba4Schristos 	    // LDRSB<c> <Rt>,[<Rn>,#-<imm8>]
1466a1ba9ba4Schristos 	    // LDRSB<c> <Rt>,[<Rn>],#+/-<imm8>
1467a1ba9ba4Schristos 	    // LDRSB<c> <Rt>,[<Rn>,#+/-<imm8>]!
1468a1ba9ba4Schristos 	    * ainstr = 0xE05000D0;
1469a1ba9ba4Schristos 	    * ainstr |= ntBIT (10) << 24; // P
1470a1ba9ba4Schristos 	    * ainstr |= ntBIT (9) << 23; // U
1471a1ba9ba4Schristos 	    * ainstr |= ntBIT (8) << 21; // W
1472a1ba9ba4Schristos 	    * ainstr |= Rn << 16;
1473a1ba9ba4Schristos 	    * ainstr |= Rt << 12;
1474a1ba9ba4Schristos 	    * ainstr |= ntBITS (4, 7) << 8;
1475a1ba9ba4Schristos 	    * ainstr |= ntBITS (0, 3);
1476a1ba9ba4Schristos 	    * pvalid = t_decoded;
1477a1ba9ba4Schristos 	    break;
1478a1ba9ba4Schristos 	  }
1479a1ba9ba4Schristos 	else
1480a1ba9ba4Schristos 	  {
1481a1ba9ba4Schristos 	    // LDRSB<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1482a1ba9ba4Schristos 	    ARMword Rm = ntBITS (0, 3);
1483a1ba9ba4Schristos 	    ARMword imm2 = ntBITS (4,5);
1484a1ba9ba4Schristos 
1485a1ba9ba4Schristos 	    tASSERT (ntBITS (6, 11) == 0);
1486a1ba9ba4Schristos 
1487a1ba9ba4Schristos 	    address += (state->Reg[Rm] << imm2);
1488a1ba9ba4Schristos 	  }
1489a1ba9ba4Schristos 
1490a1ba9ba4Schristos 	state->Reg[Rt] = ARMul_LoadByte (state, address);
1491a1ba9ba4Schristos 	if (state->Reg[Rt] & 0x80)
1492*b2396a7bSchristos 	  state->Reg[Rt] |= -(1 << 8);
1493a1ba9ba4Schristos 
1494a1ba9ba4Schristos 	* pvalid = t_resolved;
1495a1ba9ba4Schristos 	break;
1496a1ba9ba4Schristos       }
1497a1ba9ba4Schristos 
1498a1ba9ba4Schristos     case 0xC9:
1499a1ba9ba4Schristos     case 0xCD:// LDRSH
1500a1ba9ba4Schristos       {
1501a1ba9ba4Schristos 	ARMword Rt = ntBITS (12, 15);
1502a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1503a1ba9ba4Schristos 	ARMword U = tBIT (7);
1504a1ba9ba4Schristos 	ARMword address = state->Reg[Rn];
1505a1ba9ba4Schristos 
1506a1ba9ba4Schristos 	tASSERT (tBIT (4) == 1);
1507a1ba9ba4Schristos 
1508a1ba9ba4Schristos 	if (Rn == 15 || U == 1)
1509a1ba9ba4Schristos 	  {
1510a1ba9ba4Schristos 	    // Rn==15 => LDRSH<c> <Rt>,<label>
1511a1ba9ba4Schristos 	    // Rn!=15 => LDRSH<c> <Rt>,[<Rn>,#<imm12>]
1512a1ba9ba4Schristos 	    ARMword imm12 = ntBITS (0, 11);
1513a1ba9ba4Schristos 
1514a1ba9ba4Schristos 	    address += (U ? imm12 : - imm12);
1515a1ba9ba4Schristos 	  }
1516a1ba9ba4Schristos 	else if (ntBIT (11))
1517a1ba9ba4Schristos 	  {
1518a1ba9ba4Schristos 	    // LDRSH<c> <Rt>,[<Rn>,#-<imm8>]
1519a1ba9ba4Schristos 	    // LDRSH<c> <Rt>,[<Rn>],#+/-<imm8>
1520a1ba9ba4Schristos 	    // LDRSH<c> <Rt>,[<Rn>,#+/-<imm8>]!
1521a1ba9ba4Schristos 	    * ainstr = 0xE05000F0;
1522a1ba9ba4Schristos 	    * ainstr |= ntBIT (10) << 24; // P
1523a1ba9ba4Schristos 	    * ainstr |= ntBIT (9) << 23; // U
1524a1ba9ba4Schristos 	    * ainstr |= ntBIT (8) << 21; // W
1525a1ba9ba4Schristos 	    * ainstr |= Rn << 16;
1526a1ba9ba4Schristos 	    * ainstr |= Rt << 12;
1527a1ba9ba4Schristos 	    * ainstr |= ntBITS (4, 7) << 8;
1528a1ba9ba4Schristos 	    * ainstr |= ntBITS (0, 3);
1529a1ba9ba4Schristos 	    * pvalid = t_decoded;
1530a1ba9ba4Schristos 	    break;
1531a1ba9ba4Schristos 	  }
1532a1ba9ba4Schristos 	else /* U == 0 */
1533a1ba9ba4Schristos 	  {
1534a1ba9ba4Schristos 	    // LDRSH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]
1535a1ba9ba4Schristos 	    ARMword Rm = ntBITS (0, 3);
1536a1ba9ba4Schristos 	    ARMword imm2 = ntBITS (4,5);
1537a1ba9ba4Schristos 
1538a1ba9ba4Schristos 	    tASSERT (ntBITS (6, 11) == 0);
1539a1ba9ba4Schristos 
1540a1ba9ba4Schristos 	    address += (state->Reg[Rm] << imm2);
1541a1ba9ba4Schristos 	  }
1542a1ba9ba4Schristos 
1543a1ba9ba4Schristos 	state->Reg[Rt] = ARMul_LoadHalfWord (state, address);
1544a1ba9ba4Schristos 	if (state->Reg[Rt] & 0x8000)
1545*b2396a7bSchristos 	  state->Reg[Rt] |= -(1 << 16);
1546a1ba9ba4Schristos 
1547a1ba9ba4Schristos 	* pvalid = t_branch;
1548a1ba9ba4Schristos 	break;
1549a1ba9ba4Schristos       }
1550a1ba9ba4Schristos 
1551a1ba9ba4Schristos     case 0x0D0:
1552a1ba9ba4Schristos       {
1553a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
1554a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1555a1ba9ba4Schristos 
1556a1ba9ba4Schristos 	tASSERT (ntBITS (12, 15) == 15);
1557a1ba9ba4Schristos 
1558a1ba9ba4Schristos 	if (ntBIT (7) == 1)
1559a1ba9ba4Schristos 	  {
1560a1ba9ba4Schristos 	    // SXTH<c>.W <Rd>,<Rm>{,<rotation>}
1561a1ba9ba4Schristos 	    ARMword ror = ntBITS (4, 5) << 3;
1562a1ba9ba4Schristos 	    ARMword val;
1563a1ba9ba4Schristos 
1564a1ba9ba4Schristos 	    val = state->Reg[Rm];
1565a1ba9ba4Schristos 	    val = (val >> ror) | (val << (32 - ror));
1566a1ba9ba4Schristos 	    if (val & 0x8000)
1567*b2396a7bSchristos 	      val |= -(1 << 16);
1568a1ba9ba4Schristos 	    state->Reg[Rd] = val;
1569a1ba9ba4Schristos 	  }
1570a1ba9ba4Schristos 	else
1571a1ba9ba4Schristos 	  {
1572a1ba9ba4Schristos 	    // LSL{S}<c>.W <Rd>,<Rn>,<Rm>
1573a1ba9ba4Schristos 	    ARMword Rn = tBITS (0, 3);
1574a1ba9ba4Schristos 
1575a1ba9ba4Schristos 	    tASSERT (ntBITS (4, 6) == 0);
1576a1ba9ba4Schristos 
1577a1ba9ba4Schristos 	    state->Reg[Rd] = state->Reg[Rn] << (state->Reg[Rm] & 0xFF);
1578a1ba9ba4Schristos 	    if (tBIT (4))
1579a1ba9ba4Schristos 	      ARMul_NegZero (state, state->Reg[Rd]);
1580a1ba9ba4Schristos 	  }
1581a1ba9ba4Schristos 	* pvalid = t_branch;
1582a1ba9ba4Schristos 	break;
1583a1ba9ba4Schristos       }
1584a1ba9ba4Schristos 
1585a1ba9ba4Schristos     case 0x0D1: // LSR{S}<c>.W <Rd>,<Rn>,<Rm>
1586a1ba9ba4Schristos       {
1587a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1588a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1589a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
1590a1ba9ba4Schristos 
1591a1ba9ba4Schristos 	tASSERT (ntBITS (12, 15) == 15);
1592a1ba9ba4Schristos 	tASSERT (ntBITS (4, 7) == 0);
1593a1ba9ba4Schristos 
1594a1ba9ba4Schristos 	state->Reg[Rd] = state->Reg[Rn] >> (state->Reg[Rm] & 0xFF);
1595a1ba9ba4Schristos 	if (tBIT (4))
1596a1ba9ba4Schristos 	  ARMul_NegZero (state, state->Reg[Rd]);
1597a1ba9ba4Schristos 	* pvalid = t_resolved;
1598a1ba9ba4Schristos 	break;
1599a1ba9ba4Schristos       }
1600a1ba9ba4Schristos 
1601a1ba9ba4Schristos     case 0xD2:
1602a1ba9ba4Schristos       tASSERT (ntBITS (12, 15) == 15);
1603a1ba9ba4Schristos       if (ntBIT (7))
1604a1ba9ba4Schristos 	{
1605a1ba9ba4Schristos 	  tASSERT (ntBIT (6) == 0);
1606a1ba9ba4Schristos 	  // UXTB<c>.W <Rd>,<Rm>{,<rotation>}
1607a1ba9ba4Schristos 	  * ainstr = 0xE6EF0070;
1608a1ba9ba4Schristos 	  * ainstr |= (ntBITS (4, 5) << 10); // rotate
1609a1ba9ba4Schristos 	  * ainstr |= ntBITS (0, 3); // Rm
1610a1ba9ba4Schristos 	}
1611a1ba9ba4Schristos       else
1612a1ba9ba4Schristos 	{
1613a1ba9ba4Schristos 	  // ASR{S}<c>.W <Rd>,<Rn>,<Rm>
1614a1ba9ba4Schristos 	  tASSERT (ntBITS (4, 7) == 0);
1615a1ba9ba4Schristos 	  * ainstr = 0xE1A00050;
1616a1ba9ba4Schristos 	  if (! in_IT_block ())
1617a1ba9ba4Schristos 	    * ainstr |= (tBIT (4) << 20);
1618a1ba9ba4Schristos 	  * ainstr |= (ntBITS (0, 3) << 8); // Rm
1619a1ba9ba4Schristos 	  * ainstr |= tBITS (0, 3); // Rn
1620a1ba9ba4Schristos 	}
1621a1ba9ba4Schristos 
1622a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 12); // Rd
1623a1ba9ba4Schristos       * pvalid = t_decoded;
1624a1ba9ba4Schristos       break;
1625a1ba9ba4Schristos 
1626a1ba9ba4Schristos     case 0xD3: // ROR{S}<c>.W <Rd>,<Rn>,<Rm>
1627a1ba9ba4Schristos       tASSERT (ntBITS (12, 15) == 15);
1628a1ba9ba4Schristos       tASSERT (ntBITS (4, 7) == 0);
1629a1ba9ba4Schristos       * ainstr = 0xE1A00070;
1630a1ba9ba4Schristos       if (! in_IT_block ())
1631a1ba9ba4Schristos 	* ainstr |= (tBIT (4) << 20);
1632a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 12); // Rd
1633a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 3) << 8); // Rm
1634a1ba9ba4Schristos       * ainstr |= (tBITS (0, 3) << 0); // Rn
1635a1ba9ba4Schristos       * pvalid = t_decoded;
1636a1ba9ba4Schristos       break;
1637a1ba9ba4Schristos 
1638a1ba9ba4Schristos     case 0xD4:
1639a1ba9ba4Schristos       {
1640a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1641a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1642a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
1643a1ba9ba4Schristos 
1644a1ba9ba4Schristos 	tASSERT (ntBITS (12, 15) == 15);
1645a1ba9ba4Schristos 
1646a1ba9ba4Schristos 	if (ntBITS (4, 7) == 8)
1647a1ba9ba4Schristos 	  {
1648a1ba9ba4Schristos 	    // REV<c>.W <Rd>,<Rm>
1649a1ba9ba4Schristos 	    ARMword val = state->Reg[Rm];
1650a1ba9ba4Schristos 
1651a1ba9ba4Schristos 	    tASSERT (Rm == Rn);
1652a1ba9ba4Schristos 
1653a1ba9ba4Schristos 	    state->Reg [Rd] =
1654a1ba9ba4Schristos 	      (val >> 24)
1655a1ba9ba4Schristos 	      | ((val >> 8) & 0xFF00)
1656a1ba9ba4Schristos 	      | ((val << 8) & 0xFF0000)
1657a1ba9ba4Schristos 	      | (val << 24);
1658a1ba9ba4Schristos 	    * pvalid = t_resolved;
1659a1ba9ba4Schristos 	  }
1660a1ba9ba4Schristos 	else
1661a1ba9ba4Schristos 	  {
1662a1ba9ba4Schristos 	    tASSERT (ntBITS (4, 7) == 4);
1663a1ba9ba4Schristos 
1664a1ba9ba4Schristos 	    if (tBIT (4) == 1)
1665a1ba9ba4Schristos 	       // UADD8<c> <Rd>,<Rn>,<Rm>
1666a1ba9ba4Schristos 	      * ainstr = 0xE6500F10;
1667a1ba9ba4Schristos 	    else
1668a1ba9ba4Schristos 	      // UADD16<c> <Rd>,<Rn>,<Rm>
1669a1ba9ba4Schristos 	      * ainstr = 0xE6500F90;
1670a1ba9ba4Schristos 
1671a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
1672a1ba9ba4Schristos 	    * ainstr |= (Rd << 12);
1673a1ba9ba4Schristos 	    * ainstr |= (Rm <<  0);
1674a1ba9ba4Schristos 	    * pvalid = t_decoded;
1675a1ba9ba4Schristos 	  }
1676a1ba9ba4Schristos 	break;
1677a1ba9ba4Schristos       }
1678a1ba9ba4Schristos 
1679a1ba9ba4Schristos     case 0xD5:
1680a1ba9ba4Schristos       {
1681a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1682a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1683a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
1684a1ba9ba4Schristos 
1685a1ba9ba4Schristos 	tASSERT (ntBITS (12, 15) == 15);
1686a1ba9ba4Schristos 	tASSERT (ntBITS (4, 7) == 8);
1687a1ba9ba4Schristos 
1688a1ba9ba4Schristos 	if (tBIT (4))
1689a1ba9ba4Schristos 	  {
1690a1ba9ba4Schristos 	    // CLZ<c> <Rd>,<Rm>
1691a1ba9ba4Schristos 	    tASSERT (Rm == Rn);
1692a1ba9ba4Schristos 	    * ainstr = 0xE16F0F10;
1693a1ba9ba4Schristos 	  }
1694a1ba9ba4Schristos 	else
1695a1ba9ba4Schristos 	  {
1696a1ba9ba4Schristos 	     // SEL<c> <Rd>,<Rn>,<Rm>
1697a1ba9ba4Schristos 	    * ainstr = 0xE6800FB0;
1698a1ba9ba4Schristos 	    * ainstr |= (Rn << 16);
1699a1ba9ba4Schristos 	  }
1700a1ba9ba4Schristos 
1701a1ba9ba4Schristos 	* ainstr |= (Rd << 12);
1702a1ba9ba4Schristos 	* ainstr |= (Rm <<  0);
1703a1ba9ba4Schristos 	* pvalid = t_decoded;
1704a1ba9ba4Schristos 	break;
1705a1ba9ba4Schristos       }
1706a1ba9ba4Schristos 
1707a1ba9ba4Schristos     case 0xD8: // MUL
1708a1ba9ba4Schristos       {
1709a1ba9ba4Schristos 	ARMword Rn = tBITS (0, 3);
1710a1ba9ba4Schristos 	ARMword Rm = ntBITS (0, 3);
1711a1ba9ba4Schristos 	ARMword Rd = ntBITS (8, 11);
1712a1ba9ba4Schristos 	ARMword Ra = ntBITS (12, 15);
1713a1ba9ba4Schristos 
1714a1ba9ba4Schristos 	if (tBIT (4))
1715a1ba9ba4Schristos 	  {
1716a1ba9ba4Schristos 	    // SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra>
1717a1ba9ba4Schristos 	    ARMword nval = state->Reg[Rn];
1718a1ba9ba4Schristos 	    ARMword mval = state->Reg[Rm];
1719a1ba9ba4Schristos 	    ARMword res;
1720a1ba9ba4Schristos 
1721a1ba9ba4Schristos 	    tASSERT (ntBITS (6, 7) == 0);
1722a1ba9ba4Schristos 	    tASSERT (Ra != 15);
1723a1ba9ba4Schristos 
1724a1ba9ba4Schristos 	    if (ntBIT (5))
1725a1ba9ba4Schristos 	      nval >>= 16;
1726a1ba9ba4Schristos 	    else
1727a1ba9ba4Schristos 	      nval &= 0xFFFF;
1728a1ba9ba4Schristos 
1729a1ba9ba4Schristos 	    if (ntBIT (4))
1730a1ba9ba4Schristos 	      mval >>= 16;
1731a1ba9ba4Schristos 	    else
1732a1ba9ba4Schristos 	      mval &= 0xFFFF;
1733a1ba9ba4Schristos 
1734a1ba9ba4Schristos 	    res = nval * mval;
1735a1ba9ba4Schristos 	    res += state->Reg[Ra];
1736a1ba9ba4Schristos 	    // FIXME: Test and clear/set the Q bit.
1737a1ba9ba4Schristos 	    state->Reg[Rd] = res;
1738a1ba9ba4Schristos 	  }
1739a1ba9ba4Schristos 	else
1740a1ba9ba4Schristos 	  {
1741a1ba9ba4Schristos 	    if (ntBITS (4, 7) == 1)
1742a1ba9ba4Schristos 	      {
1743a1ba9ba4Schristos 		// MLS<c> <Rd>,<Rn>,<Rm>,<Ra>
1744a1ba9ba4Schristos 		state->Reg[Rd] = state->Reg[Ra] - (state->Reg[Rn] * state->Reg[Rm]);
1745a1ba9ba4Schristos 	      }
1746a1ba9ba4Schristos 	    else
1747a1ba9ba4Schristos 	      {
1748a1ba9ba4Schristos 		tASSERT (ntBITS (4, 7) == 0);
1749a1ba9ba4Schristos 
1750a1ba9ba4Schristos 		if (Ra == 15)
1751a1ba9ba4Schristos 		  // MUL<c> <Rd>,<Rn>,<Rm>
1752a1ba9ba4Schristos 		  state->Reg[Rd] = state->Reg[Rn] * state->Reg[Rm];
1753a1ba9ba4Schristos 		else
1754a1ba9ba4Schristos 		  // MLA<c> <Rd>,<Rn>,<Rm>,<Ra>
1755a1ba9ba4Schristos 		  state->Reg[Rd] = state->Reg[Rn] * state->Reg[Rm] + state->Reg[Ra];
1756a1ba9ba4Schristos 	      }
1757a1ba9ba4Schristos 	  }
1758a1ba9ba4Schristos 	* pvalid = t_resolved;
1759a1ba9ba4Schristos 	break;
1760a1ba9ba4Schristos       }
1761a1ba9ba4Schristos 
1762a1ba9ba4Schristos     case 0xDC: // SMULL
1763a1ba9ba4Schristos       tASSERT (tBIT (4) == 0);
1764a1ba9ba4Schristos       tASSERT (ntBITS (4, 7) == 0);
1765a1ba9ba4Schristos       * ainstr = 0xE0C00090;
1766a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 16); // RdHi
1767a1ba9ba4Schristos       * ainstr |= (ntBITS (12, 15) << 12); // RdLo
1768a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 3) << 8); // Rm
1769a1ba9ba4Schristos       * ainstr |= tBITS (0, 3); // Rn
1770a1ba9ba4Schristos       * pvalid = t_decoded;
1771a1ba9ba4Schristos       break;
1772a1ba9ba4Schristos 
1773a1ba9ba4Schristos     case 0xDD: // UMULL
1774a1ba9ba4Schristos       tASSERT (tBIT (4) == 0);
1775a1ba9ba4Schristos       tASSERT (ntBITS (4, 7) == 0);
1776a1ba9ba4Schristos       * ainstr = 0xE0800090;
1777a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 16); // RdHi
1778a1ba9ba4Schristos       * ainstr |= (ntBITS (12, 15) << 12); // RdLo
1779a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 3) << 8); // Rm
1780a1ba9ba4Schristos       * ainstr |= tBITS (0, 3); // Rn
1781a1ba9ba4Schristos       * pvalid = t_decoded;
1782a1ba9ba4Schristos       break;
1783a1ba9ba4Schristos 
1784a1ba9ba4Schristos     case 0xDF: // UMLAL
1785a1ba9ba4Schristos       tASSERT (tBIT (4) == 0);
1786a1ba9ba4Schristos       tASSERT (ntBITS (4, 7) == 0);
1787a1ba9ba4Schristos       * ainstr = 0xE0A00090;
1788a1ba9ba4Schristos       * ainstr |= (ntBITS (8, 11) << 16); // RdHi
1789a1ba9ba4Schristos       * ainstr |= (ntBITS (12, 15) << 12); // RdLo
1790a1ba9ba4Schristos       * ainstr |= (ntBITS (0, 3) << 8); // Rm
1791a1ba9ba4Schristos       * ainstr |= tBITS (0, 3); // Rn
1792a1ba9ba4Schristos       * pvalid = t_decoded;
1793a1ba9ba4Schristos       break;
1794a1ba9ba4Schristos 
1795a1ba9ba4Schristos     default:
1796a1ba9ba4Schristos       fprintf (stderr, "(op = %x) ", tBITS (5,12));
1797a1ba9ba4Schristos       tASSERT (0);
1798a1ba9ba4Schristos       return;
1799a1ba9ba4Schristos     }
1800a1ba9ba4Schristos 
1801a1ba9ba4Schristos   /* Tell the Thumb decoder to skip the next 16-bit insn - it was
1802a1ba9ba4Schristos      part of this insn - unless this insn has changed the PC.  */
1803a1ba9ba4Schristos   skipping_32bit_thumb = pc + 2;
1804a1ba9ba4Schristos }
1805a1ba9ba4Schristos 
1806a1ba9ba4Schristos /* Attempt to emulate an ARMv6 instruction.
1807a1ba9ba4Schristos    Stores t_branch into PVALUE upon success or t_undefined otherwise.  */
1808a1ba9ba4Schristos 
1809a1ba9ba4Schristos static void
handle_v6_thumb_insn(ARMul_State * state,ARMword tinstr,ARMword next_instr,ARMword pc,ARMword * ainstr,tdstate * pvalid)1810a1ba9ba4Schristos handle_v6_thumb_insn (ARMul_State * state,
1811a1ba9ba4Schristos 		      ARMword       tinstr,
1812a1ba9ba4Schristos 		      ARMword       next_instr,
1813a1ba9ba4Schristos 		      ARMword       pc,
1814a1ba9ba4Schristos 		      ARMword *     ainstr,
1815a1ba9ba4Schristos 		      tdstate *     pvalid)
1816a1ba9ba4Schristos {
1817a1ba9ba4Schristos   if (! state->is_v6)
1818a1ba9ba4Schristos     {
1819a1ba9ba4Schristos       * pvalid = t_undefined;
1820a1ba9ba4Schristos       return;
1821a1ba9ba4Schristos     }
1822a1ba9ba4Schristos 
1823a1ba9ba4Schristos   if (tBITS (12, 15) == 0xB
1824a1ba9ba4Schristos       && tBIT (10) == 0
1825a1ba9ba4Schristos       && tBIT (8) == 1)
1826a1ba9ba4Schristos     {
1827a1ba9ba4Schristos       // Conditional branch forwards.
1828a1ba9ba4Schristos       ARMword Rn = tBITS (0, 2);
1829a1ba9ba4Schristos       ARMword imm5 = tBIT (9) << 5 | tBITS (3, 7);
1830a1ba9ba4Schristos 
1831a1ba9ba4Schristos       if (tBIT (11))
1832a1ba9ba4Schristos 	{
1833a1ba9ba4Schristos 	  if (state->Reg[Rn] != 0)
1834a1ba9ba4Schristos 	    {
1835a1ba9ba4Schristos 	      state->Reg[15] = (pc + 4 + imm5 * 2);
1836a1ba9ba4Schristos 	      FLUSHPIPE;
1837a1ba9ba4Schristos 	    }
1838a1ba9ba4Schristos 	}
1839a1ba9ba4Schristos       else
1840a1ba9ba4Schristos 	{
1841a1ba9ba4Schristos 	  if (state->Reg[Rn] == 0)
1842a1ba9ba4Schristos 	    {
1843a1ba9ba4Schristos 	      state->Reg[15] = (pc + 4 + imm5 * 2);
1844a1ba9ba4Schristos 	      FLUSHPIPE;
1845a1ba9ba4Schristos 	    }
1846a1ba9ba4Schristos 	}
1847a1ba9ba4Schristos       * pvalid = t_branch;
1848a1ba9ba4Schristos       return;
1849a1ba9ba4Schristos     }
1850a1ba9ba4Schristos 
1851a1ba9ba4Schristos   switch (tinstr & 0xFFC0)
1852a1ba9ba4Schristos     {
1853a1ba9ba4Schristos     case 0x4400:
1854a1ba9ba4Schristos     case 0x4480:
1855a1ba9ba4Schristos     case 0x4440:
1856a1ba9ba4Schristos     case 0x44C0: // ADD
1857a1ba9ba4Schristos       {
1858a1ba9ba4Schristos 	ARMword Rd = (tBIT (7) << 3) | tBITS (0, 2);
1859a1ba9ba4Schristos 	ARMword Rm = tBITS (3, 6);
1860a1ba9ba4Schristos 	state->Reg[Rd] += state->Reg[Rm];
1861a1ba9ba4Schristos 	break;
1862a1ba9ba4Schristos       }
1863a1ba9ba4Schristos 
1864a1ba9ba4Schristos     case 0x4600: // MOV<c> <Rd>,<Rm>
1865a1ba9ba4Schristos       {
1866a1ba9ba4Schristos 	// instr [15, 8] = 0100 0110
1867a1ba9ba4Schristos 	// instr [7]     = Rd<high>
1868a1ba9ba4Schristos 	// instr [6,3]   = Rm
1869a1ba9ba4Schristos 	// instr [2,0]   = Rd<low>
1870a1ba9ba4Schristos 	ARMword Rd = (tBIT(7) << 3) | tBITS (0, 2);
1871a1ba9ba4Schristos 	// FIXME: Check for Rd == 15 and ITblock.
1872a1ba9ba4Schristos 	state->Reg[Rd] = state->Reg[tBITS (3, 6)];
1873a1ba9ba4Schristos 	break;
1874a1ba9ba4Schristos       }
1875a1ba9ba4Schristos 
1876a1ba9ba4Schristos     case 0xBF00:
1877a1ba9ba4Schristos     case 0xBF40:
1878a1ba9ba4Schristos     case 0xBF80:
1879a1ba9ba4Schristos     case 0xBFC0:
1880a1ba9ba4Schristos       handle_IT_block (state, tinstr, pvalid);
1881a1ba9ba4Schristos       return;
1882a1ba9ba4Schristos 
1883a1ba9ba4Schristos     case 0xE840:
1884a1ba9ba4Schristos     case 0xE880: // LDMIA
1885a1ba9ba4Schristos     case 0xE8C0:
1886a1ba9ba4Schristos     case 0xE900: // STM
1887a1ba9ba4Schristos     case 0xE940:
1888a1ba9ba4Schristos     case 0xE980:
1889a1ba9ba4Schristos     case 0xE9C0: // LDRD
1890a1ba9ba4Schristos     case 0xEA00: // BIC
1891a1ba9ba4Schristos     case 0xEA40: // ORR
1892a1ba9ba4Schristos     case 0xEA80: // EOR
1893a1ba9ba4Schristos     case 0xEAC0:
1894a1ba9ba4Schristos     case 0xEB00: // ADD
1895a1ba9ba4Schristos     case 0xEB40: // SBC
1896a1ba9ba4Schristos     case 0xEB80: // SUB
1897a1ba9ba4Schristos     case 0xEBC0: // RSB
1898a1ba9ba4Schristos     case 0xFA80: // UADD, SEL
1899a1ba9ba4Schristos       handle_T2_insn (state, tinstr, next_instr, pc, ainstr, pvalid);
1900a1ba9ba4Schristos       return;
1901a1ba9ba4Schristos 
1902a1ba9ba4Schristos     case 0xba00: /* rev */
1903a1ba9ba4Schristos       {
1904a1ba9ba4Schristos 	ARMword val = state->Reg[tBITS (3, 5)];
1905a1ba9ba4Schristos 	state->Reg [tBITS (0, 2)] =
1906a1ba9ba4Schristos 	  (val >> 24)
1907a1ba9ba4Schristos 	  | ((val >> 8) & 0xFF00)
1908a1ba9ba4Schristos 	  | ((val << 8) & 0xFF0000)
1909a1ba9ba4Schristos 	  | (val << 24);
1910a1ba9ba4Schristos 	break;
1911a1ba9ba4Schristos       }
1912a1ba9ba4Schristos 
1913a1ba9ba4Schristos     case 0xba40: /* rev16 */
1914a1ba9ba4Schristos       {
1915a1ba9ba4Schristos 	ARMword val = state->Reg[tBITS (3, 5)];
1916a1ba9ba4Schristos 	state->Reg [tBITS (0, 2)] = (val >> 16) | (val << 16);
1917a1ba9ba4Schristos 	break;
1918a1ba9ba4Schristos       }
1919a1ba9ba4Schristos 
1920a1ba9ba4Schristos     case 0xb660: /* cpsie */
1921a1ba9ba4Schristos     case 0xb670: /* cpsid */
1922a1ba9ba4Schristos     case 0xbac0: /* revsh */
1923a1ba9ba4Schristos     case 0xb650: /* setend */
1924a1ba9ba4Schristos     default:
1925a1ba9ba4Schristos       printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
1926a1ba9ba4Schristos       * pvalid = t_undefined;
1927a1ba9ba4Schristos       return;
1928a1ba9ba4Schristos 
1929a1ba9ba4Schristos     case 0xb200: /* sxth */
1930a1ba9ba4Schristos       {
1931a1ba9ba4Schristos 	ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
1932a1ba9ba4Schristos 
1933a1ba9ba4Schristos 	if (Rm & 0x8000)
1934a1ba9ba4Schristos 	  state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
1935a1ba9ba4Schristos 	else
1936a1ba9ba4Schristos 	  state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
1937a1ba9ba4Schristos 	break;
1938a1ba9ba4Schristos       }
1939a1ba9ba4Schristos 
1940a1ba9ba4Schristos     case 0xb240: /* sxtb */
1941a1ba9ba4Schristos       {
1942a1ba9ba4Schristos 	ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
1943a1ba9ba4Schristos 
1944a1ba9ba4Schristos 	if (Rm & 0x80)
1945a1ba9ba4Schristos 	  state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
1946a1ba9ba4Schristos 	else
1947a1ba9ba4Schristos 	  state->Reg [(tinstr & 0x7)] = Rm & 0xff;
1948a1ba9ba4Schristos 	break;
1949a1ba9ba4Schristos       }
1950a1ba9ba4Schristos 
1951a1ba9ba4Schristos     case 0xb280: /* uxth */
1952a1ba9ba4Schristos       {
1953a1ba9ba4Schristos 	ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
1954a1ba9ba4Schristos 
1955a1ba9ba4Schristos 	state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
1956a1ba9ba4Schristos 	break;
1957a1ba9ba4Schristos       }
1958a1ba9ba4Schristos 
1959a1ba9ba4Schristos     case 0xb2c0: /* uxtb */
1960a1ba9ba4Schristos       {
1961a1ba9ba4Schristos 	ARMword Rm = state->Reg [(tinstr & 0x38) >> 3];
1962a1ba9ba4Schristos 
1963a1ba9ba4Schristos 	state->Reg [(tinstr & 0x7)] = Rm & 0xff;
1964a1ba9ba4Schristos 	break;
1965a1ba9ba4Schristos       }
1966a1ba9ba4Schristos     }
1967a1ba9ba4Schristos   /* Indicate that the instruction has been processed.  */
1968a1ba9ba4Schristos   * pvalid = t_branch;
1969a1ba9ba4Schristos }
1970a1ba9ba4Schristos 
1971a1ba9ba4Schristos /* Decode a 16bit Thumb instruction.  The instruction is in the low
1972a1ba9ba4Schristos    16-bits of the tinstr field, with the following Thumb instruction
1973a1ba9ba4Schristos    held in the high 16-bits.  Passing in two Thumb instructions allows
1974a1ba9ba4Schristos    easier simulation of the special dual BL instruction.  */
1975a1ba9ba4Schristos 
1976a1ba9ba4Schristos tdstate
ARMul_ThumbDecode(ARMul_State * state,ARMword pc,ARMword tinstr,ARMword * ainstr)1977a1ba9ba4Schristos ARMul_ThumbDecode (ARMul_State * state,
1978a1ba9ba4Schristos 		   ARMword       pc,
1979a1ba9ba4Schristos 		   ARMword       tinstr,
1980a1ba9ba4Schristos 		   ARMword *     ainstr)
1981a1ba9ba4Schristos {
1982a1ba9ba4Schristos   tdstate valid = t_decoded;	/* default assumes a valid instruction */
1983a1ba9ba4Schristos   ARMword next_instr;
1984a1ba9ba4Schristos   ARMword  old_tinstr = tinstr;
1985a1ba9ba4Schristos 
1986a1ba9ba4Schristos   if (skipping_32bit_thumb == pc)
1987a1ba9ba4Schristos     {
1988a1ba9ba4Schristos       skipping_32bit_thumb = 0;
1989a1ba9ba4Schristos       return t_branch;
1990a1ba9ba4Schristos     }
1991a1ba9ba4Schristos   skipping_32bit_thumb = 0;
1992a1ba9ba4Schristos 
1993a1ba9ba4Schristos   if (state->bigendSig)
1994a1ba9ba4Schristos     {
1995a1ba9ba4Schristos       next_instr = tinstr & 0xFFFF;
1996a1ba9ba4Schristos       tinstr >>= 16;
1997a1ba9ba4Schristos     }
1998a1ba9ba4Schristos   else
1999a1ba9ba4Schristos     {
2000a1ba9ba4Schristos       next_instr = tinstr >> 16;
2001a1ba9ba4Schristos       tinstr &= 0xFFFF;
2002a1ba9ba4Schristos     }
2003a1ba9ba4Schristos 
2004a1ba9ba4Schristos   if (! IT_block_allow (state))
2005a1ba9ba4Schristos     {
2006a1ba9ba4Schristos       if (   tBITS (11, 15) == 0x1F
2007a1ba9ba4Schristos 	  || tBITS (11, 15) == 0x1E
2008a1ba9ba4Schristos 	  || tBITS (11, 15) == 0x1D)
2009a1ba9ba4Schristos 	{
2010a1ba9ba4Schristos 	  if (trace)
2011a1ba9ba4Schristos 	    fprintf (stderr, "pc: %x, SKIP  instr: %04x|%04x\n",
2012a1ba9ba4Schristos 		     pc & ~1, tinstr, next_instr);
2013a1ba9ba4Schristos 	  skipping_32bit_thumb = pc + 2;
2014a1ba9ba4Schristos 	}
2015a1ba9ba4Schristos       else if (trace)
2016a1ba9ba4Schristos 	fprintf (stderr, "pc: %x, SKIP  instr: %04x\n", pc & ~1, tinstr);
2017a1ba9ba4Schristos 
2018a1ba9ba4Schristos       return t_branch;
2019a1ba9ba4Schristos     }
2020a1ba9ba4Schristos 
2021a1ba9ba4Schristos   old_tinstr = tinstr;
2022a1ba9ba4Schristos   if (trace)
2023a1ba9ba4Schristos     fprintf (stderr, "pc: %x, Thumb instr: %x", pc & ~1, tinstr);
2024a1ba9ba4Schristos 
2025a1ba9ba4Schristos #if 1				/* debugging to catch non updates */
2026a1ba9ba4Schristos   *ainstr = 0xDEADC0DE;
2027a1ba9ba4Schristos #endif
2028a1ba9ba4Schristos 
2029a1ba9ba4Schristos   switch ((tinstr & 0xF800) >> 11)
2030a1ba9ba4Schristos     {
2031a1ba9ba4Schristos     case 0:			/* LSL */
2032a1ba9ba4Schristos     case 1:			/* LSR */
2033a1ba9ba4Schristos     case 2:			/* ASR */
2034a1ba9ba4Schristos       /* Format 1 */
2035a1ba9ba4Schristos       *ainstr = 0xE1B00000	/* base opcode */
2036a1ba9ba4Schristos 	| ((tinstr & 0x1800) >> (11 - 5))	/* shift type */
2037a1ba9ba4Schristos 	| ((tinstr & 0x07C0) << (7 - 6))	/* imm5 */
2038a1ba9ba4Schristos 	| ((tinstr & 0x0038) >> 3)	/* Rs */
2039a1ba9ba4Schristos 	| ((tinstr & 0x0007) << 12);	/* Rd */
2040a1ba9ba4Schristos       break;
2041a1ba9ba4Schristos     case 3:			/* ADD/SUB */
2042a1ba9ba4Schristos       /* Format 2 */
2043a1ba9ba4Schristos       {
2044a1ba9ba4Schristos 	ARMword subset[4] =
2045a1ba9ba4Schristos 	  {
2046a1ba9ba4Schristos 	    0xE0900000,		/* ADDS Rd,Rs,Rn    */
2047a1ba9ba4Schristos 	    0xE0500000,		/* SUBS Rd,Rs,Rn    */
2048a1ba9ba4Schristos 	    0xE2900000,		/* ADDS Rd,Rs,#imm3 */
2049a1ba9ba4Schristos 	    0xE2500000		/* SUBS Rd,Rs,#imm3 */
2050a1ba9ba4Schristos 	  };
2051a1ba9ba4Schristos 	/* It is quicker indexing into a table, than performing switch
2052a1ba9ba4Schristos 	   or conditionals: */
2053a1ba9ba4Schristos 	*ainstr = subset[(tinstr & 0x0600) >> 9]	/* base opcode */
2054a1ba9ba4Schristos 	  | ((tinstr & 0x01C0) >> 6)	/* Rn or imm3 */
2055a1ba9ba4Schristos 	  | ((tinstr & 0x0038) << (16 - 3))	/* Rs */
2056a1ba9ba4Schristos 	  | ((tinstr & 0x0007) << (12 - 0));	/* Rd */
2057a1ba9ba4Schristos 
2058a1ba9ba4Schristos 	if (in_IT_block ())
2059a1ba9ba4Schristos 	  *ainstr &= ~ (1 << 20);
2060a1ba9ba4Schristos       }
2061a1ba9ba4Schristos       break;
2062a1ba9ba4Schristos     case 4:
2063a1ba9ba4Schristos       * ainstr = 0xE3A00000; /* MOV  Rd,#imm8    */
2064a1ba9ba4Schristos       if (! in_IT_block ())
2065a1ba9ba4Schristos 	* ainstr |= (1 << 20);
2066a1ba9ba4Schristos       * ainstr |= tBITS (8, 10) << 12;
2067a1ba9ba4Schristos       * ainstr |= tBITS (0, 7);
2068a1ba9ba4Schristos       break;
2069a1ba9ba4Schristos 
2070a1ba9ba4Schristos     case 5:
2071a1ba9ba4Schristos       * ainstr = 0xE3500000;	/* CMP  Rd,#imm8    */
2072a1ba9ba4Schristos       * ainstr |= tBITS (8, 10) << 16;
2073a1ba9ba4Schristos       * ainstr |= tBITS (0, 7);
2074a1ba9ba4Schristos       break;
2075a1ba9ba4Schristos 
2076a1ba9ba4Schristos     case 6:
2077a1ba9ba4Schristos     case 7:
2078a1ba9ba4Schristos       * ainstr = tBIT (11)
2079a1ba9ba4Schristos 	? 0xE2400000		/* SUB  Rd,Rd,#imm8 */
2080a1ba9ba4Schristos 	: 0xE2800000;		/* ADD  Rd,Rd,#imm8 */
2081a1ba9ba4Schristos       if (! in_IT_block ())
2082a1ba9ba4Schristos 	* ainstr |= (1 << 20);
2083a1ba9ba4Schristos       * ainstr |= tBITS (8, 10) << 12;
2084a1ba9ba4Schristos       * ainstr |= tBITS (8, 10) << 16;
2085a1ba9ba4Schristos       * ainstr |= tBITS (0, 7);
2086a1ba9ba4Schristos       break;
2087a1ba9ba4Schristos 
2088a1ba9ba4Schristos     case 8:			/* Arithmetic and high register transfers */
2089a1ba9ba4Schristos       /* TODO: Since the subsets for both Format 4 and Format 5
2090a1ba9ba4Schristos          instructions are made up of different ARM encodings, we could
2091a1ba9ba4Schristos          save the following conditional, and just have one large
2092a1ba9ba4Schristos          subset. */
2093a1ba9ba4Schristos       if ((tinstr & (1 << 10)) == 0)
2094a1ba9ba4Schristos 	{
2095a1ba9ba4Schristos 	  /* Format 4 */
2096a1ba9ba4Schristos 	  struct
2097a1ba9ba4Schristos 	  {
2098a1ba9ba4Schristos 	    ARMword opcode;
2099a1ba9ba4Schristos 	    enum
2100a1ba9ba4Schristos 	    { t_norm, t_shift, t_neg, t_mul }
2101a1ba9ba4Schristos 	    otype;
2102a1ba9ba4Schristos 	  }
2103a1ba9ba4Schristos 	  subset[16] =
2104a1ba9ba4Schristos 	  {
2105a1ba9ba4Schristos 	    { 0xE0100000, t_norm},			/* ANDS Rd,Rd,Rs     */
2106a1ba9ba4Schristos 	    { 0xE0300000, t_norm},			/* EORS Rd,Rd,Rs     */
2107a1ba9ba4Schristos 	    { 0xE1B00010, t_shift},			/* MOVS Rd,Rd,LSL Rs */
2108a1ba9ba4Schristos 	    { 0xE1B00030, t_shift},			/* MOVS Rd,Rd,LSR Rs */
2109a1ba9ba4Schristos 	    { 0xE1B00050, t_shift},			/* MOVS Rd,Rd,ASR Rs */
2110a1ba9ba4Schristos 	    { 0xE0B00000, t_norm},			/* ADCS Rd,Rd,Rs     */
2111a1ba9ba4Schristos 	    { 0xE0D00000, t_norm},			/* SBCS Rd,Rd,Rs     */
2112a1ba9ba4Schristos 	    { 0xE1B00070, t_shift},			/* MOVS Rd,Rd,ROR Rs */
2113a1ba9ba4Schristos 	    { 0xE1100000, t_norm},			/* TST  Rd,Rs        */
2114a1ba9ba4Schristos 	    { 0xE2700000, t_neg},			/* RSBS Rd,Rs,#0     */
2115a1ba9ba4Schristos 	    { 0xE1500000, t_norm},			/* CMP  Rd,Rs        */
2116a1ba9ba4Schristos 	    { 0xE1700000, t_norm},			/* CMN  Rd,Rs        */
2117a1ba9ba4Schristos 	    { 0xE1900000, t_norm},			/* ORRS Rd,Rd,Rs     */
2118a1ba9ba4Schristos 	    { 0xE0100090, t_mul} ,			/* MULS Rd,Rd,Rs     */
2119a1ba9ba4Schristos 	    { 0xE1D00000, t_norm},			/* BICS Rd,Rd,Rs     */
2120a1ba9ba4Schristos 	    { 0xE1F00000, t_norm}	/* MVNS Rd,Rs        */
2121a1ba9ba4Schristos 	  };
2122a1ba9ba4Schristos 	  *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;	/* base */
2123a1ba9ba4Schristos 
2124a1ba9ba4Schristos 	  if (in_IT_block ())
2125a1ba9ba4Schristos 	    {
2126a1ba9ba4Schristos 	      struct
2127a1ba9ba4Schristos 	      {
2128a1ba9ba4Schristos 		ARMword opcode;
2129a1ba9ba4Schristos 		enum
2130a1ba9ba4Schristos 		  { t_norm, t_shift, t_neg, t_mul }
2131a1ba9ba4Schristos 		  otype;
2132a1ba9ba4Schristos 	      }
2133a1ba9ba4Schristos 	      subset[16] =
2134a1ba9ba4Schristos 		{
2135a1ba9ba4Schristos 		  { 0xE0000000, t_norm},	/* AND  Rd,Rd,Rs     */
2136a1ba9ba4Schristos 		  { 0xE0200000, t_norm},	/* EOR  Rd,Rd,Rs     */
2137a1ba9ba4Schristos 		  { 0xE1A00010, t_shift},	/* MOV  Rd,Rd,LSL Rs */
2138a1ba9ba4Schristos 		  { 0xE1A00030, t_shift},	/* MOV  Rd,Rd,LSR Rs */
2139a1ba9ba4Schristos 		  { 0xE1A00050, t_shift},	/* MOV  Rd,Rd,ASR Rs */
2140a1ba9ba4Schristos 		  { 0xE0A00000, t_norm},	/* ADC  Rd,Rd,Rs     */
2141a1ba9ba4Schristos 		  { 0xE0C00000, t_norm},	/* SBC  Rd,Rd,Rs     */
2142a1ba9ba4Schristos 		  { 0xE1A00070, t_shift},	/* MOV  Rd,Rd,ROR Rs */
2143a1ba9ba4Schristos 		  { 0xE1100000, t_norm},	/* TST  Rd,Rs        */
2144a1ba9ba4Schristos 		  { 0xE2600000, t_neg},		/* RSB  Rd,Rs,#0     */
2145a1ba9ba4Schristos 		  { 0xE1500000, t_norm},	/* CMP  Rd,Rs        */
2146a1ba9ba4Schristos 		  { 0xE1700000, t_norm},	/* CMN  Rd,Rs        */
2147a1ba9ba4Schristos 		  { 0xE1800000, t_norm},	/* ORR  Rd,Rd,Rs     */
2148a1ba9ba4Schristos 		  { 0xE0000090, t_mul} ,	/* MUL  Rd,Rd,Rs     */
2149a1ba9ba4Schristos 		  { 0xE1C00000, t_norm},	/* BIC  Rd,Rd,Rs     */
2150a1ba9ba4Schristos 		  { 0xE1E00000, t_norm}		/* MVN  Rd,Rs        */
2151a1ba9ba4Schristos 		};
2152a1ba9ba4Schristos 	      *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode;	/* base */
2153a1ba9ba4Schristos 	    }
2154a1ba9ba4Schristos 
2155a1ba9ba4Schristos 	  switch (subset[(tinstr & 0x03C0) >> 6].otype)
2156a1ba9ba4Schristos 	    {
2157a1ba9ba4Schristos 	    case t_norm:
2158a1ba9ba4Schristos 	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rn */
2159a1ba9ba4Schristos 		| ((tinstr & 0x0007) << 12)	/* Rd */
2160a1ba9ba4Schristos 		| ((tinstr & 0x0038) >> 3);	/* Rs */
2161a1ba9ba4Schristos 	      break;
2162a1ba9ba4Schristos 	    case t_shift:
2163a1ba9ba4Schristos 	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
2164a1ba9ba4Schristos 		| ((tinstr & 0x0007) >> 0)	/* Rm */
2165a1ba9ba4Schristos 		| ((tinstr & 0x0038) << (8 - 3));	/* Rs */
2166a1ba9ba4Schristos 	      break;
2167a1ba9ba4Schristos 	    case t_neg:
2168a1ba9ba4Schristos 	      *ainstr |= ((tinstr & 0x0007) << 12)	/* Rd */
2169a1ba9ba4Schristos 		| ((tinstr & 0x0038) << (16 - 3));	/* Rn */
2170a1ba9ba4Schristos 	      break;
2171a1ba9ba4Schristos 	    case t_mul:
2172a1ba9ba4Schristos 	      *ainstr |= ((tinstr & 0x0007) << 16)	/* Rd */
2173a1ba9ba4Schristos 		| ((tinstr & 0x0007) << 8)	/* Rs */
2174a1ba9ba4Schristos 		| ((tinstr & 0x0038) >> 3);	/* Rm */
2175a1ba9ba4Schristos 	      break;
2176a1ba9ba4Schristos 	    }
2177a1ba9ba4Schristos 	}
2178a1ba9ba4Schristos       else
2179a1ba9ba4Schristos 	{
2180a1ba9ba4Schristos 	  /* Format 5 */
2181a1ba9ba4Schristos 	  ARMword Rd = ((tinstr & 0x0007) >> 0);
2182a1ba9ba4Schristos 	  ARMword Rs = ((tinstr & 0x0038) >> 3);
2183a1ba9ba4Schristos 	  if (tinstr & (1 << 7))
2184a1ba9ba4Schristos 	    Rd += 8;
2185a1ba9ba4Schristos 	  if (tinstr & (1 << 6))
2186a1ba9ba4Schristos 	    Rs += 8;
2187a1ba9ba4Schristos 	  switch ((tinstr & 0x03C0) >> 6)
2188a1ba9ba4Schristos 	    {
2189a1ba9ba4Schristos 	    case 0x1:		/* ADD Rd,Rd,Hs */
2190a1ba9ba4Schristos 	    case 0x2:		/* ADD Hd,Hd,Rs */
2191a1ba9ba4Schristos 	    case 0x3:		/* ADD Hd,Hd,Hs */
2192a1ba9ba4Schristos 	      *ainstr = 0xE0800000	/* base */
2193a1ba9ba4Schristos 		| (Rd << 16)	/* Rn */
2194a1ba9ba4Schristos 		| (Rd << 12)	/* Rd */
2195a1ba9ba4Schristos 		| (Rs << 0);	/* Rm */
2196a1ba9ba4Schristos 	      break;
2197a1ba9ba4Schristos 	    case 0x5:		/* CMP Rd,Hs */
2198a1ba9ba4Schristos 	    case 0x6:		/* CMP Hd,Rs */
2199a1ba9ba4Schristos 	    case 0x7:		/* CMP Hd,Hs */
2200a1ba9ba4Schristos 	      *ainstr = 0xE1500000	/* base */
2201a1ba9ba4Schristos 		| (Rd << 16)	/* Rn */
2202a1ba9ba4Schristos 		| (Rd << 12)	/* Rd */
2203a1ba9ba4Schristos 		| (Rs << 0);	/* Rm */
2204a1ba9ba4Schristos 	      break;
2205a1ba9ba4Schristos 	    case 0x9:		/* MOV Rd,Hs */
2206a1ba9ba4Schristos 	    case 0xA:		/* MOV Hd,Rs */
2207a1ba9ba4Schristos 	    case 0xB:		/* MOV Hd,Hs */
2208a1ba9ba4Schristos 	      *ainstr = 0xE1A00000	/* base */
2209a1ba9ba4Schristos 		| (Rd << 12)	/* Rd */
2210a1ba9ba4Schristos 		| (Rs << 0);	/* Rm */
2211a1ba9ba4Schristos 	      break;
2212a1ba9ba4Schristos 	    case 0xC:		/* BX Rs */
2213a1ba9ba4Schristos 	    case 0xD:		/* BX Hs */
2214a1ba9ba4Schristos 	      *ainstr = 0xE12FFF10	/* base */
2215a1ba9ba4Schristos 		| ((tinstr & 0x0078) >> 3);	/* Rd */
2216a1ba9ba4Schristos 	      break;
2217a1ba9ba4Schristos 	    case 0xE:		/* UNDEFINED */
2218a1ba9ba4Schristos 	    case 0xF:		/* UNDEFINED */
2219a1ba9ba4Schristos 	      if (state->is_v5)
2220a1ba9ba4Schristos 		{
2221a1ba9ba4Schristos 		  /* BLX Rs; BLX Hs */
2222a1ba9ba4Schristos 		  *ainstr = 0xE12FFF30	/* base */
2223a1ba9ba4Schristos 		    | ((tinstr & 0x0078) >> 3);	/* Rd */
2224a1ba9ba4Schristos 		  break;
2225a1ba9ba4Schristos 		}
2226a1ba9ba4Schristos 	      /* Drop through.  */
2227a1ba9ba4Schristos 	    default:
2228a1ba9ba4Schristos 	    case 0x0:		/* UNDEFINED */
2229a1ba9ba4Schristos 	    case 0x4:		/* UNDEFINED */
2230a1ba9ba4Schristos 	    case 0x8:		/* UNDEFINED */
2231a1ba9ba4Schristos 	      handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2232a1ba9ba4Schristos 	      break;
2233a1ba9ba4Schristos 	    }
2234a1ba9ba4Schristos 	}
2235a1ba9ba4Schristos       break;
2236a1ba9ba4Schristos     case 9:			/* LDR Rd,[PC,#imm8] */
2237a1ba9ba4Schristos       /* Format 6 */
2238a1ba9ba4Schristos       *ainstr = 0xE59F0000	/* base */
2239a1ba9ba4Schristos 	| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
2240a1ba9ba4Schristos 	| ((tinstr & 0x00FF) << (2 - 0));	/* off8 */
2241a1ba9ba4Schristos       break;
2242a1ba9ba4Schristos     case 10:
2243a1ba9ba4Schristos     case 11:
2244a1ba9ba4Schristos       /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
2245a1ba9ba4Schristos          the following could be merged into a single subset, saving on
2246a1ba9ba4Schristos          the following boolean: */
2247a1ba9ba4Schristos       if ((tinstr & (1 << 9)) == 0)
2248a1ba9ba4Schristos 	{
2249a1ba9ba4Schristos 	  /* Format 7 */
2250a1ba9ba4Schristos 	  ARMword subset[4] = {
2251a1ba9ba4Schristos 	    0xE7800000,		/* STR  Rd,[Rb,Ro] */
2252a1ba9ba4Schristos 	    0xE7C00000,		/* STRB Rd,[Rb,Ro] */
2253a1ba9ba4Schristos 	    0xE7900000,		/* LDR  Rd,[Rb,Ro] */
2254a1ba9ba4Schristos 	    0xE7D00000		/* LDRB Rd,[Rb,Ro] */
2255a1ba9ba4Schristos 	  };
2256a1ba9ba4Schristos 	  *ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
2257a1ba9ba4Schristos 	    | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
2258a1ba9ba4Schristos 	    | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
2259a1ba9ba4Schristos 	    | ((tinstr & 0x01C0) >> 6);	/* Ro */
2260a1ba9ba4Schristos 	}
2261a1ba9ba4Schristos       else
2262a1ba9ba4Schristos 	{
2263a1ba9ba4Schristos 	  /* Format 8 */
2264a1ba9ba4Schristos 	  ARMword subset[4] = {
2265a1ba9ba4Schristos 	    0xE18000B0,		/* STRH  Rd,[Rb,Ro] */
2266a1ba9ba4Schristos 	    0xE19000D0,		/* LDRSB Rd,[Rb,Ro] */
2267a1ba9ba4Schristos 	    0xE19000B0,		/* LDRH  Rd,[Rb,Ro] */
2268a1ba9ba4Schristos 	    0xE19000F0		/* LDRSH Rd,[Rb,Ro] */
2269a1ba9ba4Schristos 	  };
2270a1ba9ba4Schristos 	  *ainstr = subset[(tinstr & 0x0C00) >> 10]	/* base */
2271a1ba9ba4Schristos 	    | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
2272a1ba9ba4Schristos 	    | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
2273a1ba9ba4Schristos 	    | ((tinstr & 0x01C0) >> 6);	/* Ro */
2274a1ba9ba4Schristos 	}
2275a1ba9ba4Schristos       break;
2276a1ba9ba4Schristos     case 12:			/* STR Rd,[Rb,#imm5] */
2277a1ba9ba4Schristos     case 13:			/* LDR Rd,[Rb,#imm5] */
2278a1ba9ba4Schristos     case 14:			/* STRB Rd,[Rb,#imm5] */
2279a1ba9ba4Schristos     case 15:			/* LDRB Rd,[Rb,#imm5] */
2280a1ba9ba4Schristos       /* Format 9 */
2281a1ba9ba4Schristos       {
2282a1ba9ba4Schristos 	ARMword subset[4] = {
2283a1ba9ba4Schristos 	  0xE5800000,		/* STR  Rd,[Rb,#imm5] */
2284a1ba9ba4Schristos 	  0xE5900000,		/* LDR  Rd,[Rb,#imm5] */
2285a1ba9ba4Schristos 	  0xE5C00000,		/* STRB Rd,[Rb,#imm5] */
2286a1ba9ba4Schristos 	  0xE5D00000		/* LDRB Rd,[Rb,#imm5] */
2287a1ba9ba4Schristos 	};
2288a1ba9ba4Schristos 	/* The offset range defends on whether we are transferring a
2289a1ba9ba4Schristos 	   byte or word value: */
2290a1ba9ba4Schristos 	*ainstr = subset[(tinstr & 0x1800) >> 11]	/* base */
2291a1ba9ba4Schristos 	  | ((tinstr & 0x0007) << (12 - 0))	/* Rd */
2292a1ba9ba4Schristos 	  | ((tinstr & 0x0038) << (16 - 3))	/* Rb */
2293a1ba9ba4Schristos 	  | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2)));	/* off5 */
2294a1ba9ba4Schristos       }
2295a1ba9ba4Schristos       break;
2296a1ba9ba4Schristos     case 16:			/* STRH Rd,[Rb,#imm5] */
2297a1ba9ba4Schristos     case 17:			/* LDRH Rd,[Rb,#imm5] */
2298a1ba9ba4Schristos       /* Format 10 */
2299a1ba9ba4Schristos       *ainstr = ((tinstr & (1 << 11))	/* base */
2300a1ba9ba4Schristos 		 ? 0xE1D000B0	/* LDRH */
2301a1ba9ba4Schristos 		 : 0xE1C000B0)	/* STRH */
2302a1ba9ba4Schristos 	| ((tinstr & 0x0007) << (12 - 0))	/* Rd */
2303a1ba9ba4Schristos 	| ((tinstr & 0x0038) << (16 - 3))	/* Rb */
2304a1ba9ba4Schristos 	| ((tinstr & 0x01C0) >> (6 - 1))	/* off5, low nibble */
2305a1ba9ba4Schristos 	| ((tinstr & 0x0600) >> (9 - 8));	/* off5, high nibble */
2306a1ba9ba4Schristos       break;
2307a1ba9ba4Schristos     case 18:			/* STR Rd,[SP,#imm8] */
2308a1ba9ba4Schristos     case 19:			/* LDR Rd,[SP,#imm8] */
2309a1ba9ba4Schristos       /* Format 11 */
2310a1ba9ba4Schristos       *ainstr = ((tinstr & (1 << 11))	/* base */
2311a1ba9ba4Schristos 		 ? 0xE59D0000	/* LDR */
2312a1ba9ba4Schristos 		 : 0xE58D0000)	/* STR */
2313a1ba9ba4Schristos 	| ((tinstr & 0x0700) << (12 - 8))	/* Rd */
2314a1ba9ba4Schristos 	| ((tinstr & 0x00FF) << 2);	/* off8 */
2315a1ba9ba4Schristos       break;
2316a1ba9ba4Schristos     case 20:			/* ADD Rd,PC,#imm8 */
2317a1ba9ba4Schristos     case 21:			/* ADD Rd,SP,#imm8 */
2318a1ba9ba4Schristos       /* Format 12 */
2319a1ba9ba4Schristos       if ((tinstr & (1 << 11)) == 0)
2320a1ba9ba4Schristos 	{
2321a1ba9ba4Schristos 	  /* NOTE: The PC value used here should by word aligned */
2322a1ba9ba4Schristos 	  /* We encode shift-left-by-2 in the rotate immediate field,
2323a1ba9ba4Schristos 	     so no shift of off8 is needed.  */
2324a1ba9ba4Schristos 	  *ainstr = 0xE28F0F00	/* base */
2325a1ba9ba4Schristos 	    | ((tinstr & 0x0700) << (12 - 8))	/* Rd */
2326a1ba9ba4Schristos 	    | (tinstr & 0x00FF);	/* off8 */
2327a1ba9ba4Schristos 	}
2328a1ba9ba4Schristos       else
2329a1ba9ba4Schristos 	{
2330a1ba9ba4Schristos 	  /* We encode shift-left-by-2 in the rotate immediate field,
2331a1ba9ba4Schristos 	     so no shift of off8 is needed.  */
2332a1ba9ba4Schristos 	  *ainstr = 0xE28D0F00	/* base */
2333a1ba9ba4Schristos 	    | ((tinstr & 0x0700) << (12 - 8))	/* Rd */
2334a1ba9ba4Schristos 	    | (tinstr & 0x00FF);	/* off8 */
2335a1ba9ba4Schristos 	}
2336a1ba9ba4Schristos       break;
2337a1ba9ba4Schristos     case 22:
2338a1ba9ba4Schristos     case 23:
2339a1ba9ba4Schristos       switch (tinstr & 0x0F00)
2340a1ba9ba4Schristos 	{
2341a1ba9ba4Schristos 	case 0x0000:
2342a1ba9ba4Schristos 	  /* Format 13 */
2343a1ba9ba4Schristos 	  /* NOTE: The instruction contains a shift left of 2
2344a1ba9ba4Schristos 	     equivalent (implemented as ROR #30):  */
2345a1ba9ba4Schristos 	  *ainstr = ((tinstr & (1 << 7))	/* base */
2346a1ba9ba4Schristos 		     ? 0xE24DDF00	/* SUB */
2347a1ba9ba4Schristos 		     : 0xE28DDF00)	/* ADD */
2348a1ba9ba4Schristos 	    | (tinstr & 0x007F);	/* off7 */
2349a1ba9ba4Schristos 	  break;
2350a1ba9ba4Schristos 	case 0x0400:
2351a1ba9ba4Schristos 	  /* Format 14 - Push */
2352a1ba9ba4Schristos 	  * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
2353a1ba9ba4Schristos 	  break;
2354a1ba9ba4Schristos 	case 0x0500:
2355a1ba9ba4Schristos 	  /* Format 14 - Push + LR */
2356a1ba9ba4Schristos 	  * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
2357a1ba9ba4Schristos 	  break;
2358a1ba9ba4Schristos 	case 0x0c00:
2359a1ba9ba4Schristos 	  /* Format 14 - Pop */
2360a1ba9ba4Schristos 	  * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
2361a1ba9ba4Schristos 	  break;
2362a1ba9ba4Schristos 	case 0x0d00:
2363a1ba9ba4Schristos 	  /* Format 14 - Pop + PC */
2364a1ba9ba4Schristos 	  * ainstr = 0xE8BD8000 | (tinstr & 0x00FF);
2365a1ba9ba4Schristos 	  break;
2366a1ba9ba4Schristos 	case 0x0e00:
2367a1ba9ba4Schristos 	  if (state->is_v5)
2368a1ba9ba4Schristos 	    {
2369a1ba9ba4Schristos 	      /* This is normally an undefined instruction.  The v5t architecture
2370a1ba9ba4Schristos 		 defines this particular pattern as a BKPT instruction, for
2371a1ba9ba4Schristos 		 hardware assisted debugging.  We map onto the arm BKPT
2372a1ba9ba4Schristos 		 instruction.  */
2373a1ba9ba4Schristos 	      if (state->is_v6)
2374a1ba9ba4Schristos 		// Map to the SVC instruction instead of the BKPT instruction.
2375a1ba9ba4Schristos 		* ainstr = 0xEF000000 | tBITS (0, 7);
2376a1ba9ba4Schristos 	      else
2377a1ba9ba4Schristos 		* ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
2378a1ba9ba4Schristos 	      break;
2379a1ba9ba4Schristos 	    }
2380a1ba9ba4Schristos 	  /* Drop through.  */
2381a1ba9ba4Schristos 	default:
2382a1ba9ba4Schristos 	  /* Everything else is an undefined instruction.  */
2383a1ba9ba4Schristos 	  handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2384a1ba9ba4Schristos 	  break;
2385a1ba9ba4Schristos 	}
2386a1ba9ba4Schristos       break;
2387a1ba9ba4Schristos     case 24:			/* STMIA */
2388a1ba9ba4Schristos     case 25:			/* LDMIA */
2389a1ba9ba4Schristos       /* Format 15 */
2390a1ba9ba4Schristos       *ainstr = ((tinstr & (1 << 11))	/* base */
2391a1ba9ba4Schristos 		 ? 0xE8B00000	/* LDMIA */
2392a1ba9ba4Schristos 		 : 0xE8A00000)	/* STMIA */
2393a1ba9ba4Schristos 	| ((tinstr & 0x0700) << (16 - 8))	/* Rb */
2394a1ba9ba4Schristos 	| (tinstr & 0x00FF);	/* mask8 */
2395a1ba9ba4Schristos       break;
2396a1ba9ba4Schristos     case 26:			/* Bcc */
2397a1ba9ba4Schristos     case 27:			/* Bcc/SWI */
2398a1ba9ba4Schristos       if ((tinstr & 0x0F00) == 0x0F00)
2399a1ba9ba4Schristos 	{
2400a1ba9ba4Schristos 	  /* Format 17 : SWI */
2401a1ba9ba4Schristos 	  *ainstr = 0xEF000000;
2402a1ba9ba4Schristos 	  /* Breakpoint must be handled specially.  */
2403a1ba9ba4Schristos 	  if ((tinstr & 0x00FF) == 0x18)
2404a1ba9ba4Schristos 	    *ainstr |= ((tinstr & 0x00FF) << 16);
2405a1ba9ba4Schristos 	  /* New breakpoint value.  See gdb/arm-tdep.c  */
2406a1ba9ba4Schristos 	  else if ((tinstr & 0x00FF) == 0xFE)
2407a1ba9ba4Schristos 	    *ainstr |= SWI_Breakpoint;
2408a1ba9ba4Schristos 	  else
2409a1ba9ba4Schristos 	    *ainstr |= (tinstr & 0x00FF);
2410a1ba9ba4Schristos 	}
2411a1ba9ba4Schristos       else if ((tinstr & 0x0F00) != 0x0E00)
2412a1ba9ba4Schristos 	{
2413a1ba9ba4Schristos 	  /* Format 16 */
2414a1ba9ba4Schristos 	  int doit = FALSE;
2415a1ba9ba4Schristos 	  /* TODO: Since we are doing a switch here, we could just add
2416a1ba9ba4Schristos 	     the SWI and undefined instruction checks into this
2417a1ba9ba4Schristos 	     switch to same on a couple of conditionals: */
2418a1ba9ba4Schristos 	  switch ((tinstr & 0x0F00) >> 8)
2419a1ba9ba4Schristos 	    {
2420a1ba9ba4Schristos 	    case EQ:
2421a1ba9ba4Schristos 	      doit = ZFLAG;
2422a1ba9ba4Schristos 	      break;
2423a1ba9ba4Schristos 	    case NE:
2424a1ba9ba4Schristos 	      doit = !ZFLAG;
2425a1ba9ba4Schristos 	      break;
2426a1ba9ba4Schristos 	    case VS:
2427a1ba9ba4Schristos 	      doit = VFLAG;
2428a1ba9ba4Schristos 	      break;
2429a1ba9ba4Schristos 	    case VC:
2430a1ba9ba4Schristos 	      doit = !VFLAG;
2431a1ba9ba4Schristos 	      break;
2432a1ba9ba4Schristos 	    case MI:
2433a1ba9ba4Schristos 	      doit = NFLAG;
2434a1ba9ba4Schristos 	      break;
2435a1ba9ba4Schristos 	    case PL:
2436a1ba9ba4Schristos 	      doit = !NFLAG;
2437a1ba9ba4Schristos 	      break;
2438a1ba9ba4Schristos 	    case CS:
2439a1ba9ba4Schristos 	      doit = CFLAG;
2440a1ba9ba4Schristos 	      break;
2441a1ba9ba4Schristos 	    case CC:
2442a1ba9ba4Schristos 	      doit = !CFLAG;
2443a1ba9ba4Schristos 	      break;
2444a1ba9ba4Schristos 	    case HI:
2445a1ba9ba4Schristos 	      doit = (CFLAG && !ZFLAG);
2446a1ba9ba4Schristos 	      break;
2447a1ba9ba4Schristos 	    case LS:
2448a1ba9ba4Schristos 	      doit = (!CFLAG || ZFLAG);
2449a1ba9ba4Schristos 	      break;
2450a1ba9ba4Schristos 	    case GE:
2451a1ba9ba4Schristos 	      doit = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
2452a1ba9ba4Schristos 	      break;
2453a1ba9ba4Schristos 	    case LT:
2454a1ba9ba4Schristos 	      doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
2455a1ba9ba4Schristos 	      break;
2456a1ba9ba4Schristos 	    case GT:
2457a1ba9ba4Schristos 	      doit = ((!NFLAG && !VFLAG && !ZFLAG)
2458a1ba9ba4Schristos 		      || (NFLAG && VFLAG && !ZFLAG));
2459a1ba9ba4Schristos 	      break;
2460a1ba9ba4Schristos 	    case LE:
2461a1ba9ba4Schristos 	      doit = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
2462a1ba9ba4Schristos 	      break;
2463a1ba9ba4Schristos 	    }
2464a1ba9ba4Schristos 	  if (doit)
2465a1ba9ba4Schristos 	    {
2466a1ba9ba4Schristos 	      state->Reg[15] = (pc + 4
2467a1ba9ba4Schristos 				+ (((tinstr & 0x7F) << 1)
2468a1ba9ba4Schristos 				   | ((tinstr & (1 << 7)) ? 0xFFFFFF00 : 0)));
2469a1ba9ba4Schristos 	      FLUSHPIPE;
2470a1ba9ba4Schristos 	    }
2471a1ba9ba4Schristos 	  valid = t_branch;
2472a1ba9ba4Schristos 	}
2473a1ba9ba4Schristos       else
2474a1ba9ba4Schristos 	/* UNDEFINED : cc=1110(AL) uses different format.  */
2475a1ba9ba4Schristos 	handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2476a1ba9ba4Schristos       break;
2477a1ba9ba4Schristos     case 28:			/* B */
2478a1ba9ba4Schristos       /* Format 18 */
2479a1ba9ba4Schristos       state->Reg[15] = (pc + 4
2480a1ba9ba4Schristos 			+ (((tinstr & 0x3FF) << 1)
2481a1ba9ba4Schristos 			   | ((tinstr & (1 << 10)) ? 0xFFFFF800 : 0)));
2482a1ba9ba4Schristos       FLUSHPIPE;
2483a1ba9ba4Schristos       valid = t_branch;
2484a1ba9ba4Schristos       break;
2485a1ba9ba4Schristos     case 29:			/* UNDEFINED */
2486a1ba9ba4Schristos       if (state->is_v6)
2487a1ba9ba4Schristos 	{
2488a1ba9ba4Schristos 	  handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2489a1ba9ba4Schristos 	  break;
2490a1ba9ba4Schristos 	}
2491a1ba9ba4Schristos 
2492a1ba9ba4Schristos       if (state->is_v5)
2493a1ba9ba4Schristos 	{
2494a1ba9ba4Schristos 	  if (tinstr & 1)
2495a1ba9ba4Schristos 	    {
2496a1ba9ba4Schristos 	      handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2497a1ba9ba4Schristos 	      break;
2498a1ba9ba4Schristos 	    }
2499a1ba9ba4Schristos 	  /* Drop through.  */
2500a1ba9ba4Schristos 
2501a1ba9ba4Schristos 	  /* Format 19 */
2502a1ba9ba4Schristos 	  /* There is no single ARM instruction equivalent for this
2503a1ba9ba4Schristos 	     instruction. Also, it should only ever be matched with the
2504a1ba9ba4Schristos 	     fmt19 "BL/BLX instruction 1" instruction.  However, we do
2505a1ba9ba4Schristos 	     allow the simulation of it on its own, with undefined results
2506a1ba9ba4Schristos 	     if r14 is not suitably initialised.  */
2507a1ba9ba4Schristos 	  {
2508a1ba9ba4Schristos 	    ARMword tmp = (pc + 2);
2509a1ba9ba4Schristos 
2510a1ba9ba4Schristos 	    state->Reg[15] = ((state->Reg[14] + ((tinstr & 0x07FF) << 1))
2511a1ba9ba4Schristos 			      & 0xFFFFFFFC);
2512a1ba9ba4Schristos 	    CLEART;
2513a1ba9ba4Schristos 	    state->Reg[14] = (tmp | 1);
2514a1ba9ba4Schristos 	    valid = t_branch;
2515a1ba9ba4Schristos 	    FLUSHPIPE;
2516a1ba9ba4Schristos 	    if (trace_funcs)
2517a1ba9ba4Schristos 	      fprintf (stderr, " pc changed to %x\n", state->Reg[15]);
2518a1ba9ba4Schristos 	    break;
2519a1ba9ba4Schristos 	  }
2520a1ba9ba4Schristos 	}
2521a1ba9ba4Schristos 
2522a1ba9ba4Schristos       handle_v6_thumb_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2523a1ba9ba4Schristos       break;
2524a1ba9ba4Schristos 
2525a1ba9ba4Schristos     case 30:			/* BL instruction 1 */
2526a1ba9ba4Schristos       if (state->is_v6)
2527a1ba9ba4Schristos 	{
2528a1ba9ba4Schristos 	  handle_T2_insn (state, tinstr, next_instr, pc, ainstr, & valid);
2529a1ba9ba4Schristos 	  break;
2530a1ba9ba4Schristos 	}
2531a1ba9ba4Schristos 
2532a1ba9ba4Schristos       /* Format 19 */
2533a1ba9ba4Schristos       /* There is no single ARM instruction equivalent for this Thumb
2534a1ba9ba4Schristos          instruction. To keep the simulation simple (from the user
2535a1ba9ba4Schristos          perspective) we check if the following instruction is the
2536a1ba9ba4Schristos          second half of this BL, and if it is we simulate it
2537a1ba9ba4Schristos          immediately.  */
2538a1ba9ba4Schristos       state->Reg[14] = state->Reg[15] \
2539a1ba9ba4Schristos 	+ (((tinstr & 0x07FF) << 12) \
2540a1ba9ba4Schristos 	   | ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
2541a1ba9ba4Schristos 
2542a1ba9ba4Schristos       valid = t_branch;		/* in-case we don't have the 2nd half */
2543a1ba9ba4Schristos       tinstr = next_instr;	/* move the instruction down */
2544a1ba9ba4Schristos       pc += 2;			/* point the pc at the 2nd half */
2545a1ba9ba4Schristos       if (((tinstr & 0xF800) >> 11) != 31)
2546a1ba9ba4Schristos 	{
2547a1ba9ba4Schristos 	  if (((tinstr & 0xF800) >> 11) == 29)
2548a1ba9ba4Schristos 	    {
2549a1ba9ba4Schristos 	      ARMword tmp = (pc + 2);
2550a1ba9ba4Schristos 
2551a1ba9ba4Schristos 	      state->Reg[15] = ((state->Reg[14]
2552a1ba9ba4Schristos 				 + ((tinstr & 0x07FE) << 1))
2553a1ba9ba4Schristos 				& 0xFFFFFFFC);
2554a1ba9ba4Schristos 	      CLEART;
2555a1ba9ba4Schristos 	      state->Reg[14] = (tmp | 1);
2556a1ba9ba4Schristos 	      valid = t_branch;
2557a1ba9ba4Schristos 	      FLUSHPIPE;
2558a1ba9ba4Schristos 	    }
2559a1ba9ba4Schristos 	  else
2560a1ba9ba4Schristos 	    /* Exit, since not correct instruction. */
2561a1ba9ba4Schristos 	    pc -= 2;
2562a1ba9ba4Schristos 	  break;
2563a1ba9ba4Schristos 	}
2564a1ba9ba4Schristos       /* else we fall through to process the second half of the BL */
2565a1ba9ba4Schristos       pc += 2;			/* point the pc at the 2nd half */
2566a1ba9ba4Schristos     case 31:			/* BL instruction 2 */
2567a1ba9ba4Schristos       if (state->is_v6)
2568a1ba9ba4Schristos 	{
2569a1ba9ba4Schristos 	  handle_T2_insn (state, old_tinstr, next_instr, pc, ainstr, & valid);
2570a1ba9ba4Schristos 	  break;
2571a1ba9ba4Schristos 	}
2572a1ba9ba4Schristos 
2573a1ba9ba4Schristos       /* Format 19 */
2574a1ba9ba4Schristos       /* There is no single ARM instruction equivalent for this
2575a1ba9ba4Schristos          instruction. Also, it should only ever be matched with the
2576a1ba9ba4Schristos          fmt19 "BL instruction 1" instruction. However, we do allow
2577a1ba9ba4Schristos          the simulation of it on its own, with undefined results if
2578a1ba9ba4Schristos          r14 is not suitably initialised.  */
2579a1ba9ba4Schristos       {
2580a1ba9ba4Schristos 	ARMword tmp = pc;
2581a1ba9ba4Schristos 
2582a1ba9ba4Schristos 	state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1));
2583a1ba9ba4Schristos 	state->Reg[14] = (tmp | 1);
2584a1ba9ba4Schristos 	valid = t_branch;
2585a1ba9ba4Schristos 	FLUSHPIPE;
2586a1ba9ba4Schristos       }
2587a1ba9ba4Schristos       break;
2588a1ba9ba4Schristos     }
2589a1ba9ba4Schristos 
2590a1ba9ba4Schristos   if (trace && valid != t_decoded)
2591a1ba9ba4Schristos     fprintf (stderr, "\n");
2592a1ba9ba4Schristos 
2593a1ba9ba4Schristos   return valid;
2594a1ba9ba4Schristos }
2595