001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.sparc; 024 025import jdk.internal.jvmci.code.*; 026import jdk.internal.jvmci.hotspot.*; 027import jdk.internal.jvmci.meta.*; 028import static com.oracle.graal.asm.sparc.SPARCAssembler.*; 029import static jdk.internal.jvmci.code.ValueUtil.*; 030 031import com.oracle.graal.asm.*; 032import com.oracle.graal.asm.sparc.*; 033import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; 034import com.oracle.graal.hotspot.*; 035import com.oracle.graal.hotspot.meta.*; 036import com.oracle.graal.lir.*; 037import com.oracle.graal.lir.asm.*; 038 039@Opcode("BenchMarkCounter") 040public class SPARCHotSpotCounterOp extends HotSpotCounterOp { 041 public static final LIRInstructionClass<SPARCHotSpotCounterOp> TYPE = LIRInstructionClass.create(SPARCHotSpotCounterOp.class); 042 043 private int[] counterPatchOffsets; 044 045 public SPARCHotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config) { 046 super(TYPE, name, group, increment, registers, config); 047 this.counterPatchOffsets = new int[1]; 048 } 049 050 public SPARCHotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config) { 051 super(TYPE, names, groups, increments, registers, config); 052 this.counterPatchOffsets = new int[names.length]; 053 } 054 055 @Override 056 public void emitCode(CompilationResultBuilder crb) { 057 SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; 058 TargetDescription target = crb.target; 059 060 // address for counters array 061 SPARCAddress countersArrayAddr = new SPARCAddress(thread, config.jvmciCountersThreadOffset); 062 try (ScratchRegister scratch = masm.getScratchRegister()) { 063 Register countersArrayReg = scratch.getRegister(); 064 065 // load counters array 066 masm.ldx(countersArrayAddr, countersArrayReg); 067 IncrementEmitter emitter = new IncrementEmitter(countersArrayReg, masm); 068 forEachCounter(emitter, target); 069 } 070 } 071 072 private void emitIncrement(int counterIndex, SPARCMacroAssembler masm, SPARCAddress counterAddr, Value increment) { 073 try (ScratchRegister scratch = masm.getScratchRegister()) { 074 Register counterReg = scratch.getRegister(); 075 // load counter value 076 masm.ldx(counterAddr, counterReg); 077 counterPatchOffsets[counterIndex] = masm.position(); 078 // increment counter 079 if (isConstant(increment)) { 080 masm.add(counterReg, asInt(asConstant(increment)), counterReg); 081 } else { 082 masm.add(counterReg, asRegister(increment), counterReg); 083 } 084 // store counter value 085 masm.stx(counterReg, counterAddr); 086 } 087 } 088 089 /** 090 * Patches the increment value in the instruction emitted by the 091 * {@link #emitIncrement(int, SPARCMacroAssembler, SPARCAddress, Value)} method. This method is 092 * used if patching is needed after assembly. 093 * 094 * @param asm 095 * @param increment 096 */ 097 @Override 098 public void patchCounterIncrement(Assembler asm, int[] increment) { 099 for (int i = 0; i < increment.length; i++) { 100 int inst = counterPatchOffsets[i]; 101 ((SPARCAssembler) asm).patchAddImmediate(inst, increment[i]); 102 } 103 } 104 105 public int[] getCounterPatchOffsets() { 106 return counterPatchOffsets; 107 } 108 109 private class IncrementEmitter implements CounterProcedure { 110 private int lastDisplacement = 0; 111 private final Register countersArrayReg; 112 private final SPARCMacroAssembler masm; 113 114 public IncrementEmitter(Register countersArrayReg, SPARCMacroAssembler masm) { 115 super(); 116 this.countersArrayReg = countersArrayReg; 117 this.masm = masm; 118 } 119 120 public void apply(int counterIndex, Value increment, int displacement) { 121 SPARCAddress counterAddr; 122 int relativeDisplacement = displacement - lastDisplacement; 123 if (isSimm13(relativeDisplacement)) { // Displacement fits into ld instruction 124 counterAddr = new SPARCAddress(countersArrayReg, relativeDisplacement); 125 } else { 126 try (ScratchRegister scratch = masm.getScratchRegister()) { 127 Register tempOffsetRegister = scratch.getRegister(); 128 new Setx(relativeDisplacement, tempOffsetRegister, false).emit(masm); 129 masm.add(countersArrayReg, tempOffsetRegister, countersArrayReg); 130 } 131 lastDisplacement = displacement; 132 counterAddr = new SPARCAddress(countersArrayReg, 0); 133 } 134 emitIncrement(counterIndex, masm, counterAddr, increment); 135 } 136 } 137}