src/cpu/mips/vm/assembler_mips.hpp

Wed, 29 Mar 2017 09:41:51 +0800

author
aoqi
date
Wed, 29 Mar 2017 09:41:51 +0800
changeset 392
4bfb40d1e17a
parent 391
910b77f150c4
child 396
474ce9f32bce
permissions
-rw-r--r--

#4662 TieredCompilation is turned off.
TieredCompilation is not supported yet.

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@199 40
aoqi@199 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@199 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@199 175 int _number;
aoqi@1 176 public:
aoqi@199 177 enum {
aoqi@1 178 #ifdef _LP64
aoqi@199 179 n_register_parameters = 8, // 8 integer registers used to pass parameters
aoqi@199 180 n_float_register_parameters = 8 // 4 float registers used to pass parameters
aoqi@1 181 #else
aoqi@199 182 n_register_parameters = 4, // 4 integer registers used to pass parameters
aoqi@199 183 n_float_register_parameters = 4 // 4 float registers used to pass parameters
aoqi@1 184 #endif
aoqi@199 185 };
aoqi@1 186
aoqi@199 187 Argument(int number):_number(number){ }
aoqi@199 188 Argument successor() {return Argument(number() + 1);}
aoqi@1 189
aoqi@199 190 int number()const {return _number;}
aoqi@199 191 bool is_Register()const {return _number < n_register_parameters;}
aoqi@199 192 bool is_FloatRegister()const {return _number < n_float_register_parameters;}
aoqi@199 193
aoqi@199 194 Register as_Register()const {
aoqi@199 195 assert(is_Register(), "must be a register argument");
aoqi@199 196 return ::as_Register(A0->encoding() + _number);
aoqi@199 197 }
aoqi@199 198 FloatRegister as_FloatRegister()const {
aoqi@199 199 assert(is_FloatRegister(), "must be a float register argument");
aoqi@199 200 return ::as_FloatRegister(F12->encoding() + _number);
aoqi@199 201 }
aoqi@199 202
aoqi@199 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@199 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@199 274 RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) {
aoqi@199 275 switch (rtype) {
aoqi@199 276 case relocInfo::external_word_type:
aoqi@199 277 return external_word_Relocation::spec(addr);
aoqi@199 278 case relocInfo::internal_word_type:
aoqi@199 279 return internal_word_Relocation::spec(addr);
aoqi@199 280 case relocInfo::opt_virtual_call_type:
aoqi@199 281 return opt_virtual_call_Relocation::spec();
aoqi@199 282 case relocInfo::static_call_type:
aoqi@199 283 return static_call_Relocation::spec();
aoqi@199 284 case relocInfo::runtime_call_type:
aoqi@199 285 return runtime_call_Relocation::spec();
aoqi@199 286 case relocInfo::poll_type:
aoqi@199 287 case relocInfo::poll_return_type:
aoqi@199 288 return Relocation::spec_simple(rtype);
aoqi@199 289 case relocInfo::none:
aoqi@199 290 case relocInfo::oop_type:
aoqi@199 291 // Oops are a special case. Normally they would be their own section
aoqi@199 292 // but in cases like icBuffer they are literals in the code stream that
aoqi@199 293 // we don't have a section for. We use none so that we get a literal address
aoqi@199 294 // which is always patchable.
aoqi@199 295 return RelocationHolder();
aoqi@199 296 default:
aoqi@199 297 ShouldNotReachHere();
aoqi@199 298 return RelocationHolder();
aoqi@199 299 }
aoqi@199 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@199 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@199 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@199 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@199 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@199 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@199 367 public:
fujie@381 368
fujie@381 369 public:
fujie@381 370
fujie@381 371 static const int LogInstructionSize = 2;
fujie@381 372 static const int InstructionSize = 1 << LogInstructionSize;
fujie@381 373
aoqi@199 374 // opcode, highest 6 bits: bits[31...26]
aoqi@1 375 enum ops {
aoqi@199 376 special_op = 0x00, // special_ops
aoqi@199 377 regimm_op = 0x01, // regimm_ops
aoqi@199 378 j_op = 0x02,
aoqi@199 379 jal_op = 0x03,
aoqi@199 380 beq_op = 0x04,
aoqi@199 381 bne_op = 0x05,
aoqi@199 382 blez_op = 0x06,
aoqi@199 383 bgtz_op = 0x07,
aoqi@199 384 addi_op = 0x08,
aoqi@199 385 addiu_op = 0x09,
aoqi@199 386 slti_op = 0x0a,
aoqi@199 387 sltiu_op = 0x0b,
aoqi@199 388 andi_op = 0x0c,
aoqi@199 389 ori_op = 0x0d,
aoqi@199 390 xori_op = 0x0e,
aoqi@199 391 lui_op = 0x0f,
aoqi@199 392 cop0_op = 0x10, // cop0_ops
aoqi@199 393 cop1_op = 0x11, // cop1_ops
aoqi@199 394 gs_cop2_op = 0x12, // gs_cop2_ops
aoqi@199 395 cop1x_op = 0x13, // cop1x_ops
aoqi@199 396 beql_op = 0x14,
aoqi@199 397 bnel_op = 0x15,
aoqi@199 398 blezl_op = 0x16,
aoqi@199 399 bgtzl_op = 0x17,
aoqi@199 400 daddi_op = 0x18,
aoqi@199 401 daddiu_op = 0x19,
aoqi@199 402 ldl_op = 0x1a,
aoqi@199 403 ldr_op = 0x1b,
aoqi@199 404 special2_op = 0x1c, // special2_ops
aoqi@199 405 msa_op = 0x1e, // msa_ops
aoqi@199 406 special3_op = 0x1f, // special3_ops
aoqi@199 407 lb_op = 0x20,
aoqi@199 408 lh_op = 0x21,
aoqi@199 409 lwl_op = 0x22,
aoqi@199 410 lw_op = 0x23,
aoqi@199 411 lbu_op = 0x24,
aoqi@199 412 lhu_op = 0x25,
aoqi@1 413 lwr_op = 0x26,
aoqi@1 414 lwu_op = 0x27,
aoqi@1 415 sb_op = 0x28,
aoqi@1 416 sh_op = 0x29,
aoqi@1 417 swl_op = 0x2a,
aoqi@199 418 sw_op = 0x2b,
aoqi@199 419 sdl_op = 0x2c,
aoqi@199 420 sdr_op = 0x2d,
aoqi@199 421 swr_op = 0x2e,
aoqi@199 422 cache_op = 0x2f,
aoqi@199 423 ll_op = 0x30,
aoqi@199 424 lwc1_op = 0x31,
aoqi@199 425 gs_lwc2_op = 0x32, //gs_lwc2_ops
aoqi@199 426 pref_op = 0x33,
aoqi@199 427 lld_op = 0x34,
aoqi@199 428 ldc1_op = 0x35,
aoqi@199 429 gs_ldc2_op = 0x36, //gs_ldc2_ops
aoqi@199 430 ld_op = 0x37,
aoqi@199 431 sc_op = 0x38,
aoqi@199 432 swc1_op = 0x39,
aoqi@199 433 gs_swc2_op = 0x3a, //gs_swc2_ops
aoqi@199 434 scd_op = 0x3c,
aoqi@199 435 sdc1_op = 0x3d,
aoqi@199 436 gs_sdc2_op = 0x3e, //gs_sdc2_ops
aoqi@199 437 sd_op = 0x3f
aoqi@1 438 };
aoqi@1 439
aoqi@199 440 static const char *ops_name[];
fujie@41 441
aoqi@199 442 //special family, the opcode is in low 6 bits.
aoqi@199 443 enum special_ops {
aoqi@199 444 sll_op = 0x00,
aoqi@199 445 movci_op = 0x01,
aoqi@199 446 srl_op = 0x02,
aoqi@199 447 sra_op = 0x03,
aoqi@199 448 sllv_op = 0x04,
aoqi@199 449 srlv_op = 0x06,
aoqi@199 450 srav_op = 0x07,
aoqi@199 451 jr_op = 0x08,
aoqi@199 452 jalr_op = 0x09,
aoqi@199 453 movz_op = 0x0a,
aoqi@199 454 movn_op = 0x0b,
aoqi@199 455 syscall_op = 0x0c,
aoqi@199 456 break_op = 0x0d,
aoqi@199 457 sync_op = 0x0f,
aoqi@199 458 mfhi_op = 0x10,
aoqi@199 459 mthi_op = 0x11,
aoqi@199 460 mflo_op = 0x12,
aoqi@199 461 mtlo_op = 0x13,
aoqi@199 462 dsllv_op = 0x14,
aoqi@199 463 dsrlv_op = 0x16,
aoqi@199 464 dsrav_op = 0x17,
aoqi@199 465 mult_op = 0x18,
aoqi@199 466 multu_op = 0x19,
aoqi@199 467 div_op = 0x1a,
aoqi@199 468 divu_op = 0x1b,
aoqi@199 469 dmult_op = 0x1c,
aoqi@199 470 dmultu_op = 0x1d,
aoqi@199 471 ddiv_op = 0x1e,
aoqi@199 472 ddivu_op = 0x1f,
aoqi@199 473 add_op = 0x20,
aoqi@199 474 addu_op = 0x21,
aoqi@199 475 sub_op = 0x22,
aoqi@199 476 subu_op = 0x23,
aoqi@199 477 and_op = 0x24,
aoqi@199 478 or_op = 0x25,
aoqi@199 479 xor_op = 0x26,
aoqi@199 480 nor_op = 0x27,
aoqi@199 481 slt_op = 0x2a,
aoqi@199 482 sltu_op = 0x2b,
aoqi@199 483 dadd_op = 0x2c,
aoqi@199 484 daddu_op = 0x2d,
aoqi@199 485 dsub_op = 0x2e,
aoqi@199 486 dsubu_op = 0x2f,
aoqi@199 487 tge_op = 0x30,
aoqi@199 488 tgeu_op = 0x31,
aoqi@199 489 tlt_op = 0x32,
aoqi@199 490 tltu_op = 0x33,
aoqi@199 491 teq_op = 0x34,
aoqi@199 492 tne_op = 0x36,
aoqi@199 493 dsll_op = 0x38,
aoqi@199 494 dsrl_op = 0x3a,
aoqi@199 495 dsra_op = 0x3b,
aoqi@199 496 dsll32_op = 0x3c,
aoqi@199 497 dsrl32_op = 0x3e,
aoqi@199 498 dsra32_op = 0x3f
aoqi@199 499 };
fujie@41 500
aoqi@199 501 static const char* special_name[];
aoqi@1 502
aoqi@199 503 //regimm family, the opcode is in rt[16...20], 5 bits
aoqi@199 504 enum regimm_ops {
aoqi@199 505 bltz_op = 0x00,
aoqi@199 506 bgez_op = 0x01,
aoqi@199 507 bltzl_op = 0x02,
aoqi@199 508 bgezl_op = 0x03,
aoqi@199 509 tgei_op = 0x08,
aoqi@199 510 tgeiu_op = 0x09,
aoqi@199 511 tlti_op = 0x0a,
aoqi@199 512 tltiu_op = 0x0b,
aoqi@199 513 teqi_op = 0x0c,
aoqi@199 514 tnei_op = 0x0e,
aoqi@199 515 bltzal_op = 0x10,
aoqi@199 516 bgezal_op = 0x11,
aoqi@199 517 bltzall_op = 0x12,
aoqi@199 518 bgezall_op = 0x13,
aoqi@199 519 bposge32_op = 0x1c,
aoqi@199 520 bposge64_op = 0x1d,
aoqi@199 521 synci_op = 0x1f,
aoqi@199 522 };
aoqi@1 523
aoqi@199 524 static const char* regimm_name[];
aoqi@1 525
aoqi@199 526 //cop0 family, the ops is in bits[25...21], 5 bits
aoqi@199 527 enum cop0_ops {
aoqi@199 528 mfc0_op = 0x00,
aoqi@199 529 dmfc0_op = 0x01,
aoqi@199 530 //
aoqi@199 531 mxgc0_op = 0x03, //MFGC0, DMFGC0, MTGC0
aoqi@199 532 mtc0_op = 0x04,
aoqi@199 533 dmtc0_op = 0x05,
aoqi@199 534 rdpgpr_op = 0x0a,
aoqi@199 535 inter_op = 0x0b,
aoqi@199 536 wrpgpr_op = 0x0c
aoqi@199 537 };
fujie@195 538
aoqi@199 539 //cop1 family, the ops is in bits[25...21], 5 bits
aoqi@199 540 enum cop1_ops {
aoqi@199 541 mfc1_op = 0x00,
aoqi@199 542 dmfc1_op = 0x01,
aoqi@199 543 cfc1_op = 0x02,
aoqi@199 544 mfhc1_op = 0x03,
aoqi@199 545 mtc1_op = 0x04,
aoqi@199 546 dmtc1_op = 0x05,
aoqi@199 547 ctc1_op = 0x06,
aoqi@199 548 mthc1_op = 0x07,
aoqi@199 549 bc1f_op = 0x08,
aoqi@199 550 single_fmt = 0x10,
aoqi@199 551 double_fmt = 0x11,
aoqi@199 552 word_fmt = 0x14,
aoqi@199 553 long_fmt = 0x15,
aoqi@199 554 ps_fmt = 0x16
aoqi@199 555 };
fujie@195 556
aoqi@1 557
aoqi@199 558 //2 bist (bits[17...16]) of bc1x instructions (cop1)
aoqi@199 559 enum bc_ops {
aoqi@199 560 bcf_op = 0x0,
aoqi@199 561 bct_op = 0x1,
aoqi@199 562 bcfl_op = 0x2,
aoqi@199 563 bctl_op = 0x3,
aoqi@199 564 };
aoqi@1 565
aoqi@199 566 // low 6 bits of c_x_fmt instructions (cop1)
aoqi@199 567 enum c_conds {
aoqi@199 568 f_cond = 0x30,
aoqi@199 569 un_cond = 0x31,
aoqi@199 570 eq_cond = 0x32,
aoqi@199 571 ueq_cond = 0x33,
aoqi@199 572 olt_cond = 0x34,
aoqi@199 573 ult_cond = 0x35,
aoqi@199 574 ole_cond = 0x36,
aoqi@199 575 ule_cond = 0x37,
aoqi@199 576 sf_cond = 0x38,
aoqi@199 577 ngle_cond = 0x39,
aoqi@199 578 seq_cond = 0x3a,
aoqi@199 579 ngl_cond = 0x3b,
aoqi@199 580 lt_cond = 0x3c,
aoqi@199 581 nge_cond = 0x3d,
aoqi@199 582 le_cond = 0x3e,
aoqi@199 583 ngt_cond = 0x3f
aoqi@199 584 };
aoqi@1 585
aoqi@199 586 // low 6 bits of cop1 instructions
aoqi@199 587 enum float_ops {
aoqi@199 588 fadd_op = 0x00,
aoqi@199 589 fsub_op = 0x01,
aoqi@199 590 fmul_op = 0x02,
aoqi@199 591 fdiv_op = 0x03,
aoqi@199 592 fsqrt_op = 0x04,
aoqi@199 593 fabs_op = 0x05,
aoqi@199 594 fmov_op = 0x06,
aoqi@199 595 fneg_op = 0x07,
aoqi@199 596 froundl_op = 0x08,
aoqi@199 597 ftruncl_op = 0x09,
aoqi@199 598 fceill_op = 0x0a,
aoqi@199 599 ffloorl_op = 0x0b,
aoqi@199 600 froundw_op = 0x0c,
aoqi@199 601 ftruncw_op = 0x0d,
aoqi@199 602 fceilw_op = 0x0e,
aoqi@199 603 ffloorw_op = 0x0f,
aoqi@199 604 movf_f_op = 0x11,
aoqi@199 605 movt_f_op = 0x11,
aoqi@199 606 movz_f_op = 0x12,
aoqi@199 607 movn_f_op = 0x13,
aoqi@199 608 frecip_op = 0x15,
aoqi@199 609 frsqrt_op = 0x16,
aoqi@199 610 fcvts_op = 0x20,
aoqi@199 611 fcvtd_op = 0x21,
aoqi@199 612 fcvtw_op = 0x24,
aoqi@199 613 fcvtl_op = 0x25,
aoqi@276 614 fcvtps_op = 0x26,
aoqi@276 615 fcvtspl_op = 0x28,
aoqi@199 616 fpll_op = 0x2c,
aoqi@199 617 fplu_op = 0x2d,
aoqi@199 618 fpul_op = 0x2e,
aoqi@199 619 fpuu_op = 0x2f
aoqi@199 620 };
aoqi@199 621
aoqi@199 622 static const char* cop1_name[];
aoqi@199 623
aoqi@199 624 //cop1x family, the opcode is in low 6 bits.
aoqi@199 625 enum cop1x_ops {
aoqi@199 626 lwxc1_op = 0x00,
aoqi@199 627 ldxc1_op = 0x01,
aoqi@199 628 luxc1_op = 0x05,
aoqi@199 629 swxc1_op = 0x08,
aoqi@199 630 sdxc1_op = 0x09,
aoqi@199 631 suxc1_op = 0x0d,
aoqi@199 632 prefx_op = 0x0f,
aoqi@199 633
aoqi@199 634 alnv_ps_op = 0x1e,
aoqi@199 635 madd_s_op = 0x20,
aoqi@199 636 madd_d_op = 0x21,
aoqi@199 637 madd_ps_op = 0x26,
aoqi@199 638 msub_s_op = 0x28,
aoqi@199 639 msub_d_op = 0x29,
aoqi@199 640 msub_ps_op = 0x2e,
aoqi@199 641 nmadd_s_op = 0x30,
aoqi@199 642 nmadd_d_op = 0x31,
aoqi@199 643 nmadd_ps_op = 0x36,
aoqi@199 644 nmsub_s_op = 0x38,
aoqi@199 645 nmsub_d_op = 0x39,
aoqi@199 646 nmsub_ps_op = 0x3e
aoqi@199 647 };
aoqi@199 648
aoqi@199 649 static const char* cop1x_name[];
aoqi@199 650
aoqi@199 651 //special2 family, the opcode is in low 6 bits.
aoqi@199 652 enum special2_ops {
aoqi@199 653 madd_op = 0x00,
aoqi@199 654 maddu_op = 0x01,
aoqi@199 655 mul_op = 0x02,
fujie@295 656 gs0x03_op = 0x03,
aoqi@199 657 msub_op = 0x04,
aoqi@199 658 msubu_op = 0x05,
fujie@295 659 gs0x06_op = 0x06,
aoqi@199 660 gsemul2_op = 0x07,
aoqi@199 661 gsemul3_op = 0x08,
aoqi@199 662 gsemul4_op = 0x09,
aoqi@199 663 gsemul5_op = 0x0a,
aoqi@199 664 gsemul6_op = 0x0b,
aoqi@199 665 gsemul7_op = 0x0c,
aoqi@199 666 gsemul8_op = 0x0d,
aoqi@199 667 gsemul9_op = 0x0e,
aoqi@199 668 gsemul10_op = 0x0f,
aoqi@199 669 gsmult_op = 0x10,
aoqi@199 670 gsdmult_op = 0x11,
aoqi@199 671 gsmultu_op = 0x12,
aoqi@199 672 gsdmultu_op = 0x13,
aoqi@199 673 gsdiv_op = 0x14,
aoqi@199 674 gsddiv_op = 0x15,
aoqi@199 675 gsdivu_op = 0x16,
aoqi@199 676 gsddivu_op = 0x17,
aoqi@199 677 gsmod_op = 0x1c,
aoqi@199 678 gsdmod_op = 0x1d,
aoqi@199 679 gsmodu_op = 0x1e,
aoqi@199 680 gsdmodu_op = 0x1f,
aoqi@199 681 clz_op = 0x20,
aoqi@199 682 clo_op = 0x21,
aoqi@199 683 xctx_op = 0x22, //ctz, cto, dctz, dcto, gsX
aoqi@199 684 gsrxr_x_op = 0x23, //gsX
aoqi@199 685 dclz_op = 0x24,
aoqi@199 686 dclo_op = 0x25,
aoqi@199 687 gsle_op = 0x26,
aoqi@199 688 gsgt_op = 0x27,
aoqi@199 689 gs86j_op = 0x28,
aoqi@199 690 gsloop_op = 0x29,
aoqi@199 691 gsaj_op = 0x2a,
aoqi@199 692 gsldpc_op = 0x2b,
aoqi@199 693 gs86set_op = 0x30,
aoqi@199 694 gstm_op = 0x31,
aoqi@199 695 gscvt_ld_op = 0x32,
aoqi@199 696 gscvt_ud_op = 0x33,
aoqi@199 697 gseflag_op = 0x34,
aoqi@199 698 gscam_op = 0x35,
aoqi@199 699 gstop_op = 0x36,
aoqi@199 700 gssettag_op = 0x37,
aoqi@199 701 gssdbbp_op = 0x38
aoqi@199 702 };
aoqi@199 703
aoqi@199 704 static const char* special2_name[];
aoqi@199 705
aoqi@199 706 // special3 family, the opcode is in low 6 bits.
aoqi@199 707 enum special3_ops {
aoqi@199 708 ext_op = 0x00,
aoqi@199 709 dextm_op = 0x01,
aoqi@199 710 dextu_op = 0x02,
aoqi@199 711 dext_op = 0x03,
aoqi@199 712 ins_op = 0x04,
aoqi@199 713 dinsm_op = 0x05,
aoqi@199 714 dinsu_op = 0x06,
aoqi@199 715 dins_op = 0x07,
aoqi@199 716 lxx_op = 0x0a, //lwx, lhx, lbux, ldx
aoqi@199 717 insv_op = 0x0c,
aoqi@199 718 dinsv_op = 0x0d,
aoqi@199 719 ar1_op = 0x10, //MIPS DSP
aoqi@199 720 cmp1_op = 0x11, //MIPS DSP
aoqi@199 721 re1_op = 0x12, //MIPS DSP, re1_ops
aoqi@199 722 sh1_op = 0x13, //MIPS DSP
aoqi@199 723 ar2_op = 0x14, //MIPS DSP
aoqi@199 724 cmp2_op = 0x15, //MIPS DSP
aoqi@199 725 re2_op = 0x16, //MIPS DSP, re2_ops
aoqi@199 726 sh2_op = 0x17, //MIPS DSP
fujie@256 727 ar3_op = 0x18, //MIPS DSP
fujie@256 728 bshfl_op = 0x20 //seb, seh
aoqi@199 729 };
aoqi@199 730
aoqi@199 731 // re1_ops
aoqi@199 732 enum re1_ops {
aoqi@199 733 absq_s_qb_op = 0x01,
aoqi@199 734 repl_qb_op = 0x02,
aoqi@199 735 replv_qb_op = 0x03,
aoqi@199 736 absq_s_ph_op = 0x09,
aoqi@199 737 repl_ph_op = 0x0a,
aoqi@199 738 replv_ph_op = 0x0b,
aoqi@199 739 absq_s_w_op = 0x11,
aoqi@199 740 bitrev_op = 0x1b
aoqi@199 741 };
aoqi@199 742
aoqi@199 743 // re2_ops
aoqi@199 744 enum re2_ops {
aoqi@199 745 repl_ob_op = 0x02,
aoqi@199 746 replv_ob_op = 0x03,
aoqi@199 747 absq_s_qh_op = 0x09,
aoqi@199 748 repl_qh_op = 0x0a,
aoqi@199 749 replv_qh_op = 0x0b,
aoqi@199 750 absq_s_pw_op = 0x11,
aoqi@199 751 repl_pw_op = 0x12,
aoqi@199 752 replv_pw_op = 0x13,
aoqi@199 753 };
aoqi@199 754
aoqi@199 755 static const char* special3_name[];
aoqi@199 756
aoqi@199 757 // lwc2/gs_lwc2 family, the opcode is in low 6 bits.
aoqi@199 758 enum gs_lwc2_ops {
jiangshaofeng@362 759 gslble_op = 0x10,
jiangshaofeng@362 760 gslbgt_op = 0x11,
jiangshaofeng@362 761 gslhle_op = 0x12,
jiangshaofeng@362 762 gslhgt_op = 0x13,
jiangshaofeng@362 763 gslwle_op = 0x14,
jiangshaofeng@362 764 gslwgt_op = 0x15,
jiangshaofeng@362 765 gsldle_op = 0x16,
jiangshaofeng@362 766 gsldgt_op = 0x17,
jiangshaofeng@362 767 gslwlec1_op = 0x1c,
jiangshaofeng@362 768 gslwgtc1_op = 0x1d,
jiangshaofeng@362 769 gsldlec1_op = 0x1e,
jiangshaofeng@362 770 gsldgtc1_op = 0x1f,
aoqi@199 771 gslq_op = 0x20
aoqi@199 772 };
aoqi@199 773
aoqi@199 774 static const char* gs_lwc2_name[];
aoqi@199 775
aoqi@199 776 // ldc2/gs_ldc2 family, the opcode is in low 3 bits.
aoqi@199 777 enum gs_ldc2_ops {
aoqi@199 778 gslbx_op = 0x0,
aoqi@199 779 gslhx_op = 0x1,
aoqi@199 780 gslwx_op = 0x2,
aoqi@199 781 gsldx_op = 0x3,
aoqi@199 782 gslwxc1_op = 0x6,
aoqi@199 783 gsldxc1_op = 0x7
aoqi@199 784 };
aoqi@199 785
aoqi@199 786 static const char* gs_ldc2_name[];
aoqi@199 787
aoqi@199 788 // swc2/gs_swc2 family, the opcode is in low 6 bits.
aoqi@199 789 enum gs_swc2_ops {
jiangshaofeng@362 790 gssble_op = 0x10,
jiangshaofeng@362 791 gssbgt_op = 0x11,
jiangshaofeng@362 792 gsshle_op = 0x12,
jiangshaofeng@362 793 gsshgt_op = 0x13,
jiangshaofeng@362 794 gsswle_op = 0x14,
jiangshaofeng@362 795 gsswgt_op = 0x15,
jiangshaofeng@362 796 gssdle_op = 0x16,
jiangshaofeng@362 797 gssdgt_op = 0x17,
jiangshaofeng@362 798 gsswlec1_op = 0x1c,
jiangshaofeng@362 799 gsswgtc1_op = 0x1d,
jiangshaofeng@362 800 gssdlec1_op = 0x1e,
jiangshaofeng@362 801 gssdgtc1_op = 0x1f,
aoqi@199 802 gssq_op = 0x20
aoqi@199 803 };
aoqi@199 804
aoqi@199 805 static const char* gs_swc2_name[];
aoqi@199 806
aoqi@199 807 // sdc2/gs_sdc2 family, the opcode is in low 3 bits.
aoqi@199 808 enum gs_sdc2_ops {
aoqi@199 809 gssbx_op = 0x0,
aoqi@199 810 gsshx_op = 0x1,
aoqi@199 811 gsswx_op = 0x2,
aoqi@199 812 gssdx_op = 0x3,
aoqi@199 813 gsswxc1_op = 0x6,
aoqi@199 814 gssdxc1_op = 0x7
aoqi@199 815 };
aoqi@199 816
aoqi@199 817 static const char* gs_sdc2_name[];
fujie@44 818
aoqi@1 819 /* 2013.10.16 Jin: merge from OpenJDK 8 */
aoqi@1 820 enum WhichOperand {
aoqi@1 821 // input to locate_operand, and format code for relocations
aoqi@1 822 imm_operand = 0, // embedded 32-bit|64-bit immediate operand
aoqi@1 823 disp32_operand = 1, // embedded 32-bit displacement or address
aoqi@1 824 call32_operand = 2, // embedded 32-bit self-relative displacement
aoqi@1 825 #ifndef _LP64
aoqi@1 826 _WhichOperand_limit = 3
aoqi@1 827 #else
aoqi@1 828 narrow_oop_operand = 3, // embedded 32-bit immediate narrow oop
aoqi@1 829 _WhichOperand_limit = 4
aoqi@1 830 #endif
aoqi@1 831 };
aoqi@1 832
aoqi@199 833 static int opcode(int insn) { return (insn>>26)&0x3f; }
aoqi@199 834 static int rs(int insn) { return (insn>>21)&0x1f; }
aoqi@199 835 static int rt(int insn) { return (insn>>16)&0x1f; }
aoqi@199 836 static int rd(int insn) { return (insn>>11)&0x1f; }
aoqi@199 837 static int sa(int insn) { return (insn>>6)&0x1f; }
aoqi@199 838 static int special(int insn) { return insn&0x3f; }
aoqi@199 839 static int imm_off(int insn) { return (short)low16(insn); }
lifangyuan@125 840
aoqi@199 841 static int low (int x, int l) { return bitfield(x, 0, l); }
aoqi@199 842 static int low16(int x) { return low(x, 16); }
aoqi@199 843 static int low26(int x) { return low(x, 26); }
lifangyuan@125 844
aoqi@199 845 protected:
aoqi@199 846 //help methods for instruction ejection
aoqi@1 847
aoqi@199 848 // I-Type (Immediate)
aoqi@199 849 // 31 26 25 21 20 16 15 0
aoqi@199 850 //| opcode | rs | rt | immediat |
aoqi@199 851 //| | | | |
aoqi@199 852 // 6 5 5 16
aoqi@199 853 static int insn_ORRI(int op, int rs, int rt, int imm) { return (op<<26) | (rs<<21) | (rt<<16) | low16(imm); }
lifangyuan@125 854
aoqi@199 855 // R-Type (Register)
aoqi@199 856 // 31 26 25 21 20 16 15 11 10 6 5 0
aoqi@199 857 //| special | rs | rt | rd | 0 | opcode |
aoqi@199 858 //| 0 0 0 0 0 0 | | | | 0 0 0 0 0 | |
aoqi@199 859 // 6 5 5 5 5 6
aoqi@199 860 static int insn_RRRO(int rs, int rt, int rd, int op) { return (rs<<21) | (rt<<16) | (rd<<11) | op; }
aoqi@199 861 static int insn_RRSO(int rt, int rd, int sa, int op) { return (rt<<16) | (rd<<11) | (sa<<6) | op; }
aoqi@199 862 static int insn_RRCO(int rs, int rt, int code, int op) { return (rs<<21) | (rt<<16) | (code<<6) | op; }
lifangyuan@125 863
aoqi@199 864 static int insn_COP0(int op, int rt, int rd) { return (cop0_op<<26) | (op<<21) | (rt<<16) | (rd<<11); }
aoqi@199 865 static int insn_COP1(int op, int rt, int fs) { return (cop1_op<<26) | (op<<21) | (rt<<16) | (fs<<11); }
aoqi@1 866
aoqi@199 867 static int insn_F3RO(int fmt, int ft, int fs, int fd, int func) {
aoqi@199 868 return (cop1_op<<26) | (fmt<<21) | (ft<<16) | (fs<<11) | (fd<<6) | func;
aoqi@199 869 }
aoqi@199 870 static int insn_F3ROX(int fmt, int ft, int fs, int fd, int func) {
aoqi@199 871 return (cop1x_op<<26) | (fmt<<21) | (ft<<16) | (fs<<11) | (fd<<6) | func;
aoqi@199 872 }
fujie@65 873
fujie@65 874
aoqi@199 875 //static int low (int x, int l) { return bitfield(x, 0, l); }
aoqi@199 876 //static int low16(int x) { return low(x, 16); }
aoqi@199 877 //static int low26(int x) { return low(x, 26); }
aoqi@1 878
aoqi@199 879 static int high (int x, int l) { return bitfield(x, 32-l, l); }
aoqi@199 880 static int high16(int x) { return high(x, 16); }
aoqi@199 881 static int high6 (int x) { return high(x, 6); }
aoqi@1 882
aoqi@199 883 //get the offset field of jump/branch instruction
aoqi@199 884 int offset(address entry) {
aoqi@199 885 assert(is_simm16((entry - pc() - 4) / 4), "change this code");
aoqi@199 886 if (!is_simm16((entry - pc() - 4) / 4)) {
aoqi@199 887 tty->print_cr("!!! is_simm16: %x", (entry - pc() - 4) / 4);
aoqi@199 888 }
aoqi@199 889 return (entry - pc() - 4) / 4;
aoqi@199 890 }
aoqi@1 891
aoqi@1 892
aoqi@1 893 public:
aoqi@199 894 using AbstractAssembler::offset;
aoqi@1 895
aoqi@199 896 //sign expand with the sign bit is h
aoqi@199 897 static int expand(int x, int h) { return -(x & (1<<h)) | x; }
aoqi@1 898
fujie@293 899 // If x is a mask, return the number of one-bit in x.
fujie@293 900 // else return -1.
fujie@293 901 static int is_int_mask(int x);
fujie@293 902
fujie@301 903 // If x is a mask, return the number of one-bit in x.
fujie@301 904 // else return -1.
fujie@301 905 static int is_jlong_mask(jlong x);
fujie@301 906
aoqi@199 907 // MIPS lui/addiu is both sign extended, so if you wan't to use off32/imm32, you have to use the follow three
aoqi@199 908 static int split_low(int x) {
aoqi@199 909 return (x & 0xffff);
aoqi@199 910 }
aoqi@1 911
aoqi@199 912 static int split_high(int x) {
aoqi@199 913 return ( (x >> 16) + ((x & 0x8000) != 0) ) & 0xffff;
aoqi@199 914 }
aoqi@1 915
aoqi@199 916 static int merge(int low, int high) {
aoqi@199 917 return expand(low, 15) + (high<<16);
aoqi@199 918 }
aoqi@1 919
aoqi@1 920 #ifdef _LP64
aoqi@199 921 static intptr_t merge(intptr_t x0, intptr_t x16, intptr_t x32, intptr_t x48) {
aoqi@199 922 return (x48 << 48) | (x32 << 32) | (x16 << 16) | x0;
aoqi@199 923 }
aoqi@1 924 #endif
aoqi@1 925
aoqi@199 926 // modified by spark 2005/08/18
aoqi@199 927 static bool is_simm (int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); }
aoqi@199 928 static bool is_simm16(int x) { return is_simm(x, 16); }
aoqi@1 929
fujie@381 930 static bool fit_in_jal(address target, address pc) {
fujie@381 931 #ifdef _LP64
fujie@381 932 int dst = ((intptr_t)target - (((intptr_t)pc + 4) & 0xfffffffff0000000))>>2;
fujie@381 933 #else
fujie@381 934 int dst = ((intptr_t)target - (((intptr_t)pc + 4) & 0xf0000000))>>2;
fujie@381 935 #endif
fujie@381 936 if ((dst >= 0) && (dst < (1<<26))) return true;
fujie@381 937 else return false;
aoqi@199 938 }
aoqi@199 939
aoqi@199 940 bool fit_int_branch(address entry) {
aoqi@199 941 return is_simm16(offset(entry));
aoqi@199 942 }
aoqi@1 943
aoqi@1 944 protected:
aoqi@1 945 #ifdef ASSERT
aoqi@199 946 #define CHECK_DELAY
aoqi@1 947 #endif
aoqi@1 948 #ifdef CHECK_DELAY
aoqi@199 949 enum Delay_state { no_delay, at_delay_slot, filling_delay_slot } delay_state;
aoqi@1 950 #endif
aoqi@199 951
aoqi@1 952 public:
aoqi@199 953 void assert_not_delayed() {
aoqi@1 954 #ifdef CHECK_DELAY
aoqi@199 955 assert_not_delayed("next instruction should not be a delay slot");
aoqi@1 956 #endif
aoqi@199 957 }
aoqi@1 958
aoqi@199 959 void assert_not_delayed(const char* msg) {
aoqi@1 960 #ifdef CHECK_DELAY
aoqi@199 961 //guarantee( delay_state == no_delay, msg );
aoqi@199 962 //aoqi_test
aoqi@199 963 if(delay_state != no_delay){
aoqi@199 964 tty->print_cr("%s:%d, pc: %lx", __func__, __LINE__, pc());
aoqi@199 965 }
aoqi@199 966 assert(delay_state == no_delay, msg);
aoqi@199 967 #endif
aoqi@199 968 }
aoqi@1 969
aoqi@1 970 protected:
aoqi@199 971 // Delay slot helpers
aoqi@199 972 // cti is called when emitting control-transfer instruction,
aoqi@199 973 // BEFORE doing the emitting.
aoqi@199 974 // Only effective when assertion-checking is enabled.
aoqi@199 975
aoqi@199 976 // called when emitting cti with a delay slot, AFTER emitting
aoqi@199 977 void has_delay_slot() {
aoqi@1 978 #ifdef CHECK_DELAY
aoqi@199 979 assert_not_delayed("just checking");
aoqi@199 980 delay_state = at_delay_slot;
aoqi@1 981 #endif
aoqi@199 982 }
aoqi@1 983
aoqi@1 984 public:
aoqi@199 985 Assembler* delayed() {
aoqi@1 986 #ifdef CHECK_DELAY
aoqi@199 987 guarantee( delay_state == at_delay_slot, "delayed instructition is not in delay slot");
aoqi@199 988 delay_state = filling_delay_slot;
aoqi@1 989 #endif
aoqi@199 990 return this;
aoqi@199 991 }
aoqi@1 992
aoqi@199 993 void flush() {
aoqi@1 994 #ifdef CHECK_DELAY
aoqi@199 995 guarantee( delay_state == no_delay, "ending code with a delay slot");
aoqi@1 996 #endif
aoqi@199 997 AbstractAssembler::flush();
aoqi@199 998 }
aoqi@199 999
aoqi@199 1000 inline void emit_long(int); // shadows AbstractAssembler::emit_long
aoqi@199 1001 inline void emit_data(int x) { emit_long(x); }
aoqi@199 1002 inline void emit_data(int, RelocationHolder const&);
aoqi@199 1003 inline void emit_data(int, relocInfo::relocType rtype);
aoqi@199 1004 inline void check_delay();
aoqi@199 1005
aoqi@1 1006
aoqi@1 1007 // Generic instructions
aoqi@1 1008 // Does 32bit or 64bit as needed for the platform. In some sense these
aoqi@1 1009 // belong in macro assembler but there is no need for both varieties to exist
aoqi@1 1010
aoqi@1 1011 #ifndef _LP64
aoqi@199 1012 void add(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), add_op)); }
aoqi@199 1013 void addi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1014 void addiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1015 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 1016 #else
aoqi@199 1017 void add(Register rd, Register rs, Register rt) { dadd (rd, rs, rt); }
aoqi@199 1018 void add32(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), add_op)); }
aoqi@199 1019 void addu32(Register rd, Register rs, Register rt){ emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), addu_op)); }
aoqi@199 1020 void addiu32(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1021 void addi(Register rt, Register rs, int imm) { daddi (rt, rs, imm);}
aoqi@199 1022 void addiu(Register rt, Register rs, int imm) { daddiu (rt, rs, imm);}
aoqi@199 1023 void addu(Register rd, Register rs, Register rt) { daddu (rd, rs, rt); }
aoqi@1 1024 #endif
aoqi@1 1025
aoqi@199 1026 void andr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), and_op)); }
aoqi@199 1027 void andi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(andi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 1028
aoqi@199 1029 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@199 1030 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@199 1031 void bgez (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgez_op, off)); has_delay_slot(); }
aoqi@199 1032 void bgezal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezal_op, off)); has_delay_slot(); }
aoqi@199 1033 void bgezall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezall_op, off)); has_delay_slot(); }
aoqi@199 1034 void bgezl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezl_op, off)); has_delay_slot(); }
aoqi@199 1035 void bgtz (Register rs, int off) { emit_long(insn_ORRI(bgtz_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1036 void bgtzl (Register rs, int off) { emit_long(insn_ORRI(bgtzl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1037 void blez (Register rs, int off) { emit_long(insn_ORRI(blez_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1038 void blezl (Register rs, int off) { emit_long(insn_ORRI(blezl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1039 void bltz (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltz_op, off)); has_delay_slot(); }
aoqi@199 1040 void bltzal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzal_op, off)); has_delay_slot(); }
aoqi@199 1041 void bltzall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzall_op, off)); has_delay_slot(); }
aoqi@199 1042 void bltzl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzl_op, off)); has_delay_slot(); }
aoqi@199 1043 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@199 1044 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@199 1045 void brk (int code) { emit_long(break_op | (code<<16)); }
fujie@37 1046
aoqi@199 1047 void beq (Register rs, Register rt, address entry) { beq(rs, rt, offset(entry)); }
aoqi@199 1048 void beql (Register rs, Register rt, address entry) { beql(rs, rt, offset(entry));}
aoqi@199 1049 void bgez (Register rs, address entry) { bgez (rs, offset(entry)); }
aoqi@199 1050 void bgezal (Register rs, address entry) { bgezal (rs, offset(entry)); }
aoqi@199 1051 void bgezall(Register rs, address entry) { bgezall(rs, offset(entry)); }
aoqi@199 1052 void bgezl (Register rs, address entry) { bgezl (rs, offset(entry)); }
aoqi@199 1053 void bgtz (Register rs, address entry) { bgtz (rs, offset(entry)); }
aoqi@199 1054 void bgtzl (Register rs, address entry) { bgtzl (rs, offset(entry)); }
aoqi@199 1055 void blez (Register rs, address entry) { blez (rs, offset(entry)); }
aoqi@199 1056 void blezl (Register rs, address entry) { blezl (rs, offset(entry)); }
aoqi@199 1057 void bltz (Register rs, address entry) { bltz (rs, offset(entry)); }
aoqi@199 1058 void bltzal (Register rs, address entry) { bltzal (rs, offset(entry)); }
aoqi@199 1059 void bltzall(Register rs, address entry) { bltzall(rs, offset(entry)); }
aoqi@199 1060 void bltzl (Register rs, address entry) { bltzl (rs, offset(entry)); }
aoqi@199 1061 void bne (Register rs, Register rt, address entry) { bne(rs, rt, offset(entry)); }
aoqi@199 1062 void bnel (Register rs, Register rt, address entry) { bnel(rs, rt, offset(entry)); }
fujie@37 1063
aoqi@199 1064 void beq (Register rs, Register rt, Label& L) { beq(rs, rt, target(L)); }
aoqi@199 1065 void beql (Register rs, Register rt, Label& L) { beql(rs, rt, target(L)); }
aoqi@199 1066 void bgez (Register rs, Label& L){ bgez (rs, target(L)); }
aoqi@199 1067 void bgezal (Register rs, Label& L){ bgezal (rs, target(L)); }
aoqi@199 1068 void bgezall(Register rs, Label& L){ bgezall(rs, target(L)); }
aoqi@199 1069 void bgezl (Register rs, Label& L){ bgezl (rs, target(L)); }
aoqi@199 1070 void bgtz (Register rs, Label& L){ bgtz (rs, target(L)); }
aoqi@199 1071 void bgtzl (Register rs, Label& L){ bgtzl (rs, target(L)); }
aoqi@199 1072 void blez (Register rs, Label& L){ blez (rs, target(L)); }
aoqi@199 1073 void blezl (Register rs, Label& L){ blezl (rs, target(L)); }
aoqi@199 1074 void bltz (Register rs, Label& L){ bltz (rs, target(L)); }
aoqi@199 1075 void bltzal (Register rs, Label& L){ bltzal (rs, target(L)); }
aoqi@199 1076 void bltzall(Register rs, Label& L){ bltzall(rs, target(L)); }
aoqi@199 1077 void bltzl (Register rs, Label& L){ bltzl (rs, target(L)); }
aoqi@199 1078 void bne (Register rs, Register rt, Label& L){ bne(rs, rt, target(L)); }
aoqi@199 1079 void bnel (Register rs, Register rt, Label& L){ bnel(rs, rt, target(L)); }
fujie@45 1080
aoqi@199 1081 void dadd (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dadd_op)); }
aoqi@199 1082 void daddi (Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1083 void daddiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1084 void daddu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), daddu_op)); }
aoqi@199 1085 void ddiv (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddiv_op)); }
aoqi@199 1086 void ddivu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddivu_op)); }
fujie@41 1087
aoqi@199 1088 void movz (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), movz_op)); }
aoqi@199 1089 void movn (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), movn_op)); }
aoqi@199 1090
aoqi@199 1091 void movt (Register rd, Register rs) { emit_long(((int)rs->encoding() << 21) | (1 << 16) | ((int)rd->encoding() << 11) | movci_op); }
aoqi@199 1092 void movf (Register rd, Register rs) { emit_long(((int)rs->encoding() << 21) | ((int)rd->encoding() << 11) | movci_op); }
fujie@41 1093
fujie@256 1094 enum bshfl_ops {
fujie@256 1095 seb_op = 0x10,
fujie@256 1096 seh_op = 0x18
fujie@256 1097 };
fujie@256 1098 void seb (Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (seb_op << 6) | bshfl_op); }
fujie@256 1099 void seh (Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (seh_op << 6) | bshfl_op); }
fujie@256 1100
fujie@292 1101 void ext (Register rt, Register rs, int pos, int size) {
fujie@292 1102 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@292 1103 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@292 1104 guarantee((0 < pos + size) && (pos + size <= 32), "pos + size must be in (0, 32]");
fujie@292 1105
fujie@292 1106 int lsb = pos;
fujie@292 1107 int msbd = size - 1;
fujie@292 1108
fujie@301 1109 emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (msbd << 11) | (lsb << 6) | ext_op);
fujie@301 1110 }
fujie@301 1111
fujie@301 1112 void dext (Register rt, Register rs, int pos, int size) {
fujie@301 1113 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@301 1114 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@301 1115 guarantee((0 < pos + size) && (pos + size <= 63), "pos + size must be in (0, 63]");
fujie@301 1116
fujie@301 1117 int lsb = pos;
fujie@301 1118 int msbd = size - 1;
fujie@301 1119
fujie@301 1120 emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (msbd << 11) | (lsb << 6) | dext_op);
fujie@292 1121 }
fujie@292 1122
fujie@315 1123 void rotr (Register rd, Register rt, int sa) {
fujie@315 1124 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | srl_op);
fujie@315 1125 }
fujie@315 1126
fujie@315 1127 void drotr (Register rd, Register rt, int sa) {
fujie@315 1128 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | dsrl_op);
fujie@315 1129 }
fujie@315 1130
fujie@315 1131 void drotr32 (Register rd, Register rt, int sa) {
fujie@315 1132 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | dsrl32_op);
fujie@315 1133 }
fujie@315 1134
fujie@315 1135 void rotrv (Register rd, Register rt, Register rs) {
fujie@315 1136 emit_long((special_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (1 << 6) | srlv_op);
fujie@315 1137 }
fujie@315 1138
fujie@315 1139 void drotrv (Register rd, Register rt, Register rs) {
fujie@315 1140 emit_long((special_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (1 << 6) | dsrlv_op);
fujie@315 1141 }
fujie@315 1142
aoqi@1 1143 // Do mult and div need both 32-bit and 64-bit version? FIXME aoqi
aoqi@1 1144 //#ifndef _LP64
aoqi@1 1145 #if 1
aoqi@199 1146 void div (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, div_op)); }
aoqi@199 1147 void divu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, divu_op)); }
aoqi@1 1148 #else
aoqi@199 1149 void div (Register rs, Register rt) { ddiv (rs, rt);}
aoqi@199 1150 void divu (Register rs, Register rt) { ddivu(rs, rt);}
aoqi@1 1151 #endif
aoqi@199 1152 void dmult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmult_op)); }
aoqi@199 1153 void dmultu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmultu_op)); }
aoqi@199 1154 void dsll (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsll_op)); }
aoqi@199 1155 void dsllv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsllv_op)); }
aoqi@199 1156 void dsll32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsll32_op)); }
aoqi@199 1157 void dsra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsra_op)); }
aoqi@199 1158 void dsrav (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrav_op)); }
aoqi@199 1159 void dsra32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsra32_op)); }
aoqi@199 1160 void dsrl (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsrl_op)); }
aoqi@199 1161 void dsrlv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrlv_op)); }
aoqi@199 1162 void dsrl32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, dsrl32_op)); }
aoqi@199 1163 void dsub (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsub_op)); }
aoqi@199 1164 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 1165
aoqi@199 1166 void b(int off) { beq(R0, R0, off); }
aoqi@199 1167 void b(address entry) { b(offset(entry)); }
aoqi@199 1168 void b(Label& L) { b(target(L)); }
aoqi@1 1169
aoqi@199 1170 void j(address entry);
aoqi@199 1171 void jal(address entry);
aoqi@1 1172
aoqi@199 1173 void jalr(Register rd, Register rs) { emit_long( ((int)rs->encoding()<<21) | ((int)rd->encoding()<<11) | jalr_op); has_delay_slot(); }
aoqi@199 1174 void jalr(Register rs) { jalr(RA, rs); }
aoqi@199 1175 void jalr() { jalr(T9); }
aoqi@1 1176
aoqi@199 1177 void jr(Register rs) { emit_long(((int)rs->encoding()<<21) | jr_op); has_delay_slot(); }
aoqi@199 1178
aoqi@199 1179 void lb (Register rt, Register base, int off) { emit_long(insn_ORRI(lb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1180 void lbu(Register rt, Register base, int off) { emit_long(insn_ORRI(lbu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1181 void ld (Register rt, Register base, int off) { emit_long(insn_ORRI(ld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1182 void ldl(Register rt, Register base, int off) { emit_long(insn_ORRI(ldl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1183 void ldr(Register rt, Register base, int off) { emit_long(insn_ORRI(ldr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1184 void lh (Register rt, Register base, int off) { emit_long(insn_ORRI(lh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1185 void lhu(Register rt, Register base, int off) { emit_long(insn_ORRI(lhu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1186 void ll (Register rt, Register base, int off) { emit_long(insn_ORRI(ll_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1187 void lld(Register rt, Register base, int off) { emit_long(insn_ORRI(lld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1188 void lui(Register rt, int imm) { emit_long(insn_ORRI(lui_op, 0, (int)rt->encoding(), imm)); }
aoqi@199 1189 void lw (Register rt, Register base, int off) { emit_long(insn_ORRI(lw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1190 void lwl(Register rt, Register base, int off) { emit_long(insn_ORRI(lwl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1191 void lwr(Register rt, Register base, int off) { emit_long(insn_ORRI(lwr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1192 void lwu(Register rt, Register base, int off) { emit_long(insn_ORRI(lwu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1193
aoqi@199 1194 void lb (Register rt, Address src);
aoqi@199 1195 void lbu(Register rt, Address src);
aoqi@199 1196 void ld (Register rt, Address src);
aoqi@199 1197 void ldl(Register rt, Address src);
aoqi@199 1198 void ldr(Register rt, Address src);
aoqi@199 1199 void lh (Register rt, Address src);
aoqi@199 1200 void lhu(Register rt, Address src);
aoqi@199 1201 void ll (Register rt, Address src);
aoqi@199 1202 void lld(Register rt, Address src);
aoqi@199 1203 void lw (Register rt, Address src);
aoqi@199 1204 void lwl(Register rt, Address src);
aoqi@199 1205 void lwr(Register rt, Address src);
aoqi@199 1206 void lwu(Register rt, Address src);
aoqi@199 1207 void lea(Register rt, Address src);
aoqi@199 1208 void pref(int hint, Register base, int off) { emit_long(insn_ORRI(pref_op, (int)base->encoding(), low(hint, 5), low(off, 16))); }
aoqi@199 1209
aoqi@199 1210 void mfhi (Register rd) { emit_long( ((int)rd->encoding()<<11) | mfhi_op ); }
aoqi@199 1211 void mflo (Register rd) { emit_long( ((int)rd->encoding()<<11) | mflo_op ); }
aoqi@199 1212 void mthi (Register rs) { emit_long( ((int)rs->encoding()<<21) | mthi_op ); }
aoqi@199 1213 void mtlo (Register rs) { emit_long( ((int)rs->encoding()<<21) | mtlo_op ); }
fujie@318 1214
aoqi@199 1215 void mult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, mult_op)); }
aoqi@199 1216 void multu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, multu_op)); }
aoqi@1 1217
aoqi@199 1218 void nor(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), nor_op)); }
aoqi@199 1219
aoqi@199 1220 void orr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), or_op)); }
aoqi@199 1221 void ori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(ori_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1222
aoqi@199 1223 void sb (Register rt, Register base, int off) { emit_long(insn_ORRI(sb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1224 void sc (Register rt, Register base, int off) { emit_long(insn_ORRI(sc_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1225 void scd (Register rt, Register base, int off) { emit_long(insn_ORRI(scd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1226 void sd (Register rt, Register base, int off) { emit_long(insn_ORRI(sd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1227 void sdl (Register rt, Register base, int off) { emit_long(insn_ORRI(sdl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1228 void sdr (Register rt, Register base, int off) { emit_long(insn_ORRI(sdr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1229 void sh (Register rt, Register base, int off) { emit_long(insn_ORRI(sh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
fujie@318 1230 void sll (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), sll_op)); }
aoqi@199 1231 void sllv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sllv_op)); }
aoqi@199 1232 void slt (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), slt_op)); }
aoqi@199 1233 void slti (Register rt, Register rs, int imm) { emit_long(insn_ORRI(slti_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1234 void sltiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(sltiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1235 void sltu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sltu_op)); }
aoqi@199 1236 void sra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), sa, sra_op)); }
aoqi@199 1237 void srav (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), srav_op)); }
fujie@319 1238 void srl (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), srl_op)); }
aoqi@199 1239 void srlv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), srlv_op)); }
fujie@318 1240
aoqi@1 1241 #ifndef _LP64
aoqi@199 1242 void sub (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sub_op)); }
aoqi@199 1243 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 1244 #else
aoqi@199 1245 void sub (Register rd, Register rs, Register rt) { dsub (rd, rs, rt); }
aoqi@199 1246 void subu (Register rd, Register rs, Register rt) { dsubu (rd, rs, rt); }
aoqi@199 1247 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 1248 #endif
aoqi@199 1249 void sw (Register rt, Register base, int off) { emit_long(insn_ORRI(sw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1250 void swl (Register rt, Register base, int off) { emit_long(insn_ORRI(swl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1251 void swr (Register rt, Register base, int off) { emit_long(insn_ORRI(swr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1252 void sync () { emit_long(sync_op); }
aoqi@199 1253 void syscall(int code) { emit_long( (code<<6) | syscall_op ); }
aoqi@1 1254
aoqi@199 1255 void sb(Register rt, Address dst);
aoqi@199 1256 void sc(Register rt, Address dst);
aoqi@199 1257 void scd(Register rt, Address dst);
aoqi@199 1258 void sd(Register rt, Address dst);
aoqi@199 1259 void sdl(Register rt, Address dst);
aoqi@199 1260 void sdr(Register rt, Address dst);
aoqi@199 1261 void sh(Register rt, Address dst);
aoqi@199 1262 void sw(Register rt, Address dst);
aoqi@199 1263 void swl(Register rt, Address dst);
aoqi@199 1264 void swr(Register rt, Address dst);
aoqi@1 1265
aoqi@199 1266 void teq (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, teq_op)); }
aoqi@199 1267 void teqi (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), teqi_op, imm)); }
aoqi@199 1268 void tge (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tge_op)); }
aoqi@199 1269 void tgei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgei_op, imm)); }
aoqi@199 1270 void tgeiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgeiu_op, imm)); }
aoqi@199 1271 void tgeu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tgeu_op)); }
aoqi@199 1272 void tlt (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tlt_op)); }
aoqi@199 1273 void tlti (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tlti_op, imm)); }
aoqi@199 1274 void tltiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tltiu_op, imm)); }
aoqi@199 1275 void tltu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tltu_op)); }
aoqi@199 1276 void tne (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tne_op)); }
aoqi@199 1277 void tnei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tnei_op, imm)); }
aoqi@1 1278
aoqi@199 1279 void xorr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), xor_op)); }
aoqi@199 1280 void xori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(xori_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@1 1281
aoqi@199 1282 void nop() { emit_long(0); }
aoqi@1 1283
aoqi@1 1284
fujie@195 1285
aoqi@199 1286 void ldc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(ldc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1287 void lwc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(lwc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1288 void ldc1(FloatRegister ft, Address src);
aoqi@199 1289 void lwc1(FloatRegister ft, Address src);
aoqi@1 1290
aoqi@199 1291 //COP0
aoqi@199 1292 void mfc0 (Register rt, Register rd) { emit_long(insn_COP0( mfc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1293 void dmfc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmfc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1294 // MFGC0, DMFGC0, MTGC0, DMTGC0 not implemented yet
aoqi@199 1295 void mtc0 (Register rt, Register rd) { emit_long(insn_COP0( mtc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1296 void dmtc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmtc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1297 //COP0 end
aoqi@1 1298
lifangyuan@125 1299
aoqi@199 1300 //COP1
aoqi@199 1301 void mfc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1 (mfc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1302 void dmfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmfc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1303 void cfc1 (Register rt, int fs) { emit_long(insn_COP1( cfc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1304 void mfhc1(Register rt, int fs) { emit_long(insn_COP1(mfhc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1305 void mtc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( mtc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1306 void dmtc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmtc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1307 void ctc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( ctc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1308 void ctc1 (Register rt, int fs) { emit_long(insn_COP1(ctc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1309 void mthc1(Register rt, int fs) { emit_long(insn_COP1(mthc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1310
aoqi@199 1311 void bc1f (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcf_op, off)); has_delay_slot(); }
aoqi@199 1312 void bc1fl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcfl_op, off)); has_delay_slot(); }
aoqi@199 1313 void bc1t (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bct_op, off)); has_delay_slot(); }
aoqi@199 1314 void bc1tl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bctl_op, off)); has_delay_slot(); }
aoqi@199 1315
aoqi@199 1316 void bc1f (address entry) { bc1f(offset(entry)); }
aoqi@199 1317 void bc1fl(address entry) { bc1fl(offset(entry)); }
aoqi@199 1318 void bc1t (address entry) { bc1t(offset(entry)); }
aoqi@199 1319 void bc1tl(address entry) { bc1tl(offset(entry)); }
aoqi@199 1320
aoqi@199 1321 void bc1f (Label& L) { bc1f(target(L)); }
aoqi@199 1322 void bc1fl(Label& L) { bc1fl(target(L)); }
aoqi@199 1323 void bc1t (Label& L) { bc1t(target(L)); }
aoqi@199 1324 void bc1tl(Label& L) { bc1tl(target(L)); }
aoqi@199 1325
aoqi@199 1326 //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags.
aoqi@199 1327 #define INSN_SINGLE(r1, r2, r3, op) \
aoqi@199 1328 { emit_long(insn_F3RO(single_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1329 void add_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fadd_op)}
aoqi@199 1330 void sub_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fsub_op)}
aoqi@199 1331 void mul_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fmul_op)}
aoqi@199 1332 void div_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fdiv_op)}
aoqi@199 1333 void sqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fsqrt_op)}
aoqi@199 1334 void abs_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fabs_op)}
aoqi@199 1335 void mov_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fmov_op)}
aoqi@199 1336 void neg_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fneg_op)}
aoqi@199 1337 void round_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundl_op)}
aoqi@199 1338 void trunc_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncl_op)}
aoqi@199 1339 void ceil_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceill_op)}
aoqi@199 1340 void floor_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorl_op)}
aoqi@199 1341 void round_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundw_op)}
aoqi@199 1342 void trunc_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncw_op)}
aoqi@199 1343 void ceil_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceilw_op)}
aoqi@199 1344 void floor_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorw_op)}
aoqi@199 1345 //null
aoqi@199 1346 //void movf_s(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movf_s")}
aoqi@199 1347 //void movt_s(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movt_s") }
aoqi@199 1348 void movz_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movz_f_op)}
aoqi@199 1349 void movn_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movn_f_op)}
aoqi@199 1350 //null
aoqi@199 1351 void recip_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frecip_op)}
aoqi@199 1352 void rsqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frsqrt_op)}
aoqi@199 1353 //null
aoqi@199 1354 void cvt_d_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtd_op)}
aoqi@199 1355 //null
aoqi@199 1356 void cvt_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtw_op)}
aoqi@199 1357 void cvt_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtl_op)}
aoqi@276 1358 void cvt_ps_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fcvtps_op)}
aoqi@199 1359 //null
aoqi@199 1360 void c_f_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, f_cond)}
aoqi@199 1361 void c_un_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, un_cond)}
aoqi@199 1362 void c_eq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, eq_cond)}
aoqi@199 1363 void c_ueq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ueq_cond)}
aoqi@199 1364 void c_olt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, olt_cond)}
aoqi@199 1365 void c_ult_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ult_cond)}
aoqi@199 1366 void c_ole_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ole_cond)}
aoqi@199 1367 void c_ule_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ule_cond)}
aoqi@199 1368 void c_sf_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, sf_cond)}
aoqi@199 1369 void c_ngle_s(FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngle_cond)}
aoqi@199 1370 void c_seq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, seq_cond)}
aoqi@199 1371 void c_ngl_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngl_cond)}
aoqi@199 1372 void c_lt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, lt_cond)}
aoqi@199 1373 void c_nge_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, nge_cond)}
aoqi@199 1374 void c_le_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, le_cond)}
aoqi@199 1375 void c_ngt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngt_cond)}
aoqi@199 1376
aoqi@199 1377 #undef INSN_SINGLE
aoqi@199 1378
aoqi@199 1379
aoqi@199 1380 //R0->encoding() is 0; INSN_DOUBLE is enclosed by {} for ctags.
aoqi@199 1381 #define INSN_DOUBLE(r1, r2, r3, op) \
aoqi@199 1382 { emit_long(insn_F3RO(double_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1383
aoqi@199 1384 void add_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fadd_op)}
aoqi@199 1385 void sub_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fsub_op)}
aoqi@199 1386 void mul_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fmul_op)}
aoqi@199 1387 void div_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fdiv_op)}
aoqi@199 1388 void sqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fsqrt_op)}
aoqi@199 1389 void abs_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fabs_op)}
aoqi@199 1390 void mov_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fmov_op)}
aoqi@199 1391 void neg_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fneg_op)}
aoqi@199 1392 void round_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundl_op)}
aoqi@199 1393 void trunc_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncl_op)}
aoqi@199 1394 void ceil_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceill_op)}
aoqi@199 1395 void floor_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorl_op)}
aoqi@199 1396 void round_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundw_op)}
aoqi@199 1397 void trunc_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncw_op)}
aoqi@199 1398 void ceil_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceilw_op)}
aoqi@199 1399 void floor_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorw_op)}
aoqi@199 1400 //null
aoqi@199 1401 //void movf_d(Register rd, Register rs, FPConditionCode cc) { unimplemented(" movf_d")}
aoqi@199 1402 //void movt_d(Register rd, Register rs, FPConditionCode cc) { unimplemented(" movt_d") }
aoqi@199 1403 void movz_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movz_f_op)}
aoqi@199 1404 void movn_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movn_f_op)}
aoqi@199 1405 //null
aoqi@199 1406 void recip_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frecip_op)}
aoqi@199 1407 void rsqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frsqrt_op)}
aoqi@199 1408 //null
aoqi@199 1409 void cvt_s_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvts_op)}
aoqi@199 1410 void cvt_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtl_op)}
aoqi@199 1411 //null
aoqi@199 1412 void cvt_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtw_op)}
aoqi@199 1413 //null
aoqi@199 1414 void c_f_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, f_cond)}
aoqi@199 1415 void c_un_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, un_cond)}
aoqi@199 1416 void c_eq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, eq_cond)}
aoqi@199 1417 void c_ueq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ueq_cond)}
aoqi@199 1418 void c_olt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, olt_cond)}
aoqi@199 1419 void c_ult_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ult_cond)}
aoqi@199 1420 void c_ole_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ole_cond)}
aoqi@199 1421 void c_ule_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ule_cond)}
aoqi@199 1422 void c_sf_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, sf_cond)}
aoqi@199 1423 void c_ngle_d(FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngle_cond)}
aoqi@199 1424 void c_seq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, seq_cond)}
aoqi@199 1425 void c_ngl_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngl_cond)}
aoqi@199 1426 void c_lt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, lt_cond)}
aoqi@199 1427 void c_nge_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, nge_cond)}
aoqi@199 1428 void c_le_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, le_cond)}
aoqi@199 1429 void c_ngt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngt_cond)}
aoqi@199 1430
aoqi@199 1431 #undef INSN_DOUBLE
aoqi@199 1432
aoqi@199 1433
aoqi@199 1434 //null
aoqi@199 1435 void cvt_s_w(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(word_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvts_op)); }
aoqi@199 1436 void cvt_d_w(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(word_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtd_op)); }
aoqi@199 1437 //null
aoqi@199 1438 void cvt_s_l(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(long_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvts_op)); }
aoqi@199 1439 void cvt_d_l(FloatRegister fd, FloatRegister fs) { emit_long(insn_F3RO(long_fmt, 0, (int)fs->encoding(), (int)fd->encoding(), fcvtd_op)); }
aoqi@199 1440 //null
aoqi@199 1441
aoqi@199 1442
aoqi@199 1443 //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags.
aoqi@199 1444 #define INSN_PS(r1, r2, r3, op) \
aoqi@199 1445 { emit_long(insn_F3RO(ps_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1446
aoqi@199 1447 void add_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fadd_op)}
aoqi@199 1448 void sub_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fsub_op)}
aoqi@199 1449 void mul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fmul_op)}
aoqi@199 1450 //null
aoqi@199 1451 void abs_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fabs_op)}
aoqi@199 1452 void mov_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fmov_op)}
aoqi@199 1453 void neg_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fneg_op)}
aoqi@199 1454 //null
aoqi@199 1455 //void movf_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movf_ps")}
aoqi@199 1456 //void movt_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movt_ps") }
aoqi@199 1457 void movz_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movz_f_op)}
aoqi@199 1458 void movn_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movn_f_op)}
aoqi@199 1459 //null
aoqi@199 1460 void cvt_s_pu (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvts_op)}
aoqi@199 1461 //null
aoqi@199 1462 void cvt_s_pl (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvtspl_op)}
aoqi@199 1463 //null
aoqi@199 1464 void pll_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpll_op)}
aoqi@199 1465 void plu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fplu_op)}
aoqi@199 1466 void pul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpul_op)}
aoqi@199 1467 void puu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpuu_op)}
aoqi@199 1468 void c_f_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, f_cond)}
aoqi@199 1469 void c_un_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, un_cond)}
aoqi@199 1470 void c_eq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, eq_cond)}
aoqi@199 1471 void c_ueq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ueq_cond)}
aoqi@199 1472 void c_olt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, olt_cond)}
aoqi@199 1473 void c_ult_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ult_cond)}
aoqi@199 1474 void c_ole_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ole_cond)}
aoqi@199 1475 void c_ule_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ule_cond)}
aoqi@199 1476 void c_sf_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, sf_cond)}
aoqi@199 1477 void c_ngle_ps(FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngle_cond)}
aoqi@199 1478 void c_seq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, seq_cond)}
aoqi@199 1479 void c_ngl_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngl_cond)}
aoqi@199 1480 void c_lt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, lt_cond)}
aoqi@199 1481 void c_nge_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, nge_cond)}
aoqi@199 1482 void c_le_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, le_cond)}
aoqi@199 1483 void c_ngt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngt_cond)}
aoqi@199 1484 //null
aoqi@199 1485 #undef INSN_PS
aoqi@199 1486 //COP1 end
aoqi@199 1487
aoqi@199 1488
aoqi@199 1489 //COP1X
aoqi@199 1490 //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags.
aoqi@199 1491 #define INSN_COP1X(r0, r1, r2, r3, op) \
aoqi@199 1492 { emit_long(insn_F3ROX((int)r0->encoding(), (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1493 void madd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_s_op) }
aoqi@199 1494 void madd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_d_op) }
aoqi@199 1495 void madd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, madd_ps_op) }
aoqi@199 1496 void msub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_s_op) }
aoqi@199 1497 void msub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_d_op) }
aoqi@199 1498 void msub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, msub_ps_op) }
aoqi@199 1499 void nmadd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_s_op) }
aoqi@199 1500 void nmadd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_d_op) }
aoqi@199 1501 void nmadd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmadd_ps_op) }
aoqi@199 1502 void nmsub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_s_op) }
aoqi@199 1503 void nmsub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_d_op) }
aoqi@199 1504 void nmsub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmsub_ps_op) }
aoqi@199 1505 #undef INSN_COP1X
aoqi@199 1506 //COP1X end
aoqi@199 1507
aoqi@199 1508 //SPECIAL2
aoqi@199 1509 //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags.
aoqi@199 1510 #define INSN_S2(op) \
aoqi@199 1511 { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | op);}
aoqi@199 1512
aoqi@363 1513 void madd (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | madd_op); }
aoqi@363 1514 void maddu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | maddu_op); }
aoqi@363 1515 void mul (Register rd, Register rs, Register rt) { INSN_S2(mul_op) }
aoqi@363 1516 void gsandn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x03_op) }
aoqi@363 1517 void msub (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msub_op); }
aoqi@363 1518 void msubu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msubu_op); }
aoqi@363 1519 void gsorn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x06_op) }
aoqi@199 1520
aoqi@199 1521 void gsmult (Register rd, Register rs, Register rt) { INSN_S2(gsmult_op) }
aoqi@199 1522 void gsdmult (Register rd, Register rs, Register rt) { INSN_S2(gsdmult_op) }
aoqi@199 1523 void gsmultu (Register rd, Register rs, Register rt) { INSN_S2(gsmultu_op) }
aoqi@199 1524 void gsdmultu(Register rd, Register rs, Register rt) { INSN_S2(gsdmultu_op)}
aoqi@199 1525 void gsdiv (Register rd, Register rs, Register rt) { INSN_S2(gsdiv_op) }
aoqi@199 1526 void gsddiv (Register rd, Register rs, Register rt) { INSN_S2(gsddiv_op) }
aoqi@199 1527 void gsdivu (Register rd, Register rs, Register rt) { INSN_S2(gsdivu_op) }
aoqi@199 1528 void gsddivu (Register rd, Register rs, Register rt) { INSN_S2(gsddivu_op) }
aoqi@199 1529 void gsmod (Register rd, Register rs, Register rt) { INSN_S2(gsmod_op) }
aoqi@199 1530 void gsdmod (Register rd, Register rs, Register rt) { INSN_S2(gsdmod_op) }
aoqi@199 1531 void gsmodu (Register rd, Register rs, Register rt) { INSN_S2(gsmodu_op) }
aoqi@199 1532 void gsdmodu (Register rd, Register rs, Register rt) { INSN_S2(gsdmodu_op) }
aoqi@199 1533 void clz (Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | clz_op); }
aoqi@199 1534 void clo (Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | clo_op); }
aoqi@199 1535 void ctz (Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | 0 << 6| xctx_op); }
aoqi@199 1536 void cto (Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | 1 << 6| xctx_op); }
aoqi@199 1537 void dctz(Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | 2 << 6| xctx_op); }
aoqi@199 1538 void dcto(Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | 3 << 6| xctx_op); }
aoqi@199 1539 void dclz(Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | dclz_op); }
aoqi@199 1540 void dclo(Register rd, Register rs) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rd->encoding() << 16) | ((int)rd->encoding() << 11) | dclo_op); }
aoqi@199 1541
aoqi@199 1542 #undef INSN_S2
aoqi@199 1543
aoqi@199 1544 //SPECIAL3
aoqi@199 1545 /*
aoqi@199 1546 // FIXME
aoqi@199 1547 #define is_0_to_32(a, b) \
aoqi@199 1548 assert (a >= 0, " just a check"); \
aoqi@199 1549 assert (a <= 0, " just a check"); \
aoqi@199 1550 assert (b >= 0, " just a check"); \
aoqi@199 1551 assert (b <= 0, " just a check"); \
aoqi@199 1552 assert (a+b >= 0, " just a check"); \
aoqi@199 1553 assert (a+b <= 0, " just a check");
aoqi@199 1554 */
aoqi@199 1555 #define is_0_to_32(a, b)
aoqi@199 1556
aoqi@199 1557 void ins (Register rt, Register rs, int pos, int size) { is_0_to_32(pos, size); emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (low(pos+size-1, 5) << 11) | (low(pos, 5) << 6) | ins_op); }
aoqi@199 1558 void dinsm(Register rt, Register rs, int pos, int size) { is_0_to_32(pos, size); emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (low(pos+size-33, 5) << 11) | (low(pos, 5) << 6) | dinsm_op); }
aoqi@199 1559 void dinsu(Register rt, Register rs, int pos, int size) { is_0_to_32(pos, size); emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (low(pos+size-33, 5) << 11) | (low(pos-32, 5) << 6) | dinsu_op); }
fujie@294 1560 void dins (Register rt, Register rs, int pos, int size) {
fujie@294 1561 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@294 1562 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@294 1563 guarantee((0 < pos + size) && (pos + size <= 32), "pos + size must be in (0, 32]");
fujie@294 1564
fujie@294 1565 emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (low(pos+size-1, 5) << 11) | (low(pos, 5) << 6) | dins_op);
fujie@294 1566 }
aoqi@199 1567
aoqi@199 1568 void repl_qb (Register rd, int const8) { emit_long((special3_op << 26) | (low(const8, 8) << 16) | ((int)rd->encoding() << 11) | repl_qb_op << 6 | re1_op); }
aoqi@199 1569 void replv_qb(Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_qb_op << 6 | re1_op ); }
aoqi@199 1570 void repl_ph (Register rd, int const10) { emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_ph_op << 6 | re1_op); }
aoqi@199 1571 void replv_ph(Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_ph_op << 6 | re1_op ); }
aoqi@199 1572
aoqi@199 1573 void repl_ob (Register rd, int const8) { emit_long((special3_op << 26) | (low(const8, 8) << 16) | ((int)rd->encoding() << 11) | repl_ob_op << 6 | re2_op); }
aoqi@199 1574 void replv_ob(Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_ob_op << 6 | re2_op ); }
aoqi@199 1575 void repl_qh (Register rd, int const10) { emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_qh_op << 6 | re2_op); }
aoqi@199 1576 void replv_qh(Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_qh_op << 6 | re2_op ); }
aoqi@199 1577 void repl_pw (Register rd, int const10) { emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_pw_op << 6 | re2_op); }
aoqi@199 1578 void replv_pw(Register rd, Register rt) { emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_pw_op << 6 | re2_op ); }
aoqi@199 1579
aoqi@199 1580 void sdc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(sdc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1581 void sdc1(FloatRegister ft, Address dst);
aoqi@199 1582 void swc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(swc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1583 void swc1(FloatRegister ft, Address dst);
aoqi@199 1584
aoqi@199 1585
aoqi@199 1586 void int3();
aoqi@199 1587 static void print_instruction(int);
aoqi@199 1588 int patched_branch(int dest_pos, int inst, int inst_pos);
aoqi@199 1589 int branch_destination(int inst, int pos);
aoqi@199 1590
aoqi@199 1591 /* Godson3 extension */
aoqi@199 1592
aoqi@199 1593 // gssq/gslq/gssqc1/gslqc1: vAddr = sign_extend(offset << 4 ) + GPR[base]. Therefore, the off should be ">> 4".
jiangshaofeng@362 1594 void gslble(Register rt, Register base, Register bound) {
jiangshaofeng@362 1595 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslble_op);
jiangshaofeng@362 1596 }
jiangshaofeng@362 1597
jiangshaofeng@362 1598 void gslbgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1599 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslbgt_op);
jiangshaofeng@362 1600 }
jiangshaofeng@362 1601
jiangshaofeng@362 1602 void gslhle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1603 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhle_op);
jiangshaofeng@362 1604 }
jiangshaofeng@362 1605
jiangshaofeng@362 1606 void gslhgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1607 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhgt_op);
jiangshaofeng@362 1608 }
jiangshaofeng@362 1609
jiangshaofeng@362 1610 void gslwle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1611 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwle_op);
jiangshaofeng@362 1612 }
jiangshaofeng@362 1613
jiangshaofeng@362 1614 void gslwgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1615 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgt_op);
jiangshaofeng@362 1616 }
jiangshaofeng@362 1617
jiangshaofeng@362 1618 void gsldle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1619 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldle_op);
jiangshaofeng@362 1620 }
jiangshaofeng@362 1621
jiangshaofeng@362 1622 void gsldgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1623 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgt_op);
jiangshaofeng@362 1624 }
jiangshaofeng@362 1625
jiangshaofeng@362 1626 void gslwlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1627 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwlec1_op);
jiangshaofeng@362 1628 }
jiangshaofeng@362 1629
jiangshaofeng@362 1630 void gslwgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1631 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgtc1_op);
jiangshaofeng@362 1632 }
jiangshaofeng@362 1633
jiangshaofeng@362 1634 void gsldlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1635 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldlec1_op);
jiangshaofeng@362 1636 }
jiangshaofeng@362 1637
jiangshaofeng@362 1638 void gsldgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1639 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgtc1_op);
jiangshaofeng@362 1640 }
jiangshaofeng@362 1641
lifangyuan@125 1642 void gslq(Register rq, Register rt, Register base, int off) {
lifangyuan@125 1643 off = off >> 4;
lifangyuan@125 1644 assert(is_simm(off, 9),"gslq: off exceeds 9 bits");
lifangyuan@125 1645 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | 0 << 15 | (low(off, 9) << 6) | gslq_op | (int)rq->encoding() );
lifangyuan@125 1646 }
lifangyuan@125 1647
jiangshaofeng@362 1648 void gssble(Register rt, Register base, Register bound) {
jiangshaofeng@362 1649 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssble_op);
jiangshaofeng@362 1650 }
jiangshaofeng@362 1651
jiangshaofeng@362 1652 void gssbgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1653 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssbgt_op);
jiangshaofeng@362 1654 }
jiangshaofeng@362 1655
jiangshaofeng@362 1656 void gsshle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1657 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshle_op);
jiangshaofeng@362 1658 }
jiangshaofeng@362 1659
jiangshaofeng@362 1660 void gsshgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1661 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshgt_op);
jiangshaofeng@362 1662 }
jiangshaofeng@362 1663
jiangshaofeng@362 1664 void gsswle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1665 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswle_op);
jiangshaofeng@362 1666 }
jiangshaofeng@362 1667
jiangshaofeng@362 1668 void gsswgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1669 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgt_op);
jiangshaofeng@362 1670 }
jiangshaofeng@362 1671
jiangshaofeng@362 1672 void gssdle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1673 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdle_op);
jiangshaofeng@362 1674 }
jiangshaofeng@362 1675
jiangshaofeng@362 1676 void gssdgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1677 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgt_op);
jiangshaofeng@362 1678 }
jiangshaofeng@362 1679
jiangshaofeng@362 1680 void gsswlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1681 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswlec1_op);
jiangshaofeng@362 1682 }
jiangshaofeng@362 1683
jiangshaofeng@362 1684 void gsswgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1685 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgtc1_op);
jiangshaofeng@362 1686 }
jiangshaofeng@362 1687
jiangshaofeng@362 1688 void gssdlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1689 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdlec1_op);
jiangshaofeng@362 1690 }
jiangshaofeng@362 1691
jiangshaofeng@362 1692 void gssdgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1693 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgtc1_op);
jiangshaofeng@362 1694 }
jiangshaofeng@362 1695
lifangyuan@125 1696 void gssq(Register rq, Register rt, Register base, int off) {
lifangyuan@125 1697 off = off >> 4;
lifangyuan@125 1698 assert(is_simm(off, 9),"gssq: off exceeds 9 bits");
lifangyuan@125 1699 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | 0 << 15 | (low(off, 9) << 6) | gssq_op | (int)rq->encoding() );
lifangyuan@125 1700 }
lifangyuan@125 1701
aoqi@199 1702 //LDC2 & SDC2
aoqi@199 1703 #define INSN(OPS, OP) \
aoqi@199 1704 assert(is_simm(off, 8), "NAME: off exceeds 8 bits"); \
aoqi@199 1705 assert(UseLoongsonISA, "check LoongISA"); \
aoqi@199 1706 emit_long( (OPS << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | \
aoqi@199 1707 ((int)index->encoding() << 11) | (low(off, 8) << 3) | OP);
fujie@75 1708
aoqi@199 1709 #define INSN_LDC2(NAME, op) \
aoqi@199 1710 void NAME(Register rt, Register base, Register index, int off) { \
aoqi@199 1711 INSN(gs_ldc2_op, op) \
aoqi@199 1712 }
aoqi@1 1713
aoqi@199 1714 #define INSN_LDC2_F(NAME, op) \
aoqi@199 1715 void NAME(FloatRegister rt, Register base, Register index, int off) { \
aoqi@199 1716 INSN(gs_ldc2_op, op) \
aoqi@199 1717 }
aoqi@1 1718
aoqi@199 1719 #define INSN_SDC2(NAME, op) \
aoqi@199 1720 void NAME(Register rt, Register base, Register index, int off) { \
aoqi@199 1721 INSN(gs_sdc2_op, op) \
aoqi@199 1722 }
fujie@67 1723
aoqi@199 1724 #define INSN_SDC2_F(NAME, op) \
aoqi@199 1725 void NAME(FloatRegister rt, Register base, Register index, int off) { \
aoqi@199 1726 INSN(gs_sdc2_op, op) \
aoqi@199 1727 }
fujie@67 1728
aoqi@199 1729 /*
aoqi@199 1730 void gslbx(Register rt, Register base, Register index, int off) {
aoqi@199 1731 assert(is_simm(off, 8), "gslbx: off exceeds 8 bits");
aoqi@199 1732 assert(UseLoongsonISA, "check LoongISA");
aoqi@199 1733 emit_long( (gs_ldc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) |
aoqi@199 1734 ((int)index->encoding() << 11) | (low(off, 8) << 3) | gslbx_op);
aoqi@199 1735 void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op);}
fujie@76 1736
aoqi@199 1737 INSN_LDC2(gslbx, gslbx_op)
aoqi@199 1738 INSN_LDC2(gslhx, gslhx_op)
aoqi@199 1739 INSN_LDC2(gslwx, gslwx_op)
aoqi@199 1740 INSN_LDC2(gsldx, gsldx_op)
aoqi@199 1741 INSN_LDC2_F(gslwxc1, gslwxc1_op)
aoqi@199 1742 INSN_LDC2_F(gsldxc1, gsldxc1_op)
fujie@76 1743
aoqi@199 1744 INSN_SDC2(gssbx, gssbx_op)
aoqi@199 1745 INSN_SDC2(gsshx, gsshx_op)
aoqi@199 1746 INSN_SDC2(gsswx, gsswx_op)
aoqi@199 1747 INSN_SDC2(gssdx, gssdx_op)
aoqi@199 1748 INSN_SDC2_F(gsswxc1, gsswxc1_op)
aoqi@199 1749 INSN_SDC2_F(gssdxc1, gssdxc1_op)
aoqi@199 1750 */
aoqi@199 1751 void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op) }
aoqi@199 1752 void gslhx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslhx_op) }
aoqi@199 1753 void gslwx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwx_op) }
aoqi@199 1754 void gsldx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldx_op) }
aoqi@199 1755 void gslwxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwxc1_op) }
aoqi@199 1756 void gsldxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldxc1_op) }
fujie@65 1757
aoqi@199 1758 void gssbx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssbx_op) }
aoqi@199 1759 void gsshx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsshx_op) }
aoqi@199 1760 void gsswx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswx_op) }
aoqi@199 1761 void gssdx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdx_op) }
aoqi@199 1762 void gsswxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswxc1_op) }
aoqi@199 1763 void gssdxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdxc1_op) }
fujie@65 1764
aoqi@199 1765 #undef INSN
aoqi@199 1766 #undef INSN_LDC2
aoqi@199 1767 #undef INSN_LDC2_F
aoqi@199 1768 #undef INSN_SDC2
aoqi@199 1769 #undef INSN_SDC2_F
fujie@66 1770
fujie@66 1771
aoqi@1 1772 public:
aoqi@199 1773 // Creation
aoqi@199 1774 Assembler(CodeBuffer* code) : AbstractAssembler(code) {
aoqi@1 1775 #ifdef CHECK_DELAY
aoqi@199 1776 delay_state = no_delay;
aoqi@1 1777 #endif
aoqi@199 1778 }
aoqi@1 1779
aoqi@1 1780 // Decoding
aoqi@1 1781 static address locate_operand(address inst, WhichOperand which);
aoqi@1 1782 static address locate_next_instruction(address inst);
aoqi@1 1783 };
aoqi@1 1784
aoqi@1 1785
aoqi@1 1786 // MacroAssembler extends Assembler by frequently used macros.
aoqi@1 1787 //
aoqi@1 1788 // Instructions for which a 'better' code sequence exists depending
aoqi@1 1789 // on arguments should also go in here.
aoqi@1 1790
aoqi@1 1791 class MacroAssembler: public Assembler {
aoqi@1 1792 friend class LIR_Assembler;
aoqi@1 1793 friend class Runtime1; // as_Address()
aoqi@1 1794
aoqi@199 1795 public:
aoqi@199 1796 static intptr_t i[32];
aoqi@199 1797 static float f[32];
aoqi@199 1798 static void print(outputStream *s);
aoqi@1 1799
aoqi@199 1800 static int i_offset(unsigned int k);
aoqi@199 1801 static int f_offset(unsigned int k);
aoqi@199 1802
aoqi@199 1803 static void save_registers(MacroAssembler *masm);
aoqi@199 1804 static void restore_registers(MacroAssembler *masm);
aoqi@1 1805
aoqi@1 1806 protected:
aoqi@1 1807
aoqi@1 1808 Address as_Address(AddressLiteral adr);
aoqi@1 1809 Address as_Address(ArrayAddress adr);
aoqi@1 1810
aoqi@1 1811 // Support for VM calls
aoqi@1 1812 //
aoqi@1 1813 // This is the base routine called by the different versions of call_VM_leaf. The interpreter
aoqi@1 1814 // may customize this version by overriding it for its purposes (e.g., to save/restore
aoqi@1 1815 // additional registers when doing a VM call).
aoqi@1 1816 #ifdef CC_INTERP
aoqi@1 1817 // c++ interpreter never wants to use interp_masm version of call_VM
aoqi@1 1818 #define VIRTUAL
aoqi@1 1819 #else
aoqi@1 1820 #define VIRTUAL virtual
aoqi@1 1821 #endif
aoqi@1 1822
aoqi@1 1823 VIRTUAL void call_VM_leaf_base(
aoqi@1 1824 address entry_point, // the entry point
aoqi@1 1825 int number_of_arguments // the number of arguments to pop after the call
aoqi@1 1826 );
aoqi@1 1827
aoqi@1 1828 // This is the base routine called by the different versions of call_VM. The interpreter
aoqi@1 1829 // may customize this version by overriding it for its purposes (e.g., to save/restore
aoqi@1 1830 // additional registers when doing a VM call).
aoqi@1 1831 //
aoqi@1 1832 // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base
aoqi@1 1833 // returns the register which contains the thread upon return. If a thread register has been
aoqi@1 1834 // specified, the return value will correspond to that register. If no last_java_sp is specified
aoqi@1 1835 // (noreg) than rsp will be used instead.
aoqi@1 1836 VIRTUAL void call_VM_base( // returns the register containing the thread upon return
aoqi@1 1837 Register oop_result, // where an oop-result ends up if any; use noreg otherwise
aoqi@1 1838 Register java_thread, // the thread if computed before ; use noreg otherwise
aoqi@1 1839 Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise
aoqi@1 1840 address entry_point, // the entry point
aoqi@1 1841 int number_of_arguments, // the number of arguments (w/o thread) to pop after the call
aoqi@1 1842 bool check_exceptions // whether to check for pending exceptions after return
aoqi@1 1843 );
aoqi@1 1844
aoqi@1 1845 // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
aoqi@1 1846 // The implementation is only non-empty for the InterpreterMacroAssembler,
aoqi@1 1847 // as only the interpreter handles PopFrame and ForceEarlyReturn requests.
aoqi@1 1848 virtual void check_and_handle_popframe(Register java_thread);
aoqi@1 1849 virtual void check_and_handle_earlyret(Register java_thread);
aoqi@1 1850
aoqi@1 1851 void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);
aoqi@1 1852
aoqi@1 1853 // helpers for FPU flag access
aoqi@1 1854 // tmp is a temporary register, if none is available use noreg
aoqi@1 1855 //void save_rax (Register tmp);
aoqi@1 1856 //void restore_rax(Register tmp);
aoqi@1 1857
aoqi@1 1858 public:
aoqi@1 1859 MacroAssembler(CodeBuffer* code) : Assembler(code) {}
aoqi@1 1860
aoqi@1 1861 // Support for NULL-checks
aoqi@1 1862 //
aoqi@1 1863 // Generates code that causes a NULL OS exception if the content of reg is NULL.
aoqi@1 1864 // If the accessed location is M[reg + offset] and the offset is known, provide the
aoqi@1 1865 // offset. No explicit code generation is needed if the offset is within a certain
aoqi@1 1866 // range (0 <= offset <= page_size).
aoqi@1 1867 // use "teq 83, reg" in mips now, by yjl 6/20/2005
aoqi@1 1868 void null_check(Register reg, int offset = -1);
aoqi@1 1869 static bool needs_explicit_null_check(intptr_t offset);
aoqi@199 1870
aoqi@199 1871 // Required platform-specific helpers for Label::patch_instructions.
aoqi@1 1872 // They _shadow_ the declarations in AbstractAssembler, which are undefined.
aoqi@1 1873 void pd_patch_instruction(address branch, address target);
aoqi@1 1874
aoqi@1 1875 // Alignment
aoqi@1 1876 void align(int modulus);
aoqi@1 1877
aoqi@1 1878 // Misc
aoqi@1 1879 //void fat_nop(); // 5 byte nop
aoqi@1 1880
aoqi@1 1881 // Stack frame creation/removal
aoqi@1 1882 void enter();
aoqi@1 1883 void leave();
aoqi@1 1884
aoqi@1 1885 // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information)
aoqi@1 1886 // The pointer will be loaded into the thread register.
aoqi@1 1887 void get_thread(Register thread);
aoqi@1 1888
aoqi@1 1889
aoqi@1 1890 // Support for VM calls
aoqi@1 1891 //
aoqi@1 1892 // It is imperative that all calls into the VM are handled via the call_VM macros.
aoqi@1 1893 // They make sure that the stack linkage is setup correctly. call_VM's correspond
aoqi@1 1894 // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points.
aoqi@1 1895
aoqi@1 1896
aoqi@1 1897 void call_VM(Register oop_result,
aoqi@1 1898 address entry_point,
aoqi@1 1899 bool check_exceptions = true);
aoqi@1 1900 void call_VM(Register oop_result,
aoqi@1 1901 address entry_point,
aoqi@1 1902 Register arg_1,
aoqi@1 1903 bool check_exceptions = true);
aoqi@1 1904 void call_VM(Register oop_result,
aoqi@1 1905 address entry_point,
aoqi@1 1906 Register arg_1, Register arg_2,
aoqi@1 1907 bool check_exceptions = true);
aoqi@1 1908 void call_VM(Register oop_result,
aoqi@1 1909 address entry_point,
aoqi@1 1910 Register arg_1, Register arg_2, Register arg_3,
aoqi@1 1911 bool check_exceptions = true);
aoqi@1 1912 // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls
aoqi@1 1913 void super_call_VM_leaf(address entry_point);
aoqi@1 1914 void super_call_VM_leaf(address entry_point, Register arg_1);
aoqi@1 1915 void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
aoqi@1 1916 void super_call_VM_leaf(address entry_point,
aoqi@1 1917 Register arg_1, Register arg_2, Register arg_3);
aoqi@1 1918
aoqi@1 1919 // Overloadings with last_Java_sp
aoqi@1 1920 void call_VM(Register oop_result,
aoqi@1 1921 Register last_java_sp,
aoqi@1 1922 address entry_point,
aoqi@1 1923 int number_of_arguments = 0,
aoqi@1 1924 bool check_exceptions = true);
aoqi@1 1925 void call_VM(Register oop_result,
aoqi@1 1926 Register last_java_sp,
aoqi@1 1927 address entry_point,
aoqi@1 1928 Register arg_1, bool
aoqi@1 1929 check_exceptions = true);
aoqi@1 1930 void call_VM(Register oop_result,
aoqi@1 1931 Register last_java_sp,
aoqi@1 1932 address entry_point,
aoqi@1 1933 Register arg_1, Register arg_2,
aoqi@1 1934 bool check_exceptions = true);
aoqi@1 1935 void call_VM(Register oop_result,
aoqi@1 1936 Register last_java_sp,
aoqi@1 1937 address entry_point,
aoqi@1 1938 Register arg_1, Register arg_2, Register arg_3,
aoqi@1 1939 bool check_exceptions = true);
aoqi@1 1940
aoqi@1 1941 void call_VM_leaf(address entry_point,
aoqi@1 1942 int number_of_arguments = 0);
aoqi@1 1943 void call_VM_leaf(address entry_point,
aoqi@1 1944 Register arg_1);
aoqi@1 1945 void call_VM_leaf(address entry_point,
aoqi@1 1946 Register arg_1, Register arg_2);
aoqi@1 1947 void call_VM_leaf(address entry_point,
aoqi@1 1948 Register arg_1, Register arg_2, Register arg_3);
aoqi@1 1949
aoqi@1 1950 // last Java Frame (fills frame anchor)
aoqi@1 1951 void set_last_Java_frame(Register thread,
aoqi@1 1952 Register last_java_sp,
aoqi@1 1953 Register last_java_fp,
aoqi@1 1954 address last_java_pc);
aoqi@1 1955
aoqi@1 1956 // thread in the default location (r15_thread on 64bit)
aoqi@1 1957 void set_last_Java_frame(Register last_java_sp,
aoqi@1 1958 Register last_java_fp,
aoqi@1 1959 address last_java_pc);
aoqi@1 1960
aoqi@1 1961 void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc);
aoqi@1 1962
aoqi@1 1963 // thread in the default location (r15_thread on 64bit)
aoqi@1 1964 void reset_last_Java_frame(bool clear_fp, bool clear_pc);
aoqi@1 1965
aoqi@1 1966 // Stores
aoqi@1 1967 void store_check(Register obj); // store check for obj - register is destroyed afterwards
aoqi@1 1968 void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
aoqi@1 1969
aoqi@1 1970
aoqi@1 1971 void g1_write_barrier_pre(Register obj,
aoqi@1 1972 #ifndef _LP64
aoqi@1 1973 Register thread,
aoqi@1 1974 #endif
aoqi@1 1975 Register tmp,
aoqi@1 1976 Register tmp2,
aoqi@1 1977 bool tosca_live);
aoqi@1 1978 void g1_write_barrier_post(Register store_addr,
aoqi@1 1979 Register new_val,
aoqi@1 1980 #ifndef _LP64
aoqi@1 1981 Register thread,
aoqi@1 1982 #endif
aoqi@1 1983 Register tmp,
aoqi@1 1984 Register tmp2);
aoqi@1 1985
aoqi@1 1986
aoqi@1 1987
aoqi@1 1988 // split store_check(Register obj) to enhance instruction interleaving
aoqi@1 1989 void store_check_part_1(Register obj);
aoqi@1 1990 void store_check_part_2(Register obj);
aoqi@1 1991
aoqi@1 1992 // C 'boolean' to Java boolean: x == 0 ? 0 : 1
aoqi@1 1993 void c2bool(Register x);
aoqi@1 1994 //add for compressedoops
aoqi@1 1995 void load_klass(Register dst, Register src);
aoqi@1 1996 void store_klass(Register dst, Register src);
aoqi@1 1997 void load_prototype_header(Register dst, Register src);
aoqi@1 1998 /*
aoqi@1 1999 // C++ bool manipulation
aoqi@1 2000
aoqi@1 2001 void movbool(Register dst, Address src);
aoqi@1 2002 void movbool(Address dst, bool boolconst);
aoqi@1 2003 void movbool(Address dst, Register src);
aoqi@1 2004 void testbool(Register dst);
aoqi@1 2005
aoqi@1 2006 // oop manipulations
aoqi@1 2007 void load_klass(Register dst, Register src);
aoqi@1 2008 void store_klass(Register dst, Register src);
aoqi@1 2009
aoqi@1 2010 void load_prototype_header(Register dst, Register src);*/
aoqi@1 2011
aoqi@1 2012 #ifdef _LP64
aoqi@1 2013 void store_klass_gap(Register dst, Register src);
aoqi@1 2014
aoqi@1 2015 void load_heap_oop(Register dst, Address src);
aoqi@1 2016 void store_heap_oop(Address dst, Register src);
aoqi@1 2017 void encode_heap_oop(Register r);
fujie@391 2018 void encode_heap_oop(Register dst, Register src);
aoqi@1 2019 void decode_heap_oop(Register r);
fujie@391 2020 void decode_heap_oop(Register dst, Register src);
aoqi@1 2021 void encode_heap_oop_not_null(Register r);
aoqi@1 2022 void decode_heap_oop_not_null(Register r);
aoqi@1 2023 void encode_heap_oop_not_null(Register dst, Register src);
aoqi@1 2024 void decode_heap_oop_not_null(Register dst, Register src);
aoqi@1 2025
aoqi@1 2026 void encode_klass_not_null(Register r);
aoqi@1 2027 void decode_klass_not_null(Register r);
aoqi@1 2028 void encode_klass_not_null(Register dst, Register src);
aoqi@1 2029 void decode_klass_not_null(Register dst, Register src);
aoqi@1 2030
aoqi@1 2031 //void set_narrow_oop(Register dst, jobject obj);
aoqi@1 2032
aoqi@1 2033 // Returns the byte size of the instructions generated by decode_klass_not_null()
aoqi@1 2034 // when compressed klass pointers are being used.
aoqi@1 2035 static int instr_size_for_decode_klass_not_null();
aoqi@1 2036
aoqi@1 2037 // if heap base register is used - reinit it with the correct value
aoqi@1 2038 void reinit_heapbase();
aoqi@1 2039 DEBUG_ONLY(void verify_heapbase(const char* msg);)
aoqi@1 2040
fujie@344 2041 void set_narrow_klass(Register dst, Klass* k);
fujie@344 2042 void set_narrow_oop(Register dst, jobject obj);
fujie@344 2043
aoqi@1 2044 #endif // _LP64
aoqi@1 2045
aoqi@1 2046 void incrementl(Register reg, int value = 1);
aoqi@1 2047
aoqi@1 2048 void decrementl(Register reg, int value = 1);
aoqi@1 2049
aoqi@1 2050 /*
aoqi@1 2051 // Int division/remainder for Java
aoqi@1 2052 // (as idivl, but checks for special case as described in JVM spec.)
aoqi@1 2053 // returns idivl instruction offset for implicit exception handling
aoqi@1 2054 int corrected_idivl(Register reg);
aoqi@1 2055
aoqi@1 2056 // Long division/remainder for Java
aoqi@1 2057 // (as idivq, but checks for special case as described in JVM spec.)
aoqi@1 2058 // returns idivq instruction offset for implicit exception handling
aoqi@1 2059 int corrected_idivq(Register reg);
aoqi@1 2060 */
aoqi@1 2061
aoqi@1 2062 void int3();
aoqi@1 2063 /*
aoqi@1 2064 // Long operation macros for a 32bit cpu
aoqi@1 2065 // Long negation for Java
aoqi@1 2066 void lneg(Register hi, Register lo);
aoqi@1 2067
aoqi@1 2068 // Long multiplication for Java
aoqi@1 2069 // (destroys contents of eax, ebx, ecx and edx)
aoqi@1 2070 void lmul(int x_rsp_offset, int y_rsp_offset); // rdx:rax = x * y
aoqi@1 2071
aoqi@1 2072 // Long shifts for Java
aoqi@1 2073 // (semantics as described in JVM spec.)
aoqi@1 2074 void lshl(Register hi, Register lo); // hi:lo << (rcx & 0x3f)
aoqi@1 2075 void lshr(Register hi, Register lo, bool sign_extension = false); // hi:lo >> (rcx & 0x3f)
aoqi@1 2076
aoqi@1 2077 // Long compare for Java
aoqi@1 2078 // (semantics as described in JVM spec.)
aoqi@1 2079 void lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo); // x_hi = lcmp(x, y)
aoqi@1 2080
aoqi@1 2081
aoqi@1 2082 // misc
aoqi@1 2083 */
aoqi@1 2084 // Sign extension
aoqi@1 2085 #ifdef _LP64
fujie@256 2086 void sign_extend_short(Register reg) { /*dsll32(reg, reg, 16); dsra32(reg, reg, 16);*/ seh(reg, reg); }
fujie@256 2087 void sign_extend_byte(Register reg) { /*dsll32(reg, reg, 24); dsra32(reg, reg, 24);*/ seb(reg, reg); }
aoqi@1 2088 #else
fujie@256 2089 void sign_extend_short(Register reg) { /*sll(reg, reg, 16); sra(reg, reg, 16);*/ seh(reg, reg); }
fujie@256 2090 void sign_extend_byte(Register reg) { /*sll(reg, reg, 24); sra(reg, reg, 24);*/ seb(reg, reg);}
aoqi@1 2091 #endif
aoqi@1 2092 void rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp);
aoqi@199 2093 void rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp);
aoqi@1 2094
aoqi@1 2095 // Inlined sin/cos generator for Java; must not use CPU instruction
aoqi@1 2096 // directly on Intel as it does not have high enough precision
aoqi@1 2097 // outside of the range [-pi/4, pi/4]. Extra argument indicate the
aoqi@1 2098 // number of FPU stack slots in use; all but the topmost will
aoqi@1 2099 // require saving if a slow case is necessary. Assumes argument is
aoqi@1 2100 // on FP TOS; result is on FP TOS. No cpu registers are changed by
aoqi@1 2101 // this code.
aoqi@1 2102 void trigfunc(char trig, int num_fpu_regs_in_use = 1);
aoqi@1 2103 /*
aoqi@1 2104 // branch to L if FPU flag C2 is set/not set
aoqi@1 2105 // tmp is a temporary register, if none is available use noreg
aoqi@1 2106 void jC2 (Register tmp, Label& L);
aoqi@1 2107 void jnC2(Register tmp, Label& L);
aoqi@1 2108
aoqi@1 2109 // Pop ST (ffree & fincstp combined)
aoqi@1 2110 void fpop();
aoqi@1 2111
aoqi@1 2112 // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack
aoqi@1 2113 void push_fTOS();
aoqi@1 2114
aoqi@1 2115 // pops double TOS element from CPU stack and pushes on FPU stack
aoqi@1 2116 void pop_fTOS();
aoqi@1 2117
aoqi@1 2118 void empty_FPU_stack();
aoqi@1 2119
aoqi@1 2120 void push_IU_state();
aoqi@1 2121 void pop_IU_state();
aoqi@1 2122
aoqi@1 2123 void push_FPU_state();
aoqi@1 2124 void pop_FPU_state();
aoqi@1 2125
aoqi@1 2126 void push_CPU_state();
aoqi@1 2127 void pop_CPU_state();
aoqi@1 2128
aoqi@1 2129 // Round up to a power of two
aoqi@1 2130 void round_to(Register reg, int modulus);
aoqi@1 2131
aoqi@1 2132 // Callee saved registers handling
aoqi@1 2133 void push_callee_saved_registers();
aoqi@1 2134 void pop_callee_saved_registers();
aoqi@1 2135 */
aoqi@1 2136 // allocation
aoqi@1 2137 void eden_allocate(
aoqi@1 2138 Register obj, // result: pointer to object after successful allocation
aoqi@1 2139 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
aoqi@1 2140 int con_size_in_bytes, // object size in bytes if known at compile time
aoqi@1 2141 Register t1, // temp register
aoqi@1 2142 Register t2,
aoqi@1 2143 Label& slow_case // continuation point if fast allocation fails
aoqi@1 2144 );
aoqi@1 2145 void tlab_allocate(
aoqi@1 2146 Register obj, // result: pointer to object after successful allocation
aoqi@1 2147 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
aoqi@1 2148 int con_size_in_bytes, // object size in bytes if known at compile time
aoqi@1 2149 Register t1, // temp register
aoqi@1 2150 Register t2, // temp register
aoqi@1 2151 Label& slow_case // continuation point if fast allocation fails
aoqi@1 2152 );
aoqi@1 2153 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
aoqi@1 2154
aoqi@1 2155 // void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
aoqi@1 2156
aoqi@1 2157
aoqi@1 2158 // Debugging
aoqi@1 2159
aoqi@1 2160 // only if +VerifyOops
aoqi@1 2161 void verify_oop(Register reg, const char* s = "broken oop");
aoqi@1 2162 void verify_oop_addr(Address addr, const char * s = "broken oop addr");
aoqi@1 2163 void verify_oop_subroutine();
aoqi@1 2164 // TODO: verify method and klass metadata (compare against vptr?)
aoqi@1 2165 void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {}
aoqi@1 2166 void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){}
aoqi@199 2167
aoqi@1 2168 #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__)
aoqi@1 2169 #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__)
aoqi@199 2170
aoqi@1 2171 // only if +VerifyFPU
aoqi@1 2172 void verify_FPU(int stack_depth, const char* s = "illegal FPU state");
aoqi@1 2173
aoqi@1 2174 // prints msg, dumps registers and stops execution
aoqi@1 2175 void stop(const char* msg);
aoqi@1 2176
aoqi@1 2177 // prints msg and continues
aoqi@1 2178 void warn(const char* msg);
aoqi@1 2179
aoqi@1 2180 static void debug(char* msg/*, RegistersForDebugging* regs*/);
aoqi@1 2181 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 2182 static void debug64(char* msg, int64_t pc, int64_t regs[]);
aoqi@1 2183
aoqi@1 2184 void print_reg(Register reg);
aoqi@1 2185 void print_reg(FloatRegister reg);
aoqi@1 2186 //void os_breakpoint();
aoqi@1 2187
aoqi@1 2188 void untested() { stop("untested"); }
aoqi@1 2189
aoqi@1 2190 void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, sizeof(b), "unimplemented: %s", what); stop(b); }
aoqi@1 2191
aoqi@1 2192 void should_not_reach_here() { stop("should not reach here"); }
aoqi@1 2193
aoqi@1 2194 void print_CPU_state();
aoqi@1 2195
aoqi@1 2196 // Stack overflow checking
aoqi@1 2197 void bang_stack_with_offset(int offset) {
aoqi@1 2198 // stack grows down, caller passes positive offset
aoqi@1 2199 assert(offset > 0, "must bang with negative offset");
aoqi@1 2200 if (offset <= 32768) {
aoqi@1 2201 sw(A0, SP, -offset);
aoqi@1 2202 } else {
aoqi@1 2203 #ifdef _LP64
aoqi@1 2204 li(AT, offset);
aoqi@1 2205 dsub(AT, SP, AT);
aoqi@1 2206 #else
aoqi@1 2207 move(AT, offset);
aoqi@1 2208 sub(AT, SP, AT);
aoqi@1 2209 #endif
aoqi@1 2210 sw(A0, AT, 0);
aoqi@1 2211 }
aoqi@1 2212 }
aoqi@1 2213
aoqi@199 2214 // Writes to stack successive pages until offset reached to check for
aoqi@199 2215 // stack overflow + shadow pages. Also, clobbers tmp
aoqi@199 2216 void bang_stack_size(Register size, Register tmp);
aoqi@199 2217 virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
aoqi@1 2218 Register tmp,
aoqi@1 2219 int offset);
aoqi@1 2220
aoqi@199 2221 // Support for serializing memory accesses between threads
aoqi@199 2222 void serialize_memory(Register thread, Register tmp);
aoqi@1 2223
aoqi@199 2224 //void verify_tlab();
aoqi@199 2225 void verify_tlab(Register t1, Register t2);
aoqi@1 2226
aoqi@199 2227 // Biased locking support
aoqi@199 2228 // lock_reg and obj_reg must be loaded up with the appropriate values.
aoqi@199 2229 // swap_reg must be rax, and is killed.
aoqi@199 2230 // tmp_reg is optional. If it is supplied (i.e., != noreg) it will
aoqi@199 2231 // be killed; if not supplied, push/pop will be used internally to
aoqi@199 2232 // allocate a temporary (inefficient, avoid if possible).
aoqi@199 2233 // Optional slow case is for implementations (interpreter and C1) which branch to
aoqi@199 2234 // slow case directly. Leaves condition codes set for C2's Fast_Lock node.
aoqi@199 2235 // Returns offset of first potentially-faulting instruction for null
aoqi@199 2236 // check info (currently consumed only by C1). If
aoqi@199 2237 // swap_reg_contains_mark is true then returns -1 as it is assumed
aoqi@199 2238 // the calling code has already passed any potential faults.
aoqi@199 2239 int biased_locking_enter(Register lock_reg, Register obj_reg,
aoqi@199 2240 Register swap_reg, Register tmp_reg,
aoqi@199 2241 bool swap_reg_contains_mark,
aoqi@199 2242 Label& done, Label* slow_case = NULL,
aoqi@199 2243 BiasedLockingCounters* counters = NULL);
aoqi@199 2244 void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done);
aoqi@1 2245
aoqi@1 2246
aoqi@1 2247 // Calls
aoqi@1 2248
aoqi@199 2249 void call(address entry);
aoqi@199 2250 void call(address entry, relocInfo::relocType rtype);
aoqi@199 2251 void call(address entry, RelocationHolder& rh);
aoqi@199 2252 // Emit the CompiledIC call idiom
aoqi@199 2253 void ic_call(address entry);
aoqi@1 2254
aoqi@199 2255 void jmp(address entry);
aoqi@199 2256 void jmp(address entry, relocInfo::relocType rtype);
aoqi@1 2257
aoqi@199 2258 // Argument ops
aoqi@199 2259 /*inline void store_int_argument(Register s, Argument& a);
aoqi@199 2260 inline void store_long_argument(Register s, Argument& a);
aoqi@199 2261 inline void store_float_argument(FloatRegister s, Argument& a);
aoqi@199 2262 inline void store_double_argument(FloatRegister s, Argument& a);
aoqi@199 2263 inline void store_ptr_argument(Register s, Argument& a);*/
aoqi@199 2264 inline void store_int_argument(Register s, Argument &a) {
aoqi@199 2265 if(a.is_Register()) {
aoqi@199 2266 move(a.as_Register(), s);
aoqi@199 2267 } else {
aoqi@199 2268 sw(s, a.as_caller_address());
aoqi@199 2269 }
aoqi@199 2270 }
aoqi@1 2271
aoqi@199 2272 inline void store_long_argument(Register s, Argument &a) {
aoqi@199 2273 Argument a1 = a.successor();
aoqi@199 2274 if(a.is_Register() && a1.is_Register()) {
aoqi@199 2275 move(a.as_Register(), s);
aoqi@199 2276 move(a.as_Register(), s);
aoqi@199 2277 } else {
aoqi@199 2278 sd(s, a.as_caller_address());
aoqi@199 2279 }
aoqi@199 2280 }
aoqi@1 2281
aoqi@199 2282 inline void store_float_argument(FloatRegister s, Argument &a) {
aoqi@199 2283 if(a.is_Register()) {
aoqi@199 2284 mov_s(a.as_FloatRegister(), s);
aoqi@199 2285 } else {
aoqi@199 2286 swc1(s, a.as_caller_address());
aoqi@199 2287 }
aoqi@199 2288 }
aoqi@199 2289 inline void store_double_argument(FloatRegister s, Argument &a) {
aoqi@199 2290 if(a.is_Register()) {
aoqi@199 2291 mov_d(a.as_FloatRegister(), s);
aoqi@199 2292 } else {
aoqi@199 2293 sdc1(s, a.as_caller_address());
aoqi@199 2294 }
aoqi@199 2295 }
aoqi@1 2296
aoqi@199 2297 inline void store_ptr_argument(Register s, Argument &a) {
aoqi@199 2298 if(a.is_Register()) {
aoqi@199 2299 move(a.as_Register(), s);
aoqi@199 2300 } else {
aoqi@199 2301 st_ptr(s, a.as_caller_address());
aoqi@199 2302 }
aoqi@1 2303 }
aoqi@1 2304
aoqi@1 2305 // Load and store values by size and signed-ness
aoqi@1 2306 void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg);
aoqi@1 2307 void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg);
aoqi@1 2308
aoqi@1 2309 // interface method calling
aoqi@1 2310 void lookup_interface_method(Register recv_klass,
aoqi@1 2311 Register intf_klass,
aoqi@1 2312 RegisterOrConstant itable_index,
aoqi@1 2313 Register method_result,
aoqi@1 2314 Register scan_temp,
aoqi@1 2315 Label& no_such_interface);
aoqi@1 2316 // virtual method calling
aoqi@1 2317 void lookup_virtual_method(Register recv_klass,
aoqi@1 2318 RegisterOrConstant vtable_index,
aoqi@1 2319 Register method_result);
aoqi@1 2320
aoqi@199 2321 // ld_ptr will perform lw for 32 bit VMs and ld for 64 bit VMs
aoqi@199 2322 // st_ptr will perform sw for 32 bit VMs and sd for 64 bit VMs
aoqi@199 2323 inline void ld_ptr(Register rt, Address a){
aoqi@199 2324 #ifdef _LP64
aoqi@199 2325 ld(rt, a.base(), a.disp());
aoqi@199 2326 #else
aoqi@199 2327 lw(rt, a.base(), a.disp());
aoqi@199 2328 #endif
aoqi@199 2329 }
aoqi@199 2330 inline void ld_ptr(Register rt, Register base, int offset16){
aoqi@199 2331 #ifdef _LP64
aoqi@199 2332 ld(rt, base, offset16);
aoqi@199 2333 #else
aoqi@199 2334 lw(rt, base, offset16);
aoqi@199 2335 #endif
aoqi@1 2336
aoqi@199 2337 }
aoqi@199 2338 inline void st_ptr(Register rt, Address a){
aoqi@199 2339 #ifdef _LP64
aoqi@199 2340 sd(rt, a.base(), a.disp());
aoqi@199 2341 #else
aoqi@199 2342 sw(rt, a.base(), a.disp());
aoqi@199 2343 #endif
aoqi@199 2344 }
aoqi@199 2345 inline void st_ptr(Register rt, Register base, int offset16) {
aoqi@199 2346 #ifdef _LP64
aoqi@199 2347 sd(rt, base, offset16);
aoqi@199 2348 #else
aoqi@199 2349 sw(rt, base, offset16);
aoqi@199 2350 #endif
aoqi@1 2351
aoqi@199 2352 }
aoqi@1 2353
aoqi@199 2354 void ld_ptr(Register rt, Register offset, Register base);
aoqi@199 2355 void st_ptr(Register rt, Register offset, Register base);
aoqi@1 2356
aoqi@199 2357 // ld_long will perform lw for 32 bit VMs and ld for 64 bit VMs
aoqi@199 2358 // st_long will perform sw for 32 bit VMs and sd for 64 bit VMs
aoqi@199 2359 inline void ld_long(Register rt, Register base, int offset16);
aoqi@199 2360 inline void st_long(Register rt, Register base, int offset16);
aoqi@199 2361 inline void ld_long(Register rt, Address a);
aoqi@199 2362 inline void st_long(Register rt, Address a);
aoqi@1 2363
aoqi@1 2364
aoqi@199 2365 void ld_long(Register rt, Register offset, Register base);
aoqi@199 2366 void st_long(Register rt, Register offset, Register base);
aoqi@199 2367 // Regular vs. d* versions
aoqi@199 2368 inline void addu_long(Register rd, Register rs, Register rt) {
aoqi@199 2369 #ifdef _LP64
aoqi@199 2370 daddu(rd, rs, rt);
aoqi@199 2371 #else
aoqi@199 2372 addu(rd, rs, rt);
aoqi@199 2373 #endif
aoqi@199 2374 }
aoqi@199 2375 inline void addu_long(Register rd, Register rs, long imm32_64) {
aoqi@199 2376 #ifdef _LP64
aoqi@199 2377 daddiu(rd, rs, imm32_64);
aoqi@199 2378 #else
aoqi@199 2379 addiu(rd, rs, imm32_64);
aoqi@199 2380 #endif
aoqi@1 2381
aoqi@199 2382 }
aoqi@1 2383
aoqi@199 2384 // Floating
aoqi@1 2385 public:
aoqi@199 2386 // swap the two byte of the low 16-bit halfword
aoqi@199 2387 // this directive will use AT, be sure the high 16-bit of reg is zero
aoqi@199 2388 // by yjl 6/28/2005
aoqi@199 2389 void hswap(Register reg);
aoqi@199 2390 void huswap(Register reg);
aoqi@1 2391
aoqi@199 2392 // convert big endian integer to little endian integer
aoqi@1 2393 // by yjl 6/29/2005
aoqi@199 2394 void swap(Register reg);
aoqi@199 2395
aoqi@1 2396 // implement the x86 instruction semantic
aoqi@1 2397 // if c_reg == *dest then *dest <= x_reg
aoqi@199 2398 // else c_reg <= *dest
aoqi@199 2399 // the AT indicate if xchg occurred, 1 for xchged, else 0
aoqi@199 2400 // by yjl 6/28/2005
aoqi@199 2401 void cmpxchg(Register x_reg, Address dest, Register c_reg);
aoqi@1 2402 #ifdef _LP64
aoqi@199 2403 void cmpxchg32(Register x_reg, Address dest, Register c_reg);
aoqi@1 2404 #endif
aoqi@199 2405 void cmpxchg8(Register x_regLo, Register x_regHi, Address dest, Register c_regLo, Register c_regHi);
aoqi@1 2406
aoqi@1 2407
aoqi@1 2408
aoqi@199 2409 void round_to(Register reg, int modulus) {
aoqi@199 2410 assert_different_registers(reg, AT);
aoqi@199 2411 increment(reg, modulus - 1);
aoqi@199 2412 move(AT, - modulus);
aoqi@199 2413 andr(reg, reg, AT);
aoqi@199 2414 }
aoqi@199 2415
aoqi@199 2416 //pop & push, added by aoqi
aoqi@1 2417 #ifdef _LP64
aoqi@199 2418 void extend_sign(Register rh, Register rl) { stop("extend_sign"); }
aoqi@199 2419 void neg(Register reg) { dsubu(reg, R0, reg); }
aoqi@199 2420 void push (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); }
aoqi@199 2421 void push (FloatRegister reg) { sdc1(reg, SP, -8); daddi(SP, SP, -8); }
aoqi@199 2422 void pop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); }
aoqi@199 2423 void pop (FloatRegister reg) { ldc1(reg, SP, 0); daddi(SP, SP, 8); }
aoqi@199 2424 void pop () { daddi(SP, SP, 8); }
aoqi@199 2425 void pop2 () { daddi(SP, SP, 16); }
aoqi@1 2426 #else
aoqi@199 2427 void extend_sign(Register rh, Register rl) { sra(rh, rl, 31); }
aoqi@199 2428 void neg(Register reg) { subu(reg, R0, reg); }
aoqi@199 2429 void push (Register reg) { sw (reg, SP, -4); addi(SP, SP, -4); }
aoqi@199 2430 void push (FloatRegister reg) { swc1(reg, SP, -4); addi(SP, SP, -4); }
aoqi@199 2431 void pop (Register reg) { lw (reg, SP, 0); addi(SP, SP, 4); }
aoqi@199 2432 void pop (FloatRegister reg) { lwc1(reg, SP, 0); addi(SP, SP, 4); }
aoqi@199 2433 void pop () { addi(SP, SP, 4); }
aoqi@199 2434 void pop2 () { addi(SP, SP, 8); }
aoqi@1 2435 #endif
aoqi@199 2436 void push2(Register reg1, Register reg2);
aoqi@199 2437 void pop2 (Register reg1, Register reg2);
aoqi@199 2438 void dpush (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); }
aoqi@199 2439 void dpop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); }
aoqi@1 2440
aoqi@199 2441 /* branches may exceed 16-bit offset */
aoqi@199 2442 void b_far(address entry);
aoqi@199 2443 void b_far(Label& L);
aoqi@1 2444
aoqi@199 2445 void bne_far (Register rs, Register rt, address entry);
aoqi@199 2446 void bne_far (Register rs, Register rt, Label& L);
aoqi@1 2447
aoqi@199 2448 void beq_far (Register rs, Register rt, address entry);
aoqi@199 2449 void beq_far (Register rs, Register rt, Label& L);
aoqi@199 2450
aoqi@199 2451 //move an 32-bit immediate to Register
aoqi@199 2452 void move(Register reg, int imm32) { li32(reg, imm32); }
aoqi@199 2453 void li (Register rd, long imm);
aoqi@199 2454 void li (Register rd, address addr) { li(rd, (long)addr); }
aoqi@199 2455 //replace move(Register reg, int imm)
aoqi@199 2456 void li32(Register rd, int imm32); // sign-extends to 64 bits on mips64
aoqi@1 2457 #ifdef _LP64
fujie@283 2458 void set64(Register d, jlong value);
fujie@284 2459 static int insts_for_set64(jlong value);
fujie@283 2460
fujie@340 2461 void patchable_set48(Register d, jlong value);
fujie@340 2462 void patchable_set32(Register d, jlong value);
fujie@340 2463
fujie@373 2464 void patchable_call32(Register d, jlong value);
fujie@373 2465
fujie@381 2466 static int call_size(address target, bool far, bool patchable);
fujie@381 2467
fujie@381 2468 static bool reachable_from_cache(address target);
fujie@381 2469
fujie@381 2470 void patchable_call(address target);
fujie@381 2471 void general_call(address target);
fujie@381 2472
fujie@381 2473 void patchable_jump(address target);
fujie@381 2474 void general_jump(address target);
fujie@378 2475
aoqi@199 2476 void dli(Register rd, long imm) { li(rd, imm); }
aoqi@199 2477 void li64(Register rd, long imm);
aoqi@199 2478 void li48(Register rd, long imm);
aoqi@1 2479 #endif
aoqi@1 2480
aoqi@1 2481 #ifdef _LP64
aoqi@199 2482 void move(Register rd, Register rs) { dadd(rd, rs, R0); }
aoqi@199 2483 void move_u32(Register rd, Register rs) { addu32(rd, rs, R0); }
aoqi@1 2484 #else
aoqi@199 2485 void move(Register rd, Register rs) { add(rd, rs, R0); }
aoqi@1 2486 #endif
aoqi@199 2487 void dmove(Register rd, Register rs) { dadd(rd, rs, R0); }
aoqi@1 2488
aoqi@1 2489 #ifdef _LP64
aoqi@199 2490 void shl(Register reg, int sa) { dsll(reg, reg, sa); }
aoqi@199 2491 void shr(Register reg, int sa) { dsrl(reg, reg, sa); }
aoqi@199 2492 void sar(Register reg, int sa) { dsra(reg, reg, sa); }
aoqi@1 2493 #else
aoqi@199 2494 void shl(Register reg, int sa) { sll(reg, reg, sa); }
aoqi@199 2495 void shr(Register reg, int sa) { srl(reg, reg, sa); }
aoqi@199 2496 void sar(Register reg, int sa) { sra(reg, reg, sa); }
aoqi@1 2497 #endif
aoqi@1 2498
aoqi@1 2499 #ifndef PRODUCT
aoqi@1 2500 static void pd_print_patched_instruction(address branch) {
aoqi@199 2501 jint stub_inst = *(jint*) branch;
aoqi@199 2502 print_instruction(stub_inst);
aoqi@199 2503 ::tty->print("%s", " (unresolved)");
aoqi@1 2504
aoqi@1 2505 }
aoqi@1 2506 #endif
aoqi@1 2507
aoqi@199 2508 // the follow two might use AT register, be sure you have no meanful data in AT before you call them
aoqi@199 2509 void increment(Register reg, int imm);
aoqi@199 2510 void decrement(Register reg, int imm);
aoqi@1 2511
aoqi@199 2512 //FIXME
aoqi@199 2513 void empty_FPU_stack(){/*need implemented*/};
aoqi@1 2514
aoqi@199 2515 //we need 2 fun to save and resotre general register
aoqi@199 2516 void pushad();
aoqi@199 2517 void popad();
aoqi@1 2518
aoqi@1 2519 // Test sub_klass against super_klass, with fast and slow paths.
aoqi@1 2520
aoqi@1 2521 // The fast path produces a tri-state answer: yes / no / maybe-slow.
aoqi@1 2522 // One of the three labels can be NULL, meaning take the fall-through.
aoqi@1 2523 // If super_check_offset is -1, the value is loaded up from super_klass.
aoqi@1 2524 // No registers are killed, except temp_reg.
aoqi@1 2525 void check_klass_subtype_fast_path(Register sub_klass,
aoqi@1 2526 Register super_klass,
aoqi@1 2527 Register temp_reg,
aoqi@1 2528 Label* L_success,
aoqi@1 2529 Label* L_failure,
aoqi@1 2530 Label* L_slow_path,
aoqi@1 2531 RegisterOrConstant super_check_offset = RegisterOrConstant(-1));
aoqi@1 2532
aoqi@1 2533 // The rest of the type check; must be wired to a corresponding fast path.
aoqi@1 2534 // It does not repeat the fast path logic, so don't use it standalone.
aoqi@1 2535 // The temp_reg and temp2_reg can be noreg, if no temps are available.
aoqi@1 2536 // Updates the sub's secondary super cache as necessary.
aoqi@1 2537 // If set_cond_codes, condition codes will be Z on success, NZ on failure.
aoqi@1 2538 void check_klass_subtype_slow_path(Register sub_klass,
aoqi@1 2539 Register super_klass,
aoqi@1 2540 Register temp_reg,
aoqi@1 2541 Register temp2_reg,
aoqi@1 2542 Label* L_success,
aoqi@1 2543 Label* L_failure,
aoqi@1 2544 bool set_cond_codes = false);
aoqi@1 2545
aoqi@1 2546 // Simplified, combined version, good for typical uses.
aoqi@1 2547 // Falls through on failure.
aoqi@1 2548 void check_klass_subtype(Register sub_klass,
aoqi@1 2549 Register super_klass,
aoqi@1 2550 Register temp_reg,
aoqi@1 2551 Label& L_success);
aoqi@1 2552
aoqi@1 2553 // method handles (JSR 292)
aoqi@1 2554 Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
aoqi@1 2555
aoqi@1 2556 void get_vm_result (Register oop_result, Register thread);
aoqi@1 2557 void get_vm_result_2(Register metadata_result, Register thread);
aoqi@1 2558 #undef VIRTUAL
aoqi@29 2559 void atomic_inc32(address counter_addr, int inc, Register tmp_reg1, Register tmp_reg2);
aoqi@1 2560
aoqi@30 2561 void fast_lock(Register obj, Register box, Register tmp, Register scr);
aoqi@30 2562 void fast_unlock(Register obj, Register box, Register tmp);
aoqi@1 2563 };
aoqi@1 2564
aoqi@1 2565 /**
aoqi@1 2566 * class SkipIfEqual:
aoqi@1 2567 *
aoqi@1 2568 * Instantiating this class will result in assembly code being output that will
aoqi@1 2569 * jump around any code emitted between the creation of the instance and it's
aoqi@1 2570 * automatic destruction at the end of a scope block, depending on the value of
aoqi@1 2571 * the flag passed to the constructor, which will be checked at run-time.
aoqi@1 2572 */
aoqi@1 2573 class SkipIfEqual {
aoqi@1 2574 private:
aoqi@1 2575 MacroAssembler* _masm;
aoqi@1 2576 Label _label;
aoqi@1 2577
aoqi@1 2578 public:
aoqi@1 2579 SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value);
aoqi@1 2580 ~SkipIfEqual();
aoqi@1 2581 };
aoqi@1 2582
aoqi@1 2583 #ifdef ASSERT
aoqi@1 2584 inline bool AbstractAssembler::pd_check_instruction_mark() { return true; }
aoqi@1 2585 #endif
aoqi@1 2586
aoqi@1 2587 #endif // CPU_MIPS_VM_ASSEMBLER_MIPS_HPP

mercurial