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