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