0
|
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 }
|