1 /* Disassemble moxie instructions. 2 Copyright 2009, 2012 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 "sysdep.h" 23 #include <stdio.h> 24 25 #define STATIC_TABLE 26 #define DEFINE_TABLE 27 28 #include "opcode/moxie.h" 29 #include "dis-asm.h" 30 31 static fprintf_ftype fpr; 32 static void *stream; 33 34 /* Macros to extract operands from the instruction word. */ 35 #define OP_A(i) ((i >> 4) & 0xf) 36 #define OP_B(i) (i & 0xf) 37 #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) 38 39 static const char * reg_names[16] = 40 { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", 41 "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; 42 43 int 44 print_insn_moxie (bfd_vma addr, struct disassemble_info * info) 45 { 46 int length = 2; 47 int status; 48 stream = info->stream; 49 const moxie_opc_info_t * opcode; 50 bfd_byte buffer[4]; 51 unsigned short iword; 52 fpr = info->fprintf_func; 53 54 if ((status = info->read_memory_func (addr, buffer, 2, info))) 55 goto fail; 56 iword = bfd_getb16 (buffer); 57 58 /* Form 1 instructions have the high bit set to 0. */ 59 if ((iword & (1<<15)) == 0) 60 { 61 /* Extract the Form 1 opcode. */ 62 opcode = &moxie_form1_opc_info[iword >> 8]; 63 switch (opcode->itype) 64 { 65 case MOXIE_F1_NARG: 66 fpr (stream, "%s", opcode->name); 67 break; 68 case MOXIE_F1_A: 69 fpr (stream, "%s\t%s", opcode->name, 70 reg_names[OP_A(iword)]); 71 break; 72 case MOXIE_F1_AB: 73 fpr (stream, "%s\t%s, %s", opcode->name, 74 reg_names[OP_A(iword)], 75 reg_names[OP_B(iword)]); 76 break; 77 case MOXIE_F1_A4: 78 { 79 unsigned imm; 80 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 81 goto fail; 82 imm = bfd_getb32 (buffer); 83 fpr (stream, "%s\t%s, 0x%x", opcode->name, 84 reg_names[OP_A(iword)], imm); 85 length = 6; 86 } 87 break; 88 case MOXIE_F1_4: 89 { 90 unsigned imm; 91 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 92 goto fail; 93 imm = bfd_getb32 (buffer); 94 fpr (stream, "%s\t0x%x", opcode->name, imm); 95 length = 6; 96 } 97 break; 98 case MOXIE_F1_M: 99 { 100 unsigned imm; 101 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 102 goto fail; 103 imm = bfd_getb32 (buffer); 104 fpr (stream, "%s\t", opcode->name); 105 info->print_address_func ((bfd_vma) imm, info); 106 length = 6; 107 } 108 break; 109 case MOXIE_F1_AiB: 110 fpr (stream, "%s\t(%s), %s", opcode->name, 111 reg_names[OP_A(iword)], reg_names[OP_B(iword)]); 112 break; 113 case MOXIE_F1_ABi: 114 fpr (stream, "%s\t%s, (%s)", opcode->name, 115 reg_names[OP_A(iword)], reg_names[OP_B(iword)]); 116 break; 117 case MOXIE_F1_4A: 118 { 119 unsigned imm; 120 if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) 121 goto fail; 122 imm = bfd_getb32 (buffer); 123 fpr (stream, "%s\t0x%x, %s", 124 opcode->name, imm, reg_names[OP_A(iword)]); 125 length = 6; 126 } 127 break; 128 case MOXIE_F1_AiB4: 129 { 130 unsigned imm; 131 if ((status = info->read_memory_func (addr+2, buffer, 4, info))) 132 goto fail; 133 imm = bfd_getb32 (buffer); 134 fpr (stream, "%s\t0x%x(%s), %s", opcode->name, 135 imm, 136 reg_names[OP_A(iword)], 137 reg_names[OP_B(iword)]); 138 length = 6; 139 } 140 break; 141 case MOXIE_F1_ABi4: 142 { 143 unsigned imm; 144 if ((status = info->read_memory_func (addr+2, buffer, 4, info))) 145 goto fail; 146 imm = bfd_getb32 (buffer); 147 fpr (stream, "%s\t%s, 0x%x(%s)", 148 opcode->name, 149 reg_names[OP_A(iword)], 150 imm, 151 reg_names[OP_B(iword)]); 152 length = 6; 153 } 154 break; 155 default: 156 abort (); 157 } 158 } 159 else if ((iword & (1<<14)) == 0) 160 { 161 /* Extract the Form 2 opcode. */ 162 opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; 163 switch (opcode->itype) 164 { 165 case MOXIE_F2_A8V: 166 fpr (stream, "%s\t%s, 0x%x", 167 opcode->name, 168 reg_names[(iword >> 8) & 0xf], 169 iword & ((1 << 8) - 1)); 170 break; 171 case MOXIE_F2_NARG: 172 fpr (stream, "%s", opcode->name); 173 break; 174 default: 175 abort(); 176 } 177 } 178 else 179 { 180 /* Extract the Form 3 opcode. */ 181 opcode = &moxie_form3_opc_info[(iword >> 10) & 15]; 182 switch (opcode->itype) 183 { 184 case MOXIE_F3_PCREL: 185 fpr (stream, "%s\t", opcode->name); 186 info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword)), 187 info); 188 break; 189 default: 190 abort(); 191 } 192 } 193 194 return length; 195 196 fail: 197 info->memory_error_func (status, addr, info); 198 return -1; 199 } 200