blob: 5a7006bd1f77048b0ccf35df6b1bd62aee45d00e [file] [log] [blame]
Greg Clayton6da4ca82011-01-21 22:02:52 +00001//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Greg Clayton95e31422011-02-05 02:56:16 +000010#include "lldb/Core/EmulateInstruction.h"
Greg Clayton6da4ca82011-01-21 22:02:52 +000011
Caroline Ticead379efc2011-04-05 18:46:00 +000012#include "lldb/Core/DataBufferHeap.h"
Greg Clayton6da4ca82011-01-21 22:02:52 +000013#include "lldb/Core/DataExtractor.h"
Caroline Ticead379efc2011-04-05 18:46:00 +000014#include "lldb/Core/Error.h"
Greg Clayton4272cc72011-02-02 02:24:04 +000015#include "lldb/Core/PluginManager.h"
Greg Clayton6da4ca82011-01-21 22:02:52 +000016#include "lldb/Core/StreamString.h"
Greg Clayton7fb56d02011-02-01 01:31:41 +000017#include "lldb/Host/Endian.h"
Caroline Ticead379efc2011-04-05 18:46:00 +000018#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/Thread.h"
21
22#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
23
Greg Clayton6da4ca82011-01-21 22:02:52 +000024using namespace lldb;
25using namespace lldb_private;
26
Greg Clayton4272cc72011-02-02 02:24:04 +000027EmulateInstruction*
Greg Clayton514487e2011-02-15 21:59:32 +000028EmulateInstruction::FindPlugin (const ArchSpec &arch, const char *plugin_name)
Greg Clayton4272cc72011-02-02 02:24:04 +000029{
30 EmulateInstructionCreateInstance create_callback = NULL;
31 if (plugin_name)
32 {
33 create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (plugin_name);
34 if (create_callback)
35 {
Caroline Ticead379efc2011-04-05 18:46:00 +000036 EmulateInstruction *emulate_insn_ptr = create_callback(arch);
37 if (emulate_insn_ptr)
38 return emulate_insn_ptr;
Greg Clayton4272cc72011-02-02 02:24:04 +000039 }
40 }
41 else
42 {
43 for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != NULL; ++idx)
44 {
Caroline Ticead379efc2011-04-05 18:46:00 +000045 EmulateInstruction *emulate_insn_ptr = create_callback(arch);
46 if (emulate_insn_ptr)
47 return emulate_insn_ptr;
Greg Clayton4272cc72011-02-02 02:24:04 +000048 }
49 }
50 return NULL;
51}
Greg Clayton6da4ca82011-01-21 22:02:52 +000052
53EmulateInstruction::EmulateInstruction
54(
55 lldb::ByteOrder byte_order,
56 uint32_t addr_byte_size,
Caroline Ticead379efc2011-04-05 18:46:00 +000057 const ArchSpec &arch,
Greg Clayton6da4ca82011-01-21 22:02:52 +000058 void *baton,
59 ReadMemory read_mem_callback,
60 WriteMemory write_mem_callback,
61 ReadRegister read_reg_callback,
62 WriteRegister write_reg_callback
63) :
Greg Clayton7fb56d02011-02-01 01:31:41 +000064 m_byte_order (endian::InlHostByteOrder()),
Caroline Ticead379efc2011-04-05 18:46:00 +000065 m_addr_byte_size (addr_byte_size),
66 m_arch (arch),
Greg Clayton6da4ca82011-01-21 22:02:52 +000067 m_baton (baton),
68 m_read_mem_callback (read_mem_callback),
69 m_write_mem_callback (write_mem_callback),
70 m_read_reg_callback (read_reg_callback),
71 m_write_reg_callback (write_reg_callback),
Caroline Tice25d61ac2011-04-08 23:33:06 +000072 m_opcode_pc (LLDB_INVALID_ADDRESS),
Stephen Wilson71c21d12011-04-11 19:41:40 +000073 m_opcode (),
Caroline Tice25d61ac2011-04-08 23:33:06 +000074 m_advance_pc (false)
Greg Clayton6da4ca82011-01-21 22:02:52 +000075{
Greg Clayton6da4ca82011-01-21 22:02:52 +000076}
77
Caroline Ticead379efc2011-04-05 18:46:00 +000078EmulateInstruction::EmulateInstruction
79(
80 lldb::ByteOrder byte_order,
81 uint32_t addr_byte_size,
82 const ArchSpec &arch
83) :
84 m_byte_order (endian::InlHostByteOrder()),
85 m_addr_byte_size (addr_byte_size),
86 m_arch (arch),
87 m_baton (NULL),
88 m_read_mem_callback (&ReadMemoryDefault),
89 m_write_mem_callback (&WriteMemoryDefault),
90 m_read_reg_callback (&ReadRegisterDefault),
91 m_write_reg_callback (&WriteRegisterDefault),
Caroline Tice25d61ac2011-04-08 23:33:06 +000092 m_opcode_pc (LLDB_INVALID_ADDRESS),
93 m_advance_pc (false)
Caroline Ticead379efc2011-04-05 18:46:00 +000094{
95 ::memset (&m_opcode, 0, sizeof (m_opcode));
96}
97
Greg Clayton6da4ca82011-01-21 22:02:52 +000098uint64_t
99EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr)
100{
101 uint64_t uval64 = 0;
102 bool success = m_read_reg_callback (m_baton, reg_kind, reg_num, uval64);
103 if (success_ptr)
104 *success_ptr = success;
105 if (!success)
106 uval64 = fail_value;
107 return uval64;
108}
109
110bool
111EmulateInstruction::WriteRegisterUnsigned (const Context &context, uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value)
112{
113 return m_write_reg_callback (m_baton, context, reg_kind, reg_num, reg_value);
114}
115
116uint64_t
117EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
118{
119 uint64_t uval64 = 0;
120 bool success = false;
121 if (byte_size <= 8)
122 {
123 uint8_t buf[sizeof(uint64_t)];
124 size_t bytes_read = m_read_mem_callback (m_baton, context, addr, buf, byte_size);
125 if (bytes_read == byte_size)
126 {
127 uint32_t offset = 0;
128 DataExtractor data (buf, byte_size, m_byte_order, m_addr_byte_size);
129 uval64 = data.GetMaxU64 (&offset, byte_size);
130 success = true;
131 }
132 }
133
134 if (success_ptr)
135 *success_ptr = success;
136
137 if (!success)
138 uval64 = fail_value;
139 return uval64;
140}
141
142
143bool
144EmulateInstruction::WriteMemoryUnsigned (const Context &context,
145 lldb::addr_t addr,
146 uint64_t uval,
147 size_t uval_byte_size)
148{
149 StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
150 strm.PutMaxHex64 (uval, uval_byte_size);
151
152 size_t bytes_written = m_write_mem_callback (m_baton, context, addr, strm.GetData(), uval_byte_size);
153 if (bytes_written == uval_byte_size)
154 return true;
155 return false;
156}
Caroline Ticead379efc2011-04-05 18:46:00 +0000157
158
159void
160EmulateInstruction::SetBaton (void *baton)
161{
162 m_baton = baton;
163}
164
165void
166EmulateInstruction::SetCallbacks (ReadMemory read_mem_callback,
167 WriteMemory write_mem_callback,
168 ReadRegister read_reg_callback,
169 WriteRegister write_reg_callback)
170{
171 m_read_mem_callback = read_mem_callback;
172 m_write_mem_callback = write_mem_callback;
173 m_read_reg_callback = read_reg_callback;
174 m_write_reg_callback = write_reg_callback;
175}
176
177void
178EmulateInstruction::SetReadMemCallback (ReadMemory read_mem_callback)
179{
180 m_read_mem_callback = read_mem_callback;
181}
182
183
184void
185EmulateInstruction::SetWriteMemCallback (WriteMemory write_mem_callback)
186{
187 m_write_mem_callback = write_mem_callback;
188}
189
190
191void
192EmulateInstruction::SetReadRegCallback (ReadRegister read_reg_callback)
193{
194 m_read_reg_callback = read_reg_callback;
195}
196
197
198void
199EmulateInstruction::SetWriteRegCallback (WriteRegister write_reg_callback)
200{
201 m_write_reg_callback = write_reg_callback;
202}
203
204
205
206//
207// Read & Write Memory and Registers callback functions.
208//
209
210size_t
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000211EmulateInstruction::ReadMemoryFrame (void *baton,
212 const Context &context,
213 lldb::addr_t addr,
214 void *dst,
215 size_t length)
Caroline Ticead379efc2011-04-05 18:46:00 +0000216{
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000217 if (!baton)
Caroline Ticead379efc2011-04-05 18:46:00 +0000218 return 0;
219
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000220
221 StackFrame *frame = (StackFrame *) baton;
222
Caroline Ticead379efc2011-04-05 18:46:00 +0000223 DataBufferSP data_sp (new DataBufferHeap (length, '\0'));
224 Error error;
225
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000226 size_t bytes_read = frame->GetThread().GetProcess().ReadMemory (addr, data_sp->GetBytes(), data_sp->GetByteSize(),
227 error);
Caroline Ticead379efc2011-04-05 18:46:00 +0000228
229 if (bytes_read > 0)
230 ((DataBufferHeap *) data_sp.get())->CopyData (dst, length);
231
232 return bytes_read;
233}
234
235size_t
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000236EmulateInstruction::WriteMemoryFrame (void *baton,
237 const Context &context,
238 lldb::addr_t addr,
239 const void *dst,
240 size_t length)
Caroline Ticead379efc2011-04-05 18:46:00 +0000241{
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000242 if (!baton)
Caroline Ticead379efc2011-04-05 18:46:00 +0000243 return 0;
244
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000245 StackFrame *frame = (StackFrame *) baton;
246
Caroline Ticead379efc2011-04-05 18:46:00 +0000247 lldb::DataBufferSP data_sp (new DataBufferHeap (dst, length));
248 if (data_sp)
249 {
250 length = data_sp->GetByteSize();
251 if (length > 0)
252 {
253 Error error;
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000254 size_t bytes_written = frame->GetThread().GetProcess().WriteMemory (addr, data_sp->GetBytes(), length,
255 error);
Caroline Ticead379efc2011-04-05 18:46:00 +0000256
257 return bytes_written;
258 }
259 }
260
261 return 0;
262}
263
264bool
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000265EmulateInstruction::ReadRegisterFrame (void *baton,
266 uint32_t reg_kind,
267 uint32_t reg_num,
268 uint64_t &reg_value)
Caroline Ticead379efc2011-04-05 18:46:00 +0000269{
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000270 if (!baton)
Caroline Ticead379efc2011-04-05 18:46:00 +0000271 return false;
272
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000273 StackFrame *frame = (StackFrame *) baton;
274 RegisterContext *reg_context = frame->GetRegisterContext().get();
Caroline Ticead379efc2011-04-05 18:46:00 +0000275 Scalar value;
276
Caroline Ticec1bcafd2011-04-06 23:30:18 +0000277 uint32_t internal_reg_num = reg_context->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
Caroline Ticead379efc2011-04-05 18:46:00 +0000278
Caroline Ticec1bcafd2011-04-06 23:30:18 +0000279 if (internal_reg_num == LLDB_INVALID_REGNUM)
280 return false;
281
282 if (reg_context->ReadRegisterValue (internal_reg_num, value))
Caroline Ticead379efc2011-04-05 18:46:00 +0000283 {
284 reg_value = value.GetRawBits64 (0);
285 return true;
286 }
287
288 return false;
289}
290
291bool
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000292EmulateInstruction::WriteRegisterFrame (void *baton,
293 const Context &context,
294 uint32_t reg_kind,
295 uint32_t reg_num,
296 uint64_t reg_value)
Caroline Ticead379efc2011-04-05 18:46:00 +0000297{
Caroline Tice3d50b2f2011-04-05 20:18:48 +0000298 if (!baton)
299 return false;
300
301 StackFrame *frame = (StackFrame *) baton;
302 RegisterContext *reg_context = frame->GetRegisterContext().get();
Caroline Ticead379efc2011-04-05 18:46:00 +0000303 Scalar value (reg_value);
304
Caroline Ticec1bcafd2011-04-06 23:30:18 +0000305 uint32_t internal_reg_num = reg_context->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
306 if (internal_reg_num != LLDB_INVALID_REGNUM)
307 return reg_context->WriteRegisterValue (internal_reg_num, value);
308 else
309 return false;
Caroline Ticead379efc2011-04-05 18:46:00 +0000310}
311
312size_t
313EmulateInstruction::ReadMemoryDefault (void *baton,
314 const Context &context,
315 lldb::addr_t addr,
316 void *dst,
317 size_t length)
318{
319 PrintContext ("Read from memory", context);
Greg Claytoneb0103f2011-04-07 22:46:35 +0000320 fprintf (stdout, " Read from Memory (address = %p, length = %d)\n",(void *) addr, (uint32_t) length);
Caroline Ticead379efc2011-04-05 18:46:00 +0000321
322 *((uint64_t *) dst) = 0xdeadbeef;
323 return length;
324}
325
326size_t
327EmulateInstruction::WriteMemoryDefault (void *baton,
328 const Context &context,
329 lldb::addr_t addr,
330 const void *dst,
331 size_t length)
332{
333 PrintContext ("Write to memory", context);
Greg Claytoneb0103f2011-04-07 22:46:35 +0000334 fprintf (stdout, " Write to Memory (address = %p, length = %d)\n", (void *) addr, (uint32_t) length);
Caroline Ticead379efc2011-04-05 18:46:00 +0000335 return length;
336}
337
338bool
339EmulateInstruction::ReadRegisterDefault (void *baton,
340 uint32_t reg_kind,
341 uint32_t reg_num,
342 uint64_t &reg_value)
343{
344 std::string reg_name;
345 TranslateRegister (reg_kind, reg_num, reg_name);
346 fprintf (stdout, " Read Register (%s)\n", reg_name.c_str());
347
348 reg_value = 24;
349 return true;
350}
351
352bool
353EmulateInstruction::WriteRegisterDefault (void *baton,
354 const Context &context,
355 uint32_t reg_kind,
356 uint32_t reg_num,
357 uint64_t reg_value)
358{
359 PrintContext ("Write to register", context);
360 std::string reg_name;
361 TranslateRegister (reg_kind, reg_num, reg_name);
362 fprintf (stdout, " Write to Register (%s), value = 0x%llx\n", reg_name.c_str(), reg_value);
363 return true;
364}
365
366void
367EmulateInstruction::PrintContext (const char *context_type, const Context &context)
368{
369 switch (context.type)
370 {
371 case eContextReadOpcode:
372 fprintf (stdout, " %s context: Reading an Opcode\n", context_type);
373 break;
374
375 case eContextImmediate:
376 fprintf (stdout, " %s context: Immediate\n", context_type);
377 break;
378
379 case eContextPushRegisterOnStack:
380 fprintf (stdout, " %s context: Pushing a register onto the stack.\n", context_type);
381 break;
382
383 case eContextPopRegisterOffStack:
384 fprintf (stdout, " %s context: Popping a register off the stack.\n", context_type);
385 break;
386
387 case eContextAdjustStackPointer:
388 fprintf (stdout, " %s context: Adjusting the stack pointer.\n", context_type);
389 break;
390
391 case eContextAdjustBaseRegister:
392 fprintf (stdout, " %s context: Adjusting (writing value back to) a base register.\n", context_type);
393 break;
394
395 case eContextRegisterPlusOffset:
396 fprintf (stdout, " %s context: Register plus offset\n", context_type);
397 break;
398
399 case eContextRegisterStore:
400 fprintf (stdout, " %s context: Storing a register.\n", context_type);
401 break;
402
403 case eContextRegisterLoad:
404 fprintf (stdout, " %s context: Loading a register.\n", context_type);
405 break;
406
407 case eContextRelativeBranchImmediate:
408 fprintf (stdout, " %s context: Relative branch immediate\n", context_type);
409 break;
410
411 case eContextAbsoluteBranchRegister:
412 fprintf (stdout, " %s context: Absolute branch register\n", context_type);
413 break;
414
415 case eContextSupervisorCall:
416 fprintf (stdout, " %s context: Performing a supervisor call.\n", context_type);
417 break;
418
419 case eContextTableBranchReadMemory:
420 fprintf (stdout, " %s context: Table branch read memory\n", context_type);
421 break;
422
423 case eContextWriteRegisterRandomBits:
424 fprintf (stdout, " %s context: Write random bits to a register\n", context_type);
425 break;
426
427 case eContextWriteMemoryRandomBits:
428 fprintf (stdout, " %s context: Write random bits to a memory address\n", context_type);
429 break;
430
431 case eContextMultiplication:
432 fprintf (stdout, " %s context: Performing a multiplication\n", context_type);
433 break;
434
435 case eContextAddition:
436 fprintf (stdout, " %s context: Performing an addition\n", context_type);
437 break;
438
439 case eContextReturnFromException:
440 fprintf (stdout, " %s context: Returning from an exception\n", context_type);
441 break;
442
443 default:
444 fprintf (stdout, " %s context: Unrecognized context.\n", context_type);
445 break;
446 }
447
448 switch (context.info_type)
449 {
450 case eInfoTypeRegisterPlusOffset:
451 {
452 std::string reg_name;
453 TranslateRegister (context.info.RegisterPlusOffset.reg.kind,
454 context.info.RegisterPlusOffset.reg.num,
455 reg_name);
456 fprintf (stdout, " Info type: Register plus offset (%s +/- %lld)\n", reg_name.c_str(),
457 context.info.RegisterPlusOffset.signed_offset);
458 }
459 break;
460 case eInfoTypeRegisterPlusIndirectOffset:
461 {
462 std::string base_reg_name;
463 std::string offset_reg_name;
464 TranslateRegister (context.info.RegisterPlusIndirectOffset.base_reg.kind,
465 context.info.RegisterPlusIndirectOffset.base_reg.num,
466 base_reg_name);
467 TranslateRegister (context.info.RegisterPlusIndirectOffset.offset_reg.kind,
468 context.info.RegisterPlusIndirectOffset.offset_reg.num,
469 offset_reg_name);
470 fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s)\n",
471 base_reg_name.c_str(),
472 offset_reg_name.c_str());
473 }
474 break;
475 case eInfoTypeRegisterToRegisterPlusOffset:
476 {
477 std::string base_reg_name;
478 std::string data_reg_name;
479 TranslateRegister (context.info.RegisterToRegisterPlusOffset.base_reg.kind,
480 context.info.RegisterToRegisterPlusOffset.base_reg.num,
481 base_reg_name);
482 TranslateRegister (context.info.RegisterToRegisterPlusOffset.data_reg.kind,
483 context.info.RegisterToRegisterPlusOffset.data_reg.num,
484 data_reg_name);
485 fprintf (stdout, " Info type: Register plus offset (%s +/- %lld) and data register (%s)\n",
486 base_reg_name.c_str(), context.info.RegisterToRegisterPlusOffset.offset,
487 data_reg_name.c_str());
488 }
489 break;
490 case eInfoTypeRegisterToRegisterPlusIndirectOffset:
491 {
492 std::string base_reg_name;
493 std::string offset_reg_name;
494 std::string data_reg_name;
495 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.base_reg.kind,
496 context.info.RegisterToRegisterPlusIndirectOffset.base_reg.num,
497 base_reg_name);
498 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.kind,
499 context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.num,
500 offset_reg_name);
501 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.data_reg.kind,
502 context.info.RegisterToRegisterPlusIndirectOffset.data_reg.num,
503 data_reg_name);
504 fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s) and data register (%s)\n",
505 base_reg_name.c_str(), offset_reg_name.c_str(), data_reg_name.c_str());
506 }
507 break;
508
509 case eInfoTypeRegisterRegisterOperands:
510 {
511 std::string op1_reg_name;
512 std::string op2_reg_name;
513 TranslateRegister (context.info.RegisterRegisterOperands.operand1.kind,
514 context.info.RegisterRegisterOperands.operand1.num,
515 op1_reg_name);
516 TranslateRegister (context.info.RegisterRegisterOperands.operand2.kind,
517 context.info.RegisterRegisterOperands.operand2.num,
518 op2_reg_name);
519 fprintf (stdout, " Info type: Register operands for binary op (%s, %s)\n",
520 op1_reg_name.c_str(),
521 op2_reg_name.c_str());
522 }
523 break;
524 case eInfoTypeOffset:
525 fprintf (stdout, " Info type: signed offset (%lld)\n", context.info.signed_offset);
526 break;
527
528 case eInfoTypeRegister:
529 {
530 std::string reg_name;
531 TranslateRegister (context.info.reg.kind, context.info.reg.num, reg_name);
532 fprintf (stdout, " Info type: Register (%s)\n", reg_name.c_str());
533 }
534 break;
535
536 case eInfoTypeImmediate:
537 fprintf (stdout, " Info type: Immediate (%lld)\n", context.info.immediate);
538 break;
539
540 case eInfoTypeImmediateSigned:
541 fprintf (stdout, " Info type: Signed immediate (%lld)\n", context.info.signed_immediate);
542 break;
543
544 case eInfoTypeAddress:
545 fprintf (stdout, " Info type: Address (%p)\n", (void *) context.info.address);
546 break;
547
548 case eInfoTypeModeAndImmediate:
549 {
550 std::string mode_name;
551
552 if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeARM)
553 mode_name = "ARM";
554 else if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeThumb)
555 mode_name = "Thumb";
556 else
557 mode_name = "Unknown mode";
558
559 fprintf (stdout, " Info type: Mode (%s) and immediate (%d)\n", mode_name.c_str(),
560 context.info.ModeAndImmediate.data_value);
561 }
562 break;
563
564 case eInfoTypeModeAndImmediateSigned:
565 {
566 std::string mode_name;
567
568 if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeARM)
569 mode_name = "ARM";
570 else if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeThumb)
571 mode_name = "Thumb";
572 else
573 mode_name = "Unknown mode";
574
575 fprintf (stdout, " Info type: Mode (%s) and signed immediate (%d)\n", mode_name.c_str(),
576 context.info.ModeAndImmediateSigned.signed_data_value);
577 }
578 break;
579
580 case eInfoTypeMode:
581 {
582 std::string mode_name;
583
584 if (context.info.mode == EmulateInstructionARM::eModeARM)
585 mode_name = "ARM";
586 else if (context.info.mode == EmulateInstructionARM::eModeThumb)
587 mode_name = "Thumb";
588 else
589 mode_name = "Unknown mode";
590
591 fprintf (stdout, " Info type: Mode (%s)\n", mode_name.c_str());
592 }
593 break;
594
595 case eInfoTypeNoArgs:
596 fprintf (stdout, " Info type: no arguments\n");
597 break;
598
599 default:
600 break;
601 }
602}
603
604void
605EmulateInstruction::TranslateRegister (uint32_t kind, uint32_t num, std::string &name)
606{
607 if (kind == eRegisterKindDWARF)
608 {
609 if (num == 13) //dwarf_sp NOTE: This is ARM-SPECIFIC
610 name = "sp";
611 else if (num == 14) //dwarf_lr NOTE: This is ARM-SPECIFIC
612 name = "lr";
613 else if (num == 15) //dwarf_pc NOTE: This is ARM-SPECIFIC
614 name = "pc";
615 else if (num == 16) //dwarf_cpsr NOTE: This is ARM-SPECIFIC
616 name = "cpsr";
617 else
618 {
619 StreamString sstr;
620
621 sstr.Printf ("r%d", num);
622 name = sstr.GetData();
623 }
624
625 }
626 else if (kind == eRegisterKindGeneric)
627 {
628 if (num == LLDB_REGNUM_GENERIC_SP)
629 name = "sp";
630 else if (num == LLDB_REGNUM_GENERIC_FLAGS)
631 name = "cpsr";
632 else if (num == LLDB_REGNUM_GENERIC_PC)
633 name = "pc";
634 else if (num == LLDB_REGNUM_GENERIC_RA)
635 name = "lr";
636 else
637 {
638 StreamString sstr;
639
640 sstr.Printf ("r%d", num);
641 name = sstr.GetData();
642 }
643 }
644 else
645 {
646 StreamString sstr;
647
648 sstr.Printf ("r%d", num);
649 name = sstr.GetData();
650 }
651}
652
653
654