150477Speter/* alpha-dis.c -- Disassemble Alpha AXP instructions 21817Sdg Copyright (C) 1996-2017 Free Software Foundation, Inc. 31817Sdg Contributed by Richard Henderson <rth@tamu.edu>, 41541Srgrimes patterned after the PPC opcode handling written by Ian Lance Taylor. 51541Srgrimes 61541Srgrimes This file is part of libopcodes. 7160798Sjhb 81541Srgrimes This library is free software; you can redistribute it and/or modify 9146806Srwatson it under the terms of the GNU General Public License as published by 10146806Srwatson the Free Software Foundation; either version 3, or (at your option) 11146806Srwatson any later version. 12146806Srwatson 13146806Srwatson It is distributed in the hope that it will be useful, but WITHOUT 14160798Sjhb ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15160798Sjhb or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 1611294Sswallace License for more details. 1710905Sbde 181541Srgrimes You should have received a copy of the GNU General Public License 1910905Sbde along with this file; see the file COPYING. If not, write to the Free 2010905Sbde Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 211541Srgrimes 02110-1301, USA. */ 221541Srgrimes 231541Srgrimes#include "sysdep.h" 241541Srgrimes#include <stdio.h> 251541Srgrimes#include "dis-asm.h" 2699855Salfred#include "opcode/alpha.h" 271541Srgrimes 281541Srgrimes/* OSF register names. */ 291541Srgrimes 3069449Salfredstatic const char * const osf_regnames[64] = { 31160797Sjhb "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", 32160797Sjhb "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", 33104747Srwatson "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", 34104747Srwatson "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero", 35123408Speter "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", 36123408Speter "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", 371541Srgrimes "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", 381541Srgrimes "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" 3911294Sswallace}; 4011294Sswallace 4111294Sswallace/* VMS register names. */ 4211294Sswallace 431541Srgrimesstatic const char * const vms_regnames[64] = { 441541Srgrimes "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", 451541Srgrimes "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", 461541Srgrimes "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", 471541Srgrimes "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ", 481541Srgrimes "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", 49160798Sjhb "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", 50160798Sjhb "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", 51146806Srwatson "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ" 52160798Sjhb}; 53160798Sjhb 54146806Srwatson/* Disassemble Alpha instructions. */ 55160798Sjhb 56146806Srwatsonint 57160798Sjhbprint_insn_alpha (bfd_vma memaddr, struct disassemble_info *info) 5812216Sbde{ 5912216Sbde static const struct alpha_opcode *opcode_index[AXP_NOPS+1]; 6012216Sbde const char * const * regnames; 61160798Sjhb const struct alpha_opcode *opcode, *opcode_end; 62160798Sjhb const unsigned char *opindex; 63146806Srwatson unsigned insn, op, isa_mask; 64146806Srwatson int need_comma; 65160798Sjhb 66160798Sjhb /* Initialize the majorop table the first time through */ 67160798Sjhb if (!opcode_index[0]) 68146806Srwatson { 69160798Sjhb opcode = alpha_opcodes; 70160798Sjhb opcode_end = opcode + alpha_num_opcodes; 71160798Sjhb 72160798Sjhb for (op = 0; op < AXP_NOPS; ++op) 73160798Sjhb { 74160798Sjhb opcode_index[op] = opcode; 75146806Srwatson while (opcode < opcode_end && op == AXP_OP (opcode->opcode)) 76160798Sjhb ++opcode; 77146806Srwatson } 78160798Sjhb opcode_index[op] = opcode; 79146806Srwatson } 80160798Sjhb 81160798Sjhb if (info->flavour == bfd_target_evax_flavour) 82146806Srwatson regnames = vms_regnames; 8312216Sbde else 84160798Sjhb regnames = osf_regnames; 85160798Sjhb 86160798Sjhb isa_mask = AXP_OPCODE_NOPAL; 87160798Sjhb switch (info->mach) 88160798Sjhb { 89146806Srwatson case bfd_mach_alpha_ev4: 90160798Sjhb isa_mask |= AXP_OPCODE_EV4; 91146806Srwatson break; 92160798Sjhb case bfd_mach_alpha_ev5: 93146806Srwatson isa_mask |= AXP_OPCODE_EV5; 94160798Sjhb break; 95146806Srwatson case bfd_mach_alpha_ev6: 96146806Srwatson isa_mask |= AXP_OPCODE_EV6; 97146806Srwatson break; 98160798Sjhb } 99146806Srwatson 100146806Srwatson /* Read the insn into a host word */ 101160798Sjhb { 102146806Srwatson bfd_byte buffer[4]; 103146806Srwatson int status = (*info->read_memory_func) (memaddr, buffer, 4, info); 104160798Sjhb if (status != 0) 105146806Srwatson { 106146806Srwatson (*info->memory_error_func) (status, memaddr, info); 107160798Sjhb return -1; 108160798Sjhb } 109160798Sjhb insn = bfd_getl32 (buffer); 110160798Sjhb } 111160798Sjhb 112160798Sjhb /* Get the major opcode of the instruction. */ 113160798Sjhb op = AXP_OP (insn); 114160798Sjhb 115160798Sjhb /* Find the first match in the opcode table. */ 116160798Sjhb opcode_end = opcode_index[op + 1]; 117160798Sjhb for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode) 118160798Sjhb { 119146806Srwatson if ((insn ^ opcode->opcode) & opcode->mask) 120160798Sjhb continue; 121146806Srwatson 122160798Sjhb if (!(opcode->flags & isa_mask)) 123146806Srwatson continue; 124146806Srwatson 125160798Sjhb /* Make two passes over the operands. First see if any of them 126160798Sjhb have extraction functions, and, if they do, make sure the 12721776Sbde instruction is valid. */ 12821776Sbde { 12921776Sbde int invalid = 0; 130160798Sjhb for (opindex = opcode->operands; *opindex != 0; opindex++) 131146806Srwatson { 132160798Sjhb const struct alpha_operand *operand = alpha_operands + *opindex; 133160798Sjhb if (operand->extract) 134160798Sjhb (*operand->extract) (insn, &invalid); 135160798Sjhb } 136146806Srwatson if (invalid) 137160798Sjhb continue; 138146806Srwatson } 139160798Sjhb 140160798Sjhb /* The instruction is valid. */ 141160798Sjhb goto found; 142160798Sjhb } 143146806Srwatson 144160798Sjhb /* No instruction found */ 145146806Srwatson (*info->fprintf_func) (info->stream, ".long %#08x", insn); 146160798Sjhb 147146806Srwatson return 4; 148160798Sjhb 149160798Sjhbfound: 150160798Sjhb (*info->fprintf_func) (info->stream, "%s", opcode->name); 151146806Srwatson if (opcode->operands[0] != 0) 152146806Srwatson (*info->fprintf_func) (info->stream, "\t"); 153160798Sjhb 154146806Srwatson /* Now extract and print the operands. */ 155160798Sjhb need_comma = 0; 156146806Srwatson for (opindex = opcode->operands; *opindex != 0; opindex++) 157160798Sjhb { 158146806Srwatson const struct alpha_operand *operand = alpha_operands + *opindex; 159146806Srwatson int value; 160160798Sjhb 161160798Sjhb /* Operands that are marked FAKE are simply ignored. We 162160798Sjhb already made sure that the extract function considered 163146806Srwatson the instruction to be valid. */ 164160798Sjhb if ((operand->flags & AXP_OPERAND_FAKE) != 0) 165146806Srwatson continue; 166160798Sjhb 167160798Sjhb /* Extract the value from the instruction. */ 168146806Srwatson if (operand->extract) 169160798Sjhb value = (*operand->extract) (insn, (int *) NULL); 170146806Srwatson else 171146806Srwatson { 172146806Srwatson value = (insn >> operand->shift) & ((1 << operand->bits) - 1); 173160798Sjhb if (operand->flags & AXP_OPERAND_SIGNED) 174146806Srwatson { 175160798Sjhb int signbit = 1 << (operand->bits - 1); 176146806Srwatson value = (value ^ signbit) - signbit; 177160798Sjhb } 178146806Srwatson } 179160798Sjhb 180160798Sjhb if (need_comma && 181160798Sjhb ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA)) 182146806Srwatson != AXP_OPERAND_PARENS)) 183160798Sjhb { 184160798Sjhb (*info->fprintf_func) (info->stream, ","); 185160798Sjhb } 186146806Srwatson if (operand->flags & AXP_OPERAND_PARENS) 187160798Sjhb (*info->fprintf_func) (info->stream, "("); 188146806Srwatson 189146806Srwatson /* Print the operand as directed by the flags. */ 190160798Sjhb if (operand->flags & AXP_OPERAND_IR) 191146806Srwatson (*info->fprintf_func) (info->stream, "%s", regnames[value]); 192146806Srwatson else if (operand->flags & AXP_OPERAND_FPR) 193160798Sjhb (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]); 194160798Sjhb else if (operand->flags & AXP_OPERAND_RELATIVE) 195146806Srwatson (*info->print_address_func) (memaddr + 4 + value, info); 196160798Sjhb else if (operand->flags & AXP_OPERAND_SIGNED) 197123750Speter (*info->fprintf_func) (info->stream, "%d", value); 19812216Sbde else 199160798Sjhb (*info->fprintf_func) (info->stream, "%#x", value); 200146806Srwatson 201146806Srwatson if (operand->flags & AXP_OPERAND_PARENS) 202160798Sjhb (*info->fprintf_func) (info->stream, ")"); 203160798Sjhb need_comma = 1; 204146806Srwatson } 205160798Sjhb 206146806Srwatson return 4; 207160798Sjhb} 208146806Srwatson