1 /*
   2  * Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.asm.sparc;
  26 
  27 import sun.jvm.hotspot.asm.*;
  28 import java.io.*;
  29 import java.util.*;
  30 
  31 public abstract class SPARCDisassembler extends Disassembler
  32                     implements /* imports */ SPARCOpcodes, RTLDataTypes, RTLOperations {
  33 
  34     // instruction cache - Map<Integer, Instruction>.
  35     protected static Map instructionCache = new HashMap();
  36     protected final SPARCInstructionFactory factory;
  37 
  38     public SPARCDisassembler(long startPc, byte[] code, SPARCInstructionFactory factory) {
  39         super(startPc, code);
  40         this.factory = factory;
  41     }
  42 
  43     protected static InstructionDecoder illegalDecoder = new IllegalInstructionDecoder();
  44     protected static InstructionDecoder callDecoder = new CallDecoder();
  45 
  46     // direct call instruction
  47     protected Instruction decodeFormat1Instruction(int instruction) {
  48         return callDecoder.decode(instruction, factory);
  49     }
  50 
  51     protected abstract InstructionDecoder getFormat2Decoder(int op2);
  52 
  53     protected Instruction decodeFormat2Instruction(int instruction) {
  54         int op2 = (instruction & OP_2_MASK) >>> OP_2_START_BIT;
  55         InstructionDecoder decoder = getFormat2Decoder(op2);
  56         return decoder.decode(instruction, factory);
  57     }
  58 
  59     // "op3" - used in format 3 & 3A instructions - 6 bits width
  60 
  61     protected static int getOp3(int instruction) {
  62         return (instruction & OP_3_MASK) >>> OP_3_START_BIT;
  63     }
  64 
  65     // op3 opcodes is broken up into column and row. MSB 2 bits form column.
  66     // LSB 4 bits form row number.
  67 
  68     protected static int getOp3Row(int op3) {
  69         return op3 & 0xF;
  70     }
  71 
  72     protected static int getOp3Column(int op3) {
  73         return (op3 >>> 4) & 0x3;
  74     }
  75 
  76     protected abstract InstructionDecoder getFormat3Decoder(int row, int column);
  77 
  78     // memory instructions
  79     protected Instruction decodeFormat3Instruction(int instruction) {
  80         int op3 = getOp3(instruction);
  81         int row = getOp3Row(op3);
  82         int column = getOp3Column(op3);
  83         return getFormat3Decoder(row, column).decode(instruction, factory);
  84     }
  85 
  86     protected abstract InstructionDecoder getFormat3ADecoder(int row, int column);
  87 
  88     // arithmetic, logic, shift and the rest
  89     protected Instruction decodeFormat3AInstruction(int instruction) {
  90         int op3 = getOp3(instruction);
  91         int row = getOp3Row(op3);
  92         int column = getOp3Column(op3);
  93         return getFormat3ADecoder(row, column).decode(instruction, factory);
  94     }
  95 
  96     public void decode(InstructionVisitor visitor) {
  97         visitor.prologue();
  98         try {
  99             DataInputStream dis = new DataInputStream(new ByteArrayInputStream(code));
 100             int instruction = -1;
 101             int format = -1;
 102             Instruction instr = null;
 103             int len = 0;
 104 
 105             while (len < code.length) {
 106                 instr = null;
 107                 instruction =  dis.readInt();
 108                 // check whether we have this in cache.
 109                 instr = (Instruction) instructionCache.get(new Integer(instruction));
 110                 if (instr == null) {
 111                     format = (instruction & FORMAT_MASK) >>> FORMAT_START_BIT;
 112 
 113                     switch (format) {
 114                         case FORMAT_2:  // 0
 115                             instr = decodeFormat2Instruction(instruction);
 116                             break;
 117 
 118                         case FORMAT_1:  // 1
 119                             instr = decodeFormat1Instruction(instruction);
 120                             break;
 121 
 122                         case FORMAT_3A: // 2
 123                             instr = decodeFormat3AInstruction(instruction);
 124                             break;
 125 
 126                         case FORMAT_3:  // 3
 127                             instr = decodeFormat3Instruction(instruction);
 128                             break;
 129                     }
 130 
 131                     // add the new instruction to cache.
 132                     instructionCache.put(new Integer(instruction), instr);
 133                 }
 134 
 135                 visitor.visit(startPc + len, instr);
 136                 len += 4;
 137             }
 138         } catch (IOException ioExp) {
 139             // ignore, can't happen
 140         } finally {
 141             visitor.epilogue();
 142         }
 143     }
 144 }