Mercurial > hg > truffle
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 } |