SPARCTestAssembler.java revision 11519:4e13df329624
138032Speter/* 238032Speter * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 338032Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 438032Speter * 538032Speter * This code is free software; you can redistribute it and/or modify it 638032Speter * under the terms of the GNU General Public License version 2 only, as 738032Speter * published by the Free Software Foundation. 838032Speter * 938032Speter * This code is distributed in the hope that it will be useful, but WITHOUT 1038032Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1138032Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1238032Speter * version 2 for more details (a copy is included in the LICENSE file that 1338032Speter * accompanied this code). 1438032Speter * 1538032Speter * You should have received a copy of the GNU General Public License version 1638032Speter * 2 along with this work; if not, write to the Free Software Foundation, 1738032Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1838032Speter * 1938032Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2038032Speter * or visit www.oracle.com if you need additional information or have any 2138032Speter * questions. 2238032Speter */ 2338032Speter 2438032Speterpackage jdk.vm.ci.code.test.sparc; 2538032Speter 2638032Speterimport jdk.vm.ci.code.CodeCacheProvider; 2738032Speterimport jdk.vm.ci.code.DebugInfo; 2838032Speterimport jdk.vm.ci.code.Register; 2938032Speterimport jdk.vm.ci.code.StackSlot; 3038032Speterimport jdk.vm.ci.code.site.ConstantReference; 31import jdk.vm.ci.code.site.DataSectionReference; 32import jdk.vm.ci.code.test.TestAssembler; 33import jdk.vm.ci.code.test.TestHotSpotVMConfig; 34import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 35import jdk.vm.ci.hotspot.HotSpotCompiledCode; 36import jdk.vm.ci.hotspot.HotSpotConstant; 37import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; 38import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 39import jdk.vm.ci.meta.JavaKind; 40import jdk.vm.ci.meta.VMConstant; 41import jdk.vm.ci.sparc.SPARC; 42import jdk.vm.ci.sparc.SPARCKind; 43 44public class SPARCTestAssembler extends TestAssembler { 45 46 private static final int MASK13 = (1 << 13) - 1; 47 48 public SPARCTestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { 49 super(codeCache, config, 0, 16, SPARCKind.WORD, SPARC.l0, SPARC.l1, SPARC.l2, SPARC.l3, SPARC.l4, SPARC.l5, SPARC.l6, SPARC.l7); 50 } 51 52 private void emitOp2(Register rd, int op2, int imm22) { 53 code.emitInt((0b00 << 30) | (rd.encoding << 25) | (op2 << 22) | imm22); 54 } 55 56 private void emitOp3(int op, Register rd, int op3, Register rs1, Register rs2) { 57 code.emitInt((op << 30) | (rd.encoding << 25) | (op3 << 19) | (rs1.encoding << 14) | rs2.encoding); 58 } 59 60 private void emitOp3(int op, Register rd, int op3, Register rs1, int simm13) { 61 code.emitInt((op << 30) | (rd.encoding << 25) | (op3 << 19) | (rs1.encoding << 14) | (1 << 13) | (simm13 & MASK13)); 62 } 63 64 private void emitNop() { 65 code.emitInt(1 << 24); 66 } 67 68 @Override 69 public void emitPrologue() { 70 // SAVE sp, -128, sp 71 emitOp3(0b10, SPARC.sp, 0b111100, SPARC.sp, -SPARC.REGISTER_SAFE_AREA_SIZE); 72 setDeoptRescueSlot(newStackSlot(SPARCKind.XWORD)); 73 } 74 75 @Override 76 public void emitEpilogue() { 77 recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); 78 recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 4, true, null); 79 code.emitInt(1 << 30); // CALL 80 } 81 82 @Override 83 public HotSpotCompiledCode finish(HotSpotResolvedJavaMethod method) { 84 frameSize += SPARC.REGISTER_SAFE_AREA_SIZE; 85 return super.finish(method); 86 } 87 88 @Override 89 public void emitGrowStack(int size) { 90 emitOp3(0b10, SPARC.sp, 0b000100, SPARC.sp, size); // SUB sp, size, sp 91 } 92 93 @Override 94 public Register emitIntArg0() { 95 return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int)[0]; 96 } 97 98 @Override 99 public Register emitIntArg1() { 100 return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int)[1]; 101 } 102 103 @Override 104 public Register emitLoadInt(int c) { 105 Register ret = newRegister(); 106 int hi = c >>> 10; 107 int lo = c & ((1 << 10) - 1); 108 if (hi == 0) { 109 emitOp3(0b10, ret, 0b000010, SPARC.g0, lo); // OR g0, lo, ret 110 } else { 111 emitOp2(ret, 0b100, hi); // SETHI hi, ret 112 if (lo != 0) { 113 emitOp3(0b10, ret, 0b000010, ret, lo); // OR ret, lo, ret 114 } 115 } 116 return ret; 117 } 118 119 @Override 120 public Register emitLoadLong(long c) { 121 if ((c & 0xFFFF_FFFFL) == c) { 122 return emitLoadInt((int) c); 123 } else { 124 DataSectionReference ref = new DataSectionReference(); 125 data.align(8); 126 ref.setOffset(data.position()); 127 data.emitLong(c); 128 return emitLoadPointer(ref); 129 } 130 } 131 132 private void emitPatchableSethi(Register ret, boolean wide) { 133 int startPos = code.position(); 134 emitOp2(ret, 0b100, 0); // SETHI 0, ret 135 if (wide) { 136 // pad for later patching 137 while (code.position() < (startPos + 28)) { 138 emitNop(); 139 } 140 } 141 } 142 143 @Override 144 public Register emitLoadFloat(float c) { 145 DataSectionReference ref = new DataSectionReference(); 146 data.align(4); 147 ref.setOffset(data.position()); 148 data.emitFloat(c); 149 150 Register ptr = newRegister(); 151 recordDataPatchInCode(ref); 152 emitPatchableSethi(ptr, true); 153 emitOp3(0b11, SPARC.f0, 0b100000, ptr, 0); // LDF [ptr+0], f0 154 return SPARC.f0; 155 } 156 157 @Override 158 public Register emitLoadPointer(HotSpotConstant c) { 159 Register ret = newRegister(); 160 recordDataPatchInCode(new ConstantReference((VMConstant) c)); 161 162 emitPatchableSethi(ret, !c.isCompressed()); 163 emitOp3(0b10, ret, 0b000010, ret, 0); // OR ret, 0, ret 164 165 return ret; 166 } 167 168 @Override 169 public Register emitLoadPointer(DataSectionReference ref) { 170 Register ret = newRegister(); 171 recordDataPatchInCode(ref); 172 emitPatchableSethi(ret, true); 173 emitOp3(0b11, ret, 0b001011, ret, 0); // LDX [ret+0], ret 174 return ret; 175 } 176 177 @Override 178 public Register emitLoadNarrowPointer(DataSectionReference ref) { 179 Register ret = newRegister(); 180 recordDataPatchInCode(ref); 181 emitPatchableSethi(ret, true); 182 emitOp3(0b11, ret, 0b000000, ret, 0); // LDUW [ret+0], ret 183 return ret; 184 } 185 186 @Override 187 public Register emitLoadPointer(Register b, int offset) { 188 Register ret = newRegister(); 189 emitOp3(0b11, ret, 0b001011, b, offset); // LDX [b+offset], ret 190 return ret; 191 } 192 193 @Override 194 public StackSlot emitIntToStack(Register a) { 195 StackSlot ret = newStackSlot(SPARCKind.WORD); 196 // STW a, [fp+offset] 197 emitOp3(0b11, a, 0b000100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); 198 return ret; 199 } 200 201 @Override 202 public StackSlot emitLongToStack(Register a) { 203 StackSlot ret = newStackSlot(SPARCKind.XWORD); 204 // STX a, [fp+offset] 205 emitOp3(0b11, a, 0b001110, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); 206 return ret; 207 } 208 209 @Override 210 public StackSlot emitFloatToStack(Register a) { 211 StackSlot ret = newStackSlot(SPARCKind.SINGLE); 212 // STF a, [fp+offset] 213 emitOp3(0b11, a, 0b100100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); 214 return ret; 215 } 216 217 @Override 218 public StackSlot emitPointerToStack(Register a) { 219 StackSlot ret = newStackSlot(SPARCKind.XWORD); 220 // STX a, [fp+offset] 221 emitOp3(0b11, a, 0b001110, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); 222 return ret; 223 } 224 225 @Override 226 public StackSlot emitNarrowPointerToStack(Register a) { 227 StackSlot ret = newStackSlot(SPARCKind.WORD); 228 // STW a, [fp+offset] 229 emitOp3(0b11, a, 0b000100, SPARC.fp, ret.getRawOffset() + SPARC.STACK_BIAS); 230 return ret; 231 } 232 233 @Override 234 public Register emitUncompressPointer(Register compressed, long base, int shift) { 235 Register ret; 236 if (shift > 0) { 237 ret = newRegister(); 238 emitOp3(0b10, ret, 0b100101, compressed, shift); // SLL compressed, shift, ret 239 } else { 240 ret = compressed; 241 } 242 if (base == 0) { 243 return ret; 244 } else { 245 Register b = emitLoadLong(base); 246 emitOp3(0b10, b, 0b00000, ret, b); // ADD b, ret, b 247 return b; 248 } 249 } 250 251 @Override 252 public Register emitIntAdd(Register a, Register b) { 253 Register ret = newRegister(); 254 emitOp3(0b10, ret, 0b00000, a, b); // ADD a, b, ret 255 return ret; 256 } 257 258 private void emitMove(Register to, Register from) { 259 if (to != from) { 260 emitOp3(0b10, to, 0b000010, from, SPARC.g0); // OR from, g0, to 261 } 262 } 263 264 @Override 265 public void emitIntRet(Register a) { 266 emitPointerRet(a); 267 } 268 269 @Override 270 public void emitPointerRet(Register a) { 271 emitMove(SPARC.i0, a); 272 emitOp3(0b10, SPARC.g0, 0b111000, SPARC.i7, 8); // JMPL [i7+8], g0 273 emitOp3(0b10, SPARC.g0, 0b111101, SPARC.g0, SPARC.g0); // RESTORE g0, g0, g0 274 } 275 276 @Override 277 public void emitTrap(DebugInfo info) { 278 recordImplicitException(info); 279 emitOp3(0b11, SPARC.g0, 0b001011, SPARC.g0, 0); // LDX [g0+0], g0 280 } 281 282 @Override 283 public DataSectionReference emitDataItem(HotSpotConstant c) { 284 if (c.isCompressed()) { 285 data.align(4); 286 } else { 287 data.align(8); 288 } 289 return super.emitDataItem(c); 290 } 291} 292