hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java
changeset 38126 c3706b502779
parent 37761 82b8d12a553f
parent 38079 fd24ad51113a
child 38127 2ab00cd4556e
equal deleted inserted replaced
37761:82b8d12a553f 38126:c3706b502779
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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 
       
    24 package compiler.jvmci.code.amd64;
       
    25 
       
    26 import jdk.vm.ci.amd64.AMD64;
       
    27 import jdk.vm.ci.amd64.AMD64Kind;
       
    28 import jdk.vm.ci.code.CodeCacheProvider;
       
    29 import jdk.vm.ci.code.DebugInfo;
       
    30 import jdk.vm.ci.code.Register;
       
    31 import jdk.vm.ci.code.StackSlot;
       
    32 import jdk.vm.ci.code.site.ConstantReference;
       
    33 import jdk.vm.ci.code.site.DataSectionReference;
       
    34 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
       
    35 import jdk.vm.ci.hotspot.HotSpotConstant;
       
    36 import jdk.vm.ci.hotspot.HotSpotForeignCallTarget;
       
    37 import jdk.vm.ci.hotspot.HotSpotVMConfig;
       
    38 import jdk.vm.ci.meta.JavaKind;
       
    39 import jdk.vm.ci.meta.LIRKind;
       
    40 import jdk.vm.ci.meta.VMConstant;
       
    41 
       
    42 import compiler.jvmci.code.TestAssembler;
       
    43 
       
    44 public class AMD64TestAssembler extends TestAssembler {
       
    45 
       
    46     public AMD64TestAssembler(CodeCacheProvider codeCache) {
       
    47         super(codeCache, 16, 16, AMD64Kind.DWORD, AMD64.rax, AMD64.rcx, AMD64.rdi, AMD64.r8, AMD64.r9, AMD64.r10);
       
    48     }
       
    49 
       
    50     private void emitFatNop() {
       
    51         // 5 byte NOP:
       
    52         // NOP DWORD ptr [EAX + EAX*1 + 00H]
       
    53         code.emitByte(0x0F);
       
    54         code.emitByte(0x1F);
       
    55         code.emitByte(0x44);
       
    56         code.emitByte(0x00);
       
    57         code.emitByte(0x00);
       
    58     }
       
    59 
       
    60     @Override
       
    61     public void emitPrologue() {
       
    62         // WARNING: Initial instruction MUST be 5 bytes or longer so that
       
    63         // NativeJump::patch_verified_entry will be able to patch out the entry
       
    64         // code safely.
       
    65         emitFatNop();
       
    66         code.emitByte(0x50 | AMD64.rbp.encoding);  // PUSH rbp
       
    67         emitMove(true, AMD64.rbp, AMD64.rsp);      // MOV rbp, rsp
       
    68         setDeoptRescueSlot(newStackSlot(LIRKind.value(AMD64Kind.QWORD)));
       
    69     }
       
    70 
       
    71     @Override
       
    72     public void emitEpilogue() {
       
    73         HotSpotVMConfig config = HotSpotVMConfig.config();
       
    74         recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
       
    75         recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 5, true, null);
       
    76         code.emitByte(0xE8); // CALL rel32
       
    77         code.emitInt(0xDEADDEAD);
       
    78     }
       
    79 
       
    80     @Override
       
    81     public void emitGrowStack(int size) {
       
    82         // SUB rsp, size
       
    83         code.emitByte(0x48);
       
    84         code.emitByte(0x81);
       
    85         code.emitByte(0xEC);
       
    86         code.emitInt(size);
       
    87     }
       
    88 
       
    89     @Override
       
    90     public Register emitIntArg0() {
       
    91         return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)[0];
       
    92     }
       
    93 
       
    94     @Override
       
    95     public Register emitIntArg1() {
       
    96         return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)[1];
       
    97     }
       
    98 
       
    99     private void emitREX(boolean w, int r, int x, int b) {
       
   100         int wrxb = (w ? 0x08 : 0) | ((r >> 3) << 2) | ((x >> 3) << 1) | (b >> 3);
       
   101         if (wrxb != 0) {
       
   102             code.emitByte(0x40 | wrxb);
       
   103         }
       
   104     }
       
   105 
       
   106     private void emitModRMReg(boolean w, int opcode, int r, int m) {
       
   107         emitREX(w, r, 0, m);
       
   108         code.emitByte((byte) opcode);
       
   109         code.emitByte((byte) 0xC0 | ((r & 0x7) << 3) | (m & 0x7));
       
   110     }
       
   111 
       
   112     private void emitModRMMemory(boolean w, int opcode, int r, int b, int offset) {
       
   113         emitREX(w, r, 0, b);
       
   114         code.emitByte((byte) opcode);
       
   115         code.emitByte((byte) 0x80 | ((r & 0x7) << 3) | (b & 0x7));
       
   116         code.emitInt(offset);
       
   117     }
       
   118 
       
   119     @Override
       
   120     public Register emitLoadInt(int c) {
       
   121         Register ret = newRegister();
       
   122         emitREX(false, 0, 0, ret.encoding);
       
   123         code.emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
       
   124         code.emitInt(c);
       
   125         return ret;
       
   126     }
       
   127 
       
   128     @Override
       
   129     public Register emitLoadLong(long c) {
       
   130         Register ret = newRegister();
       
   131         emitREX(true, 0, 0, ret.encoding);
       
   132         code.emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r64, imm64
       
   133         code.emitLong(c);
       
   134         return ret;
       
   135     }
       
   136 
       
   137     @Override
       
   138     public Register emitLoadFloat(float c) {
       
   139         DataSectionReference ref = new DataSectionReference();
       
   140         ref.setOffset(data.position());
       
   141         data.emitFloat(c);
       
   142 
       
   143         recordDataPatchInCode(ref);
       
   144         Register ret = AMD64.xmm0;
       
   145         emitREX(false, ret.encoding, 0, 0);
       
   146         code.emitByte(0xF3);
       
   147         code.emitByte(0x0F);
       
   148         code.emitByte(0x10);                               // MOVSS xmm1, xmm2/m32
       
   149         code.emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // xmm, [rip+offset]
       
   150         code.emitInt(0xDEADDEAD);
       
   151         return ret;
       
   152     }
       
   153 
       
   154     @Override
       
   155     public Register emitLoadPointer(HotSpotConstant c) {
       
   156         recordDataPatchInCode(new ConstantReference((VMConstant) c));
       
   157         if (c.isCompressed()) {
       
   158             Register ret = newRegister();
       
   159             emitREX(false, 0, 0, ret.encoding);
       
   160             code.emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
       
   161             code.emitInt(0xDEADDEAD);
       
   162             return ret;
       
   163         } else {
       
   164             return emitLoadLong(0xDEADDEADDEADDEADl);
       
   165         }
       
   166     }
       
   167 
       
   168     private Register emitLoadPointer(DataSectionReference ref, boolean narrow) {
       
   169         recordDataPatchInCode(ref);
       
   170         Register ret = newRegister();
       
   171         emitREX(!narrow, ret.encoding, 0, 0);
       
   172         code.emitByte(0x8B);                               // MOV r64,r/m64
       
   173         code.emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // r64, [rip+offset]
       
   174         code.emitInt(0xDEADDEAD);
       
   175         return ret;
       
   176     }
       
   177 
       
   178     @Override
       
   179     public Register emitLoadPointer(DataSectionReference ref) {
       
   180         return emitLoadPointer(ref, false);
       
   181     }
       
   182 
       
   183     @Override
       
   184     public Register emitLoadNarrowPointer(DataSectionReference ref) {
       
   185         return emitLoadPointer(ref, true);
       
   186     }
       
   187 
       
   188     @Override
       
   189     public Register emitLoadPointer(Register b, int offset) {
       
   190         Register ret = newRegister();
       
   191         emitModRMMemory(true, 0x8B, ret.encoding, b.encoding, offset); // MOV r64,r/m64
       
   192         return ret;
       
   193     }
       
   194 
       
   195     @Override
       
   196     public StackSlot emitIntToStack(Register a) {
       
   197         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.DWORD));
       
   198         emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
       
   199         return ret;
       
   200     }
       
   201 
       
   202     @Override
       
   203     public StackSlot emitLongToStack(Register a) {
       
   204         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.QWORD));
       
   205         emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
       
   206         return ret;
       
   207     }
       
   208 
       
   209     @Override
       
   210     public StackSlot emitFloatToStack(Register a) {
       
   211         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.SINGLE));
       
   212         emitREX(false, a.encoding, 0, 0);
       
   213         code.emitByte(0xF3);
       
   214         code.emitByte(0x0F);
       
   215         code.emitByte(0x11);                               // MOVSS xmm2/m32, xmm1
       
   216         code.emitByte(0x85 | ((a.encoding & 0x7) << 3));   // [rbp+offset]
       
   217         code.emitInt(ret.getRawOffset() + 16);
       
   218         return ret;
       
   219     }
       
   220 
       
   221     @Override
       
   222     public StackSlot emitPointerToStack(Register a) {
       
   223         StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.QWORD));
       
   224         emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
       
   225         return ret;
       
   226     }
       
   227 
       
   228     @Override
       
   229     public StackSlot emitNarrowPointerToStack(Register a) {
       
   230         StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.DWORD));
       
   231         emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
       
   232         return ret;
       
   233     }
       
   234 
       
   235     @Override
       
   236     public Register emitUncompressPointer(Register compressed, long base, int shift) {
       
   237         if (shift > 0) {
       
   238             emitModRMReg(true, 0xC1, 4, compressed.encoding);
       
   239             code.emitByte(shift);
       
   240         }
       
   241         if (base == 0) {
       
   242             return compressed;
       
   243         } else {
       
   244             Register tmp = emitLoadLong(base);
       
   245             emitModRMReg(true, 0x03, tmp.encoding, compressed.encoding);
       
   246             return tmp;
       
   247         }
       
   248     }
       
   249 
       
   250     @Override
       
   251     public Register emitIntAdd(Register a, Register b) {
       
   252         emitModRMReg(false, 0x03, a.encoding, b.encoding);
       
   253         return a;
       
   254     }
       
   255 
       
   256     private void emitMove(boolean w, Register to, Register from) {
       
   257         if (to != from) {
       
   258             emitModRMReg(w, 0x8B, to.encoding, from.encoding);
       
   259         }
       
   260     }
       
   261 
       
   262     @Override
       
   263     public void emitIntRet(Register a) {
       
   264         emitMove(false, AMD64.rax, a);             // MOV eax, ...
       
   265         emitMove(true, AMD64.rsp, AMD64.rbp);      // MOV rsp, rbp
       
   266         code.emitByte(0x58 | AMD64.rbp.encoding);  // POP rbp
       
   267         code.emitByte(0xC3);                       // RET
       
   268     }
       
   269 
       
   270     @Override
       
   271     public void emitPointerRet(Register a) {
       
   272         emitMove(true, AMD64.rax, a);              // MOV rax, ...
       
   273         emitMove(true, AMD64.rsp, AMD64.rbp);      // MOV rsp, rbp
       
   274         code.emitByte(0x58 | AMD64.rbp.encoding);  // POP rbp
       
   275         code.emitByte(0xC3);                       // RET
       
   276     }
       
   277 
       
   278     @Override
       
   279     public void emitTrap(DebugInfo info) {
       
   280         recordImplicitException(info);
       
   281         // MOV rax, [0]
       
   282         code.emitByte(0x8B);
       
   283         code.emitByte(0x04);
       
   284         code.emitByte(0x25);
       
   285         code.emitInt(0);
       
   286     }
       
   287 }