hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java
changeset 35137 c8f8f6de68a7
child 35144 f2381983e98e
equal deleted inserted replaced
35136:f3788128ff3f 35137:c8f8f6de68a7
       
     1 /*
       
     2  * Copyright (c) 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 
       
    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.CompilationResult;
       
    30 import jdk.vm.ci.code.CompilationResult.ConstantReference;
       
    31 import jdk.vm.ci.code.CompilationResult.DataSectionReference;
       
    32 import jdk.vm.ci.code.DataSection.Data;
       
    33 import jdk.vm.ci.code.DebugInfo;
       
    34 import jdk.vm.ci.code.InfopointReason;
       
    35 import jdk.vm.ci.code.Register;
       
    36 import jdk.vm.ci.code.StackSlot;
       
    37 import jdk.vm.ci.hotspot.HotSpotConstant;
       
    38 import jdk.vm.ci.meta.JavaConstant;
       
    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(CompilationResult result, CodeCacheProvider codeCache) {
       
    47         super(result, codeCache, 16, 16, AMD64Kind.DWORD, AMD64.rax, AMD64.rcx, AMD64.rdi, AMD64.r8, AMD64.r9, AMD64.r10);
       
    48     }
       
    49 
       
    50     public void emitPrologue() {
       
    51         emitByte(0x50 | AMD64.rbp.encoding);  // PUSH rbp
       
    52         emitMove(true, AMD64.rbp, AMD64.rsp); // MOV rbp, rsp
       
    53     }
       
    54 
       
    55     public void emitGrowStack(int size) {
       
    56         // SUB rsp, size
       
    57         emitByte(0x48);
       
    58         emitByte(0x81);
       
    59         emitByte(0xEC);
       
    60         emitInt(size);
       
    61     }
       
    62 
       
    63     public Register emitIntArg0() {
       
    64         return AMD64.rsi;
       
    65     }
       
    66 
       
    67     public Register emitIntArg1() {
       
    68         return AMD64.rdx;
       
    69     }
       
    70 
       
    71     private void emitREX(boolean w, int r, int x, int b) {
       
    72         int wrxb = (w ? 0x08 : 0) | ((r >> 3) << 2) | ((x >> 3) << 1) | (b >> 3);
       
    73         if (wrxb != 0) {
       
    74             emitByte(0x40 | wrxb);
       
    75         }
       
    76     }
       
    77 
       
    78     private void emitModRMReg(boolean w, int opcode, int r, int m) {
       
    79         emitREX(w, r, 0, m);
       
    80         emitByte((byte) opcode);
       
    81         emitByte((byte) 0xC0 | ((r & 0x7) << 3) | (m & 0x7));
       
    82     }
       
    83 
       
    84     private void emitModRMMemory(boolean w, int opcode, int r, int b, int offset) {
       
    85         emitREX(w, r, 0, b);
       
    86         emitByte((byte) opcode);
       
    87         emitByte((byte) 0x80 | ((r & 0x7) << 3) | (b & 0x7));
       
    88         emitInt(offset);
       
    89     }
       
    90 
       
    91     public Register emitLoadInt(int c) {
       
    92         Register ret = newRegister();
       
    93         emitREX(false, 0, 0, ret.encoding);
       
    94         emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
       
    95         emitInt(c);
       
    96         return ret;
       
    97     }
       
    98 
       
    99     public Register emitLoadLong(long c) {
       
   100         Register ret = newRegister();
       
   101         emitREX(true, 0, 0, ret.encoding);
       
   102         emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r64, imm64
       
   103         emitLong(c);
       
   104         return ret;
       
   105     }
       
   106 
       
   107     public Register emitLoadFloat(float c) {
       
   108         Data data = codeCache.createDataItem(JavaConstant.forFloat(c));
       
   109         DataSectionReference ref = result.getDataSection().insertData(data);
       
   110         result.recordDataPatch(position(), ref);
       
   111         Register ret = AMD64.xmm0;
       
   112         emitREX(false, ret.encoding, 0, 0);
       
   113         emitByte(0xF3);
       
   114         emitByte(0x0F);
       
   115         emitByte(0x10);                               // MOVSS xmm1, xmm2/m32
       
   116         emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // xmm, [rip+offset]
       
   117         emitInt(0xDEADDEAD);
       
   118         return ret;
       
   119     }
       
   120 
       
   121     public Register emitLoadPointer(HotSpotConstant c) {
       
   122         result.recordDataPatch(position(), new ConstantReference((VMConstant) c));
       
   123         if (c.isCompressed()) {
       
   124             Register ret = newRegister();
       
   125             emitREX(false, 0, 0, ret.encoding);
       
   126             emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
       
   127             emitInt(0xDEADDEAD);
       
   128             return ret;
       
   129         } else {
       
   130             return emitLoadLong(0xDEADDEADDEADDEADl);
       
   131         }
       
   132     }
       
   133 
       
   134     private Register emitLoadPointer(DataSectionReference ref, boolean narrow) {
       
   135         result.recordDataPatch(position(), ref);
       
   136         Register ret = newRegister();
       
   137         emitREX(!narrow, ret.encoding, 0, 0);
       
   138         emitByte(0x8B);                               // MOV r64,r/m64
       
   139         emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // r64, [rip+offset]
       
   140         emitInt(0xDEADDEAD);
       
   141         return ret;
       
   142     }
       
   143 
       
   144     public Register emitLoadPointer(DataSectionReference ref) {
       
   145         return emitLoadPointer(ref, false);
       
   146     }
       
   147 
       
   148     public Register emitLoadNarrowPointer(DataSectionReference ref) {
       
   149         return emitLoadPointer(ref, true);
       
   150     }
       
   151 
       
   152     public Register emitLoadPointer(Register b, int offset) {
       
   153         Register ret = newRegister();
       
   154         emitModRMMemory(true, 0x8B, ret.encoding, b.encoding, offset); // MOV r64,r/m64
       
   155         return ret;
       
   156     }
       
   157 
       
   158     public StackSlot emitIntToStack(Register a) {
       
   159         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.DWORD));
       
   160         emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
       
   161         return ret;
       
   162     }
       
   163 
       
   164     public StackSlot emitLongToStack(Register a) {
       
   165         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.QWORD));
       
   166         emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
       
   167         return ret;
       
   168     }
       
   169 
       
   170     public StackSlot emitFloatToStack(Register a) {
       
   171         StackSlot ret = newStackSlot(LIRKind.value(AMD64Kind.SINGLE));
       
   172         emitREX(false, a.encoding, 0, 0);
       
   173         emitByte(0xF3);
       
   174         emitByte(0x0F);
       
   175         emitByte(0x11);                               // MOVSS xmm2/m32, xmm1
       
   176         emitByte(0x85 | ((a.encoding & 0x7) << 3));   // [rbp+offset]
       
   177         emitInt(ret.getRawOffset() + 16);
       
   178         return ret;
       
   179     }
       
   180 
       
   181     public StackSlot emitPointerToStack(Register a) {
       
   182         StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.QWORD));
       
   183         emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m64,r64
       
   184         return ret;
       
   185     }
       
   186 
       
   187     public StackSlot emitNarrowPointerToStack(Register a) {
       
   188         StackSlot ret = newStackSlot(LIRKind.reference(AMD64Kind.DWORD));
       
   189         emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16); // MOV r/m32,r32
       
   190         return ret;
       
   191     }
       
   192 
       
   193     public Register emitUncompressPointer(Register compressed, long base, int shift) {
       
   194         if (shift > 0) {
       
   195             emitModRMReg(true, 0xC1, 4, compressed.encoding);
       
   196             emitByte(shift);
       
   197         }
       
   198         if (base == 0) {
       
   199             return compressed;
       
   200         } else {
       
   201             Register tmp = emitLoadLong(base);
       
   202             emitModRMReg(true, 0x03, tmp.encoding, compressed.encoding);
       
   203             return tmp;
       
   204         }
       
   205     }
       
   206 
       
   207     public Register emitIntAdd(Register a, Register b) {
       
   208         emitModRMReg(false, 0x03, a.encoding, b.encoding);
       
   209         return a;
       
   210     }
       
   211 
       
   212     private void emitMove(boolean w, Register to, Register from) {
       
   213         if (to != from) {
       
   214             emitModRMReg(w, 0x8B, to.encoding, from.encoding);
       
   215         }
       
   216     }
       
   217 
       
   218     public void emitIntRet(Register a) {
       
   219         emitMove(false, AMD64.rax, a);        // MOV eax, ...
       
   220         emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
       
   221         emitByte(0x58 | AMD64.rbp.encoding);  // POP rbp
       
   222         emitByte(0xC3);                       // RET
       
   223     }
       
   224 
       
   225     public void emitPointerRet(Register a) {
       
   226         emitMove(true, AMD64.rax, a);         // MOV rax, ...
       
   227         emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
       
   228         emitByte(0x58 | AMD64.rbp.encoding);  // POP rbp
       
   229         emitByte(0xC3);                       // RET
       
   230     }
       
   231 
       
   232     public void emitTrap(DebugInfo info) {
       
   233         result.recordInfopoint(position(), info, InfopointReason.IMPLICIT_EXCEPTION);
       
   234         // MOV rax, [0]
       
   235         emitByte(0x8B);
       
   236         emitByte(0x04);
       
   237         emitByte(0x25);
       
   238         emitInt(0);
       
   239     }
       
   240 }