static_inst.cc (7122:0c8bb53cdffe) static_inst.cc (7140:d2f0418e9390)
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Stephen Hines
41 */
42
43#include "arch/arm/faults.hh"
44#include "arch/arm/insts/static_inst.hh"
45#include "base/condcodes.hh"
46#include "base/cprintf.hh"
47#include "base/loader/symtab.hh"
48
49namespace ArmISA
50{
51// Shift Rm by an immediate value
52int32_t
53ArmStaticInstBase::shift_rm_imm(uint32_t base, uint32_t shamt,
54 uint32_t type, uint32_t cfval) const
55{
56 assert(shamt < 32);
57 ArmShiftType shiftType;
58 shiftType = (ArmShiftType)type;
59
60 switch (shiftType)
61 {
62 case LSL:
63 return base << shamt;
64 case LSR:
65 if (shamt == 0)
66 return 0;
67 else
68 return base >> shamt;
69 case ASR:
70 if (shamt == 0)
71 return (int32_t)base >> 31;
72 else
73 return (int32_t)base >> shamt;
74 case ROR:
75 if (shamt == 0)
76 return (cfval << 31) | (base >> 1); // RRX
77 else
78 return (base << (32 - shamt)) | (base >> shamt);
79 default:
80 ccprintf(std::cerr, "Unhandled shift type\n");
81 exit(1);
82 break;
83 }
84 return 0;
85}
86
87// Shift Rm by Rs
88int32_t
89ArmStaticInstBase::shift_rm_rs(uint32_t base, uint32_t shamt,
90 uint32_t type, uint32_t cfval) const
91{
92 enum ArmShiftType shiftType;
93 shiftType = (enum ArmShiftType) type;
94
95 switch (shiftType)
96 {
97 case LSL:
98 if (shamt >= 32)
99 return 0;
100 else
101 return base << shamt;
102 case LSR:
103 if (shamt >= 32)
104 return 0;
105 else
106 return base >> shamt;
107 case ASR:
108 if (shamt >= 32)
109 return (int32_t)base >> 31;
110 else
111 return (int32_t)base >> shamt;
112 case ROR:
113 shamt = shamt & 0x1f;
114 if (shamt == 0)
115 return base;
116 else
117 return (base << (32 - shamt)) | (base >> shamt);
118 default:
119 ccprintf(std::cerr, "Unhandled shift type\n");
120 exit(1);
121 break;
122 }
123 return 0;
124}
125
126
127// Generate C for a shift by immediate
128bool
129ArmStaticInstBase::shift_carry_imm(uint32_t base, uint32_t shamt,
130 uint32_t type, uint32_t cfval) const
131{
132 enum ArmShiftType shiftType;
133 shiftType = (enum ArmShiftType) type;
134
135 switch (shiftType)
136 {
137 case LSL:
138 if (shamt == 0)
139 return cfval;
140 else
141 return (base >> (32 - shamt)) & 1;
142 case LSR:
143 if (shamt == 0)
144 return (base >> 31);
145 else
146 return (base >> (shamt - 1)) & 1;
147 case ASR:
148 if (shamt == 0)
149 return (base >> 31);
150 else
151 return (base >> (shamt - 1)) & 1;
152 case ROR:
153 shamt = shamt & 0x1f;
154 if (shamt == 0)
155 return (base & 1); // RRX
156 else
157 return (base >> (shamt - 1)) & 1;
158 default:
159 ccprintf(std::cerr, "Unhandled shift type\n");
160 exit(1);
161 break;
162 }
163 return 0;
164}
165
166
167// Generate C for a shift by Rs
168bool
169ArmStaticInstBase::shift_carry_rs(uint32_t base, uint32_t shamt,
170 uint32_t type, uint32_t cfval) const
171{
172 enum ArmShiftType shiftType;
173 shiftType = (enum ArmShiftType) type;
174
175 if (shamt == 0)
176 return cfval;
177
178 switch (shiftType)
179 {
180 case LSL:
181 if (shamt > 32)
182 return 0;
183 else
184 return (base >> (32 - shamt)) & 1;
185 case LSR:
186 if (shamt > 32)
187 return 0;
188 else
189 return (base >> (shamt - 1)) & 1;
190 case ASR:
191 if (shamt > 32)
192 shamt = 32;
193 return (base >> (shamt - 1)) & 1;
194 case ROR:
195 shamt = shamt & 0x1f;
196 if (shamt == 0)
197 shamt = 32;
198 return (base >> (shamt - 1)) & 1;
199 default:
200 ccprintf(std::cerr, "Unhandled shift type\n");
201 exit(1);
202 break;
203 }
204 return 0;
205}
206
207
208// Generate the appropriate carry bit for an addition operation
209bool
210ArmStaticInstBase::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const
211{
212 return findCarry(32, result, lhs, rhs);
213}
214
215// Generate the appropriate carry bit for a subtraction operation
216bool
217ArmStaticInstBase::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const
218{
219 return findCarry(32, result, lhs, ~rhs);
220}
221
222bool
223ArmStaticInstBase::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const
224{
225 return findOverflow(32, result, lhs, rhs);
226}
227
228bool
229ArmStaticInstBase::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const
230{
231 return findOverflow(32, result, lhs, ~rhs);
232}
233
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Stephen Hines
41 */
42
43#include "arch/arm/faults.hh"
44#include "arch/arm/insts/static_inst.hh"
45#include "base/condcodes.hh"
46#include "base/cprintf.hh"
47#include "base/loader/symtab.hh"
48
49namespace ArmISA
50{
51// Shift Rm by an immediate value
52int32_t
53ArmStaticInstBase::shift_rm_imm(uint32_t base, uint32_t shamt,
54 uint32_t type, uint32_t cfval) const
55{
56 assert(shamt < 32);
57 ArmShiftType shiftType;
58 shiftType = (ArmShiftType)type;
59
60 switch (shiftType)
61 {
62 case LSL:
63 return base << shamt;
64 case LSR:
65 if (shamt == 0)
66 return 0;
67 else
68 return base >> shamt;
69 case ASR:
70 if (shamt == 0)
71 return (int32_t)base >> 31;
72 else
73 return (int32_t)base >> shamt;
74 case ROR:
75 if (shamt == 0)
76 return (cfval << 31) | (base >> 1); // RRX
77 else
78 return (base << (32 - shamt)) | (base >> shamt);
79 default:
80 ccprintf(std::cerr, "Unhandled shift type\n");
81 exit(1);
82 break;
83 }
84 return 0;
85}
86
87// Shift Rm by Rs
88int32_t
89ArmStaticInstBase::shift_rm_rs(uint32_t base, uint32_t shamt,
90 uint32_t type, uint32_t cfval) const
91{
92 enum ArmShiftType shiftType;
93 shiftType = (enum ArmShiftType) type;
94
95 switch (shiftType)
96 {
97 case LSL:
98 if (shamt >= 32)
99 return 0;
100 else
101 return base << shamt;
102 case LSR:
103 if (shamt >= 32)
104 return 0;
105 else
106 return base >> shamt;
107 case ASR:
108 if (shamt >= 32)
109 return (int32_t)base >> 31;
110 else
111 return (int32_t)base >> shamt;
112 case ROR:
113 shamt = shamt & 0x1f;
114 if (shamt == 0)
115 return base;
116 else
117 return (base << (32 - shamt)) | (base >> shamt);
118 default:
119 ccprintf(std::cerr, "Unhandled shift type\n");
120 exit(1);
121 break;
122 }
123 return 0;
124}
125
126
127// Generate C for a shift by immediate
128bool
129ArmStaticInstBase::shift_carry_imm(uint32_t base, uint32_t shamt,
130 uint32_t type, uint32_t cfval) const
131{
132 enum ArmShiftType shiftType;
133 shiftType = (enum ArmShiftType) type;
134
135 switch (shiftType)
136 {
137 case LSL:
138 if (shamt == 0)
139 return cfval;
140 else
141 return (base >> (32 - shamt)) & 1;
142 case LSR:
143 if (shamt == 0)
144 return (base >> 31);
145 else
146 return (base >> (shamt - 1)) & 1;
147 case ASR:
148 if (shamt == 0)
149 return (base >> 31);
150 else
151 return (base >> (shamt - 1)) & 1;
152 case ROR:
153 shamt = shamt & 0x1f;
154 if (shamt == 0)
155 return (base & 1); // RRX
156 else
157 return (base >> (shamt - 1)) & 1;
158 default:
159 ccprintf(std::cerr, "Unhandled shift type\n");
160 exit(1);
161 break;
162 }
163 return 0;
164}
165
166
167// Generate C for a shift by Rs
168bool
169ArmStaticInstBase::shift_carry_rs(uint32_t base, uint32_t shamt,
170 uint32_t type, uint32_t cfval) const
171{
172 enum ArmShiftType shiftType;
173 shiftType = (enum ArmShiftType) type;
174
175 if (shamt == 0)
176 return cfval;
177
178 switch (shiftType)
179 {
180 case LSL:
181 if (shamt > 32)
182 return 0;
183 else
184 return (base >> (32 - shamt)) & 1;
185 case LSR:
186 if (shamt > 32)
187 return 0;
188 else
189 return (base >> (shamt - 1)) & 1;
190 case ASR:
191 if (shamt > 32)
192 shamt = 32;
193 return (base >> (shamt - 1)) & 1;
194 case ROR:
195 shamt = shamt & 0x1f;
196 if (shamt == 0)
197 shamt = 32;
198 return (base >> (shamt - 1)) & 1;
199 default:
200 ccprintf(std::cerr, "Unhandled shift type\n");
201 exit(1);
202 break;
203 }
204 return 0;
205}
206
207
208// Generate the appropriate carry bit for an addition operation
209bool
210ArmStaticInstBase::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const
211{
212 return findCarry(32, result, lhs, rhs);
213}
214
215// Generate the appropriate carry bit for a subtraction operation
216bool
217ArmStaticInstBase::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const
218{
219 return findCarry(32, result, lhs, ~rhs);
220}
221
222bool
223ArmStaticInstBase::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const
224{
225 return findOverflow(32, result, lhs, rhs);
226}
227
228bool
229ArmStaticInstBase::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const
230{
231 return findOverflow(32, result, lhs, ~rhs);
232}
233
234uint32_t
235ArmStaticInstBase::modified_imm(uint8_t ctrlImm, uint8_t dataImm) const
236{
237 uint32_t bigData = dataImm;
238 uint32_t bigCtrl = ctrlImm;
239 if (bigCtrl < 4) {
240 switch (bigCtrl) {
241 case 0:
242 return bigData;
243 case 1:
244 return bigData | (bigData << 16);
245 case 2:
246 return (bigData << 8) | (bigData << 24);
247 case 3:
248 return (bigData << 0) | (bigData << 8) |
249 (bigData << 16) | (bigData << 24);
250 }
251 }
252 bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1);
253 bigData |= (1 << 7);
254 return bigData << (32 - bigCtrl);
255}
256
257void
258ArmStaticInstBase::printReg(std::ostream &os, int reg) const
259{
260 if (reg < FP_Base_DepTag) {
261 switch (reg) {
262 case PCReg:
263 ccprintf(os, "pc");
264 break;
265 case StackPointerReg:
266 ccprintf(os, "sp");
267 break;
268 case FramePointerReg:
269 ccprintf(os, "fp");
270 break;
271 case ReturnAddressReg:
272 ccprintf(os, "lr");
273 break;
274 default:
275 ccprintf(os, "r%d", reg);
276 break;
277 }
278 } else if (reg < Ctrl_Base_DepTag) {
279 ccprintf(os, "f%d", reg - FP_Base_DepTag);
280 } else {
281 reg -= Ctrl_Base_DepTag;
282 assert(reg < NUM_MISCREGS);
283 ccprintf(os, "%s", ArmISA::miscRegName[reg]);
284 }
285}
286
287void
288ArmStaticInstBase::printMnemonic(std::ostream &os,
289 const std::string &suffix,
290 bool withPred) const
291{
292 os << " " << mnemonic;
293 if (withPred) {
294 unsigned condCode = machInst.condCode;
295 switch (condCode) {
296 case COND_EQ:
297 os << "eq";
298 break;
299 case COND_NE:
300 os << "ne";
301 break;
302 case COND_CS:
303 os << "cs";
304 break;
305 case COND_CC:
306 os << "cc";
307 break;
308 case COND_MI:
309 os << "mi";
310 break;
311 case COND_PL:
312 os << "pl";
313 break;
314 case COND_VS:
315 os << "vs";
316 break;
317 case COND_VC:
318 os << "vc";
319 break;
320 case COND_HI:
321 os << "hi";
322 break;
323 case COND_LS:
324 os << "ls";
325 break;
326 case COND_GE:
327 os << "ge";
328 break;
329 case COND_LT:
330 os << "lt";
331 break;
332 case COND_GT:
333 os << "gt";
334 break;
335 case COND_LE:
336 os << "le";
337 break;
338 case COND_AL:
339 // This one is implicit.
340 break;
341 case COND_UC:
342 // Unconditional.
343 break;
344 default:
345 panic("Unrecognized condition code %d.\n", condCode);
346 }
347 os << suffix;
348 if (machInst.bigThumb)
349 os << ".w";
350 os << " ";
351 }
352}
353
354void
355ArmStaticInstBase::printMemSymbol(std::ostream &os,
356 const SymbolTable *symtab,
357 const std::string &prefix,
358 const Addr addr,
359 const std::string &suffix) const
360{
361 Addr symbolAddr;
362 std::string symbol;
363 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
364 ccprintf(os, "%s%s", prefix, symbol);
365 if (symbolAddr != addr)
366 ccprintf(os, "+%d", addr - symbolAddr);
367 ccprintf(os, suffix);
368 }
369}
370
371void
372ArmStaticInstBase::printShiftOperand(std::ostream &os) const
373{
374 printReg(os, machInst.rm);
375
376 bool immShift = (machInst.opcode4 == 0);
377 bool done = false;
378 unsigned shiftAmt = (machInst.shiftSize);
379 ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift;
380
381 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
382 shiftAmt = 32;
383
384 switch (type) {
385 case LSL:
386 if (immShift && shiftAmt == 0) {
387 done = true;
388 break;
389 }
390 os << ", LSL";
391 break;
392 case LSR:
393 os << ", LSR";
394 break;
395 case ASR:
396 os << ", ASR";
397 break;
398 case ROR:
399 if (immShift && shiftAmt == 0) {
400 os << ", RRX";
401 done = true;
402 break;
403 }
404 os << ", ROR";
405 break;
406 default:
407 panic("Tried to disassemble unrecognized shift type.\n");
408 }
409 if (!done) {
410 os << " ";
411 if (immShift)
412 os << "#" << shiftAmt;
413 else
414 printReg(os, machInst.rs);
415 }
416}
417
418void
419ArmStaticInstBase::printDataInst(std::ostream &os, bool withImm) const
420{
421 printMnemonic(os, machInst.sField ? "s" : "");
422 //XXX It would be nice if the decoder figured this all out for us.
423 unsigned opcode = machInst.opcode;
424 bool firstOp = true;
425
426 // Destination
427 // Cmp, cmn, teq, and tst don't have one.
428 if (opcode < 8 || opcode > 0xb) {
429 firstOp = false;
430 printReg(os, machInst.rd);
431 }
432
433 // Source 1.
434 // Mov and Movn don't have one of these.
435 if (opcode != 0xd && opcode != 0xf) {
436 if (!firstOp)
437 os << ", ";
438 firstOp = false;
439 printReg(os, machInst.rn);
440 }
441
442 if (!firstOp)
443 os << ", ";
444 if (withImm) {
445 unsigned rotate = machInst.rotate * 2;
446 uint32_t imm = machInst.imm;
447 ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate));
448 } else {
449 printShiftOperand(os);
450 }
451}
452
453std::string
454ArmStaticInstBase::generateDisassembly(Addr pc,
455 const SymbolTable *symtab) const
456{
457 std::stringstream ss;
458 printMnemonic(ss);
459 return ss.str();
460}
461}
234void
235ArmStaticInstBase::printReg(std::ostream &os, int reg) const
236{
237 if (reg < FP_Base_DepTag) {
238 switch (reg) {
239 case PCReg:
240 ccprintf(os, "pc");
241 break;
242 case StackPointerReg:
243 ccprintf(os, "sp");
244 break;
245 case FramePointerReg:
246 ccprintf(os, "fp");
247 break;
248 case ReturnAddressReg:
249 ccprintf(os, "lr");
250 break;
251 default:
252 ccprintf(os, "r%d", reg);
253 break;
254 }
255 } else if (reg < Ctrl_Base_DepTag) {
256 ccprintf(os, "f%d", reg - FP_Base_DepTag);
257 } else {
258 reg -= Ctrl_Base_DepTag;
259 assert(reg < NUM_MISCREGS);
260 ccprintf(os, "%s", ArmISA::miscRegName[reg]);
261 }
262}
263
264void
265ArmStaticInstBase::printMnemonic(std::ostream &os,
266 const std::string &suffix,
267 bool withPred) const
268{
269 os << " " << mnemonic;
270 if (withPred) {
271 unsigned condCode = machInst.condCode;
272 switch (condCode) {
273 case COND_EQ:
274 os << "eq";
275 break;
276 case COND_NE:
277 os << "ne";
278 break;
279 case COND_CS:
280 os << "cs";
281 break;
282 case COND_CC:
283 os << "cc";
284 break;
285 case COND_MI:
286 os << "mi";
287 break;
288 case COND_PL:
289 os << "pl";
290 break;
291 case COND_VS:
292 os << "vs";
293 break;
294 case COND_VC:
295 os << "vc";
296 break;
297 case COND_HI:
298 os << "hi";
299 break;
300 case COND_LS:
301 os << "ls";
302 break;
303 case COND_GE:
304 os << "ge";
305 break;
306 case COND_LT:
307 os << "lt";
308 break;
309 case COND_GT:
310 os << "gt";
311 break;
312 case COND_LE:
313 os << "le";
314 break;
315 case COND_AL:
316 // This one is implicit.
317 break;
318 case COND_UC:
319 // Unconditional.
320 break;
321 default:
322 panic("Unrecognized condition code %d.\n", condCode);
323 }
324 os << suffix;
325 if (machInst.bigThumb)
326 os << ".w";
327 os << " ";
328 }
329}
330
331void
332ArmStaticInstBase::printMemSymbol(std::ostream &os,
333 const SymbolTable *symtab,
334 const std::string &prefix,
335 const Addr addr,
336 const std::string &suffix) const
337{
338 Addr symbolAddr;
339 std::string symbol;
340 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
341 ccprintf(os, "%s%s", prefix, symbol);
342 if (symbolAddr != addr)
343 ccprintf(os, "+%d", addr - symbolAddr);
344 ccprintf(os, suffix);
345 }
346}
347
348void
349ArmStaticInstBase::printShiftOperand(std::ostream &os) const
350{
351 printReg(os, machInst.rm);
352
353 bool immShift = (machInst.opcode4 == 0);
354 bool done = false;
355 unsigned shiftAmt = (machInst.shiftSize);
356 ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift;
357
358 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
359 shiftAmt = 32;
360
361 switch (type) {
362 case LSL:
363 if (immShift && shiftAmt == 0) {
364 done = true;
365 break;
366 }
367 os << ", LSL";
368 break;
369 case LSR:
370 os << ", LSR";
371 break;
372 case ASR:
373 os << ", ASR";
374 break;
375 case ROR:
376 if (immShift && shiftAmt == 0) {
377 os << ", RRX";
378 done = true;
379 break;
380 }
381 os << ", ROR";
382 break;
383 default:
384 panic("Tried to disassemble unrecognized shift type.\n");
385 }
386 if (!done) {
387 os << " ";
388 if (immShift)
389 os << "#" << shiftAmt;
390 else
391 printReg(os, machInst.rs);
392 }
393}
394
395void
396ArmStaticInstBase::printDataInst(std::ostream &os, bool withImm) const
397{
398 printMnemonic(os, machInst.sField ? "s" : "");
399 //XXX It would be nice if the decoder figured this all out for us.
400 unsigned opcode = machInst.opcode;
401 bool firstOp = true;
402
403 // Destination
404 // Cmp, cmn, teq, and tst don't have one.
405 if (opcode < 8 || opcode > 0xb) {
406 firstOp = false;
407 printReg(os, machInst.rd);
408 }
409
410 // Source 1.
411 // Mov and Movn don't have one of these.
412 if (opcode != 0xd && opcode != 0xf) {
413 if (!firstOp)
414 os << ", ";
415 firstOp = false;
416 printReg(os, machInst.rn);
417 }
418
419 if (!firstOp)
420 os << ", ";
421 if (withImm) {
422 unsigned rotate = machInst.rotate * 2;
423 uint32_t imm = machInst.imm;
424 ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate));
425 } else {
426 printShiftOperand(os);
427 }
428}
429
430std::string
431ArmStaticInstBase::generateDisassembly(Addr pc,
432 const SymbolTable *symtab) const
433{
434 std::stringstream ss;
435 printMnemonic(ss);
436 return ss.str();
437}
438}