1 /*
   2  * Copyright (c) 2014, 2015, 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 org.graalvm.compiler.hotspot.sparc;
  24 
  25 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  26 import static jdk.vm.ci.code.ValueUtil.asRegister;
  27 import static jdk.vm.ci.sparc.SPARC.STACK_BIAS;
  28 import static jdk.vm.ci.sparc.SPARC.g0;
  29 import static jdk.vm.ci.sparc.SPARC.i0;
  30 import static jdk.vm.ci.sparc.SPARC.i1;
  31 import static jdk.vm.ci.sparc.SPARC.i2;
  32 import static jdk.vm.ci.sparc.SPARC.i3;
  33 import static jdk.vm.ci.sparc.SPARC.i4;
  34 import static jdk.vm.ci.sparc.SPARC.l7;
  35 import static jdk.vm.ci.sparc.SPARC.o0;
  36 import static jdk.vm.ci.sparc.SPARC.o1;
  37 import static jdk.vm.ci.sparc.SPARC.o2;
  38 import static jdk.vm.ci.sparc.SPARC.o3;
  39 import static jdk.vm.ci.sparc.SPARC.o4;
  40 import static jdk.vm.ci.sparc.SPARC.o5;
  41 import static jdk.vm.ci.sparc.SPARC.o7;
  42 import static jdk.vm.ci.sparc.SPARC.sp;
  43 
  44 import org.graalvm.compiler.asm.sparc.SPARCAddress;
  45 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
  46 import org.graalvm.compiler.core.common.LIRKind;
  47 import org.graalvm.compiler.hotspot.HotSpotBackend;
  48 import org.graalvm.compiler.lir.LIRInstructionClass;
  49 import org.graalvm.compiler.lir.Opcode;
  50 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  51 import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction;
  52 
  53 import jdk.vm.ci.code.Register;
  54 import jdk.vm.ci.meta.AllocatableValue;
  55 import jdk.vm.ci.meta.PlatformKind;
  56 
  57 /**
  58  * Emits code that enters a stack frame which is tailored to call the C++ method
  59  * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}.
  60  */
  61 @Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME")
  62 final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction {
  63     public static final LIRInstructionClass<SPARCHotSpotEnterUnpackFramesStackFrameOp> TYPE = LIRInstructionClass.create(SPARCHotSpotEnterUnpackFramesStackFrameOp.class);
  64 
  65     private final Register thread;
  66     private final int threadLastJavaSpOffset;
  67     private final int threadLastJavaPcOffset;
  68     @Alive(REG) AllocatableValue framePc;
  69     @Alive(REG) AllocatableValue senderSp;
  70     @Temp(REG) AllocatableValue scratch;
  71     @Temp(REG) AllocatableValue callerReturnPc;
  72 
  73     SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch,
  74                     PlatformKind wordKind) {
  75         super(TYPE);
  76         this.thread = thread;
  77         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
  78         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
  79         this.framePc = framePc;
  80         this.senderSp = senderSp;
  81         this.scratch = scratch;
  82         callerReturnPc = o7.asValue(LIRKind.value(wordKind));
  83     }
  84 
  85     @Override
  86     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
  87         final int totalFrameSize = crb.frameMap.totalFrameSize();
  88         Register framePcRegister = asRegister(framePc);
  89         Register senderSpRegister = asRegister(senderSp);
  90         Register scratchRegister = asRegister(scratch);
  91 
  92         // Save final sender SP to O5_savedSP.
  93         masm.mov(senderSpRegister, o5);
  94 
  95         // Load final frame PC.
  96         masm.mov(framePcRegister, asRegister(callerReturnPc));
  97 
  98         // Allocate a full sized frame.
  99         masm.save(sp, -totalFrameSize, sp);
 100 
 101         masm.mov(i0, o0);
 102         masm.mov(i1, o1);
 103         masm.mov(i2, o2);
 104         masm.mov(i3, o3);
 105         masm.mov(i4, o4);
 106 
 107         // Set up last Java values.
 108         masm.add(sp, STACK_BIAS, scratchRegister);
 109         masm.stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset));
 110 
 111         // Clear last Java PC.
 112         masm.stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset));
 113 
 114         /*
 115          * Safe thread register manually since we are not using LEAF_SP for {@link
 116          * DeoptimizationStub#UNPACK_FRAMES}.
 117          */
 118         masm.mov(thread, l7);
 119     }
 120 
 121     @Override
 122     public boolean leavesRegisterWindow() {
 123         return true;
 124     }
 125 }