comparison graal/com.oracle.max.asmdis/src/com/sun/max/asm/dis/risc/RiscDisassembler.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children bc8527f3071c
comparison
equal deleted inserted replaced
3732:3e2e8b8abdaf 3733:e233f5660da4
1 /*
2 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.sun.max.asm.dis.risc;
24
25 import java.io.*;
26 import java.util.*;
27 import java.util.Arrays;
28
29 import com.sun.max.*;
30 import com.sun.max.asm.*;
31 import com.sun.max.asm.dis.*;
32 import com.sun.max.asm.gen.*;
33 import com.sun.max.asm.gen.risc.*;
34 import com.sun.max.asm.gen.risc.bitRange.*;
35 import com.sun.max.asm.gen.risc.field.*;
36 import com.sun.max.lang.*;
37 import com.sun.max.program.*;
38
39 /**
40 */
41 public abstract class RiscDisassembler extends Disassembler {
42
43 private final RiscAssembly assembly;
44
45 protected RiscDisassembler(ImmediateArgument startAddress, RiscAssembly assembly, Endianness endianness, InlineDataDecoder inlineDataDecoder) {
46 super(startAddress, endianness, inlineDataDecoder);
47 assert assembly != null;
48 this.assembly = assembly;
49 this.byteFields = new ImmediateOperandField[]{createByteField(0), createByteField(1), createByteField(2), createByteField(3)};
50 }
51
52 public RiscAssembly assembly() {
53 return assembly;
54 }
55
56 private static final boolean INLINE_INVALID_INSTRUCTIONS_AS_BYTES = true;
57
58 /**
59 * Extract the value for each operand of a template from an encoded instruction whose opcode
60 * matches that of the template.
61 *
62 * @param instruction the encoded instruction
63 * @return the decoded arguments for each operand or null if at least one operand has
64 * an invalid value in the encoded instruction
65 */
66 private List<Argument> disassemble(int instruction, RiscTemplate template) {
67 final List<Argument> arguments = new ArrayList<Argument>();
68 for (OperandField operandField : template.parameters()) {
69 final Argument argument = operandField.disassemble(instruction);
70 if (argument == null) {
71 return null;
72 }
73 arguments.add(argument);
74 }
75 return arguments;
76 }
77
78 private boolean isLegalArgumentList(RiscTemplate template, List<Argument> arguments) {
79 final List<InstructionConstraint> constraints = template.instructionDescription().constraints();
80 for (InstructionConstraint constraint : constraints) {
81 if (!(constraint.check(template, arguments))) {
82 return false;
83 }
84 }
85 return true;
86 }
87
88 /**
89 * Creates a disassembled instruction based on a given sequence of bytes, a template and a set of arguments. The
90 * caller has performed the necessary decoding of the bytes to derive the template and arguments.
91 *
92 * @param position the position an instruction stream from which the bytes were read
93 * @param bytes the bytes of an instruction
94 * @param template the template that corresponds to the instruction encoded in {@code bytes}
95 * @param arguments the arguments of the instruction encoded in {@code bytes}
96 * @return a disassembled instruction representing the result of decoding {@code bytes} into an instruction
97 */
98 protected abstract DisassembledInstruction createDisassembledInstruction(int position, byte[] bytes, RiscTemplate template, List<Argument> arguments);
99
100 @Override
101 public List<DisassembledObject> scanOne0(BufferedInputStream stream) throws IOException, AssemblyException {
102 final int instruction = endianness().readInt(stream);
103 final List<DisassembledObject> result = new LinkedList<DisassembledObject>();
104 final byte[] instructionBytes = endianness().toBytes(instruction);
105 for (SpecificityGroup specificityGroup : assembly().specificityGroups()) {
106 for (OpcodeMaskGroup opcodeMaskGroup : specificityGroup.opcodeMaskGroups()) {
107 final int opcode = instruction & opcodeMaskGroup.mask();
108 for (RiscTemplate template : opcodeMaskGroup.templatesFor(opcode)) {
109 // Skip synthetic instructions when preference is for raw instructions,
110 // and skip instructions with a different number of arguments than requested if so (i.e. when running the AssemblyTester):
111 if (template != null && template.isDisassemblable() && ((abstractionPreference() == AbstractionPreference.SYNTHETIC) || !template.instructionDescription().isSynthetic())) {
112 final List<Argument> arguments = disassemble(instruction, template);
113 if (arguments != null && (expectedNumberOfArguments() < 0 || arguments.size() == expectedNumberOfArguments())) {
114 if (isLegalArgumentList(template, arguments)) {
115 final Assembler assembler = createAssembler(currentPosition);
116 try {
117 assembly().assemble(assembler, template, arguments);
118 final byte[] bytes = assembler.toByteArray();
119 if (Arrays.equals(bytes, instructionBytes)) {
120 final DisassembledInstruction disassembledInstruction = createDisassembledInstruction(currentPosition, bytes, template, arguments);
121 result.add(disassembledInstruction);
122 }
123 } catch (AssemblyException assemblyException) {
124 ProgramWarning.message("could not assemble matching instruction: " + template);
125 }
126 }
127 }
128 }
129 }
130 }
131 }
132 if (result.isEmpty()) {
133 if (INLINE_INVALID_INSTRUCTIONS_AS_BYTES) {
134 stream.reset();
135 final InlineData inlineData = new InlineData(currentPosition, instructionBytes);
136 final DisassembledData disassembledData = createDisassembledDataObjects(inlineData).iterator().next();
137 result.add(disassembledData);
138 } else {
139 throw new AssemblyException("instruction could not be disassembled: " + Bytes.toHexLiteral(endianness().toBytes(instruction)));
140 }
141 }
142 currentPosition += 4;
143 return result;
144 }
145
146 @Override
147 public List<DisassembledObject> scan0(BufferedInputStream stream) throws IOException, AssemblyException {
148 final List<DisassembledObject> result = new ArrayList<DisassembledObject>();
149 try {
150 while (true) {
151
152 scanInlineData(stream, result);
153
154 final List<DisassembledObject> disassembledObjects = scanOne(stream);
155 boolean foundSyntheticDisassembledInstruction = false;
156 if (abstractionPreference() == AbstractionPreference.SYNTHETIC) {
157 for (DisassembledObject disassembledObject : disassembledObjects) {
158 if (disassembledObject instanceof DisassembledInstruction) {
159 final DisassembledInstruction disassembledInstruction = (DisassembledInstruction) disassembledObject;
160 if (disassembledInstruction.template().instructionDescription().isSynthetic()) {
161 result.add(disassembledInstruction);
162 foundSyntheticDisassembledInstruction = true;
163 break;
164 }
165 }
166 }
167 }
168 if (!foundSyntheticDisassembledInstruction) {
169 result.add(Utils.first(disassembledObjects));
170 }
171 }
172 } catch (IOException ioException) {
173 return result;
174 }
175 }
176
177 protected RiscTemplate createInlineDataTemplate(InstructionDescription instructionDescription) {
178 return new RiscTemplate(instructionDescription);
179 }
180
181 private final ImmediateOperandField[] byteFields;
182
183 private ImmediateOperandField createByteField(int index) {
184 if (assembly().bitRangeEndianness() == BitRangeOrder.ASCENDING) {
185 final int firstBit = index * Bytes.WIDTH;
186 final int lastBit = firstBit + 7;
187 return ImmediateOperandField.createAscending(firstBit, lastBit);
188 }
189 final int lastBit = index * Bytes.WIDTH;
190 final int firstBit = lastBit + 7;
191 return ImmediateOperandField.createDescending(firstBit, lastBit);
192 }
193
194 @Override
195 public ImmediateArgument addressForRelativeAddressing(DisassembledInstruction di) {
196 return di.startAddress();
197 }
198
199 @Override
200 public String mnemonic(DisassembledInstruction di) {
201 final RiscExternalInstruction instruction = new RiscExternalInstruction((RiscTemplate) di.template(), di.arguments(), di.startAddress(), null);
202 return instruction.name();
203 }
204
205 @Override
206 public String operandsToString(DisassembledInstruction di, AddressMapper addressMapper) {
207 final RiscExternalInstruction instruction = new RiscExternalInstruction((RiscTemplate) di.template(), di.arguments(), di.startAddress(), addressMapper);
208 return instruction.operands();
209 }
210
211 @Override
212 public String toString(DisassembledInstruction di, AddressMapper addressMapper) {
213 final RiscExternalInstruction instruction = new RiscExternalInstruction((RiscTemplate) di.template(), di.arguments(), di.startAddress(), addressMapper);
214 return instruction.toString();
215 }
216 }