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