annotate src/cpu/x86/vm/x86_64.ad @ 0:a61af66fc99e

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 3d62cb85208d
rev   line source
duke@0 1 //
duke@0 2 // Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
duke@0 3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 //
duke@0 5 // This code is free software; you can redistribute it and/or modify it
duke@0 6 // under the terms of the GNU General Public License version 2 only, as
duke@0 7 // published by the Free Software Foundation.
duke@0 8 //
duke@0 9 // This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 12 // version 2 for more details (a copy is included in the LICENSE file that
duke@0 13 // accompanied this code).
duke@0 14 //
duke@0 15 // You should have received a copy of the GNU General Public License version
duke@0 16 // 2 along with this work; if not, write to the Free Software Foundation,
duke@0 17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 18 //
duke@0 19 // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@0 20 // CA 95054 USA or visit www.sun.com if you need additional information or
duke@0 21 // have any questions.
duke@0 22 //
duke@0 23 //
duke@0 24
duke@0 25 // AMD64 Architecture Description File
duke@0 26
duke@0 27 //----------REGISTER DEFINITION BLOCK------------------------------------------
duke@0 28 // This information is used by the matcher and the register allocator to
duke@0 29 // describe individual registers and classes of registers within the target
duke@0 30 // archtecture.
duke@0 31
duke@0 32 register %{
duke@0 33 //----------Architecture Description Register Definitions----------------------
duke@0 34 // General Registers
duke@0 35 // "reg_def" name ( register save type, C convention save type,
duke@0 36 // ideal register type, encoding );
duke@0 37 // Register Save Types:
duke@0 38 //
duke@0 39 // NS = No-Save: The register allocator assumes that these registers
duke@0 40 // can be used without saving upon entry to the method, &
duke@0 41 // that they do not need to be saved at call sites.
duke@0 42 //
duke@0 43 // SOC = Save-On-Call: The register allocator assumes that these registers
duke@0 44 // can be used without saving upon entry to the method,
duke@0 45 // but that they must be saved at call sites.
duke@0 46 //
duke@0 47 // SOE = Save-On-Entry: The register allocator assumes that these registers
duke@0 48 // must be saved before using them upon entry to the
duke@0 49 // method, but they do not need to be saved at call
duke@0 50 // sites.
duke@0 51 //
duke@0 52 // AS = Always-Save: The register allocator assumes that these registers
duke@0 53 // must be saved before using them upon entry to the
duke@0 54 // method, & that they must be saved at call sites.
duke@0 55 //
duke@0 56 // Ideal Register Type is used to determine how to save & restore a
duke@0 57 // register. Op_RegI will get spilled with LoadI/StoreI, Op_RegP will get
duke@0 58 // spilled with LoadP/StoreP. If the register supports both, use Op_RegI.
duke@0 59 //
duke@0 60 // The encoding number is the actual bit-pattern placed into the opcodes.
duke@0 61
duke@0 62 // General Registers
duke@0 63 // R8-R15 must be encoded with REX. (RSP, RBP, RSI, RDI need REX when
duke@0 64 // used as byte registers)
duke@0 65
duke@0 66 // Previously set RBX, RSI, and RDI as save-on-entry for java code
duke@0 67 // Turn off SOE in java-code due to frequent use of uncommon-traps.
duke@0 68 // Now that allocator is better, turn on RSI and RDI as SOE registers.
duke@0 69
duke@0 70 reg_def RAX (SOC, SOC, Op_RegI, 0, rax->as_VMReg());
duke@0 71 reg_def RAX_H(SOC, SOC, Op_RegI, 0, rax->as_VMReg()->next());
duke@0 72
duke@0 73 reg_def RCX (SOC, SOC, Op_RegI, 1, rcx->as_VMReg());
duke@0 74 reg_def RCX_H(SOC, SOC, Op_RegI, 1, rcx->as_VMReg()->next());
duke@0 75
duke@0 76 reg_def RDX (SOC, SOC, Op_RegI, 2, rdx->as_VMReg());
duke@0 77 reg_def RDX_H(SOC, SOC, Op_RegI, 2, rdx->as_VMReg()->next());
duke@0 78
duke@0 79 reg_def RBX (SOC, SOE, Op_RegI, 3, rbx->as_VMReg());
duke@0 80 reg_def RBX_H(SOC, SOE, Op_RegI, 3, rbx->as_VMReg()->next());
duke@0 81
duke@0 82 reg_def RSP (NS, NS, Op_RegI, 4, rsp->as_VMReg());
duke@0 83 reg_def RSP_H(NS, NS, Op_RegI, 4, rsp->as_VMReg()->next());
duke@0 84
duke@0 85 // now that adapter frames are gone RBP is always saved and restored by the prolog/epilog code
duke@0 86 reg_def RBP (NS, SOE, Op_RegI, 5, rbp->as_VMReg());
duke@0 87 reg_def RBP_H(NS, SOE, Op_RegI, 5, rbp->as_VMReg()->next());
duke@0 88
duke@0 89 #ifdef _WIN64
duke@0 90
duke@0 91 reg_def RSI (SOC, SOE, Op_RegI, 6, rsi->as_VMReg());
duke@0 92 reg_def RSI_H(SOC, SOE, Op_RegI, 6, rsi->as_VMReg()->next());
duke@0 93
duke@0 94 reg_def RDI (SOC, SOE, Op_RegI, 7, rdi->as_VMReg());
duke@0 95 reg_def RDI_H(SOC, SOE, Op_RegI, 7, rdi->as_VMReg()->next());
duke@0 96
duke@0 97 #else
duke@0 98
duke@0 99 reg_def RSI (SOC, SOC, Op_RegI, 6, rsi->as_VMReg());
duke@0 100 reg_def RSI_H(SOC, SOC, Op_RegI, 6, rsi->as_VMReg()->next());
duke@0 101
duke@0 102 reg_def RDI (SOC, SOC, Op_RegI, 7, rdi->as_VMReg());
duke@0 103 reg_def RDI_H(SOC, SOC, Op_RegI, 7, rdi->as_VMReg()->next());
duke@0 104
duke@0 105 #endif
duke@0 106
duke@0 107 reg_def R8 (SOC, SOC, Op_RegI, 8, r8->as_VMReg());
duke@0 108 reg_def R8_H (SOC, SOC, Op_RegI, 8, r8->as_VMReg()->next());
duke@0 109
duke@0 110 reg_def R9 (SOC, SOC, Op_RegI, 9, r9->as_VMReg());
duke@0 111 reg_def R9_H (SOC, SOC, Op_RegI, 9, r9->as_VMReg()->next());
duke@0 112
duke@0 113 reg_def R10 (SOC, SOC, Op_RegI, 10, r10->as_VMReg());
duke@0 114 reg_def R10_H(SOC, SOC, Op_RegI, 10, r10->as_VMReg()->next());
duke@0 115
duke@0 116 reg_def R11 (SOC, SOC, Op_RegI, 11, r11->as_VMReg());
duke@0 117 reg_def R11_H(SOC, SOC, Op_RegI, 11, r11->as_VMReg()->next());
duke@0 118
duke@0 119 reg_def R12 (SOC, SOE, Op_RegI, 12, r12->as_VMReg());
duke@0 120 reg_def R12_H(SOC, SOE, Op_RegI, 12, r12->as_VMReg()->next());
duke@0 121
duke@0 122 reg_def R13 (SOC, SOE, Op_RegI, 13, r13->as_VMReg());
duke@0 123 reg_def R13_H(SOC, SOE, Op_RegI, 13, r13->as_VMReg()->next());
duke@0 124
duke@0 125 reg_def R14 (SOC, SOE, Op_RegI, 14, r14->as_VMReg());
duke@0 126 reg_def R14_H(SOC, SOE, Op_RegI, 14, r14->as_VMReg()->next());
duke@0 127
duke@0 128 reg_def R15 (SOC, SOE, Op_RegI, 15, r15->as_VMReg());
duke@0 129 reg_def R15_H(SOC, SOE, Op_RegI, 15, r15->as_VMReg()->next());
duke@0 130
duke@0 131
duke@0 132 // Floating Point Registers
duke@0 133
duke@0 134 // XMM registers. 128-bit registers or 4 words each, labeled (a)-d.
duke@0 135 // Word a in each register holds a Float, words ab hold a Double. We
duke@0 136 // currently do not use the SIMD capabilities, so registers cd are
duke@0 137 // unused at the moment.
duke@0 138 // XMM8-XMM15 must be encoded with REX.
duke@0 139 // Linux ABI: No register preserved across function calls
duke@0 140 // XMM0-XMM7 might hold parameters
duke@0 141 // Windows ABI: XMM6-XMM15 preserved across function calls
duke@0 142 // XMM0-XMM3 might hold parameters
duke@0 143
duke@0 144 reg_def XMM0 (SOC, SOC, Op_RegF, 0, xmm0->as_VMReg());
duke@0 145 reg_def XMM0_H (SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next());
duke@0 146
duke@0 147 reg_def XMM1 (SOC, SOC, Op_RegF, 1, xmm1->as_VMReg());
duke@0 148 reg_def XMM1_H (SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next());
duke@0 149
duke@0 150 reg_def XMM2 (SOC, SOC, Op_RegF, 2, xmm2->as_VMReg());
duke@0 151 reg_def XMM2_H (SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next());
duke@0 152
duke@0 153 reg_def XMM3 (SOC, SOC, Op_RegF, 3, xmm3->as_VMReg());
duke@0 154 reg_def XMM3_H (SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next());
duke@0 155
duke@0 156 reg_def XMM4 (SOC, SOC, Op_RegF, 4, xmm4->as_VMReg());
duke@0 157 reg_def XMM4_H (SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next());
duke@0 158
duke@0 159 reg_def XMM5 (SOC, SOC, Op_RegF, 5, xmm5->as_VMReg());
duke@0 160 reg_def XMM5_H (SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next());
duke@0 161
duke@0 162 #ifdef _WIN64
duke@0 163
duke@0 164 reg_def XMM6 (SOC, SOE, Op_RegF, 6, xmm6->as_VMReg());
duke@0 165 reg_def XMM6_H (SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next());
duke@0 166
duke@0 167 reg_def XMM7 (SOC, SOE, Op_RegF, 7, xmm7->as_VMReg());
duke@0 168 reg_def XMM7_H (SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next());
duke@0 169
duke@0 170 reg_def XMM8 (SOC, SOE, Op_RegF, 8, xmm8->as_VMReg());
duke@0 171 reg_def XMM8_H (SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next());
duke@0 172
duke@0 173 reg_def XMM9 (SOC, SOE, Op_RegF, 9, xmm9->as_VMReg());
duke@0 174 reg_def XMM9_H (SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next());
duke@0 175
duke@0 176 reg_def XMM10 (SOC, SOE, Op_RegF, 10, xmm10->as_VMReg());
duke@0 177 reg_def XMM10_H(SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next());
duke@0 178
duke@0 179 reg_def XMM11 (SOC, SOE, Op_RegF, 11, xmm11->as_VMReg());
duke@0 180 reg_def XMM11_H(SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next());
duke@0 181
duke@0 182 reg_def XMM12 (SOC, SOE, Op_RegF, 12, xmm12->as_VMReg());
duke@0 183 reg_def XMM12_H(SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next());
duke@0 184
duke@0 185 reg_def XMM13 (SOC, SOE, Op_RegF, 13, xmm13->as_VMReg());
duke@0 186 reg_def XMM13_H(SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next());
duke@0 187
duke@0 188 reg_def XMM14 (SOC, SOE, Op_RegF, 14, xmm14->as_VMReg());
duke@0 189 reg_def XMM14_H(SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next());
duke@0 190
duke@0 191 reg_def XMM15 (SOC, SOE, Op_RegF, 15, xmm15->as_VMReg());
duke@0 192 reg_def XMM15_H(SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next());
duke@0 193
duke@0 194 #else
duke@0 195
duke@0 196 reg_def XMM6 (SOC, SOC, Op_RegF, 6, xmm6->as_VMReg());
duke@0 197 reg_def XMM6_H (SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next());
duke@0 198
duke@0 199 reg_def XMM7 (SOC, SOC, Op_RegF, 7, xmm7->as_VMReg());
duke@0 200 reg_def XMM7_H (SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next());
duke@0 201
duke@0 202 reg_def XMM8 (SOC, SOC, Op_RegF, 8, xmm8->as_VMReg());
duke@0 203 reg_def XMM8_H (SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next());
duke@0 204
duke@0 205 reg_def XMM9 (SOC, SOC, Op_RegF, 9, xmm9->as_VMReg());
duke@0 206 reg_def XMM9_H (SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next());
duke@0 207
duke@0 208 reg_def XMM10 (SOC, SOC, Op_RegF, 10, xmm10->as_VMReg());
duke@0 209 reg_def XMM10_H(SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next());
duke@0 210
duke@0 211 reg_def XMM11 (SOC, SOC, Op_RegF, 11, xmm11->as_VMReg());
duke@0 212 reg_def XMM11_H(SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next());
duke@0 213
duke@0 214 reg_def XMM12 (SOC, SOC, Op_RegF, 12, xmm12->as_VMReg());
duke@0 215 reg_def XMM12_H(SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next());
duke@0 216
duke@0 217 reg_def XMM13 (SOC, SOC, Op_RegF, 13, xmm13->as_VMReg());
duke@0 218 reg_def XMM13_H(SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next());
duke@0 219
duke@0 220 reg_def XMM14 (SOC, SOC, Op_RegF, 14, xmm14->as_VMReg());
duke@0 221 reg_def XMM14_H(SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next());
duke@0 222
duke@0 223 reg_def XMM15 (SOC, SOC, Op_RegF, 15, xmm15->as_VMReg());
duke@0 224 reg_def XMM15_H(SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next());
duke@0 225
duke@0 226 #endif // _WIN64
duke@0 227
duke@0 228 reg_def RFLAGS(SOC, SOC, 0, 16, VMRegImpl::Bad());
duke@0 229
duke@0 230 // Specify priority of register selection within phases of register
duke@0 231 // allocation. Highest priority is first. A useful heuristic is to
duke@0 232 // give registers a low priority when they are required by machine
duke@0 233 // instructions, like EAX and EDX on I486, and choose no-save registers
duke@0 234 // before save-on-call, & save-on-call before save-on-entry. Registers
duke@0 235 // which participate in fixed calling sequences should come last.
duke@0 236 // Registers which are used as pairs must fall on an even boundary.
duke@0 237
duke@0 238 alloc_class chunk0(R10, R10_H,
duke@0 239 R11, R11_H,
duke@0 240 R8, R8_H,
duke@0 241 R9, R9_H,
duke@0 242 R12, R12_H,
duke@0 243 RCX, RCX_H,
duke@0 244 RBX, RBX_H,
duke@0 245 RDI, RDI_H,
duke@0 246 RDX, RDX_H,
duke@0 247 RSI, RSI_H,
duke@0 248 RAX, RAX_H,
duke@0 249 RBP, RBP_H,
duke@0 250 R13, R13_H,
duke@0 251 R14, R14_H,
duke@0 252 R15, R15_H,
duke@0 253 RSP, RSP_H);
duke@0 254
duke@0 255 // XXX probably use 8-15 first on Linux
duke@0 256 alloc_class chunk1(XMM0, XMM0_H,
duke@0 257 XMM1, XMM1_H,
duke@0 258 XMM2, XMM2_H,
duke@0 259 XMM3, XMM3_H,
duke@0 260 XMM4, XMM4_H,
duke@0 261 XMM5, XMM5_H,
duke@0 262 XMM6, XMM6_H,
duke@0 263 XMM7, XMM7_H,
duke@0 264 XMM8, XMM8_H,
duke@0 265 XMM9, XMM9_H,
duke@0 266 XMM10, XMM10_H,
duke@0 267 XMM11, XMM11_H,
duke@0 268 XMM12, XMM12_H,
duke@0 269 XMM13, XMM13_H,
duke@0 270 XMM14, XMM14_H,
duke@0 271 XMM15, XMM15_H);
duke@0 272
duke@0 273 alloc_class chunk2(RFLAGS);
duke@0 274
duke@0 275
duke@0 276 //----------Architecture Description Register Classes--------------------------
duke@0 277 // Several register classes are automatically defined based upon information in
duke@0 278 // this architecture description.
duke@0 279 // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
duke@0 280 // 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
duke@0 281 // 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
duke@0 282 // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
duke@0 283 //
duke@0 284
duke@0 285 // Class for all pointer registers (including RSP)
duke@0 286 reg_class any_reg(RAX, RAX_H,
duke@0 287 RDX, RDX_H,
duke@0 288 RBP, RBP_H,
duke@0 289 RDI, RDI_H,
duke@0 290 RSI, RSI_H,
duke@0 291 RCX, RCX_H,
duke@0 292 RBX, RBX_H,
duke@0 293 RSP, RSP_H,
duke@0 294 R8, R8_H,
duke@0 295 R9, R9_H,
duke@0 296 R10, R10_H,
duke@0 297 R11, R11_H,
duke@0 298 R12, R12_H,
duke@0 299 R13, R13_H,
duke@0 300 R14, R14_H,
duke@0 301 R15, R15_H);
duke@0 302
duke@0 303 // Class for all pointer registers except RSP
duke@0 304 reg_class ptr_reg(RAX, RAX_H,
duke@0 305 RDX, RDX_H,
duke@0 306 RBP, RBP_H,
duke@0 307 RDI, RDI_H,
duke@0 308 RSI, RSI_H,
duke@0 309 RCX, RCX_H,
duke@0 310 RBX, RBX_H,
duke@0 311 R8, R8_H,
duke@0 312 R9, R9_H,
duke@0 313 R10, R10_H,
duke@0 314 R11, R11_H,
duke@0 315 R12, R12_H,
duke@0 316 R13, R13_H,
duke@0 317 R14, R14_H);
duke@0 318
duke@0 319 // Class for all pointer registers except RAX and RSP
duke@0 320 reg_class ptr_no_rax_reg(RDX, RDX_H,
duke@0 321 RBP, RBP_H,
duke@0 322 RDI, RDI_H,
duke@0 323 RSI, RSI_H,
duke@0 324 RCX, RCX_H,
duke@0 325 RBX, RBX_H,
duke@0 326 R8, R8_H,
duke@0 327 R9, R9_H,
duke@0 328 R10, R10_H,
duke@0 329 R11, R11_H,
duke@0 330 R12, R12_H,
duke@0 331 R13, R13_H,
duke@0 332 R14, R14_H);
duke@0 333
duke@0 334 reg_class ptr_no_rbp_reg(RDX, RDX_H,
duke@0 335 RAX, RAX_H,
duke@0 336 RDI, RDI_H,
duke@0 337 RSI, RSI_H,
duke@0 338 RCX, RCX_H,
duke@0 339 RBX, RBX_H,
duke@0 340 R8, R8_H,
duke@0 341 R9, R9_H,
duke@0 342 R10, R10_H,
duke@0 343 R11, R11_H,
duke@0 344 R12, R12_H,
duke@0 345 R13, R13_H,
duke@0 346 R14, R14_H);
duke@0 347
duke@0 348 // Class for all pointer registers except RAX, RBX and RSP
duke@0 349 reg_class ptr_no_rax_rbx_reg(RDX, RDX_H,
duke@0 350 RBP, RBP_H,
duke@0 351 RDI, RDI_H,
duke@0 352 RSI, RSI_H,
duke@0 353 RCX, RCX_H,
duke@0 354 R8, R8_H,
duke@0 355 R9, R9_H,
duke@0 356 R10, R10_H,
duke@0 357 R11, R11_H,
duke@0 358 R12, R12_H,
duke@0 359 R13, R13_H,
duke@0 360 R14, R14_H);
duke@0 361
duke@0 362 // Singleton class for RAX pointer register
duke@0 363 reg_class ptr_rax_reg(RAX, RAX_H);
duke@0 364
duke@0 365 // Singleton class for RBX pointer register
duke@0 366 reg_class ptr_rbx_reg(RBX, RBX_H);
duke@0 367
duke@0 368 // Singleton class for RSI pointer register
duke@0 369 reg_class ptr_rsi_reg(RSI, RSI_H);
duke@0 370
duke@0 371 // Singleton class for RDI pointer register
duke@0 372 reg_class ptr_rdi_reg(RDI, RDI_H);
duke@0 373
duke@0 374 // Singleton class for RBP pointer register
duke@0 375 reg_class ptr_rbp_reg(RBP, RBP_H);
duke@0 376
duke@0 377 // Singleton class for stack pointer
duke@0 378 reg_class ptr_rsp_reg(RSP, RSP_H);
duke@0 379
duke@0 380 // Singleton class for TLS pointer
duke@0 381 reg_class ptr_r15_reg(R15, R15_H);
duke@0 382
duke@0 383 // Class for all long registers (except RSP)
duke@0 384 reg_class long_reg(RAX, RAX_H,
duke@0 385 RDX, RDX_H,
duke@0 386 RBP, RBP_H,
duke@0 387 RDI, RDI_H,
duke@0 388 RSI, RSI_H,
duke@0 389 RCX, RCX_H,
duke@0 390 RBX, RBX_H,
duke@0 391 R8, R8_H,
duke@0 392 R9, R9_H,
duke@0 393 R10, R10_H,
duke@0 394 R11, R11_H,
duke@0 395 R12, R12_H,
duke@0 396 R13, R13_H,
duke@0 397 R14, R14_H);
duke@0 398
duke@0 399 // Class for all long registers except RAX, RDX (and RSP)
duke@0 400 reg_class long_no_rax_rdx_reg(RBP, RBP_H,
duke@0 401 RDI, RDI_H,
duke@0 402 RSI, RSI_H,
duke@0 403 RCX, RCX_H,
duke@0 404 RBX, RBX_H,
duke@0 405 R8, R8_H,
duke@0 406 R9, R9_H,
duke@0 407 R10, R10_H,
duke@0 408 R11, R11_H,
duke@0 409 R12, R12_H,
duke@0 410 R13, R13_H,
duke@0 411 R14, R14_H);
duke@0 412
duke@0 413 // Class for all long registers except RCX (and RSP)
duke@0 414 reg_class long_no_rcx_reg(RBP, RBP_H,
duke@0 415 RDI, RDI_H,
duke@0 416 RSI, RSI_H,
duke@0 417 RAX, RAX_H,
duke@0 418 RDX, RDX_H,
duke@0 419 RBX, RBX_H,
duke@0 420 R8, R8_H,
duke@0 421 R9, R9_H,
duke@0 422 R10, R10_H,
duke@0 423 R11, R11_H,
duke@0 424 R12, R12_H,
duke@0 425 R13, R13_H,
duke@0 426 R14, R14_H);
duke@0 427
duke@0 428 // Class for all long registers except RAX (and RSP)
duke@0 429 reg_class long_no_rax_reg(RBP, RBP_H,
duke@0 430 RDX, RDX_H,
duke@0 431 RDI, RDI_H,
duke@0 432 RSI, RSI_H,
duke@0 433 RCX, RCX_H,
duke@0 434 RBX, RBX_H,
duke@0 435 R8, R8_H,
duke@0 436 R9, R9_H,
duke@0 437 R10, R10_H,
duke@0 438 R11, R11_H,
duke@0 439 R12, R12_H,
duke@0 440 R13, R13_H,
duke@0 441 R14, R14_H);
duke@0 442
duke@0 443 // Singleton class for RAX long register
duke@0 444 reg_class long_rax_reg(RAX, RAX_H);
duke@0 445
duke@0 446 // Singleton class for RCX long register
duke@0 447 reg_class long_rcx_reg(RCX, RCX_H);
duke@0 448
duke@0 449 // Singleton class for RDX long register
duke@0 450 reg_class long_rdx_reg(RDX, RDX_H);
duke@0 451
duke@0 452 // Class for all int registers (except RSP)
duke@0 453 reg_class int_reg(RAX,
duke@0 454 RDX,
duke@0 455 RBP,
duke@0 456 RDI,
duke@0 457 RSI,
duke@0 458 RCX,
duke@0 459 RBX,
duke@0 460 R8,
duke@0 461 R9,
duke@0 462 R10,
duke@0 463 R11,
duke@0 464 R12,
duke@0 465 R13,
duke@0 466 R14);
duke@0 467
duke@0 468 // Class for all int registers except RCX (and RSP)
duke@0 469 reg_class int_no_rcx_reg(RAX,
duke@0 470 RDX,
duke@0 471 RBP,
duke@0 472 RDI,
duke@0 473 RSI,
duke@0 474 RBX,
duke@0 475 R8,
duke@0 476 R9,
duke@0 477 R10,
duke@0 478 R11,
duke@0 479 R12,
duke@0 480 R13,
duke@0 481 R14);
duke@0 482
duke@0 483 // Class for all int registers except RAX, RDX (and RSP)
duke@0 484 reg_class int_no_rax_rdx_reg(RBP,
duke@0 485 RDI
duke@0 486 RSI,
duke@0 487 RCX,
duke@0 488 RBX,
duke@0 489 R8,
duke@0 490 R9,
duke@0 491 R10,
duke@0 492 R11,
duke@0 493 R12,
duke@0 494 R13,
duke@0 495 R14);
duke@0 496
duke@0 497 // Singleton class for RAX int register
duke@0 498 reg_class int_rax_reg(RAX);
duke@0 499
duke@0 500 // Singleton class for RBX int register
duke@0 501 reg_class int_rbx_reg(RBX);
duke@0 502
duke@0 503 // Singleton class for RCX int register
duke@0 504 reg_class int_rcx_reg(RCX);
duke@0 505
duke@0 506 // Singleton class for RCX int register
duke@0 507 reg_class int_rdx_reg(RDX);
duke@0 508
duke@0 509 // Singleton class for RCX int register
duke@0 510 reg_class int_rdi_reg(RDI);
duke@0 511
duke@0 512 // Singleton class for instruction pointer
duke@0 513 // reg_class ip_reg(RIP);
duke@0 514
duke@0 515 // Singleton class for condition codes
duke@0 516 reg_class int_flags(RFLAGS);
duke@0 517
duke@0 518 // Class for all float registers
duke@0 519 reg_class float_reg(XMM0,
duke@0 520 XMM1,
duke@0 521 XMM2,
duke@0 522 XMM3,
duke@0 523 XMM4,
duke@0 524 XMM5,
duke@0 525 XMM6,
duke@0 526 XMM7,
duke@0 527 XMM8,
duke@0 528 XMM9,
duke@0 529 XMM10,
duke@0 530 XMM11,
duke@0 531 XMM12,
duke@0 532 XMM13,
duke@0 533 XMM14,
duke@0 534 XMM15);
duke@0 535
duke@0 536 // Class for all double registers
duke@0 537 reg_class double_reg(XMM0, XMM0_H,
duke@0 538 XMM1, XMM1_H,
duke@0 539 XMM2, XMM2_H,
duke@0 540 XMM3, XMM3_H,
duke@0 541 XMM4, XMM4_H,
duke@0 542 XMM5, XMM5_H,
duke@0 543 XMM6, XMM6_H,
duke@0 544 XMM7, XMM7_H,
duke@0 545 XMM8, XMM8_H,
duke@0 546 XMM9, XMM9_H,
duke@0 547 XMM10, XMM10_H,
duke@0 548 XMM11, XMM11_H,
duke@0 549 XMM12, XMM12_H,
duke@0 550 XMM13, XMM13_H,
duke@0 551 XMM14, XMM14_H,
duke@0 552 XMM15, XMM15_H);
duke@0 553 %}
duke@0 554
duke@0 555
duke@0 556 //----------SOURCE BLOCK-------------------------------------------------------
duke@0 557 // This is a block of C++ code which provides values, functions, and
duke@0 558 // definitions necessary in the rest of the architecture description
duke@0 559 source %{
duke@0 560 #define RELOC_IMM64 Assembler::imm64_operand
duke@0 561 #define RELOC_DISP32 Assembler::disp32_operand
duke@0 562
duke@0 563 #define __ _masm.
duke@0 564
duke@0 565 // !!!!! Special hack to get all types of calls to specify the byte offset
duke@0 566 // from the start of the call to the point where the return address
duke@0 567 // will point.
duke@0 568 int MachCallStaticJavaNode::ret_addr_offset()
duke@0 569 {
duke@0 570 return 5; // 5 bytes from start of call to where return address points
duke@0 571 }
duke@0 572
duke@0 573 int MachCallDynamicJavaNode::ret_addr_offset()
duke@0 574 {
duke@0 575 return 15; // 15 bytes from start of call to where return address points
duke@0 576 }
duke@0 577
duke@0 578 // In os_cpu .ad file
duke@0 579 // int MachCallRuntimeNode::ret_addr_offset()
duke@0 580
duke@0 581 // Indicate if the safepoint node needs the polling page as an input.
duke@0 582 // Since amd64 does not have absolute addressing but RIP-relative
duke@0 583 // addressing and the polling page is within 2G, it doesn't.
duke@0 584 bool SafePointNode::needs_polling_address_input()
duke@0 585 {
duke@0 586 return false;
duke@0 587 }
duke@0 588
duke@0 589 //
duke@0 590 // Compute padding required for nodes which need alignment
duke@0 591 //
duke@0 592
duke@0 593 // The address of the call instruction needs to be 4-byte aligned to
duke@0 594 // ensure that it does not span a cache line so that it can be patched.
duke@0 595 int CallStaticJavaDirectNode::compute_padding(int current_offset) const
duke@0 596 {
duke@0 597 current_offset += 1; // skip call opcode byte
duke@0 598 return round_to(current_offset, alignment_required()) - current_offset;
duke@0 599 }
duke@0 600
duke@0 601 // The address of the call instruction needs to be 4-byte aligned to
duke@0 602 // ensure that it does not span a cache line so that it can be patched.
duke@0 603 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
duke@0 604 {
duke@0 605 current_offset += 11; // skip movq instruction + call opcode byte
duke@0 606 return round_to(current_offset, alignment_required()) - current_offset;
duke@0 607 }
duke@0 608
duke@0 609 #ifndef PRODUCT
duke@0 610 void MachBreakpointNode::format(PhaseRegAlloc*, outputStream* st) const
duke@0 611 {
duke@0 612 st->print("INT3");
duke@0 613 }
duke@0 614 #endif
duke@0 615
duke@0 616 // EMIT_RM()
duke@0 617 void emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3)
duke@0 618 {
duke@0 619 unsigned char c = (unsigned char) ((f1 << 6) | (f2 << 3) | f3);
duke@0 620 *(cbuf.code_end()) = c;
duke@0 621 cbuf.set_code_end(cbuf.code_end() + 1);
duke@0 622 }
duke@0 623
duke@0 624 // EMIT_CC()
duke@0 625 void emit_cc(CodeBuffer &cbuf, int f1, int f2)
duke@0 626 {
duke@0 627 unsigned char c = (unsigned char) (f1 | f2);
duke@0 628 *(cbuf.code_end()) = c;
duke@0 629 cbuf.set_code_end(cbuf.code_end() + 1);
duke@0 630 }
duke@0 631
duke@0 632 // EMIT_OPCODE()
duke@0 633 void emit_opcode(CodeBuffer &cbuf, int code)
duke@0 634 {
duke@0 635 *(cbuf.code_end()) = (unsigned char) code;
duke@0 636 cbuf.set_code_end(cbuf.code_end() + 1);
duke@0 637 }
duke@0 638
duke@0 639 // EMIT_OPCODE() w/ relocation information
duke@0 640 void emit_opcode(CodeBuffer &cbuf,
duke@0 641 int code, relocInfo::relocType reloc, int offset, int format)
duke@0 642 {
duke@0 643 cbuf.relocate(cbuf.inst_mark() + offset, reloc, format);
duke@0 644 emit_opcode(cbuf, code);
duke@0 645 }
duke@0 646
duke@0 647 // EMIT_D8()
duke@0 648 void emit_d8(CodeBuffer &cbuf, int d8)
duke@0 649 {
duke@0 650 *(cbuf.code_end()) = (unsigned char) d8;
duke@0 651 cbuf.set_code_end(cbuf.code_end() + 1);
duke@0 652 }
duke@0 653
duke@0 654 // EMIT_D16()
duke@0 655 void emit_d16(CodeBuffer &cbuf, int d16)
duke@0 656 {
duke@0 657 *((short *)(cbuf.code_end())) = d16;
duke@0 658 cbuf.set_code_end(cbuf.code_end() + 2);
duke@0 659 }
duke@0 660
duke@0 661 // EMIT_D32()
duke@0 662 void emit_d32(CodeBuffer &cbuf, int d32)
duke@0 663 {
duke@0 664 *((int *)(cbuf.code_end())) = d32;
duke@0 665 cbuf.set_code_end(cbuf.code_end() + 4);
duke@0 666 }
duke@0 667
duke@0 668 // EMIT_D64()
duke@0 669 void emit_d64(CodeBuffer &cbuf, int64_t d64)
duke@0 670 {
duke@0 671 *((int64_t*) (cbuf.code_end())) = d64;
duke@0 672 cbuf.set_code_end(cbuf.code_end() + 8);
duke@0 673 }
duke@0 674
duke@0 675 // emit 32 bit value and construct relocation entry from relocInfo::relocType
duke@0 676 void emit_d32_reloc(CodeBuffer& cbuf,
duke@0 677 int d32,
duke@0 678 relocInfo::relocType reloc,
duke@0 679 int format)
duke@0 680 {
duke@0 681 assert(reloc != relocInfo::external_word_type, "use 2-arg emit_d32_reloc");
duke@0 682 cbuf.relocate(cbuf.inst_mark(), reloc, format);
duke@0 683
duke@0 684 *((int*) (cbuf.code_end())) = d32;
duke@0 685 cbuf.set_code_end(cbuf.code_end() + 4);
duke@0 686 }
duke@0 687
duke@0 688 // emit 32 bit value and construct relocation entry from RelocationHolder
duke@0 689 void emit_d32_reloc(CodeBuffer& cbuf,
duke@0 690 int d32,
duke@0 691 RelocationHolder const& rspec,
duke@0 692 int format)
duke@0 693 {
duke@0 694 #ifdef ASSERT
duke@0 695 if (rspec.reloc()->type() == relocInfo::oop_type &&
duke@0 696 d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) {
duke@0 697 assert(oop((intptr_t)d32)->is_oop() && oop((intptr_t)d32)->is_perm(), "cannot embed non-perm oops in code");
duke@0 698 }
duke@0 699 #endif
duke@0 700 cbuf.relocate(cbuf.inst_mark(), rspec, format);
duke@0 701
duke@0 702 *((int* )(cbuf.code_end())) = d32;
duke@0 703 cbuf.set_code_end(cbuf.code_end() + 4);
duke@0 704 }
duke@0 705
duke@0 706 void emit_d32_reloc(CodeBuffer& cbuf, address addr) {
duke@0 707 address next_ip = cbuf.code_end() + 4;
duke@0 708 emit_d32_reloc(cbuf, (int) (addr - next_ip),
duke@0 709 external_word_Relocation::spec(addr),
duke@0 710 RELOC_DISP32);
duke@0 711 }
duke@0 712
duke@0 713
duke@0 714 // emit 64 bit value and construct relocation entry from relocInfo::relocType
duke@0 715 void emit_d64_reloc(CodeBuffer& cbuf,
duke@0 716 int64_t d64,
duke@0 717 relocInfo::relocType reloc,
duke@0 718 int format)
duke@0 719 {
duke@0 720 cbuf.relocate(cbuf.inst_mark(), reloc, format);
duke@0 721
duke@0 722 *((int64_t*) (cbuf.code_end())) = d64;
duke@0 723 cbuf.set_code_end(cbuf.code_end() + 8);
duke@0 724 }
duke@0 725
duke@0 726 // emit 64 bit value and construct relocation entry from RelocationHolder
duke@0 727 void emit_d64_reloc(CodeBuffer& cbuf,
duke@0 728 int64_t d64,
duke@0 729 RelocationHolder const& rspec,
duke@0 730 int format)
duke@0 731 {
duke@0 732 #ifdef ASSERT
duke@0 733 if (rspec.reloc()->type() == relocInfo::oop_type &&
duke@0 734 d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
duke@0 735 assert(oop(d64)->is_oop() && oop(d64)->is_perm(),
duke@0 736 "cannot embed non-perm oops in code");
duke@0 737 }
duke@0 738 #endif
duke@0 739 cbuf.relocate(cbuf.inst_mark(), rspec, format);
duke@0 740
duke@0 741 *((int64_t*) (cbuf.code_end())) = d64;
duke@0 742 cbuf.set_code_end(cbuf.code_end() + 8);
duke@0 743 }
duke@0 744
duke@0 745 // Access stack slot for load or store
duke@0 746 void store_to_stackslot(CodeBuffer &cbuf, int opcode, int rm_field, int disp)
duke@0 747 {
duke@0 748 emit_opcode(cbuf, opcode); // (e.g., FILD [RSP+src])
duke@0 749 if (-0x80 <= disp && disp < 0x80) {
duke@0 750 emit_rm(cbuf, 0x01, rm_field, RSP_enc); // R/M byte
duke@0 751 emit_rm(cbuf, 0x00, RSP_enc, RSP_enc); // SIB byte
duke@0 752 emit_d8(cbuf, disp); // Displacement // R/M byte
duke@0 753 } else {
duke@0 754 emit_rm(cbuf, 0x02, rm_field, RSP_enc); // R/M byte
duke@0 755 emit_rm(cbuf, 0x00, RSP_enc, RSP_enc); // SIB byte
duke@0 756 emit_d32(cbuf, disp); // Displacement // R/M byte
duke@0 757 }
duke@0 758 }
duke@0 759
duke@0 760 // rRegI ereg, memory mem) %{ // emit_reg_mem
duke@0 761 void encode_RegMem(CodeBuffer &cbuf,
duke@0 762 int reg,
duke@0 763 int base, int index, int scale, int disp, bool disp_is_oop)
duke@0 764 {
duke@0 765 assert(!disp_is_oop, "cannot have disp");
duke@0 766 int regenc = reg & 7;
duke@0 767 int baseenc = base & 7;
duke@0 768 int indexenc = index & 7;
duke@0 769
duke@0 770 // There is no index & no scale, use form without SIB byte
duke@0 771 if (index == 0x4 && scale == 0 && base != RSP_enc && base != R12_enc) {
duke@0 772 // If no displacement, mode is 0x0; unless base is [RBP] or [R13]
duke@0 773 if (disp == 0 && base != RBP_enc && base != R13_enc) {
duke@0 774 emit_rm(cbuf, 0x0, regenc, baseenc); // *
duke@0 775 } else if (-0x80 <= disp && disp < 0x80 && !disp_is_oop) {
duke@0 776 // If 8-bit displacement, mode 0x1
duke@0 777 emit_rm(cbuf, 0x1, regenc, baseenc); // *
duke@0 778 emit_d8(cbuf, disp);
duke@0 779 } else {
duke@0 780 // If 32-bit displacement
duke@0 781 if (base == -1) { // Special flag for absolute address
duke@0 782 emit_rm(cbuf, 0x0, regenc, 0x5); // *
duke@0 783 if (disp_is_oop) {
duke@0 784 emit_d32_reloc(cbuf, disp, relocInfo::oop_type, RELOC_DISP32);
duke@0 785 } else {
duke@0 786 emit_d32(cbuf, disp);
duke@0 787 }
duke@0 788 } else {
duke@0 789 // Normal base + offset
duke@0 790 emit_rm(cbuf, 0x2, regenc, baseenc); // *
duke@0 791 if (disp_is_oop) {
duke@0 792 emit_d32_reloc(cbuf, disp, relocInfo::oop_type, RELOC_DISP32);
duke@0 793 } else {
duke@0 794 emit_d32(cbuf, disp);
duke@0 795 }
duke@0 796 }
duke@0 797 }
duke@0 798 } else {
duke@0 799 // Else, encode with the SIB byte
duke@0 800 // If no displacement, mode is 0x0; unless base is [RBP] or [R13]
duke@0 801 if (disp == 0 && base != RBP_enc && base != R13_enc) {
duke@0 802 // If no displacement
duke@0 803 emit_rm(cbuf, 0x0, regenc, 0x4); // *
duke@0 804 emit_rm(cbuf, scale, indexenc, baseenc);
duke@0 805 } else {
duke@0 806 if (-0x80 <= disp && disp < 0x80 && !disp_is_oop) {
duke@0 807 // If 8-bit displacement, mode 0x1
duke@0 808 emit_rm(cbuf, 0x1, regenc, 0x4); // *
duke@0 809 emit_rm(cbuf, scale, indexenc, baseenc);
duke@0 810 emit_d8(cbuf, disp);
duke@0 811 } else {
duke@0 812 // If 32-bit displacement
duke@0 813 if (base == 0x04 ) {
duke@0 814 emit_rm(cbuf, 0x2, regenc, 0x4);
duke@0 815 emit_rm(cbuf, scale, indexenc, 0x04); // XXX is this valid???
duke@0 816 } else {
duke@0 817 emit_rm(cbuf, 0x2, regenc, 0x4);
duke@0 818 emit_rm(cbuf, scale, indexenc, baseenc); // *
duke@0 819 }
duke@0 820 if (disp_is_oop) {
duke@0 821 emit_d32_reloc(cbuf, disp, relocInfo::oop_type, RELOC_DISP32);
duke@0 822 } else {
duke@0 823 emit_d32(cbuf, disp);
duke@0 824 }
duke@0 825 }
duke@0 826 }
duke@0 827 }
duke@0 828 }
duke@0 829
duke@0 830 void encode_copy(CodeBuffer &cbuf, int dstenc, int srcenc)
duke@0 831 {
duke@0 832 if (dstenc != srcenc) {
duke@0 833 if (dstenc < 8) {
duke@0 834 if (srcenc >= 8) {
duke@0 835 emit_opcode(cbuf, Assembler::REX_B);
duke@0 836 srcenc -= 8;
duke@0 837 }
duke@0 838 } else {
duke@0 839 if (srcenc < 8) {
duke@0 840 emit_opcode(cbuf, Assembler::REX_R);
duke@0 841 } else {
duke@0 842 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 843 srcenc -= 8;
duke@0 844 }
duke@0 845 dstenc -= 8;
duke@0 846 }
duke@0 847
duke@0 848 emit_opcode(cbuf, 0x8B);
duke@0 849 emit_rm(cbuf, 0x3, dstenc, srcenc);
duke@0 850 }
duke@0 851 }
duke@0 852
duke@0 853 void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
duke@0 854 if( dst_encoding == src_encoding ) {
duke@0 855 // reg-reg copy, use an empty encoding
duke@0 856 } else {
duke@0 857 MacroAssembler _masm(&cbuf);
duke@0 858
duke@0 859 __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding));
duke@0 860 }
duke@0 861 }
duke@0 862
duke@0 863
duke@0 864 //=============================================================================
duke@0 865 #ifndef PRODUCT
duke@0 866 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const
duke@0 867 {
duke@0 868 Compile* C = ra_->C;
duke@0 869
duke@0 870 int framesize = C->frame_slots() << LogBytesPerInt;
duke@0 871 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
duke@0 872 // Remove wordSize for return adr already pushed
duke@0 873 // and another for the RBP we are going to save
duke@0 874 framesize -= 2*wordSize;
duke@0 875 bool need_nop = true;
duke@0 876
duke@0 877 // Calls to C2R adapters often do not accept exceptional returns.
duke@0 878 // We require that their callers must bang for them. But be
duke@0 879 // careful, because some VM calls (such as call site linkage) can
duke@0 880 // use several kilobytes of stack. But the stack safety zone should
duke@0 881 // account for that. See bugs 4446381, 4468289, 4497237.
duke@0 882 if (C->need_stack_bang(framesize)) {
duke@0 883 st->print_cr("# stack bang"); st->print("\t");
duke@0 884 need_nop = false;
duke@0 885 }
duke@0 886 st->print_cr("pushq rbp"); st->print("\t");
duke@0 887
duke@0 888 if (VerifyStackAtCalls) {
duke@0 889 // Majik cookie to verify stack depth
duke@0 890 st->print_cr("pushq 0xffffffffbadb100d"
duke@0 891 "\t# Majik cookie for stack depth check");
duke@0 892 st->print("\t");
duke@0 893 framesize -= wordSize; // Remove 2 for cookie
duke@0 894 need_nop = false;
duke@0 895 }
duke@0 896
duke@0 897 if (framesize) {
duke@0 898 st->print("subq rsp, #%d\t# Create frame", framesize);
duke@0 899 if (framesize < 0x80 && need_nop) {
duke@0 900 st->print("\n\tnop\t# nop for patch_verified_entry");
duke@0 901 }
duke@0 902 }
duke@0 903 }
duke@0 904 #endif
duke@0 905
duke@0 906 void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const
duke@0 907 {
duke@0 908 Compile* C = ra_->C;
duke@0 909
duke@0 910 // WARNING: Initial instruction MUST be 5 bytes or longer so that
duke@0 911 // NativeJump::patch_verified_entry will be able to patch out the entry
duke@0 912 // code safely. The fldcw is ok at 6 bytes, the push to verify stack
duke@0 913 // depth is ok at 5 bytes, the frame allocation can be either 3 or
duke@0 914 // 6 bytes. So if we don't do the fldcw or the push then we must
duke@0 915 // use the 6 byte frame allocation even if we have no frame. :-(
duke@0 916 // If method sets FPU control word do it now
duke@0 917
duke@0 918 int framesize = C->frame_slots() << LogBytesPerInt;
duke@0 919 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
duke@0 920 // Remove wordSize for return adr already pushed
duke@0 921 // and another for the RBP we are going to save
duke@0 922 framesize -= 2*wordSize;
duke@0 923 bool need_nop = true;
duke@0 924
duke@0 925 // Calls to C2R adapters often do not accept exceptional returns.
duke@0 926 // We require that their callers must bang for them. But be
duke@0 927 // careful, because some VM calls (such as call site linkage) can
duke@0 928 // use several kilobytes of stack. But the stack safety zone should
duke@0 929 // account for that. See bugs 4446381, 4468289, 4497237.
duke@0 930 if (C->need_stack_bang(framesize)) {
duke@0 931 MacroAssembler masm(&cbuf);
duke@0 932 masm.generate_stack_overflow_check(framesize);
duke@0 933 need_nop = false;
duke@0 934 }
duke@0 935
duke@0 936 // We always push rbp so that on return to interpreter rbp will be
duke@0 937 // restored correctly and we can correct the stack.
duke@0 938 emit_opcode(cbuf, 0x50 | RBP_enc);
duke@0 939
duke@0 940 if (VerifyStackAtCalls) {
duke@0 941 // Majik cookie to verify stack depth
duke@0 942 emit_opcode(cbuf, 0x68); // pushq (sign-extended) 0xbadb100d
duke@0 943 emit_d32(cbuf, 0xbadb100d);
duke@0 944 framesize -= wordSize; // Remove 2 for cookie
duke@0 945 need_nop = false;
duke@0 946 }
duke@0 947
duke@0 948 if (framesize) {
duke@0 949 emit_opcode(cbuf, Assembler::REX_W);
duke@0 950 if (framesize < 0x80) {
duke@0 951 emit_opcode(cbuf, 0x83); // sub SP,#framesize
duke@0 952 emit_rm(cbuf, 0x3, 0x05, RSP_enc);
duke@0 953 emit_d8(cbuf, framesize);
duke@0 954 if (need_nop) {
duke@0 955 emit_opcode(cbuf, 0x90); // nop
duke@0 956 }
duke@0 957 } else {
duke@0 958 emit_opcode(cbuf, 0x81); // sub SP,#framesize
duke@0 959 emit_rm(cbuf, 0x3, 0x05, RSP_enc);
duke@0 960 emit_d32(cbuf, framesize);
duke@0 961 }
duke@0 962 }
duke@0 963
duke@0 964 C->set_frame_complete(cbuf.code_end() - cbuf.code_begin());
duke@0 965
duke@0 966 #ifdef ASSERT
duke@0 967 if (VerifyStackAtCalls) {
duke@0 968 Label L;
duke@0 969 MacroAssembler masm(&cbuf);
duke@0 970 masm.pushq(rax);
duke@0 971 masm.movq(rax, rsp);
duke@0 972 masm.andq(rax, StackAlignmentInBytes-1);
duke@0 973 masm.cmpq(rax, StackAlignmentInBytes-wordSize);
duke@0 974 masm.popq(rax);
duke@0 975 masm.jcc(Assembler::equal, L);
duke@0 976 masm.stop("Stack is not properly aligned!");
duke@0 977 masm.bind(L);
duke@0 978 }
duke@0 979 #endif
duke@0 980 }
duke@0 981
duke@0 982 uint MachPrologNode::size(PhaseRegAlloc* ra_) const
duke@0 983 {
duke@0 984 return MachNode::size(ra_); // too many variables; just compute it
duke@0 985 // the hard way
duke@0 986 }
duke@0 987
duke@0 988 int MachPrologNode::reloc() const
duke@0 989 {
duke@0 990 return 0; // a large enough number
duke@0 991 }
duke@0 992
duke@0 993 //=============================================================================
duke@0 994 #ifndef PRODUCT
duke@0 995 void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
duke@0 996 {
duke@0 997 Compile* C = ra_->C;
duke@0 998 int framesize = C->frame_slots() << LogBytesPerInt;
duke@0 999 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
duke@0 1000 // Remove word for return adr already pushed
duke@0 1001 // and RBP
duke@0 1002 framesize -= 2*wordSize;
duke@0 1003
duke@0 1004 if (framesize) {
duke@0 1005 st->print_cr("addq\trsp, %d\t# Destroy frame", framesize);
duke@0 1006 st->print("\t");
duke@0 1007 }
duke@0 1008
duke@0 1009 st->print_cr("popq\trbp");
duke@0 1010 if (do_polling() && C->is_method_compilation()) {
duke@0 1011 st->print_cr("\ttestl\trax, [rip + #offset_to_poll_page]\t"
duke@0 1012 "# Safepoint: poll for GC");
duke@0 1013 st->print("\t");
duke@0 1014 }
duke@0 1015 }
duke@0 1016 #endif
duke@0 1017
duke@0 1018 void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
duke@0 1019 {
duke@0 1020 Compile* C = ra_->C;
duke@0 1021 int framesize = C->frame_slots() << LogBytesPerInt;
duke@0 1022 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
duke@0 1023 // Remove word for return adr already pushed
duke@0 1024 // and RBP
duke@0 1025 framesize -= 2*wordSize;
duke@0 1026
duke@0 1027 // Note that VerifyStackAtCalls' Majik cookie does not change the frame size popped here
duke@0 1028
duke@0 1029 if (framesize) {
duke@0 1030 emit_opcode(cbuf, Assembler::REX_W);
duke@0 1031 if (framesize < 0x80) {
duke@0 1032 emit_opcode(cbuf, 0x83); // addq rsp, #framesize
duke@0 1033 emit_rm(cbuf, 0x3, 0x00, RSP_enc);
duke@0 1034 emit_d8(cbuf, framesize);
duke@0 1035 } else {
duke@0 1036 emit_opcode(cbuf, 0x81); // addq rsp, #framesize
duke@0 1037 emit_rm(cbuf, 0x3, 0x00, RSP_enc);
duke@0 1038 emit_d32(cbuf, framesize);
duke@0 1039 }
duke@0 1040 }
duke@0 1041
duke@0 1042 // popq rbp
duke@0 1043 emit_opcode(cbuf, 0x58 | RBP_enc);
duke@0 1044
duke@0 1045 if (do_polling() && C->is_method_compilation()) {
duke@0 1046 // testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
duke@0 1047 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 1048 cbuf.set_inst_mark();
duke@0 1049 cbuf.relocate(cbuf.inst_mark(), relocInfo::poll_return_type, 0); // XXX
duke@0 1050 emit_opcode(cbuf, 0x85); // testl
duke@0 1051 emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
duke@0 1052 // cbuf.inst_mark() is beginning of instruction
duke@0 1053 emit_d32_reloc(cbuf, os::get_polling_page());
duke@0 1054 // relocInfo::poll_return_type,
duke@0 1055 }
duke@0 1056 }
duke@0 1057
duke@0 1058 uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
duke@0 1059 {
duke@0 1060 Compile* C = ra_->C;
duke@0 1061 int framesize = C->frame_slots() << LogBytesPerInt;
duke@0 1062 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
duke@0 1063 // Remove word for return adr already pushed
duke@0 1064 // and RBP
duke@0 1065 framesize -= 2*wordSize;
duke@0 1066
duke@0 1067 uint size = 0;
duke@0 1068
duke@0 1069 if (do_polling() && C->is_method_compilation()) {
duke@0 1070 size += 6;
duke@0 1071 }
duke@0 1072
duke@0 1073 // count popq rbp
duke@0 1074 size++;
duke@0 1075
duke@0 1076 if (framesize) {
duke@0 1077 if (framesize < 0x80) {
duke@0 1078 size += 4;
duke@0 1079 } else if (framesize) {
duke@0 1080 size += 7;
duke@0 1081 }
duke@0 1082 }
duke@0 1083
duke@0 1084 return size;
duke@0 1085 }
duke@0 1086
duke@0 1087 int MachEpilogNode::reloc() const
duke@0 1088 {
duke@0 1089 return 2; // a large enough number
duke@0 1090 }
duke@0 1091
duke@0 1092 const Pipeline* MachEpilogNode::pipeline() const
duke@0 1093 {
duke@0 1094 return MachNode::pipeline_class();
duke@0 1095 }
duke@0 1096
duke@0 1097 int MachEpilogNode::safepoint_offset() const
duke@0 1098 {
duke@0 1099 return 0;
duke@0 1100 }
duke@0 1101
duke@0 1102 //=============================================================================
duke@0 1103
duke@0 1104 enum RC {
duke@0 1105 rc_bad,
duke@0 1106 rc_int,
duke@0 1107 rc_float,
duke@0 1108 rc_stack
duke@0 1109 };
duke@0 1110
duke@0 1111 static enum RC rc_class(OptoReg::Name reg)
duke@0 1112 {
duke@0 1113 if( !OptoReg::is_valid(reg) ) return rc_bad;
duke@0 1114
duke@0 1115 if (OptoReg::is_stack(reg)) return rc_stack;
duke@0 1116
duke@0 1117 VMReg r = OptoReg::as_VMReg(reg);
duke@0 1118
duke@0 1119 if (r->is_Register()) return rc_int;
duke@0 1120
duke@0 1121 assert(r->is_XMMRegister(), "must be");
duke@0 1122 return rc_float;
duke@0 1123 }
duke@0 1124
duke@0 1125 uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
duke@0 1126 PhaseRegAlloc* ra_,
duke@0 1127 bool do_size,
duke@0 1128 outputStream* st) const
duke@0 1129 {
duke@0 1130
duke@0 1131 // Get registers to move
duke@0 1132 OptoReg::Name src_second = ra_->get_reg_second(in(1));
duke@0 1133 OptoReg::Name src_first = ra_->get_reg_first(in(1));
duke@0 1134 OptoReg::Name dst_second = ra_->get_reg_second(this);
duke@0 1135 OptoReg::Name dst_first = ra_->get_reg_first(this);
duke@0 1136
duke@0 1137 enum RC src_second_rc = rc_class(src_second);
duke@0 1138 enum RC src_first_rc = rc_class(src_first);
duke@0 1139 enum RC dst_second_rc = rc_class(dst_second);
duke@0 1140 enum RC dst_first_rc = rc_class(dst_first);
duke@0 1141
duke@0 1142 assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first),
duke@0 1143 "must move at least 1 register" );
duke@0 1144
duke@0 1145 if (src_first == dst_first && src_second == dst_second) {
duke@0 1146 // Self copy, no move
duke@0 1147 return 0;
duke@0 1148 } else if (src_first_rc == rc_stack) {
duke@0 1149 // mem ->
duke@0 1150 if (dst_first_rc == rc_stack) {
duke@0 1151 // mem -> mem
duke@0 1152 assert(src_second != dst_first, "overlap");
duke@0 1153 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1154 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1155 // 64-bit
duke@0 1156 int src_offset = ra_->reg2offset(src_first);
duke@0 1157 int dst_offset = ra_->reg2offset(dst_first);
duke@0 1158 if (cbuf) {
duke@0 1159 emit_opcode(*cbuf, 0xFF);
duke@0 1160 encode_RegMem(*cbuf, RSI_enc, RSP_enc, 0x4, 0, src_offset, false);
duke@0 1161
duke@0 1162 emit_opcode(*cbuf, 0x8F);
duke@0 1163 encode_RegMem(*cbuf, RAX_enc, RSP_enc, 0x4, 0, dst_offset, false);
duke@0 1164
duke@0 1165 #ifndef PRODUCT
duke@0 1166 } else if (!do_size) {
duke@0 1167 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
duke@0 1168 "popq [rsp + #%d]",
duke@0 1169 src_offset,
duke@0 1170 dst_offset);
duke@0 1171 #endif
duke@0 1172 }
duke@0 1173 return
duke@0 1174 3 + ((src_offset == 0) ? 0 : (src_offset < 0x80 ? 1 : 4)) +
duke@0 1175 3 + ((dst_offset == 0) ? 0 : (dst_offset < 0x80 ? 1 : 4));
duke@0 1176 } else {
duke@0 1177 // 32-bit
duke@0 1178 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1179 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1180 // No pushl/popl, so:
duke@0 1181 int src_offset = ra_->reg2offset(src_first);
duke@0 1182 int dst_offset = ra_->reg2offset(dst_first);
duke@0 1183 if (cbuf) {
duke@0 1184 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1185 emit_opcode(*cbuf, 0x89);
duke@0 1186 emit_opcode(*cbuf, 0x44);
duke@0 1187 emit_opcode(*cbuf, 0x24);
duke@0 1188 emit_opcode(*cbuf, 0xF8);
duke@0 1189
duke@0 1190 emit_opcode(*cbuf, 0x8B);
duke@0 1191 encode_RegMem(*cbuf,
duke@0 1192 RAX_enc,
duke@0 1193 RSP_enc, 0x4, 0, src_offset,
duke@0 1194 false);
duke@0 1195
duke@0 1196 emit_opcode(*cbuf, 0x89);
duke@0 1197 encode_RegMem(*cbuf,
duke@0 1198 RAX_enc,
duke@0 1199 RSP_enc, 0x4, 0, dst_offset,
duke@0 1200 false);
duke@0 1201
duke@0 1202 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1203 emit_opcode(*cbuf, 0x8B);
duke@0 1204 emit_opcode(*cbuf, 0x44);
duke@0 1205 emit_opcode(*cbuf, 0x24);
duke@0 1206 emit_opcode(*cbuf, 0xF8);
duke@0 1207
duke@0 1208 #ifndef PRODUCT
duke@0 1209 } else if (!do_size) {
duke@0 1210 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
duke@0 1211 "movl rax, [rsp + #%d]\n\t"
duke@0 1212 "movl [rsp + #%d], rax\n\t"
duke@0 1213 "movq rax, [rsp - #8]",
duke@0 1214 src_offset,
duke@0 1215 dst_offset);
duke@0 1216 #endif
duke@0 1217 }
duke@0 1218 return
duke@0 1219 5 + // movq
duke@0 1220 3 + ((src_offset == 0) ? 0 : (src_offset < 0x80 ? 1 : 4)) + // movl
duke@0 1221 3 + ((dst_offset == 0) ? 0 : (dst_offset < 0x80 ? 1 : 4)) + // movl
duke@0 1222 5; // movq
duke@0 1223 }
duke@0 1224 } else if (dst_first_rc == rc_int) {
duke@0 1225 // mem -> gpr
duke@0 1226 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1227 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1228 // 64-bit
duke@0 1229 int offset = ra_->reg2offset(src_first);
duke@0 1230 if (cbuf) {
duke@0 1231 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1232 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1233 } else {
duke@0 1234 emit_opcode(*cbuf, Assembler::REX_WR);
duke@0 1235 }
duke@0 1236 emit_opcode(*cbuf, 0x8B);
duke@0 1237 encode_RegMem(*cbuf,
duke@0 1238 Matcher::_regEncode[dst_first],
duke@0 1239 RSP_enc, 0x4, 0, offset,
duke@0 1240 false);
duke@0 1241 #ifndef PRODUCT
duke@0 1242 } else if (!do_size) {
duke@0 1243 st->print("movq %s, [rsp + #%d]\t# spill",
duke@0 1244 Matcher::regName[dst_first],
duke@0 1245 offset);
duke@0 1246 #endif
duke@0 1247 }
duke@0 1248 return
duke@0 1249 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + 4; // REX
duke@0 1250 } else {
duke@0 1251 // 32-bit
duke@0 1252 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1253 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1254 int offset = ra_->reg2offset(src_first);
duke@0 1255 if (cbuf) {
duke@0 1256 if (Matcher::_regEncode[dst_first] >= 8) {
duke@0 1257 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1258 }
duke@0 1259 emit_opcode(*cbuf, 0x8B);
duke@0 1260 encode_RegMem(*cbuf,
duke@0 1261 Matcher::_regEncode[dst_first],
duke@0 1262 RSP_enc, 0x4, 0, offset,
duke@0 1263 false);
duke@0 1264 #ifndef PRODUCT
duke@0 1265 } else if (!do_size) {
duke@0 1266 st->print("movl %s, [rsp + #%d]\t# spill",
duke@0 1267 Matcher::regName[dst_first],
duke@0 1268 offset);
duke@0 1269 #endif
duke@0 1270 }
duke@0 1271 return
duke@0 1272 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1273 ((Matcher::_regEncode[dst_first] < 8)
duke@0 1274 ? 3
duke@0 1275 : 4); // REX
duke@0 1276 }
duke@0 1277 } else if (dst_first_rc == rc_float) {
duke@0 1278 // mem-> xmm
duke@0 1279 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1280 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1281 // 64-bit
duke@0 1282 int offset = ra_->reg2offset(src_first);
duke@0 1283 if (cbuf) {
duke@0 1284 emit_opcode(*cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
duke@0 1285 if (Matcher::_regEncode[dst_first] >= 8) {
duke@0 1286 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1287 }
duke@0 1288 emit_opcode(*cbuf, 0x0F);
duke@0 1289 emit_opcode(*cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
duke@0 1290 encode_RegMem(*cbuf,
duke@0 1291 Matcher::_regEncode[dst_first],
duke@0 1292 RSP_enc, 0x4, 0, offset,
duke@0 1293 false);
duke@0 1294 #ifndef PRODUCT
duke@0 1295 } else if (!do_size) {
duke@0 1296 st->print("%s %s, [rsp + #%d]\t# spill",
duke@0 1297 UseXmmLoadAndClearUpper ? "movsd " : "movlpd",
duke@0 1298 Matcher::regName[dst_first],
duke@0 1299 offset);
duke@0 1300 #endif
duke@0 1301 }
duke@0 1302 return
duke@0 1303 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1304 ((Matcher::_regEncode[dst_first] < 8)
duke@0 1305 ? 5
duke@0 1306 : 6); // REX
duke@0 1307 } else {
duke@0 1308 // 32-bit
duke@0 1309 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1310 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1311 int offset = ra_->reg2offset(src_first);
duke@0 1312 if (cbuf) {
duke@0 1313 emit_opcode(*cbuf, 0xF3);
duke@0 1314 if (Matcher::_regEncode[dst_first] >= 8) {
duke@0 1315 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1316 }
duke@0 1317 emit_opcode(*cbuf, 0x0F);
duke@0 1318 emit_opcode(*cbuf, 0x10);
duke@0 1319 encode_RegMem(*cbuf,
duke@0 1320 Matcher::_regEncode[dst_first],
duke@0 1321 RSP_enc, 0x4, 0, offset,
duke@0 1322 false);
duke@0 1323 #ifndef PRODUCT
duke@0 1324 } else if (!do_size) {
duke@0 1325 st->print("movss %s, [rsp + #%d]\t# spill",
duke@0 1326 Matcher::regName[dst_first],
duke@0 1327 offset);
duke@0 1328 #endif
duke@0 1329 }
duke@0 1330 return
duke@0 1331 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1332 ((Matcher::_regEncode[dst_first] < 8)
duke@0 1333 ? 5
duke@0 1334 : 6); // REX
duke@0 1335 }
duke@0 1336 }
duke@0 1337 } else if (src_first_rc == rc_int) {
duke@0 1338 // gpr ->
duke@0 1339 if (dst_first_rc == rc_stack) {
duke@0 1340 // gpr -> mem
duke@0 1341 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1342 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1343 // 64-bit
duke@0 1344 int offset = ra_->reg2offset(dst_first);
duke@0 1345 if (cbuf) {
duke@0 1346 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1347 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1348 } else {
duke@0 1349 emit_opcode(*cbuf, Assembler::REX_WR);
duke@0 1350 }
duke@0 1351 emit_opcode(*cbuf, 0x89);
duke@0 1352 encode_RegMem(*cbuf,
duke@0 1353 Matcher::_regEncode[src_first],
duke@0 1354 RSP_enc, 0x4, 0, offset,
duke@0 1355 false);
duke@0 1356 #ifndef PRODUCT
duke@0 1357 } else if (!do_size) {
duke@0 1358 st->print("movq [rsp + #%d], %s\t# spill",
duke@0 1359 offset,
duke@0 1360 Matcher::regName[src_first]);
duke@0 1361 #endif
duke@0 1362 }
duke@0 1363 return ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) + 4; // REX
duke@0 1364 } else {
duke@0 1365 // 32-bit
duke@0 1366 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1367 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1368 int offset = ra_->reg2offset(dst_first);
duke@0 1369 if (cbuf) {
duke@0 1370 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1371 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1372 }
duke@0 1373 emit_opcode(*cbuf, 0x89);
duke@0 1374 encode_RegMem(*cbuf,
duke@0 1375 Matcher::_regEncode[src_first],
duke@0 1376 RSP_enc, 0x4, 0, offset,
duke@0 1377 false);
duke@0 1378 #ifndef PRODUCT
duke@0 1379 } else if (!do_size) {
duke@0 1380 st->print("movl [rsp + #%d], %s\t# spill",
duke@0 1381 offset,
duke@0 1382 Matcher::regName[src_first]);
duke@0 1383 #endif
duke@0 1384 }
duke@0 1385 return
duke@0 1386 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1387 ((Matcher::_regEncode[src_first] < 8)
duke@0 1388 ? 3
duke@0 1389 : 4); // REX
duke@0 1390 }
duke@0 1391 } else if (dst_first_rc == rc_int) {
duke@0 1392 // gpr -> gpr
duke@0 1393 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1394 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1395 // 64-bit
duke@0 1396 if (cbuf) {
duke@0 1397 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1398 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1399 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1400 } else {
duke@0 1401 emit_opcode(*cbuf, Assembler::REX_WB);
duke@0 1402 }
duke@0 1403 } else {
duke@0 1404 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1405 emit_opcode(*cbuf, Assembler::REX_WR);
duke@0 1406 } else {
duke@0 1407 emit_opcode(*cbuf, Assembler::REX_WRB);
duke@0 1408 }
duke@0 1409 }
duke@0 1410 emit_opcode(*cbuf, 0x8B);
duke@0 1411 emit_rm(*cbuf, 0x3,
duke@0 1412 Matcher::_regEncode[dst_first] & 7,
duke@0 1413 Matcher::_regEncode[src_first] & 7);
duke@0 1414 #ifndef PRODUCT
duke@0 1415 } else if (!do_size) {
duke@0 1416 st->print("movq %s, %s\t# spill",
duke@0 1417 Matcher::regName[dst_first],
duke@0 1418 Matcher::regName[src_first]);
duke@0 1419 #endif
duke@0 1420 }
duke@0 1421 return 3; // REX
duke@0 1422 } else {
duke@0 1423 // 32-bit
duke@0 1424 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1425 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1426 if (cbuf) {
duke@0 1427 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1428 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1429 emit_opcode(*cbuf, Assembler::REX_B);
duke@0 1430 }
duke@0 1431 } else {
duke@0 1432 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1433 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1434 } else {
duke@0 1435 emit_opcode(*cbuf, Assembler::REX_RB);
duke@0 1436 }
duke@0 1437 }
duke@0 1438 emit_opcode(*cbuf, 0x8B);
duke@0 1439 emit_rm(*cbuf, 0x3,
duke@0 1440 Matcher::_regEncode[dst_first] & 7,
duke@0 1441 Matcher::_regEncode[src_first] & 7);
duke@0 1442 #ifndef PRODUCT
duke@0 1443 } else if (!do_size) {
duke@0 1444 st->print("movl %s, %s\t# spill",
duke@0 1445 Matcher::regName[dst_first],
duke@0 1446 Matcher::regName[src_first]);
duke@0 1447 #endif
duke@0 1448 }
duke@0 1449 return
duke@0 1450 (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8)
duke@0 1451 ? 2
duke@0 1452 : 3; // REX
duke@0 1453 }
duke@0 1454 } else if (dst_first_rc == rc_float) {
duke@0 1455 // gpr -> xmm
duke@0 1456 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1457 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1458 // 64-bit
duke@0 1459 if (cbuf) {
duke@0 1460 emit_opcode(*cbuf, 0x66);
duke@0 1461 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1462 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1463 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1464 } else {
duke@0 1465 emit_opcode(*cbuf, Assembler::REX_WB);
duke@0 1466 }
duke@0 1467 } else {
duke@0 1468 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1469 emit_opcode(*cbuf, Assembler::REX_WR);
duke@0 1470 } else {
duke@0 1471 emit_opcode(*cbuf, Assembler::REX_WRB);
duke@0 1472 }
duke@0 1473 }
duke@0 1474 emit_opcode(*cbuf, 0x0F);
duke@0 1475 emit_opcode(*cbuf, 0x6E);
duke@0 1476 emit_rm(*cbuf, 0x3,
duke@0 1477 Matcher::_regEncode[dst_first] & 7,
duke@0 1478 Matcher::_regEncode[src_first] & 7);
duke@0 1479 #ifndef PRODUCT
duke@0 1480 } else if (!do_size) {
duke@0 1481 st->print("movdq %s, %s\t# spill",
duke@0 1482 Matcher::regName[dst_first],
duke@0 1483 Matcher::regName[src_first]);
duke@0 1484 #endif
duke@0 1485 }
duke@0 1486 return 5; // REX
duke@0 1487 } else {
duke@0 1488 // 32-bit
duke@0 1489 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1490 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1491 if (cbuf) {
duke@0 1492 emit_opcode(*cbuf, 0x66);
duke@0 1493 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1494 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1495 emit_opcode(*cbuf, Assembler::REX_B);
duke@0 1496 }
duke@0 1497 } else {
duke@0 1498 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1499 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1500 } else {
duke@0 1501 emit_opcode(*cbuf, Assembler::REX_RB);
duke@0 1502 }
duke@0 1503 }
duke@0 1504 emit_opcode(*cbuf, 0x0F);
duke@0 1505 emit_opcode(*cbuf, 0x6E);
duke@0 1506 emit_rm(*cbuf, 0x3,
duke@0 1507 Matcher::_regEncode[dst_first] & 7,
duke@0 1508 Matcher::_regEncode[src_first] & 7);
duke@0 1509 #ifndef PRODUCT
duke@0 1510 } else if (!do_size) {
duke@0 1511 st->print("movdl %s, %s\t# spill",
duke@0 1512 Matcher::regName[dst_first],
duke@0 1513 Matcher::regName[src_first]);
duke@0 1514 #endif
duke@0 1515 }
duke@0 1516 return
duke@0 1517 (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8)
duke@0 1518 ? 4
duke@0 1519 : 5; // REX
duke@0 1520 }
duke@0 1521 }
duke@0 1522 } else if (src_first_rc == rc_float) {
duke@0 1523 // xmm ->
duke@0 1524 if (dst_first_rc == rc_stack) {
duke@0 1525 // xmm -> mem
duke@0 1526 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1527 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1528 // 64-bit
duke@0 1529 int offset = ra_->reg2offset(dst_first);
duke@0 1530 if (cbuf) {
duke@0 1531 emit_opcode(*cbuf, 0xF2);
duke@0 1532 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1533 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1534 }
duke@0 1535 emit_opcode(*cbuf, 0x0F);
duke@0 1536 emit_opcode(*cbuf, 0x11);
duke@0 1537 encode_RegMem(*cbuf,
duke@0 1538 Matcher::_regEncode[src_first],
duke@0 1539 RSP_enc, 0x4, 0, offset,
duke@0 1540 false);
duke@0 1541 #ifndef PRODUCT
duke@0 1542 } else if (!do_size) {
duke@0 1543 st->print("movsd [rsp + #%d], %s\t# spill",
duke@0 1544 offset,
duke@0 1545 Matcher::regName[src_first]);
duke@0 1546 #endif
duke@0 1547 }
duke@0 1548 return
duke@0 1549 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1550 ((Matcher::_regEncode[src_first] < 8)
duke@0 1551 ? 5
duke@0 1552 : 6); // REX
duke@0 1553 } else {
duke@0 1554 // 32-bit
duke@0 1555 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1556 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1557 int offset = ra_->reg2offset(dst_first);
duke@0 1558 if (cbuf) {
duke@0 1559 emit_opcode(*cbuf, 0xF3);
duke@0 1560 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1561 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1562 }
duke@0 1563 emit_opcode(*cbuf, 0x0F);
duke@0 1564 emit_opcode(*cbuf, 0x11);
duke@0 1565 encode_RegMem(*cbuf,
duke@0 1566 Matcher::_regEncode[src_first],
duke@0 1567 RSP_enc, 0x4, 0, offset,
duke@0 1568 false);
duke@0 1569 #ifndef PRODUCT
duke@0 1570 } else if (!do_size) {
duke@0 1571 st->print("movss [rsp + #%d], %s\t# spill",
duke@0 1572 offset,
duke@0 1573 Matcher::regName[src_first]);
duke@0 1574 #endif
duke@0 1575 }
duke@0 1576 return
duke@0 1577 ((offset == 0) ? 0 : (offset < 0x80 ? 1 : 4)) +
duke@0 1578 ((Matcher::_regEncode[src_first] < 8)
duke@0 1579 ? 5
duke@0 1580 : 6); // REX
duke@0 1581 }
duke@0 1582 } else if (dst_first_rc == rc_int) {
duke@0 1583 // xmm -> gpr
duke@0 1584 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1585 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1586 // 64-bit
duke@0 1587 if (cbuf) {
duke@0 1588 emit_opcode(*cbuf, 0x66);
duke@0 1589 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1590 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1591 emit_opcode(*cbuf, Assembler::REX_W);
duke@0 1592 } else {
duke@0 1593 emit_opcode(*cbuf, Assembler::REX_WR); // attention!
duke@0 1594 }
duke@0 1595 } else {
duke@0 1596 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1597 emit_opcode(*cbuf, Assembler::REX_WB); // attention!
duke@0 1598 } else {
duke@0 1599 emit_opcode(*cbuf, Assembler::REX_WRB);
duke@0 1600 }
duke@0 1601 }
duke@0 1602 emit_opcode(*cbuf, 0x0F);
duke@0 1603 emit_opcode(*cbuf, 0x7E);
duke@0 1604 emit_rm(*cbuf, 0x3,
duke@0 1605 Matcher::_regEncode[dst_first] & 7,
duke@0 1606 Matcher::_regEncode[src_first] & 7);
duke@0 1607 #ifndef PRODUCT
duke@0 1608 } else if (!do_size) {
duke@0 1609 st->print("movdq %s, %s\t# spill",
duke@0 1610 Matcher::regName[dst_first],
duke@0 1611 Matcher::regName[src_first]);
duke@0 1612 #endif
duke@0 1613 }
duke@0 1614 return 5; // REX
duke@0 1615 } else {
duke@0 1616 // 32-bit
duke@0 1617 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1618 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1619 if (cbuf) {
duke@0 1620 emit_opcode(*cbuf, 0x66);
duke@0 1621 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1622 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1623 emit_opcode(*cbuf, Assembler::REX_R); // attention!
duke@0 1624 }
duke@0 1625 } else {
duke@0 1626 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1627 emit_opcode(*cbuf, Assembler::REX_B); // attention!
duke@0 1628 } else {
duke@0 1629 emit_opcode(*cbuf, Assembler::REX_RB);
duke@0 1630 }
duke@0 1631 }
duke@0 1632 emit_opcode(*cbuf, 0x0F);
duke@0 1633 emit_opcode(*cbuf, 0x7E);
duke@0 1634 emit_rm(*cbuf, 0x3,
duke@0 1635 Matcher::_regEncode[dst_first] & 7,
duke@0 1636 Matcher::_regEncode[src_first] & 7);
duke@0 1637 #ifndef PRODUCT
duke@0 1638 } else if (!do_size) {
duke@0 1639 st->print("movdl %s, %s\t# spill",
duke@0 1640 Matcher::regName[dst_first],
duke@0 1641 Matcher::regName[src_first]);
duke@0 1642 #endif
duke@0 1643 }
duke@0 1644 return
duke@0 1645 (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8)
duke@0 1646 ? 4
duke@0 1647 : 5; // REX
duke@0 1648 }
duke@0 1649 } else if (dst_first_rc == rc_float) {
duke@0 1650 // xmm -> xmm
duke@0 1651 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
duke@0 1652 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
duke@0 1653 // 64-bit
duke@0 1654 if (cbuf) {
duke@0 1655 emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x66 : 0xF2);
duke@0 1656 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1657 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1658 emit_opcode(*cbuf, Assembler::REX_B);
duke@0 1659 }
duke@0 1660 } else {
duke@0 1661 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1662 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1663 } else {
duke@0 1664 emit_opcode(*cbuf, Assembler::REX_RB);
duke@0 1665 }
duke@0 1666 }
duke@0 1667 emit_opcode(*cbuf, 0x0F);
duke@0 1668 emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10);
duke@0 1669 emit_rm(*cbuf, 0x3,
duke@0 1670 Matcher::_regEncode[dst_first] & 7,
duke@0 1671 Matcher::_regEncode[src_first] & 7);
duke@0 1672 #ifndef PRODUCT
duke@0 1673 } else if (!do_size) {
duke@0 1674 st->print("%s %s, %s\t# spill",
duke@0 1675 UseXmmRegToRegMoveAll ? "movapd" : "movsd ",
duke@0 1676 Matcher::regName[dst_first],
duke@0 1677 Matcher::regName[src_first]);
duke@0 1678 #endif
duke@0 1679 }
duke@0 1680 return
duke@0 1681 (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8)
duke@0 1682 ? 4
duke@0 1683 : 5; // REX
duke@0 1684 } else {
duke@0 1685 // 32-bit
duke@0 1686 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
duke@0 1687 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
duke@0 1688 if (cbuf) {
duke@0 1689 if (!UseXmmRegToRegMoveAll)
duke@0 1690 emit_opcode(*cbuf, 0xF3);
duke@0 1691 if (Matcher::_regEncode[dst_first] < 8) {
duke@0 1692 if (Matcher::_regEncode[src_first] >= 8) {
duke@0 1693 emit_opcode(*cbuf, Assembler::REX_B);
duke@0 1694 }
duke@0 1695 } else {
duke@0 1696 if (Matcher::_regEncode[src_first] < 8) {
duke@0 1697 emit_opcode(*cbuf, Assembler::REX_R);
duke@0 1698 } else {
duke@0 1699 emit_opcode(*cbuf, Assembler::REX_RB);
duke@0 1700 }
duke@0 1701 }
duke@0 1702 emit_opcode(*cbuf, 0x0F);
duke@0 1703 emit_opcode(*cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10);
duke@0 1704 emit_rm(*cbuf, 0x3,
duke@0 1705 Matcher::_regEncode[dst_first] & 7,
duke@0 1706 Matcher::_regEncode[src_first] & 7);
duke@0 1707 #ifndef PRODUCT
duke@0 1708 } else if (!do_size) {
duke@0 1709 st->print("%s %s, %s\t# spill",
duke@0 1710 UseXmmRegToRegMoveAll ? "movaps" : "movss ",
duke@0 1711 Matcher::regName[dst_first],
duke@0 1712 Matcher::regName[src_first]);
duke@0 1713 #endif
duke@0 1714 }
duke@0 1715 return
duke@0 1716 (Matcher::_regEncode[src_first] < 8 && Matcher::_regEncode[dst_first] < 8)
duke@0 1717 ? (UseXmmRegToRegMoveAll ? 3 : 4)
duke@0 1718 : (UseXmmRegToRegMoveAll ? 4 : 5); // REX
duke@0 1719 }
duke@0 1720 }
duke@0 1721 }
duke@0 1722
duke@0 1723 assert(0," foo ");
duke@0 1724 Unimplemented();
duke@0 1725
duke@0 1726 return 0;
duke@0 1727 }
duke@0 1728
duke@0 1729 #ifndef PRODUCT
duke@0 1730 void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const
duke@0 1731 {
duke@0 1732 implementation(NULL, ra_, false, st);
duke@0 1733 }
duke@0 1734 #endif
duke@0 1735
duke@0 1736 void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const
duke@0 1737 {
duke@0 1738 implementation(&cbuf, ra_, false, NULL);
duke@0 1739 }
duke@0 1740
duke@0 1741 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const
duke@0 1742 {
duke@0 1743 return implementation(NULL, ra_, true, NULL);
duke@0 1744 }
duke@0 1745
duke@0 1746 //=============================================================================
duke@0 1747 #ifndef PRODUCT
duke@0 1748 void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const
duke@0 1749 {
duke@0 1750 st->print("nop \t# %d bytes pad for loops and calls", _count);
duke@0 1751 }
duke@0 1752 #endif
duke@0 1753
duke@0 1754 void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const
duke@0 1755 {
duke@0 1756 MacroAssembler _masm(&cbuf);
duke@0 1757 __ nop(_count);
duke@0 1758 }
duke@0 1759
duke@0 1760 uint MachNopNode::size(PhaseRegAlloc*) const
duke@0 1761 {
duke@0 1762 return _count;
duke@0 1763 }
duke@0 1764
duke@0 1765
duke@0 1766 //=============================================================================
duke@0 1767 #ifndef PRODUCT
duke@0 1768 void BoxLockNode::format(PhaseRegAlloc* ra_, outputStream* st) const
duke@0 1769 {
duke@0 1770 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
duke@0 1771 int reg = ra_->get_reg_first(this);
duke@0 1772 st->print("leaq %s, [rsp + #%d]\t# box lock",
duke@0 1773 Matcher::regName[reg], offset);
duke@0 1774 }
duke@0 1775 #endif
duke@0 1776
duke@0 1777 void BoxLockNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
duke@0 1778 {
duke@0 1779 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
duke@0 1780 int reg = ra_->get_encode(this);
duke@0 1781 if (offset >= 0x80) {
duke@0 1782 emit_opcode(cbuf, reg < 8 ? Assembler::REX_W : Assembler::REX_WR);
duke@0 1783 emit_opcode(cbuf, 0x8D); // LEA reg,[SP+offset]
duke@0 1784 emit_rm(cbuf, 0x2, reg & 7, 0x04);
duke@0 1785 emit_rm(cbuf, 0x0, 0x04, RSP_enc);
duke@0 1786 emit_d32(cbuf, offset);
duke@0 1787 } else {
duke@0 1788 emit_opcode(cbuf, reg < 8 ? Assembler::REX_W : Assembler::REX_WR);
duke@0 1789 emit_opcode(cbuf, 0x8D); // LEA reg,[SP+offset]
duke@0 1790 emit_rm(cbuf, 0x1, reg & 7, 0x04);
duke@0 1791 emit_rm(cbuf, 0x0, 0x04, RSP_enc);
duke@0 1792 emit_d8(cbuf, offset);
duke@0 1793 }
duke@0 1794 }
duke@0 1795
duke@0 1796 uint BoxLockNode::size(PhaseRegAlloc *ra_) const
duke@0 1797 {
duke@0 1798 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
duke@0 1799 return (offset < 0x80) ? 5 : 8; // REX
duke@0 1800 }
duke@0 1801
duke@0 1802 //=============================================================================
duke@0 1803
duke@0 1804 // emit call stub, compiled java to interpreter
duke@0 1805 void emit_java_to_interp(CodeBuffer& cbuf)
duke@0 1806 {
duke@0 1807 // Stub is fixed up when the corresponding call is converted from
duke@0 1808 // calling compiled code to calling interpreted code.
duke@0 1809 // movq rbx, 0
duke@0 1810 // jmp -5 # to self
duke@0 1811
duke@0 1812 address mark = cbuf.inst_mark(); // get mark within main instrs section
duke@0 1813
duke@0 1814 // Note that the code buffer's inst_mark is always relative to insts.
duke@0 1815 // That's why we must use the macroassembler to generate a stub.
duke@0 1816 MacroAssembler _masm(&cbuf);
duke@0 1817
duke@0 1818 address base =
duke@0 1819 __ start_a_stub(Compile::MAX_stubs_size);
duke@0 1820 if (base == NULL) return; // CodeBuffer::expand failed
duke@0 1821 // static stub relocation stores the instruction address of the call
duke@0 1822 __ relocate(static_stub_Relocation::spec(mark), RELOC_IMM64);
duke@0 1823 // static stub relocation also tags the methodOop in the code-stream.
duke@0 1824 __ movoop(rbx, (jobject) NULL); // method is zapped till fixup time
duke@0 1825 __ jump(RuntimeAddress(__ pc()));
duke@0 1826
duke@0 1827 // Update current stubs pointer and restore code_end.
duke@0 1828 __ end_a_stub();
duke@0 1829 }
duke@0 1830
duke@0 1831 // size of call stub, compiled java to interpretor
duke@0 1832 uint size_java_to_interp()
duke@0 1833 {
duke@0 1834 return 15; // movq (1+1+8); jmp (1+4)
duke@0 1835 }
duke@0 1836
duke@0 1837 // relocation entries for call stub, compiled java to interpretor
duke@0 1838 uint reloc_java_to_interp()
duke@0 1839 {
duke@0 1840 return 4; // 3 in emit_java_to_interp + 1 in Java_Static_Call
duke@0 1841 }
duke@0 1842
duke@0 1843 //=============================================================================
duke@0 1844 #ifndef PRODUCT
duke@0 1845 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
duke@0 1846 {
duke@0 1847 st->print_cr("cmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t"
duke@0 1848 "# Inline cache check", oopDesc::klass_offset_in_bytes());
duke@0 1849 st->print_cr("\tjne SharedRuntime::_ic_miss_stub");
duke@0 1850 st->print_cr("\tnop");
duke@0 1851 if (!OptoBreakpoint) {
duke@0 1852 st->print_cr("\tnop");
duke@0 1853 }
duke@0 1854 }
duke@0 1855 #endif
duke@0 1856
duke@0 1857 void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
duke@0 1858 {
duke@0 1859 MacroAssembler masm(&cbuf);
duke@0 1860 #ifdef ASSERT
duke@0 1861 uint code_size = cbuf.code_size();
duke@0 1862 #endif
duke@0 1863 masm.cmpq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
duke@0 1864
duke@0 1865 masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
duke@0 1866
duke@0 1867 /* WARNING these NOPs are critical so that verified entry point is properly
duke@0 1868 aligned for patching by NativeJump::patch_verified_entry() */
duke@0 1869 int nops_cnt = 1;
duke@0 1870 if (!OptoBreakpoint) {
duke@0 1871 // Leave space for int3
duke@0 1872 nops_cnt += 1;
duke@0 1873 }
duke@0 1874 masm.nop(nops_cnt);
duke@0 1875
duke@0 1876 assert(cbuf.code_size() - code_size == size(ra_),
duke@0 1877 "checking code size of inline cache node");
duke@0 1878 }
duke@0 1879
duke@0 1880 uint MachUEPNode::size(PhaseRegAlloc* ra_) const
duke@0 1881 {
duke@0 1882 return OptoBreakpoint ? 11 : 12;
duke@0 1883 }
duke@0 1884
duke@0 1885
duke@0 1886 //=============================================================================
duke@0 1887 uint size_exception_handler()
duke@0 1888 {
duke@0 1889 // NativeCall instruction size is the same as NativeJump.
duke@0 1890 // Note that this value is also credited (in output.cpp) to
duke@0 1891 // the size of the code section.
duke@0 1892 return NativeJump::instruction_size;
duke@0 1893 }
duke@0 1894
duke@0 1895 // Emit exception handler code.
duke@0 1896 int emit_exception_handler(CodeBuffer& cbuf)
duke@0 1897 {
duke@0 1898
duke@0 1899 // Note that the code buffer's inst_mark is always relative to insts.
duke@0 1900 // That's why we must use the macroassembler to generate a handler.
duke@0 1901 MacroAssembler _masm(&cbuf);
duke@0 1902 address base =
duke@0 1903 __ start_a_stub(size_exception_handler());
duke@0 1904 if (base == NULL) return 0; // CodeBuffer::expand failed
duke@0 1905 int offset = __ offset();
duke@0 1906 __ jump(RuntimeAddress(OptoRuntime::exception_blob()->instructions_begin()));
duke@0 1907 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
duke@0 1908 __ end_a_stub();
duke@0 1909 return offset;
duke@0 1910 }
duke@0 1911
duke@0 1912 uint size_deopt_handler()
duke@0 1913 {
duke@0 1914 // three 5 byte instructions
duke@0 1915 return 15;
duke@0 1916 }
duke@0 1917
duke@0 1918 // Emit deopt handler code.
duke@0 1919 int emit_deopt_handler(CodeBuffer& cbuf)
duke@0 1920 {
duke@0 1921
duke@0 1922 // Note that the code buffer's inst_mark is always relative to insts.
duke@0 1923 // That's why we must use the macroassembler to generate a handler.
duke@0 1924 MacroAssembler _masm(&cbuf);
duke@0 1925 address base =
duke@0 1926 __ start_a_stub(size_deopt_handler());
duke@0 1927 if (base == NULL) return 0; // CodeBuffer::expand failed
duke@0 1928 int offset = __ offset();
duke@0 1929 address the_pc = (address) __ pc();
duke@0 1930 Label next;
duke@0 1931 // push a "the_pc" on the stack without destroying any registers
duke@0 1932 // as they all may be live.
duke@0 1933
duke@0 1934 // push address of "next"
duke@0 1935 __ call(next, relocInfo::none); // reloc none is fine since it is a disp32
duke@0 1936 __ bind(next);
duke@0 1937 // adjust it so it matches "the_pc"
duke@0 1938 __ subq(Address(rsp, 0), __ offset() - offset);
duke@0 1939 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
duke@0 1940 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
duke@0 1941 __ end_a_stub();
duke@0 1942 return offset;
duke@0 1943 }
duke@0 1944
duke@0 1945 static void emit_double_constant(CodeBuffer& cbuf, double x) {
duke@0 1946 int mark = cbuf.insts()->mark_off();
duke@0 1947 MacroAssembler _masm(&cbuf);
duke@0 1948 address double_address = __ double_constant(x);
duke@0 1949 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
duke@0 1950 emit_d32_reloc(cbuf,
duke@0 1951 (int) (double_address - cbuf.code_end() - 4),
duke@0 1952 internal_word_Relocation::spec(double_address),
duke@0 1953 RELOC_DISP32);
duke@0 1954 }
duke@0 1955
duke@0 1956 static void emit_float_constant(CodeBuffer& cbuf, float x) {
duke@0 1957 int mark = cbuf.insts()->mark_off();
duke@0 1958 MacroAssembler _masm(&cbuf);
duke@0 1959 address float_address = __ float_constant(x);
duke@0 1960 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
duke@0 1961 emit_d32_reloc(cbuf,
duke@0 1962 (int) (float_address - cbuf.code_end() - 4),
duke@0 1963 internal_word_Relocation::spec(float_address),
duke@0 1964 RELOC_DISP32);
duke@0 1965 }
duke@0 1966
duke@0 1967
duke@0 1968 int Matcher::regnum_to_fpu_offset(int regnum)
duke@0 1969 {
duke@0 1970 return regnum - 32; // The FP registers are in the second chunk
duke@0 1971 }
duke@0 1972
duke@0 1973 // This is UltraSparc specific, true just means we have fast l2f conversion
duke@0 1974 const bool Matcher::convL2FSupported(void) {
duke@0 1975 return true;
duke@0 1976 }
duke@0 1977
duke@0 1978 // Vector width in bytes
duke@0 1979 const uint Matcher::vector_width_in_bytes(void) {
duke@0 1980 return 8;
duke@0 1981 }
duke@0 1982
duke@0 1983 // Vector ideal reg
duke@0 1984 const uint Matcher::vector_ideal_reg(void) {
duke@0 1985 return Op_RegD;
duke@0 1986 }
duke@0 1987
duke@0 1988 // Is this branch offset short enough that a short branch can be used?
duke@0 1989 //
duke@0 1990 // NOTE: If the platform does not provide any short branch variants, then
duke@0 1991 // this method should return false for offset 0.
duke@0 1992 bool Matcher::is_short_branch_offset(int offset)
duke@0 1993 {
duke@0 1994 return -0x80 <= offset && offset < 0x80;
duke@0 1995 }
duke@0 1996
duke@0 1997 const bool Matcher::isSimpleConstant64(jlong value) {
duke@0 1998 // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?.
duke@0 1999 //return value == (int) value; // Cf. storeImmL and immL32.
duke@0 2000
duke@0 2001 // Probably always true, even if a temp register is required.
duke@0 2002 return true;
duke@0 2003 }
duke@0 2004
duke@0 2005 // The ecx parameter to rep stosq for the ClearArray node is in words.
duke@0 2006 const bool Matcher::init_array_count_is_in_bytes = false;
duke@0 2007
duke@0 2008 // Threshold size for cleararray.
duke@0 2009 const int Matcher::init_array_short_size = 8 * BytesPerLong;
duke@0 2010
duke@0 2011 // Should the Matcher clone shifts on addressing modes, expecting them
duke@0 2012 // to be subsumed into complex addressing expressions or compute them
duke@0 2013 // into registers? True for Intel but false for most RISCs
duke@0 2014 const bool Matcher::clone_shift_expressions = true;
duke@0 2015
duke@0 2016 // Is it better to copy float constants, or load them directly from
duke@0 2017 // memory? Intel can load a float constant from a direct address,
duke@0 2018 // requiring no extra registers. Most RISCs will have to materialize
duke@0 2019 // an address into a register first, so they would do better to copy
duke@0 2020 // the constant from stack.
duke@0 2021 const bool Matcher::rematerialize_float_constants = true; // XXX
duke@0 2022
duke@0 2023 // If CPU can load and store mis-aligned doubles directly then no
duke@0 2024 // fixup is needed. Else we split the double into 2 integer pieces
duke@0 2025 // and move it piece-by-piece. Only happens when passing doubles into
duke@0 2026 // C code as the Java calling convention forces doubles to be aligned.
duke@0 2027 const bool Matcher::misaligned_doubles_ok = true;
duke@0 2028
duke@0 2029 // No-op on amd64
duke@0 2030 void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) {}
duke@0 2031
duke@0 2032 // Advertise here if the CPU requires explicit rounding operations to
duke@0 2033 // implement the UseStrictFP mode.
duke@0 2034 const bool Matcher::strict_fp_requires_explicit_rounding = true;
duke@0 2035
duke@0 2036 // Do floats take an entire double register or just half?
duke@0 2037 const bool Matcher::float_in_double = true;
duke@0 2038 // Do ints take an entire long register or just half?
duke@0 2039 const bool Matcher::int_in_long = true;
duke@0 2040
duke@0 2041 // Return whether or not this register is ever used as an argument.
duke@0 2042 // This function is used on startup to build the trampoline stubs in
duke@0 2043 // generateOptoStub. Registers not mentioned will be killed by the VM
duke@0 2044 // call in the trampoline, and arguments in those registers not be
duke@0 2045 // available to the callee.
duke@0 2046 bool Matcher::can_be_java_arg(int reg)
duke@0 2047 {
duke@0 2048 return
duke@0 2049 reg == RDI_num || reg == RDI_H_num ||
duke@0 2050 reg == RSI_num || reg == RSI_H_num ||
duke@0 2051 reg == RDX_num || reg == RDX_H_num ||
duke@0 2052 reg == RCX_num || reg == RCX_H_num ||
duke@0 2053 reg == R8_num || reg == R8_H_num ||
duke@0 2054 reg == R9_num || reg == R9_H_num ||
duke@0 2055 reg == XMM0_num || reg == XMM0_H_num ||
duke@0 2056 reg == XMM1_num || reg == XMM1_H_num ||
duke@0 2057 reg == XMM2_num || reg == XMM2_H_num ||
duke@0 2058 reg == XMM3_num || reg == XMM3_H_num ||
duke@0 2059 reg == XMM4_num || reg == XMM4_H_num ||
duke@0 2060 reg == XMM5_num || reg == XMM5_H_num ||
duke@0 2061 reg == XMM6_num || reg == XMM6_H_num ||
duke@0 2062 reg == XMM7_num || reg == XMM7_H_num;
duke@0 2063 }
duke@0 2064
duke@0 2065 bool Matcher::is_spillable_arg(int reg)
duke@0 2066 {
duke@0 2067 return can_be_java_arg(reg);
duke@0 2068 }
duke@0 2069
duke@0 2070 // Register for DIVI projection of divmodI
duke@0 2071 RegMask Matcher::divI_proj_mask() {
duke@0 2072 return INT_RAX_REG_mask;
duke@0 2073 }
duke@0 2074
duke@0 2075 // Register for MODI projection of divmodI
duke@0 2076 RegMask Matcher::modI_proj_mask() {
duke@0 2077 return INT_RDX_REG_mask;
duke@0 2078 }
duke@0 2079
duke@0 2080 // Register for DIVL projection of divmodL
duke@0 2081 RegMask Matcher::divL_proj_mask() {
duke@0 2082 return LONG_RAX_REG_mask;
duke@0 2083 }
duke@0 2084
duke@0 2085 // Register for MODL projection of divmodL
duke@0 2086 RegMask Matcher::modL_proj_mask() {
duke@0 2087 return LONG_RDX_REG_mask;
duke@0 2088 }
duke@0 2089
duke@0 2090 %}
duke@0 2091
duke@0 2092 //----------ENCODING BLOCK-----------------------------------------------------
duke@0 2093 // This block specifies the encoding classes used by the compiler to
duke@0 2094 // output byte streams. Encoding classes are parameterized macros
duke@0 2095 // used by Machine Instruction Nodes in order to generate the bit
duke@0 2096 // encoding of the instruction. Operands specify their base encoding
duke@0 2097 // interface with the interface keyword. There are currently
duke@0 2098 // supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, &
duke@0 2099 // COND_INTER. REG_INTER causes an operand to generate a function
duke@0 2100 // which returns its register number when queried. CONST_INTER causes
duke@0 2101 // an operand to generate a function which returns the value of the
duke@0 2102 // constant when queried. MEMORY_INTER causes an operand to generate
duke@0 2103 // four functions which return the Base Register, the Index Register,
duke@0 2104 // the Scale Value, and the Offset Value of the operand when queried.
duke@0 2105 // COND_INTER causes an operand to generate six functions which return
duke@0 2106 // the encoding code (ie - encoding bits for the instruction)
duke@0 2107 // associated with each basic boolean condition for a conditional
duke@0 2108 // instruction.
duke@0 2109 //
duke@0 2110 // Instructions specify two basic values for encoding. Again, a
duke@0 2111 // function is available to check if the constant displacement is an
duke@0 2112 // oop. They use the ins_encode keyword to specify their encoding
duke@0 2113 // classes (which must be a sequence of enc_class names, and their
duke@0 2114 // parameters, specified in the encoding block), and they use the
duke@0 2115 // opcode keyword to specify, in order, their primary, secondary, and
duke@0 2116 // tertiary opcode. Only the opcode sections which a particular
duke@0 2117 // instruction needs for encoding need to be specified.
duke@0 2118 encode %{
duke@0 2119 // Build emit functions for each basic byte or larger field in the
duke@0 2120 // intel encoding scheme (opcode, rm, sib, immediate), and call them
duke@0 2121 // from C++ code in the enc_class source block. Emit functions will
duke@0 2122 // live in the main source block for now. In future, we can
duke@0 2123 // generalize this by adding a syntax that specifies the sizes of
duke@0 2124 // fields in an order, so that the adlc can build the emit functions
duke@0 2125 // automagically
duke@0 2126
duke@0 2127 // Emit primary opcode
duke@0 2128 enc_class OpcP
duke@0 2129 %{
duke@0 2130 emit_opcode(cbuf, $primary);
duke@0 2131 %}
duke@0 2132
duke@0 2133 // Emit secondary opcode
duke@0 2134 enc_class OpcS
duke@0 2135 %{
duke@0 2136 emit_opcode(cbuf, $secondary);
duke@0 2137 %}
duke@0 2138
duke@0 2139 // Emit tertiary opcode
duke@0 2140 enc_class OpcT
duke@0 2141 %{
duke@0 2142 emit_opcode(cbuf, $tertiary);
duke@0 2143 %}
duke@0 2144
duke@0 2145 // Emit opcode directly
duke@0 2146 enc_class Opcode(immI d8)
duke@0 2147 %{
duke@0 2148 emit_opcode(cbuf, $d8$$constant);
duke@0 2149 %}
duke@0 2150
duke@0 2151 // Emit size prefix
duke@0 2152 enc_class SizePrefix
duke@0 2153 %{
duke@0 2154 emit_opcode(cbuf, 0x66);
duke@0 2155 %}
duke@0 2156
duke@0 2157 enc_class reg(rRegI reg)
duke@0 2158 %{
duke@0 2159 emit_rm(cbuf, 0x3, 0, $reg$$reg & 7);
duke@0 2160 %}
duke@0 2161
duke@0 2162 enc_class reg_reg(rRegI dst, rRegI src)
duke@0 2163 %{
duke@0 2164 emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
duke@0 2165 %}
duke@0 2166
duke@0 2167 enc_class opc_reg_reg(immI opcode, rRegI dst, rRegI src)
duke@0 2168 %{
duke@0 2169 emit_opcode(cbuf, $opcode$$constant);
duke@0 2170 emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
duke@0 2171 %}
duke@0 2172
duke@0 2173 enc_class cmpfp_fixup()
duke@0 2174 %{
duke@0 2175 // jnp,s exit
duke@0 2176 emit_opcode(cbuf, 0x7B);
duke@0 2177 emit_d8(cbuf, 0x0A);
duke@0 2178
duke@0 2179 // pushfq
duke@0 2180 emit_opcode(cbuf, 0x9C);
duke@0 2181
duke@0 2182 // andq $0xffffff2b, (%rsp)
duke@0 2183 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2184 emit_opcode(cbuf, 0x81);
duke@0 2185 emit_opcode(cbuf, 0x24);
duke@0 2186 emit_opcode(cbuf, 0x24);
duke@0 2187 emit_d32(cbuf, 0xffffff2b);
duke@0 2188
duke@0 2189 // popfq
duke@0 2190 emit_opcode(cbuf, 0x9D);
duke@0 2191
duke@0 2192 // nop (target for branch to avoid branch to branch)
duke@0 2193 emit_opcode(cbuf, 0x90);
duke@0 2194 %}
duke@0 2195
duke@0 2196 enc_class cmpfp3(rRegI dst)
duke@0 2197 %{
duke@0 2198 int dstenc = $dst$$reg;
duke@0 2199
duke@0 2200 // movl $dst, -1
duke@0 2201 if (dstenc >= 8) {
duke@0 2202 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2203 }
duke@0 2204 emit_opcode(cbuf, 0xB8 | (dstenc & 7));
duke@0 2205 emit_d32(cbuf, -1);
duke@0 2206
duke@0 2207 // jp,s done
duke@0 2208 emit_opcode(cbuf, 0x7A);
duke@0 2209 emit_d8(cbuf, dstenc < 4 ? 0x08 : 0x0A);
duke@0 2210
duke@0 2211 // jb,s done
duke@0 2212 emit_opcode(cbuf, 0x72);
duke@0 2213 emit_d8(cbuf, dstenc < 4 ? 0x06 : 0x08);
duke@0 2214
duke@0 2215 // setne $dst
duke@0 2216 if (dstenc >= 4) {
duke@0 2217 emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_B);
duke@0 2218 }
duke@0 2219 emit_opcode(cbuf, 0x0F);
duke@0 2220 emit_opcode(cbuf, 0x95);
duke@0 2221 emit_opcode(cbuf, 0xC0 | (dstenc & 7));
duke@0 2222
duke@0 2223 // movzbl $dst, $dst
duke@0 2224 if (dstenc >= 4) {
duke@0 2225 emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_RB);
duke@0 2226 }
duke@0 2227 emit_opcode(cbuf, 0x0F);
duke@0 2228 emit_opcode(cbuf, 0xB6);
duke@0 2229 emit_rm(cbuf, 0x3, dstenc & 7, dstenc & 7);
duke@0 2230 %}
duke@0 2231
duke@0 2232 enc_class cdql_enc(no_rax_rdx_RegI div)
duke@0 2233 %{
duke@0 2234 // Full implementation of Java idiv and irem; checks for
duke@0 2235 // special case as described in JVM spec., p.243 & p.271.
duke@0 2236 //
duke@0 2237 // normal case special case
duke@0 2238 //
duke@0 2239 // input : rax: dividend min_int
duke@0 2240 // reg: divisor -1
duke@0 2241 //
duke@0 2242 // output: rax: quotient (= rax idiv reg) min_int
duke@0 2243 // rdx: remainder (= rax irem reg) 0
duke@0 2244 //
duke@0 2245 // Code sequnce:
duke@0 2246 //
duke@0 2247 // 0: 3d 00 00 00 80 cmp $0x80000000,%eax
duke@0 2248 // 5: 75 07/08 jne e <normal>
duke@0 2249 // 7: 33 d2 xor %edx,%edx
duke@0 2250 // [div >= 8 -> offset + 1]
duke@0 2251 // [REX_B]
duke@0 2252 // 9: 83 f9 ff cmp $0xffffffffffffffff,$div
duke@0 2253 // c: 74 03/04 je 11 <done>
duke@0 2254 // 000000000000000e <normal>:
duke@0 2255 // e: 99 cltd
duke@0 2256 // [div >= 8 -> offset + 1]
duke@0 2257 // [REX_B]
duke@0 2258 // f: f7 f9 idiv $div
duke@0 2259 // 0000000000000011 <done>:
duke@0 2260
duke@0 2261 // cmp $0x80000000,%eax
duke@0 2262 emit_opcode(cbuf, 0x3d);
duke@0 2263 emit_d8(cbuf, 0x00);
duke@0 2264 emit_d8(cbuf, 0x00);
duke@0 2265 emit_d8(cbuf, 0x00);
duke@0 2266 emit_d8(cbuf, 0x80);
duke@0 2267
duke@0 2268 // jne e <normal>
duke@0 2269 emit_opcode(cbuf, 0x75);
duke@0 2270 emit_d8(cbuf, $div$$reg < 8 ? 0x07 : 0x08);
duke@0 2271
duke@0 2272 // xor %edx,%edx
duke@0 2273 emit_opcode(cbuf, 0x33);
duke@0 2274 emit_d8(cbuf, 0xD2);
duke@0 2275
duke@0 2276 // cmp $0xffffffffffffffff,%ecx
duke@0 2277 if ($div$$reg >= 8) {
duke@0 2278 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2279 }
duke@0 2280 emit_opcode(cbuf, 0x83);
duke@0 2281 emit_rm(cbuf, 0x3, 0x7, $div$$reg & 7);
duke@0 2282 emit_d8(cbuf, 0xFF);
duke@0 2283
duke@0 2284 // je 11 <done>
duke@0 2285 emit_opcode(cbuf, 0x74);
duke@0 2286 emit_d8(cbuf, $div$$reg < 8 ? 0x03 : 0x04);
duke@0 2287
duke@0 2288 // <normal>
duke@0 2289 // cltd
duke@0 2290 emit_opcode(cbuf, 0x99);
duke@0 2291
duke@0 2292 // idivl (note: must be emitted by the user of this rule)
duke@0 2293 // <done>
duke@0 2294 %}
duke@0 2295
duke@0 2296 enc_class cdqq_enc(no_rax_rdx_RegL div)
duke@0 2297 %{
duke@0 2298 // Full implementation of Java ldiv and lrem; checks for
duke@0 2299 // special case as described in JVM spec., p.243 & p.271.
duke@0 2300 //
duke@0 2301 // normal case special case
duke@0 2302 //
duke@0 2303 // input : rax: dividend min_long
duke@0 2304 // reg: divisor -1
duke@0 2305 //
duke@0 2306 // output: rax: quotient (= rax idiv reg) min_long
duke@0 2307 // rdx: remainder (= rax irem reg) 0
duke@0 2308 //
duke@0 2309 // Code sequnce:
duke@0 2310 //
duke@0 2311 // 0: 48 ba 00 00 00 00 00 mov $0x8000000000000000,%rdx
duke@0 2312 // 7: 00 00 80
duke@0 2313 // a: 48 39 d0 cmp %rdx,%rax
duke@0 2314 // d: 75 08 jne 17 <normal>
duke@0 2315 // f: 33 d2 xor %edx,%edx
duke@0 2316 // 11: 48 83 f9 ff cmp $0xffffffffffffffff,$div
duke@0 2317 // 15: 74 05 je 1c <done>
duke@0 2318 // 0000000000000017 <normal>:
duke@0 2319 // 17: 48 99 cqto
duke@0 2320 // 19: 48 f7 f9 idiv $div
duke@0 2321 // 000000000000001c <done>:
duke@0 2322
duke@0 2323 // mov $0x8000000000000000,%rdx
duke@0 2324 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2325 emit_opcode(cbuf, 0xBA);
duke@0 2326 emit_d8(cbuf, 0x00);
duke@0 2327 emit_d8(cbuf, 0x00);
duke@0 2328 emit_d8(cbuf, 0x00);
duke@0 2329 emit_d8(cbuf, 0x00);
duke@0 2330 emit_d8(cbuf, 0x00);
duke@0 2331 emit_d8(cbuf, 0x00);
duke@0 2332 emit_d8(cbuf, 0x00);
duke@0 2333 emit_d8(cbuf, 0x80);
duke@0 2334
duke@0 2335 // cmp %rdx,%rax
duke@0 2336 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2337 emit_opcode(cbuf, 0x39);
duke@0 2338 emit_d8(cbuf, 0xD0);
duke@0 2339
duke@0 2340 // jne 17 <normal>
duke@0 2341 emit_opcode(cbuf, 0x75);
duke@0 2342 emit_d8(cbuf, 0x08);
duke@0 2343
duke@0 2344 // xor %edx,%edx
duke@0 2345 emit_opcode(cbuf, 0x33);
duke@0 2346 emit_d8(cbuf, 0xD2);
duke@0 2347
duke@0 2348 // cmp $0xffffffffffffffff,$div
duke@0 2349 emit_opcode(cbuf, $div$$reg < 8 ? Assembler::REX_W : Assembler::REX_WB);
duke@0 2350 emit_opcode(cbuf, 0x83);
duke@0 2351 emit_rm(cbuf, 0x3, 0x7, $div$$reg & 7);
duke@0 2352 emit_d8(cbuf, 0xFF);
duke@0 2353
duke@0 2354 // je 1e <done>
duke@0 2355 emit_opcode(cbuf, 0x74);
duke@0 2356 emit_d8(cbuf, 0x05);
duke@0 2357
duke@0 2358 // <normal>
duke@0 2359 // cqto
duke@0 2360 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2361 emit_opcode(cbuf, 0x99);
duke@0 2362
duke@0 2363 // idivq (note: must be emitted by the user of this rule)
duke@0 2364 // <done>
duke@0 2365 %}
duke@0 2366
duke@0 2367 // Opcde enc_class for 8/32 bit immediate instructions with sign-extension
duke@0 2368 enc_class OpcSE(immI imm)
duke@0 2369 %{
duke@0 2370 // Emit primary opcode and set sign-extend bit
duke@0 2371 // Check for 8-bit immediate, and set sign extend bit in opcode
duke@0 2372 if (-0x80 <= $imm$$constant && $imm$$constant < 0x80) {
duke@0 2373 emit_opcode(cbuf, $primary | 0x02);
duke@0 2374 } else {
duke@0 2375 // 32-bit immediate
duke@0 2376 emit_opcode(cbuf, $primary);
duke@0 2377 }
duke@0 2378 %}
duke@0 2379
duke@0 2380 enc_class OpcSErm(rRegI dst, immI imm)
duke@0 2381 %{
duke@0 2382 // OpcSEr/m
duke@0 2383 int dstenc = $dst$$reg;
duke@0 2384 if (dstenc >= 8) {
duke@0 2385 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2386 dstenc -= 8;
duke@0 2387 }
duke@0 2388 // Emit primary opcode and set sign-extend bit
duke@0 2389 // Check for 8-bit immediate, and set sign extend bit in opcode
duke@0 2390 if (-0x80 <= $imm$$constant && $imm$$constant < 0x80) {
duke@0 2391 emit_opcode(cbuf, $primary | 0x02);
duke@0 2392 } else {
duke@0 2393 // 32-bit immediate
duke@0 2394 emit_opcode(cbuf, $primary);
duke@0 2395 }
duke@0 2396 // Emit r/m byte with secondary opcode, after primary opcode.
duke@0 2397 emit_rm(cbuf, 0x3, $secondary, dstenc);
duke@0 2398 %}
duke@0 2399
duke@0 2400 enc_class OpcSErm_wide(rRegL dst, immI imm)
duke@0 2401 %{
duke@0 2402 // OpcSEr/m
duke@0 2403 int dstenc = $dst$$reg;
duke@0 2404 if (dstenc < 8) {
duke@0 2405 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2406 } else {
duke@0 2407 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2408 dstenc -= 8;
duke@0 2409 }
duke@0 2410 // Emit primary opcode and set sign-extend bit
duke@0 2411 // Check for 8-bit immediate, and set sign extend bit in opcode
duke@0 2412 if (-0x80 <= $imm$$constant && $imm$$constant < 0x80) {
duke@0 2413 emit_opcode(cbuf, $primary | 0x02);
duke@0 2414 } else {
duke@0 2415 // 32-bit immediate
duke@0 2416 emit_opcode(cbuf, $primary);
duke@0 2417 }
duke@0 2418 // Emit r/m byte with secondary opcode, after primary opcode.
duke@0 2419 emit_rm(cbuf, 0x3, $secondary, dstenc);
duke@0 2420 %}
duke@0 2421
duke@0 2422 enc_class Con8or32(immI imm)
duke@0 2423 %{
duke@0 2424 // Check for 8-bit immediate, and set sign extend bit in opcode
duke@0 2425 if (-0x80 <= $imm$$constant && $imm$$constant < 0x80) {
duke@0 2426 $$$emit8$imm$$constant;
duke@0 2427 } else {
duke@0 2428 // 32-bit immediate
duke@0 2429 $$$emit32$imm$$constant;
duke@0 2430 }
duke@0 2431 %}
duke@0 2432
duke@0 2433 enc_class Lbl(label labl)
duke@0 2434 %{
duke@0 2435 // JMP, CALL
duke@0 2436 Label* l = $labl$$label;
duke@0 2437 emit_d32(cbuf, l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0);
duke@0 2438 %}
duke@0 2439
duke@0 2440 enc_class LblShort(label labl)
duke@0 2441 %{
duke@0 2442 // JMP, CALL
duke@0 2443 Label* l = $labl$$label;
duke@0 2444 int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
duke@0 2445 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
duke@0 2446 emit_d8(cbuf, disp);
duke@0 2447 %}
duke@0 2448
duke@0 2449 enc_class opc2_reg(rRegI dst)
duke@0 2450 %{
duke@0 2451 // BSWAP
duke@0 2452 emit_cc(cbuf, $secondary, $dst$$reg);
duke@0 2453 %}
duke@0 2454
duke@0 2455 enc_class opc3_reg(rRegI dst)
duke@0 2456 %{
duke@0 2457 // BSWAP
duke@0 2458 emit_cc(cbuf, $tertiary, $dst$$reg);
duke@0 2459 %}
duke@0 2460
duke@0 2461 enc_class reg_opc(rRegI div)
duke@0 2462 %{
duke@0 2463 // INC, DEC, IDIV, IMOD, JMP indirect, ...
duke@0 2464 emit_rm(cbuf, 0x3, $secondary, $div$$reg & 7);
duke@0 2465 %}
duke@0 2466
duke@0 2467 enc_class Jcc(cmpOp cop, label labl)
duke@0 2468 %{
duke@0 2469 // JCC
duke@0 2470 Label* l = $labl$$label;
duke@0 2471 $$$emit8$primary;
duke@0 2472 emit_cc(cbuf, $secondary, $cop$$cmpcode);
duke@0 2473 emit_d32(cbuf, l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0);
duke@0 2474 %}
duke@0 2475
duke@0 2476 enc_class JccShort (cmpOp cop, label labl)
duke@0 2477 %{
duke@0 2478 // JCC
duke@0 2479 Label *l = $labl$$label;
duke@0 2480 emit_cc(cbuf, $primary, $cop$$cmpcode);
duke@0 2481 int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
duke@0 2482 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
duke@0 2483 emit_d8(cbuf, disp);
duke@0 2484 %}
duke@0 2485
duke@0 2486 enc_class enc_cmov(cmpOp cop)
duke@0 2487 %{
duke@0 2488 // CMOV
duke@0 2489 $$$emit8$primary;
duke@0 2490 emit_cc(cbuf, $secondary, $cop$$cmpcode);
duke@0 2491 %}
duke@0 2492
duke@0 2493 enc_class enc_cmovf_branch(cmpOp cop, regF dst, regF src)
duke@0 2494 %{
duke@0 2495 // Invert sense of branch from sense of cmov
duke@0 2496 emit_cc(cbuf, 0x70, $cop$$cmpcode ^ 1);
duke@0 2497 emit_d8(cbuf, ($dst$$reg < 8 && $src$$reg < 8)
duke@0 2498 ? (UseXmmRegToRegMoveAll ? 3 : 4)
duke@0 2499 : (UseXmmRegToRegMoveAll ? 4 : 5) ); // REX
duke@0 2500 // UseXmmRegToRegMoveAll ? movaps(dst, src) : movss(dst, src)
duke@0 2501 if (!UseXmmRegToRegMoveAll) emit_opcode(cbuf, 0xF3);
duke@0 2502 if ($dst$$reg < 8) {
duke@0 2503 if ($src$$reg >= 8) {
duke@0 2504 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2505 }
duke@0 2506 } else {
duke@0 2507 if ($src$$reg < 8) {
duke@0 2508 emit_opcode(cbuf, Assembler::REX_R);
duke@0 2509 } else {
duke@0 2510 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 2511 }
duke@0 2512 }
duke@0 2513 emit_opcode(cbuf, 0x0F);
duke@0 2514 emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10);
duke@0 2515 emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
duke@0 2516 %}
duke@0 2517
duke@0 2518 enc_class enc_cmovd_branch(cmpOp cop, regD dst, regD src)
duke@0 2519 %{
duke@0 2520 // Invert sense of branch from sense of cmov
duke@0 2521 emit_cc(cbuf, 0x70, $cop$$cmpcode ^ 1);
duke@0 2522 emit_d8(cbuf, $dst$$reg < 8 && $src$$reg < 8 ? 4 : 5); // REX
duke@0 2523
duke@0 2524 // UseXmmRegToRegMoveAll ? movapd(dst, src) : movsd(dst, src)
duke@0 2525 emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x66 : 0xF2);
duke@0 2526 if ($dst$$reg < 8) {
duke@0 2527 if ($src$$reg >= 8) {
duke@0 2528 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2529 }
duke@0 2530 } else {
duke@0 2531 if ($src$$reg < 8) {
duke@0 2532 emit_opcode(cbuf, Assembler::REX_R);
duke@0 2533 } else {
duke@0 2534 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 2535 }
duke@0 2536 }
duke@0 2537 emit_opcode(cbuf, 0x0F);
duke@0 2538 emit_opcode(cbuf, UseXmmRegToRegMoveAll ? 0x28 : 0x10);
duke@0 2539 emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
duke@0 2540 %}
duke@0 2541
duke@0 2542 enc_class enc_PartialSubtypeCheck()
duke@0 2543 %{
duke@0 2544 Register Rrdi = as_Register(RDI_enc); // result register
duke@0 2545 Register Rrax = as_Register(RAX_enc); // super class
duke@0 2546 Register Rrcx = as_Register(RCX_enc); // killed
duke@0 2547 Register Rrsi = as_Register(RSI_enc); // sub class
duke@0 2548 Label hit, miss;
duke@0 2549
duke@0 2550 MacroAssembler _masm(&cbuf);
duke@0 2551 // Compare super with sub directly, since super is not in its own SSA.
duke@0 2552 // The compiler used to emit this test, but we fold it in here,
duke@0 2553 // to allow platform-specific tweaking on sparc.
duke@0 2554 __ cmpq(Rrax, Rrsi);
duke@0 2555 __ jcc(Assembler::equal, hit);
duke@0 2556 #ifndef PRODUCT
duke@0 2557 __ lea(Rrcx, ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr));
duke@0 2558 __ incrementl(Address(Rrcx, 0));
duke@0 2559 #endif //PRODUCT
duke@0 2560 __ movq(Rrdi, Address(Rrsi,
duke@0 2561 sizeof(oopDesc) +
duke@0 2562 Klass::secondary_supers_offset_in_bytes()));
duke@0 2563 __ movl(Rrcx, Address(Rrdi, arrayOopDesc::length_offset_in_bytes()));
duke@0 2564 __ addq(Rrdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
duke@0 2565 __ repne_scan();
duke@0 2566 __ jcc(Assembler::notEqual, miss);
duke@0 2567 __ movq(Address(Rrsi,
duke@0 2568 sizeof(oopDesc) +
duke@0 2569 Klass::secondary_super_cache_offset_in_bytes()),
duke@0 2570 Rrax);
duke@0 2571 __ bind(hit);
duke@0 2572 if ($primary) {
duke@0 2573 __ xorq(Rrdi, Rrdi);
duke@0 2574 }
duke@0 2575 __ bind(miss);
duke@0 2576 %}
duke@0 2577
duke@0 2578 enc_class Java_To_Interpreter(method meth)
duke@0 2579 %{
duke@0 2580 // CALL Java_To_Interpreter
duke@0 2581 // This is the instruction starting address for relocation info.
duke@0 2582 cbuf.set_inst_mark();
duke@0 2583 $$$emit8$primary;
duke@0 2584 // CALL directly to the runtime
duke@0 2585 emit_d32_reloc(cbuf,
duke@0 2586 (int) ($meth$$method - ((intptr_t) cbuf.code_end()) - 4),
duke@0 2587 runtime_call_Relocation::spec(),
duke@0 2588 RELOC_DISP32);
duke@0 2589 %}
duke@0 2590
duke@0 2591 enc_class Java_Static_Call(method meth)
duke@0 2592 %{
duke@0 2593 // JAVA STATIC CALL
duke@0 2594 // CALL to fixup routine. Fixup routine uses ScopeDesc info to
duke@0 2595 // determine who we intended to call.
duke@0 2596 cbuf.set_inst_mark();
duke@0 2597 $$$emit8$primary;
duke@0 2598
duke@0 2599 if (!_method) {
duke@0 2600 emit_d32_reloc(cbuf,
duke@0 2601 (int) ($meth$$method - ((intptr_t) cbuf.code_end()) - 4),
duke@0 2602 runtime_call_Relocation::spec(),
duke@0 2603 RELOC_DISP32);
duke@0 2604 } else if (_optimized_virtual) {
duke@0 2605 emit_d32_reloc(cbuf,
duke@0 2606 (int) ($meth$$method - ((intptr_t) cbuf.code_end()) - 4),
duke@0 2607 opt_virtual_call_Relocation::spec(),
duke@0 2608 RELOC_DISP32);
duke@0 2609 } else {
duke@0 2610 emit_d32_reloc(cbuf,
duke@0 2611 (int) ($meth$$method - ((intptr_t) cbuf.code_end()) - 4),
duke@0 2612 static_call_Relocation::spec(),
duke@0 2613 RELOC_DISP32);
duke@0 2614 }
duke@0 2615 if (_method) {
duke@0 2616 // Emit stub for static call
duke@0 2617 emit_java_to_interp(cbuf);
duke@0 2618 }
duke@0 2619 %}
duke@0 2620
duke@0 2621 enc_class Java_Dynamic_Call(method meth)
duke@0 2622 %{
duke@0 2623 // JAVA DYNAMIC CALL
duke@0 2624 // !!!!!
duke@0 2625 // Generate "movq rax, -1", placeholder instruction to load oop-info
duke@0 2626 // emit_call_dynamic_prologue( cbuf );
duke@0 2627 cbuf.set_inst_mark();
duke@0 2628
duke@0 2629 // movq rax, -1
duke@0 2630 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2631 emit_opcode(cbuf, 0xB8 | RAX_enc);
duke@0 2632 emit_d64_reloc(cbuf,
duke@0 2633 (int64_t) Universe::non_oop_word(),
duke@0 2634 oop_Relocation::spec_for_immediate(), RELOC_IMM64);
duke@0 2635 address virtual_call_oop_addr = cbuf.inst_mark();
duke@0 2636 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
duke@0 2637 // who we intended to call.
duke@0 2638 cbuf.set_inst_mark();
duke@0 2639 $$$emit8$primary;
duke@0 2640 emit_d32_reloc(cbuf,
duke@0 2641 (int) ($meth$$method - ((intptr_t) cbuf.code_end()) - 4),
duke@0 2642 virtual_call_Relocation::spec(virtual_call_oop_addr),
duke@0 2643 RELOC_DISP32);
duke@0 2644 %}
duke@0 2645
duke@0 2646 enc_class Java_Compiled_Call(method meth)
duke@0 2647 %{
duke@0 2648 // JAVA COMPILED CALL
duke@0 2649 int disp = in_bytes(methodOopDesc:: from_compiled_offset());
duke@0 2650
duke@0 2651 // XXX XXX offset is 128 is 1.5 NON-PRODUCT !!!
duke@0 2652 // assert(-0x80 <= disp && disp < 0x80, "compiled_code_offset isn't small");
duke@0 2653
duke@0 2654 // callq *disp(%rax)
duke@0 2655 cbuf.set_inst_mark();
duke@0 2656 $$$emit8$primary;
duke@0 2657 if (disp < 0x80) {
duke@0 2658 emit_rm(cbuf, 0x01, $secondary, RAX_enc); // R/M byte
duke@0 2659 emit_d8(cbuf, disp); // Displacement
duke@0 2660 } else {
duke@0 2661 emit_rm(cbuf, 0x02, $secondary, RAX_enc); // R/M byte
duke@0 2662 emit_d32(cbuf, disp); // Displacement
duke@0 2663 }
duke@0 2664 %}
duke@0 2665
duke@0 2666 enc_class reg_opc_imm(rRegI dst, immI8 shift)
duke@0 2667 %{
duke@0 2668 // SAL, SAR, SHR
duke@0 2669 int dstenc = $dst$$reg;
duke@0 2670 if (dstenc >= 8) {
duke@0 2671 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2672 dstenc -= 8;
duke@0 2673 }
duke@0 2674 $$$emit8$primary;
duke@0 2675 emit_rm(cbuf, 0x3, $secondary, dstenc);
duke@0 2676 $$$emit8$shift$$constant;
duke@0 2677 %}
duke@0 2678
duke@0 2679 enc_class reg_opc_imm_wide(rRegL dst, immI8 shift)
duke@0 2680 %{
duke@0 2681 // SAL, SAR, SHR
duke@0 2682 int dstenc = $dst$$reg;
duke@0 2683 if (dstenc < 8) {
duke@0 2684 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2685 } else {
duke@0 2686 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2687 dstenc -= 8;
duke@0 2688 }
duke@0 2689 $$$emit8$primary;
duke@0 2690 emit_rm(cbuf, 0x3, $secondary, dstenc);
duke@0 2691 $$$emit8$shift$$constant;
duke@0 2692 %}
duke@0 2693
duke@0 2694 enc_class load_immI(rRegI dst, immI src)
duke@0 2695 %{
duke@0 2696 int dstenc = $dst$$reg;
duke@0 2697 if (dstenc >= 8) {
duke@0 2698 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2699 dstenc -= 8;
duke@0 2700 }
duke@0 2701 emit_opcode(cbuf, 0xB8 | dstenc);
duke@0 2702 $$$emit32$src$$constant;
duke@0 2703 %}
duke@0 2704
duke@0 2705 enc_class load_immL(rRegL dst, immL src)
duke@0 2706 %{
duke@0 2707 int dstenc = $dst$$reg;
duke@0 2708 if (dstenc < 8) {
duke@0 2709 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2710 } else {
duke@0 2711 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2712 dstenc -= 8;
duke@0 2713 }
duke@0 2714 emit_opcode(cbuf, 0xB8 | dstenc);
duke@0 2715 emit_d64(cbuf, $src$$constant);
duke@0 2716 %}
duke@0 2717
duke@0 2718 enc_class load_immUL32(rRegL dst, immUL32 src)
duke@0 2719 %{
duke@0 2720 // same as load_immI, but this time we care about zeroes in the high word
duke@0 2721 int dstenc = $dst$$reg;
duke@0 2722 if (dstenc >= 8) {
duke@0 2723 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2724 dstenc -= 8;
duke@0 2725 }
duke@0 2726 emit_opcode(cbuf, 0xB8 | dstenc);
duke@0 2727 $$$emit32$src$$constant;
duke@0 2728 %}
duke@0 2729
duke@0 2730 enc_class load_immL32(rRegL dst, immL32 src)
duke@0 2731 %{
duke@0 2732 int dstenc = $dst$$reg;
duke@0 2733 if (dstenc < 8) {
duke@0 2734 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2735 } else {
duke@0 2736 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2737 dstenc -= 8;
duke@0 2738 }
duke@0 2739 emit_opcode(cbuf, 0xC7);
duke@0 2740 emit_rm(cbuf, 0x03, 0x00, dstenc);
duke@0 2741 $$$emit32$src$$constant;
duke@0 2742 %}
duke@0 2743
duke@0 2744 enc_class load_immP31(rRegP dst, immP32 src)
duke@0 2745 %{
duke@0 2746 // same as load_immI, but this time we care about zeroes in the high word
duke@0 2747 int dstenc = $dst$$reg;
duke@0 2748 if (dstenc >= 8) {
duke@0 2749 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2750 dstenc -= 8;
duke@0 2751 }
duke@0 2752 emit_opcode(cbuf, 0xB8 | dstenc);
duke@0 2753 $$$emit32$src$$constant;
duke@0 2754 %}
duke@0 2755
duke@0 2756 enc_class load_immP(rRegP dst, immP src)
duke@0 2757 %{
duke@0 2758 int dstenc = $dst$$reg;
duke@0 2759 if (dstenc < 8) {
duke@0 2760 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2761 } else {
duke@0 2762 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2763 dstenc -= 8;
duke@0 2764 }
duke@0 2765 emit_opcode(cbuf, 0xB8 | dstenc);
duke@0 2766 // This next line should be generated from ADLC
duke@0 2767 if ($src->constant_is_oop()) {
duke@0 2768 emit_d64_reloc(cbuf, $src$$constant, relocInfo::oop_type, RELOC_IMM64);
duke@0 2769 } else {
duke@0 2770 emit_d64(cbuf, $src$$constant);
duke@0 2771 }
duke@0 2772 %}
duke@0 2773
duke@0 2774 enc_class load_immF(regF dst, immF con)
duke@0 2775 %{
duke@0 2776 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 2777 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
duke@0 2778 emit_float_constant(cbuf, $con$$constant);
duke@0 2779 %}
duke@0 2780
duke@0 2781 enc_class load_immD(regD dst, immD con)
duke@0 2782 %{
duke@0 2783 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 2784 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
duke@0 2785 emit_double_constant(cbuf, $con$$constant);
duke@0 2786 %}
duke@0 2787
duke@0 2788 enc_class load_conF (regF dst, immF con) %{ // Load float constant
duke@0 2789 emit_opcode(cbuf, 0xF3);
duke@0 2790 if ($dst$$reg >= 8) {
duke@0 2791 emit_opcode(cbuf, Assembler::REX_R);
duke@0 2792 }
duke@0 2793 emit_opcode(cbuf, 0x0F);
duke@0 2794 emit_opcode(cbuf, 0x10);
duke@0 2795 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
duke@0 2796 emit_float_constant(cbuf, $con$$constant);
duke@0 2797 %}
duke@0 2798
duke@0 2799 enc_class load_conD (regD dst, immD con) %{ // Load double constant
duke@0 2800 // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
duke@0 2801 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
duke@0 2802 if ($dst$$reg >= 8) {
duke@0 2803 emit_opcode(cbuf, Assembler::REX_R);
duke@0 2804 }
duke@0 2805 emit_opcode(cbuf, 0x0F);
duke@0 2806 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
duke@0 2807 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
duke@0 2808 emit_double_constant(cbuf, $con$$constant);
duke@0 2809 %}
duke@0 2810
duke@0 2811 // Encode a reg-reg copy. If it is useless, then empty encoding.
duke@0 2812 enc_class enc_copy(rRegI dst, rRegI src)
duke@0 2813 %{
duke@0 2814 encode_copy(cbuf, $dst$$reg, $src$$reg);
duke@0 2815 %}
duke@0 2816
duke@0 2817 // Encode xmm reg-reg copy. If it is useless, then empty encoding.
duke@0 2818 enc_class enc_CopyXD( RegD dst, RegD src ) %{
duke@0 2819 encode_CopyXD( cbuf, $dst$$reg, $src$$reg );
duke@0 2820 %}
duke@0 2821
duke@0 2822 enc_class enc_copy_always(rRegI dst, rRegI src)
duke@0 2823 %{
duke@0 2824 int srcenc = $src$$reg;
duke@0 2825 int dstenc = $dst$$reg;
duke@0 2826
duke@0 2827 if (dstenc < 8) {
duke@0 2828 if (srcenc >= 8) {
duke@0 2829 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2830 srcenc -= 8;
duke@0 2831 }
duke@0 2832 } else {
duke@0 2833 if (srcenc < 8) {
duke@0 2834 emit_opcode(cbuf, Assembler::REX_R);
duke@0 2835 } else {
duke@0 2836 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 2837 srcenc -= 8;
duke@0 2838 }
duke@0 2839 dstenc -= 8;
duke@0 2840 }
duke@0 2841
duke@0 2842 emit_opcode(cbuf, 0x8B);
duke@0 2843 emit_rm(cbuf, 0x3, dstenc, srcenc);
duke@0 2844 %}
duke@0 2845
duke@0 2846 enc_class enc_copy_wide(rRegL dst, rRegL src)
duke@0 2847 %{
duke@0 2848 int srcenc = $src$$reg;
duke@0 2849 int dstenc = $dst$$reg;
duke@0 2850
duke@0 2851 if (dstenc != srcenc) {
duke@0 2852 if (dstenc < 8) {
duke@0 2853 if (srcenc < 8) {
duke@0 2854 emit_opcode(cbuf, Assembler::REX_W);
duke@0 2855 } else {
duke@0 2856 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2857 srcenc -= 8;
duke@0 2858 }
duke@0 2859 } else {
duke@0 2860 if (srcenc < 8) {
duke@0 2861 emit_opcode(cbuf, Assembler::REX_WR);
duke@0 2862 } else {
duke@0 2863 emit_opcode(cbuf, Assembler::REX_WRB);
duke@0 2864 srcenc -= 8;
duke@0 2865 }
duke@0 2866 dstenc -= 8;
duke@0 2867 }
duke@0 2868 emit_opcode(cbuf, 0x8B);
duke@0 2869 emit_rm(cbuf, 0x3, dstenc, srcenc);
duke@0 2870 }
duke@0 2871 %}
duke@0 2872
duke@0 2873 enc_class Con32(immI src)
duke@0 2874 %{
duke@0 2875 // Output immediate
duke@0 2876 $$$emit32$src$$constant;
duke@0 2877 %}
duke@0 2878
duke@0 2879 enc_class Con64(immL src)
duke@0 2880 %{
duke@0 2881 // Output immediate
duke@0 2882 emit_d64($src$$constant);
duke@0 2883 %}
duke@0 2884
duke@0 2885 enc_class Con32F_as_bits(immF src)
duke@0 2886 %{
duke@0 2887 // Output Float immediate bits
duke@0 2888 jfloat jf = $src$$constant;
duke@0 2889 jint jf_as_bits = jint_cast(jf);
duke@0 2890 emit_d32(cbuf, jf_as_bits);
duke@0 2891 %}
duke@0 2892
duke@0 2893 enc_class Con16(immI src)
duke@0 2894 %{
duke@0 2895 // Output immediate
duke@0 2896 $$$emit16$src$$constant;
duke@0 2897 %}
duke@0 2898
duke@0 2899 // How is this different from Con32??? XXX
duke@0 2900 enc_class Con_d32(immI src)
duke@0 2901 %{
duke@0 2902 emit_d32(cbuf,$src$$constant);
duke@0 2903 %}
duke@0 2904
duke@0 2905 enc_class conmemref (rRegP t1) %{ // Con32(storeImmI)
duke@0 2906 // Output immediate memory reference
duke@0 2907 emit_rm(cbuf, 0x00, $t1$$reg, 0x05 );
duke@0 2908 emit_d32(cbuf, 0x00);
duke@0 2909 %}
duke@0 2910
duke@0 2911 enc_class jump_enc(rRegL switch_val, rRegI dest) %{
duke@0 2912 MacroAssembler masm(&cbuf);
duke@0 2913
duke@0 2914 Register switch_reg = as_Register($switch_val$$reg);
duke@0 2915 Register dest_reg = as_Register($dest$$reg);
duke@0 2916 address table_base = masm.address_table_constant(_index2label);
duke@0 2917
duke@0 2918 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
duke@0 2919 // to do that and the compiler is using that register as one it can allocate.
duke@0 2920 // So we build it all by hand.
duke@0 2921 // Address index(noreg, switch_reg, Address::times_1);
duke@0 2922 // ArrayAddress dispatch(table, index);
duke@0 2923
duke@0 2924 Address dispatch(dest_reg, switch_reg, Address::times_1);
duke@0 2925
duke@0 2926 masm.lea(dest_reg, InternalAddress(table_base));
duke@0 2927 masm.jmp(dispatch);
duke@0 2928 %}
duke@0 2929
duke@0 2930 enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
duke@0 2931 MacroAssembler masm(&cbuf);
duke@0 2932
duke@0 2933 Register switch_reg = as_Register($switch_val$$reg);
duke@0 2934 Register dest_reg = as_Register($dest$$reg);
duke@0 2935 address table_base = masm.address_table_constant(_index2label);
duke@0 2936
duke@0 2937 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
duke@0 2938 // to do that and the compiler is using that register as one it can allocate.
duke@0 2939 // So we build it all by hand.
duke@0 2940 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
duke@0 2941 // ArrayAddress dispatch(table, index);
duke@0 2942
duke@0 2943 Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
duke@0 2944
duke@0 2945 masm.lea(dest_reg, InternalAddress(table_base));
duke@0 2946 masm.jmp(dispatch);
duke@0 2947 %}
duke@0 2948
duke@0 2949 enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
duke@0 2950 MacroAssembler masm(&cbuf);
duke@0 2951
duke@0 2952 Register switch_reg = as_Register($switch_val$$reg);
duke@0 2953 Register dest_reg = as_Register($dest$$reg);
duke@0 2954 address table_base = masm.address_table_constant(_index2label);
duke@0 2955
duke@0 2956 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
duke@0 2957 // to do that and the compiler is using that register as one it can allocate.
duke@0 2958 // So we build it all by hand.
duke@0 2959 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
duke@0 2960 // ArrayAddress dispatch(table, index);
duke@0 2961
duke@0 2962 Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant);
duke@0 2963 masm.lea(dest_reg, InternalAddress(table_base));
duke@0 2964 masm.jmp(dispatch);
duke@0 2965
duke@0 2966 %}
duke@0 2967
duke@0 2968 enc_class lock_prefix()
duke@0 2969 %{
duke@0 2970 if (os::is_MP()) {
duke@0 2971 emit_opcode(cbuf, 0xF0); // lock
duke@0 2972 }
duke@0 2973 %}
duke@0 2974
duke@0 2975 enc_class REX_mem(memory mem)
duke@0 2976 %{
duke@0 2977 if ($mem$$base >= 8) {
duke@0 2978 if ($mem$$index < 8) {
duke@0 2979 emit_opcode(cbuf, Assembler::REX_B);
duke@0 2980 } else {
duke@0 2981 emit_opcode(cbuf, Assembler::REX_XB);
duke@0 2982 }
duke@0 2983 } else {
duke@0 2984 if ($mem$$index >= 8) {
duke@0 2985 emit_opcode(cbuf, Assembler::REX_X);
duke@0 2986 }
duke@0 2987 }
duke@0 2988 %}
duke@0 2989
duke@0 2990 enc_class REX_mem_wide(memory mem)
duke@0 2991 %{
duke@0 2992 if ($mem$$base >= 8) {
duke@0 2993 if ($mem$$index < 8) {
duke@0 2994 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 2995 } else {
duke@0 2996 emit_opcode(cbuf, Assembler::REX_WXB);
duke@0 2997 }
duke@0 2998 } else {
duke@0 2999 if ($mem$$index < 8) {
duke@0 3000 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3001 } else {
duke@0 3002 emit_opcode(cbuf, Assembler::REX_WX);
duke@0 3003 }
duke@0 3004 }
duke@0 3005 %}
duke@0 3006
duke@0 3007 // for byte regs
duke@0 3008 enc_class REX_breg(rRegI reg)
duke@0 3009 %{
duke@0 3010 if ($reg$$reg >= 4) {
duke@0 3011 emit_opcode(cbuf, $reg$$reg < 8 ? Assembler::REX : Assembler::REX_B);
duke@0 3012 }
duke@0 3013 %}
duke@0 3014
duke@0 3015 // for byte regs
duke@0 3016 enc_class REX_reg_breg(rRegI dst, rRegI src)
duke@0 3017 %{
duke@0 3018 if ($dst$$reg < 8) {
duke@0 3019 if ($src$$reg >= 4) {
duke@0 3020 emit_opcode(cbuf, $src$$reg < 8 ? Assembler::REX : Assembler::REX_B);
duke@0 3021 }
duke@0 3022 } else {
duke@0 3023 if ($src$$reg < 8) {
duke@0 3024 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3025 } else {
duke@0 3026 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 3027 }
duke@0 3028 }
duke@0 3029 %}
duke@0 3030
duke@0 3031 // for byte regs
duke@0 3032 enc_class REX_breg_mem(rRegI reg, memory mem)
duke@0 3033 %{
duke@0 3034 if ($reg$$reg < 8) {
duke@0 3035 if ($mem$$base < 8) {
duke@0 3036 if ($mem$$index >= 8) {
duke@0 3037 emit_opcode(cbuf, Assembler::REX_X);
duke@0 3038 } else if ($reg$$reg >= 4) {
duke@0 3039 emit_opcode(cbuf, Assembler::REX);
duke@0 3040 }
duke@0 3041 } else {
duke@0 3042 if ($mem$$index < 8) {
duke@0 3043 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3044 } else {
duke@0 3045 emit_opcode(cbuf, Assembler::REX_XB);
duke@0 3046 }
duke@0 3047 }
duke@0 3048 } else {
duke@0 3049 if ($mem$$base < 8) {
duke@0 3050 if ($mem$$index < 8) {
duke@0 3051 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3052 } else {
duke@0 3053 emit_opcode(cbuf, Assembler::REX_RX);
duke@0 3054 }
duke@0 3055 } else {
duke@0 3056 if ($mem$$index < 8) {
duke@0 3057 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 3058 } else {
duke@0 3059 emit_opcode(cbuf, Assembler::REX_RXB);
duke@0 3060 }
duke@0 3061 }
duke@0 3062 }
duke@0 3063 %}
duke@0 3064
duke@0 3065 enc_class REX_reg(rRegI reg)
duke@0 3066 %{
duke@0 3067 if ($reg$$reg >= 8) {
duke@0 3068 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3069 }
duke@0 3070 %}
duke@0 3071
duke@0 3072 enc_class REX_reg_wide(rRegI reg)
duke@0 3073 %{
duke@0 3074 if ($reg$$reg < 8) {
duke@0 3075 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3076 } else {
duke@0 3077 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 3078 }
duke@0 3079 %}
duke@0 3080
duke@0 3081 enc_class REX_reg_reg(rRegI dst, rRegI src)
duke@0 3082 %{
duke@0 3083 if ($dst$$reg < 8) {
duke@0 3084 if ($src$$reg >= 8) {
duke@0 3085 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3086 }
duke@0 3087 } else {
duke@0 3088 if ($src$$reg < 8) {
duke@0 3089 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3090 } else {
duke@0 3091 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 3092 }
duke@0 3093 }
duke@0 3094 %}
duke@0 3095
duke@0 3096 enc_class REX_reg_reg_wide(rRegI dst, rRegI src)
duke@0 3097 %{
duke@0 3098 if ($dst$$reg < 8) {
duke@0 3099 if ($src$$reg < 8) {
duke@0 3100 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3101 } else {
duke@0 3102 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 3103 }
duke@0 3104 } else {
duke@0 3105 if ($src$$reg < 8) {
duke@0 3106 emit_opcode(cbuf, Assembler::REX_WR);
duke@0 3107 } else {
duke@0 3108 emit_opcode(cbuf, Assembler::REX_WRB);
duke@0 3109 }
duke@0 3110 }
duke@0 3111 %}
duke@0 3112
duke@0 3113 enc_class REX_reg_mem(rRegI reg, memory mem)
duke@0 3114 %{
duke@0 3115 if ($reg$$reg < 8) {
duke@0 3116 if ($mem$$base < 8) {
duke@0 3117 if ($mem$$index >= 8) {
duke@0 3118 emit_opcode(cbuf, Assembler::REX_X);
duke@0 3119 }
duke@0 3120 } else {
duke@0 3121 if ($mem$$index < 8) {
duke@0 3122 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3123 } else {
duke@0 3124 emit_opcode(cbuf, Assembler::REX_XB);
duke@0 3125 }
duke@0 3126 }
duke@0 3127 } else {
duke@0 3128 if ($mem$$base < 8) {
duke@0 3129 if ($mem$$index < 8) {
duke@0 3130 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3131 } else {
duke@0 3132 emit_opcode(cbuf, Assembler::REX_RX);
duke@0 3133 }
duke@0 3134 } else {
duke@0 3135 if ($mem$$index < 8) {
duke@0 3136 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 3137 } else {
duke@0 3138 emit_opcode(cbuf, Assembler::REX_RXB);
duke@0 3139 }
duke@0 3140 }
duke@0 3141 }
duke@0 3142 %}
duke@0 3143
duke@0 3144 enc_class REX_reg_mem_wide(rRegL reg, memory mem)
duke@0 3145 %{
duke@0 3146 if ($reg$$reg < 8) {
duke@0 3147 if ($mem$$base < 8) {
duke@0 3148 if ($mem$$index < 8) {
duke@0 3149 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3150 } else {
duke@0 3151 emit_opcode(cbuf, Assembler::REX_WX);
duke@0 3152 }
duke@0 3153 } else {
duke@0 3154 if ($mem$$index < 8) {
duke@0 3155 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 3156 } else {
duke@0 3157 emit_opcode(cbuf, Assembler::REX_WXB);
duke@0 3158 }
duke@0 3159 }
duke@0 3160 } else {
duke@0 3161 if ($mem$$base < 8) {
duke@0 3162 if ($mem$$index < 8) {
duke@0 3163 emit_opcode(cbuf, Assembler::REX_WR);
duke@0 3164 } else {
duke@0 3165 emit_opcode(cbuf, Assembler::REX_WRX);
duke@0 3166 }
duke@0 3167 } else {
duke@0 3168 if ($mem$$index < 8) {
duke@0 3169 emit_opcode(cbuf, Assembler::REX_WRB);
duke@0 3170 } else {
duke@0 3171 emit_opcode(cbuf, Assembler::REX_WRXB);
duke@0 3172 }
duke@0 3173 }
duke@0 3174 }
duke@0 3175 %}
duke@0 3176
duke@0 3177 enc_class reg_mem(rRegI ereg, memory mem)
duke@0 3178 %{
duke@0 3179 // High registers handle in encode_RegMem
duke@0 3180 int reg = $ereg$$reg;
duke@0 3181 int base = $mem$$base;
duke@0 3182 int index = $mem$$index;
duke@0 3183 int scale = $mem$$scale;
duke@0 3184 int disp = $mem$$disp;
duke@0 3185 bool disp_is_oop = $mem->disp_is_oop();
duke@0 3186
duke@0 3187 encode_RegMem(cbuf, reg, base, index, scale, disp, disp_is_oop);
duke@0 3188 %}
duke@0 3189
duke@0 3190 enc_class RM_opc_mem(immI rm_opcode, memory mem)
duke@0 3191 %{
duke@0 3192 int rm_byte_opcode = $rm_opcode$$constant;
duke@0 3193
duke@0 3194 // High registers handle in encode_RegMem
duke@0 3195 int base = $mem$$base;
duke@0 3196 int index = $mem$$index;
duke@0 3197 int scale = $mem$$scale;
duke@0 3198 int displace = $mem$$disp;
duke@0 3199
duke@0 3200 bool disp_is_oop = $mem->disp_is_oop(); // disp-as-oop when
duke@0 3201 // working with static
duke@0 3202 // globals
duke@0 3203 encode_RegMem(cbuf, rm_byte_opcode, base, index, scale, displace,
duke@0 3204 disp_is_oop);
duke@0 3205 %}
duke@0 3206
duke@0 3207 enc_class reg_lea(rRegI dst, rRegI src0, immI src1)
duke@0 3208 %{
duke@0 3209 int reg_encoding = $dst$$reg;
duke@0 3210 int base = $src0$$reg; // 0xFFFFFFFF indicates no base
duke@0 3211 int index = 0x04; // 0x04 indicates no index
duke@0 3212 int scale = 0x00; // 0x00 indicates no scale
duke@0 3213 int displace = $src1$$constant; // 0x00 indicates no displacement
duke@0 3214 bool disp_is_oop = false;
duke@0 3215 encode_RegMem(cbuf, reg_encoding, base, index, scale, displace,
duke@0 3216 disp_is_oop);
duke@0 3217 %}
duke@0 3218
duke@0 3219 enc_class neg_reg(rRegI dst)
duke@0 3220 %{
duke@0 3221 int dstenc = $dst$$reg;
duke@0 3222 if (dstenc >= 8) {
duke@0 3223 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3224 dstenc -= 8;
duke@0 3225 }
duke@0 3226 // NEG $dst
duke@0 3227 emit_opcode(cbuf, 0xF7);
duke@0 3228 emit_rm(cbuf, 0x3, 0x03, dstenc);
duke@0 3229 %}
duke@0 3230
duke@0 3231 enc_class neg_reg_wide(rRegI dst)
duke@0 3232 %{
duke@0 3233 int dstenc = $dst$$reg;
duke@0 3234 if (dstenc < 8) {
duke@0 3235 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3236 } else {
duke@0 3237 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 3238 dstenc -= 8;
duke@0 3239 }
duke@0 3240 // NEG $dst
duke@0 3241 emit_opcode(cbuf, 0xF7);
duke@0 3242 emit_rm(cbuf, 0x3, 0x03, dstenc);
duke@0 3243 %}
duke@0 3244
duke@0 3245 enc_class setLT_reg(rRegI dst)
duke@0 3246 %{
duke@0 3247 int dstenc = $dst$$reg;
duke@0 3248 if (dstenc >= 8) {
duke@0 3249 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3250 dstenc -= 8;
duke@0 3251 } else if (dstenc >= 4) {
duke@0 3252 emit_opcode(cbuf, Assembler::REX);
duke@0 3253 }
duke@0 3254 // SETLT $dst
duke@0 3255 emit_opcode(cbuf, 0x0F);
duke@0 3256 emit_opcode(cbuf, 0x9C);
duke@0 3257 emit_rm(cbuf, 0x3, 0x0, dstenc);
duke@0 3258 %}
duke@0 3259
duke@0 3260 enc_class setNZ_reg(rRegI dst)
duke@0 3261 %{
duke@0 3262 int dstenc = $dst$$reg;
duke@0 3263 if (dstenc >= 8) {
duke@0 3264 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3265 dstenc -= 8;
duke@0 3266 } else if (dstenc >= 4) {
duke@0 3267 emit_opcode(cbuf, Assembler::REX);
duke@0 3268 }
duke@0 3269 // SETNZ $dst
duke@0 3270 emit_opcode(cbuf, 0x0F);
duke@0 3271 emit_opcode(cbuf, 0x95);
duke@0 3272 emit_rm(cbuf, 0x3, 0x0, dstenc);
duke@0 3273 %}
duke@0 3274
duke@0 3275 enc_class enc_cmpLTP(no_rcx_RegI p, no_rcx_RegI q, no_rcx_RegI y,
duke@0 3276 rcx_RegI tmp)
duke@0 3277 %{
duke@0 3278 // cadd_cmpLT
duke@0 3279
duke@0 3280 int tmpReg = $tmp$$reg;
duke@0 3281
duke@0 3282 int penc = $p$$reg;
duke@0 3283 int qenc = $q$$reg;
duke@0 3284 int yenc = $y$$reg;
duke@0 3285
duke@0 3286 // subl $p,$q
duke@0 3287 if (penc < 8) {
duke@0 3288 if (qenc >= 8) {
duke@0 3289 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3290 }
duke@0 3291 } else {
duke@0 3292 if (qenc < 8) {
duke@0 3293 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3294 } else {
duke@0 3295 emit_opcode(cbuf, Assembler::REX_RB);
duke@0 3296 }
duke@0 3297 }
duke@0 3298 emit_opcode(cbuf, 0x2B);
duke@0 3299 emit_rm(cbuf, 0x3, penc & 7, qenc & 7);
duke@0 3300
duke@0 3301 // sbbl $tmp, $tmp
duke@0 3302 emit_opcode(cbuf, 0x1B);
duke@0 3303 emit_rm(cbuf, 0x3, tmpReg, tmpReg);
duke@0 3304
duke@0 3305 // andl $tmp, $y
duke@0 3306 if (yenc >= 8) {
duke@0 3307 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3308 }
duke@0 3309 emit_opcode(cbuf, 0x23);
duke@0 3310 emit_rm(cbuf, 0x3, tmpReg, yenc & 7);
duke@0 3311
duke@0 3312 // addl $p,$tmp
duke@0 3313 if (penc >= 8) {
duke@0 3314 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3315 }
duke@0 3316 emit_opcode(cbuf, 0x03);
duke@0 3317 emit_rm(cbuf, 0x3, penc & 7, tmpReg);
duke@0 3318 %}
duke@0 3319
duke@0 3320 // Compare the lonogs and set -1, 0, or 1 into dst
duke@0 3321 enc_class cmpl3_flag(rRegL src1, rRegL src2, rRegI dst)
duke@0 3322 %{
duke@0 3323 int src1enc = $src1$$reg;
duke@0 3324 int src2enc = $src2$$reg;
duke@0 3325 int dstenc = $dst$$reg;
duke@0 3326
duke@0 3327 // cmpq $src1, $src2
duke@0 3328 if (src1enc < 8) {
duke@0 3329 if (src2enc < 8) {
duke@0 3330 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3331 } else {
duke@0 3332 emit_opcode(cbuf, Assembler::REX_WB);
duke@0 3333 }
duke@0 3334 } else {
duke@0 3335 if (src2enc < 8) {
duke@0 3336 emit_opcode(cbuf, Assembler::REX_WR);
duke@0 3337 } else {
duke@0 3338 emit_opcode(cbuf, Assembler::REX_WRB);
duke@0 3339 }
duke@0 3340 }
duke@0 3341 emit_opcode(cbuf, 0x3B);
duke@0 3342 emit_rm(cbuf, 0x3, src1enc & 7, src2enc & 7);
duke@0 3343
duke@0 3344 // movl $dst, -1
duke@0 3345 if (dstenc >= 8) {
duke@0 3346 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3347 }
duke@0 3348 emit_opcode(cbuf, 0xB8 | (dstenc & 7));
duke@0 3349 emit_d32(cbuf, -1);
duke@0 3350
duke@0 3351 // jl,s done
duke@0 3352 emit_opcode(cbuf, 0x7C);
duke@0 3353 emit_d8(cbuf, dstenc < 4 ? 0x06 : 0x08);
duke@0 3354
duke@0 3355 // setne $dst
duke@0 3356 if (dstenc >= 4) {
duke@0 3357 emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_B);
duke@0 3358 }
duke@0 3359 emit_opcode(cbuf, 0x0F);
duke@0 3360 emit_opcode(cbuf, 0x95);
duke@0 3361 emit_opcode(cbuf, 0xC0 | (dstenc & 7));
duke@0 3362
duke@0 3363 // movzbl $dst, $dst
duke@0 3364 if (dstenc >= 4) {
duke@0 3365 emit_opcode(cbuf, dstenc < 8 ? Assembler::REX : Assembler::REX_RB);
duke@0 3366 }
duke@0 3367 emit_opcode(cbuf, 0x0F);
duke@0 3368 emit_opcode(cbuf, 0xB6);
duke@0 3369 emit_rm(cbuf, 0x3, dstenc & 7, dstenc & 7);
duke@0 3370 %}
duke@0 3371
duke@0 3372 enc_class Push_ResultXD(regD dst) %{
duke@0 3373 int dstenc = $dst$$reg;
duke@0 3374
duke@0 3375 store_to_stackslot( cbuf, 0xDD, 0x03, 0 ); //FSTP [RSP]
duke@0 3376
duke@0 3377 // UseXmmLoadAndClearUpper ? movsd dst,[rsp] : movlpd dst,[rsp]
duke@0 3378 emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
duke@0 3379 if (dstenc >= 8) {
duke@0 3380 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3381 }
duke@0 3382 emit_opcode (cbuf, 0x0F );
duke@0 3383 emit_opcode (cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12 );
duke@0 3384 encode_RegMem(cbuf, dstenc, RSP_enc, 0x4, 0, 0, false);
duke@0 3385
duke@0 3386 // add rsp,8
duke@0 3387 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3388 emit_opcode(cbuf,0x83);
duke@0 3389 emit_rm(cbuf,0x3, 0x0, RSP_enc);
duke@0 3390 emit_d8(cbuf,0x08);
duke@0 3391 %}
duke@0 3392
duke@0 3393 enc_class Push_SrcXD(regD src) %{
duke@0 3394 int srcenc = $src$$reg;
duke@0 3395
duke@0 3396 // subq rsp,#8
duke@0 3397 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3398 emit_opcode(cbuf, 0x83);
duke@0 3399 emit_rm(cbuf, 0x3, 0x5, RSP_enc);
duke@0 3400 emit_d8(cbuf, 0x8);
duke@0 3401
duke@0 3402 // movsd [rsp],src
duke@0 3403 emit_opcode(cbuf, 0xF2);
duke@0 3404 if (srcenc >= 8) {
duke@0 3405 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3406 }
duke@0 3407 emit_opcode(cbuf, 0x0F);
duke@0 3408 emit_opcode(cbuf, 0x11);
duke@0 3409 encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false);
duke@0 3410
duke@0 3411 // fldd [rsp]
duke@0 3412 emit_opcode(cbuf, 0x66);
duke@0 3413 emit_opcode(cbuf, 0xDD);
duke@0 3414 encode_RegMem(cbuf, 0x0, RSP_enc, 0x4, 0, 0, false);
duke@0 3415 %}
duke@0 3416
duke@0 3417
duke@0 3418 enc_class movq_ld(regD dst, memory mem) %{
duke@0 3419 MacroAssembler _masm(&cbuf);
duke@0 3420 Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
duke@0 3421 __ movq(as_XMMRegister($dst$$reg), madr);
duke@0 3422 %}
duke@0 3423
duke@0 3424 enc_class movq_st(memory mem, regD src) %{
duke@0 3425 MacroAssembler _masm(&cbuf);
duke@0 3426 Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
duke@0 3427 __ movq(madr, as_XMMRegister($src$$reg));
duke@0 3428 %}
duke@0 3429
duke@0 3430 enc_class pshufd_8x8(regF dst, regF src) %{
duke@0 3431 MacroAssembler _masm(&cbuf);
duke@0 3432
duke@0 3433 encode_CopyXD(cbuf, $dst$$reg, $src$$reg);
duke@0 3434 __ punpcklbw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg));
duke@0 3435 __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($dst$$reg), 0x00);
duke@0 3436 %}
duke@0 3437
duke@0 3438 enc_class pshufd_4x16(regF dst, regF src) %{
duke@0 3439 MacroAssembler _masm(&cbuf);
duke@0 3440
duke@0 3441 __ pshuflw(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), 0x00);
duke@0 3442 %}
duke@0 3443
duke@0 3444 enc_class pshufd(regD dst, regD src, int mode) %{
duke@0 3445 MacroAssembler _masm(&cbuf);
duke@0 3446
duke@0 3447 __ pshufd(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg), $mode);
duke@0 3448 %}
duke@0 3449
duke@0 3450 enc_class pxor(regD dst, regD src) %{
duke@0 3451 MacroAssembler _masm(&cbuf);
duke@0 3452
duke@0 3453 __ pxor(as_XMMRegister($dst$$reg), as_XMMRegister($src$$reg));
duke@0 3454 %}
duke@0 3455
duke@0 3456 enc_class mov_i2x(regD dst, rRegI src) %{
duke@0 3457 MacroAssembler _masm(&cbuf);
duke@0 3458
duke@0 3459 __ movdl(as_XMMRegister($dst$$reg), as_Register($src$$reg));
duke@0 3460 %}
duke@0 3461
duke@0 3462 // obj: object to lock
duke@0 3463 // box: box address (header location) -- killed
duke@0 3464 // tmp: rax -- killed
duke@0 3465 // scr: rbx -- killed
duke@0 3466 //
duke@0 3467 // What follows is a direct transliteration of fast_lock() and fast_unlock()
duke@0 3468 // from i486.ad. See that file for comments.
duke@0 3469 // TODO: where possible switch from movq (r, 0) to movl(r,0) and
duke@0 3470 // use the shorter encoding. (Movl clears the high-order 32-bits).
duke@0 3471
duke@0 3472
duke@0 3473 enc_class Fast_Lock(rRegP obj, rRegP box, rax_RegI tmp, rRegP scr)
duke@0 3474 %{
duke@0 3475 Register objReg = as_Register((int)$obj$$reg);
duke@0 3476 Register boxReg = as_Register((int)$box$$reg);
duke@0 3477 Register tmpReg = as_Register($tmp$$reg);
duke@0 3478 Register scrReg = as_Register($scr$$reg);
duke@0 3479 MacroAssembler masm(&cbuf);
duke@0 3480
duke@0 3481 // Verify uniqueness of register assignments -- necessary but not sufficient
duke@0 3482 assert (objReg != boxReg && objReg != tmpReg &&
duke@0 3483 objReg != scrReg && tmpReg != scrReg, "invariant") ;
duke@0 3484
duke@0 3485 if (_counters != NULL) {
duke@0 3486 masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr()));
duke@0 3487 }
duke@0 3488 if (EmitSync & 1) {
duke@0 3489 masm.movptr (Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())) ;
duke@0 3490 masm.cmpq (rsp, 0) ;
duke@0 3491 } else
duke@0 3492 if (EmitSync & 2) {
duke@0 3493 Label DONE_LABEL;
duke@0 3494 if (UseBiasedLocking) {
duke@0 3495 // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument.
duke@0 3496 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters);
duke@0 3497 }
duke@0 3498 masm.movl(tmpReg, 0x1);
duke@0 3499 masm.orq(tmpReg, Address(objReg, 0));
duke@0 3500 masm.movq(Address(boxReg, 0), tmpReg);
duke@0 3501 if (os::is_MP()) {
duke@0 3502 masm.lock();
duke@0 3503 }
duke@0 3504 masm.cmpxchgq(boxReg, Address(objReg, 0)); // Updates tmpReg
duke@0 3505 masm.jcc(Assembler::equal, DONE_LABEL);
duke@0 3506
duke@0 3507 // Recursive locking
duke@0 3508 masm.subq(tmpReg, rsp);
duke@0 3509 masm.andq(tmpReg, 7 - os::vm_page_size());
duke@0 3510 masm.movq(Address(boxReg, 0), tmpReg);
duke@0 3511
duke@0 3512 masm.bind(DONE_LABEL);
duke@0 3513 masm.nop(); // avoid branch to branch
duke@0 3514 } else {
duke@0 3515 Label DONE_LABEL, IsInflated, Egress;
duke@0 3516
duke@0 3517 masm.movq (tmpReg, Address(objReg, 0)) ;
duke@0 3518 masm.testq (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased
duke@0 3519 masm.jcc (Assembler::notZero, IsInflated) ;
duke@0 3520
duke@0 3521 // it's stack-locked, biased or neutral
duke@0 3522 // TODO: optimize markword triage order to reduce the number of
duke@0 3523 // conditional branches in the most common cases.
duke@0 3524 // Beware -- there's a subtle invariant that fetch of the markword
duke@0 3525 // at [FETCH], below, will never observe a biased encoding (*101b).
duke@0 3526 // If this invariant is not held we'll suffer exclusion (safety) failure.
duke@0 3527
duke@0 3528 if (UseBiasedLocking) {
duke@0 3529 masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters);
duke@0 3530 masm.movq (tmpReg, Address(objReg, 0)) ; // [FETCH]
duke@0 3531 }
duke@0 3532
duke@0 3533 masm.orq (tmpReg, 1) ;
duke@0 3534 masm.movq (Address(boxReg, 0), tmpReg) ;
duke@0 3535 if (os::is_MP()) { masm.lock(); }
duke@0 3536 masm.cmpxchgq(boxReg, Address(objReg, 0)); // Updates tmpReg
duke@0 3537 if (_counters != NULL) {
duke@0 3538 masm.cond_inc32(Assembler::equal,
duke@0 3539 ExternalAddress((address) _counters->fast_path_entry_count_addr()));
duke@0 3540 }
duke@0 3541 masm.jcc (Assembler::equal, DONE_LABEL);
duke@0 3542
duke@0 3543 // Recursive locking
duke@0 3544 masm.subq (tmpReg, rsp);
duke@0 3545 masm.andq (tmpReg, 7 - os::vm_page_size());
duke@0 3546 masm.movq (Address(boxReg, 0), tmpReg);
duke@0 3547 if (_counters != NULL) {
duke@0 3548 masm.cond_inc32(Assembler::equal,
duke@0 3549 ExternalAddress((address) _counters->fast_path_entry_count_addr()));
duke@0 3550 }
duke@0 3551 masm.jmp (DONE_LABEL) ;
duke@0 3552
duke@0 3553 masm.bind (IsInflated) ;
duke@0 3554 // It's inflated
duke@0 3555
duke@0 3556 // TODO: someday avoid the ST-before-CAS penalty by
duke@0 3557 // relocating (deferring) the following ST.
duke@0 3558 // We should also think about trying a CAS without having
duke@0 3559 // fetched _owner. If the CAS is successful we may
duke@0 3560 // avoid an RTO->RTS upgrade on the $line.
duke@0 3561 masm.movptr(Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())) ;
duke@0 3562
duke@0 3563 masm.movq (boxReg, tmpReg) ;
duke@0 3564 masm.movq (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
duke@0 3565 masm.testq (tmpReg, tmpReg) ;
duke@0 3566 masm.jcc (Assembler::notZero, DONE_LABEL) ;
duke@0 3567
duke@0 3568 // It's inflated and appears unlocked
duke@0 3569 if (os::is_MP()) { masm.lock(); }
duke@0 3570 masm.cmpxchgq(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
duke@0 3571 // Intentional fall-through into DONE_LABEL ...
duke@0 3572
duke@0 3573 masm.bind (DONE_LABEL) ;
duke@0 3574 masm.nop () ; // avoid jmp to jmp
duke@0 3575 }
duke@0 3576 %}
duke@0 3577
duke@0 3578 // obj: object to unlock
duke@0 3579 // box: box address (displaced header location), killed
duke@0 3580 // RBX: killed tmp; cannot be obj nor box
duke@0 3581 enc_class Fast_Unlock(rRegP obj, rax_RegP box, rRegP tmp)
duke@0 3582 %{
duke@0 3583
duke@0 3584 Register objReg = as_Register($obj$$reg);
duke@0 3585 Register boxReg = as_Register($box$$reg);
duke@0 3586 Register tmpReg = as_Register($tmp$$reg);
duke@0 3587 MacroAssembler masm(&cbuf);
duke@0 3588
duke@0 3589 if (EmitSync & 4) {
duke@0 3590 masm.cmpq (rsp, 0) ;
duke@0 3591 } else
duke@0 3592 if (EmitSync & 8) {
duke@0 3593 Label DONE_LABEL;
duke@0 3594 if (UseBiasedLocking) {
duke@0 3595 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
duke@0 3596 }
duke@0 3597
duke@0 3598 // Check whether the displaced header is 0
duke@0 3599 //(=> recursive unlock)
duke@0 3600 masm.movq(tmpReg, Address(boxReg, 0));
duke@0 3601 masm.testq(tmpReg, tmpReg);
duke@0 3602 masm.jcc(Assembler::zero, DONE_LABEL);
duke@0 3603
duke@0 3604 // If not recursive lock, reset the header to displaced header
duke@0 3605 if (os::is_MP()) {
duke@0 3606 masm.lock();
duke@0 3607 }
duke@0 3608 masm.cmpxchgq(tmpReg, Address(objReg, 0)); // Uses RAX which is box
duke@0 3609 masm.bind(DONE_LABEL);
duke@0 3610 masm.nop(); // avoid branch to branch
duke@0 3611 } else {
duke@0 3612 Label DONE_LABEL, Stacked, CheckSucc ;
duke@0 3613
duke@0 3614 if (UseBiasedLocking) {
duke@0 3615 masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
duke@0 3616 }
duke@0 3617
duke@0 3618 masm.movq (tmpReg, Address(objReg, 0)) ;
duke@0 3619 masm.cmpq (Address(boxReg, 0), (int)NULL_WORD) ;
duke@0 3620 masm.jcc (Assembler::zero, DONE_LABEL) ;
duke@0 3621 masm.testq (tmpReg, 0x02) ;
duke@0 3622 masm.jcc (Assembler::zero, Stacked) ;
duke@0 3623
duke@0 3624 // It's inflated
duke@0 3625 masm.movq (boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
duke@0 3626 masm.xorq (boxReg, r15_thread) ;
duke@0 3627 masm.orq (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
duke@0 3628 masm.jcc (Assembler::notZero, DONE_LABEL) ;
duke@0 3629 masm.movq (boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
duke@0 3630 masm.orq (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
duke@0 3631 masm.jcc (Assembler::notZero, CheckSucc) ;
duke@0 3632 masm.mov64 (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int)NULL_WORD) ;
duke@0 3633 masm.jmp (DONE_LABEL) ;
duke@0 3634
duke@0 3635 if ((EmitSync & 65536) == 0) {
duke@0 3636 Label LSuccess, LGoSlowPath ;
duke@0 3637 masm.bind (CheckSucc) ;
duke@0 3638 masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int)NULL_WORD) ;
duke@0 3639 masm.jcc (Assembler::zero, LGoSlowPath) ;
duke@0 3640
duke@0 3641 // I'd much rather use lock:andl m->_owner, 0 as it's faster than the
duke@0 3642 // the explicit ST;MEMBAR combination, but masm doesn't currently support
duke@0 3643 // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc
duke@0 3644 // are all faster when the write buffer is populated.
duke@0 3645 masm.movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int)NULL_WORD) ;
duke@0 3646 if (os::is_MP()) {
duke@0 3647 masm.lock () ; masm.addq (Address(rsp, 0), 0) ;
duke@0 3648 }
duke@0 3649 masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int)NULL_WORD) ;
duke@0 3650 masm.jcc (Assembler::notZero, LSuccess) ;
duke@0 3651
duke@0 3652 masm.movptr (boxReg, (int)NULL_WORD) ; // box is really EAX
duke@0 3653 if (os::is_MP()) { masm.lock(); }
duke@0 3654 masm.cmpxchgq (r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2));
duke@0 3655 masm.jcc (Assembler::notEqual, LSuccess) ;
duke@0 3656 // Intentional fall-through into slow-path
duke@0 3657
duke@0 3658 masm.bind (LGoSlowPath) ;
duke@0 3659 masm.orl (boxReg, 1) ; // set ICC.ZF=0 to indicate failure
duke@0 3660 masm.jmp (DONE_LABEL) ;
duke@0 3661
duke@0 3662 masm.bind (LSuccess) ;
duke@0 3663 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success
duke@0 3664 masm.jmp (DONE_LABEL) ;
duke@0 3665 }
duke@0 3666
duke@0 3667 masm.bind (Stacked) ;
duke@0 3668 masm.movq (tmpReg, Address (boxReg, 0)) ; // re-fetch
duke@0 3669 if (os::is_MP()) { masm.lock(); }
duke@0 3670 masm.cmpxchgq(tmpReg, Address(objReg, 0)); // Uses RAX which is box
duke@0 3671
duke@0 3672 if (EmitSync & 65536) {
duke@0 3673 masm.bind (CheckSucc) ;
duke@0 3674 }
duke@0 3675 masm.bind(DONE_LABEL);
duke@0 3676 if (EmitSync & 32768) {
duke@0 3677 masm.nop(); // avoid branch to branch
duke@0 3678 }
duke@0 3679 }
duke@0 3680 %}
duke@0 3681
duke@0 3682 enc_class enc_String_Compare()
duke@0 3683 %{
duke@0 3684 Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL,
duke@0 3685 POP_LABEL, DONE_LABEL, CONT_LABEL,
duke@0 3686 WHILE_HEAD_LABEL;
duke@0 3687 MacroAssembler masm(&cbuf);
duke@0 3688
duke@0 3689 // Get the first character position in both strings
duke@0 3690 // [8] char array, [12] offset, [16] count
duke@0 3691 int value_offset = java_lang_String::value_offset_in_bytes();
duke@0 3692 int offset_offset = java_lang_String::offset_offset_in_bytes();
duke@0 3693 int count_offset = java_lang_String::count_offset_in_bytes();
duke@0 3694 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
duke@0 3695
duke@0 3696 masm.movq(rax, Address(rsi, value_offset));
duke@0 3697 masm.movl(rcx, Address(rsi, offset_offset));
duke@0 3698 masm.leaq(rax, Address(rax, rcx, Address::times_2, base_offset));
duke@0 3699 masm.movq(rbx, Address(rdi, value_offset));
duke@0 3700 masm.movl(rcx, Address(rdi, offset_offset));
duke@0 3701 masm.leaq(rbx, Address(rbx, rcx, Address::times_2, base_offset));
duke@0 3702
duke@0 3703 // Compute the minimum of the string lengths(rsi) and the
duke@0 3704 // difference of the string lengths (stack)
duke@0 3705
duke@0 3706 masm.movl(rdi, Address(rdi, count_offset));
duke@0 3707 masm.movl(rsi, Address(rsi, count_offset));
duke@0 3708 masm.movl(rcx, rdi);
duke@0 3709 masm.subl(rdi, rsi);
duke@0 3710 masm.pushq(rdi);
duke@0 3711 masm.cmovl(Assembler::lessEqual, rsi, rcx);
duke@0 3712
duke@0 3713 // Is the minimum length zero?
duke@0 3714 masm.bind(RCX_GOOD_LABEL);
duke@0 3715 masm.testl(rsi, rsi);
duke@0 3716 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
duke@0 3717
duke@0 3718 // Load first characters
duke@0 3719 masm.load_unsigned_word(rcx, Address(rbx, 0));
duke@0 3720 masm.load_unsigned_word(rdi, Address(rax, 0));
duke@0 3721
duke@0 3722 // Compare first characters
duke@0 3723 masm.subl(rcx, rdi);
duke@0 3724 masm.jcc(Assembler::notZero, POP_LABEL);
duke@0 3725 masm.decrementl(rsi);
duke@0 3726 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
duke@0 3727
duke@0 3728 {
duke@0 3729 // Check after comparing first character to see if strings are equivalent
duke@0 3730 Label LSkip2;
duke@0 3731 // Check if the strings start at same location
duke@0 3732 masm.cmpq(rbx, rax);
duke@0 3733 masm.jcc(Assembler::notEqual, LSkip2);
duke@0 3734
duke@0 3735 // Check if the length difference is zero (from stack)
duke@0 3736 masm.cmpl(Address(rsp, 0), 0x0);
duke@0 3737 masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL);
duke@0 3738
duke@0 3739 // Strings might not be equivalent
duke@0 3740 masm.bind(LSkip2);
duke@0 3741 }
duke@0 3742
duke@0 3743 // Shift RAX and RBX to the end of the arrays, negate min
duke@0 3744 masm.leaq(rax, Address(rax, rsi, Address::times_2, 2));
duke@0 3745 masm.leaq(rbx, Address(rbx, rsi, Address::times_2, 2));
duke@0 3746 masm.negq(rsi);
duke@0 3747
duke@0 3748 // Compare the rest of the characters
duke@0 3749 masm.bind(WHILE_HEAD_LABEL);
duke@0 3750 masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0));
duke@0 3751 masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0));
duke@0 3752 masm.subl(rcx, rdi);
duke@0 3753 masm.jcc(Assembler::notZero, POP_LABEL);
duke@0 3754 masm.incrementq(rsi);
duke@0 3755 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
duke@0 3756
duke@0 3757 // Strings are equal up to min length. Return the length difference.
duke@0 3758 masm.bind(LENGTH_DIFF_LABEL);
duke@0 3759 masm.popq(rcx);
duke@0 3760 masm.jmp(DONE_LABEL);
duke@0 3761
duke@0 3762 // Discard the stored length difference
duke@0 3763 masm.bind(POP_LABEL);
duke@0 3764 masm.addq(rsp, 8);
duke@0 3765
duke@0 3766 // That's it
duke@0 3767 masm.bind(DONE_LABEL);
duke@0 3768 %}
duke@0 3769
duke@0 3770 enc_class enc_rethrow()
duke@0 3771 %{
duke@0 3772 cbuf.set_inst_mark();
duke@0 3773 emit_opcode(cbuf, 0xE9); // jmp entry
duke@0 3774 emit_d32_reloc(cbuf,
duke@0 3775 (int) (OptoRuntime::rethrow_stub() - cbuf.code_end() - 4),
duke@0 3776 runtime_call_Relocation::spec(),
duke@0 3777 RELOC_DISP32);
duke@0 3778 %}
duke@0 3779
duke@0 3780 enc_class absF_encoding(regF dst)
duke@0 3781 %{
duke@0 3782 int dstenc = $dst$$reg;
duke@0 3783 address signmask_address = (address) StubRoutines::amd64::float_sign_mask();
duke@0 3784
duke@0 3785 cbuf.set_inst_mark();
duke@0 3786 if (dstenc >= 8) {
duke@0 3787 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3788 dstenc -= 8;
duke@0 3789 }
duke@0 3790 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 3791 emit_opcode(cbuf, 0x0F);
duke@0 3792 emit_opcode(cbuf, 0x54);
duke@0 3793 emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101
duke@0 3794 emit_d32_reloc(cbuf, signmask_address);
duke@0 3795 %}
duke@0 3796
duke@0 3797 enc_class absD_encoding(regD dst)
duke@0 3798 %{
duke@0 3799 int dstenc = $dst$$reg;
duke@0 3800 address signmask_address = (address) StubRoutines::amd64::double_sign_mask();
duke@0 3801
duke@0 3802 cbuf.set_inst_mark();
duke@0 3803 emit_opcode(cbuf, 0x66);
duke@0 3804 if (dstenc >= 8) {
duke@0 3805 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3806 dstenc -= 8;
duke@0 3807 }
duke@0 3808 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 3809 emit_opcode(cbuf, 0x0F);
duke@0 3810 emit_opcode(cbuf, 0x54);
duke@0 3811 emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101
duke@0 3812 emit_d32_reloc(cbuf, signmask_address);
duke@0 3813 %}
duke@0 3814
duke@0 3815 enc_class negF_encoding(regF dst)
duke@0 3816 %{
duke@0 3817 int dstenc = $dst$$reg;
duke@0 3818 address signflip_address = (address) StubRoutines::amd64::float_sign_flip();
duke@0 3819
duke@0 3820 cbuf.set_inst_mark();
duke@0 3821 if (dstenc >= 8) {
duke@0 3822 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3823 dstenc -= 8;
duke@0 3824 }
duke@0 3825 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 3826 emit_opcode(cbuf, 0x0F);
duke@0 3827 emit_opcode(cbuf, 0x57);
duke@0 3828 emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101
duke@0 3829 emit_d32_reloc(cbuf, signflip_address);
duke@0 3830 %}
duke@0 3831
duke@0 3832 enc_class negD_encoding(regD dst)
duke@0 3833 %{
duke@0 3834 int dstenc = $dst$$reg;
duke@0 3835 address signflip_address = (address) StubRoutines::amd64::double_sign_flip();
duke@0 3836
duke@0 3837 cbuf.set_inst_mark();
duke@0 3838 emit_opcode(cbuf, 0x66);
duke@0 3839 if (dstenc >= 8) {
duke@0 3840 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3841 dstenc -= 8;
duke@0 3842 }
duke@0 3843 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 3844 emit_opcode(cbuf, 0x0F);
duke@0 3845 emit_opcode(cbuf, 0x57);
duke@0 3846 emit_rm(cbuf, 0x0, dstenc, 0x5); // 00 reg 101
duke@0 3847 emit_d32_reloc(cbuf, signflip_address);
duke@0 3848 %}
duke@0 3849
duke@0 3850 enc_class f2i_fixup(rRegI dst, regF src)
duke@0 3851 %{
duke@0 3852 int dstenc = $dst$$reg;
duke@0 3853 int srcenc = $src$$reg;
duke@0 3854
duke@0 3855 // cmpl $dst, #0x80000000
duke@0 3856 if (dstenc >= 8) {
duke@0 3857 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3858 }
duke@0 3859 emit_opcode(cbuf, 0x81);
duke@0 3860 emit_rm(cbuf, 0x3, 0x7, dstenc & 7);
duke@0 3861 emit_d32(cbuf, 0x80000000);
duke@0 3862
duke@0 3863 // jne,s done
duke@0 3864 emit_opcode(cbuf, 0x75);
duke@0 3865 if (srcenc < 8 && dstenc < 8) {
duke@0 3866 emit_d8(cbuf, 0xF);
duke@0 3867 } else if (srcenc >= 8 && dstenc >= 8) {
duke@0 3868 emit_d8(cbuf, 0x11);
duke@0 3869 } else {
duke@0 3870 emit_d8(cbuf, 0x10);
duke@0 3871 }
duke@0 3872
duke@0 3873 // subq rsp, #8
duke@0 3874 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3875 emit_opcode(cbuf, 0x83);
duke@0 3876 emit_rm(cbuf, 0x3, 0x5, RSP_enc);
duke@0 3877 emit_d8(cbuf, 8);
duke@0 3878
duke@0 3879 // movss [rsp], $src
duke@0 3880 emit_opcode(cbuf, 0xF3);
duke@0 3881 if (srcenc >= 8) {
duke@0 3882 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3883 }
duke@0 3884 emit_opcode(cbuf, 0x0F);
duke@0 3885 emit_opcode(cbuf, 0x11);
duke@0 3886 encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes
duke@0 3887
duke@0 3888 // call f2i_fixup
duke@0 3889 cbuf.set_inst_mark();
duke@0 3890 emit_opcode(cbuf, 0xE8);
duke@0 3891 emit_d32_reloc(cbuf,
duke@0 3892 (int)
duke@0 3893 (StubRoutines::amd64::f2i_fixup() - cbuf.code_end() - 4),
duke@0 3894 runtime_call_Relocation::spec(),
duke@0 3895 RELOC_DISP32);
duke@0 3896
duke@0 3897 // popq $dst
duke@0 3898 if (dstenc >= 8) {
duke@0 3899 emit_opcode(cbuf, Assembler::REX_B);
duke@0 3900 }
duke@0 3901 emit_opcode(cbuf, 0x58 | (dstenc & 7));
duke@0 3902
duke@0 3903 // done:
duke@0 3904 %}
duke@0 3905
duke@0 3906 enc_class f2l_fixup(rRegL dst, regF src)
duke@0 3907 %{
duke@0 3908 int dstenc = $dst$$reg;
duke@0 3909 int srcenc = $src$$reg;
duke@0 3910 address const_address = (address) StubRoutines::amd64::double_sign_flip();
duke@0 3911
duke@0 3912 // cmpq $dst, [0x8000000000000000]
duke@0 3913 cbuf.set_inst_mark();
duke@0 3914 emit_opcode(cbuf, dstenc < 8 ? Assembler::REX_W : Assembler::REX_WR);
duke@0 3915 emit_opcode(cbuf, 0x39);
duke@0 3916 // XXX reg_mem doesn't support RIP-relative addressing yet
duke@0 3917 emit_rm(cbuf, 0x0, dstenc & 7, 0x5); // 00 reg 101
duke@0 3918 emit_d32_reloc(cbuf, const_address);
duke@0 3919
duke@0 3920
duke@0 3921 // jne,s done
duke@0 3922 emit_opcode(cbuf, 0x75);
duke@0 3923 if (srcenc < 8 && dstenc < 8) {
duke@0 3924 emit_d8(cbuf, 0xF);
duke@0 3925 } else if (srcenc >= 8 && dstenc >= 8) {
duke@0 3926 emit_d8(cbuf, 0x11);
duke@0 3927 } else {
duke@0 3928 emit_d8(cbuf, 0x10);
duke@0 3929 }
duke@0 3930
duke@0 3931 // subq rsp, #8
duke@0 3932 emit_opcode(cbuf, Assembler::REX_W);
duke@0 3933 emit_opcode(cbuf, 0x83);
duke@0 3934 emit_rm(cbuf, 0x3, 0x5, RSP_enc);
duke@0 3935 emit_d8(cbuf, 8);
duke@0 3936
duke@0 3937 // movss [rsp], $src
duke@0 3938 emit_opcode(cbuf, 0xF3);
duke@0 3939 if (srcenc >= 8) {
duke@0 3940 emit_opcode(cbuf, Assembler::REX_R);
duke@0 3941 }
duke@0 3942 emit_opcode(cbuf, 0x0F);
duke@0 3943 emit_opcode(cbuf, 0x11);
duke@0 3944 encode_RegMem(cbuf, srcenc, RSP_enc, 0x4, 0, 0, false); // 2 bytes
duke@0 3945
duke@0 3946 // call f2l_fixup