1 /* Disassemble moxie instructions. 2 Copyright 2009 3 Free Software Foundation, Inc. 4 5 This file is part of the GNU opcodes library. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include <stdio.h> 23 #include "sysdep.h" 24 #define STATIC_TABLE 25 #define DEFINE_TABLE 26 27 #include "opcode/moxie.h" 28 #include "dis-asm.h" 29 30 static fprintf_ftype fpr; 31 static void *stream; 32 33 /* Macros to extract operands from the instruction word. */ 34 #define OP_A(i) ((i >> 4) & 0xf) 35 #define OP_B(i) (i & 0xf) 36 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) 37 38 static const char * reg_names[16] = 39 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", 40 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; 41 42 int 43 print_insn_moxie (bfd_vma addr, struct disassemble_info * info) 44 { 45 int length = 2; 46 int status; 47 stream = info->stream; 48 const moxie_opc_info_t * opcode; 49 bfd_byte buffer[4]; 50 unsigned short iword; 51 fpr = info->fprintf_func; 52 53 if ((status = info->read_memory_func (addr, buffer, 2, info))) 54 goto fail; 55 iword = bfd_getb16 (buffer); 56 57 /* Form 1 instructions have the high bit set to 0. */ 58 if ((iword & (1<<15)) == 0) 59 { 60 /* Extract the Form 1 opcode. */ 61 opcode = &moxie_form1_opc_info[iword >> 8]; 62 switch (opcode->itype) 63 { 64 case MOXIE_F1_NARG: 65 fpr (stream, "%s", opcode->name); 66 break; 67 case MOXIE_F1_A: 68 fpr (stream, "%s\t%s", opcode->name, 69 reg_names[OP_A(iword)]); 70 break; 71 case MOXIE_F1_AB: 72 fpr (stream, "%s\t%s, %s", opcode->name, 73 reg_names[OP_A(iword)], 74 reg_names[OP_B(iword)]); 75 break; 76 case MOXIE_F1_A4: 77 { 78 unsigned imm; 79 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 80 goto fail; 81 imm = bfd_getb32 (buffer); 82 fpr (stream, "%s\t%s, 0x%x", opcode->name, 83 reg_names[OP_A(iword)], imm); 84 length = 6; 85 } 86 break; 87 case MOXIE_F1_4: 88 { 89 unsigned imm; 90 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 91 goto fail; 92 imm = bfd_getb32 (buffer); 93 fpr (stream, "%s\t0x%x", opcode->name, imm); 94 length = 6; 95 } 96 break; 97 case MOXIE_F1_M: 98 { 99 unsigned imm; 100 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 101 goto fail; 102 imm = bfd_getb32 (buffer); 103 fpr (stream, "%s\t", opcode->name); 104 info->print_address_func ((bfd_vma) imm, info); 105 length = 6; 106 } 107 break; 108 case MOXIE_F1_AiB: 109 fpr (stream, "%s\t(%s), %s", opcode->name, 110 reg_names[OP_A(iword)], reg_names[OP_B(iword)]); 111 break; 112 case MOXIE_F1_ABi: 113 fpr (stream, "%s\t%s, (%s)", opcode->name, 114 reg_names[OP_A(iword)], reg_names[OP_B(iword)]); 115 break; 116 case MOXIE_F1_4A: 117 { 118 unsigned imm; 119 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 120 goto fail; 121 imm = bfd_getb32 (buffer); 122 fpr (stream, "%s\t0x%x, %s", 123 opcode->name, imm, reg_names[OP_A(iword)]); 124 length = 6; 125 } 126 break; 127 case MOXIE_F1_AiB4: 128 { 129 unsigned imm; 130 if ((status = info->read_memory_func (addr+2, buffer, 4, info))) 131 goto fail; 132 imm = bfd_getb32 (buffer); 133 fpr (stream, "%s\t0x%x(%s), %s", opcode->name, 134 imm, 135 reg_names[OP_A(iword)], 136 reg_names[OP_B(iword)]); 137 length = 6; 138 } 139 break; 140 case MOXIE_F1_ABi4: 141 { 142 unsigned imm; 143 if ((status = info->read_memory_func (addr+2, buffer, 4, info))) 144 goto fail; 145 imm = bfd_getb32 (buffer); 146 fpr (stream, "%s\t%s, 0x%x(%s)", 147 opcode->name, 148 reg_names[OP_A(iword)], 149 imm, 150 reg_names[OP_B(iword)]); 151 length = 6; 152 } 153 break; 154 default: 155 abort (); 156 } 157 } 158 else if ((iword & (1<<14)) == 0) 159 { 160 /* Extract the Form 2 opcode. */ 161 opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; 162 switch (opcode->itype) 163 { 164 case MOXIE_F2_A8V: 165 fpr (stream, "%s\t%s, 0x%x", 166 opcode->name, 167 reg_names[(iword >> 8) & 0xf], 168 iword & ((1 << 8) - 1)); 169 break; 170 case MOXIE_F2_NARG: 171 fpr (stream, "%s", opcode->name); 172 break; 173 default: 174 abort(); 175 } 176 } 177 else 178 { 179 /* Extract the Form 3 opcode. */ 180 opcode = &moxie_form3_opc_info[(iword >> 10) & 15]; 181 switch (opcode->itype) 182 { 183 case MOXIE_F3_PCREL: 184 fpr (stream, "%s\t", opcode->name); 185 info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword)), 186 info); 187 break; 188 default: 189 abort(); 190 } 191 } 192 193 return length; 194 195 fail: 196 info->memory_error_func (status, addr, info); 197 return -1; 198 } 199