Mercurial > hg > truffle
comparison graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/cisc/x86/X86TemplateAssembler.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.gen.cisc.x86; | |
24 | |
25 import static com.sun.max.asm.gen.cisc.x86.X86AssemblerGenerator.*; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 | |
30 import com.sun.max.asm.*; | |
31 import com.sun.max.asm.amd64.*; | |
32 import com.sun.max.lang.*; | |
33 import com.sun.max.program.*; | |
34 | |
35 /** | |
36 * An assembler that creates binary instructions from templates and arguments. | |
37 */ | |
38 public class X86TemplateAssembler { | |
39 | |
40 private static final int MORE_BYTES_THAN_ANY_INSTRUCTION = 32; | |
41 private final byte[] bytes = new byte[MORE_BYTES_THAN_ANY_INSTRUCTION]; | |
42 private int n; | |
43 | |
44 private int rexByte; | |
45 | |
46 private void emit(byte b) { | |
47 bytes[n++] = b; | |
48 } | |
49 | |
50 private void emit(int b) { | |
51 bytes[n++] = (byte) (b & 0xff); | |
52 } | |
53 | |
54 private void emit(HexByte b) { | |
55 bytes[n++] = b.byteValue(); | |
56 } | |
57 | |
58 private int createRexData(int bitIndex, Argument argument, boolean unconditionalRexBit) { | |
59 if (unconditionalRexBit) { | |
60 return ((int) argument.asLong() & 8) >> (3 - bitIndex); | |
61 } | |
62 int rexByte = 0; | |
63 if (argument instanceof AMD64GeneralRegister8) { | |
64 final AMD64GeneralRegister8 reg8 = (AMD64GeneralRegister8) argument; | |
65 if (reg8.requiresRexPrefix()) { | |
66 rexByte |= basicRexValue(template); | |
67 if (argument.asLong() >= 8) { | |
68 rexByte |= createRexData(bitIndex, argument.asLong()); | |
69 } | |
70 } | |
71 } else { | |
72 if (argument.asLong() >= 8) { | |
73 rexByte |= createRexData(bitIndex, argument.asLong()) + basicRexValue(template); | |
74 } | |
75 } | |
76 return rexByte; | |
77 } | |
78 | |
79 private int createRexData(int bitIndex, long argument) { | |
80 final byte b = (byte) (argument & 0xffL); | |
81 if (b == 0) { | |
82 return 0; | |
83 } | |
84 return X86Field.inRexPlace(bitIndex, b); | |
85 } | |
86 | |
87 private int createFieldData(X86Field field, long argument) { | |
88 return field.inPlace((byte) (argument & field.mask)); | |
89 } | |
90 | |
91 private final X86Template template; | |
92 private WordWidth addressWidth; | |
93 | |
94 public X86TemplateAssembler(X86Template template, WordWidth addressWidth) { | |
95 this.template = template; | |
96 this.addressWidth = addressWidth; | |
97 } | |
98 | |
99 private int createModRMByte() { | |
100 if (!template.hasModRMByte()) { | |
101 return 0; | |
102 } | |
103 int result = template.modCase().ordinal() << X86Field.MOD.shift(); | |
104 if (template.modRMGroupOpcode() != null) { | |
105 result |= template.modRMGroupOpcode().byteValue() << X86Field.REG.shift(); | |
106 } | |
107 result |= template.rmCase().value() << X86Field.RM.shift(); | |
108 return result; | |
109 } | |
110 | |
111 private int createSibByte() { | |
112 if (template.hasSibByte() && template.sibBaseCase() == X86TemplateContext.SibBaseCase.SPECIAL) { | |
113 return 5 << X86Field.BASE.shift(); | |
114 } | |
115 return 0; | |
116 } | |
117 | |
118 private boolean modRMRequiresSib(int modRMByte) { | |
119 final byte m = (byte) modRMByte; | |
120 return X86Field.MOD.extract(m) != 3 && X86Field.RM.extract(m) == 4; | |
121 } | |
122 | |
123 private boolean modRMRequiresImmediate(int modRMByte) { | |
124 final byte m = (byte) modRMByte; | |
125 return X86Field.MOD.extract(m) == 0 && X86Field.RM.extract(m) == 5; | |
126 } | |
127 | |
128 private boolean sibRequiresImmediate(int sibRMByte) { | |
129 final byte s = (byte) sibRMByte; | |
130 return X86Field.BASE.extract(s) == 5; | |
131 } | |
132 | |
133 public byte[] assemble(List<Argument> arguments) { | |
134 int rexByte = 0; | |
135 final boolean unconditionalRexBit = template.operandSizeAttribute() == WordWidth.BITS_64 && template.instructionDescription().defaultOperandSize() != WordWidth.BITS_64; | |
136 if (unconditionalRexBit) { | |
137 rexByte = X86Opcode.REX_MIN.byteValue() | (1 << X86Field.REX_W_BIT_INDEX); | |
138 } | |
139 int opcode1 = template.opcode1().byteValue() & 0xff; | |
140 int opcode2 = template.opcode2() == null ? 0 : template.opcode2().byteValue() & 0xff; | |
141 int modRMByte = createModRMByte(); | |
142 int sibByte = createSibByte(); | |
143 final ByteArrayOutputStream appendStream = new ByteArrayOutputStream(); | |
144 for (int i = 0; i < arguments.size(); i++) { | |
145 final X86Parameter parameter = template.parameters().get(i); | |
146 final long argument = arguments.get(i).asLong(); | |
147 switch (parameter.place()) { | |
148 case MOD_REG_REXR: | |
149 rexByte |= createRexData(X86Field.REX_R_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
150 // fall through... | |
151 case MOD_REG: | |
152 modRMByte |= createFieldData(X86Field.REG, argument); | |
153 break; | |
154 case MOD_RM_REXB: | |
155 rexByte |= createRexData(X86Field.REX_B_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
156 // fall through... | |
157 case MOD_RM: | |
158 modRMByte |= createFieldData(X86Field.RM, argument); | |
159 break; | |
160 case SIB_BASE_REXB: | |
161 rexByte |= createRexData(X86Field.REX_B_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
162 // fall through... | |
163 case SIB_BASE: | |
164 sibByte |= createFieldData(X86Field.BASE, argument); | |
165 break; | |
166 case SIB_INDEX_REXX: | |
167 rexByte |= createRexData(X86Field.REX_X_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
168 // fall through... | |
169 case SIB_INDEX: | |
170 sibByte |= createFieldData(X86Field.INDEX, argument); | |
171 break; | |
172 case SIB_SCALE: | |
173 sibByte |= createFieldData(X86Field.SCALE, argument); | |
174 break; | |
175 case APPEND: | |
176 if (parameter instanceof X86EnumerableParameter) { | |
177 appendStream.write((byte) (argument & 0xffL)); | |
178 } else { | |
179 try { | |
180 final X86NumericalParameter numericalParameter = (X86NumericalParameter) parameter; | |
181 switch (numericalParameter.width()) { | |
182 case BITS_8: | |
183 appendStream.write((byte) (argument & 0xffL)); | |
184 break; | |
185 case BITS_16: | |
186 Endianness.LITTLE.writeShort(appendStream, (short) (argument & 0xffffL)); | |
187 break; | |
188 case BITS_32: | |
189 Endianness.LITTLE.writeInt(appendStream, (int) (argument & 0xffffffffL)); | |
190 break; | |
191 case BITS_64: | |
192 Endianness.LITTLE.writeLong(appendStream, argument); | |
193 break; | |
194 } | |
195 } catch (IOException ioException) { | |
196 throw ProgramError.unexpected(); | |
197 } | |
198 } | |
199 break; | |
200 case OPCODE1_REXB: | |
201 rexByte |= createRexData(X86Field.REX_B_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
202 // fall through... | |
203 case OPCODE1: | |
204 opcode1 |= (int) argument & 7; | |
205 break; | |
206 case OPCODE2_REXB: | |
207 rexByte |= createRexData(X86Field.REX_B_BIT_INDEX, arguments.get(i), unconditionalRexBit); | |
208 // fall through... | |
209 case OPCODE2: | |
210 opcode2 |= (int) argument & 7; | |
211 break; | |
212 } | |
213 } | |
214 if (rexByte > 0) { | |
215 emit(rexByte); | |
216 } | |
217 if (template.addressSizeAttribute() != addressWidth) { | |
218 emit(X86Opcode.ADDRESS_SIZE); | |
219 } | |
220 if (template.operandSizeAttribute() == WordWidth.BITS_16) { | |
221 emit(X86Opcode.OPERAND_SIZE); | |
222 } | |
223 if (template.instructionSelectionPrefix() != null) { | |
224 emit(template.instructionSelectionPrefix()); | |
225 } | |
226 emit(opcode1); | |
227 if (opcode2 != 0) { | |
228 emit(opcode2); | |
229 } | |
230 if (template.hasModRMByte()) { | |
231 emit(modRMByte); | |
232 if (modRMRequiresImmediate(modRMByte) && appendStream.size() == 0) { | |
233 return null; | |
234 } | |
235 } | |
236 if (template.hasSibByte()) { | |
237 if (sibRequiresImmediate(sibByte) && appendStream.size() == 0) { | |
238 return null; | |
239 } | |
240 emit(sibByte); | |
241 } else if (modRMRequiresSib(modRMByte)) { | |
242 return null; | |
243 } | |
244 for (byte b : appendStream.toByteArray()) { | |
245 emit(b); | |
246 } | |
247 return Bytes.withLength(bytes, n); | |
248 } | |
249 | |
250 } |