1 /*
2 * Copyright (c) 2011, 2018, 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 */
266 masm.cmpl(idxScratchReg, highKey - lowKey);
267 } else {
268 masm.cmpl(idxScratchReg, highKey);
269 }
270
271 // Jump to default target if index is not within the jump table
272 if (defaultTarget != null) {
273 masm.jcc(ConditionFlag.Above, defaultTarget.label());
274 }
275
276 // Set scratch to address of jump table
277 masm.leaq(scratchReg, new AMD64Address(AMD64.rip, 0));
278 final int afterLea = masm.position();
279
280 // Load jump table entry into scratch and jump to it
281 masm.movslq(idxScratchReg, new AMD64Address(scratchReg, idxScratchReg, Scale.Times4, 0));
282 masm.addq(scratchReg, idxScratchReg);
283 masm.jmp(scratchReg);
284
285 // Inserting padding so that jump table address is 4-byte aligned
286 if ((masm.position() & 0x3) != 0) {
287 masm.nop(4 - (masm.position() & 0x3));
288 }
289
290 // Patch LEA instruction above now that we know the position of the jump table
291 // TODO this is ugly and should be done differently
292 final int jumpTablePos = masm.position();
293 final int leaDisplacementPosition = afterLea - 4;
294 masm.emitInt(jumpTablePos - afterLea, leaDisplacementPosition);
295
296 // Emit jump table entries
297 for (LabelRef target : targets) {
298 Label label = target.label();
299 int offsetToJumpTableBase = masm.position() - jumpTablePos;
300 if (label.isBound()) {
301 int imm32 = label.position() - jumpTablePos;
302 masm.emitInt(imm32);
303 } else {
304 label.addPatchAt(masm.position());
305
306 masm.emitByte(0); // pseudo-opcode for jump table entry
307 masm.emitShort(offsetToJumpTableBase);
308 masm.emitByte(0); // padding to make jump table entry 4 bytes wide
309 }
310 }
311
312 JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
313 crb.compilationResult.addAnnotation(jt);
314 }
315 }
316
317 @Opcode("SETcc")
318 public static final class CondSetOp extends AMD64LIRInstruction {
319 public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class);
320 @Def({REG, HINT}) protected Value result;
321 private final ConditionFlag condition;
322
323 public CondSetOp(Variable result, Condition condition) {
324 super(TYPE);
325 this.result = result;
326 this.condition = intCond(condition);
327 }
328
329 @Override
330 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
331 setcc(masm, result, condition);
332 }
|
1 /*
2 * Copyright (c) 2011, 2019, 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 */
266 masm.cmpl(idxScratchReg, highKey - lowKey);
267 } else {
268 masm.cmpl(idxScratchReg, highKey);
269 }
270
271 // Jump to default target if index is not within the jump table
272 if (defaultTarget != null) {
273 masm.jcc(ConditionFlag.Above, defaultTarget.label());
274 }
275
276 // Set scratch to address of jump table
277 masm.leaq(scratchReg, new AMD64Address(AMD64.rip, 0));
278 final int afterLea = masm.position();
279
280 // Load jump table entry into scratch and jump to it
281 masm.movslq(idxScratchReg, new AMD64Address(scratchReg, idxScratchReg, Scale.Times4, 0));
282 masm.addq(scratchReg, idxScratchReg);
283 masm.jmp(scratchReg);
284
285 // Inserting padding so that jump table address is 4-byte aligned
286 masm.align(4);
287
288 // Patch LEA instruction above now that we know the position of the jump table
289 // this is ugly but there is no better way to do this given the assembler API
290 final int jumpTablePos = masm.position();
291 final int leaDisplacementPosition = afterLea - 4;
292 masm.emitInt(jumpTablePos - afterLea, leaDisplacementPosition);
293
294 // Emit jump table entries
295 for (LabelRef target : targets) {
296 Label label = target.label();
297 int offsetToJumpTableBase = masm.position() - jumpTablePos;
298 if (label.isBound()) {
299 int imm32 = label.position() - jumpTablePos;
300 masm.emitInt(imm32);
301 } else {
302 label.addPatchAt(masm.position());
303
304 masm.emitByte(0); // pseudo-opcode for jump table entry
305 masm.emitShort(offsetToJumpTableBase);
306 masm.emitByte(0); // padding to make jump table entry 4 bytes wide
307 }
308 }
309
310 JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
311 crb.compilationResult.addAnnotation(jt);
312 }
313 }
314
315 public static final class HashTableSwitchOp extends AMD64BlockEndOp {
316 public static final LIRInstructionClass<HashTableSwitchOp> TYPE = LIRInstructionClass.create(HashTableSwitchOp.class);
317 private final JavaConstant[] keys;
318 private final LabelRef defaultTarget;
319 private final LabelRef[] targets;
320 @Alive protected Value value;
321 @Alive protected Value hash;
322 @Temp({REG}) protected Value entryScratch;
323 @Temp({REG}) protected Value scratch;
324
325 public HashTableSwitchOp(final JavaConstant[] keys, final LabelRef defaultTarget, LabelRef[] targets, Value value, Value hash, Variable scratch, Variable entryScratch) {
326 super(TYPE);
327 this.keys = keys;
328 this.defaultTarget = defaultTarget;
329 this.targets = targets;
330 this.value = value;
331 this.hash = hash;
332 this.scratch = scratch;
333 this.entryScratch = entryScratch;
334 }
335
336 @Override
337 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
338 Register valueReg = asRegister(value, AMD64Kind.DWORD);
339 Register indexReg = asRegister(hash, AMD64Kind.DWORD);
340 Register scratchReg = asRegister(scratch, AMD64Kind.QWORD);
341 Register entryScratchReg = asRegister(entryScratch, AMD64Kind.QWORD);
342
343 // Set scratch to address of jump table
344 masm.leaq(scratchReg, new AMD64Address(AMD64.rip, 0));
345 final int afterLea = masm.position();
346
347 // When the default target is set, the jump table contains entries with two DWORDS:
348 // the original key before hashing and the label jump address
349 if (defaultTarget != null) {
350
351 // Move the table entry (two DWORDs) into a QWORD
352 masm.movq(entryScratchReg, new AMD64Address(scratchReg, indexReg, Scale.Times8, 0));
353
354 // Jump to the default target if the first DWORD (original key) doesn't match the
355 // current key. Accounts for hash collisions with unknown keys
356 masm.cmpl(entryScratchReg, valueReg);
357 masm.jcc(ConditionFlag.NotEqual, defaultTarget.label());
358
359 // Shift to the second DWORD
360 masm.sarq(entryScratchReg, 32);
361 } else {
362
363 // The jump table has a single DWORD with the label address if there's no
364 // default target
365 masm.movslq(entryScratchReg, new AMD64Address(scratchReg, indexReg, Scale.Times4, 0));
366 }
367 masm.addq(scratchReg, entryScratchReg);
368 masm.jmp(scratchReg);
369
370 // Inserting padding so that jump the table address is aligned
371 if (defaultTarget != null) {
372 masm.align(8);
373 } else {
374 masm.align(4);
375 }
376
377 // Patch LEA instruction above now that we know the position of the jump table
378 // this is ugly but there is no better way to do this given the assembler API
379 final int jumpTablePos = masm.position();
380 final int leaDisplacementPosition = afterLea - 4;
381 masm.emitInt(jumpTablePos - afterLea, leaDisplacementPosition);
382
383 // Emit jump table entries
384 for (int i = 0; i < targets.length; i++) {
385
386 Label label = targets[i].label();
387
388 if (defaultTarget != null) {
389 masm.emitInt(keys[i].asInt());
390 }
391 if (label.isBound()) {
392 int imm32 = label.position() - jumpTablePos;
393 masm.emitInt(imm32);
394 } else {
395 int offsetToJumpTableBase = masm.position() - jumpTablePos;
396 label.addPatchAt(masm.position());
397 masm.emitByte(0); // pseudo-opcode for jump table entry
398 masm.emitShort(offsetToJumpTableBase);
399 masm.emitByte(0); // padding to make jump table entry 4 bytes wide
400 }
401 }
402
403 JumpTable jt = new JumpTable(jumpTablePos, keys[0].asInt(), keys[keys.length - 1].asInt(), 4);
404 crb.compilationResult.addAnnotation(jt);
405 }
406 }
407
408 @Opcode("SETcc")
409 public static final class CondSetOp extends AMD64LIRInstruction {
410 public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class);
411 @Def({REG, HINT}) protected Value result;
412 private final ConditionFlag condition;
413
414 public CondSetOp(Variable result, Condition condition) {
415 super(TYPE);
416 this.result = result;
417 this.condition = intCond(condition);
418 }
419
420 @Override
421 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
422 setcc(masm, result, condition);
423 }
|