pj-dis.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* pj-dis.c -- Disassemble picoJava instructions.
  2. Copyright (C) 1999-2022 Free Software Foundation, Inc.
  3. Contributed by Steve Chamberlain, of Transmeta (sac@pobox.com).
  4. This file is part of the GNU opcodes library.
  5. This library is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. It is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  12. License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "sysdep.h"
  18. #include <stdio.h>
  19. #include "libiberty.h"
  20. #include "opcode/pj.h"
  21. #include "disassemble.h"
  22. extern const pj_opc_info_t pj_opc_info[512];
  23. static int
  24. get_int (bfd_vma memaddr, int *iptr, struct disassemble_info *info)
  25. {
  26. unsigned char ival[4];
  27. int status = info->read_memory_func (memaddr, ival, 4, info);
  28. *iptr = (((unsigned) ival[0] << 24)
  29. | (ival[1] << 16)
  30. | (ival[2] << 8)
  31. | (ival[3] << 0));
  32. return status;
  33. }
  34. int
  35. print_insn_pj (bfd_vma addr, struct disassemble_info *info)
  36. {
  37. fprintf_ftype fprintf_fn = info->fprintf_func;
  38. void *stream = info->stream;
  39. unsigned char opcode;
  40. int status;
  41. if ((status = info->read_memory_func (addr, &opcode, 1, info)))
  42. goto fail;
  43. if (opcode == 0xff)
  44. {
  45. unsigned char byte_2;
  46. if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info)))
  47. goto fail;
  48. fprintf_fn (stream, "%s", pj_opc_info[opcode + byte_2].u.name);
  49. return 2;
  50. }
  51. else
  52. {
  53. char *sep = "\t";
  54. int insn_start = addr;
  55. const pj_opc_info_t *op = &pj_opc_info[opcode];
  56. unsigned int a;
  57. addr++;
  58. fprintf_fn (stream, "%s", op->u.name);
  59. /* The tableswitch instruction is followed by the default
  60. address, low value, high value and the destinations. */
  61. if (strcmp (op->u.name, "tableswitch") == 0)
  62. {
  63. int lowval;
  64. int highval;
  65. int val;
  66. addr = (addr + 3) & ~3;
  67. if ((status = get_int (addr, &val, info)))
  68. goto fail;
  69. fprintf_fn (stream, " default: ");
  70. (*info->print_address_func) (val + insn_start, info);
  71. addr += 4;
  72. if ((status = get_int (addr, &lowval, info)))
  73. goto fail;
  74. addr += 4;
  75. if ((status = get_int (addr, &highval, info)))
  76. goto fail;
  77. addr += 4;
  78. while (lowval <= highval)
  79. {
  80. if ((status = get_int (addr, &val, info)))
  81. goto fail;
  82. fprintf_fn (stream, " %d:[", lowval);
  83. (*info->print_address_func) (val + insn_start, info);
  84. fprintf_fn (stream, " ]");
  85. addr += 4;
  86. lowval++;
  87. }
  88. return addr - insn_start;
  89. }
  90. /* The lookupswitch instruction is followed by the default
  91. address, element count and pairs of values and
  92. addresses. */
  93. if (strcmp (op->u.name, "lookupswitch") == 0)
  94. {
  95. int count;
  96. int val;
  97. addr = (addr + 3) & ~3;
  98. if ((status = get_int (addr, &val, info)))
  99. goto fail;
  100. addr += 4;
  101. fprintf_fn (stream, " default: ");
  102. (*info->print_address_func) (val + insn_start, info);
  103. if ((status = get_int (addr, &count, info)))
  104. goto fail;
  105. addr += 4;
  106. while (count--)
  107. {
  108. if ((status = get_int (addr, &val, info)))
  109. goto fail;
  110. addr += 4;
  111. fprintf_fn (stream, " %d:[", val);
  112. if ((status = get_int (addr, &val, info)))
  113. goto fail;
  114. addr += 4;
  115. (*info->print_address_func) (val + insn_start, info);
  116. fprintf_fn (stream, " ]");
  117. }
  118. return addr - insn_start;
  119. }
  120. for (a = 0; a < ARRAY_SIZE (op->arg) && op->arg[a]; a++)
  121. {
  122. unsigned char data[4];
  123. int val = 0;
  124. int i;
  125. int size = ASIZE (op->arg[a]);
  126. if ((status = info->read_memory_func (addr, data, size, info)))
  127. goto fail;
  128. val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1;
  129. for (i = 0; i < size; i++)
  130. val = ((unsigned) val << 8) | (data[i] & 0xff);
  131. fprintf_fn (stream, "%s", sep);
  132. if (PCREL (op->arg[a]))
  133. (*info->print_address_func) (val + insn_start, info);
  134. else
  135. fprintf_fn (stream, "%d", val);
  136. sep = ",";
  137. addr += size;
  138. }
  139. return op->len;
  140. }
  141. fail:
  142. info->memory_error_func (status, addr, info);
  143. return -1;
  144. }