src/cpu/mips/vm/assembler_mips.hpp

Tue, 28 Jun 2016 16:34:47 +0800

author
aoqi<aoqi@loongson.cn>
date
Tue, 28 Jun 2016 16:34:47 +0800
changeset 30
45b68a4063c2
parent 29
6c147e7e4605
child 37
440521e9c713
permissions
-rw-r--r--

[Code Reorganization] Moved fast_lock and fast_unlock from mips_64.ad to MacroAssembler.

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@1 3 * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
aoqi@1 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@1 5 *
aoqi@1 6 * This code is free software; you can redistribute it and/or modify it
aoqi@1 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@1 8 * published by the Free Software Foundation.
aoqi@1 9 *
aoqi@1 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@1 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@1 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@1 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@1 14 * accompanied this code).
aoqi@1 15 *
aoqi@1 16 * You should have received a copy of the GNU General Public License version
aoqi@1 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@1 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@1 19 *
aoqi@1 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@1 21 * or visit www.oracle.com if you need additional information or have any
aoqi@1 22 * questions.
aoqi@1 23 *
aoqi@1 24 */
aoqi@1 25
aoqi@1 26 #ifndef CPU_MIPS_VM_ASSEMBLER_MIPS_HPP
aoqi@1 27 #define CPU_MIPS_VM_ASSEMBLER_MIPS_HPP
aoqi@1 28
aoqi@1 29 #include "asm/register.hpp"
aoqi@1 30
aoqi@1 31 class BiasedLockingCounters;
aoqi@1 32
aoqi@1 33
aoqi@1 34 // Note: A register location is represented via a Register, not
aoqi@1 35 // via an address for efficiency & simplicity reasons.
aoqi@1 36
aoqi@1 37 class ArrayAddress;
aoqi@1 38
aoqi@1 39 class Address VALUE_OBJ_CLASS_SPEC {
aoqi@1 40
aoqi@1 41 public:
aoqi@1 42 enum ScaleFactor {
aoqi@1 43 no_scale = -1,
aoqi@1 44 times_1 = 0,
aoqi@1 45 times_2 = 1,
aoqi@1 46 times_4 = 2,
aoqi@1 47 times_8 = 3,
aoqi@1 48 times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4)
aoqi@1 49 };
aoqi@1 50
aoqi@1 51 static ScaleFactor times(int size) {
aoqi@1 52 assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size");
aoqi@1 53 if (size == 8) return times_8;
aoqi@1 54 if (size == 4) return times_4;
aoqi@1 55 if (size == 2) return times_2;
aoqi@1 56 return times_1;
aoqi@1 57 }
aoqi@1 58
aoqi@1 59 private:
aoqi@1 60 Register _base;
aoqi@1 61 Register _index;
aoqi@1 62 ScaleFactor _scale;
aoqi@1 63 int _disp;
aoqi@1 64 RelocationHolder _rspec;
aoqi@1 65
aoqi@1 66 // Easily misused constructors make them private
aoqi@1 67 // %%% can we make these go away?
aoqi@1 68 //FIXME aoqi
aoqi@1 69 //NOT_LP64(Address(address loc, RelocationHolder spec);)
aoqi@1 70 Address(address loc, RelocationHolder spec);
aoqi@1 71 Address(int disp, address loc, relocInfo::relocType rtype);
aoqi@1 72 Address(int disp, address loc, RelocationHolder spec);
aoqi@1 73
aoqi@1 74 public:
aoqi@1 75
aoqi@1 76 int disp() { return _disp; }
aoqi@1 77 // creation
aoqi@1 78 Address()
aoqi@1 79 : _base(noreg),
aoqi@1 80 _index(noreg),
aoqi@1 81 _scale(no_scale),
aoqi@1 82 _disp(0) {
aoqi@1 83 }
aoqi@1 84
aoqi@1 85 // No default displacement otherwise Register can be implicitly
aoqi@1 86 // converted to 0(Register) which is quite a different animal.
aoqi@1 87
aoqi@1 88 Address(Register base, int disp)
aoqi@1 89 : _base(base),
aoqi@1 90 _index(noreg),
aoqi@1 91 _scale(no_scale),
aoqi@1 92 _disp(disp) {
aoqi@1 93 }
aoqi@1 94
aoqi@1 95 Address(Register base)
aoqi@1 96 : _base(base),
aoqi@1 97 _index(noreg),
aoqi@1 98 _scale(no_scale),
aoqi@1 99 _disp(0) {
aoqi@1 100 }
aoqi@1 101
aoqi@1 102 Address(Register base, Register index, ScaleFactor scale, int disp = 0)
aoqi@1 103 : _base (base),
aoqi@1 104 _index(index),
aoqi@1 105 _scale(scale),
aoqi@1 106 _disp (disp) {
aoqi@1 107 assert(!index->is_valid() == (scale == Address::no_scale),
aoqi@1 108 "inconsistent address");
aoqi@1 109 }
aoqi@1 110
aoqi@1 111 // The following two overloads are used in connection with the
aoqi@1 112 // ByteSize type (see sizes.hpp). They simplify the use of
aoqi@1 113 // ByteSize'd arguments in assembly code. Note that their equivalent
aoqi@1 114 // for the optimized build are the member functions with int disp
aoqi@1 115 // argument since ByteSize is mapped to an int type in that case.
aoqi@1 116 //
aoqi@1 117 // Note: DO NOT introduce similar overloaded functions for WordSize
aoqi@1 118 // arguments as in the optimized mode, both ByteSize and WordSize
aoqi@1 119 // are mapped to the same type and thus the compiler cannot make a
aoqi@1 120 // distinction anymore (=> compiler errors).
aoqi@1 121
aoqi@1 122 #ifdef ASSERT
aoqi@1 123 Address(Register base, ByteSize disp)
aoqi@1 124 : _base(base),
aoqi@1 125 _index(noreg),
aoqi@1 126 _scale(no_scale),
aoqi@1 127 _disp(in_bytes(disp)) {
aoqi@1 128 }
aoqi@1 129
aoqi@1 130 Address(Register base, Register index, ScaleFactor scale, ByteSize disp)
aoqi@1 131 : _base(base),
aoqi@1 132 _index(index),
aoqi@1 133 _scale(scale),
aoqi@1 134 _disp(in_bytes(disp)) {
aoqi@1 135 assert(!index->is_valid() == (scale == Address::no_scale),
aoqi@1 136 "inconsistent address");
aoqi@1 137 }
aoqi@1 138 #endif // ASSERT
aoqi@1 139
aoqi@1 140 // accessors
aoqi@1 141 bool uses(Register reg) const { return _base == reg || _index == reg; }
aoqi@1 142 Register base() const { return _base; }
aoqi@1 143 Register index() const { return _index; }
aoqi@1 144 ScaleFactor scale() const { return _scale; }
aoqi@1 145 int disp() const { return _disp; }
aoqi@1 146
aoqi@1 147 // Convert the raw encoding form into the form expected by the constructor for
aoqi@1 148 // Address. An index of 4 (rsp) corresponds to having no index, so convert
aoqi@1 149 // that to noreg for the Address constructor.
aoqi@1 150 //static Address make_raw(int base, int index, int scale, int disp);
aoqi@1 151
aoqi@1 152 static Address make_array(ArrayAddress);
aoqi@1 153
aoqi@1 154 /*
aoqi@1 155 private:
aoqi@1 156 bool base_needs_rex() const {
aoqi@1 157 return _base != noreg && _base->encoding() >= 8;
aoqi@1 158 }
aoqi@1 159
aoqi@1 160 bool index_needs_rex() const {
aoqi@1 161 return _index != noreg &&_index->encoding() >= 8;
aoqi@1 162 }
aoqi@1 163
aoqi@1 164 relocInfo::relocType reloc() const { return _rspec.type(); }
aoqi@1 165 */
aoqi@1 166 friend class Assembler;
aoqi@1 167 friend class MacroAssembler;
aoqi@1 168 friend class LIR_Assembler; // base/index/scale/disp
aoqi@1 169 };
aoqi@1 170
aoqi@1 171
aoqi@1 172 // Calling convention
aoqi@1 173 class Argument VALUE_OBJ_CLASS_SPEC {
aoqi@1 174 private:
aoqi@1 175 int _number;
aoqi@1 176 public:
aoqi@1 177 enum {
aoqi@1 178 #ifdef _LP64
aoqi@1 179 n_register_parameters = 8, // 8 integer registers used to pass parameters
aoqi@1 180 n_float_register_parameters = 8 // 4 float registers used to pass parameters
aoqi@1 181 #else
aoqi@1 182 n_register_parameters = 4, // 4 integer registers used to pass parameters
aoqi@1 183 n_float_register_parameters = 4 // 4 float registers used to pass parameters
aoqi@1 184 #endif
aoqi@1 185 };
aoqi@1 186
aoqi@1 187 Argument(int number):_number(number){ }
aoqi@1 188 Argument successor() {return Argument(number() + 1);}
aoqi@1 189
aoqi@1 190 int number()const {return _number;}
aoqi@1 191 bool is_Register()const {return _number < n_register_parameters;}
aoqi@1 192 bool is_FloatRegister()const {return _number < n_float_register_parameters;}
aoqi@1 193
aoqi@1 194 Register as_Register()const {
aoqi@1 195 assert(is_Register(), "must be a register argument");
aoqi@1 196 return ::as_Register(A0->encoding() + _number);
aoqi@1 197 }
aoqi@1 198 FloatRegister as_FloatRegister()const {
aoqi@1 199 assert(is_FloatRegister(), "must be a float register argument");
aoqi@1 200 return ::as_FloatRegister(F12->encoding() + _number);
aoqi@1 201 }
aoqi@1 202
aoqi@1 203 Address as_caller_address()const {return Address(SP, (number() LP64_ONLY( -n_register_parameters)) * wordSize);}
aoqi@1 204 };
aoqi@1 205
aoqi@1 206
aoqi@1 207
aoqi@1 208 //
aoqi@1 209 // AddressLiteral has been split out from Address because operands of this type
aoqi@1 210 // need to be treated specially on 32bit vs. 64bit platforms. By splitting it out
aoqi@1 211 // the few instructions that need to deal with address literals are unique and the
aoqi@1 212 // MacroAssembler does not have to implement every instruction in the Assembler
aoqi@1 213 // in order to search for address literals that may need special handling depending
aoqi@1 214 // on the instruction and the platform. As small step on the way to merging i486/amd64
aoqi@1 215 // directories.
aoqi@1 216 //
aoqi@1 217 class AddressLiteral VALUE_OBJ_CLASS_SPEC {
aoqi@1 218 friend class ArrayAddress;
aoqi@1 219 RelocationHolder _rspec;
aoqi@1 220 // Typically we use AddressLiterals we want to use their rval
aoqi@1 221 // However in some situations we want the lval (effect address) of the item.
aoqi@1 222 // We provide a special factory for making those lvals.
aoqi@1 223 bool _is_lval;
aoqi@1 224
aoqi@1 225 // If the target is far we'll need to load the ea of this to
aoqi@1 226 // a register to reach it. Otherwise if near we can do rip
aoqi@1 227 // relative addressing.
aoqi@1 228
aoqi@1 229 address _target;
aoqi@1 230
aoqi@1 231 protected:
aoqi@1 232 // creation
aoqi@1 233 AddressLiteral()
aoqi@1 234 : _is_lval(false),
aoqi@1 235 _target(NULL)
aoqi@1 236 {}
aoqi@1 237
aoqi@1 238 public:
aoqi@1 239
aoqi@1 240 AddressLiteral(address target, relocInfo::relocType rtype);
aoqi@1 241
aoqi@1 242 AddressLiteral(address target, RelocationHolder const& rspec)
aoqi@1 243 : _rspec(rspec),
aoqi@1 244 _is_lval(false),
aoqi@1 245 _target(target)
aoqi@1 246 {}
aoqi@1 247 #ifdef _LP64
aoqi@1 248 // 32-bit complains about a multiple declaration for int*.
aoqi@1 249 AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none)
aoqi@1 250 : _target((address) addr),
aoqi@1 251 _rspec(rspec_from_rtype(rtype, (address) addr)) {}
aoqi@1 252 #endif
aoqi@1 253
aoqi@1 254
aoqi@1 255 AddressLiteral addr() {
aoqi@1 256 AddressLiteral ret = *this;
aoqi@1 257 ret._is_lval = true;
aoqi@1 258 return ret;
aoqi@1 259 }
aoqi@1 260
aoqi@1 261
aoqi@1 262 private:
aoqi@1 263
aoqi@1 264 address target() { return _target; }
aoqi@1 265 bool is_lval() { return _is_lval; }
aoqi@1 266
aoqi@1 267 relocInfo::relocType reloc() const { return _rspec.type(); }
aoqi@1 268 const RelocationHolder& rspec() const { return _rspec; }
aoqi@1 269
aoqi@1 270 friend class Assembler;
aoqi@1 271 friend class MacroAssembler;
aoqi@1 272 friend class Address;
aoqi@1 273 friend class LIR_Assembler;
aoqi@1 274 RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) {
aoqi@1 275 switch (rtype) {
aoqi@1 276 case relocInfo::external_word_type:
aoqi@1 277 return external_word_Relocation::spec(addr);
aoqi@1 278 case relocInfo::internal_word_type:
aoqi@1 279 return internal_word_Relocation::spec(addr);
aoqi@1 280 case relocInfo::opt_virtual_call_type:
aoqi@1 281 return opt_virtual_call_Relocation::spec();
aoqi@1 282 case relocInfo::static_call_type:
aoqi@1 283 return static_call_Relocation::spec();
aoqi@1 284 case relocInfo::runtime_call_type:
aoqi@1 285 return runtime_call_Relocation::spec();
aoqi@1 286 case relocInfo::poll_type:
aoqi@1 287 case relocInfo::poll_return_type:
aoqi@1 288 return Relocation::spec_simple(rtype);
aoqi@1 289 case relocInfo::none:
aoqi@1 290 case relocInfo::oop_type:
aoqi@1 291 // Oops are a special case. Normally they would be their own section
aoqi@1 292 // but in cases like icBuffer they are literals in the code stream that
aoqi@1 293 // we don't have a section for. We use none so that we get a literal address
aoqi@1 294 // which is always patchable.
aoqi@1 295 return RelocationHolder();
aoqi@1 296 default:
aoqi@1 297 ShouldNotReachHere();
aoqi@1 298 return RelocationHolder();
aoqi@1 299 }
aoqi@1 300 }
aoqi@1 301
aoqi@1 302 };
aoqi@1 303
aoqi@1 304 // Convience classes
aoqi@1 305 class RuntimeAddress: public AddressLiteral {
aoqi@1 306
aoqi@1 307 public:
aoqi@1 308
aoqi@1 309 RuntimeAddress(address target) : AddressLiteral(target, relocInfo::runtime_call_type) {}
aoqi@1 310
aoqi@1 311 };
aoqi@1 312
aoqi@1 313 class OopAddress: public AddressLiteral {
aoqi@1 314
aoqi@1 315 public:
aoqi@1 316
aoqi@1 317 OopAddress(address target) : AddressLiteral(target, relocInfo::oop_type){}
aoqi@1 318
aoqi@1 319 };
aoqi@1 320
aoqi@1 321 class ExternalAddress: public AddressLiteral {
aoqi@1 322
aoqi@1 323 public:
aoqi@1 324
aoqi@1 325 ExternalAddress(address target) : AddressLiteral(target, relocInfo::external_word_type){}
aoqi@1 326
aoqi@1 327 };
aoqi@1 328
aoqi@1 329 class InternalAddress: public AddressLiteral {
aoqi@1 330
aoqi@1 331 public:
aoqi@1 332
aoqi@1 333 InternalAddress(address target) : AddressLiteral(target, relocInfo::internal_word_type) {}
aoqi@1 334
aoqi@1 335 };
aoqi@1 336
aoqi@1 337 // x86 can do array addressing as a single operation since disp can be an absolute
aoqi@1 338 // address amd64 can't. We create a class that expresses the concept but does extra
aoqi@1 339 // magic on amd64 to get the final result
aoqi@1 340
aoqi@1 341 class ArrayAddress VALUE_OBJ_CLASS_SPEC {
aoqi@1 342 private:
aoqi@1 343
aoqi@1 344 AddressLiteral _base;
aoqi@1 345 Address _index;
aoqi@1 346
aoqi@1 347 public:
aoqi@1 348
aoqi@1 349 ArrayAddress() {};
aoqi@1 350 ArrayAddress(AddressLiteral base, Address index): _base(base), _index(index) {};
aoqi@1 351 AddressLiteral base() { return _base; }
aoqi@1 352 Address index() { return _index; }
aoqi@1 353
aoqi@1 354 };
aoqi@1 355
aoqi@1 356 const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512 / wordSize);
aoqi@1 357
aoqi@1 358 // The MIPS LOONGSON Assembler: Pure assembler doing NO optimizations on the instruction
aoqi@1 359 // level ; i.e., what you write is what you get. The Assembler is generating code into
aoqi@1 360 // a CodeBuffer.
aoqi@1 361
aoqi@1 362 class Assembler : public AbstractAssembler {
aoqi@1 363 friend class AbstractAssembler; // for the non-virtual hack
aoqi@1 364 friend class LIR_Assembler; // as_Address()
aoqi@1 365 friend class StubGenerator;
aoqi@1 366
aoqi@1 367 public:
aoqi@1 368 enum ops {
aoqi@1 369 special_op = 0x00,
aoqi@1 370 regimm_op = 0x01,
aoqi@1 371 j_op = 0x02,
aoqi@1 372 jal_op = 0x03,
aoqi@1 373 beq_op = 0x04,
aoqi@1 374 bne_op = 0x05,
aoqi@1 375 blez_op = 0x06,
aoqi@1 376 bgtz_op = 0x07,
aoqi@1 377 addi_op = 0x08,
aoqi@1 378 addiu_op = 0x09,
aoqi@1 379 slti_op = 0x0a,
aoqi@1 380 sltiu_op = 0x0b,
aoqi@1 381 andi_op = 0x0c,
aoqi@1 382 ori_op = 0x0d,
aoqi@1 383 xori_op = 0x0e,
aoqi@1 384 lui_op = 0x0f,
aoqi@1 385 cop0_op = 0x10,
aoqi@1 386 cop1_op = 0x11,
aoqi@1 387 cop2_op = 0x12,
aoqi@1 388 cop3_op = 0x13,
aoqi@1 389 beql_op = 0x14,
aoqi@1 390 bnel_op = 0x15,
aoqi@1 391 blezl_op = 0x16,
aoqi@1 392 bgtzl_op = 0x17,
aoqi@1 393 daddi_op = 0x18,
aoqi@1 394 daddiu_op = 0x19,
aoqi@1 395 ldl_op = 0x1a,
aoqi@1 396 ldr_op = 0x1b,
aoqi@1 397 lb_op = 0x20,
aoqi@1 398 lh_op = 0x21,
aoqi@1 399 lwl_op = 0x22,
aoqi@1 400 lw_op = 0x23,
aoqi@1 401 lbu_op = 0x24,
aoqi@1 402 lhu_op = 0x25,
aoqi@1 403 lwr_op = 0x26,
aoqi@1 404 lwu_op = 0x27,
aoqi@1 405 sb_op = 0x28,
aoqi@1 406 sh_op = 0x29,
aoqi@1 407 swl_op = 0x2a,
aoqi@1 408 sw_op = 0x2b,
aoqi@1 409 sdl_op = 0x2c,
aoqi@1 410 sdr_op = 0x2d,
aoqi@1 411 swr_op = 0x2e,
aoqi@1 412 cache_op = 0x2f,
aoqi@1 413 ll_op = 0x30,
aoqi@1 414 lwc1_op = 0x31,
aoqi@1 415 lld_op = 0x34,
aoqi@1 416 ldc1_op = 0x35,
aoqi@1 417 ld_op = 0x37,
aoqi@1 418 sc_op = 0x38,
aoqi@1 419 swc1_op = 0x39,
aoqi@1 420 scd_op = 0x3c,
aoqi@1 421 sdc1_op = 0x3d,
aoqi@1 422 sd_op = 0x3f
aoqi@1 423 };
aoqi@1 424
aoqi@1 425 static const char *ops_name[];
aoqi@1 426
aoqi@1 427 //special family, the opcode is in low 6 bits.
aoqi@1 428 enum special_ops {
aoqi@1 429 sll_op = 0x00,
aoqi@1 430 srl_op = 0x02,
aoqi@1 431 sra_op = 0x03,
aoqi@1 432 sllv_op = 0x04,
aoqi@1 433 srlv_op = 0x06,
aoqi@1 434 srav_op = 0x07,
aoqi@1 435 jr_op = 0x08,
aoqi@1 436 jalr_op = 0x09,
aoqi@1 437 syscall_op = 0x0c,
aoqi@1 438 break_op = 0x0d,
aoqi@1 439 sync_op = 0x0f,
aoqi@1 440 mfhi_op = 0x10,
aoqi@1 441 mthi_op = 0x11,
aoqi@1 442 mflo_op = 0x12,
aoqi@1 443 mtlo_op = 0x13,
aoqi@1 444 dsllv_op = 0x14,
aoqi@1 445 dsrlv_op = 0x16,
aoqi@1 446 dsrav_op = 0x17,
aoqi@1 447 mult_op = 0x18,
aoqi@1 448 multu_op = 0x19,
aoqi@1 449 div_op = 0x1a,
aoqi@1 450 divu_op = 0x1b,
aoqi@1 451 dmult_op = 0x1c,
aoqi@1 452 dmultu_op = 0x1d,
aoqi@1 453 ddiv_op = 0x1e,
aoqi@1 454 ddivu_op = 0x1f,
aoqi@1 455 add_op = 0x20,
aoqi@1 456 addu_op = 0x21,
aoqi@1 457 sub_op = 0x22,
aoqi@1 458 subu_op = 0x23,
aoqi@1 459 and_op = 0x24,
aoqi@1 460 or_op = 0x25,
aoqi@1 461 xor_op = 0x26,
aoqi@1 462 nor_op = 0x27,
aoqi@1 463 slt_op = 0x2a,
aoqi@1 464 sltu_op = 0x2b,
aoqi@1 465 dadd_op = 0x2c,
aoqi@1 466 daddu_op = 0x2d,
aoqi@1 467 dsub_op = 0x2e,
aoqi@1 468 dsubu_op = 0x2f,
aoqi@1 469 tge_op = 0x30,
aoqi@1 470 tgeu_op = 0x31,
aoqi@1 471 tlt_op = 0x32,
aoqi@1 472 tltu_op = 0x33,
aoqi@1 473 teq_op = 0x34,
aoqi@1 474 tne_op = 0x36,
aoqi@1 475 dsll_op = 0x38,
aoqi@1 476 dsrl_op = 0x3a,
aoqi@1 477 dsra_op = 0x3b,
aoqi@1 478 dsll32_op = 0x3c,
aoqi@1 479 dsrl32_op = 0x3e,
aoqi@1 480 dsra32_op = 0x3f
aoqi@1 481 };
aoqi@1 482
aoqi@1 483 static const char* special_name[];
aoqi@1 484
aoqi@1 485 //regimm family, the opcode is in rt[16...20], 5 bits
aoqi@1 486 enum regimm_ops {
aoqi@1 487 bltz_op = 0x00,
aoqi@1 488 bgez_op = 0x01,
aoqi@1 489 bltzl_op = 0x02,
aoqi@1 490 bgezl_op = 0x03,
aoqi@1 491 tgei_op = 0x08,
aoqi@1 492 tgeiu_op = 0x09,
aoqi@1 493 tlti_op = 0x0a,
aoqi@1 494 tltiu_op = 0x0b,
aoqi@1 495 teqi_op = 0x0c,
aoqi@1 496 tnei_op = 0x0e,
aoqi@1 497 bltzal_op = 0x10,
aoqi@1 498 bgezal_op = 0x11,
aoqi@1 499 bltzall_op = 0x12,
aoqi@1 500 bgezall_op = 0x13,
aoqi@1 501 };
aoqi@1 502
aoqi@1 503 static const char* regimm_name[];
aoqi@1 504
aoqi@1 505 //copx family,the op in rs, 5 bits
aoqi@1 506 enum cop_ops {
aoqi@1 507 mf_op = 0x00,
aoqi@1 508 dmf_op = 0x01,
aoqi@1 509 cf_op = 0x02,
aoqi@1 510 mt_op = 0x04,
aoqi@1 511 dmt_op = 0x05,
aoqi@1 512 ct_op = 0x06,
aoqi@1 513 bc_op = 0x08,
aoqi@1 514 single_fmt = 0x10,
aoqi@1 515 double_fmt = 0x11,
aoqi@1 516 word_fmt = 0x14,
aoqi@1 517 long_fmt = 0x15
aoqi@1 518 };
aoqi@1 519
aoqi@1 520 enum bc_ops {
aoqi@1 521 bcf_op = 0x00,
aoqi@1 522 bct_op = 0x01,
aoqi@1 523 bcfl_op = 0x02,
aoqi@1 524 bctl_op = 0x03,
aoqi@1 525 };
aoqi@1 526
aoqi@1 527 enum c_conds {
aoqi@1 528 f_cond = 0x30,
aoqi@1 529 un_cond = 0x31,
aoqi@1 530 eq_cond = 0x32,
aoqi@1 531 ueq_cond = 0x33,
aoqi@1 532 olt_cond = 0x34,
aoqi@1 533 ult_cond = 0x35,
aoqi@1 534 ole_cond = 0x36,
aoqi@1 535 ule_cond = 0x37,
aoqi@1 536 sf_cond = 0x38,
aoqi@1 537 ngle_cond = 0x39,
aoqi@1 538 seq_cond = 0x3a,
aoqi@1 539 ngl_cond = 0x3b,
aoqi@1 540 lt_cond = 0x3c,
aoqi@1 541 nge_cond = 0x3d,
aoqi@1 542 le_cond = 0x3e,
aoqi@1 543 ngt_cond = 0x3f
aoqi@1 544 };
aoqi@1 545
aoqi@1 546 //low 6 bits of cp1 instruction
aoqi@1 547 enum float_ops {
aoqi@1 548 fadd_op = 0x00,
aoqi@1 549 fsub_op = 0x01,
aoqi@1 550 fmul_op = 0x02,
aoqi@1 551 fdiv_op = 0x03,
aoqi@1 552 fsqrt_op = 0x04,
aoqi@1 553 fabs_op = 0x05,
aoqi@1 554 fmov_op = 0x06,
aoqi@1 555 fneg_op = 0x07,
aoqi@1 556 froundl_op = 0x08,
aoqi@1 557 ftruncl_op = 0x09,
aoqi@1 558 fceill_op = 0x0a,
aoqi@1 559 ffloorl_op = 0x0b,
aoqi@1 560 froundw_op = 0x0c,
aoqi@1 561 ftruncw_op = 0x0d,
aoqi@1 562 fceilw_op = 0x0e,
aoqi@1 563 ffloorw_op = 0x0f,
aoqi@1 564 fcvts_op = 0x20,
aoqi@1 565 fcvtd_op = 0x21,
aoqi@1 566 fcvtw_op = 0x24,
aoqi@1 567 fcvtl_op = 0x25,
aoqi@1 568 fpll_op =0x2c,
aoqi@1 569 fplu_op =0x2d,
aoqi@1 570 fpul_op =0x2e,
aoqi@1 571 fpuu_op =0x2f,
aoqi@1 572
aoqi@1 573 };
aoqi@1 574
aoqi@1 575 /* 2013.10.16 Jin: merge from OpenJDK 8 */
aoqi@1 576 enum WhichOperand {
aoqi@1 577 // input to locate_operand, and format code for relocations
aoqi@1 578 imm_operand = 0, // embedded 32-bit|64-bit immediate operand
aoqi@1 579 disp32_operand = 1, // embedded 32-bit displacement or address
aoqi@1 580 call32_operand = 2, // embedded 32-bit self-relative displacement
aoqi@1 581 #ifndef _LP64
aoqi@1 582 _WhichOperand_limit = 3
aoqi@1 583 #else
aoqi@1 584 narrow_oop_operand = 3, // embedded 32-bit immediate narrow oop
aoqi@1 585 _WhichOperand_limit = 4
aoqi@1 586 #endif
aoqi@1 587 };
aoqi@1 588
aoqi@1 589 /* Godson3 extension */
aoqi@1 590 enum godson3_ops {
aoqi@1 591 gsldx_op = (0x36 << 26) | 0x3,
aoqi@1 592 gslwx_op = (0x36 << 26) | 0x2,
aoqi@1 593 };
aoqi@1 594
aoqi@1 595 static const char* float_name[];
aoqi@1 596
aoqi@1 597 static int opcode(int insn) { return (insn>>26)&0x3f; }
aoqi@1 598 static int rs(int insn) { return (insn>>21)&0x1f; }
aoqi@1 599 static int rt(int insn) { return (insn>>16)&0x1f; }
aoqi@1 600 static int rd(int insn) { return (insn>>11)&0x1f; }
aoqi@1 601 static int sa(int insn) { return (insn>>6)&0x1f; }
aoqi@1 602 static int special(int insn) { return insn&0x3f; }
aoqi@1 603 static int imm_off(int insn) { return (short)low16(insn); }
aoqi@1 604
aoqi@1 605 static int low (int x, int l) { return bitfield(x, 0, l); }
aoqi@1 606 static int low16(int x) { return low(x, 16); }
aoqi@1 607 static int low26(int x) { return low(x, 26); }
aoqi@1 608
aoqi@1 609 protected:
aoqi@1 610 //help methods for instruction ejection
aoqi@1 611
aoqi@1 612 //I-Type (Immediate)
aoqi@1 613 // 31 26 25 21 20 16 15 0
aoqi@1 614 //| opcode | rs | rt | immediat |
aoqi@1 615 //| | | | |
aoqi@1 616 // 6 5 5 16
aoqi@1 617 static int insn_ORRI(int op, int rs, int rt, int imm) { return (op<<26) | (rs<<21) | (rt<<16) | low16(imm); }
aoqi@1 618
aoqi@1 619 //R-Type (Register)
aoqi@1 620 // 31 26 25 21 20 16 15 11 10 6 5 0
aoqi@1 621 //| special | rs | rt | rd | 0 | opcode |
aoqi@1 622 //| 0 0 0 0 0 0 | | | | 0 0 0 0 0 | |
aoqi@1 623 // 6 5 5 5 5 6
aoqi@1 624 static int insn_RRRO(int rs, int rt, int rd, int op) { return (rs<<21) | (rt<<16) | (rd<<11) | op; }
aoqi@1 625 static int insn_RRSO(int rt, int rd, int sa, int op) { return (rt<<16) | (rd<<11) | (sa<<6) | op; }
aoqi@1 626 static int insn_RRCO(int rs, int rt, int code, int op) { return (rs<<21) | (rt<<16) | (code<<6) | op; }
aoqi@1 627
aoqi@1 628 static int insn_COP0(int op, int rt, int rd) { return (cop0_op<<26) | (op<<21) | (rt<<16) | (rd<<11); }
aoqi@1 629 static int insn_COP1(int op, int rt, int fs) { return (cop1_op<<26) | (op<<21) | (rt<<16) | (fs<<11); }
aoqi@1 630
aoqi@1 631 static int insn_F3RO(int fmt, int ft, int fs, int fd, int func) {
aoqi@1 632 return (cop1_op<<26) | (fmt<<21) | (ft<<16) | (fs<<11) | (fd<<6) | func;
aoqi@1 633 }
aoqi@1 634
aoqi@1 635
aoqi@1 636 //static int low (int x, int l) { return bitfield(x, 0, l); }
aoqi@1 637 //static int low16(int x) { return low(x, 16); }
aoqi@1 638 //static int low26(int x) { return low(x, 26); }
aoqi@1 639
aoqi@1 640 static int high (int x, int l) { return bitfield(x, 32-l, l); }
aoqi@1 641 static int high16(int x) { return high(x, 16); }
aoqi@1 642 static int high6 (int x) { return high(x, 6); }
aoqi@1 643
aoqi@1 644 //get the offset field of jump/branch instruction
aoqi@1 645 int offset(address entry) {
aoqi@1 646 assert(is_simm16((entry - pc() - 4) / 4), "change this code");
aoqi@1 647 if (!is_simm16((entry - pc() - 4) / 4)) {
aoqi@1 648 tty->print_cr("!!! is_simm16: %x", (entry - pc() - 4) / 4);
aoqi@1 649 }
aoqi@1 650 return (entry - pc() - 4) / 4;
aoqi@1 651 }
aoqi@1 652
aoqi@1 653
aoqi@1 654 public:
aoqi@1 655 using AbstractAssembler::offset;
aoqi@1 656
aoqi@1 657 //sign expand with the sign bit is h
aoqi@1 658 static int expand(int x, int h) { return -(x & (1<<h)) | x; }
aoqi@1 659
aoqi@1 660 // mips lui/addiu is both sign extended, so if you wan't to use off32/imm32, you have to use the follow three
aoqi@1 661 // by yjl 6/22/2005
aoqi@1 662 static int split_low(int x) {
aoqi@1 663 return (x & 0xffff);
aoqi@1 664 }
aoqi@1 665
aoqi@1 666 static int split_high(int x) {
aoqi@1 667 return ( (x >> 16) + ((x & 0x8000) != 0) ) & 0xffff;
aoqi@1 668 }
aoqi@1 669
aoqi@1 670 static int merge(int low, int high) {
aoqi@1 671 return expand(low, 15) + (high<<16);
aoqi@1 672 }
aoqi@1 673
aoqi@1 674 #ifdef _LP64
aoqi@1 675 static intptr_t merge(intptr_t x0, intptr_t x16, intptr_t x32, intptr_t x48) {
aoqi@1 676 return (x48 << 48) | (x32 << 32) | (x16 << 16) | x0;
aoqi@1 677 /*
aoqi@1 678 return ((intptr_t)(long_at(0) & 0xffff) << 48)
aoqi@1 679 + expand((intptr_t)(long_at(4) & 0xffff) << 32, 47)
aoqi@1 680 + expand((intptr_t)(long_at(12) & 0xffff) << 16, 31)
aoqi@1 681 + expand((intptr_t)(long_at(20) & 0xffff), 15);
aoqi@1 682 return expand(low, 15) + (high<<16);
aoqi@1 683 */
aoqi@1 684 }
aoqi@1 685 #endif
aoqi@1 686
aoqi@1 687 // modified by spark 2005/08/18
aoqi@1 688 static bool is_simm (int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); }
aoqi@1 689 static bool is_simm16(int x) { return is_simm(x, 16); }
aoqi@1 690
aoqi@1 691 // test if imm can be coded in a instruction with 16-bit imm/off
aoqi@1 692 // by yjl 6/23/2005
aoqi@1 693 /*static bool fit_in_insn(int imm) {
aoqi@1 694 return imm == (short)imm;
aoqi@1 695 }*/
aoqi@1 696
aoqi@1 697 static bool fit_in_jal(int offset) {
aoqi@1 698 return is_simm(offset, 26);
aoqi@1 699 }
aoqi@1 700
aoqi@1 701
aoqi@1 702 // test if entry can be filled in the jl/jal,
aoqi@1 703 // must be used just before you emit jl/jal
aoqi@1 704 // by yjl 6/27/2005
aoqi@1 705 bool fit_int_jal(address entry) {
aoqi@1 706 return fit_in_jal(offset(entry));
aoqi@1 707 }
aoqi@1 708
aoqi@1 709 bool fit_int_branch(address entry) {
aoqi@1 710 return is_simm16(offset(entry));
aoqi@1 711 }
aoqi@1 712
aoqi@1 713 protected:
aoqi@1 714 #ifdef ASSERT
aoqi@1 715 #define CHECK_DELAY
aoqi@1 716 #endif
aoqi@1 717 #ifdef CHECK_DELAY
aoqi@1 718 enum Delay_state { no_delay, at_delay_slot, filling_delay_slot } delay_state;
aoqi@1 719 #endif
aoqi@1 720
aoqi@1 721 public:
aoqi@1 722 void assert_not_delayed() {
aoqi@1 723 #ifdef CHECK_DELAY
aoqi@1 724 assert_not_delayed("next instruction should not be a delay slot");
aoqi@1 725 #endif
aoqi@1 726 }
aoqi@1 727
aoqi@1 728 void assert_not_delayed(const char* msg) {
aoqi@1 729 #ifdef CHECK_DELAY
aoqi@1 730 //guarantee( delay_state == no_delay, msg );
aoqi@1 731 //aoqi_test
aoqi@1 732 if(delay_state != no_delay){
aoqi@1 733 tty->print_cr("%s:%d, pc: %lx", __func__, __LINE__, pc());
aoqi@1 734 }
aoqi@1 735 assert(delay_state == no_delay, msg);
aoqi@1 736 #endif
aoqi@1 737 }
aoqi@1 738
aoqi@1 739 protected:
aoqi@1 740 // Delay slot helpers
aoqi@1 741 // cti is called when emitting control-transfer instruction,
aoqi@1 742 // BEFORE doing the emitting.
aoqi@1 743 // Only effective when assertion-checking is enabled.
aoqi@1 744
aoqi@1 745 // called when emitting cti with a delay slot, AFTER emitting
aoqi@1 746 void has_delay_slot() {
aoqi@1 747 #ifdef CHECK_DELAY
aoqi@1 748 assert_not_delayed("just checking");
aoqi@1 749 delay_state = at_delay_slot;
aoqi@1 750 #endif
aoqi@1 751 }
aoqi@1 752
aoqi@1 753 public:
aoqi@1 754 Assembler* delayed() {
aoqi@1 755 #ifdef CHECK_DELAY
aoqi@1 756 guarantee( delay_state == at_delay_slot, "delayed instructition is not in delay slot");
aoqi@1 757 delay_state = filling_delay_slot;
aoqi@1 758 #endif
aoqi@1 759 return this;
aoqi@1 760 }
aoqi@1 761
aoqi@1 762 void flush() {
aoqi@1 763 #ifdef CHECK_DELAY
aoqi@1 764 guarantee( delay_state == no_delay, "ending code with a delay slot");
aoqi@1 765 #endif
aoqi@1 766 AbstractAssembler::flush();
aoqi@1 767 }
aoqi@1 768
aoqi@1 769 inline void emit_long(int); // shadows AbstractAssembler::emit_long
aoqi@1 770 inline void emit_data(int x) { emit_long(x); }
aoqi@1 771 inline void emit_data(int, RelocationHolder const&);
aoqi@1 772 inline void emit_data(int, relocInfo::relocType rtype);
aoqi@1 773 inline void check_delay();
aoqi@1 774
aoqi@1 775
aoqi@1 776 // Generic instructions
aoqi@1 777 // Does 32bit or 64bit as needed for the platform. In some sense these
aoqi@1 778 // belong in macro assembler but there is no need for both varieties to exist
aoqi@1 779
aoqi@1 780 #ifndef _LP64
aoqi@1 781 void add(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), add_op)); }
aoqi@1 782 void addi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 783 void addiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 784 void addu(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), addu_op)); }
aoqi@1 785 #else
aoqi@1 786 void add(Register rd, Register rs, Register rt) { dadd (rd, rs, rt); }
aoqi@1 787 void add32(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), add_op)); }
aoqi@1 788 void addu32(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), addu_op)); }
aoqi@1 789 void addiu32(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 790 void addi(Register rt, Register rs, int imm) { daddi (rt, rs, imm);}
aoqi@1 791 void addiu(Register rt, Register rs, int imm) { daddiu (rt, rs, imm);}
aoqi@1 792 void addu(Register rd, Register rs, Register rt) { daddu (rd, rs, rt); }
aoqi@1 793 #endif
aoqi@1 794
aoqi@1 795 void andr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), and_op)); }
aoqi@1 796 void andi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(andi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 797
aoqi@1 798 void beq (Register rs, Register rt, int off) { emit_long(insn_ORRI(beq_op, (int)rs->encoding(), (int)rt->encoding(), off)); has_delay_slot(); }
aoqi@1 799 void beql (Register rs, Register rt, int off) { emit_long(insn_ORRI(beql_op, (int)rs->encoding(), (int)rt->encoding(), off)); has_delay_slot(); }
aoqi@1 800 void bgez (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgez_op, off)); has_delay_slot(); }
aoqi@1 801 void bgezal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezal_op, off)); has_delay_slot(); }
aoqi@1 802 void bgezall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezall_op, off)); has_delay_slot(); }
aoqi@1 803 void bgezl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezl_op, off)); has_delay_slot(); }
aoqi@1 804 void bgtz (Register rs, int off) { emit_long(insn_ORRI(bgtz_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@1 805 void bgtzl (Register rs, int off) { emit_long(insn_ORRI(bgtzl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@1 806 void blez (Register rs, int off) { emit_long(insn_ORRI(blez_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@1 807 void blezl (Register rs, int off) { emit_long(insn_ORRI(blezl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@1 808 void bltz (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltz_op, off)); has_delay_slot(); }
aoqi@1 809 void bltzal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzal_op, off)); has_delay_slot(); }
aoqi@1 810 void bltzall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzall_op, off)); has_delay_slot(); }
aoqi@1 811 void bltzl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzl_op, off)); has_delay_slot(); }
aoqi@1 812 void bne (Register rs, Register rt, int off) { emit_long(insn_ORRI(bne_op, (int)rs->encoding(), (int)rt->encoding(), off)); has_delay_slot(); }
aoqi@1 813 void bnel (Register rs, Register rt, int off) { emit_long(insn_ORRI(bnel_op, (int)rs->encoding(), (int)rt->encoding(), off)); has_delay_slot(); }
aoqi@1 814 void brk (int code) { emit_long(break_op | (code<<16)); }
aoqi@1 815
aoqi@1 816 void beq (Register rs, Register rt, address entry) { beq(rs, rt, offset(entry)); }
aoqi@1 817 void beql (Register rs, Register rt, address entry) { beql(rs, rt, offset(entry));}
aoqi@1 818 void bgez (Register rs, address entry) { bgez (rs, offset(entry)); }
aoqi@1 819 void bgezal (Register rs, address entry) { bgezal (rs, offset(entry)); }
aoqi@1 820 void bgezall(Register rs, address entry) { bgezall(rs, offset(entry)); }
aoqi@1 821 void bgezl (Register rs, address entry) { bgezl (rs, offset(entry)); }
aoqi@1 822 void bgtz (Register rs, address entry) { bgtz (rs, offset(entry)); }
aoqi@1 823 void bgtzl (Register rs, address entry) { bgtzl (rs, offset(entry)); }
aoqi@1 824 void blez (Register rs, address entry) { blez (rs, offset(entry)); }
aoqi@1 825 void blezl (Register rs, address entry) { blezl (rs, offset(entry)); }
aoqi@1 826 void bltz (Register rs, address entry) { bltz (rs, offset(entry)); }
aoqi@1 827 void bltzal (Register rs, address entry) { bltzal (rs, offset(entry)); }
aoqi@1 828 void bltzall(Register rs, address entry) { bltzall(rs, offset(entry)); }
aoqi@1 829 void bltzl (Register rs, address entry) { bltzl (rs, offset(entry)); }
aoqi@1 830 void bne (Register rs, Register rt, address entry) { bne(rs, rt, offset(entry)); }
aoqi@1 831 void bnel (Register rs, Register rt, address entry) { bnel(rs, rt, offset(entry)); }
aoqi@1 832
aoqi@1 833 void beq (Register rs, Register rt, Label& L) { beq(rs, rt, target(L)); }
aoqi@1 834 void beql (Register rs, Register rt, Label& L) { beql(rs, rt, target(L)); }
aoqi@1 835 void bgez (Register rs, Label& L){ bgez (rs, target(L)); }
aoqi@1 836 void bgezal (Register rs, Label& L){ bgezal (rs, target(L)); }
aoqi@1 837 void bgezall(Register rs, Label& L){ bgezall(rs, target(L)); }
aoqi@1 838 void bgezl (Register rs, Label& L){ bgezl (rs, target(L)); }
aoqi@1 839 void bgtz (Register rs, Label& L){ bgtz (rs, target(L)); }
aoqi@1 840 void bgtzl (Register rs, Label& L){ bgtzl (rs, target(L)); }
aoqi@1 841 void blez (Register rs, Label& L){ blez (rs, target(L)); }
aoqi@1 842 void blezl (Register rs, Label& L){ blezl (rs, target(L)); }
aoqi@1 843 void bltz (Register rs, Label& L){ bltz (rs, target(L)); }
aoqi@1 844 void bltzal (Register rs, Label& L){ bltzal (rs, target(L)); }
aoqi@1 845 void bltzall(Register rs, Label& L){ bltzall(rs, target(L)); }
aoqi@1 846 void bltzl (Register rs, Label& L){ bltzl (rs, target(L)); }
aoqi@1 847 void bne (Register rs, Register rt, Label& L){ bne(rs, rt, target(L)); }
aoqi@1 848 void bnel (Register rs, Register rt, Label& L){ bnel(rs, rt, target(L)); }
aoqi@1 849
aoqi@1 850 void dadd (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dadd_op)); }
aoqi@1 851 void daddi (Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 852 void daddiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 853 void daddu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), daddu_op)); }
aoqi@1 854 void ddiv (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddiv_op)); }
aoqi@1 855 void ddivu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddivu_op)); }
aoqi@1 856 // Do mult and div need both 32-bit and 64-bit version? FIXME aoqi
aoqi@1 857 //#ifndef _LP64
aoqi@1 858 #if 1
aoqi@1 859 void div (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, div_op)); }
aoqi@1 860 void divu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, divu_op)); }
aoqi@1 861 #else
aoqi@1 862 void div (Register rs, Register rt) { ddiv (rs, rt);}
aoqi@1 863 void divu (Register rs, Register rt) { ddivu(rs, rt);}
aoqi@1 864 #endif
aoqi@1 865 void dmfc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmf_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@1 866 void dmtc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmt_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@1 867 void dmult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmult_op)); }
aoqi@1 868 void dmultu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmultu_op)); }
aoqi@1 869 void dsll (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsll_op)); }
aoqi@1 870 void dsllv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsllv_op)); }
aoqi@1 871 void dsll32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsll32_op)); }
aoqi@1 872 void dsra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsra_op)); }
aoqi@1 873 void dsrav (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrav_op)); }
aoqi@1 874 void dsra32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsra32_op)); }
aoqi@1 875 void dsrl (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsrl_op)); }
aoqi@1 876 void dsrlv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrlv_op)); }
aoqi@1 877 void dsrl32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsrl32_op)); }
aoqi@1 878 void dsub (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsub_op)); }
aoqi@1 879 void dsubu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsubu_op)); }
aoqi@1 880
aoqi@1 881 void b(int off) { beq(R0, R0, off); }
aoqi@1 882 void b(address entry) { b(offset(entry)); }
aoqi@1 883 void b(Label& L) { b(target(L)); }
aoqi@1 884
aoqi@1 885 void j(address entry);
aoqi@1 886 void jal(address entry);
aoqi@1 887
aoqi@1 888 void jalr(Register rd, Register rs) { emit_long( ((int)rs->encoding()<<21) | ((int)rd->encoding()<<11) | jalr_op); has_delay_slot(); }
aoqi@1 889 void jalr(Register rs) { jalr(RA, rs); }
aoqi@1 890 void jalr() { jalr(T9); }
aoqi@1 891
aoqi@1 892 void jr(Register rs) { emit_long(((int)rs->encoding()<<21) | jr_op); has_delay_slot(); }
aoqi@1 893
aoqi@1 894 void lb (Register rt, Register base, int off) { emit_long(insn_ORRI(lb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 895 void lbu(Register rt, Register base, int off) { emit_long(insn_ORRI(lbu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 896 void ld (Register rt, Register base, int off) { emit_long(insn_ORRI(ld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 897 void ldl(Register rt, Register base, int off) { emit_long(insn_ORRI(ldl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 898 void ldr(Register rt, Register base, int off) { emit_long(insn_ORRI(ldr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 899 void lh (Register rt, Register base, int off) { emit_long(insn_ORRI(lh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 900 void lhu(Register rt, Register base, int off) { emit_long(insn_ORRI(lhu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 901 void ll (Register rt, Register base, int off) { emit_long(insn_ORRI(ll_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 902 void lld(Register rt, Register base, int off) { emit_long(insn_ORRI(lld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 903 void lui(Register rt, int imm) { emit_long(insn_ORRI(lui_op, 0, (int)rt->encoding(), imm)); }
aoqi@1 904 void lw (Register rt, Register base, int off) { emit_long(insn_ORRI(lw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 905 void lwl(Register rt, Register base, int off) { emit_long(insn_ORRI(lwl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 906 void lwr(Register rt, Register base, int off) { emit_long(insn_ORRI(lwr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 907 void lwu(Register rt, Register base, int off) { emit_long(insn_ORRI(lwu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 908
aoqi@1 909 void lb (Register rt, Address src);
aoqi@1 910 void lbu(Register rt, Address src);
aoqi@1 911 void ld (Register rt, Address src);
aoqi@1 912 void ldl(Register rt, Address src);
aoqi@1 913 void ldr(Register rt, Address src);
aoqi@1 914 void lh (Register rt, Address src);
aoqi@1 915 void lhu(Register rt, Address src);
aoqi@1 916 void ll (Register rt, Address src);
aoqi@1 917 void lld(Register rt, Address src);
aoqi@1 918 void lw (Register rt, Address src);
aoqi@1 919 void lwl(Register rt, Address src);
aoqi@1 920 void lwr(Register rt, Address src);
aoqi@1 921 void lwu(Register rt, Address src);
aoqi@1 922 void lea(Register rt, Address src);
aoqi@1 923
aoqi@1 924 void mfc0 (Register rt, Register rd) { emit_long(insn_COP0(mf_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@1 925 void mfhi (Register rd) { emit_long( ((int)rd->encoding()<<11) | mfhi_op ); }
aoqi@1 926 void mflo (Register rd) { emit_long( ((int)rd->encoding()<<11) | mflo_op ); }
aoqi@1 927 void mtc0 (Register rt, Register rd) { emit_long(insn_COP0(mt_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@1 928 void mthi (Register rs) { emit_long( ((int)rs->encoding()<<21) | mthi_op ); }
aoqi@1 929 void mtlo (Register rs) { emit_long( ((int)rs->encoding()<<21) | mtlo_op ); }
aoqi@1 930 // Do mult and div need both 32-bit and 64-bit version? FIXME aoqi
aoqi@1 931 //#ifndef _LP64
aoqi@1 932 #if 1
aoqi@1 933 void mult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, mult_op)); }
aoqi@1 934 void multu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, multu_op)); }
aoqi@1 935 #else
aoqi@1 936 void mult (Register rs, Register rt) { dmult (rs, rt); }
aoqi@1 937 void multu(Register rs, Register rt) { dmultu (rs, rt); }
aoqi@1 938 #endif
aoqi@1 939
aoqi@1 940 void nor(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), nor_op)); }
aoqi@1 941
aoqi@1 942 void orr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), or_op)); }
aoqi@1 943 void ori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(ori_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 944
aoqi@1 945 void sb (Register rt, Register base, int off) { emit_long(insn_ORRI(sb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 946 void sc (Register rt, Register base, int off) { emit_long(insn_ORRI(sc_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 947 void scd (Register rt, Register base, int off) { emit_long(insn_ORRI(scd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 948 void sd (Register rt, Register base, int off) { emit_long(insn_ORRI(sd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 949 void sdl (Register rt, Register base, int off) { emit_long(insn_ORRI(sdl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 950 void sdr (Register rt, Register base, int off) { emit_long(insn_ORRI(sdr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 951 void sh (Register rt, Register base, int off) { emit_long(insn_ORRI(sh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 952 //#ifndef _LP64
aoqi@1 953 #if 1
aoqi@1 954 void sll (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, sll_op)); }
aoqi@1 955 void sllv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sllv_op)); }
aoqi@1 956 #else
aoqi@1 957 void sll (Register rd, Register rt , int sa) { dsll (rd, rt, sa);}
aoqi@1 958 void sllv (Register rd, Register rt, Register rs) { dsllv (rd, rt, rs); }
aoqi@1 959 #endif
aoqi@1 960 void slt (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), slt_op)); }
aoqi@1 961 void slti (Register rt, Register rs, int imm) { emit_long(insn_ORRI(slti_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 962 void sltiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(sltiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 963 void sltu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sltu_op)); }
aoqi@1 964 //#ifndef _LP64
aoqi@1 965 #if 1
aoqi@1 966 void sra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, sra_op)); }
aoqi@1 967 void srav (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), srav_op)); }
aoqi@1 968 void srl (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, srl_op)); }
aoqi@1 969 void srlv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), srlv_op)); }
aoqi@1 970 #else
aoqi@1 971 void sra (Register rd, Register rt , int sa) { dsra (rd, rt, sa); }
aoqi@1 972 void srav (Register rd, Register rt, Register rs) { dsrav (rd, rt, rs); }
aoqi@1 973 void srl (Register rd, Register rt , int sa) { dsrl (rd, rt, sa); }
aoqi@1 974 void srlv (Register rd, Register rt, Register rs) { dsrlv (rd, rt, rs); }
aoqi@1 975 #endif
aoqi@1 976 #ifndef _LP64
aoqi@1 977 void sub (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sub_op)); }
aoqi@1 978 void subu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), subu_op)); }
aoqi@1 979 #else
aoqi@1 980 void sub (Register rd, Register rs, Register rt) { dsub (rd, rs, rt); }
aoqi@1 981 void subu (Register rd, Register rs, Register rt) { dsubu (rd, rs, rt); }
aoqi@1 982 void subu32 (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), subu_op)); }
aoqi@1 983 #endif
aoqi@1 984 void sw (Register rt, Register base, int off) { emit_long(insn_ORRI(sw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 985 void swl (Register rt, Register base, int off) { emit_long(insn_ORRI(swl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 986 void swr (Register rt, Register base, int off) { emit_long(insn_ORRI(swr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@1 987 void sync () { emit_long(sync_op); }
aoqi@1 988 void syscall(int code) { emit_long( (code<<6) | syscall_op ); }
aoqi@1 989
aoqi@1 990 void sb(Register rt, Address dst);
aoqi@1 991 void sc(Register rt, Address dst);
aoqi@1 992 void scd(Register rt, Address dst);
aoqi@1 993 void sd(Register rt, Address dst);
aoqi@1 994 void sdl(Register rt, Address dst);
aoqi@1 995 void sdr(Register rt, Address dst);
aoqi@1 996 void sh(Register rt, Address dst);
aoqi@1 997 void sw(Register rt, Address dst);
aoqi@1 998 void swl(Register rt, Address dst);
aoqi@1 999 void swr(Register rt, Address dst);
aoqi@1 1000
aoqi@1 1001 void teq (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, teq_op)); }
aoqi@1 1002 void teqi (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), teqi_op, imm)); }
aoqi@1 1003 void tge (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tge_op)); }
aoqi@1 1004 void tgei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgei_op, imm)); }
aoqi@1 1005 void tgeiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgeiu_op, imm)); }
aoqi@1 1006 void tgeu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tgeu_op)); }
aoqi@1 1007 void tlt (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tlt_op)); }
aoqi@1 1008 void tlti (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tlti_op, imm)); }
aoqi@1 1009 void tltiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tltiu_op, imm)); }
aoqi@1 1010 void tltu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tltu_op)); }
aoqi@1 1011 void tne (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tne_op)); }
aoqi@1 1012 void tnei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tnei_op, imm)); }
aoqi@1 1013
aoqi@1 1014 void xorr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), xor_op)); }
aoqi@1 1015 void xori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(xori_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 1016
aoqi@1 1017 void nop() { emit_long(0); }
aoqi@1 1018 //float instructions for mips
aoqi@1 1019 void abs_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fabs_op));}
aoqi@1 1020 void abs_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fabs_op));}
aoqi@1 1021 void add_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fadd_op));}
aoqi@1 1022 void add_d(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fadd_op));}
aoqi@1 1023
aoqi@1 1024 void bc1f (int off) { emit_long(insn_ORRI(cop1_op, bc_op, bcf_op, off)); has_delay_slot(); }
aoqi@1 1025 void bc1fl(int off) { emit_long(insn_ORRI(cop1_op, bc_op, bcfl_op, off)); has_delay_slot(); }
aoqi@1 1026 void bc1t (int off) { emit_long(insn_ORRI(cop1_op, bc_op, bct_op, off)); has_delay_slot(); }
aoqi@1 1027 void bc1tl(int off) { emit_long(insn_ORRI(cop1_op, bc_op, bctl_op, off)); has_delay_slot(); }
aoqi@1 1028
aoqi@1 1029 void bc1f (address entry) { bc1f(offset(entry)); }
aoqi@1 1030 void bc1fl(address entry) { bc1fl(offset(entry)); }
aoqi@1 1031 void bc1t (address entry) { bc1t(offset(entry)); }
aoqi@1 1032 void bc1tl(address entry) { bc1tl(offset(entry)); }
aoqi@1 1033
aoqi@1 1034 void bc1f (Label& L) { bc1f(target(L)); }
aoqi@1 1035 void bc1fl(Label& L) { bc1fl(target(L)); }
aoqi@1 1036 void bc1t (Label& L) { bc1t(target(L)); }
aoqi@1 1037 void bc1tl(Label& L) { bc1tl(target(L)); }
aoqi@1 1038
aoqi@1 1039 void c_f_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, f_cond)); }
aoqi@1 1040 void c_f_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, f_cond)); }
aoqi@1 1041 void c_un_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, un_cond)); }
aoqi@1 1042 void c_un_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, un_cond)); }
aoqi@1 1043 void c_eq_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, eq_cond)); }
aoqi@1 1044 void c_eq_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, eq_cond)); }
aoqi@1 1045 void c_ueq_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ueq_cond)); }
aoqi@1 1046 void c_ueq_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ueq_cond)); }
aoqi@1 1047 void c_olt_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, olt_cond)); }
aoqi@1 1048 void c_olt_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, olt_cond)); }
aoqi@1 1049 void c_ult_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ult_cond)); }
aoqi@1 1050 void c_ult_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ult_cond)); }
aoqi@1 1051 void c_ole_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ole_cond)); }
aoqi@1 1052 void c_ole_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ole_cond)); }
aoqi@1 1053 void c_ule_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ule_cond)); }
aoqi@1 1054 void c_ule_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ule_cond)); }
aoqi@1 1055 void c_sf_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, sf_cond)); }
aoqi@1 1056 void c_sf_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, sf_cond)); }
aoqi@1 1057 void c_ngle_s(FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngle_cond)); }
aoqi@1 1058 void c_ngle_d(FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngle_cond)); }
aoqi@1 1059 void c_seq_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, seq_cond)); }
aoqi@1 1060 void c_seq_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, seq_cond)); }
aoqi@1 1061 void c_ngl_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngl_cond)); }
aoqi@1 1062 void c_ngl_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngl_cond)); }
aoqi@1 1063 void c_lt_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, lt_cond)); }
aoqi@1 1064 void c_lt_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, lt_cond)); }
aoqi@1 1065 void c_nge_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, nge_cond)); }
aoqi@1 1066 void c_nge_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, nge_cond)); }
aoqi@1 1067 void c_le_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, le_cond)); }
aoqi@1 1068 void c_le_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, le_cond)); }
aoqi@1 1069 void c_ngt_s (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngt_cond)); }
aoqi@1 1070 void c_ngt_d (FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), 0, ngt_cond)); }
aoqi@1 1071
aoqi@1 1072 void ceil_l_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fceill_op)); }
aoqi@1 1073 void ceil_l_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fceill_op)); }
aoqi@1 1074 void ceil_w_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fceilw_op)); }
aoqi@1 1075 void ceil_w_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fceilw_op)); }
aoqi@1 1076 void cfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(cf_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1077 void ctc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(ct_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1078 void cfc1(Register rt, int fs) { emit_long(insn_COP1(cf_op, (int)rt->encoding(), fs)); }
aoqi@1 1079 void ctc1(Register rt, int fs) { emit_long(insn_COP1(ct_op, (int)rt->encoding(), fs)); }
aoqi@1 1080
aoqi@1 1081 void cvt_d_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtd_op)); }
aoqi@1 1082 void cvt_d_w(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(word_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtd_op)); }
aoqi@1 1083 void cvt_d_l(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(long_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtd_op)); }
aoqi@1 1084 void cvt_l_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtl_op)); }
aoqi@1 1085 void cvt_l_w(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(word_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtl_op)); }
aoqi@1 1086 void cvt_l_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtl_op)); }
aoqi@1 1087 void cvt_s_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvts_op)); }
aoqi@1 1088 void cvt_s_w(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(word_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvts_op)); }
aoqi@1 1089 void cvt_s_l(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(long_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvts_op)); }
aoqi@1 1090 void cvt_w_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtw_op)); }
aoqi@1 1091 void cvt_w_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtw_op)); }
aoqi@1 1092 void cvt_w_l(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(long_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtw_op)); }
aoqi@1 1093 void pll(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(long_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fpll_op)); }
aoqi@1 1094 void plu(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(long_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fplu_op)); }
aoqi@1 1095 void pul(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(long_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fpul_op)); }
aoqi@1 1096 void puu(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(long_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fpuu_op)); }
aoqi@1 1097
aoqi@1 1098 void div_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fdiv_op)); }
aoqi@1 1099 void div_d(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fdiv_op)); }
aoqi@1 1100 void dmfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmf_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1101 void dmtc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmt_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1102
aoqi@1 1103 void floor_l_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ffloorl_op)); }
aoqi@1 1104 void floor_l_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ffloorl_op)); }
aoqi@1 1105 void floor_w_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ffloorw_op)); }
aoqi@1 1106 void floor_w_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ffloorw_op)); }
aoqi@1 1107
aoqi@1 1108 void ldc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(ldc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@1 1109 void lwc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(lwc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@1 1110 void ldc1(FloatRegister ft, Address src);
aoqi@1 1111 void lwc1(FloatRegister ft, Address src);
aoqi@1 1112
aoqi@1 1113 void mfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(mf_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1114 void mov_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fmov_op)); }
aoqi@1 1115 void mov_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fmov_op)); }
aoqi@1 1116 void mtc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(mt_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@1 1117 void mul_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fmul_op)); }
aoqi@1 1118 void mul_d(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fmul_op)); }
aoqi@1 1119
aoqi@1 1120 void neg_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fneg_op)); }
aoqi@1 1121 void neg_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fneg_op)); }
aoqi@1 1122
aoqi@1 1123 void round_l_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), froundl_op)); }
aoqi@1 1124 void round_l_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), froundl_op)); }
aoqi@1 1125 void round_w_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), froundw_op)); }
aoqi@1 1126 void round_w_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), froundw_op)); }
aoqi@1 1127
aoqi@1 1128 void sdc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(sdc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@1 1129 void sdc1(FloatRegister ft, Address dst);
aoqi@1 1130 void sqrt_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fsqrt_op)); }
aoqi@1 1131 void sqrt_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fsqrt_op)); }
aoqi@1 1132 void sub_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(single_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fsub_op)); }
aoqi@1 1133 void sub_d(FloatRegister fd, FloatRegister fs, FloatRegister ft) { emit_long(insn_F3RO(double_fmt, (int)ft->encoding(), (int)fs->encoding(), (int)fd->encoding(), fsub_op)); }
aoqi@1 1134 void swc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(swc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@1 1135 void swc1(FloatRegister ft, Address dst);
aoqi@1 1136
aoqi@1 1137 void trunc_l_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ftruncl_op)); }
aoqi@1 1138 void trunc_l_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ftruncl_op)); }
aoqi@1 1139 void trunc_w_s(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(single_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ftruncw_op)); }
aoqi@1 1140 void trunc_w_d(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(double_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), ftruncw_op)); }
aoqi@1 1141
aoqi@1 1142 void int3();
aoqi@1 1143 static void print_instruction(int);
aoqi@1 1144 int patched_branch(int dest_pos, int inst, int inst_pos);
aoqi@1 1145 int branch_destination(int inst, int pos);
aoqi@1 1146
aoqi@1 1147 /* Godson3 extension */
aoqi@1 1148 void gsldx(Register rt, Register base, Register index, int off) {
aoqi@1 1149 assert(is_simm(off, 8), "gsldx: off exceeds 8 bits");
aoqi@1 1150 emit_long(gsldx_op | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)index->encoding() << 11) | (off << 3));
aoqi@1 1151 }
aoqi@1 1152
aoqi@1 1153 void gslwx(Register rt, Register base, Register index, int off) {
aoqi@1 1154 assert(is_simm(off, 8), "gslwx: off exceeds 8 bits");
aoqi@1 1155 emit_long(gslwx_op | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)index->encoding() << 11) | (off << 3));
aoqi@1 1156 }
aoqi@1 1157
aoqi@1 1158 public:
aoqi@1 1159 // Creation
aoqi@1 1160 Assembler(CodeBuffer* code) : AbstractAssembler(code) {
aoqi@1 1161 #ifdef CHECK_DELAY
aoqi@1 1162 delay_state = no_delay;
aoqi@1 1163 #endif
aoqi@1 1164 }
aoqi@1 1165
aoqi@1 1166 // Decoding
aoqi@1 1167 static address locate_operand(address inst, WhichOperand which);
aoqi@1 1168 static address locate_next_instruction(address inst);
aoqi@1 1169 };
aoqi@1 1170
aoqi@1 1171
aoqi@1 1172 // MacroAssembler extends Assembler by frequently used macros.
aoqi@1 1173 //
aoqi@1 1174 // Instructions for which a 'better' code sequence exists depending
aoqi@1 1175 // on arguments should also go in here.
aoqi@1 1176
aoqi@1 1177 class MacroAssembler: public Assembler {
aoqi@1 1178 friend class LIR_Assembler;
aoqi@1 1179 friend class Runtime1; // as_Address()
aoqi@1 1180
aoqi@1 1181 public:
aoqi@1 1182 static intptr_t i[32];
aoqi@1 1183 static float f[32];
aoqi@1 1184 static void print(outputStream *s);
aoqi@1 1185
aoqi@1 1186 static int i_offset(unsigned int k);
aoqi@1 1187 static int f_offset(unsigned int k);
aoqi@1 1188
aoqi@1 1189 static void save_registers(MacroAssembler *masm);
aoqi@1 1190 static void restore_registers(MacroAssembler *masm);
aoqi@1 1191
aoqi@1 1192 protected:
aoqi@1 1193
aoqi@1 1194 Address as_Address(AddressLiteral adr);
aoqi@1 1195 Address as_Address(ArrayAddress adr);
aoqi@1 1196
aoqi@1 1197 // Support for VM calls
aoqi@1 1198 //
aoqi@1 1199 // This is the base routine called by the different versions of call_VM_leaf. The interpreter
aoqi@1 1200 // may customize this version by overriding it for its purposes (e.g., to save/restore
aoqi@1 1201 // additional registers when doing a VM call).
aoqi@1 1202 #ifdef CC_INTERP
aoqi@1 1203 // c++ interpreter never wants to use interp_masm version of call_VM
aoqi@1 1204 #define VIRTUAL
aoqi@1 1205 #else
aoqi@1 1206 #define VIRTUAL virtual
aoqi@1 1207 #endif
aoqi@1 1208
aoqi@1 1209 VIRTUAL void call_VM_leaf_base(
aoqi@1 1210 address entry_point, // the entry point
aoqi@1 1211 int number_of_arguments // the number of arguments to pop after the call
aoqi@1 1212 );
aoqi@1 1213
aoqi@1 1214 // This is the base routine called by the different versions of call_VM. The interpreter
aoqi@1 1215 // may customize this version by overriding it for its purposes (e.g., to save/restore
aoqi@1 1216 // additional registers when doing a VM call).
aoqi@1 1217 //
aoqi@1 1218 // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base
aoqi@1 1219 // returns the register which contains the thread upon return. If a thread register has been
aoqi@1 1220 // specified, the return value will correspond to that register. If no last_java_sp is specified
aoqi@1 1221 // (noreg) than rsp will be used instead.
aoqi@1 1222 VIRTUAL void call_VM_base( // returns the register containing the thread upon return
aoqi@1 1223 Register oop_result, // where an oop-result ends up if any; use noreg otherwise
aoqi@1 1224 Register java_thread, // the thread if computed before ; use noreg otherwise
aoqi@1 1225 Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise
aoqi@1 1226 address entry_point, // the entry point
aoqi@1 1227 int number_of_arguments, // the number of arguments (w/o thread) to pop after the call
aoqi@1 1228 bool check_exceptions // whether to check for pending exceptions after return
aoqi@1 1229 );
aoqi@1 1230
aoqi@1 1231 // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
aoqi@1 1232 // The implementation is only non-empty for the InterpreterMacroAssembler,
aoqi@1 1233 // as only the interpreter handles PopFrame and ForceEarlyReturn requests.
aoqi@1 1234 virtual void check_and_handle_popframe(Register java_thread);
aoqi@1 1235 virtual void check_and_handle_earlyret(Register java_thread);
aoqi@1 1236
aoqi@1 1237 void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);
aoqi@1 1238
aoqi@1 1239 // helpers for FPU flag access
aoqi@1 1240 // tmp is a temporary register, if none is available use noreg
aoqi@1 1241 //void save_rax (Register tmp);
aoqi@1 1242 //void restore_rax(Register tmp);
aoqi@1 1243
aoqi@1 1244 public:
aoqi@1 1245 MacroAssembler(CodeBuffer* code) : Assembler(code) {}
aoqi@1 1246
aoqi@1 1247 // Support for NULL-checks
aoqi@1 1248 //
aoqi@1 1249 // Generates code that causes a NULL OS exception if the content of reg is NULL.
aoqi@1 1250 // If the accessed location is M[reg + offset] and the offset is known, provide the
aoqi@1 1251 // offset. No explicit code generation is needed if the offset is within a certain
aoqi@1 1252 // range (0 <= offset <= page_size).
aoqi@1 1253 // use "teq 83, reg" in mips now, by yjl 6/20/2005
aoqi@1 1254 void null_check(Register reg, int offset = -1);
aoqi@1 1255 static bool needs_explicit_null_check(intptr_t offset);
aoqi@1 1256
aoqi@1 1257 // Required platform-specific helpers for Label::patch_instructions.
aoqi@1 1258 // They _shadow_ the declarations in AbstractAssembler, which are undefined.
aoqi@1 1259 void pd_patch_instruction(address branch, address target);
aoqi@1 1260
aoqi@1 1261 // Alignment
aoqi@1 1262 void align(int modulus);
aoqi@1 1263
aoqi@1 1264 // Misc
aoqi@1 1265 //void fat_nop(); // 5 byte nop
aoqi@1 1266
aoqi@1 1267 // Stack frame creation/removal
aoqi@1 1268 void enter();
aoqi@1 1269 void leave();
aoqi@1 1270
aoqi@1 1271 // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information)
aoqi@1 1272 // The pointer will be loaded into the thread register.
aoqi@1 1273 void get_thread(Register thread);
aoqi@1 1274
aoqi@1 1275
aoqi@1 1276 // Support for VM calls
aoqi@1 1277 //
aoqi@1 1278 // It is imperative that all calls into the VM are handled via the call_VM macros.
aoqi@1 1279 // They make sure that the stack linkage is setup correctly. call_VM's correspond
aoqi@1 1280 // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points.
aoqi@1 1281
aoqi@1 1282
aoqi@1 1283 void call_VM(Register oop_result,
aoqi@1 1284 address entry_point,
aoqi@1 1285 bool check_exceptions = true);
aoqi@1 1286 void call_VM(Register oop_result,
aoqi@1 1287 address entry_point,
aoqi@1 1288 Register arg_1,
aoqi@1 1289 bool check_exceptions = true);
aoqi@1 1290 void call_VM(Register oop_result,
aoqi@1 1291 address entry_point,
aoqi@1 1292 Register arg_1, Register arg_2,
aoqi@1 1293 bool check_exceptions = true);
aoqi@1 1294 void call_VM(Register oop_result,
aoqi@1 1295 address entry_point,
aoqi@1 1296 Register arg_1, Register arg_2, Register arg_3,
aoqi@1 1297 bool check_exceptions = true);
aoqi@1 1298 // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls
aoqi@1 1299 void super_call_VM_leaf(address entry_point);
aoqi@1 1300 void super_call_VM_leaf(address entry_point, Register arg_1);
aoqi@1 1301 void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
aoqi@1 1302 void super_call_VM_leaf(address entry_point,
aoqi@1 1303 Register arg_1, Register arg_2, Register arg_3);
aoqi@1 1304
aoqi@1 1305 // Overloadings with last_Java_sp
aoqi@1 1306 void call_VM(Register oop_result,
aoqi@1 1307 Register last_java_sp,
aoqi@1 1308 address entry_point,
aoqi@1 1309 int number_of_arguments = 0,
aoqi@1 1310 bool check_exceptions = true);
aoqi@1 1311 void call_VM(Register oop_result,
aoqi@1 1312 Register last_java_sp,
aoqi@1 1313 address entry_point,
aoqi@1 1314 Register arg_1, bool
aoqi@1 1315 check_exceptions = true);
aoqi@1 1316 void call_VM(Register oop_result,
aoqi@1 1317 Register last_java_sp,
aoqi@1 1318 address entry_point,
aoqi@1 1319 Register arg_1, Register arg_2,
aoqi@1 1320 bool check_exceptions = true);
aoqi@1 1321 void call_VM(Register oop_result,
aoqi@1 1322 Register last_java_sp,
aoqi@1 1323 address entry_point,
aoqi@1 1324 Register arg_1, Register arg_2, Register arg_3,
aoqi@1 1325 bool check_exceptions = true);
aoqi@1 1326
aoqi@1 1327 void call_VM_leaf(address entry_point,
aoqi@1 1328 int number_of_arguments = 0);
aoqi@1 1329 void call_VM_leaf(address entry_point,
aoqi@1 1330 Register arg_1);
aoqi@1 1331 void call_VM_leaf(address entry_point,
aoqi@1 1332 Register arg_1, Register arg_2);
aoqi@1 1333 void call_VM_leaf(address entry_point,
aoqi@1 1334 Register arg_1, Register arg_2, Register arg_3);
aoqi@1 1335
aoqi@1 1336 // last Java Frame (fills frame anchor)
aoqi@1 1337 void set_last_Java_frame(Register thread,
aoqi@1 1338 Register last_java_sp,
aoqi@1 1339 Register last_java_fp,
aoqi@1 1340 address last_java_pc);
aoqi@1 1341
aoqi@1 1342 // thread in the default location (r15_thread on 64bit)
aoqi@1 1343 void set_last_Java_frame(Register last_java_sp,
aoqi@1 1344 Register last_java_fp,
aoqi@1 1345 address last_java_pc);
aoqi@1 1346
aoqi@1 1347 void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc);
aoqi@1 1348
aoqi@1 1349 // thread in the default location (r15_thread on 64bit)
aoqi@1 1350 void reset_last_Java_frame(bool clear_fp, bool clear_pc);
aoqi@1 1351
aoqi@1 1352 // Stores
aoqi@1 1353 void store_check(Register obj); // store check for obj - register is destroyed afterwards
aoqi@1 1354 void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
aoqi@1 1355
aoqi@1 1356
aoqi@1 1357 void g1_write_barrier_pre(Register obj,
aoqi@1 1358 #ifndef _LP64
aoqi@1 1359 Register thread,
aoqi@1 1360 #endif
aoqi@1 1361 Register tmp,
aoqi@1 1362 Register tmp2,
aoqi@1 1363 bool tosca_live);
aoqi@1 1364 void g1_write_barrier_post(Register store_addr,
aoqi@1 1365 Register new_val,
aoqi@1 1366 #ifndef _LP64
aoqi@1 1367 Register thread,
aoqi@1 1368 #endif
aoqi@1 1369 Register tmp,
aoqi@1 1370 Register tmp2);
aoqi@1 1371
aoqi@1 1372
aoqi@1 1373
aoqi@1 1374 // split store_check(Register obj) to enhance instruction interleaving
aoqi@1 1375 void store_check_part_1(Register obj);
aoqi@1 1376 void store_check_part_2(Register obj);
aoqi@1 1377
aoqi@1 1378 // C 'boolean' to Java boolean: x == 0 ? 0 : 1
aoqi@1 1379 void c2bool(Register x);
aoqi@1 1380 //add for compressedoops
aoqi@1 1381 void load_klass(Register dst, Register src);
aoqi@1 1382 void store_klass(Register dst, Register src);
aoqi@1 1383 void load_prototype_header(Register dst, Register src);
aoqi@1 1384 /*
aoqi@1 1385 // C++ bool manipulation
aoqi@1 1386
aoqi@1 1387 void movbool(Register dst, Address src);
aoqi@1 1388 void movbool(Address dst, bool boolconst);
aoqi@1 1389 void movbool(Address dst, Register src);
aoqi@1 1390 void testbool(Register dst);
aoqi@1 1391
aoqi@1 1392 // oop manipulations
aoqi@1 1393 void load_klass(Register dst, Register src);
aoqi@1 1394 void store_klass(Register dst, Register src);
aoqi@1 1395
aoqi@1 1396 void load_prototype_header(Register dst, Register src);*/
aoqi@1 1397
aoqi@1 1398 #ifdef _LP64
aoqi@1 1399 void store_klass_gap(Register dst, Register src);
aoqi@1 1400
aoqi@1 1401 void load_heap_oop(Register dst, Address src);
aoqi@1 1402 void store_heap_oop(Address dst, Register src);
aoqi@1 1403 void encode_heap_oop(Register r);
aoqi@1 1404 void decode_heap_oop(Register r);
aoqi@1 1405 void encode_heap_oop_not_null(Register r);
aoqi@1 1406 void decode_heap_oop_not_null(Register r);
aoqi@1 1407 void encode_heap_oop_not_null(Register dst, Register src);
aoqi@1 1408 void decode_heap_oop_not_null(Register dst, Register src);
aoqi@1 1409
aoqi@1 1410 void encode_klass_not_null(Register r);
aoqi@1 1411 void decode_klass_not_null(Register r);
aoqi@1 1412 void encode_klass_not_null(Register dst, Register src);
aoqi@1 1413 void decode_klass_not_null(Register dst, Register src);
aoqi@1 1414
aoqi@1 1415 //void set_narrow_oop(Register dst, jobject obj);
aoqi@1 1416
aoqi@1 1417 // Returns the byte size of the instructions generated by decode_klass_not_null()
aoqi@1 1418 // when compressed klass pointers are being used.
aoqi@1 1419 static int instr_size_for_decode_klass_not_null();
aoqi@1 1420
aoqi@1 1421 // if heap base register is used - reinit it with the correct value
aoqi@1 1422 void reinit_heapbase();
aoqi@1 1423 DEBUG_ONLY(void verify_heapbase(const char* msg);)
aoqi@1 1424
aoqi@1 1425 #endif // _LP64
aoqi@1 1426
aoqi@1 1427 void incrementl(Register reg, int value = 1);
aoqi@1 1428
aoqi@1 1429 void decrementl(Register reg, int value = 1);
aoqi@1 1430
aoqi@1 1431 /*
aoqi@1 1432 // Int division/remainder for Java
aoqi@1 1433 // (as idivl, but checks for special case as described in JVM spec.)
aoqi@1 1434 // returns idivl instruction offset for implicit exception handling
aoqi@1 1435 int corrected_idivl(Register reg);
aoqi@1 1436
aoqi@1 1437 // Long division/remainder for Java
aoqi@1 1438 // (as idivq, but checks for special case as described in JVM spec.)
aoqi@1 1439 // returns idivq instruction offset for implicit exception handling
aoqi@1 1440 int corrected_idivq(Register reg);
aoqi@1 1441 */
aoqi@1 1442
aoqi@1 1443 void int3();
aoqi@1 1444 /*
aoqi@1 1445 // Long operation macros for a 32bit cpu
aoqi@1 1446 // Long negation for Java
aoqi@1 1447 void lneg(Register hi, Register lo);
aoqi@1 1448
aoqi@1 1449 // Long multiplication for Java
aoqi@1 1450 // (destroys contents of eax, ebx, ecx and edx)
aoqi@1 1451 void lmul(int x_rsp_offset, int y_rsp_offset); // rdx:rax = x * y
aoqi@1 1452
aoqi@1 1453 // Long shifts for Java
aoqi@1 1454 // (semantics as described in JVM spec.)
aoqi@1 1455 void lshl(Register hi, Register lo); // hi:lo << (rcx & 0x3f)
aoqi@1 1456 void lshr(Register hi, Register lo, bool sign_extension = false); // hi:lo >> (rcx & 0x3f)
aoqi@1 1457
aoqi@1 1458 // Long compare for Java
aoqi@1 1459 // (semantics as described in JVM spec.)
aoqi@1 1460 void lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo); // x_hi = lcmp(x, y)
aoqi@1 1461
aoqi@1 1462
aoqi@1 1463 // misc
aoqi@1 1464 */
aoqi@1 1465 // Sign extension
aoqi@1 1466 #ifdef _LP64
aoqi@1 1467 void sign_extend_short(Register reg) { dsll32(reg, reg, 16); dsra32(reg, reg, 16); }
aoqi@1 1468 void sign_extend_byte(Register reg) { dsll32(reg, reg, 24); dsra32(reg, reg, 24); }
aoqi@1 1469 #else
aoqi@1 1470 void sign_extend_short(Register reg) { sll(reg, reg, 16); sra(reg, reg, 16); }
aoqi@1 1471 void sign_extend_byte(Register reg) { sll(reg, reg, 24); sra(reg, reg, 24); }
aoqi@1 1472 #endif
aoqi@1 1473 void rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp);
aoqi@1 1474 void rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp);
aoqi@1 1475
aoqi@1 1476 // Inlined sin/cos generator for Java; must not use CPU instruction
aoqi@1 1477 // directly on Intel as it does not have high enough precision
aoqi@1 1478 // outside of the range [-pi/4, pi/4]. Extra argument indicate the
aoqi@1 1479 // number of FPU stack slots in use; all but the topmost will
aoqi@1 1480 // require saving if a slow case is necessary. Assumes argument is
aoqi@1 1481 // on FP TOS; result is on FP TOS. No cpu registers are changed by
aoqi@1 1482 // this code.
aoqi@1 1483 void trigfunc(char trig, int num_fpu_regs_in_use = 1);
aoqi@1 1484 /*
aoqi@1 1485 // branch to L if FPU flag C2 is set/not set
aoqi@1 1486 // tmp is a temporary register, if none is available use noreg
aoqi@1 1487 void jC2 (Register tmp, Label& L);
aoqi@1 1488 void jnC2(Register tmp, Label& L);
aoqi@1 1489
aoqi@1 1490 // Pop ST (ffree & fincstp combined)
aoqi@1 1491 void fpop();
aoqi@1 1492
aoqi@1 1493 // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack
aoqi@1 1494 void push_fTOS();
aoqi@1 1495
aoqi@1 1496 // pops double TOS element from CPU stack and pushes on FPU stack
aoqi@1 1497 void pop_fTOS();
aoqi@1 1498
aoqi@1 1499 void empty_FPU_stack();
aoqi@1 1500
aoqi@1 1501 void push_IU_state();
aoqi@1 1502 void pop_IU_state();
aoqi@1 1503
aoqi@1 1504 void push_FPU_state();
aoqi@1 1505 void pop_FPU_state();
aoqi@1 1506
aoqi@1 1507 void push_CPU_state();
aoqi@1 1508 void pop_CPU_state();
aoqi@1 1509
aoqi@1 1510 // Round up to a power of two
aoqi@1 1511 void round_to(Register reg, int modulus);
aoqi@1 1512
aoqi@1 1513 // Callee saved registers handling
aoqi@1 1514 void push_callee_saved_registers();
aoqi@1 1515 void pop_callee_saved_registers();
aoqi@1 1516 */
aoqi@1 1517 // allocation
aoqi@1 1518 void eden_allocate(
aoqi@1 1519 Register obj, // result: pointer to object after successful allocation
aoqi@1 1520 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
aoqi@1 1521 int con_size_in_bytes, // object size in bytes if known at compile time
aoqi@1 1522 Register t1, // temp register
aoqi@1 1523 Register t2,
aoqi@1 1524 Label& slow_case // continuation point if fast allocation fails
aoqi@1 1525 );
aoqi@1 1526 void tlab_allocate(
aoqi@1 1527 Register obj, // result: pointer to object after successful allocation
aoqi@1 1528 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
aoqi@1 1529 int con_size_in_bytes, // object size in bytes if known at compile time
aoqi@1 1530 Register t1, // temp register
aoqi@1 1531 Register t2, // temp register
aoqi@1 1532 Label& slow_case // continuation point if fast allocation fails
aoqi@1 1533 );
aoqi@1 1534 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
aoqi@1 1535
aoqi@1 1536 //----
aoqi@1 1537 // void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
aoqi@1 1538
aoqi@1 1539
aoqi@1 1540 // Debugging
aoqi@1 1541
aoqi@1 1542 // only if +VerifyOops
aoqi@1 1543 void verify_oop(Register reg, const char* s = "broken oop");
aoqi@1 1544 void verify_oop_addr(Address addr, const char * s = "broken oop addr");
aoqi@1 1545 void verify_oop_subroutine();
aoqi@1 1546 // TODO: verify method and klass metadata (compare against vptr?)
aoqi@1 1547 void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {}
aoqi@1 1548 void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){}
aoqi@1 1549
aoqi@1 1550 #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__)
aoqi@1 1551 #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__)
aoqi@1 1552
aoqi@1 1553 // only if +VerifyFPU
aoqi@1 1554 void verify_FPU(int stack_depth, const char* s = "illegal FPU state");
aoqi@1 1555
aoqi@1 1556 // prints msg, dumps registers and stops execution
aoqi@1 1557 void stop(const char* msg);
aoqi@1 1558
aoqi@1 1559 // prints msg and continues
aoqi@1 1560 void warn(const char* msg);
aoqi@1 1561
aoqi@1 1562 static void debug(char* msg/*, RegistersForDebugging* regs*/);
aoqi@1 1563 static void debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg);
aoqi@1 1564 static void debug64(char* msg, int64_t pc, int64_t regs[]);
aoqi@1 1565
aoqi@1 1566 void print_reg(Register reg);
aoqi@1 1567 void print_reg(FloatRegister reg);
aoqi@1 1568 //void os_breakpoint();
aoqi@1 1569
aoqi@1 1570 void untested() { stop("untested"); }
aoqi@1 1571
aoqi@1 1572 void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, sizeof(b), "unimplemented: %s", what); stop(b); }
aoqi@1 1573
aoqi@1 1574 void should_not_reach_here() { stop("should not reach here"); }
aoqi@1 1575
aoqi@1 1576 void print_CPU_state();
aoqi@1 1577
aoqi@1 1578 // Stack overflow checking
aoqi@1 1579 void bang_stack_with_offset(int offset) {
aoqi@1 1580 // stack grows down, caller passes positive offset
aoqi@1 1581 assert(offset > 0, "must bang with negative offset");
aoqi@1 1582 if (offset <= 32768) {
aoqi@1 1583 sw(A0, SP, -offset);
aoqi@1 1584 } else {
aoqi@1 1585 #ifdef _LP64
aoqi@1 1586 li(AT, offset);
aoqi@1 1587 dsub(AT, SP, AT);
aoqi@1 1588 #else
aoqi@1 1589 move(AT, offset);
aoqi@1 1590 sub(AT, SP, AT);
aoqi@1 1591 #endif
aoqi@1 1592 sw(A0, AT, 0);
aoqi@1 1593 }
aoqi@1 1594 }
aoqi@1 1595
aoqi@1 1596 // Writes to stack successive pages until offset reached to check for
aoqi@1 1597 // stack overflow + shadow pages. Also, clobbers tmp
aoqi@1 1598 void bang_stack_size(Register size, Register tmp);
aoqi@1 1599 virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
aoqi@1 1600 Register tmp,
aoqi@1 1601 int offset);
aoqi@1 1602
aoqi@1 1603 // Support for serializing memory accesses between threads
aoqi@1 1604 void serialize_memory(Register thread, Register tmp);
aoqi@1 1605
aoqi@1 1606 //void verify_tlab();
aoqi@1 1607 void verify_tlab(Register t1, Register t2);
aoqi@1 1608
aoqi@1 1609 // Biased locking support
aoqi@1 1610 // lock_reg and obj_reg must be loaded up with the appropriate values.
aoqi@1 1611 // swap_reg must be rax, and is killed.
aoqi@1 1612 // tmp_reg is optional. If it is supplied (i.e., != noreg) it will
aoqi@1 1613 // be killed; if not supplied, push/pop will be used internally to
aoqi@1 1614 // allocate a temporary (inefficient, avoid if possible).
aoqi@1 1615 // Optional slow case is for implementations (interpreter and C1) which branch to
aoqi@1 1616 // slow case directly. Leaves condition codes set for C2's Fast_Lock node.
aoqi@1 1617 // Returns offset of first potentially-faulting instruction for null
aoqi@1 1618 // check info (currently consumed only by C1). If
aoqi@1 1619 // swap_reg_contains_mark is true then returns -1 as it is assumed
aoqi@1 1620 // the calling code has already passed any potential faults.
aoqi@1 1621 int biased_locking_enter(Register lock_reg, Register obj_reg,
aoqi@1 1622 Register swap_reg, Register tmp_reg,
aoqi@1 1623 bool swap_reg_contains_mark,
aoqi@1 1624 Label& done, Label* slow_case = NULL,
aoqi@1 1625 BiasedLockingCounters* counters = NULL);
aoqi@1 1626 void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done);
aoqi@1 1627
aoqi@1 1628
aoqi@1 1629 // Calls
aoqi@1 1630
aoqi@1 1631 void call(address entry);
aoqi@1 1632 void call(address entry, relocInfo::relocType rtype);
aoqi@1 1633 void call(address entry, RelocationHolder& rh);
aoqi@1 1634 // Emit the CompiledIC call idiom
aoqi@1 1635 void ic_call(address entry);
aoqi@1 1636
aoqi@1 1637 void jmp(address entry);
aoqi@1 1638 void jmp(address entry, relocInfo::relocType rtype);
aoqi@1 1639
aoqi@1 1640 // Argument ops
aoqi@1 1641 /*inline void store_int_argument(Register s, Argument& a);
aoqi@1 1642 inline void store_long_argument(Register s, Argument& a);
aoqi@1 1643 inline void store_float_argument(FloatRegister s, Argument& a);
aoqi@1 1644 inline void store_double_argument(FloatRegister s, Argument& a);
aoqi@1 1645 inline void store_ptr_argument(Register s, Argument& a);*/
aoqi@1 1646 inline void store_int_argument(Register s, Argument &a) {
aoqi@1 1647 if(a.is_Register()) {
aoqi@1 1648 move(a.as_Register(), s);
aoqi@1 1649 } else {
aoqi@1 1650 sw(s, a.as_caller_address());
aoqi@1 1651 }
aoqi@1 1652 }
aoqi@1 1653
aoqi@1 1654 inline void store_long_argument(Register s, Argument &a) {
aoqi@1 1655 Argument a1 = a.successor();
aoqi@1 1656 if(a.is_Register() && a1.is_Register()) {
aoqi@1 1657 move(a.as_Register(), s);
aoqi@1 1658 move(a.as_Register(), s);
aoqi@1 1659 } else {
aoqi@1 1660 sd(s, a.as_caller_address());
aoqi@1 1661 }
aoqi@1 1662 }
aoqi@1 1663
aoqi@1 1664 inline void store_float_argument(FloatRegister s, Argument &a) {
aoqi@1 1665 if(a.is_Register()) {
aoqi@1 1666 mov_s(a.as_FloatRegister(), s);
aoqi@1 1667 } else {
aoqi@1 1668 swc1(s, a.as_caller_address());
aoqi@1 1669 }
aoqi@1 1670 }
aoqi@1 1671 inline void store_double_argument(FloatRegister s, Argument &a) {
aoqi@1 1672 if(a.is_Register()) {
aoqi@1 1673 mov_d(a.as_FloatRegister(), s);
aoqi@1 1674 } else {
aoqi@1 1675 sdc1(s, a.as_caller_address());
aoqi@1 1676 }
aoqi@1 1677 }
aoqi@1 1678
aoqi@1 1679 inline void store_ptr_argument(Register s, Argument &a) {
aoqi@1 1680 if(a.is_Register()) {
aoqi@1 1681 move(a.as_Register(), s);
aoqi@1 1682 } else {
aoqi@1 1683 st_ptr(s, a.as_caller_address());
aoqi@1 1684 }
aoqi@1 1685 }
aoqi@1 1686
aoqi@1 1687 // Load and store values by size and signed-ness
aoqi@1 1688 void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg);
aoqi@1 1689 void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg);
aoqi@1 1690
aoqi@1 1691 // interface method calling
aoqi@1 1692 void lookup_interface_method(Register recv_klass,
aoqi@1 1693 Register intf_klass,
aoqi@1 1694 RegisterOrConstant itable_index,
aoqi@1 1695 Register method_result,
aoqi@1 1696 Register scan_temp,
aoqi@1 1697 Label& no_such_interface);
aoqi@1 1698 // virtual method calling
aoqi@1 1699 void lookup_virtual_method(Register recv_klass,
aoqi@1 1700 RegisterOrConstant vtable_index,
aoqi@1 1701 Register method_result);
aoqi@1 1702
aoqi@1 1703 // ld_ptr will perform lw for 32 bit VMs and ld for 64 bit VMs
aoqi@1 1704 // st_ptr will perform sw for 32 bit VMs and sd for 64 bit VMs
aoqi@1 1705 inline void ld_ptr(Register rt, Address a){
aoqi@1 1706 #ifdef _LP64
aoqi@1 1707 ld(rt, a.base(), a.disp());
aoqi@1 1708 #else
aoqi@1 1709 lw(rt, a.base(), a.disp());
aoqi@1 1710 #endif
aoqi@1 1711 }
aoqi@1 1712 inline void ld_ptr(Register rt, Register base, int offset16){
aoqi@1 1713 #ifdef _LP64
aoqi@1 1714 ld(rt, base, offset16);
aoqi@1 1715 #else
aoqi@1 1716 lw(rt, base, offset16);
aoqi@1 1717 #endif
aoqi@1 1718
aoqi@1 1719 }
aoqi@1 1720 inline void st_ptr(Register rt, Address a){
aoqi@1 1721 #ifdef _LP64
aoqi@1 1722 sd(rt, a.base(), a.disp());
aoqi@1 1723 #else
aoqi@1 1724 sw(rt, a.base(), a.disp());
aoqi@1 1725 #endif
aoqi@1 1726 }
aoqi@1 1727 inline void st_ptr(Register rt, Register base, int offset16) {
aoqi@1 1728 #ifdef _LP64
aoqi@1 1729 sd(rt, base, offset16);
aoqi@1 1730 #else
aoqi@1 1731 sw(rt, base, offset16);
aoqi@1 1732 #endif
aoqi@1 1733
aoqi@1 1734 }
aoqi@1 1735
aoqi@1 1736 void ld_ptr(Register rt, Register offset, Register base);
aoqi@1 1737 void st_ptr(Register rt, Register offset, Register base);
aoqi@1 1738
aoqi@1 1739 // ld_long will perform lw for 32 bit VMs and ld for 64 bit VMs
aoqi@1 1740 // st_long will perform sw for 32 bit VMs and sd for 64 bit VMs
aoqi@1 1741 inline void ld_long(Register rt, Register base, int offset16);
aoqi@1 1742 inline void st_long(Register rt, Register base, int offset16);
aoqi@1 1743 inline void ld_long(Register rt, Address a);
aoqi@1 1744 inline void st_long(Register rt, Address a);
aoqi@1 1745
aoqi@1 1746
aoqi@1 1747 void ld_long(Register rt, Register offset, Register base);
aoqi@1 1748 void st_long(Register rt, Register offset, Register base);
aoqi@1 1749 // Regular vs. d* versions
aoqi@1 1750 inline void addu_long(Register rd, Register rs, Register rt) {
aoqi@1 1751 #ifdef _LP64
aoqi@1 1752 daddu(rd, rs, rt);
aoqi@1 1753 #else
aoqi@1 1754 addu(rd, rs, rt);
aoqi@1 1755 #endif
aoqi@1 1756 }
aoqi@1 1757 inline void addu_long(Register rd, Register rs, long imm32_64) {
aoqi@1 1758 #ifdef _LP64
aoqi@1 1759 daddiu(rd, rs, imm32_64);
aoqi@1 1760 #else
aoqi@1 1761 addiu(rd, rs, imm32_64);
aoqi@1 1762 #endif
aoqi@1 1763
aoqi@1 1764 }
aoqi@1 1765
aoqi@1 1766 // Floating
aoqi@1 1767 public:
aoqi@1 1768 // swap the two byte of the low 16-bit halfword
aoqi@1 1769 // this directive will use AT, be sure the high 16-bit of reg is zero
aoqi@1 1770 // by yjl 6/28/2005
aoqi@1 1771 void hswap(Register reg);
aoqi@1 1772 void huswap(Register reg);
aoqi@1 1773
aoqi@1 1774 // convert big endian integer to little endian integer
aoqi@1 1775 // by yjl 6/29/2005
aoqi@1 1776 void swap(Register reg);
aoqi@1 1777
aoqi@1 1778 // implement the x86 instruction semantic
aoqi@1 1779 // if c_reg == *dest then *dest <= x_reg
aoqi@1 1780 // else c_reg <= *dest
aoqi@1 1781 // the AT indicate if xchg occurred, 1 for xchged, else 0
aoqi@1 1782 // by yjl 6/28/2005
aoqi@1 1783 void cmpxchg(Register x_reg, Address dest, Register c_reg);
aoqi@1 1784 #ifdef _LP64
aoqi@1 1785 void cmpxchg32(Register x_reg, Address dest, Register c_reg);
aoqi@1 1786 #endif
aoqi@1 1787 void cmpxchg8(Register x_regLo, Register x_regHi, Address dest, Register c_regLo, Register c_regHi);
aoqi@1 1788
aoqi@1 1789
aoqi@1 1790
aoqi@1 1791 void round_to(Register reg, int modulus) {
aoqi@1 1792 assert_different_registers(reg, AT);
aoqi@1 1793 increment(reg, modulus - 1);
aoqi@1 1794 move(AT, - modulus);
aoqi@1 1795 andr(reg, reg, AT);
aoqi@1 1796 }
aoqi@1 1797
aoqi@1 1798 //pop & push, added by aoqi
aoqi@1 1799 #ifdef _LP64
aoqi@1 1800 void extend_sign(Register rh, Register rl) { stop("extend_sign"); }
aoqi@1 1801 void neg(Register reg) { dsubu(reg, R0, reg); }
aoqi@1 1802 void push (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); }
aoqi@1 1803 void push (FloatRegister reg) { sdc1(reg, SP, -8); daddi(SP, SP, -8); }
aoqi@1 1804 void pop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); }
aoqi@1 1805 void pop (FloatRegister reg) { ldc1(reg, SP, 0); daddi(SP, SP, 8); }
aoqi@1 1806 void pop () { daddi(SP, SP, 8); }
aoqi@1 1807 void pop2 () { daddi(SP, SP, 16); }
aoqi@1 1808 #else
aoqi@1 1809 void extend_sign(Register rh, Register rl) { sra(rh, rl, 31); }
aoqi@1 1810 void neg(Register reg) { subu(reg, R0, reg); }
aoqi@1 1811 void push (Register reg) { sw (reg, SP, -4); addi(SP, SP, -4); }
aoqi@1 1812 void push (FloatRegister reg) { swc1(reg, SP, -4); addi(SP, SP, -4); }
aoqi@1 1813 void pop (Register reg) { lw (reg, SP, 0); addi(SP, SP, 4); }
aoqi@1 1814 void pop (FloatRegister reg) { lwc1(reg, SP, 0); addi(SP, SP, 4); }
aoqi@1 1815 void pop () { addi(SP, SP, 4); }
aoqi@1 1816 void pop2 () { addi(SP, SP, 8); }
aoqi@1 1817 #endif
aoqi@1 1818 void push2(Register reg1, Register reg2);
aoqi@1 1819 void pop2 (Register reg1, Register reg2);
aoqi@1 1820 void dpush (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); }
aoqi@1 1821 void dpop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); }
aoqi@1 1822
aoqi@1 1823 /* branches may exceed 16-bit offset */
aoqi@1 1824 void b_far(address entry);
aoqi@1 1825 void b_far(Label& L);
aoqi@1 1826
aoqi@1 1827 void bne_far (Register rs, Register rt, address entry);
aoqi@1 1828 void bne_far (Register rs, Register rt, Label& L);
aoqi@1 1829
aoqi@1 1830 void beq_far (Register rs, Register rt, address entry);
aoqi@1 1831 void beq_far (Register rs, Register rt, Label& L);
aoqi@1 1832
aoqi@1 1833 //move an 32-bit immediate to Register
aoqi@1 1834 void move(Register reg, int imm32) { li32(reg, imm32); }
aoqi@1 1835 void li (Register rd, long imm);
aoqi@1 1836 void li (Register rd, address addr) { li(rd, (long)addr); }
aoqi@1 1837 //replace move(Register reg, int imm)
aoqi@1 1838 void li32(Register rd, int imm32); // sign-extends to 64 bits on mips64
aoqi@1 1839 #ifdef _LP64
aoqi@1 1840 void dli(Register rd, long imm) { li(rd, imm); }
aoqi@1 1841 void li64(Register rd, long imm);
aoqi@1 1842 void li48(Register rd, long imm);
aoqi@1 1843 #endif
aoqi@1 1844
aoqi@1 1845 #ifdef _LP64
aoqi@1 1846 void move(Register rd, Register rs) { dadd(rd, rs, R0); }
aoqi@1 1847 void move_u32(Register rd, Register rs) { addu32(rd, rs, R0); }
aoqi@1 1848 #else
aoqi@1 1849 void move(Register rd, Register rs) { add(rd, rs, R0); }
aoqi@1 1850 #endif
aoqi@1 1851 void dmove(Register rd, Register rs) { dadd(rd, rs, R0); }
aoqi@1 1852
aoqi@1 1853 #ifdef _LP64
aoqi@1 1854 void shl(Register reg, int sa) { dsll(reg, reg, sa); }
aoqi@1 1855 void shr(Register reg, int sa) { dsrl(reg, reg, sa); }
aoqi@1 1856 void sar(Register reg, int sa) { dsra(reg, reg, sa); }
aoqi@1 1857 #else
aoqi@1 1858 void shl(Register reg, int sa) { sll(reg, reg, sa); }
aoqi@1 1859 void shr(Register reg, int sa) { srl(reg, reg, sa); }
aoqi@1 1860 void sar(Register reg, int sa) { sra(reg, reg, sa); }
aoqi@1 1861 #endif
aoqi@1 1862
aoqi@1 1863 #ifndef PRODUCT
aoqi@1 1864 static void pd_print_patched_instruction(address branch) {
aoqi@1 1865 jint stub_inst = *(jint*) branch;
aoqi@1 1866 print_instruction(stub_inst);
aoqi@1 1867 ::tty->print("%s", " (unresolved)");
aoqi@1 1868
aoqi@1 1869 }
aoqi@1 1870 #endif
aoqi@1 1871
aoqi@1 1872 // the follow two might use AT register, be sure you have no meanful data in AT before you call them
aoqi@1 1873 // by yjl 6/23/2005
aoqi@1 1874 void increment(Register reg, int imm);
aoqi@1 1875 void decrement(Register reg, int imm);
aoqi@1 1876
aoqi@1 1877 //FIXME
aoqi@1 1878 void empty_FPU_stack(){/*need implemented*/};
aoqi@1 1879
aoqi@1 1880 //we need 2 fun to save and resotre general register
aoqi@1 1881 void pushad();
aoqi@1 1882 void popad();
aoqi@1 1883
aoqi@1 1884 // Test sub_klass against super_klass, with fast and slow paths.
aoqi@1 1885
aoqi@1 1886 // The fast path produces a tri-state answer: yes / no / maybe-slow.
aoqi@1 1887 // One of the three labels can be NULL, meaning take the fall-through.
aoqi@1 1888 // If super_check_offset is -1, the value is loaded up from super_klass.
aoqi@1 1889 // No registers are killed, except temp_reg.
aoqi@1 1890 void check_klass_subtype_fast_path(Register sub_klass,
aoqi@1 1891 Register super_klass,
aoqi@1 1892 Register temp_reg,
aoqi@1 1893 Label* L_success,
aoqi@1 1894 Label* L_failure,
aoqi@1 1895 Label* L_slow_path,
aoqi@1 1896 RegisterOrConstant super_check_offset = RegisterOrConstant(-1));
aoqi@1 1897
aoqi@1 1898 // The rest of the type check; must be wired to a corresponding fast path.
aoqi@1 1899 // It does not repeat the fast path logic, so don't use it standalone.
aoqi@1 1900 // The temp_reg and temp2_reg can be noreg, if no temps are available.
aoqi@1 1901 // Updates the sub's secondary super cache as necessary.
aoqi@1 1902 // If set_cond_codes, condition codes will be Z on success, NZ on failure.
aoqi@1 1903 void check_klass_subtype_slow_path(Register sub_klass,
aoqi@1 1904 Register super_klass,
aoqi@1 1905 Register temp_reg,
aoqi@1 1906 Register temp2_reg,
aoqi@1 1907 Label* L_success,
aoqi@1 1908 Label* L_failure,
aoqi@1 1909 bool set_cond_codes = false);
aoqi@1 1910
aoqi@1 1911 // Simplified, combined version, good for typical uses.
aoqi@1 1912 // Falls through on failure.
aoqi@1 1913 void check_klass_subtype(Register sub_klass,
aoqi@1 1914 Register super_klass,
aoqi@1 1915 Register temp_reg,
aoqi@1 1916 Label& L_success);
aoqi@1 1917
aoqi@1 1918 // method handles (JSR 292)
aoqi@1 1919 Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
aoqi@1 1920
aoqi@1 1921 void get_vm_result (Register oop_result, Register thread);
aoqi@1 1922 void get_vm_result_2(Register metadata_result, Register thread);
aoqi@1 1923 #undef VIRTUAL
aoqi@29 1924 void atomic_inc32(address counter_addr, int inc, Register tmp_reg1, Register tmp_reg2);
aoqi@1 1925
aoqi@30 1926 void fast_lock(Register obj, Register box, Register tmp, Register scr);
aoqi@30 1927 void fast_unlock(Register obj, Register box, Register tmp);
aoqi@1 1928 };
aoqi@1 1929
aoqi@1 1930 /**
aoqi@1 1931 * class SkipIfEqual:
aoqi@1 1932 *
aoqi@1 1933 * Instantiating this class will result in assembly code being output that will
aoqi@1 1934 * jump around any code emitted between the creation of the instance and it's
aoqi@1 1935 * automatic destruction at the end of a scope block, depending on the value of
aoqi@1 1936 * the flag passed to the constructor, which will be checked at run-time.
aoqi@1 1937 */
aoqi@1 1938 class SkipIfEqual {
aoqi@1 1939 private:
aoqi@1 1940 MacroAssembler* _masm;
aoqi@1 1941 Label _label;
aoqi@1 1942
aoqi@1 1943 public:
aoqi@1 1944 SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value);
aoqi@1 1945 ~SkipIfEqual();
aoqi@1 1946 };
aoqi@1 1947
aoqi@1 1948 #ifdef ASSERT
aoqi@1 1949 inline bool AbstractAssembler::pd_check_instruction_mark() { return true; }
aoqi@1 1950 #endif
aoqi@1 1951
aoqi@1 1952 #endif // CPU_MIPS_VM_ASSEMBLER_MIPS_HPP

mercurial