1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,2254 @@ 1.4 +/* 1.5 + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +class BiasedLockingCounters; 1.29 + 1.30 +// <sys/trap.h> promises that the system will not use traps 16-31 1.31 +#define ST_RESERVED_FOR_USER_0 0x10 1.32 + 1.33 +/* Written: David Ungar 4/19/97 */ 1.34 + 1.35 +// Contains all the definitions needed for sparc assembly code generation. 1.36 + 1.37 +// Register aliases for parts of the system: 1.38 + 1.39 +// 64 bit values can be kept in g1-g5, o1-o5 and o7 and all 64 bits are safe 1.40 +// across context switches in V8+ ABI. Of course, there are no 64 bit regs 1.41 +// in V8 ABI. All 64 bits are preserved in V9 ABI for all registers. 1.42 + 1.43 +// g2-g4 are scratch registers called "application globals". Their 1.44 +// meaning is reserved to the "compilation system"--which means us! 1.45 +// They are are not supposed to be touched by ordinary C code, although 1.46 +// highly-optimized C code might steal them for temps. They are safe 1.47 +// across thread switches, and the ABI requires that they be safe 1.48 +// across function calls. 1.49 +// 1.50 +// g1 and g3 are touched by more modules. V8 allows g1 to be clobbered 1.51 +// across func calls, and V8+ also allows g5 to be clobbered across 1.52 +// func calls. Also, g1 and g5 can get touched while doing shared 1.53 +// library loading. 1.54 +// 1.55 +// We must not touch g7 (it is the thread-self register) and g6 is 1.56 +// reserved for certain tools. g0, of course, is always zero. 1.57 +// 1.58 +// (Sources: SunSoft Compilers Group, thread library engineers.) 1.59 + 1.60 +// %%%% The interpreter should be revisited to reduce global scratch regs. 1.61 + 1.62 +// This global always holds the current JavaThread pointer: 1.63 + 1.64 +REGISTER_DECLARATION(Register, G2_thread , G2); 1.65 + 1.66 +// The following globals are part of the Java calling convention: 1.67 + 1.68 +REGISTER_DECLARATION(Register, G5_method , G5); 1.69 +REGISTER_DECLARATION(Register, G5_megamorphic_method , G5_method); 1.70 +REGISTER_DECLARATION(Register, G5_inline_cache_reg , G5_method); 1.71 + 1.72 +// The following globals are used for the new C1 & interpreter calling convention: 1.73 +REGISTER_DECLARATION(Register, Gargs , G4); // pointing to the last argument 1.74 + 1.75 +// This local is used to preserve G2_thread in the interpreter and in stubs: 1.76 +REGISTER_DECLARATION(Register, L7_thread_cache , L7); 1.77 + 1.78 +// These globals are used as scratch registers in the interpreter: 1.79 + 1.80 +REGISTER_DECLARATION(Register, Gframe_size , G1); // SAME REG as G1_scratch 1.81 +REGISTER_DECLARATION(Register, G1_scratch , G1); // also SAME 1.82 +REGISTER_DECLARATION(Register, G3_scratch , G3); 1.83 +REGISTER_DECLARATION(Register, G4_scratch , G4); 1.84 + 1.85 +// These globals are used as short-lived scratch registers in the compiler: 1.86 + 1.87 +REGISTER_DECLARATION(Register, Gtemp , G5); 1.88 + 1.89 +// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, 1.90 +// because a single patchable "set" instruction (NativeMovConstReg, 1.91 +// or NativeMovConstPatching for compiler1) instruction 1.92 +// serves to set up either quantity, depending on whether the compiled 1.93 +// call site is an inline cache or is megamorphic. See the function 1.94 +// CompiledIC::set_to_megamorphic. 1.95 +// 1.96 +// On the other hand, G5_inline_cache_klass must differ from G5_method, 1.97 +// because both registers are needed for an inline cache that calls 1.98 +// an interpreted method. 1.99 +// 1.100 +// Note that G5_method is only the method-self for the interpreter, 1.101 +// and is logically unrelated to G5_megamorphic_method. 1.102 +// 1.103 +// Invariants on G2_thread (the JavaThread pointer): 1.104 +// - it should not be used for any other purpose anywhere 1.105 +// - it must be re-initialized by StubRoutines::call_stub() 1.106 +// - it must be preserved around every use of call_VM 1.107 + 1.108 +// We can consider using g2/g3/g4 to cache more values than the 1.109 +// JavaThread, such as the card-marking base or perhaps pointers into 1.110 +// Eden. It's something of a waste to use them as scratch temporaries, 1.111 +// since they are not supposed to be volatile. (Of course, if we find 1.112 +// that Java doesn't benefit from application globals, then we can just 1.113 +// use them as ordinary temporaries.) 1.114 +// 1.115 +// Since g1 and g5 (and/or g6) are the volatile (caller-save) registers, 1.116 +// it makes sense to use them routinely for procedure linkage, 1.117 +// whenever the On registers are not applicable. Examples: G5_method, 1.118 +// G5_inline_cache_klass, and a double handful of miscellaneous compiler 1.119 +// stubs. This means that compiler stubs, etc., should be kept to a 1.120 +// maximum of two or three G-register arguments. 1.121 + 1.122 + 1.123 +// stub frames 1.124 + 1.125 +REGISTER_DECLARATION(Register, Lentry_args , L0); // pointer to args passed to callee (interpreter) not stub itself 1.126 + 1.127 +// Interpreter frames 1.128 + 1.129 +#ifdef CC_INTERP 1.130 +REGISTER_DECLARATION(Register, Lstate , L0); // interpreter state object pointer 1.131 +REGISTER_DECLARATION(Register, L1_scratch , L1); // scratch 1.132 +REGISTER_DECLARATION(Register, Lmirror , L1); // mirror (for native methods only) 1.133 +REGISTER_DECLARATION(Register, L2_scratch , L2); 1.134 +REGISTER_DECLARATION(Register, L3_scratch , L3); 1.135 +REGISTER_DECLARATION(Register, L4_scratch , L4); 1.136 +REGISTER_DECLARATION(Register, Lscratch , L5); // C1 uses 1.137 +REGISTER_DECLARATION(Register, Lscratch2 , L6); // C1 uses 1.138 +REGISTER_DECLARATION(Register, L7_scratch , L7); // constant pool cache 1.139 +REGISTER_DECLARATION(Register, O5_savedSP , O5); 1.140 +REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply 1.141 + // a copy SP, so in 64-bit it's a biased value. The bias 1.142 + // is added and removed as needed in the frame code. 1.143 +// Interface to signature handler 1.144 +REGISTER_DECLARATION(Register, Llocals , L7); // pointer to locals for signature handler 1.145 +REGISTER_DECLARATION(Register, Lmethod , L6); // methodOop when calling signature handler 1.146 + 1.147 +#else 1.148 +REGISTER_DECLARATION(Register, Lesp , L0); // expression stack pointer 1.149 +REGISTER_DECLARATION(Register, Lbcp , L1); // pointer to next bytecode 1.150 +REGISTER_DECLARATION(Register, Lmethod , L2); 1.151 +REGISTER_DECLARATION(Register, Llocals , L3); 1.152 +REGISTER_DECLARATION(Register, Largs , L3); // pointer to locals for signature handler 1.153 + // must match Llocals in asm interpreter 1.154 +REGISTER_DECLARATION(Register, Lmonitors , L4); 1.155 +REGISTER_DECLARATION(Register, Lbyte_code , L5); 1.156 +// When calling out from the interpreter we record SP so that we can remove any extra stack 1.157 +// space allocated during adapter transitions. This register is only live from the point 1.158 +// of the call until we return. 1.159 +REGISTER_DECLARATION(Register, Llast_SP , L5); 1.160 +REGISTER_DECLARATION(Register, Lscratch , L5); 1.161 +REGISTER_DECLARATION(Register, Lscratch2 , L6); 1.162 +REGISTER_DECLARATION(Register, LcpoolCache , L6); // constant pool cache 1.163 + 1.164 +REGISTER_DECLARATION(Register, O5_savedSP , O5); 1.165 +REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply 1.166 + // a copy SP, so in 64-bit it's a biased value. The bias 1.167 + // is added and removed as needed in the frame code. 1.168 +REGISTER_DECLARATION(Register, IdispatchTables , I4); // Base address of the bytecode dispatch tables 1.169 +REGISTER_DECLARATION(Register, IdispatchAddress , I3); // Register which saves the dispatch address for each bytecode 1.170 +REGISTER_DECLARATION(Register, ImethodDataPtr , I2); // Pointer to the current method data 1.171 +#endif /* CC_INTERP */ 1.172 + 1.173 +// NOTE: Lscratch2 and LcpoolCache point to the same registers in 1.174 +// the interpreter code. If Lscratch2 needs to be used for some 1.175 +// purpose than LcpoolCache should be restore after that for 1.176 +// the interpreter to work right 1.177 +// (These assignments must be compatible with L7_thread_cache; see above.) 1.178 + 1.179 +// Since Lbcp points into the middle of the method object, 1.180 +// it is temporarily converted into a "bcx" during GC. 1.181 + 1.182 +// Exception processing 1.183 +// These registers are passed into exception handlers. 1.184 +// All exception handlers require the exception object being thrown. 1.185 +// In addition, an nmethod's exception handler must be passed 1.186 +// the address of the call site within the nmethod, to allow 1.187 +// proper selection of the applicable catch block. 1.188 +// (Interpreter frames use their own bcp() for this purpose.) 1.189 +// 1.190 +// The Oissuing_pc value is not always needed. When jumping to a 1.191 +// handler that is known to be interpreted, the Oissuing_pc value can be 1.192 +// omitted. An actual catch block in compiled code receives (from its 1.193 +// nmethod's exception handler) the thrown exception in the Oexception, 1.194 +// but it doesn't need the Oissuing_pc. 1.195 +// 1.196 +// If an exception handler (either interpreted or compiled) 1.197 +// discovers there is no applicable catch block, it updates 1.198 +// the Oissuing_pc to the continuation PC of its own caller, 1.199 +// pops back to that caller's stack frame, and executes that 1.200 +// caller's exception handler. Obviously, this process will 1.201 +// iterate until the control stack is popped back to a method 1.202 +// containing an applicable catch block. A key invariant is 1.203 +// that the Oissuing_pc value is always a value local to 1.204 +// the method whose exception handler is currently executing. 1.205 +// 1.206 +// Note: The issuing PC value is __not__ a raw return address (I7 value). 1.207 +// It is a "return pc", the address __following__ the call. 1.208 +// Raw return addresses are converted to issuing PCs by frame::pc(), 1.209 +// or by stubs. Issuing PCs can be used directly with PC range tables. 1.210 +// 1.211 +REGISTER_DECLARATION(Register, Oexception , O0); // exception being thrown 1.212 +REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is coming from 1.213 + 1.214 + 1.215 +// These must occur after the declarations above 1.216 +#ifndef DONT_USE_REGISTER_DEFINES 1.217 + 1.218 +#define Gthread AS_REGISTER(Register, Gthread) 1.219 +#define Gmethod AS_REGISTER(Register, Gmethod) 1.220 +#define Gmegamorphic_method AS_REGISTER(Register, Gmegamorphic_method) 1.221 +#define Ginline_cache_reg AS_REGISTER(Register, Ginline_cache_reg) 1.222 +#define Gargs AS_REGISTER(Register, Gargs) 1.223 +#define Lthread_cache AS_REGISTER(Register, Lthread_cache) 1.224 +#define Gframe_size AS_REGISTER(Register, Gframe_size) 1.225 +#define Gtemp AS_REGISTER(Register, Gtemp) 1.226 + 1.227 +#ifdef CC_INTERP 1.228 +#define Lstate AS_REGISTER(Register, Lstate) 1.229 +#define Lesp AS_REGISTER(Register, Lesp) 1.230 +#define L1_scratch AS_REGISTER(Register, L1_scratch) 1.231 +#define Lmirror AS_REGISTER(Register, Lmirror) 1.232 +#define L2_scratch AS_REGISTER(Register, L2_scratch) 1.233 +#define L3_scratch AS_REGISTER(Register, L3_scratch) 1.234 +#define L4_scratch AS_REGISTER(Register, L4_scratch) 1.235 +#define Lscratch AS_REGISTER(Register, Lscratch) 1.236 +#define Lscratch2 AS_REGISTER(Register, Lscratch2) 1.237 +#define L7_scratch AS_REGISTER(Register, L7_scratch) 1.238 +#define Ostate AS_REGISTER(Register, Ostate) 1.239 +#else 1.240 +#define Lesp AS_REGISTER(Register, Lesp) 1.241 +#define Lbcp AS_REGISTER(Register, Lbcp) 1.242 +#define Lmethod AS_REGISTER(Register, Lmethod) 1.243 +#define Llocals AS_REGISTER(Register, Llocals) 1.244 +#define Lmonitors AS_REGISTER(Register, Lmonitors) 1.245 +#define Lbyte_code AS_REGISTER(Register, Lbyte_code) 1.246 +#define Lscratch AS_REGISTER(Register, Lscratch) 1.247 +#define Lscratch2 AS_REGISTER(Register, Lscratch2) 1.248 +#define LcpoolCache AS_REGISTER(Register, LcpoolCache) 1.249 +#endif /* ! CC_INTERP */ 1.250 + 1.251 +#define Lentry_args AS_REGISTER(Register, Lentry_args) 1.252 +#define I5_savedSP AS_REGISTER(Register, I5_savedSP) 1.253 +#define O5_savedSP AS_REGISTER(Register, O5_savedSP) 1.254 +#define IdispatchAddress AS_REGISTER(Register, IdispatchAddress) 1.255 +#define ImethodDataPtr AS_REGISTER(Register, ImethodDataPtr) 1.256 +#define IdispatchTables AS_REGISTER(Register, IdispatchTables) 1.257 + 1.258 +#define Oexception AS_REGISTER(Register, Oexception) 1.259 +#define Oissuing_pc AS_REGISTER(Register, Oissuing_pc) 1.260 + 1.261 + 1.262 +#endif 1.263 + 1.264 +// Address is an abstraction used to represent a memory location. 1.265 +// 1.266 +// Note: A register location is represented via a Register, not 1.267 +// via an address for efficiency & simplicity reasons. 1.268 + 1.269 +class Address VALUE_OBJ_CLASS_SPEC { 1.270 + private: 1.271 + Register _base; 1.272 +#ifdef _LP64 1.273 + int _hi32; // bits 63::32 1.274 + int _low32; // bits 31::0 1.275 +#endif 1.276 + int _hi; 1.277 + int _disp; 1.278 + RelocationHolder _rspec; 1.279 + 1.280 + RelocationHolder rspec_from_rtype(relocInfo::relocType rt, address a = NULL) { 1.281 + switch (rt) { 1.282 + case relocInfo::external_word_type: 1.283 + return external_word_Relocation::spec(a); 1.284 + case relocInfo::internal_word_type: 1.285 + return internal_word_Relocation::spec(a); 1.286 +#ifdef _LP64 1.287 + case relocInfo::opt_virtual_call_type: 1.288 + return opt_virtual_call_Relocation::spec(); 1.289 + case relocInfo::static_call_type: 1.290 + return static_call_Relocation::spec(); 1.291 + case relocInfo::runtime_call_type: 1.292 + return runtime_call_Relocation::spec(); 1.293 +#endif 1.294 + case relocInfo::none: 1.295 + return RelocationHolder(); 1.296 + default: 1.297 + ShouldNotReachHere(); 1.298 + return RelocationHolder(); 1.299 + } 1.300 + } 1.301 + 1.302 + public: 1.303 + Address(Register b, address a, relocInfo::relocType rt = relocInfo::none) 1.304 + : _rspec(rspec_from_rtype(rt, a)) 1.305 + { 1.306 + _base = b; 1.307 +#ifdef _LP64 1.308 + _hi32 = (intptr_t)a >> 32; // top 32 bits in 64 bit word 1.309 + _low32 = (intptr_t)a & ~0; // low 32 bits in 64 bit word 1.310 +#endif 1.311 + _hi = (intptr_t)a & ~0x3ff; // top 22 bits in low word 1.312 + _disp = (intptr_t)a & 0x3ff; // bottom 10 bits 1.313 + } 1.314 + 1.315 + Address(Register b, address a, RelocationHolder const& rspec) 1.316 + : _rspec(rspec) 1.317 + { 1.318 + _base = b; 1.319 +#ifdef _LP64 1.320 + _hi32 = (intptr_t)a >> 32; // top 32 bits in 64 bit word 1.321 + _low32 = (intptr_t)a & ~0; // low 32 bits in 64 bit word 1.322 +#endif 1.323 + _hi = (intptr_t)a & ~0x3ff; // top 22 bits 1.324 + _disp = (intptr_t)a & 0x3ff; // bottom 10 bits 1.325 + } 1.326 + 1.327 + Address(Register b, intptr_t h, intptr_t d, RelocationHolder const& rspec = RelocationHolder()) 1.328 + : _rspec(rspec) 1.329 + { 1.330 + _base = b; 1.331 +#ifdef _LP64 1.332 +// [RGV] Put in Assert to force me to check usage of this constructor 1.333 + assert( h == 0, "Check usage of this constructor" ); 1.334 + _hi32 = h; 1.335 + _low32 = d; 1.336 + _hi = h; 1.337 + _disp = d; 1.338 +#else 1.339 + _hi = h; 1.340 + _disp = d; 1.341 +#endif 1.342 + } 1.343 + 1.344 + Address() 1.345 + : _rspec(RelocationHolder()) 1.346 + { 1.347 + _base = G0; 1.348 +#ifdef _LP64 1.349 + _hi32 = 0; 1.350 + _low32 = 0; 1.351 +#endif 1.352 + _hi = 0; 1.353 + _disp = 0; 1.354 + } 1.355 + 1.356 + // fancier constructors 1.357 + 1.358 + enum addr_type { 1.359 + extra_in_argument, // in the In registers 1.360 + extra_out_argument // in the Outs 1.361 + }; 1.362 + 1.363 + Address( addr_type, int ); 1.364 + 1.365 + // accessors 1.366 + 1.367 + Register base() const { return _base; } 1.368 +#ifdef _LP64 1.369 + int hi32() const { return _hi32; } 1.370 + int low32() const { return _low32; } 1.371 +#endif 1.372 + int hi() const { return _hi; } 1.373 + int disp() const { return _disp; } 1.374 +#ifdef _LP64 1.375 + intptr_t value() const { return ((intptr_t)_hi32 << 32) | 1.376 + (intptr_t)(uint32_t)_low32; } 1.377 +#else 1.378 + int value() const { return _hi | _disp; } 1.379 +#endif 1.380 + const relocInfo::relocType rtype() { return _rspec.type(); } 1.381 + const RelocationHolder& rspec() { return _rspec; } 1.382 + 1.383 + RelocationHolder rspec(int offset) const { 1.384 + return offset == 0 ? _rspec : _rspec.plus(offset); 1.385 + } 1.386 + 1.387 + inline bool is_simm13(int offset = 0); // check disp+offset for overflow 1.388 + 1.389 + Address split_disp() const { // deal with disp overflow 1.390 + Address a = (*this); 1.391 + int hi_disp = _disp & ~0x3ff; 1.392 + if (hi_disp != 0) { 1.393 + a._disp -= hi_disp; 1.394 + a._hi += hi_disp; 1.395 + } 1.396 + return a; 1.397 + } 1.398 + 1.399 + Address after_save() const { 1.400 + Address a = (*this); 1.401 + a._base = a._base->after_save(); 1.402 + return a; 1.403 + } 1.404 + 1.405 + Address after_restore() const { 1.406 + Address a = (*this); 1.407 + a._base = a._base->after_restore(); 1.408 + return a; 1.409 + } 1.410 + 1.411 + friend class Assembler; 1.412 +}; 1.413 + 1.414 + 1.415 +inline Address RegisterImpl::address_in_saved_window() const { 1.416 + return (Address(SP, 0, (sp_offset_in_saved_window() * wordSize) + STACK_BIAS)); 1.417 +} 1.418 + 1.419 + 1.420 + 1.421 +// Argument is an abstraction used to represent an outgoing 1.422 +// actual argument or an incoming formal parameter, whether 1.423 +// it resides in memory or in a register, in a manner consistent 1.424 +// with the SPARC Application Binary Interface, or ABI. This is 1.425 +// often referred to as the native or C calling convention. 1.426 + 1.427 +class Argument VALUE_OBJ_CLASS_SPEC { 1.428 + private: 1.429 + int _number; 1.430 + bool _is_in; 1.431 + 1.432 + public: 1.433 +#ifdef _LP64 1.434 + enum { 1.435 + n_register_parameters = 6, // only 6 registers may contain integer parameters 1.436 + n_float_register_parameters = 16 // Can have up to 16 floating registers 1.437 + }; 1.438 +#else 1.439 + enum { 1.440 + n_register_parameters = 6 // only 6 registers may contain integer parameters 1.441 + }; 1.442 +#endif 1.443 + 1.444 + // creation 1.445 + Argument(int number, bool is_in) : _number(number), _is_in(is_in) {} 1.446 + 1.447 + int number() const { return _number; } 1.448 + bool is_in() const { return _is_in; } 1.449 + bool is_out() const { return !is_in(); } 1.450 + 1.451 + Argument successor() const { return Argument(number() + 1, is_in()); } 1.452 + Argument as_in() const { return Argument(number(), true ); } 1.453 + Argument as_out() const { return Argument(number(), false); } 1.454 + 1.455 + // locating register-based arguments: 1.456 + bool is_register() const { return _number < n_register_parameters; } 1.457 + 1.458 +#ifdef _LP64 1.459 + // locating Floating Point register-based arguments: 1.460 + bool is_float_register() const { return _number < n_float_register_parameters; } 1.461 + 1.462 + FloatRegister as_float_register() const { 1.463 + assert(is_float_register(), "must be a register argument"); 1.464 + return as_FloatRegister(( number() *2 ) + 1); 1.465 + } 1.466 + FloatRegister as_double_register() const { 1.467 + assert(is_float_register(), "must be a register argument"); 1.468 + return as_FloatRegister(( number() *2 )); 1.469 + } 1.470 +#endif 1.471 + 1.472 + Register as_register() const { 1.473 + assert(is_register(), "must be a register argument"); 1.474 + return is_in() ? as_iRegister(number()) : as_oRegister(number()); 1.475 + } 1.476 + 1.477 + // locating memory-based arguments 1.478 + Address as_address() const { 1.479 + assert(!is_register(), "must be a memory argument"); 1.480 + return address_in_frame(); 1.481 + } 1.482 + 1.483 + // When applied to a register-based argument, give the corresponding address 1.484 + // into the 6-word area "into which callee may store register arguments" 1.485 + // (This is a different place than the corresponding register-save area location.) 1.486 + Address address_in_frame() const { 1.487 + return Address( is_in() ? Address::extra_in_argument 1.488 + : Address::extra_out_argument, 1.489 + _number ); 1.490 + } 1.491 + 1.492 + // debugging 1.493 + const char* name() const; 1.494 + 1.495 + friend class Assembler; 1.496 +}; 1.497 + 1.498 + 1.499 +// The SPARC Assembler: Pure assembler doing NO optimizations on the instruction 1.500 +// level; i.e., what you write 1.501 +// is what you get. The Assembler is generating code into a CodeBuffer. 1.502 + 1.503 +class Assembler : public AbstractAssembler { 1.504 + protected: 1.505 + 1.506 + static void print_instruction(int inst); 1.507 + static int patched_branch(int dest_pos, int inst, int inst_pos); 1.508 + static int branch_destination(int inst, int pos); 1.509 + 1.510 + 1.511 + friend class AbstractAssembler; 1.512 + 1.513 + // code patchers need various routines like inv_wdisp() 1.514 + friend class NativeInstruction; 1.515 + friend class NativeGeneralJump; 1.516 + friend class Relocation; 1.517 + friend class Label; 1.518 + 1.519 + public: 1.520 + // op carries format info; see page 62 & 267 1.521 + 1.522 + enum ops { 1.523 + call_op = 1, // fmt 1 1.524 + branch_op = 0, // also sethi (fmt2) 1.525 + arith_op = 2, // fmt 3, arith & misc 1.526 + ldst_op = 3 // fmt 3, load/store 1.527 + }; 1.528 + 1.529 + enum op2s { 1.530 + bpr_op2 = 3, 1.531 + fb_op2 = 6, 1.532 + fbp_op2 = 5, 1.533 + br_op2 = 2, 1.534 + bp_op2 = 1, 1.535 + cb_op2 = 7, // V8 1.536 + sethi_op2 = 4 1.537 + }; 1.538 + 1.539 + enum op3s { 1.540 + // selected op3s 1.541 + add_op3 = 0x00, 1.542 + and_op3 = 0x01, 1.543 + or_op3 = 0x02, 1.544 + xor_op3 = 0x03, 1.545 + sub_op3 = 0x04, 1.546 + andn_op3 = 0x05, 1.547 + orn_op3 = 0x06, 1.548 + xnor_op3 = 0x07, 1.549 + addc_op3 = 0x08, 1.550 + mulx_op3 = 0x09, 1.551 + umul_op3 = 0x0a, 1.552 + smul_op3 = 0x0b, 1.553 + subc_op3 = 0x0c, 1.554 + udivx_op3 = 0x0d, 1.555 + udiv_op3 = 0x0e, 1.556 + sdiv_op3 = 0x0f, 1.557 + 1.558 + addcc_op3 = 0x10, 1.559 + andcc_op3 = 0x11, 1.560 + orcc_op3 = 0x12, 1.561 + xorcc_op3 = 0x13, 1.562 + subcc_op3 = 0x14, 1.563 + andncc_op3 = 0x15, 1.564 + orncc_op3 = 0x16, 1.565 + xnorcc_op3 = 0x17, 1.566 + addccc_op3 = 0x18, 1.567 + umulcc_op3 = 0x1a, 1.568 + smulcc_op3 = 0x1b, 1.569 + subccc_op3 = 0x1c, 1.570 + udivcc_op3 = 0x1e, 1.571 + sdivcc_op3 = 0x1f, 1.572 + 1.573 + taddcc_op3 = 0x20, 1.574 + tsubcc_op3 = 0x21, 1.575 + taddcctv_op3 = 0x22, 1.576 + tsubcctv_op3 = 0x23, 1.577 + mulscc_op3 = 0x24, 1.578 + sll_op3 = 0x25, 1.579 + sllx_op3 = 0x25, 1.580 + srl_op3 = 0x26, 1.581 + srlx_op3 = 0x26, 1.582 + sra_op3 = 0x27, 1.583 + srax_op3 = 0x27, 1.584 + rdreg_op3 = 0x28, 1.585 + membar_op3 = 0x28, 1.586 + 1.587 + flushw_op3 = 0x2b, 1.588 + movcc_op3 = 0x2c, 1.589 + sdivx_op3 = 0x2d, 1.590 + popc_op3 = 0x2e, 1.591 + movr_op3 = 0x2f, 1.592 + 1.593 + sir_op3 = 0x30, 1.594 + wrreg_op3 = 0x30, 1.595 + saved_op3 = 0x31, 1.596 + 1.597 + fpop1_op3 = 0x34, 1.598 + fpop2_op3 = 0x35, 1.599 + impdep1_op3 = 0x36, 1.600 + impdep2_op3 = 0x37, 1.601 + jmpl_op3 = 0x38, 1.602 + rett_op3 = 0x39, 1.603 + trap_op3 = 0x3a, 1.604 + flush_op3 = 0x3b, 1.605 + save_op3 = 0x3c, 1.606 + restore_op3 = 0x3d, 1.607 + done_op3 = 0x3e, 1.608 + retry_op3 = 0x3e, 1.609 + 1.610 + lduw_op3 = 0x00, 1.611 + ldub_op3 = 0x01, 1.612 + lduh_op3 = 0x02, 1.613 + ldd_op3 = 0x03, 1.614 + stw_op3 = 0x04, 1.615 + stb_op3 = 0x05, 1.616 + sth_op3 = 0x06, 1.617 + std_op3 = 0x07, 1.618 + ldsw_op3 = 0x08, 1.619 + ldsb_op3 = 0x09, 1.620 + ldsh_op3 = 0x0a, 1.621 + ldx_op3 = 0x0b, 1.622 + 1.623 + ldstub_op3 = 0x0d, 1.624 + stx_op3 = 0x0e, 1.625 + swap_op3 = 0x0f, 1.626 + 1.627 + lduwa_op3 = 0x10, 1.628 + ldxa_op3 = 0x1b, 1.629 + 1.630 + stwa_op3 = 0x14, 1.631 + stxa_op3 = 0x1e, 1.632 + 1.633 + ldf_op3 = 0x20, 1.634 + ldfsr_op3 = 0x21, 1.635 + ldqf_op3 = 0x22, 1.636 + lddf_op3 = 0x23, 1.637 + stf_op3 = 0x24, 1.638 + stfsr_op3 = 0x25, 1.639 + stqf_op3 = 0x26, 1.640 + stdf_op3 = 0x27, 1.641 + 1.642 + prefetch_op3 = 0x2d, 1.643 + 1.644 + 1.645 + ldc_op3 = 0x30, 1.646 + ldcsr_op3 = 0x31, 1.647 + lddc_op3 = 0x33, 1.648 + stc_op3 = 0x34, 1.649 + stcsr_op3 = 0x35, 1.650 + stdcq_op3 = 0x36, 1.651 + stdc_op3 = 0x37, 1.652 + 1.653 + casa_op3 = 0x3c, 1.654 + casxa_op3 = 0x3e, 1.655 + 1.656 + alt_bit_op3 = 0x10, 1.657 + cc_bit_op3 = 0x10 1.658 + }; 1.659 + 1.660 + enum opfs { 1.661 + // selected opfs 1.662 + fmovs_opf = 0x01, 1.663 + fmovd_opf = 0x02, 1.664 + 1.665 + fnegs_opf = 0x05, 1.666 + fnegd_opf = 0x06, 1.667 + 1.668 + fadds_opf = 0x41, 1.669 + faddd_opf = 0x42, 1.670 + fsubs_opf = 0x45, 1.671 + fsubd_opf = 0x46, 1.672 + 1.673 + fmuls_opf = 0x49, 1.674 + fmuld_opf = 0x4a, 1.675 + fdivs_opf = 0x4d, 1.676 + fdivd_opf = 0x4e, 1.677 + 1.678 + fcmps_opf = 0x51, 1.679 + fcmpd_opf = 0x52, 1.680 + 1.681 + fstox_opf = 0x81, 1.682 + fdtox_opf = 0x82, 1.683 + fxtos_opf = 0x84, 1.684 + fxtod_opf = 0x88, 1.685 + fitos_opf = 0xc4, 1.686 + fdtos_opf = 0xc6, 1.687 + fitod_opf = 0xc8, 1.688 + fstod_opf = 0xc9, 1.689 + fstoi_opf = 0xd1, 1.690 + fdtoi_opf = 0xd2 1.691 + }; 1.692 + 1.693 + enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7 }; 1.694 + 1.695 + enum Condition { 1.696 + // for FBfcc & FBPfcc instruction 1.697 + f_never = 0, 1.698 + f_notEqual = 1, 1.699 + f_notZero = 1, 1.700 + f_lessOrGreater = 2, 1.701 + f_unorderedOrLess = 3, 1.702 + f_less = 4, 1.703 + f_unorderedOrGreater = 5, 1.704 + f_greater = 6, 1.705 + f_unordered = 7, 1.706 + f_always = 8, 1.707 + f_equal = 9, 1.708 + f_zero = 9, 1.709 + f_unorderedOrEqual = 10, 1.710 + f_greaterOrEqual = 11, 1.711 + f_unorderedOrGreaterOrEqual = 12, 1.712 + f_lessOrEqual = 13, 1.713 + f_unorderedOrLessOrEqual = 14, 1.714 + f_ordered = 15, 1.715 + 1.716 + // V8 coproc, pp 123 v8 manual 1.717 + 1.718 + cp_always = 8, 1.719 + cp_never = 0, 1.720 + cp_3 = 7, 1.721 + cp_2 = 6, 1.722 + cp_2or3 = 5, 1.723 + cp_1 = 4, 1.724 + cp_1or3 = 3, 1.725 + cp_1or2 = 2, 1.726 + cp_1or2or3 = 1, 1.727 + cp_0 = 9, 1.728 + cp_0or3 = 10, 1.729 + cp_0or2 = 11, 1.730 + cp_0or2or3 = 12, 1.731 + cp_0or1 = 13, 1.732 + cp_0or1or3 = 14, 1.733 + cp_0or1or2 = 15, 1.734 + 1.735 + 1.736 + // for integers 1.737 + 1.738 + never = 0, 1.739 + equal = 1, 1.740 + zero = 1, 1.741 + lessEqual = 2, 1.742 + less = 3, 1.743 + lessEqualUnsigned = 4, 1.744 + lessUnsigned = 5, 1.745 + carrySet = 5, 1.746 + negative = 6, 1.747 + overflowSet = 7, 1.748 + always = 8, 1.749 + notEqual = 9, 1.750 + notZero = 9, 1.751 + greater = 10, 1.752 + greaterEqual = 11, 1.753 + greaterUnsigned = 12, 1.754 + greaterEqualUnsigned = 13, 1.755 + carryClear = 13, 1.756 + positive = 14, 1.757 + overflowClear = 15 1.758 + }; 1.759 + 1.760 + enum CC { 1.761 + icc = 0, xcc = 2, 1.762 + // ptr_cc is the correct condition code for a pointer or intptr_t: 1.763 + ptr_cc = NOT_LP64(icc) LP64_ONLY(xcc), 1.764 + fcc0 = 0, fcc1 = 1, fcc2 = 2, fcc3 = 3 1.765 + }; 1.766 + 1.767 + enum PrefetchFcn { 1.768 + severalReads = 0, oneRead = 1, severalWritesAndPossiblyReads = 2, oneWrite = 3, page = 4 1.769 + }; 1.770 + 1.771 + public: 1.772 + // Helper functions for groups of instructions 1.773 + 1.774 + enum Predict { pt = 1, pn = 0 }; // pt = predict taken 1.775 + 1.776 + enum Membar_mask_bits { // page 184, v9 1.777 + StoreStore = 1 << 3, 1.778 + LoadStore = 1 << 2, 1.779 + StoreLoad = 1 << 1, 1.780 + LoadLoad = 1 << 0, 1.781 + 1.782 + Sync = 1 << 6, 1.783 + MemIssue = 1 << 5, 1.784 + Lookaside = 1 << 4 1.785 + }; 1.786 + 1.787 + // test if x is within signed immediate range for nbits 1.788 + static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); } 1.789 + 1.790 + // test if -4096 <= x <= 4095 1.791 + static bool is_simm13(int x) { return is_simm(x, 13); } 1.792 + 1.793 + enum ASIs { // page 72, v9 1.794 + ASI_PRIMARY = 0x80, 1.795 + ASI_PRIMARY_LITTLE = 0x88 1.796 + // add more from book as needed 1.797 + }; 1.798 + 1.799 + protected: 1.800 + // helpers 1.801 + 1.802 + // x is supposed to fit in a field "nbits" wide 1.803 + // and be sign-extended. Check the range. 1.804 + 1.805 + static void assert_signed_range(intptr_t x, int nbits) { 1.806 + assert( nbits == 32 1.807 + || -(1 << nbits-1) <= x && x < ( 1 << nbits-1), 1.808 + "value out of range"); 1.809 + } 1.810 + 1.811 + static void assert_signed_word_disp_range(intptr_t x, int nbits) { 1.812 + assert( (x & 3) == 0, "not word aligned"); 1.813 + assert_signed_range(x, nbits + 2); 1.814 + } 1.815 + 1.816 + static void assert_unsigned_const(int x, int nbits) { 1.817 + assert( juint(x) < juint(1 << nbits), "unsigned constant out of range"); 1.818 + } 1.819 + 1.820 + // fields: note bits numbered from LSB = 0, 1.821 + // fields known by inclusive bit range 1.822 + 1.823 + static int fmask(juint hi_bit, juint lo_bit) { 1.824 + assert( hi_bit >= lo_bit && 0 <= lo_bit && hi_bit < 32, "bad bits"); 1.825 + return (1 << ( hi_bit-lo_bit + 1 )) - 1; 1.826 + } 1.827 + 1.828 + // inverse of u_field 1.829 + 1.830 + static int inv_u_field(int x, int hi_bit, int lo_bit) { 1.831 + juint r = juint(x) >> lo_bit; 1.832 + r &= fmask( hi_bit, lo_bit); 1.833 + return int(r); 1.834 + } 1.835 + 1.836 + 1.837 + // signed version: extract from field and sign-extend 1.838 + 1.839 + static int inv_s_field(int x, int hi_bit, int lo_bit) { 1.840 + int sign_shift = 31 - hi_bit; 1.841 + return inv_u_field( ((x << sign_shift) >> sign_shift), hi_bit, lo_bit); 1.842 + } 1.843 + 1.844 + // given a field that ranges from hi_bit to lo_bit (inclusive, 1.845 + // LSB = 0), and an unsigned value for the field, 1.846 + // shift it into the field 1.847 + 1.848 +#ifdef ASSERT 1.849 + static int u_field(int x, int hi_bit, int lo_bit) { 1.850 + assert( ( x & ~fmask(hi_bit, lo_bit)) == 0, 1.851 + "value out of range"); 1.852 + int r = x << lo_bit; 1.853 + assert( inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); 1.854 + return r; 1.855 + } 1.856 +#else 1.857 + // make sure this is inlined as it will reduce code size significantly 1.858 + #define u_field(x, hi_bit, lo_bit) ((x) << (lo_bit)) 1.859 +#endif 1.860 + 1.861 + static int inv_op( int x ) { return inv_u_field(x, 31, 30); } 1.862 + static int inv_op2( int x ) { return inv_u_field(x, 24, 22); } 1.863 + static int inv_op3( int x ) { return inv_u_field(x, 24, 19); } 1.864 + static int inv_cond( int x ){ return inv_u_field(x, 28, 25); } 1.865 + 1.866 + static bool inv_immed( int x ) { return (x & Assembler::immed(true)) != 0; } 1.867 + 1.868 + static Register inv_rd( int x ) { return as_Register(inv_u_field(x, 29, 25)); } 1.869 + static Register inv_rs1( int x ) { return as_Register(inv_u_field(x, 18, 14)); } 1.870 + static Register inv_rs2( int x ) { return as_Register(inv_u_field(x, 4, 0)); } 1.871 + 1.872 + static int op( int x) { return u_field(x, 31, 30); } 1.873 + static int rd( Register r) { return u_field(r->encoding(), 29, 25); } 1.874 + static int fcn( int x) { return u_field(x, 29, 25); } 1.875 + static int op3( int x) { return u_field(x, 24, 19); } 1.876 + static int rs1( Register r) { return u_field(r->encoding(), 18, 14); } 1.877 + static int rs2( Register r) { return u_field(r->encoding(), 4, 0); } 1.878 + static int annul( bool a) { return u_field(a ? 1 : 0, 29, 29); } 1.879 + static int cond( int x) { return u_field(x, 28, 25); } 1.880 + static int cond_mov( int x) { return u_field(x, 17, 14); } 1.881 + static int rcond( RCondition x) { return u_field(x, 12, 10); } 1.882 + static int op2( int x) { return u_field(x, 24, 22); } 1.883 + static int predict( bool p) { return u_field(p ? 1 : 0, 19, 19); } 1.884 + static int branchcc( CC fcca) { return u_field(fcca, 21, 20); } 1.885 + static int cmpcc( CC fcca) { return u_field(fcca, 26, 25); } 1.886 + static int imm_asi( int x) { return u_field(x, 12, 5); } 1.887 + static int immed( bool i) { return u_field(i ? 1 : 0, 13, 13); } 1.888 + static int opf_low6( int w) { return u_field(w, 10, 5); } 1.889 + static int opf_low5( int w) { return u_field(w, 9, 5); } 1.890 + static int trapcc( CC cc) { return u_field(cc, 12, 11); } 1.891 + static int sx( int i) { return u_field(i, 12, 12); } // shift x=1 means 64-bit 1.892 + static int opf( int x) { return u_field(x, 13, 5); } 1.893 + 1.894 + static int opf_cc( CC c, bool useFloat ) { return u_field((useFloat ? 0 : 4) + c, 13, 11); } 1.895 + static int mov_cc( CC c, bool useFloat ) { return u_field(useFloat ? 0 : 1, 18, 18) | u_field(c, 12, 11); } 1.896 + 1.897 + static int fd( FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 29, 25); }; 1.898 + static int fs1(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 18, 14); }; 1.899 + static int fs2(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 4, 0); }; 1.900 + 1.901 + // some float instructions use this encoding on the op3 field 1.902 + static int alt_op3(int op, FloatRegisterImpl::Width w) { 1.903 + int r; 1.904 + switch(w) { 1.905 + case FloatRegisterImpl::S: r = op + 0; break; 1.906 + case FloatRegisterImpl::D: r = op + 3; break; 1.907 + case FloatRegisterImpl::Q: r = op + 2; break; 1.908 + default: ShouldNotReachHere(); break; 1.909 + } 1.910 + return op3(r); 1.911 + } 1.912 + 1.913 + 1.914 + // compute inverse of simm 1.915 + static int inv_simm(int x, int nbits) { 1.916 + return (int)(x << (32 - nbits)) >> (32 - nbits); 1.917 + } 1.918 + 1.919 + static int inv_simm13( int x ) { return inv_simm(x, 13); } 1.920 + 1.921 + // signed immediate, in low bits, nbits long 1.922 + static int simm(int x, int nbits) { 1.923 + assert_signed_range(x, nbits); 1.924 + return x & (( 1 << nbits ) - 1); 1.925 + } 1.926 + 1.927 + // compute inverse of wdisp16 1.928 + static intptr_t inv_wdisp16(int x, intptr_t pos) { 1.929 + int lo = x & (( 1 << 14 ) - 1); 1.930 + int hi = (x >> 20) & 3; 1.931 + if (hi >= 2) hi |= ~1; 1.932 + return (((hi << 14) | lo) << 2) + pos; 1.933 + } 1.934 + 1.935 + // word offset, 14 bits at LSend, 2 bits at B21, B20 1.936 + static int wdisp16(intptr_t x, intptr_t off) { 1.937 + intptr_t xx = x - off; 1.938 + assert_signed_word_disp_range(xx, 16); 1.939 + int r = (xx >> 2) & ((1 << 14) - 1) 1.940 + | ( ( (xx>>(2+14)) & 3 ) << 20 ); 1.941 + assert( inv_wdisp16(r, off) == x, "inverse is not inverse"); 1.942 + return r; 1.943 + } 1.944 + 1.945 + 1.946 + // word displacement in low-order nbits bits 1.947 + 1.948 + static intptr_t inv_wdisp( int x, intptr_t pos, int nbits ) { 1.949 + int pre_sign_extend = x & (( 1 << nbits ) - 1); 1.950 + int r = pre_sign_extend >= ( 1 << (nbits-1) ) 1.951 + ? pre_sign_extend | ~(( 1 << nbits ) - 1) 1.952 + : pre_sign_extend; 1.953 + return (r << 2) + pos; 1.954 + } 1.955 + 1.956 + static int wdisp( intptr_t x, intptr_t off, int nbits ) { 1.957 + intptr_t xx = x - off; 1.958 + assert_signed_word_disp_range(xx, nbits); 1.959 + int r = (xx >> 2) & (( 1 << nbits ) - 1); 1.960 + assert( inv_wdisp( r, off, nbits ) == x, "inverse not inverse"); 1.961 + return r; 1.962 + } 1.963 + 1.964 + 1.965 + // Extract the top 32 bits in a 64 bit word 1.966 + static int32_t hi32( int64_t x ) { 1.967 + int32_t r = int32_t( (uint64_t)x >> 32 ); 1.968 + return r; 1.969 + } 1.970 + 1.971 + // given a sethi instruction, extract the constant, left-justified 1.972 + static int inv_hi22( int x ) { 1.973 + return x << 10; 1.974 + } 1.975 + 1.976 + // create an imm22 field, given a 32-bit left-justified constant 1.977 + static int hi22( int x ) { 1.978 + int r = int( juint(x) >> 10 ); 1.979 + assert( (r & ~((1 << 22) - 1)) == 0, "just checkin'"); 1.980 + return r; 1.981 + } 1.982 + 1.983 + // create a low10 __value__ (not a field) for a given a 32-bit constant 1.984 + static int low10( int x ) { 1.985 + return x & ((1 << 10) - 1); 1.986 + } 1.987 + 1.988 + // instruction only in v9 1.989 + static void v9_only() { assert( VM_Version::v9_instructions_work(), "This instruction only works on SPARC V9"); } 1.990 + 1.991 + // instruction only in v8 1.992 + static void v8_only() { assert( VM_Version::v8_instructions_work(), "This instruction only works on SPARC V8"); } 1.993 + 1.994 + // instruction deprecated in v9 1.995 + static void v9_dep() { } // do nothing for now 1.996 + 1.997 + // some float instructions only exist for single prec. on v8 1.998 + static void v8_s_only(FloatRegisterImpl::Width w) { if (w != FloatRegisterImpl::S) v9_only(); } 1.999 + 1.1000 + // v8 has no CC field 1.1001 + static void v8_no_cc(CC cc) { if (cc) v9_only(); } 1.1002 + 1.1003 + protected: 1.1004 + // Simple delay-slot scheme: 1.1005 + // In order to check the programmer, the assembler keeps track of deley slots. 1.1006 + // It forbids CTIs in delay slots (conservative, but should be OK). 1.1007 + // Also, when putting an instruction into a delay slot, you must say 1.1008 + // asm->delayed()->add(...), in order to check that you don't omit 1.1009 + // delay-slot instructions. 1.1010 + // To implement this, we use a simple FSA 1.1011 + 1.1012 +#ifdef ASSERT 1.1013 + #define CHECK_DELAY 1.1014 +#endif 1.1015 +#ifdef CHECK_DELAY 1.1016 + enum Delay_state { no_delay, at_delay_slot, filling_delay_slot } delay_state; 1.1017 +#endif 1.1018 + 1.1019 + public: 1.1020 + // Tells assembler next instruction must NOT be in delay slot. 1.1021 + // Use at start of multinstruction macros. 1.1022 + void assert_not_delayed() { 1.1023 + // This is a separate overloading to avoid creation of string constants 1.1024 + // in non-asserted code--with some compilers this pollutes the object code. 1.1025 +#ifdef CHECK_DELAY 1.1026 + assert_not_delayed("next instruction should not be a delay slot"); 1.1027 +#endif 1.1028 + } 1.1029 + void assert_not_delayed(const char* msg) { 1.1030 +#ifdef CHECK_DELAY 1.1031 + assert_msg ( delay_state == no_delay, msg); 1.1032 +#endif 1.1033 + } 1.1034 + 1.1035 + protected: 1.1036 + // Delay slot helpers 1.1037 + // cti is called when emitting control-transfer instruction, 1.1038 + // BEFORE doing the emitting. 1.1039 + // Only effective when assertion-checking is enabled. 1.1040 + void cti() { 1.1041 +#ifdef CHECK_DELAY 1.1042 + assert_not_delayed("cti should not be in delay slot"); 1.1043 +#endif 1.1044 + } 1.1045 + 1.1046 + // called when emitting cti with a delay slot, AFTER emitting 1.1047 + void has_delay_slot() { 1.1048 +#ifdef CHECK_DELAY 1.1049 + assert_not_delayed("just checking"); 1.1050 + delay_state = at_delay_slot; 1.1051 +#endif 1.1052 + } 1.1053 + 1.1054 +public: 1.1055 + // Tells assembler you know that next instruction is delayed 1.1056 + Assembler* delayed() { 1.1057 +#ifdef CHECK_DELAY 1.1058 + assert ( delay_state == at_delay_slot, "delayed instruction is not in delay slot"); 1.1059 + delay_state = filling_delay_slot; 1.1060 +#endif 1.1061 + return this; 1.1062 + } 1.1063 + 1.1064 + void flush() { 1.1065 +#ifdef CHECK_DELAY 1.1066 + assert ( delay_state == no_delay, "ending code with a delay slot"); 1.1067 +#endif 1.1068 + AbstractAssembler::flush(); 1.1069 + } 1.1070 + 1.1071 + inline void emit_long(int); // shadows AbstractAssembler::emit_long 1.1072 + inline void emit_data(int x) { emit_long(x); } 1.1073 + inline void emit_data(int, RelocationHolder const&); 1.1074 + inline void emit_data(int, relocInfo::relocType rtype); 1.1075 + // helper for above fcns 1.1076 + inline void check_delay(); 1.1077 + 1.1078 + 1.1079 + public: 1.1080 + // instructions, refer to page numbers in the SPARC Architecture Manual, V9 1.1081 + 1.1082 + // pp 135 (addc was addx in v8) 1.1083 + 1.1084 + inline void add( Register s1, Register s2, Register d ); 1.1085 + inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); 1.1086 + inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec); 1.1087 + inline void add( const Address& a, Register d, int offset = 0); 1.1088 + 1.1089 + void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1090 + void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1091 + void addc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); } 1.1092 + void addc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1093 + void addccc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1094 + void addccc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1095 + 1.1096 + // pp 136 1.1097 + 1.1098 + inline void bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none ); 1.1099 + inline void bpr( RCondition c, bool a, Predict p, Register s1, Label& L); 1.1100 + 1.1101 + protected: // use MacroAssembler::br instead 1.1102 + 1.1103 + // pp 138 1.1104 + 1.1105 + inline void fb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); 1.1106 + inline void fb( Condition c, bool a, Label& L ); 1.1107 + 1.1108 + // pp 141 1.1109 + 1.1110 + inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1111 + inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); 1.1112 + 1.1113 + public: 1.1114 + 1.1115 + // pp 144 1.1116 + 1.1117 + inline void br( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); 1.1118 + inline void br( Condition c, bool a, Label& L ); 1.1119 + 1.1120 + // pp 146 1.1121 + 1.1122 + inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1123 + inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); 1.1124 + 1.1125 + // pp 121 (V8) 1.1126 + 1.1127 + inline void cb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); 1.1128 + inline void cb( Condition c, bool a, Label& L ); 1.1129 + 1.1130 + // pp 149 1.1131 + 1.1132 + inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); 1.1133 + inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); 1.1134 + 1.1135 + // pp 150 1.1136 + 1.1137 + // These instructions compare the contents of s2 with the contents of 1.1138 + // memory at address in s1. If the values are equal, the contents of memory 1.1139 + // at address s1 is swapped with the data in d. If the values are not equal, 1.1140 + // the the contents of memory at s1 is loaded into d, without the swap. 1.1141 + 1.1142 + void casa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(casa_op3 ) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); } 1.1143 + void casxa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(casxa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); } 1.1144 + 1.1145 + // pp 152 1.1146 + 1.1147 + void udiv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | rs2(s2)); } 1.1148 + void udiv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1149 + void sdiv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | rs2(s2)); } 1.1150 + void sdiv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1151 + void udivcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); } 1.1152 + void udivcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1153 + void sdivcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); } 1.1154 + void sdivcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1155 + 1.1156 + // pp 155 1.1157 + 1.1158 + void done() { v9_only(); cti(); emit_long( op(arith_op) | fcn(0) | op3(done_op3) ); } 1.1159 + void retry() { v9_only(); cti(); emit_long( op(arith_op) | fcn(1) | op3(retry_op3) ); } 1.1160 + 1.1161 + // pp 156 1.1162 + 1.1163 + void fadd( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x40 + w) | fs2(s2, w)); } 1.1164 + void fsub( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x44 + w) | fs2(s2, w)); } 1.1165 + 1.1166 + // pp 157 1.1167 + 1.1168 + void fcmp( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_long( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x50 + w) | fs2(s2, w)); } 1.1169 + void fcmpe( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_long( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x54 + w) | fs2(s2, w)); } 1.1170 + 1.1171 + // pp 159 1.1172 + 1.1173 + void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } 1.1174 + void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } 1.1175 + 1.1176 + // pp 160 1.1177 + 1.1178 + void ftof( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | opf(0xc0 + sw + dw*4) | fs2(s, sw)); } 1.1179 + 1.1180 + // pp 161 1.1181 + 1.1182 + void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, w)); } 1.1183 + void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, w)); } 1.1184 + 1.1185 + // pp 162 1.1186 + 1.1187 + void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x00 + w) | fs2(s, w)); } 1.1188 + 1.1189 + void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(s, w)); } 1.1190 + 1.1191 + // page 144 sparc v8 architecture (double prec works on v8 if the source and destination registers are the same). fnegs is the only instruction available 1.1192 + // on v8 to do negation of single, double and quad precision floats. 1.1193 + 1.1194 + void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(sd, w)); else emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x05) | fs2(sd, w)); } 1.1195 + 1.1196 + void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(s, w)); } 1.1197 + 1.1198 + // page 144 sparc v8 architecture (double prec works on v8 if the source and destination registers are the same). fabss is the only instruction available 1.1199 + // on v8 to do abs operation on single/double/quad precision floats. 1.1200 + 1.1201 + void fabs( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(sd, w)); else emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x09) | fs2(sd, w)); } 1.1202 + 1.1203 + // pp 163 1.1204 + 1.1205 + void fmul( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x48 + w) | fs2(s2, w)); } 1.1206 + void fmul( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | fs1(s1, sw) | opf(0x60 + sw + dw*4) | fs2(s2, sw)); } 1.1207 + void fdiv( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x4c + w) | fs2(s2, w)); } 1.1208 + 1.1209 + // pp 164 1.1210 + 1.1211 + void fsqrt( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x28 + w) | fs2(s, w)); } 1.1212 + 1.1213 + // pp 165 1.1214 + 1.1215 + inline void flush( Register s1, Register s2 ); 1.1216 + inline void flush( Register s1, int simm13a); 1.1217 + 1.1218 + // pp 167 1.1219 + 1.1220 + void flushw() { v9_only(); emit_long( op(arith_op) | op3(flushw_op3) ); } 1.1221 + 1.1222 + // pp 168 1.1223 + 1.1224 + void illtrap( int const22a) { if (const22a != 0) v9_only(); emit_long( op(branch_op) | u_field(const22a, 21, 0) ); } 1.1225 + // v8 unimp == illtrap(0) 1.1226 + 1.1227 + // pp 169 1.1228 + 1.1229 + void impdep1( int id1, int const19a ) { v9_only(); emit_long( op(arith_op) | fcn(id1) | op3(impdep1_op3) | u_field(const19a, 18, 0)); } 1.1230 + void impdep2( int id1, int const19a ) { v9_only(); emit_long( op(arith_op) | fcn(id1) | op3(impdep2_op3) | u_field(const19a, 18, 0)); } 1.1231 + 1.1232 + // pp 149 (v8) 1.1233 + 1.1234 + void cpop1( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_long( op(arith_op) | fcn(crd) | op3(impdep1_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); } 1.1235 + void cpop2( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_long( op(arith_op) | fcn(crd) | op3(impdep2_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); } 1.1236 + 1.1237 + // pp 170 1.1238 + 1.1239 + void jmpl( Register s1, Register s2, Register d ); 1.1240 + void jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec = RelocationHolder() ); 1.1241 + 1.1242 + inline void jmpl( Address& a, Register d, int offset = 0); 1.1243 + 1.1244 + // 171 1.1245 + 1.1246 + inline void ldf( FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d ); 1.1247 + inline void ldf( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ); 1.1248 + 1.1249 + inline void ldf( FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0); 1.1250 + 1.1251 + 1.1252 + inline void ldfsr( Register s1, Register s2 ); 1.1253 + inline void ldfsr( Register s1, int simm13a); 1.1254 + inline void ldxfsr( Register s1, Register s2 ); 1.1255 + inline void ldxfsr( Register s1, int simm13a); 1.1256 + 1.1257 + // pp 94 (v8) 1.1258 + 1.1259 + inline void ldc( Register s1, Register s2, int crd ); 1.1260 + inline void ldc( Register s1, int simm13a, int crd); 1.1261 + inline void lddc( Register s1, Register s2, int crd ); 1.1262 + inline void lddc( Register s1, int simm13a, int crd); 1.1263 + inline void ldcsr( Register s1, Register s2, int crd ); 1.1264 + inline void ldcsr( Register s1, int simm13a, int crd); 1.1265 + 1.1266 + 1.1267 + // 173 1.1268 + 1.1269 + void ldfa( FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1270 + void ldfa( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1271 + 1.1272 + // pp 175, lduw is ld on v8 1.1273 + 1.1274 + inline void ldsb( Register s1, Register s2, Register d ); 1.1275 + inline void ldsb( Register s1, int simm13a, Register d); 1.1276 + inline void ldsh( Register s1, Register s2, Register d ); 1.1277 + inline void ldsh( Register s1, int simm13a, Register d); 1.1278 + inline void ldsw( Register s1, Register s2, Register d ); 1.1279 + inline void ldsw( Register s1, int simm13a, Register d); 1.1280 + inline void ldub( Register s1, Register s2, Register d ); 1.1281 + inline void ldub( Register s1, int simm13a, Register d); 1.1282 + inline void lduh( Register s1, Register s2, Register d ); 1.1283 + inline void lduh( Register s1, int simm13a, Register d); 1.1284 + inline void lduw( Register s1, Register s2, Register d ); 1.1285 + inline void lduw( Register s1, int simm13a, Register d); 1.1286 + inline void ldx( Register s1, Register s2, Register d ); 1.1287 + inline void ldx( Register s1, int simm13a, Register d); 1.1288 + inline void ld( Register s1, Register s2, Register d ); 1.1289 + inline void ld( Register s1, int simm13a, Register d); 1.1290 + inline void ldd( Register s1, Register s2, Register d ); 1.1291 + inline void ldd( Register s1, int simm13a, Register d); 1.1292 + 1.1293 + inline void ldsb( const Address& a, Register d, int offset = 0 ); 1.1294 + inline void ldsh( const Address& a, Register d, int offset = 0 ); 1.1295 + inline void ldsw( const Address& a, Register d, int offset = 0 ); 1.1296 + inline void ldub( const Address& a, Register d, int offset = 0 ); 1.1297 + inline void lduh( const Address& a, Register d, int offset = 0 ); 1.1298 + inline void lduw( const Address& a, Register d, int offset = 0 ); 1.1299 + inline void ldx( const Address& a, Register d, int offset = 0 ); 1.1300 + inline void ld( const Address& a, Register d, int offset = 0 ); 1.1301 + inline void ldd( const Address& a, Register d, int offset = 0 ); 1.1302 + 1.1303 + // pp 177 1.1304 + 1.1305 + void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1306 + void ldsba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1307 + void ldsha( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1308 + void ldsha( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1309 + void ldswa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1310 + void ldswa( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1311 + void lduba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1312 + void lduba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1313 + void lduha( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1314 + void lduha( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1315 + void lduwa( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1316 + void lduwa( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1317 + void ldxa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1318 + void ldxa( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1319 + void ldda( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1320 + void ldda( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1321 + 1.1322 + // pp 179 1.1323 + 1.1324 + inline void ldstub( Register s1, Register s2, Register d ); 1.1325 + inline void ldstub( Register s1, int simm13a, Register d); 1.1326 + 1.1327 + // pp 180 1.1328 + 1.1329 + void ldstuba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1330 + void ldstuba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1331 + 1.1332 + // pp 181 1.1333 + 1.1334 + void and3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); } 1.1335 + void and3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1336 + void andcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1337 + void andcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1338 + void andn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); } 1.1339 + void andn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1340 + void andncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1341 + void andncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1342 + void or3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); } 1.1343 + void or3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1344 + void orcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1345 + void orcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1346 + void orn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2) ); } 1.1347 + void orn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1348 + void orncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1349 + void orncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1350 + void xor3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); } 1.1351 + void xor3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1352 + void xorcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1353 + void xorcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1354 + void xnor( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | rs2(s2) ); } 1.1355 + void xnor( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1356 + void xnorcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1357 + void xnorcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1358 + 1.1359 + // pp 183 1.1360 + 1.1361 + void membar( Membar_mask_bits const7a ) { v9_only(); emit_long( op(arith_op) | op3(membar_op3) | rs1(O7) | immed(true) | u_field( int(const7a), 6, 0)); } 1.1362 + 1.1363 + // pp 185 1.1364 + 1.1365 + void fmov( FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop2_op3) | cond_mov(c) | opf_cc(cca, floatCC) | opf_low6(w) | fs2(s2, w)); } 1.1366 + 1.1367 + // pp 189 1.1368 + 1.1369 + void fmov( FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop2_op3) | rs1(s1) | rcond(c) | opf_low5(4 + w) | fs2(s2, w)); } 1.1370 + 1.1371 + // pp 191 1.1372 + 1.1373 + void movcc( Condition c, bool floatCC, CC cca, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | rs2(s2) ); } 1.1374 + void movcc( Condition c, bool floatCC, CC cca, int simm11a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | immed(true) | simm(simm11a, 11) ); } 1.1375 + 1.1376 + // pp 195 1.1377 + 1.1378 + void movr( RCondition c, Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | rs2(s2) ); } 1.1379 + void movr( RCondition c, Register s1, int simm10a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | immed(true) | simm(simm10a, 10) ); } 1.1380 + 1.1381 + // pp 196 1.1382 + 1.1383 + void mulx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | rs2(s2) ); } 1.1384 + void mulx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1385 + void sdivx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | rs2(s2) ); } 1.1386 + void sdivx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1387 + void udivx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | rs2(s2) ); } 1.1388 + void udivx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1389 + 1.1390 + // pp 197 1.1391 + 1.1392 + void umul( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | rs2(s2) ); } 1.1393 + void umul( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1394 + void smul( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | rs2(s2) ); } 1.1395 + void smul( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1396 + void umulcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1397 + void umulcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1398 + void smulcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1399 + void smulcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1400 + 1.1401 + // pp 199 1.1402 + 1.1403 + void mulscc( Register s1, Register s2, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | rs2(s2) ); } 1.1404 + void mulscc( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1405 + 1.1406 + // pp 201 1.1407 + 1.1408 + void nop() { emit_long( op(branch_op) | op2(sethi_op2) ); } 1.1409 + 1.1410 + 1.1411 + // pp 202 1.1412 + 1.1413 + void popc( Register s, Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(popc_op3) | rs2(s)); } 1.1414 + void popc( int simm13a, Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(popc_op3) | immed(true) | simm(simm13a, 13)); } 1.1415 + 1.1416 + // pp 203 1.1417 + 1.1418 + void prefetch( Register s1, Register s2, PrefetchFcn f); 1.1419 + void prefetch( Register s1, int simm13a, PrefetchFcn f); 1.1420 + void prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1421 + void prefetcha( Register s1, int simm13a, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1422 + 1.1423 + inline void prefetch(const Address& a, PrefetchFcn F, int offset = 0); 1.1424 + 1.1425 + // pp 208 1.1426 + 1.1427 + // not implementing read privileged register 1.1428 + 1.1429 + inline void rdy( Register d) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(0, 18, 14)); } 1.1430 + inline void rdccr( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(2, 18, 14)); } 1.1431 + inline void rdasi( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(3, 18, 14)); } 1.1432 + inline void rdtick( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(4, 18, 14)); } // Spoon! 1.1433 + inline void rdpc( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(5, 18, 14)); } 1.1434 + inline void rdfprs( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(6, 18, 14)); } 1.1435 + 1.1436 + // pp 213 1.1437 + 1.1438 + inline void rett( Register s1, Register s2); 1.1439 + inline void rett( Register s1, int simm13a, relocInfo::relocType rt = relocInfo::none); 1.1440 + 1.1441 + // pp 214 1.1442 + 1.1443 + void save( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | rs2(s2) ); } 1.1444 + void save( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1445 + 1.1446 + void restore( Register s1 = G0, Register s2 = G0, Register d = G0 ) { emit_long( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | rs2(s2) ); } 1.1447 + void restore( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1448 + 1.1449 + // pp 216 1.1450 + 1.1451 + void saved() { v9_only(); emit_long( op(arith_op) | fcn(0) | op3(saved_op3)); } 1.1452 + void restored() { v9_only(); emit_long( op(arith_op) | fcn(1) | op3(saved_op3)); } 1.1453 + 1.1454 + // pp 217 1.1455 + 1.1456 + inline void sethi( int imm22a, Register d, RelocationHolder const& rspec = RelocationHolder() ); 1.1457 + // pp 218 1.1458 + 1.1459 + void sll( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | rs2(s2) ); } 1.1460 + void sll( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } 1.1461 + void srl( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | rs2(s2) ); } 1.1462 + void srl( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } 1.1463 + void sra( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | rs2(s2) ); } 1.1464 + void sra( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } 1.1465 + 1.1466 + void sllx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | rs2(s2) ); } 1.1467 + void sllx( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } 1.1468 + void srlx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | rs2(s2) ); } 1.1469 + void srlx( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } 1.1470 + void srax( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | rs2(s2) ); } 1.1471 + void srax( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } 1.1472 + 1.1473 + // pp 220 1.1474 + 1.1475 + void sir( int simm13a ) { emit_long( op(arith_op) | fcn(15) | op3(sir_op3) | immed(true) | simm(simm13a, 13)); } 1.1476 + 1.1477 + // pp 221 1.1478 + 1.1479 + void stbar() { emit_long( op(arith_op) | op3(membar_op3) | u_field(15, 18, 14)); } 1.1480 + 1.1481 + // pp 222 1.1482 + 1.1483 + inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2 ); 1.1484 + inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a); 1.1485 + inline void stf( FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset = 0); 1.1486 + 1.1487 + inline void stfsr( Register s1, Register s2 ); 1.1488 + inline void stfsr( Register s1, int simm13a); 1.1489 + inline void stxfsr( Register s1, Register s2 ); 1.1490 + inline void stxfsr( Register s1, int simm13a); 1.1491 + 1.1492 + // pp 224 1.1493 + 1.1494 + void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1495 + void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1496 + 1.1497 + // p 226 1.1498 + 1.1499 + inline void stb( Register d, Register s1, Register s2 ); 1.1500 + inline void stb( Register d, Register s1, int simm13a); 1.1501 + inline void sth( Register d, Register s1, Register s2 ); 1.1502 + inline void sth( Register d, Register s1, int simm13a); 1.1503 + inline void stw( Register d, Register s1, Register s2 ); 1.1504 + inline void stw( Register d, Register s1, int simm13a); 1.1505 + inline void st( Register d, Register s1, Register s2 ); 1.1506 + inline void st( Register d, Register s1, int simm13a); 1.1507 + inline void stx( Register d, Register s1, Register s2 ); 1.1508 + inline void stx( Register d, Register s1, int simm13a); 1.1509 + inline void std( Register d, Register s1, Register s2 ); 1.1510 + inline void std( Register d, Register s1, int simm13a); 1.1511 + 1.1512 + inline void stb( Register d, const Address& a, int offset = 0 ); 1.1513 + inline void sth( Register d, const Address& a, int offset = 0 ); 1.1514 + inline void stw( Register d, const Address& a, int offset = 0 ); 1.1515 + inline void stx( Register d, const Address& a, int offset = 0 ); 1.1516 + inline void st( Register d, const Address& a, int offset = 0 ); 1.1517 + inline void std( Register d, const Address& a, int offset = 0 ); 1.1518 + 1.1519 + // pp 177 1.1520 + 1.1521 + void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1522 + void stba( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1523 + void stha( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1524 + void stha( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1525 + void stwa( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1526 + void stwa( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1527 + void stxa( Register d, Register s1, Register s2, int ia ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1528 + void stxa( Register d, Register s1, int simm13a ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1529 + void stda( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1530 + void stda( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1531 + 1.1532 + // pp 97 (v8) 1.1533 + 1.1534 + inline void stc( int crd, Register s1, Register s2 ); 1.1535 + inline void stc( int crd, Register s1, int simm13a); 1.1536 + inline void stdc( int crd, Register s1, Register s2 ); 1.1537 + inline void stdc( int crd, Register s1, int simm13a); 1.1538 + inline void stcsr( int crd, Register s1, Register s2 ); 1.1539 + inline void stcsr( int crd, Register s1, int simm13a); 1.1540 + inline void stdcq( int crd, Register s1, Register s2 ); 1.1541 + inline void stdcq( int crd, Register s1, int simm13a); 1.1542 + 1.1543 + // pp 230 1.1544 + 1.1545 + void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); } 1.1546 + void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1547 + void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); } 1.1548 + void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1549 + void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); } 1.1550 + void subc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1551 + void subccc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 1.1552 + void subccc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1553 + 1.1554 + // pp 231 1.1555 + 1.1556 + inline void swap( Register s1, Register s2, Register d ); 1.1557 + inline void swap( Register s1, int simm13a, Register d); 1.1558 + inline void swap( Address& a, Register d, int offset = 0 ); 1.1559 + 1.1560 + // pp 232 1.1561 + 1.1562 + void swapa( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 1.1563 + void swapa( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1564 + 1.1565 + // pp 234, note op in book is wrong, see pp 268 1.1566 + 1.1567 + void taddcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | rs2(s2) ); } 1.1568 + void taddcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1569 + void taddcctv( Register s1, Register s2, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | rs2(s2) ); } 1.1570 + void taddcctv( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1571 + 1.1572 + // pp 235 1.1573 + 1.1574 + void tsubcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | rs2(s2) ); } 1.1575 + void tsubcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1576 + void tsubcctv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | rs2(s2) ); } 1.1577 + void tsubcctv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 1.1578 + 1.1579 + // pp 237 1.1580 + 1.1581 + void trap( Condition c, CC cc, Register s1, Register s2 ) { v8_no_cc(cc); emit_long( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | rs2(s2)); } 1.1582 + void trap( Condition c, CC cc, Register s1, int trapa ) { v8_no_cc(cc); emit_long( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | immed(true) | u_field(trapa, 6, 0)); } 1.1583 + // simple uncond. trap 1.1584 + void trap( int trapa ) { trap( always, icc, G0, trapa ); } 1.1585 + 1.1586 + // pp 239 omit write priv register for now 1.1587 + 1.1588 + inline void wry( Register d) { v9_dep(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(0, 29, 25)); } 1.1589 + inline void wrccr(Register s) { v9_only(); emit_long( op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25)); } 1.1590 + inline void wrccr(Register s, int simm13a) { v9_only(); emit_long( op(arith_op) | 1.1591 + rs1(s) | 1.1592 + op3(wrreg_op3) | 1.1593 + u_field(2, 29, 25) | 1.1594 + u_field(1, 13, 13) | 1.1595 + simm(simm13a, 13)); } 1.1596 + inline void wrasi( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } 1.1597 + inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } 1.1598 + 1.1599 + 1.1600 + // Creation 1.1601 + Assembler(CodeBuffer* code) : AbstractAssembler(code) { 1.1602 +#ifdef CHECK_DELAY 1.1603 + delay_state = no_delay; 1.1604 +#endif 1.1605 + } 1.1606 + 1.1607 + // Testing 1.1608 +#ifndef PRODUCT 1.1609 + void test_v9(); 1.1610 + void test_v8_onlys(); 1.1611 +#endif 1.1612 +}; 1.1613 + 1.1614 + 1.1615 +class RegistersForDebugging : public StackObj { 1.1616 + public: 1.1617 + intptr_t i[8], l[8], o[8], g[8]; 1.1618 + float f[32]; 1.1619 + double d[32]; 1.1620 + 1.1621 + void print(outputStream* s); 1.1622 + 1.1623 + static int i_offset(int j) { return offset_of(RegistersForDebugging, i[j]); } 1.1624 + static int l_offset(int j) { return offset_of(RegistersForDebugging, l[j]); } 1.1625 + static int o_offset(int j) { return offset_of(RegistersForDebugging, o[j]); } 1.1626 + static int g_offset(int j) { return offset_of(RegistersForDebugging, g[j]); } 1.1627 + static int f_offset(int j) { return offset_of(RegistersForDebugging, f[j]); } 1.1628 + static int d_offset(int j) { return offset_of(RegistersForDebugging, d[j / 2]); } 1.1629 + 1.1630 + // gen asm code to save regs 1.1631 + static void save_registers(MacroAssembler* a); 1.1632 + 1.1633 + // restore global registers in case C code disturbed them 1.1634 + static void restore_registers(MacroAssembler* a, Register r); 1.1635 +}; 1.1636 + 1.1637 + 1.1638 +// MacroAssembler extends Assembler by a few frequently used macros. 1.1639 +// 1.1640 +// Most of the standard SPARC synthetic ops are defined here. 1.1641 +// Instructions for which a 'better' code sequence exists depending 1.1642 +// on arguments should also go in here. 1.1643 + 1.1644 +#define JMP2(r1, r2) jmp(r1, r2, __FILE__, __LINE__) 1.1645 +#define JMP(r1, off) jmp(r1, off, __FILE__, __LINE__) 1.1646 +#define JUMP(a, off) jump(a, off, __FILE__, __LINE__) 1.1647 +#define JUMPL(a, d, off) jumpl(a, d, off, __FILE__, __LINE__) 1.1648 + 1.1649 + 1.1650 +class MacroAssembler: public Assembler { 1.1651 + protected: 1.1652 + // Support for VM calls 1.1653 + // This is the base routine called by the different versions of call_VM_leaf. The interpreter 1.1654 + // may customize this version by overriding it for its purposes (e.g., to save/restore 1.1655 + // additional registers when doing a VM call). 1.1656 +#ifdef CC_INTERP 1.1657 + #define VIRTUAL 1.1658 +#else 1.1659 + #define VIRTUAL virtual 1.1660 +#endif 1.1661 + 1.1662 + VIRTUAL void call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments); 1.1663 + 1.1664 + // 1.1665 + // It is imperative that all calls into the VM are handled via the call_VM macros. 1.1666 + // They make sure that the stack linkage is setup correctly. call_VM's correspond 1.1667 + // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. 1.1668 + // 1.1669 + // This is the base routine called by the different versions of call_VM. The interpreter 1.1670 + // may customize this version by overriding it for its purposes (e.g., to save/restore 1.1671 + // additional registers when doing a VM call). 1.1672 + // 1.1673 + // A non-volatile java_thread_cache register should be specified so 1.1674 + // that the G2_thread value can be preserved across the call. 1.1675 + // (If java_thread_cache is noreg, then a slow get_thread call 1.1676 + // will re-initialize the G2_thread.) call_VM_base returns the register that contains the 1.1677 + // thread. 1.1678 + // 1.1679 + // If no last_java_sp is specified (noreg) than SP will be used instead. 1.1680 + 1.1681 + virtual void call_VM_base( 1.1682 + Register oop_result, // where an oop-result ends up if any; use noreg otherwise 1.1683 + Register java_thread_cache, // the thread if computed before ; use noreg otherwise 1.1684 + Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise 1.1685 + address entry_point, // the entry point 1.1686 + int number_of_arguments, // the number of arguments (w/o thread) to pop after call 1.1687 + bool check_exception=true // flag which indicates if exception should be checked 1.1688 + ); 1.1689 + 1.1690 + // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. 1.1691 + // The implementation is only non-empty for the InterpreterMacroAssembler, 1.1692 + // as only the interpreter handles and ForceEarlyReturn PopFrame requests. 1.1693 + virtual void check_and_handle_popframe(Register scratch_reg); 1.1694 + virtual void check_and_handle_earlyret(Register scratch_reg); 1.1695 + 1.1696 + public: 1.1697 + MacroAssembler(CodeBuffer* code) : Assembler(code) {} 1.1698 + 1.1699 + // Support for NULL-checks 1.1700 + // 1.1701 + // Generates code that causes a NULL OS exception if the content of reg is NULL. 1.1702 + // If the accessed location is M[reg + offset] and the offset is known, provide the 1.1703 + // offset. No explicit code generation is needed if the offset is within a certain 1.1704 + // range (0 <= offset <= page_size). 1.1705 + // 1.1706 + // %%%%%% Currently not done for SPARC 1.1707 + 1.1708 + void null_check(Register reg, int offset = -1); 1.1709 + static bool needs_explicit_null_check(intptr_t offset); 1.1710 + 1.1711 + // support for delayed instructions 1.1712 + MacroAssembler* delayed() { Assembler::delayed(); return this; } 1.1713 + 1.1714 + // branches that use right instruction for v8 vs. v9 1.1715 + inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1716 + inline void br( Condition c, bool a, Predict p, Label& L ); 1.1717 + inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1718 + inline void fb( Condition c, bool a, Predict p, Label& L ); 1.1719 + 1.1720 + // compares register with zero and branches (V9 and V8 instructions) 1.1721 + void br_zero( Condition c, bool a, Predict p, Register s1, Label& L); 1.1722 + // Compares a pointer register with zero and branches on (not)null. 1.1723 + // Does a test & branch on 32-bit systems and a register-branch on 64-bit. 1.1724 + void br_null ( Register s1, bool a, Predict p, Label& L ); 1.1725 + void br_notnull( Register s1, bool a, Predict p, Label& L ); 1.1726 + 1.1727 + inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1728 + inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); 1.1729 + 1.1730 + // Branch that tests xcc in LP64 and icc in !LP64 1.1731 + inline void brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1732 + inline void brx( Condition c, bool a, Predict p, Label& L ); 1.1733 + 1.1734 + // unconditional short branch 1.1735 + inline void ba( bool a, Label& L ); 1.1736 + 1.1737 + // Branch that tests fp condition codes 1.1738 + inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); 1.1739 + inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); 1.1740 + 1.1741 + // get PC the best way 1.1742 + inline int get_pc( Register d ); 1.1743 + 1.1744 + // Sparc shorthands(pp 85, V8 manual, pp 289 V9 manual) 1.1745 + inline void cmp( Register s1, Register s2 ) { subcc( s1, s2, G0 ); } 1.1746 + inline void cmp( Register s1, int simm13a ) { subcc( s1, simm13a, G0 ); } 1.1747 + 1.1748 + inline void jmp( Register s1, Register s2 ); 1.1749 + inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); 1.1750 + 1.1751 + inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); 1.1752 + inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); 1.1753 + inline void callr( Register s1, Register s2 ); 1.1754 + inline void callr( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); 1.1755 + 1.1756 + // Emits nothing on V8 1.1757 + inline void iprefetch( address d, relocInfo::relocType rt = relocInfo::none ); 1.1758 + inline void iprefetch( Label& L); 1.1759 + 1.1760 + inline void tst( Register s ) { orcc( G0, s, G0 ); } 1.1761 + 1.1762 +#ifdef PRODUCT 1.1763 + inline void ret( bool trace = TraceJumps ) { if (trace) { 1.1764 + mov(I7, O7); // traceable register 1.1765 + JMP(O7, 2 * BytesPerInstWord); 1.1766 + } else { 1.1767 + jmpl( I7, 2 * BytesPerInstWord, G0 ); 1.1768 + } 1.1769 + } 1.1770 + 1.1771 + inline void retl( bool trace = TraceJumps ) { if (trace) JMP(O7, 2 * BytesPerInstWord); 1.1772 + else jmpl( O7, 2 * BytesPerInstWord, G0 ); } 1.1773 +#else 1.1774 + void ret( bool trace = TraceJumps ); 1.1775 + void retl( bool trace = TraceJumps ); 1.1776 +#endif /* PRODUCT */ 1.1777 + 1.1778 + // Required platform-specific helpers for Label::patch_instructions. 1.1779 + // They _shadow_ the declarations in AbstractAssembler, which are undefined. 1.1780 + void pd_patch_instruction(address branch, address target); 1.1781 +#ifndef PRODUCT 1.1782 + static void pd_print_patched_instruction(address branch); 1.1783 +#endif 1.1784 + 1.1785 + // sethi Macro handles optimizations and relocations 1.1786 + void sethi( Address& a, bool ForceRelocatable = false ); 1.1787 + void sethi( intptr_t imm22a, Register d, bool ForceRelocatable = false, RelocationHolder const& rspec = RelocationHolder()); 1.1788 + 1.1789 + // compute the size of a sethi/set 1.1790 + static int size_of_sethi( address a, bool worst_case = false ); 1.1791 + static int worst_case_size_of_set(); 1.1792 + 1.1793 + // set may be either setsw or setuw (high 32 bits may be zero or sign) 1.1794 + void set( intptr_t value, Register d, RelocationHolder const& rspec = RelocationHolder() ); 1.1795 + void setsw( int value, Register d, RelocationHolder const& rspec = RelocationHolder() ); 1.1796 + void set64( jlong value, Register d, Register tmp); 1.1797 + 1.1798 + // sign-extend 32 to 64 1.1799 + inline void signx( Register s, Register d ) { sra( s, G0, d); } 1.1800 + inline void signx( Register d ) { sra( d, G0, d); } 1.1801 + 1.1802 + inline void not1( Register s, Register d ) { xnor( s, G0, d ); } 1.1803 + inline void not1( Register d ) { xnor( d, G0, d ); } 1.1804 + 1.1805 + inline void neg( Register s, Register d ) { sub( G0, s, d ); } 1.1806 + inline void neg( Register d ) { sub( G0, d, d ); } 1.1807 + 1.1808 + inline void cas( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY); } 1.1809 + inline void casx( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY); } 1.1810 + // Functions for isolating 64 bit atomic swaps for LP64 1.1811 + // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's 1.1812 + inline void cas_ptr( Register s1, Register s2, Register d) { 1.1813 +#ifdef _LP64 1.1814 + casx( s1, s2, d ); 1.1815 +#else 1.1816 + cas( s1, s2, d ); 1.1817 +#endif 1.1818 + } 1.1819 + 1.1820 + // Functions for isolating 64 bit shifts for LP64 1.1821 + inline void sll_ptr( Register s1, Register s2, Register d ); 1.1822 + inline void sll_ptr( Register s1, int imm6a, Register d ); 1.1823 + inline void srl_ptr( Register s1, Register s2, Register d ); 1.1824 + inline void srl_ptr( Register s1, int imm6a, Register d ); 1.1825 + 1.1826 + // little-endian 1.1827 + inline void casl( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY_LITTLE); } 1.1828 + inline void casxl( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY_LITTLE); } 1.1829 + 1.1830 + inline void inc( Register d, int const13 = 1 ) { add( d, const13, d); } 1.1831 + inline void inccc( Register d, int const13 = 1 ) { addcc( d, const13, d); } 1.1832 + 1.1833 + inline void dec( Register d, int const13 = 1 ) { sub( d, const13, d); } 1.1834 + inline void deccc( Register d, int const13 = 1 ) { subcc( d, const13, d); } 1.1835 + 1.1836 + inline void btst( Register s1, Register s2 ) { andcc( s1, s2, G0 ); } 1.1837 + inline void btst( int simm13a, Register s ) { andcc( s, simm13a, G0 ); } 1.1838 + 1.1839 + inline void bset( Register s1, Register s2 ) { or3( s1, s2, s2 ); } 1.1840 + inline void bset( int simm13a, Register s ) { or3( s, simm13a, s ); } 1.1841 + 1.1842 + inline void bclr( Register s1, Register s2 ) { andn( s1, s2, s2 ); } 1.1843 + inline void bclr( int simm13a, Register s ) { andn( s, simm13a, s ); } 1.1844 + 1.1845 + inline void btog( Register s1, Register s2 ) { xor3( s1, s2, s2 ); } 1.1846 + inline void btog( int simm13a, Register s ) { xor3( s, simm13a, s ); } 1.1847 + 1.1848 + inline void clr( Register d ) { or3( G0, G0, d ); } 1.1849 + 1.1850 + inline void clrb( Register s1, Register s2); 1.1851 + inline void clrh( Register s1, Register s2); 1.1852 + inline void clr( Register s1, Register s2); 1.1853 + inline void clrx( Register s1, Register s2); 1.1854 + 1.1855 + inline void clrb( Register s1, int simm13a); 1.1856 + inline void clrh( Register s1, int simm13a); 1.1857 + inline void clr( Register s1, int simm13a); 1.1858 + inline void clrx( Register s1, int simm13a); 1.1859 + 1.1860 + // copy & clear upper word 1.1861 + inline void clruw( Register s, Register d ) { srl( s, G0, d); } 1.1862 + // clear upper word 1.1863 + inline void clruwu( Register d ) { srl( d, G0, d); } 1.1864 + 1.1865 + // membar psuedo instruction. takes into account target memory model. 1.1866 + inline void membar( Assembler::Membar_mask_bits const7a ); 1.1867 + 1.1868 + // returns if membar generates anything. 1.1869 + inline bool membar_has_effect( Assembler::Membar_mask_bits const7a ); 1.1870 + 1.1871 + // mov pseudo instructions 1.1872 + inline void mov( Register s, Register d) { 1.1873 + if ( s != d ) or3( G0, s, d); 1.1874 + else assert_not_delayed(); // Put something useful in the delay slot! 1.1875 + } 1.1876 + 1.1877 + inline void mov_or_nop( Register s, Register d) { 1.1878 + if ( s != d ) or3( G0, s, d); 1.1879 + else nop(); 1.1880 + } 1.1881 + 1.1882 + inline void mov( int simm13a, Register d) { or3( G0, simm13a, d); } 1.1883 + 1.1884 + // address pseudos: make these names unlike instruction names to avoid confusion 1.1885 + inline void split_disp( Address& a, Register temp ); 1.1886 + inline intptr_t load_pc_address( Register reg, int bytes_to_skip ); 1.1887 + inline void load_address( Address& a, int offset = 0 ); 1.1888 + inline void load_contents( Address& a, Register d, int offset = 0 ); 1.1889 + inline void load_ptr_contents( Address& a, Register d, int offset = 0 ); 1.1890 + inline void store_contents( Register s, Address& a, int offset = 0 ); 1.1891 + inline void store_ptr_contents( Register s, Address& a, int offset = 0 ); 1.1892 + inline void jumpl_to( Address& a, Register d, int offset = 0 ); 1.1893 + inline void jump_to( Address& a, int offset = 0 ); 1.1894 + 1.1895 + // ring buffer traceable jumps 1.1896 + 1.1897 + void jmp2( Register r1, Register r2, const char* file, int line ); 1.1898 + void jmp ( Register r1, int offset, const char* file, int line ); 1.1899 + 1.1900 + void jumpl( Address& a, Register d, int offset, const char* file, int line ); 1.1901 + void jump ( Address& a, int offset, const char* file, int line ); 1.1902 + 1.1903 + 1.1904 + // argument pseudos: 1.1905 + 1.1906 + inline void load_argument( Argument& a, Register d ); 1.1907 + inline void store_argument( Register s, Argument& a ); 1.1908 + inline void store_ptr_argument( Register s, Argument& a ); 1.1909 + inline void store_float_argument( FloatRegister s, Argument& a ); 1.1910 + inline void store_double_argument( FloatRegister s, Argument& a ); 1.1911 + inline void store_long_argument( Register s, Argument& a ); 1.1912 + 1.1913 + // handy macros: 1.1914 + 1.1915 + inline void round_to( Register r, int modulus ) { 1.1916 + assert_not_delayed(); 1.1917 + inc( r, modulus - 1 ); 1.1918 + and3( r, -modulus, r ); 1.1919 + } 1.1920 + 1.1921 + // -------------------------------------------------- 1.1922 + 1.1923 + // Functions for isolating 64 bit loads for LP64 1.1924 + // ld_ptr will perform ld for 32 bit VM's and ldx for 64 bit VM's 1.1925 + // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's 1.1926 + inline void ld_ptr( Register s1, Register s2, Register d ); 1.1927 + inline void ld_ptr( Register s1, int simm13a, Register d); 1.1928 + inline void ld_ptr( const Address& a, Register d, int offset = 0 ); 1.1929 + inline void st_ptr( Register d, Register s1, Register s2 ); 1.1930 + inline void st_ptr( Register d, Register s1, int simm13a); 1.1931 + inline void st_ptr( Register d, const Address& a, int offset = 0 ); 1.1932 + 1.1933 + // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's 1.1934 + // st_long will perform st for 32 bit VM's and stx for 64 bit VM's 1.1935 + inline void ld_long( Register s1, Register s2, Register d ); 1.1936 + inline void ld_long( Register s1, int simm13a, Register d ); 1.1937 + inline void ld_long( const Address& a, Register d, int offset = 0 ); 1.1938 + inline void st_long( Register d, Register s1, Register s2 ); 1.1939 + inline void st_long( Register d, Register s1, int simm13a ); 1.1940 + inline void st_long( Register d, const Address& a, int offset = 0 ); 1.1941 + 1.1942 + // -------------------------------------------------- 1.1943 + 1.1944 + public: 1.1945 + // traps as per trap.h (SPARC ABI?) 1.1946 + 1.1947 + void breakpoint_trap(); 1.1948 + void breakpoint_trap(Condition c, CC cc = icc); 1.1949 + void flush_windows_trap(); 1.1950 + void clean_windows_trap(); 1.1951 + void get_psr_trap(); 1.1952 + void set_psr_trap(); 1.1953 + 1.1954 + // V8/V9 flush_windows 1.1955 + void flush_windows(); 1.1956 + 1.1957 + // Support for serializing memory accesses between threads 1.1958 + void serialize_memory(Register thread, Register tmp1, Register tmp2); 1.1959 + 1.1960 + // Stack frame creation/removal 1.1961 + void enter(); 1.1962 + void leave(); 1.1963 + 1.1964 + // V8/V9 integer multiply 1.1965 + void mult(Register s1, Register s2, Register d); 1.1966 + void mult(Register s1, int simm13a, Register d); 1.1967 + 1.1968 + // V8/V9 read and write of condition codes. 1.1969 + void read_ccr(Register d); 1.1970 + void write_ccr(Register s); 1.1971 + 1.1972 + // Manipulation of C++ bools 1.1973 + // These are idioms to flag the need for care with accessing bools but on 1.1974 + // this platform we assume byte size 1.1975 + 1.1976 + inline void stbool( Register d, const Address& a, int offset = 0 ) { stb(d, a, offset); } 1.1977 + inline void ldbool( const Address& a, Register d, int offset = 0 ) { ldsb( a, d, offset ); } 1.1978 + inline void tstbool( Register s ) { tst(s); } 1.1979 + inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } 1.1980 + 1.1981 + // Support for managing the JavaThread pointer (i.e.; the reference to 1.1982 + // thread-local information). 1.1983 + void get_thread(); // load G2_thread 1.1984 + void verify_thread(); // verify G2_thread contents 1.1985 + void save_thread (const Register threache); // save to cache 1.1986 + void restore_thread(const Register thread_cache); // restore from cache 1.1987 + 1.1988 + // Support for last Java frame (but use call_VM instead where possible) 1.1989 + void set_last_Java_frame(Register last_java_sp, Register last_Java_pc); 1.1990 + void reset_last_Java_frame(void); 1.1991 + 1.1992 + // Call into the VM. 1.1993 + // Passes the thread pointer (in O0) as a prepended argument. 1.1994 + // Makes sure oop return values are visible to the GC. 1.1995 + void call_VM(Register oop_result, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); 1.1996 + void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true); 1.1997 + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); 1.1998 + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); 1.1999 + 1.2000 + // these overloadings are not presently used on SPARC: 1.2001 + void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); 1.2002 + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); 1.2003 + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); 1.2004 + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); 1.2005 + 1.2006 + void call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments = 0); 1.2007 + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1); 1.2008 + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2); 1.2009 + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3); 1.2010 + 1.2011 + void get_vm_result (Register oop_result); 1.2012 + void get_vm_result_2(Register oop_result); 1.2013 + 1.2014 + // vm result is currently getting hijacked to for oop preservation 1.2015 + void set_vm_result(Register oop_result); 1.2016 + 1.2017 + // if call_VM_base was called with check_exceptions=false, then call 1.2018 + // check_and_forward_exception to handle exceptions when it is safe 1.2019 + void check_and_forward_exception(Register scratch_reg); 1.2020 + 1.2021 + private: 1.2022 + // For V8 1.2023 + void read_ccr_trap(Register ccr_save); 1.2024 + void write_ccr_trap(Register ccr_save1, Register scratch1, Register scratch2); 1.2025 + 1.2026 +#ifdef ASSERT 1.2027 + // For V8 debugging. Uses V8 instruction sequence and checks 1.2028 + // result with V9 insturctions rdccr and wrccr. 1.2029 + // Uses Gscatch and Gscatch2 1.2030 + void read_ccr_v8_assert(Register ccr_save); 1.2031 + void write_ccr_v8_assert(Register ccr_save); 1.2032 +#endif // ASSERT 1.2033 + 1.2034 + public: 1.2035 + // Stores 1.2036 + void store_check(Register tmp, Register obj); // store check for obj - register is destroyed afterwards 1.2037 + void store_check(Register tmp, Register obj, Register offset); // store check for obj - register is destroyed afterwards 1.2038 + 1.2039 + // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack 1.2040 + void push_fTOS(); 1.2041 + 1.2042 + // pops double TOS element from CPU stack and pushes on FPU stack 1.2043 + void pop_fTOS(); 1.2044 + 1.2045 + void empty_FPU_stack(); 1.2046 + 1.2047 + void push_IU_state(); 1.2048 + void pop_IU_state(); 1.2049 + 1.2050 + void push_FPU_state(); 1.2051 + void pop_FPU_state(); 1.2052 + 1.2053 + void push_CPU_state(); 1.2054 + void pop_CPU_state(); 1.2055 + 1.2056 + // Debugging 1.2057 + void _verify_oop(Register reg, const char * msg, const char * file, int line); 1.2058 + void _verify_oop_addr(Address addr, const char * msg, const char * file, int line); 1.2059 + 1.2060 +#define verify_oop(reg) _verify_oop(reg, "broken oop " #reg, __FILE__, __LINE__) 1.2061 +#define verify_oop_addr(addr) _verify_oop_addr(addr, "broken oop addr ", __FILE__, __LINE__) 1.2062 + 1.2063 + // only if +VerifyOops 1.2064 + void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); 1.2065 + // only if +VerifyFPU 1.2066 + void stop(const char* msg); // prints msg, dumps registers and stops execution 1.2067 + void warn(const char* msg); // prints msg, but don't stop 1.2068 + void untested(const char* what = ""); 1.2069 + void unimplemented(const char* what = "") { char* b = new char[1024]; sprintf(b, "unimplemented: %s", what); stop(b); } 1.2070 + void should_not_reach_here() { stop("should not reach here"); } 1.2071 + void print_CPU_state(); 1.2072 + 1.2073 + // oops in code 1.2074 + Address allocate_oop_address( jobject obj, Register d ); // allocate_index 1.2075 + Address constant_oop_address( jobject obj, Register d ); // find_index 1.2076 + inline void set_oop ( jobject obj, Register d ); // uses allocate_oop_address 1.2077 + inline void set_oop_constant( jobject obj, Register d ); // uses constant_oop_address 1.2078 + inline void set_oop ( Address obj_addr ); // same as load_address 1.2079 + 1.2080 + // nop padding 1.2081 + void align(int modulus); 1.2082 + 1.2083 + // declare a safepoint 1.2084 + void safepoint(); 1.2085 + 1.2086 + // factor out part of stop into subroutine to save space 1.2087 + void stop_subroutine(); 1.2088 + // factor out part of verify_oop into subroutine to save space 1.2089 + void verify_oop_subroutine(); 1.2090 + 1.2091 + // side-door communication with signalHandler in os_solaris.cpp 1.2092 + static address _verify_oop_implicit_branch[3]; 1.2093 + 1.2094 +#ifndef PRODUCT 1.2095 + static void test(); 1.2096 +#endif 1.2097 + 1.2098 + // convert an incoming arglist to varargs format; put the pointer in d 1.2099 + void set_varargs( Argument a, Register d ); 1.2100 + 1.2101 + int total_frame_size_in_bytes(int extraWords); 1.2102 + 1.2103 + // used when extraWords known statically 1.2104 + void save_frame(int extraWords); 1.2105 + void save_frame_c1(int size_in_bytes); 1.2106 + // make a frame, and simultaneously pass up one or two register value 1.2107 + // into the new register window 1.2108 + void save_frame_and_mov(int extraWords, Register s1, Register d1, Register s2 = Register(), Register d2 = Register()); 1.2109 + 1.2110 + // give no. (outgoing) params, calc # of words will need on frame 1.2111 + void calc_mem_param_words(Register Rparam_words, Register Rresult); 1.2112 + 1.2113 + // used to calculate frame size dynamically 1.2114 + // result is in bytes and must be negated for save inst 1.2115 + void calc_frame_size(Register extraWords, Register resultReg); 1.2116 + 1.2117 + // calc and also save 1.2118 + void calc_frame_size_and_save(Register extraWords, Register resultReg); 1.2119 + 1.2120 + static void debug(char* msg, RegistersForDebugging* outWindow); 1.2121 + 1.2122 + // implementations of bytecodes used by both interpreter and compiler 1.2123 + 1.2124 + void lcmp( Register Ra_hi, Register Ra_low, 1.2125 + Register Rb_hi, Register Rb_low, 1.2126 + Register Rresult); 1.2127 + 1.2128 + void lneg( Register Rhi, Register Rlow ); 1.2129 + 1.2130 + void lshl( Register Rin_high, Register Rin_low, Register Rcount, 1.2131 + Register Rout_high, Register Rout_low, Register Rtemp ); 1.2132 + 1.2133 + void lshr( Register Rin_high, Register Rin_low, Register Rcount, 1.2134 + Register Rout_high, Register Rout_low, Register Rtemp ); 1.2135 + 1.2136 + void lushr( Register Rin_high, Register Rin_low, Register Rcount, 1.2137 + Register Rout_high, Register Rout_low, Register Rtemp ); 1.2138 + 1.2139 +#ifdef _LP64 1.2140 + void lcmp( Register Ra, Register Rb, Register Rresult); 1.2141 +#endif 1.2142 + 1.2143 + void float_cmp( bool is_float, int unordered_result, 1.2144 + FloatRegister Fa, FloatRegister Fb, 1.2145 + Register Rresult); 1.2146 + 1.2147 + void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); 1.2148 + void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { Assembler::fneg(w, sd); } 1.2149 + void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); 1.2150 + void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); 1.2151 + 1.2152 + void save_all_globals_into_locals(); 1.2153 + void restore_globals_from_locals(); 1.2154 + 1.2155 + void casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, 1.2156 + address lock_addr=0, bool use_call_vm=false); 1.2157 + void cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, 1.2158 + address lock_addr=0, bool use_call_vm=false); 1.2159 + void casn (Register addr_reg, Register cmp_reg, Register set_reg) ; 1.2160 + 1.2161 + // These set the icc condition code to equal if the lock succeeded 1.2162 + // and notEqual if it failed and requires a slow case 1.2163 + void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch, 1.2164 + BiasedLockingCounters* counters = NULL); 1.2165 + void compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch); 1.2166 + 1.2167 + // Biased locking support 1.2168 + // Upon entry, lock_reg must point to the lock record on the stack, 1.2169 + // obj_reg must contain the target object, and mark_reg must contain 1.2170 + // the target object's header. 1.2171 + // Destroys mark_reg if an attempt is made to bias an anonymously 1.2172 + // biased lock. In this case a failure will go either to the slow 1.2173 + // case or fall through with the notEqual condition code set with 1.2174 + // the expectation that the slow case in the runtime will be called. 1.2175 + // In the fall-through case where the CAS-based lock is done, 1.2176 + // mark_reg is not destroyed. 1.2177 + void biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, 1.2178 + Label& done, Label* slow_case = NULL, 1.2179 + BiasedLockingCounters* counters = NULL); 1.2180 + // Upon entry, the base register of mark_addr must contain the oop. 1.2181 + // Destroys temp_reg. 1.2182 + 1.2183 + // If allow_delay_slot_filling is set to true, the next instruction 1.2184 + // emitted after this one will go in an annulled delay slot if the 1.2185 + // biased locking exit case failed. 1.2186 + void biased_locking_exit(Address mark_addr, Register temp_reg, Label& done, bool allow_delay_slot_filling = false); 1.2187 + 1.2188 + // allocation 1.2189 + void eden_allocate( 1.2190 + Register obj, // result: pointer to object after successful allocation 1.2191 + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise 1.2192 + int con_size_in_bytes, // object size in bytes if known at compile time 1.2193 + Register t1, // temp register 1.2194 + Register t2, // temp register 1.2195 + Label& slow_case // continuation point if fast allocation fails 1.2196 + ); 1.2197 + void tlab_allocate( 1.2198 + Register obj, // result: pointer to object after successful allocation 1.2199 + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise 1.2200 + int con_size_in_bytes, // object size in bytes if known at compile time 1.2201 + Register t1, // temp register 1.2202 + Label& slow_case // continuation point if fast allocation fails 1.2203 + ); 1.2204 + void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); 1.2205 + 1.2206 + // Stack overflow checking 1.2207 + 1.2208 + // Note: this clobbers G3_scratch 1.2209 + void bang_stack_with_offset(int offset) { 1.2210 + // stack grows down, caller passes positive offset 1.2211 + assert(offset > 0, "must bang with negative offset"); 1.2212 + set((-offset)+STACK_BIAS, G3_scratch); 1.2213 + st(G0, SP, G3_scratch); 1.2214 + } 1.2215 + 1.2216 + // Writes to stack successive pages until offset reached to check for 1.2217 + // stack overflow + shadow pages. Clobbers tsp and scratch registers. 1.2218 + void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); 1.2219 + 1.2220 + void verify_tlab(); 1.2221 + 1.2222 + Condition negate_condition(Condition cond); 1.2223 + 1.2224 + // Helper functions for statistics gathering. 1.2225 + // Conditionally (non-atomically) increments passed counter address, preserving condition codes. 1.2226 + void cond_inc(Condition cond, address counter_addr, Register Rtemp1, Register Rtemp2); 1.2227 + // Unconditional increment. 1.2228 + void inc_counter(address counter_addr, Register Rtemp1, Register Rtemp2); 1.2229 + 1.2230 +#undef VIRTUAL 1.2231 + 1.2232 +}; 1.2233 + 1.2234 +/** 1.2235 + * class SkipIfEqual: 1.2236 + * 1.2237 + * Instantiating this class will result in assembly code being output that will 1.2238 + * jump around any code emitted between the creation of the instance and it's 1.2239 + * automatic destruction at the end of a scope block, depending on the value of 1.2240 + * the flag passed to the constructor, which will be checked at run-time. 1.2241 + */ 1.2242 +class SkipIfEqual : public StackObj { 1.2243 + private: 1.2244 + MacroAssembler* _masm; 1.2245 + Label _label; 1.2246 + 1.2247 + public: 1.2248 + // 'temp' is a temp register that this object can use (and trash) 1.2249 + SkipIfEqual(MacroAssembler*, Register temp, 1.2250 + const bool* flag_addr, Assembler::Condition condition); 1.2251 + ~SkipIfEqual(); 1.2252 +}; 1.2253 + 1.2254 +#ifdef ASSERT 1.2255 +// On RISC, there's no benefit to verifying instruction boundaries. 1.2256 +inline bool AbstractAssembler::pd_check_instruction_mark() { return false; } 1.2257 +#endif