src/cpu/mips/vm/assembler_mips.hpp

Wed, 04 Dec 2019 18:01:06 +0800

author
jiefu
date
Wed, 04 Dec 2019 18:01:06 +0800
changeset 9761
17884ee5d053
parent 9759
8c71022cf5f3
child 9932
86ea9a02a717
permissions
-rw-r--r--

#10637: java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java fails with -XX:ReservedCodeCacheSize=256m
Reviewed-by: aoqi

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@9459 3 * Copyright (c) 2015, 2019, 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 public:
aoqi@1 41 enum ScaleFactor {
aoqi@1 42 no_scale = -1,
aoqi@1 43 times_1 = 0,
aoqi@1 44 times_2 = 1,
aoqi@1 45 times_4 = 2,
aoqi@1 46 times_8 = 3,
aoqi@1 47 times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4)
aoqi@1 48 };
aoqi@1 49 static ScaleFactor times(int size) {
aoqi@1 50 assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size");
aoqi@1 51 if (size == 8) return times_8;
aoqi@1 52 if (size == 4) return times_4;
aoqi@1 53 if (size == 2) return times_2;
aoqi@1 54 return times_1;
aoqi@1 55 }
aoqi@1 56
aoqi@1 57 private:
aoqi@1 58 Register _base;
aoqi@1 59 Register _index;
aoqi@1 60 ScaleFactor _scale;
aoqi@1 61 int _disp;
aoqi@1 62 RelocationHolder _rspec;
aoqi@1 63
aoqi@1 64 // Easily misused constructors make them private
aoqi@1 65 Address(address loc, RelocationHolder spec);
aoqi@1 66 Address(int disp, address loc, relocInfo::relocType rtype);
aoqi@1 67 Address(int disp, address loc, RelocationHolder spec);
aoqi@1 68
aoqi@1 69 public:
aoqi@1 70
aoqi@1 71 // creation
aoqi@1 72 Address()
aoqi@1 73 : _base(noreg),
aoqi@1 74 _index(noreg),
aoqi@1 75 _scale(no_scale),
aoqi@1 76 _disp(0) {
aoqi@1 77 }
aoqi@1 78
aoqi@1 79 // No default displacement otherwise Register can be implicitly
aoqi@1 80 // converted to 0(Register) which is quite a different animal.
aoqi@1 81
fujie@9264 82 Address(Register base, int disp = 0)
aoqi@1 83 : _base(base),
aoqi@1 84 _index(noreg),
aoqi@1 85 _scale(no_scale),
aoqi@1 86 _disp(disp) {
fujie@9264 87 assert_different_registers(_base, AT);
aoqi@1 88 }
aoqi@1 89
aoqi@1 90 Address(Register base, Register index, ScaleFactor scale, int disp = 0)
aoqi@1 91 : _base (base),
aoqi@1 92 _index(index),
aoqi@1 93 _scale(scale),
aoqi@1 94 _disp (disp) {
fujie@9264 95 assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address");
fujie@9264 96 assert_different_registers(_base, _index, AT);
aoqi@1 97 }
aoqi@1 98
aoqi@1 99 // The following two overloads are used in connection with the
aoqi@1 100 // ByteSize type (see sizes.hpp). They simplify the use of
aoqi@1 101 // ByteSize'd arguments in assembly code. Note that their equivalent
aoqi@1 102 // for the optimized build are the member functions with int disp
aoqi@1 103 // argument since ByteSize is mapped to an int type in that case.
aoqi@1 104 //
aoqi@1 105 // Note: DO NOT introduce similar overloaded functions for WordSize
aoqi@1 106 // arguments as in the optimized mode, both ByteSize and WordSize
aoqi@1 107 // are mapped to the same type and thus the compiler cannot make a
aoqi@1 108 // distinction anymore (=> compiler errors).
aoqi@1 109
aoqi@1 110 #ifdef ASSERT
aoqi@1 111 Address(Register base, ByteSize disp)
aoqi@1 112 : _base(base),
aoqi@1 113 _index(noreg),
aoqi@1 114 _scale(no_scale),
aoqi@1 115 _disp(in_bytes(disp)) {
fujie@9264 116 assert_different_registers(_base, AT);
aoqi@1 117 }
aoqi@1 118
aoqi@1 119 Address(Register base, Register index, ScaleFactor scale, ByteSize disp)
aoqi@1 120 : _base(base),
aoqi@1 121 _index(index),
aoqi@1 122 _scale(scale),
aoqi@1 123 _disp(in_bytes(disp)) {
fujie@9264 124 assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address");
fujie@9264 125 assert_different_registers(_base, _index, AT);
aoqi@1 126 }
aoqi@1 127 #endif // ASSERT
aoqi@1 128
aoqi@1 129 // accessors
aoqi@1 130 bool uses(Register reg) const { return _base == reg || _index == reg; }
aoqi@1 131 Register base() const { return _base; }
aoqi@1 132 Register index() const { return _index; }
aoqi@1 133 ScaleFactor scale() const { return _scale; }
aoqi@1 134 int disp() const { return _disp; }
aoqi@1 135
aoqi@1 136 static Address make_array(ArrayAddress);
aoqi@1 137
aoqi@1 138 friend class Assembler;
aoqi@1 139 friend class MacroAssembler;
aoqi@1 140 friend class LIR_Assembler; // base/index/scale/disp
aoqi@1 141 };
aoqi@1 142
aoqi@1 143
aoqi@1 144 // Calling convention
aoqi@1 145 class Argument VALUE_OBJ_CLASS_SPEC {
aoqi@1 146 private:
aoqi@199 147 int _number;
aoqi@1 148 public:
aoqi@199 149 enum {
aoqi@1 150 #ifdef _LP64
aoqi@199 151 n_register_parameters = 8, // 8 integer registers used to pass parameters
huangjia@9759 152 n_float_register_parameters = 8 // 8 float registers used to pass parameters
aoqi@1 153 #else
aoqi@199 154 n_register_parameters = 4, // 4 integer registers used to pass parameters
aoqi@199 155 n_float_register_parameters = 4 // 4 float registers used to pass parameters
aoqi@1 156 #endif
aoqi@199 157 };
aoqi@1 158
aoqi@199 159 Argument(int number):_number(number){ }
aoqi@199 160 Argument successor() {return Argument(number() + 1);}
aoqi@1 161
aoqi@199 162 int number()const {return _number;}
aoqi@199 163 bool is_Register()const {return _number < n_register_parameters;}
aoqi@199 164 bool is_FloatRegister()const {return _number < n_float_register_parameters;}
aoqi@199 165
aoqi@199 166 Register as_Register()const {
aoqi@199 167 assert(is_Register(), "must be a register argument");
aoqi@199 168 return ::as_Register(A0->encoding() + _number);
aoqi@199 169 }
aoqi@199 170 FloatRegister as_FloatRegister()const {
aoqi@199 171 assert(is_FloatRegister(), "must be a float register argument");
aoqi@199 172 return ::as_FloatRegister(F12->encoding() + _number);
aoqi@199 173 }
aoqi@199 174
aoqi@199 175 Address as_caller_address()const {return Address(SP, (number() LP64_ONLY( -n_register_parameters)) * wordSize);}
aoqi@1 176 };
aoqi@1 177
aoqi@1 178
aoqi@1 179
aoqi@1 180 //
aoqi@1 181 // AddressLiteral has been split out from Address because operands of this type
aoqi@1 182 // need to be treated specially on 32bit vs. 64bit platforms. By splitting it out
aoqi@1 183 // the few instructions that need to deal with address literals are unique and the
aoqi@1 184 // MacroAssembler does not have to implement every instruction in the Assembler
aoqi@1 185 // in order to search for address literals that may need special handling depending
aoqi@1 186 // on the instruction and the platform. As small step on the way to merging i486/amd64
aoqi@1 187 // directories.
aoqi@1 188 //
aoqi@1 189 class AddressLiteral VALUE_OBJ_CLASS_SPEC {
aoqi@1 190 friend class ArrayAddress;
aoqi@1 191 RelocationHolder _rspec;
aoqi@1 192 // Typically we use AddressLiterals we want to use their rval
aoqi@1 193 // However in some situations we want the lval (effect address) of the item.
aoqi@1 194 // We provide a special factory for making those lvals.
aoqi@1 195 bool _is_lval;
aoqi@1 196
aoqi@1 197 // If the target is far we'll need to load the ea of this to
aoqi@1 198 // a register to reach it. Otherwise if near we can do rip
aoqi@1 199 // relative addressing.
aoqi@1 200
aoqi@1 201 address _target;
aoqi@1 202
aoqi@1 203 protected:
aoqi@1 204 // creation
aoqi@1 205 AddressLiteral()
aoqi@1 206 : _is_lval(false),
aoqi@1 207 _target(NULL)
aoqi@1 208 {}
aoqi@1 209
aoqi@6880 210 public:
aoqi@6880 211
aoqi@1 212
aoqi@1 213 AddressLiteral(address target, relocInfo::relocType rtype);
aoqi@1 214
aoqi@1 215 AddressLiteral(address target, RelocationHolder const& rspec)
aoqi@1 216 : _rspec(rspec),
aoqi@1 217 _is_lval(false),
aoqi@1 218 _target(target)
aoqi@1 219 {}
aoqi@1 220 #ifdef _LP64
aoqi@1 221 // 32-bit complains about a multiple declaration for int*.
aoqi@1 222 AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none)
aoqi@1 223 : _target((address) addr),
aoqi@1 224 _rspec(rspec_from_rtype(rtype, (address) addr)) {}
aoqi@1 225 #endif
aoqi@1 226
aoqi@1 227 AddressLiteral addr() {
aoqi@1 228 AddressLiteral ret = *this;
aoqi@1 229 ret._is_lval = true;
aoqi@1 230 return ret;
aoqi@1 231 }
aoqi@1 232
aoqi@1 233
aoqi@1 234 private:
aoqi@1 235
aoqi@1 236 address target() { return _target; }
aoqi@1 237 bool is_lval() { return _is_lval; }
aoqi@1 238
aoqi@1 239 relocInfo::relocType reloc() const { return _rspec.type(); }
aoqi@1 240 const RelocationHolder& rspec() const { return _rspec; }
aoqi@1 241
aoqi@1 242 friend class Assembler;
aoqi@1 243 friend class MacroAssembler;
aoqi@1 244 friend class Address;
aoqi@1 245 friend class LIR_Assembler;
aoqi@199 246 RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) {
aoqi@199 247 switch (rtype) {
aoqi@199 248 case relocInfo::external_word_type:
aoqi@199 249 return external_word_Relocation::spec(addr);
aoqi@199 250 case relocInfo::internal_word_type:
aoqi@199 251 return internal_word_Relocation::spec(addr);
aoqi@199 252 case relocInfo::opt_virtual_call_type:
aoqi@199 253 return opt_virtual_call_Relocation::spec();
aoqi@199 254 case relocInfo::static_call_type:
aoqi@199 255 return static_call_Relocation::spec();
aoqi@199 256 case relocInfo::runtime_call_type:
aoqi@199 257 return runtime_call_Relocation::spec();
aoqi@199 258 case relocInfo::poll_type:
aoqi@199 259 case relocInfo::poll_return_type:
aoqi@199 260 return Relocation::spec_simple(rtype);
aoqi@199 261 case relocInfo::none:
aoqi@199 262 case relocInfo::oop_type:
aoqi@199 263 // Oops are a special case. Normally they would be their own section
aoqi@199 264 // but in cases like icBuffer they are literals in the code stream that
aoqi@199 265 // we don't have a section for. We use none so that we get a literal address
aoqi@199 266 // which is always patchable.
aoqi@199 267 return RelocationHolder();
aoqi@199 268 default:
aoqi@199 269 ShouldNotReachHere();
aoqi@199 270 return RelocationHolder();
aoqi@199 271 }
aoqi@199 272 }
aoqi@1 273
aoqi@1 274 };
aoqi@1 275
aoqi@1 276 // Convience classes
aoqi@1 277 class RuntimeAddress: public AddressLiteral {
aoqi@1 278
aoqi@199 279 public:
aoqi@1 280
aoqi@1 281 RuntimeAddress(address target) : AddressLiteral(target, relocInfo::runtime_call_type) {}
aoqi@1 282
aoqi@1 283 };
aoqi@1 284
aoqi@1 285 class OopAddress: public AddressLiteral {
aoqi@1 286
aoqi@199 287 public:
aoqi@1 288
aoqi@1 289 OopAddress(address target) : AddressLiteral(target, relocInfo::oop_type){}
aoqi@1 290
aoqi@1 291 };
aoqi@1 292
aoqi@1 293 class ExternalAddress: public AddressLiteral {
aoqi@1 294
aoqi@199 295 public:
aoqi@1 296
aoqi@1 297 ExternalAddress(address target) : AddressLiteral(target, relocInfo::external_word_type){}
aoqi@1 298
aoqi@1 299 };
aoqi@1 300
aoqi@1 301 class InternalAddress: public AddressLiteral {
aoqi@1 302
aoqi@199 303 public:
aoqi@1 304
aoqi@1 305 InternalAddress(address target) : AddressLiteral(target, relocInfo::internal_word_type) {}
aoqi@1 306
aoqi@1 307 };
aoqi@1 308
aoqi@1 309 // x86 can do array addressing as a single operation since disp can be an absolute
aoqi@1 310 // address amd64 can't. We create a class that expresses the concept but does extra
aoqi@1 311 // magic on amd64 to get the final result
aoqi@1 312
aoqi@1 313 class ArrayAddress VALUE_OBJ_CLASS_SPEC {
aoqi@1 314 private:
aoqi@1 315
aoqi@1 316 AddressLiteral _base;
aoqi@1 317 Address _index;
aoqi@1 318
aoqi@1 319 public:
aoqi@1 320
aoqi@1 321 ArrayAddress() {};
aoqi@1 322 ArrayAddress(AddressLiteral base, Address index): _base(base), _index(index) {};
aoqi@1 323 AddressLiteral base() { return _base; }
aoqi@1 324 Address index() { return _index; }
aoqi@1 325
aoqi@1 326 };
aoqi@1 327
aoqi@1 328 const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512 / wordSize);
aoqi@1 329
aoqi@1 330 // The MIPS LOONGSON Assembler: Pure assembler doing NO optimizations on the instruction
aoqi@199 331 // level ; i.e., what you write is what you get. The Assembler is generating code into
aoqi@1 332 // a CodeBuffer.
aoqi@1 333
aoqi@1 334 class Assembler : public AbstractAssembler {
aoqi@1 335 friend class AbstractAssembler; // for the non-virtual hack
aoqi@1 336 friend class LIR_Assembler; // as_Address()
aoqi@1 337 friend class StubGenerator;
aoqi@1 338
aoqi@199 339 public:
fujie@9274 340 enum Condition {
fujie@9274 341 zero ,
fujie@9274 342 notZero ,
fujie@9274 343 equal ,
fujie@9274 344 notEqual ,
fujie@9274 345 less ,
fujie@9274 346 lessEqual ,
fujie@9274 347 greater ,
fujie@9274 348 greaterEqual ,
fujie@9274 349 below ,
fujie@9274 350 belowEqual ,
fujie@9274 351 above ,
fujie@9274 352 aboveEqual
fujie@9274 353 };
fujie@9274 354
fujie@381 355 static const int LogInstructionSize = 2;
fujie@381 356 static const int InstructionSize = 1 << LogInstructionSize;
fujie@381 357
aoqi@199 358 // opcode, highest 6 bits: bits[31...26]
aoqi@1 359 enum ops {
aoqi@199 360 special_op = 0x00, // special_ops
aoqi@199 361 regimm_op = 0x01, // regimm_ops
aoqi@199 362 j_op = 0x02,
aoqi@199 363 jal_op = 0x03,
aoqi@199 364 beq_op = 0x04,
aoqi@199 365 bne_op = 0x05,
aoqi@199 366 blez_op = 0x06,
aoqi@199 367 bgtz_op = 0x07,
aoqi@199 368 addi_op = 0x08,
aoqi@199 369 addiu_op = 0x09,
aoqi@199 370 slti_op = 0x0a,
aoqi@199 371 sltiu_op = 0x0b,
aoqi@199 372 andi_op = 0x0c,
aoqi@199 373 ori_op = 0x0d,
aoqi@199 374 xori_op = 0x0e,
aoqi@199 375 lui_op = 0x0f,
aoqi@199 376 cop0_op = 0x10, // cop0_ops
aoqi@199 377 cop1_op = 0x11, // cop1_ops
aoqi@199 378 gs_cop2_op = 0x12, // gs_cop2_ops
aoqi@199 379 cop1x_op = 0x13, // cop1x_ops
aoqi@199 380 beql_op = 0x14,
aoqi@199 381 bnel_op = 0x15,
aoqi@199 382 blezl_op = 0x16,
aoqi@199 383 bgtzl_op = 0x17,
aoqi@199 384 daddi_op = 0x18,
aoqi@199 385 daddiu_op = 0x19,
aoqi@199 386 ldl_op = 0x1a,
aoqi@199 387 ldr_op = 0x1b,
aoqi@199 388 special2_op = 0x1c, // special2_ops
aoqi@199 389 msa_op = 0x1e, // msa_ops
aoqi@199 390 special3_op = 0x1f, // special3_ops
aoqi@199 391 lb_op = 0x20,
aoqi@199 392 lh_op = 0x21,
aoqi@199 393 lwl_op = 0x22,
aoqi@199 394 lw_op = 0x23,
aoqi@199 395 lbu_op = 0x24,
aoqi@199 396 lhu_op = 0x25,
aoqi@1 397 lwr_op = 0x26,
aoqi@1 398 lwu_op = 0x27,
aoqi@1 399 sb_op = 0x28,
aoqi@1 400 sh_op = 0x29,
aoqi@1 401 swl_op = 0x2a,
aoqi@199 402 sw_op = 0x2b,
aoqi@199 403 sdl_op = 0x2c,
aoqi@199 404 sdr_op = 0x2d,
aoqi@199 405 swr_op = 0x2e,
aoqi@199 406 cache_op = 0x2f,
aoqi@199 407 ll_op = 0x30,
aoqi@199 408 lwc1_op = 0x31,
aoqi@199 409 gs_lwc2_op = 0x32, //gs_lwc2_ops
aoqi@199 410 pref_op = 0x33,
aoqi@199 411 lld_op = 0x34,
aoqi@199 412 ldc1_op = 0x35,
aoqi@199 413 gs_ldc2_op = 0x36, //gs_ldc2_ops
aoqi@199 414 ld_op = 0x37,
aoqi@199 415 sc_op = 0x38,
aoqi@199 416 swc1_op = 0x39,
aoqi@199 417 gs_swc2_op = 0x3a, //gs_swc2_ops
aoqi@199 418 scd_op = 0x3c,
aoqi@199 419 sdc1_op = 0x3d,
aoqi@199 420 gs_sdc2_op = 0x3e, //gs_sdc2_ops
aoqi@199 421 sd_op = 0x3f
aoqi@1 422 };
aoqi@1 423
aoqi@199 424 static const char *ops_name[];
fujie@41 425
aoqi@199 426 //special family, the opcode is in low 6 bits.
aoqi@199 427 enum special_ops {
aoqi@199 428 sll_op = 0x00,
aoqi@199 429 movci_op = 0x01,
aoqi@199 430 srl_op = 0x02,
aoqi@199 431 sra_op = 0x03,
aoqi@199 432 sllv_op = 0x04,
aoqi@199 433 srlv_op = 0x06,
aoqi@199 434 srav_op = 0x07,
aoqi@199 435 jr_op = 0x08,
aoqi@199 436 jalr_op = 0x09,
aoqi@199 437 movz_op = 0x0a,
aoqi@199 438 movn_op = 0x0b,
aoqi@199 439 syscall_op = 0x0c,
aoqi@199 440 break_op = 0x0d,
aoqi@199 441 sync_op = 0x0f,
aoqi@199 442 mfhi_op = 0x10,
aoqi@199 443 mthi_op = 0x11,
aoqi@199 444 mflo_op = 0x12,
aoqi@199 445 mtlo_op = 0x13,
aoqi@199 446 dsllv_op = 0x14,
aoqi@199 447 dsrlv_op = 0x16,
aoqi@199 448 dsrav_op = 0x17,
aoqi@199 449 mult_op = 0x18,
aoqi@199 450 multu_op = 0x19,
aoqi@199 451 div_op = 0x1a,
aoqi@199 452 divu_op = 0x1b,
aoqi@199 453 dmult_op = 0x1c,
aoqi@199 454 dmultu_op = 0x1d,
aoqi@199 455 ddiv_op = 0x1e,
aoqi@199 456 ddivu_op = 0x1f,
aoqi@199 457 add_op = 0x20,
aoqi@199 458 addu_op = 0x21,
aoqi@199 459 sub_op = 0x22,
aoqi@199 460 subu_op = 0x23,
aoqi@199 461 and_op = 0x24,
aoqi@199 462 or_op = 0x25,
aoqi@199 463 xor_op = 0x26,
aoqi@199 464 nor_op = 0x27,
aoqi@199 465 slt_op = 0x2a,
aoqi@199 466 sltu_op = 0x2b,
aoqi@199 467 dadd_op = 0x2c,
aoqi@199 468 daddu_op = 0x2d,
aoqi@199 469 dsub_op = 0x2e,
aoqi@199 470 dsubu_op = 0x2f,
aoqi@199 471 tge_op = 0x30,
aoqi@199 472 tgeu_op = 0x31,
aoqi@199 473 tlt_op = 0x32,
aoqi@199 474 tltu_op = 0x33,
aoqi@199 475 teq_op = 0x34,
aoqi@199 476 tne_op = 0x36,
aoqi@199 477 dsll_op = 0x38,
aoqi@199 478 dsrl_op = 0x3a,
aoqi@199 479 dsra_op = 0x3b,
aoqi@199 480 dsll32_op = 0x3c,
aoqi@199 481 dsrl32_op = 0x3e,
aoqi@199 482 dsra32_op = 0x3f
aoqi@199 483 };
fujie@41 484
aoqi@199 485 static const char* special_name[];
aoqi@1 486
aoqi@199 487 //regimm family, the opcode is in rt[16...20], 5 bits
aoqi@199 488 enum regimm_ops {
aoqi@199 489 bltz_op = 0x00,
aoqi@199 490 bgez_op = 0x01,
aoqi@199 491 bltzl_op = 0x02,
aoqi@199 492 bgezl_op = 0x03,
aoqi@199 493 tgei_op = 0x08,
aoqi@199 494 tgeiu_op = 0x09,
aoqi@199 495 tlti_op = 0x0a,
aoqi@199 496 tltiu_op = 0x0b,
aoqi@199 497 teqi_op = 0x0c,
aoqi@199 498 tnei_op = 0x0e,
aoqi@199 499 bltzal_op = 0x10,
aoqi@199 500 bgezal_op = 0x11,
aoqi@199 501 bltzall_op = 0x12,
aoqi@199 502 bgezall_op = 0x13,
aoqi@199 503 bposge32_op = 0x1c,
aoqi@199 504 bposge64_op = 0x1d,
aoqi@199 505 synci_op = 0x1f,
aoqi@199 506 };
aoqi@1 507
aoqi@199 508 static const char* regimm_name[];
aoqi@1 509
aoqi@199 510 //cop0 family, the ops is in bits[25...21], 5 bits
aoqi@199 511 enum cop0_ops {
aoqi@199 512 mfc0_op = 0x00,
aoqi@199 513 dmfc0_op = 0x01,
aoqi@199 514 //
aoqi@199 515 mxgc0_op = 0x03, //MFGC0, DMFGC0, MTGC0
aoqi@199 516 mtc0_op = 0x04,
aoqi@199 517 dmtc0_op = 0x05,
aoqi@199 518 rdpgpr_op = 0x0a,
aoqi@199 519 inter_op = 0x0b,
aoqi@199 520 wrpgpr_op = 0x0c
aoqi@199 521 };
fujie@195 522
aoqi@199 523 //cop1 family, the ops is in bits[25...21], 5 bits
aoqi@199 524 enum cop1_ops {
aoqi@199 525 mfc1_op = 0x00,
aoqi@199 526 dmfc1_op = 0x01,
aoqi@199 527 cfc1_op = 0x02,
aoqi@199 528 mfhc1_op = 0x03,
aoqi@199 529 mtc1_op = 0x04,
aoqi@199 530 dmtc1_op = 0x05,
aoqi@199 531 ctc1_op = 0x06,
aoqi@199 532 mthc1_op = 0x07,
aoqi@199 533 bc1f_op = 0x08,
aoqi@199 534 single_fmt = 0x10,
aoqi@199 535 double_fmt = 0x11,
aoqi@199 536 word_fmt = 0x14,
aoqi@199 537 long_fmt = 0x15,
aoqi@199 538 ps_fmt = 0x16
aoqi@199 539 };
fujie@195 540
aoqi@1 541
aoqi@199 542 //2 bist (bits[17...16]) of bc1x instructions (cop1)
aoqi@199 543 enum bc_ops {
aoqi@199 544 bcf_op = 0x0,
aoqi@199 545 bct_op = 0x1,
aoqi@199 546 bcfl_op = 0x2,
aoqi@199 547 bctl_op = 0x3,
aoqi@199 548 };
aoqi@1 549
aoqi@199 550 // low 6 bits of c_x_fmt instructions (cop1)
aoqi@199 551 enum c_conds {
aoqi@199 552 f_cond = 0x30,
aoqi@199 553 un_cond = 0x31,
aoqi@199 554 eq_cond = 0x32,
aoqi@199 555 ueq_cond = 0x33,
aoqi@199 556 olt_cond = 0x34,
aoqi@199 557 ult_cond = 0x35,
aoqi@199 558 ole_cond = 0x36,
aoqi@199 559 ule_cond = 0x37,
aoqi@199 560 sf_cond = 0x38,
aoqi@199 561 ngle_cond = 0x39,
aoqi@199 562 seq_cond = 0x3a,
aoqi@199 563 ngl_cond = 0x3b,
aoqi@199 564 lt_cond = 0x3c,
aoqi@199 565 nge_cond = 0x3d,
aoqi@199 566 le_cond = 0x3e,
aoqi@199 567 ngt_cond = 0x3f
aoqi@199 568 };
aoqi@1 569
aoqi@199 570 // low 6 bits of cop1 instructions
aoqi@199 571 enum float_ops {
aoqi@199 572 fadd_op = 0x00,
aoqi@199 573 fsub_op = 0x01,
aoqi@199 574 fmul_op = 0x02,
aoqi@199 575 fdiv_op = 0x03,
aoqi@199 576 fsqrt_op = 0x04,
aoqi@199 577 fabs_op = 0x05,
aoqi@199 578 fmov_op = 0x06,
aoqi@199 579 fneg_op = 0x07,
aoqi@199 580 froundl_op = 0x08,
aoqi@199 581 ftruncl_op = 0x09,
aoqi@199 582 fceill_op = 0x0a,
aoqi@199 583 ffloorl_op = 0x0b,
aoqi@199 584 froundw_op = 0x0c,
aoqi@199 585 ftruncw_op = 0x0d,
aoqi@199 586 fceilw_op = 0x0e,
aoqi@199 587 ffloorw_op = 0x0f,
aoqi@199 588 movf_f_op = 0x11,
aoqi@199 589 movt_f_op = 0x11,
aoqi@199 590 movz_f_op = 0x12,
aoqi@199 591 movn_f_op = 0x13,
aoqi@199 592 frecip_op = 0x15,
aoqi@199 593 frsqrt_op = 0x16,
aoqi@199 594 fcvts_op = 0x20,
aoqi@199 595 fcvtd_op = 0x21,
aoqi@199 596 fcvtw_op = 0x24,
aoqi@199 597 fcvtl_op = 0x25,
aoqi@276 598 fcvtps_op = 0x26,
aoqi@276 599 fcvtspl_op = 0x28,
aoqi@199 600 fpll_op = 0x2c,
aoqi@199 601 fplu_op = 0x2d,
aoqi@199 602 fpul_op = 0x2e,
aoqi@199 603 fpuu_op = 0x2f
aoqi@199 604 };
aoqi@199 605
aoqi@199 606 static const char* cop1_name[];
aoqi@199 607
aoqi@199 608 //cop1x family, the opcode is in low 6 bits.
aoqi@199 609 enum cop1x_ops {
aoqi@199 610 lwxc1_op = 0x00,
aoqi@199 611 ldxc1_op = 0x01,
aoqi@199 612 luxc1_op = 0x05,
aoqi@199 613 swxc1_op = 0x08,
aoqi@199 614 sdxc1_op = 0x09,
aoqi@199 615 suxc1_op = 0x0d,
aoqi@199 616 prefx_op = 0x0f,
aoqi@199 617
aoqi@199 618 alnv_ps_op = 0x1e,
aoqi@199 619 madd_s_op = 0x20,
aoqi@199 620 madd_d_op = 0x21,
aoqi@199 621 madd_ps_op = 0x26,
aoqi@199 622 msub_s_op = 0x28,
aoqi@199 623 msub_d_op = 0x29,
aoqi@199 624 msub_ps_op = 0x2e,
aoqi@199 625 nmadd_s_op = 0x30,
aoqi@199 626 nmadd_d_op = 0x31,
aoqi@199 627 nmadd_ps_op = 0x36,
aoqi@199 628 nmsub_s_op = 0x38,
aoqi@199 629 nmsub_d_op = 0x39,
aoqi@199 630 nmsub_ps_op = 0x3e
aoqi@199 631 };
aoqi@199 632
aoqi@199 633 static const char* cop1x_name[];
aoqi@199 634
aoqi@199 635 //special2 family, the opcode is in low 6 bits.
aoqi@199 636 enum special2_ops {
aoqi@199 637 madd_op = 0x00,
aoqi@199 638 maddu_op = 0x01,
aoqi@199 639 mul_op = 0x02,
fujie@295 640 gs0x03_op = 0x03,
aoqi@199 641 msub_op = 0x04,
aoqi@199 642 msubu_op = 0x05,
fujie@295 643 gs0x06_op = 0x06,
aoqi@199 644 gsemul2_op = 0x07,
aoqi@199 645 gsemul3_op = 0x08,
aoqi@199 646 gsemul4_op = 0x09,
aoqi@199 647 gsemul5_op = 0x0a,
aoqi@199 648 gsemul6_op = 0x0b,
aoqi@199 649 gsemul7_op = 0x0c,
aoqi@199 650 gsemul8_op = 0x0d,
aoqi@199 651 gsemul9_op = 0x0e,
aoqi@199 652 gsemul10_op = 0x0f,
aoqi@199 653 gsmult_op = 0x10,
aoqi@199 654 gsdmult_op = 0x11,
aoqi@199 655 gsmultu_op = 0x12,
aoqi@199 656 gsdmultu_op = 0x13,
aoqi@199 657 gsdiv_op = 0x14,
aoqi@199 658 gsddiv_op = 0x15,
aoqi@199 659 gsdivu_op = 0x16,
aoqi@199 660 gsddivu_op = 0x17,
aoqi@199 661 gsmod_op = 0x1c,
aoqi@199 662 gsdmod_op = 0x1d,
aoqi@199 663 gsmodu_op = 0x1e,
aoqi@199 664 gsdmodu_op = 0x1f,
aoqi@199 665 clz_op = 0x20,
aoqi@199 666 clo_op = 0x21,
aoqi@199 667 xctx_op = 0x22, //ctz, cto, dctz, dcto, gsX
aoqi@199 668 gsrxr_x_op = 0x23, //gsX
aoqi@199 669 dclz_op = 0x24,
aoqi@199 670 dclo_op = 0x25,
aoqi@199 671 gsle_op = 0x26,
aoqi@199 672 gsgt_op = 0x27,
aoqi@199 673 gs86j_op = 0x28,
aoqi@199 674 gsloop_op = 0x29,
aoqi@199 675 gsaj_op = 0x2a,
aoqi@199 676 gsldpc_op = 0x2b,
aoqi@199 677 gs86set_op = 0x30,
aoqi@199 678 gstm_op = 0x31,
aoqi@199 679 gscvt_ld_op = 0x32,
aoqi@199 680 gscvt_ud_op = 0x33,
aoqi@199 681 gseflag_op = 0x34,
aoqi@199 682 gscam_op = 0x35,
aoqi@199 683 gstop_op = 0x36,
aoqi@199 684 gssettag_op = 0x37,
aoqi@199 685 gssdbbp_op = 0x38
aoqi@199 686 };
aoqi@199 687
aoqi@8012 688 enum gscam_ops {
aoqi@8012 689 campv_op = 0x0,
aoqi@8012 690 campi_op = 0x1,
aoqi@8012 691 camwi_op = 0x2,
aoqi@8012 692 ramri_op = 0x3
aoqi@8012 693 };
aoqi@8012 694
aoqi@199 695 static const char* special2_name[];
aoqi@199 696
aoqi@199 697 // special3 family, the opcode is in low 6 bits.
aoqi@199 698 enum special3_ops {
aoqi@199 699 ext_op = 0x00,
aoqi@199 700 dextm_op = 0x01,
aoqi@199 701 dextu_op = 0x02,
aoqi@199 702 dext_op = 0x03,
aoqi@199 703 ins_op = 0x04,
aoqi@199 704 dinsm_op = 0x05,
aoqi@199 705 dinsu_op = 0x06,
aoqi@199 706 dins_op = 0x07,
aoqi@199 707 lxx_op = 0x0a, //lwx, lhx, lbux, ldx
aoqi@199 708 insv_op = 0x0c,
aoqi@199 709 dinsv_op = 0x0d,
aoqi@199 710 ar1_op = 0x10, //MIPS DSP
aoqi@199 711 cmp1_op = 0x11, //MIPS DSP
aoqi@199 712 re1_op = 0x12, //MIPS DSP, re1_ops
aoqi@199 713 sh1_op = 0x13, //MIPS DSP
aoqi@199 714 ar2_op = 0x14, //MIPS DSP
aoqi@199 715 cmp2_op = 0x15, //MIPS DSP
aoqi@199 716 re2_op = 0x16, //MIPS DSP, re2_ops
aoqi@199 717 sh2_op = 0x17, //MIPS DSP
fujie@256 718 ar3_op = 0x18, //MIPS DSP
aoqi@8012 719 bshfl_op = 0x20, //seb, seh
aoqi@8012 720 rdhwr_op = 0x3b
aoqi@199 721 };
aoqi@199 722
aoqi@199 723 // re1_ops
aoqi@199 724 enum re1_ops {
aoqi@199 725 absq_s_qb_op = 0x01,
aoqi@199 726 repl_qb_op = 0x02,
aoqi@199 727 replv_qb_op = 0x03,
aoqi@199 728 absq_s_ph_op = 0x09,
aoqi@199 729 repl_ph_op = 0x0a,
aoqi@199 730 replv_ph_op = 0x0b,
aoqi@199 731 absq_s_w_op = 0x11,
aoqi@199 732 bitrev_op = 0x1b
aoqi@199 733 };
aoqi@199 734
aoqi@199 735 // re2_ops
aoqi@199 736 enum re2_ops {
aoqi@199 737 repl_ob_op = 0x02,
aoqi@199 738 replv_ob_op = 0x03,
aoqi@199 739 absq_s_qh_op = 0x09,
aoqi@199 740 repl_qh_op = 0x0a,
aoqi@199 741 replv_qh_op = 0x0b,
aoqi@199 742 absq_s_pw_op = 0x11,
aoqi@199 743 repl_pw_op = 0x12,
aoqi@8012 744 replv_pw_op = 0x13
aoqi@199 745 };
aoqi@199 746
aoqi@199 747 static const char* special3_name[];
aoqi@199 748
aoqi@199 749 // lwc2/gs_lwc2 family, the opcode is in low 6 bits.
aoqi@199 750 enum gs_lwc2_ops {
jiangshaofeng@362 751 gslble_op = 0x10,
jiangshaofeng@362 752 gslbgt_op = 0x11,
jiangshaofeng@362 753 gslhle_op = 0x12,
jiangshaofeng@362 754 gslhgt_op = 0x13,
jiangshaofeng@362 755 gslwle_op = 0x14,
jiangshaofeng@362 756 gslwgt_op = 0x15,
jiangshaofeng@362 757 gsldle_op = 0x16,
jiangshaofeng@362 758 gsldgt_op = 0x17,
jiangshaofeng@362 759 gslwlec1_op = 0x1c,
jiangshaofeng@362 760 gslwgtc1_op = 0x1d,
jiangshaofeng@362 761 gsldlec1_op = 0x1e,
jiangshaofeng@362 762 gsldgtc1_op = 0x1f,
aoqi@199 763 gslq_op = 0x20
aoqi@199 764 };
aoqi@199 765
aoqi@199 766 static const char* gs_lwc2_name[];
aoqi@199 767
aoqi@199 768 // ldc2/gs_ldc2 family, the opcode is in low 3 bits.
aoqi@199 769 enum gs_ldc2_ops {
aoqi@199 770 gslbx_op = 0x0,
aoqi@199 771 gslhx_op = 0x1,
aoqi@199 772 gslwx_op = 0x2,
aoqi@199 773 gsldx_op = 0x3,
aoqi@199 774 gslwxc1_op = 0x6,
aoqi@199 775 gsldxc1_op = 0x7
aoqi@199 776 };
aoqi@199 777
aoqi@199 778 static const char* gs_ldc2_name[];
aoqi@199 779
aoqi@199 780 // swc2/gs_swc2 family, the opcode is in low 6 bits.
aoqi@199 781 enum gs_swc2_ops {
jiangshaofeng@362 782 gssble_op = 0x10,
jiangshaofeng@362 783 gssbgt_op = 0x11,
jiangshaofeng@362 784 gsshle_op = 0x12,
jiangshaofeng@362 785 gsshgt_op = 0x13,
jiangshaofeng@362 786 gsswle_op = 0x14,
jiangshaofeng@362 787 gsswgt_op = 0x15,
jiangshaofeng@362 788 gssdle_op = 0x16,
jiangshaofeng@362 789 gssdgt_op = 0x17,
jiangshaofeng@362 790 gsswlec1_op = 0x1c,
jiangshaofeng@362 791 gsswgtc1_op = 0x1d,
jiangshaofeng@362 792 gssdlec1_op = 0x1e,
jiangshaofeng@362 793 gssdgtc1_op = 0x1f,
aoqi@199 794 gssq_op = 0x20
aoqi@199 795 };
aoqi@199 796
aoqi@199 797 static const char* gs_swc2_name[];
aoqi@199 798
aoqi@199 799 // sdc2/gs_sdc2 family, the opcode is in low 3 bits.
aoqi@199 800 enum gs_sdc2_ops {
aoqi@199 801 gssbx_op = 0x0,
aoqi@199 802 gsshx_op = 0x1,
aoqi@199 803 gsswx_op = 0x2,
aoqi@199 804 gssdx_op = 0x3,
aoqi@199 805 gsswxc1_op = 0x6,
aoqi@199 806 gssdxc1_op = 0x7
aoqi@199 807 };
aoqi@199 808
aoqi@199 809 static const char* gs_sdc2_name[];
fujie@44 810
aoqi@1 811 enum WhichOperand {
aoqi@1 812 // input to locate_operand, and format code for relocations
aoqi@1 813 imm_operand = 0, // embedded 32-bit|64-bit immediate operand
aoqi@1 814 disp32_operand = 1, // embedded 32-bit displacement or address
aoqi@1 815 call32_operand = 2, // embedded 32-bit self-relative displacement
aoqi@1 816 #ifndef _LP64
aoqi@1 817 _WhichOperand_limit = 3
aoqi@1 818 #else
aoqi@1 819 narrow_oop_operand = 3, // embedded 32-bit immediate narrow oop
aoqi@1 820 _WhichOperand_limit = 4
aoqi@1 821 #endif
aoqi@1 822 };
aoqi@1 823
aoqi@199 824 static int opcode(int insn) { return (insn>>26)&0x3f; }
aoqi@199 825 static int rs(int insn) { return (insn>>21)&0x1f; }
aoqi@199 826 static int rt(int insn) { return (insn>>16)&0x1f; }
aoqi@199 827 static int rd(int insn) { return (insn>>11)&0x1f; }
aoqi@199 828 static int sa(int insn) { return (insn>>6)&0x1f; }
aoqi@199 829 static int special(int insn) { return insn&0x3f; }
aoqi@199 830 static int imm_off(int insn) { return (short)low16(insn); }
lifangyuan@125 831
aoqi@199 832 static int low (int x, int l) { return bitfield(x, 0, l); }
aoqi@199 833 static int low16(int x) { return low(x, 16); }
aoqi@199 834 static int low26(int x) { return low(x, 26); }
lifangyuan@125 835
aoqi@199 836 protected:
aoqi@199 837 //help methods for instruction ejection
aoqi@1 838
aoqi@199 839 // I-Type (Immediate)
aoqi@199 840 // 31 26 25 21 20 16 15 0
aoqi@199 841 //| opcode | rs | rt | immediat |
aoqi@199 842 //| | | | |
aoqi@199 843 // 6 5 5 16
fujie@9263 844 static int insn_ORRI(int op, int rs, int rt, int imm) { assert(is_simm16(imm), "not a signed 16-bit int"); return (op<<26) | (rs<<21) | (rt<<16) | low16(imm); }
lifangyuan@125 845
aoqi@199 846 // R-Type (Register)
aoqi@199 847 // 31 26 25 21 20 16 15 11 10 6 5 0
aoqi@199 848 //| special | rs | rt | rd | 0 | opcode |
aoqi@199 849 //| 0 0 0 0 0 0 | | | | 0 0 0 0 0 | |
aoqi@199 850 // 6 5 5 5 5 6
aoqi@199 851 static int insn_RRRO(int rs, int rt, int rd, int op) { return (rs<<21) | (rt<<16) | (rd<<11) | op; }
aoqi@199 852 static int insn_RRSO(int rt, int rd, int sa, int op) { return (rt<<16) | (rd<<11) | (sa<<6) | op; }
aoqi@199 853 static int insn_RRCO(int rs, int rt, int code, int op) { return (rs<<21) | (rt<<16) | (code<<6) | op; }
lifangyuan@125 854
aoqi@199 855 static int insn_COP0(int op, int rt, int rd) { return (cop0_op<<26) | (op<<21) | (rt<<16) | (rd<<11); }
aoqi@199 856 static int insn_COP1(int op, int rt, int fs) { return (cop1_op<<26) | (op<<21) | (rt<<16) | (fs<<11); }
aoqi@1 857
aoqi@199 858 static int insn_F3RO(int fmt, int ft, int fs, int fd, int func) {
aoqi@199 859 return (cop1_op<<26) | (fmt<<21) | (ft<<16) | (fs<<11) | (fd<<6) | func;
aoqi@199 860 }
aoqi@199 861 static int insn_F3ROX(int fmt, int ft, int fs, int fd, int func) {
aoqi@199 862 return (cop1x_op<<26) | (fmt<<21) | (ft<<16) | (fs<<11) | (fd<<6) | func;
aoqi@199 863 }
fujie@65 864
aoqi@199 865 static int high (int x, int l) { return bitfield(x, 32-l, l); }
aoqi@199 866 static int high16(int x) { return high(x, 16); }
aoqi@199 867 static int high6 (int x) { return high(x, 6); }
aoqi@1 868
aoqi@199 869 //get the offset field of jump/branch instruction
aoqi@199 870 int offset(address entry) {
aoqi@199 871 assert(is_simm16((entry - pc() - 4) / 4), "change this code");
aoqi@199 872 if (!is_simm16((entry - pc() - 4) / 4)) {
aoqi@199 873 tty->print_cr("!!! is_simm16: %x", (entry - pc() - 4) / 4);
aoqi@199 874 }
aoqi@199 875 return (entry - pc() - 4) / 4;
aoqi@199 876 }
aoqi@1 877
aoqi@1 878
aoqi@1 879 public:
aoqi@199 880 using AbstractAssembler::offset;
aoqi@1 881
aoqi@199 882 //sign expand with the sign bit is h
aoqi@199 883 static int expand(int x, int h) { return -(x & (1<<h)) | x; }
aoqi@1 884
fujie@293 885 // If x is a mask, return the number of one-bit in x.
fujie@293 886 // else return -1.
fujie@293 887 static int is_int_mask(int x);
fujie@293 888
fujie@301 889 // If x is a mask, return the number of one-bit in x.
fujie@301 890 // else return -1.
fujie@301 891 static int is_jlong_mask(jlong x);
fujie@301 892
aoqi@199 893 // 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 894 static int split_low(int x) {
aoqi@199 895 return (x & 0xffff);
aoqi@199 896 }
aoqi@1 897
fujie@9265 898 // Convert 16-bit x to a sign-extended 16-bit integer
fujie@9263 899 static int simm16(int x) {
fujie@9263 900 assert(x == (x & 0xFFFF), "must be 16-bit only");
fujie@9263 901 return (x << 16) >> 16;
fujie@9263 902 }
fujie@9263 903
aoqi@199 904 static int split_high(int x) {
aoqi@199 905 return ( (x >> 16) + ((x & 0x8000) != 0) ) & 0xffff;
aoqi@199 906 }
aoqi@1 907
aoqi@199 908 static int merge(int low, int high) {
aoqi@199 909 return expand(low, 15) + (high<<16);
aoqi@199 910 }
aoqi@1 911
aoqi@1 912 #ifdef _LP64
aoqi@199 913 static intptr_t merge(intptr_t x0, intptr_t x16, intptr_t x32, intptr_t x48) {
aoqi@199 914 return (x48 << 48) | (x32 << 32) | (x16 << 16) | x0;
aoqi@199 915 }
aoqi@1 916 #endif
aoqi@1 917
aoqi@9261 918 // Test if x is within signed immediate range for nbits.
aoqi@9261 919 static bool is_simm (int x, int nbits) {
aoqi@9261 920 assert(0 < nbits && nbits < 32, "out of bounds");
aoqi@9261 921 const int min = -( ((int)1) << nbits-1 );
aoqi@9261 922 const int maxplus1 = ( ((int)1) << nbits-1 );
aoqi@9261 923 return min <= x && x < maxplus1;
aoqi@9261 924 }
aoqi@9261 925
aoqi@9261 926 static bool is_simm(jlong x, unsigned int nbits) {
aoqi@9261 927 assert(0 < nbits && nbits < 64, "out of bounds");
aoqi@9261 928 const jlong min = -( ((jlong)1) << nbits-1 );
aoqi@9261 929 const jlong maxplus1 = ( ((jlong)1) << nbits-1 );
aoqi@9261 930 return min <= x && x < maxplus1;
aoqi@9261 931 }
aoqi@9261 932
aoqi@9261 933 // Test if x is within unsigned immediate range for nbits
aoqi@9261 934 static bool is_uimm(int x, unsigned int nbits) {
aoqi@9261 935 assert(0 < nbits && nbits < 32, "out of bounds");
aoqi@9261 936 const int maxplus1 = ( ((int)1) << nbits );
aoqi@9261 937 return 0 <= x && x < maxplus1;
aoqi@9261 938 }
aoqi@9261 939
aoqi@9261 940 static bool is_uimm(jlong x, unsigned int nbits) {
aoqi@9261 941 assert(0 < nbits && nbits < 64, "out of bounds");
aoqi@9261 942 const jlong maxplus1 = ( ((jlong)1) << nbits );
aoqi@9261 943 return 0 <= x && x < maxplus1;
aoqi@9261 944 }
aoqi@9261 945
aoqi@199 946 static bool is_simm16(int x) { return is_simm(x, 16); }
jiefu@9646 947 static bool is_simm16(long x) { return is_simm((jlong)x, (unsigned int)16); }
aoqi@1 948
fujie@381 949 static bool fit_in_jal(address target, address pc) {
fujie@381 950 #ifdef _LP64
fujie@9168 951 intptr_t mask = 0xfffffffff0000000;
fujie@381 952 #else
fujie@9168 953 intptr_t mask = 0xf0000000;
fujie@381 954 #endif
fujie@9168 955 return ((intptr_t)(pc + 4) & mask) == ((intptr_t)target & mask);
aoqi@199 956 }
aoqi@199 957
aoqi@199 958 bool fit_int_branch(address entry) {
aoqi@199 959 return is_simm16(offset(entry));
aoqi@199 960 }
aoqi@1 961
aoqi@1 962 protected:
aoqi@1 963 #ifdef ASSERT
aoqi@199 964 #define CHECK_DELAY
aoqi@1 965 #endif
aoqi@1 966 #ifdef CHECK_DELAY
aoqi@199 967 enum Delay_state { no_delay, at_delay_slot, filling_delay_slot } delay_state;
aoqi@1 968 #endif
aoqi@199 969
aoqi@1 970 public:
aoqi@199 971 void assert_not_delayed() {
aoqi@1 972 #ifdef CHECK_DELAY
aoqi@199 973 assert_not_delayed("next instruction should not be a delay slot");
aoqi@1 974 #endif
aoqi@199 975 }
aoqi@1 976
aoqi@199 977 void assert_not_delayed(const char* msg) {
aoqi@1 978 #ifdef CHECK_DELAY
aoqi@199 979 //guarantee( delay_state == no_delay, msg );
aoqi@199 980 //aoqi_test
aoqi@199 981 if(delay_state != no_delay){
aoqi@199 982 tty->print_cr("%s:%d, pc: %lx", __func__, __LINE__, pc());
aoqi@199 983 }
aoqi@199 984 assert(delay_state == no_delay, msg);
aoqi@199 985 #endif
aoqi@199 986 }
aoqi@1 987
aoqi@1 988 protected:
aoqi@199 989 // Delay slot helpers
aoqi@199 990 // cti is called when emitting control-transfer instruction,
aoqi@199 991 // BEFORE doing the emitting.
aoqi@199 992 // Only effective when assertion-checking is enabled.
aoqi@199 993
aoqi@199 994 // called when emitting cti with a delay slot, AFTER emitting
aoqi@199 995 void has_delay_slot() {
aoqi@1 996 #ifdef CHECK_DELAY
aoqi@199 997 assert_not_delayed("just checking");
aoqi@199 998 delay_state = at_delay_slot;
aoqi@1 999 #endif
aoqi@199 1000 }
aoqi@1 1001
aoqi@1 1002 public:
aoqi@199 1003 Assembler* delayed() {
aoqi@1 1004 #ifdef CHECK_DELAY
aoqi@199 1005 guarantee( delay_state == at_delay_slot, "delayed instructition is not in delay slot");
aoqi@199 1006 delay_state = filling_delay_slot;
aoqi@1 1007 #endif
aoqi@199 1008 return this;
aoqi@199 1009 }
aoqi@1 1010
aoqi@199 1011 void flush() {
aoqi@1 1012 #ifdef CHECK_DELAY
aoqi@199 1013 guarantee( delay_state == no_delay, "ending code with a delay slot");
aoqi@1 1014 #endif
aoqi@199 1015 AbstractAssembler::flush();
aoqi@199 1016 }
aoqi@199 1017
aoqi@199 1018 inline void emit_long(int); // shadows AbstractAssembler::emit_long
aoqi@199 1019 inline void emit_data(int x) { emit_long(x); }
aoqi@199 1020 inline void emit_data(int, RelocationHolder const&);
aoqi@199 1021 inline void emit_data(int, relocInfo::relocType rtype);
aoqi@199 1022 inline void check_delay();
aoqi@199 1023
aoqi@1 1024
aoqi@1 1025 // Generic instructions
aoqi@1 1026 // Does 32bit or 64bit as needed for the platform. In some sense these
aoqi@1 1027 // belong in macro assembler but there is no need for both varieties to exist
aoqi@1 1028
aoqi@1 1029 #ifndef _LP64
aoqi@199 1030 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 1031 void addi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1032 void addiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1033 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 1034 #else
aoqi@199 1035 void add(Register rd, Register rs, Register rt) { dadd (rd, rs, rt); }
aoqi@199 1036 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 1037 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 1038 void addiu32(Register rt, Register rs, int imm) { emit_long(insn_ORRI(addiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1039 void addi(Register rt, Register rs, int imm) { daddi (rt, rs, imm);}
aoqi@199 1040 void addiu(Register rt, Register rs, int imm) { daddiu (rt, rs, imm);}
aoqi@199 1041 void addu(Register rd, Register rs, Register rt) { daddu (rd, rs, rt); }
aoqi@1 1042 #endif
aoqi@1 1043
aoqi@199 1044 void andr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), and_op)); }
fujie@9263 1045 void andi(Register rt, Register rs, int imm) { emit_long(insn_ORRI(andi_op, (int)rs->encoding(), (int)rt->encoding(), simm16(imm))); }
aoqi@1 1046
aoqi@199 1047 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 1048 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 1049 void bgez (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgez_op, off)); has_delay_slot(); }
aoqi@199 1050 void bgezal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezal_op, off)); has_delay_slot(); }
aoqi@199 1051 void bgezall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezall_op, off)); has_delay_slot(); }
aoqi@199 1052 void bgezl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bgezl_op, off)); has_delay_slot(); }
aoqi@199 1053 void bgtz (Register rs, int off) { emit_long(insn_ORRI(bgtz_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1054 void bgtzl (Register rs, int off) { emit_long(insn_ORRI(bgtzl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1055 void blez (Register rs, int off) { emit_long(insn_ORRI(blez_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1056 void blezl (Register rs, int off) { emit_long(insn_ORRI(blezl_op, (int)rs->encoding(), 0, off)); has_delay_slot(); }
aoqi@199 1057 void bltz (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltz_op, off)); has_delay_slot(); }
aoqi@199 1058 void bltzal (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzal_op, off)); has_delay_slot(); }
aoqi@199 1059 void bltzall(Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzall_op, off)); has_delay_slot(); }
aoqi@199 1060 void bltzl (Register rs, int off) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), bltzl_op, off)); has_delay_slot(); }
aoqi@199 1061 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 1062 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@9261 1063 // two versions of brk:
aoqi@9261 1064 // the brk(code) version is according to MIPS64 Architecture For Programmers Volume II: The MIPS64 Instruction Set
aoqi@9261 1065 // the brk(code1, code2) is according to disassembler of hsdis (binutils-2.27)
aoqi@9261 1066 // both versions work
aoqi@9261 1067 void brk (int code) { assert(is_uimm(code, 20), "code is 20 bits"); emit_long( (low(code, 20)<<6) | break_op ); }
aoqi@9261 1068 void brk (int code1, int code2) { assert(is_uimm(code1, 10) && is_uimm(code2, 10), "code is 20 bits"); emit_long( (low(code1, 10)<<16) | (low(code2, 10)<<6) | break_op ); }
fujie@37 1069
aoqi@199 1070 void beq (Register rs, Register rt, address entry) { beq(rs, rt, offset(entry)); }
aoqi@199 1071 void beql (Register rs, Register rt, address entry) { beql(rs, rt, offset(entry));}
aoqi@199 1072 void bgez (Register rs, address entry) { bgez (rs, offset(entry)); }
aoqi@199 1073 void bgezal (Register rs, address entry) { bgezal (rs, offset(entry)); }
aoqi@199 1074 void bgezall(Register rs, address entry) { bgezall(rs, offset(entry)); }
aoqi@199 1075 void bgezl (Register rs, address entry) { bgezl (rs, offset(entry)); }
aoqi@199 1076 void bgtz (Register rs, address entry) { bgtz (rs, offset(entry)); }
aoqi@199 1077 void bgtzl (Register rs, address entry) { bgtzl (rs, offset(entry)); }
aoqi@199 1078 void blez (Register rs, address entry) { blez (rs, offset(entry)); }
aoqi@199 1079 void blezl (Register rs, address entry) { blezl (rs, offset(entry)); }
aoqi@199 1080 void bltz (Register rs, address entry) { bltz (rs, offset(entry)); }
aoqi@199 1081 void bltzal (Register rs, address entry) { bltzal (rs, offset(entry)); }
aoqi@199 1082 void bltzall(Register rs, address entry) { bltzall(rs, offset(entry)); }
aoqi@199 1083 void bltzl (Register rs, address entry) { bltzl (rs, offset(entry)); }
aoqi@199 1084 void bne (Register rs, Register rt, address entry) { bne(rs, rt, offset(entry)); }
aoqi@199 1085 void bnel (Register rs, Register rt, address entry) { bnel(rs, rt, offset(entry)); }
fujie@37 1086
aoqi@199 1087 void beq (Register rs, Register rt, Label& L) { beq(rs, rt, target(L)); }
aoqi@199 1088 void beql (Register rs, Register rt, Label& L) { beql(rs, rt, target(L)); }
aoqi@199 1089 void bgez (Register rs, Label& L){ bgez (rs, target(L)); }
aoqi@199 1090 void bgezal (Register rs, Label& L){ bgezal (rs, target(L)); }
aoqi@199 1091 void bgezall(Register rs, Label& L){ bgezall(rs, target(L)); }
aoqi@199 1092 void bgezl (Register rs, Label& L){ bgezl (rs, target(L)); }
aoqi@199 1093 void bgtz (Register rs, Label& L){ bgtz (rs, target(L)); }
aoqi@199 1094 void bgtzl (Register rs, Label& L){ bgtzl (rs, target(L)); }
aoqi@199 1095 void blez (Register rs, Label& L){ blez (rs, target(L)); }
aoqi@199 1096 void blezl (Register rs, Label& L){ blezl (rs, target(L)); }
aoqi@199 1097 void bltz (Register rs, Label& L){ bltz (rs, target(L)); }
aoqi@199 1098 void bltzal (Register rs, Label& L){ bltzal (rs, target(L)); }
aoqi@199 1099 void bltzall(Register rs, Label& L){ bltzall(rs, target(L)); }
aoqi@199 1100 void bltzl (Register rs, Label& L){ bltzl (rs, target(L)); }
aoqi@199 1101 void bne (Register rs, Register rt, Label& L){ bne(rs, rt, target(L)); }
aoqi@199 1102 void bnel (Register rs, Register rt, Label& L){ bnel(rs, rt, target(L)); }
fujie@45 1103
aoqi@199 1104 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 1105 void daddi (Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddi_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1106 void daddiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(daddiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1107 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 1108 void ddiv (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddiv_op)); }
aoqi@199 1109 void ddivu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, ddivu_op)); }
fujie@41 1110
aoqi@199 1111 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 1112 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 1113
aoqi@199 1114 void movt (Register rd, Register rs) { emit_long(((int)rs->encoding() << 21) | (1 << 16) | ((int)rd->encoding() << 11) | movci_op); }
aoqi@199 1115 void movf (Register rd, Register rs) { emit_long(((int)rs->encoding() << 21) | ((int)rd->encoding() << 11) | movci_op); }
fujie@41 1116
fujie@256 1117 enum bshfl_ops {
fujie@256 1118 seb_op = 0x10,
fujie@256 1119 seh_op = 0x18
fujie@256 1120 };
fujie@256 1121 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 1122 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 1123
aoqi@6880 1124 void ext (Register rt, Register rs, int pos, int size) {
fujie@292 1125 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@292 1126 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@292 1127 guarantee((0 < pos + size) && (pos + size <= 32), "pos + size must be in (0, 32]");
fujie@292 1128
fujie@292 1129 int lsb = pos;
fujie@292 1130 int msbd = size - 1;
fujie@292 1131
aoqi@6880 1132 emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (msbd << 11) | (lsb << 6) | ext_op);
fujie@301 1133 }
fujie@301 1134
aoqi@6880 1135 void dext (Register rt, Register rs, int pos, int size) {
fujie@301 1136 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@301 1137 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@301 1138 guarantee((0 < pos + size) && (pos + size <= 63), "pos + size must be in (0, 63]");
fujie@301 1139
fujie@301 1140 int lsb = pos;
fujie@301 1141 int msbd = size - 1;
fujie@301 1142
aoqi@6880 1143 emit_long((special3_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | (msbd << 11) | (lsb << 6) | dext_op);
fujie@292 1144 }
fujie@292 1145
aoqi@6880 1146 void rotr (Register rd, Register rt, int sa) {
aoqi@6880 1147 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | srl_op);
fujie@315 1148 }
fujie@315 1149
aoqi@6880 1150 void drotr (Register rd, Register rt, int sa) {
aoqi@6880 1151 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | dsrl_op);
fujie@315 1152 }
fujie@315 1153
aoqi@6880 1154 void drotr32 (Register rd, Register rt, int sa) {
aoqi@6880 1155 emit_long((special_op << 26) | (1 << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (low(sa, 5) << 6) | dsrl32_op);
fujie@315 1156 }
fujie@315 1157
aoqi@6880 1158 void rotrv (Register rd, Register rt, Register rs) {
aoqi@6880 1159 emit_long((special_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (1 << 6) | srlv_op);
fujie@315 1160 }
fujie@315 1161
aoqi@6880 1162 void drotrv (Register rd, Register rt, Register rs) {
aoqi@6880 1163 emit_long((special_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | (1 << 6) | dsrlv_op);
fujie@315 1164 }
fujie@315 1165
aoqi@199 1166 void div (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, div_op)); }
aoqi@199 1167 void divu (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, divu_op)); }
aoqi@199 1168 void dmult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmult_op)); }
aoqi@199 1169 void dmultu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, dmultu_op)); }
fujie@408 1170 void dsll (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsll_op)); }
aoqi@199 1171 void dsllv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsllv_op)); }
fujie@408 1172 void dsll32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsll32_op)); }
fujie@408 1173 void dsra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsra_op)); }
aoqi@199 1174 void dsrav (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrav_op)); }
fujie@408 1175 void dsra32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsra32_op)); }
fujie@408 1176 void dsrl (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsrl_op)); }
aoqi@199 1177 void dsrlv (Register rd, Register rt, Register rs) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), dsrlv_op)); }
fujie@408 1178 void dsrl32(Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), dsrl32_op)); }
aoqi@199 1179 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 1180 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 1181
aoqi@199 1182 void b(int off) { beq(R0, R0, off); }
aoqi@199 1183 void b(address entry) { b(offset(entry)); }
aoqi@199 1184 void b(Label& L) { b(target(L)); }
aoqi@1 1185
aoqi@199 1186 void j(address entry);
aoqi@199 1187 void jal(address entry);
aoqi@1 1188
aoqi@199 1189 void jalr(Register rd, Register rs) { emit_long( ((int)rs->encoding()<<21) | ((int)rd->encoding()<<11) | jalr_op); has_delay_slot(); }
aoqi@199 1190 void jalr(Register rs) { jalr(RA, rs); }
aoqi@199 1191 void jalr() { jalr(T9); }
aoqi@1 1192
aoqi@199 1193 void jr(Register rs) { emit_long(((int)rs->encoding()<<21) | jr_op); has_delay_slot(); }
aoqi@199 1194
aoqi@199 1195 void lb (Register rt, Register base, int off) { emit_long(insn_ORRI(lb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1196 void lbu(Register rt, Register base, int off) { emit_long(insn_ORRI(lbu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1197 void ld (Register rt, Register base, int off) { emit_long(insn_ORRI(ld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1198 void ldl(Register rt, Register base, int off) { emit_long(insn_ORRI(ldl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1199 void ldr(Register rt, Register base, int off) { emit_long(insn_ORRI(ldr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1200 void lh (Register rt, Register base, int off) { emit_long(insn_ORRI(lh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1201 void lhu(Register rt, Register base, int off) { emit_long(insn_ORRI(lhu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1202 void ll (Register rt, Register base, int off) { emit_long(insn_ORRI(ll_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1203 void lld(Register rt, Register base, int off) { emit_long(insn_ORRI(lld_op, (int)base->encoding(), (int)rt->encoding(), off)); }
fujie@9263 1204 void lui(Register rt, int imm) { emit_long(insn_ORRI(lui_op, 0, (int)rt->encoding(), simm16(imm))); }
aoqi@199 1205 void lw (Register rt, Register base, int off) { emit_long(insn_ORRI(lw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1206 void lwl(Register rt, Register base, int off) { emit_long(insn_ORRI(lwl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1207 void lwr(Register rt, Register base, int off) { emit_long(insn_ORRI(lwr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1208 void lwu(Register rt, Register base, int off) { emit_long(insn_ORRI(lwu_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1209
aoqi@199 1210 void lb (Register rt, Address src);
aoqi@199 1211 void lbu(Register rt, Address src);
aoqi@199 1212 void ld (Register rt, Address src);
aoqi@199 1213 void ldl(Register rt, Address src);
aoqi@199 1214 void ldr(Register rt, Address src);
aoqi@199 1215 void lh (Register rt, Address src);
aoqi@199 1216 void lhu(Register rt, Address src);
aoqi@199 1217 void ll (Register rt, Address src);
aoqi@199 1218 void lld(Register rt, Address src);
aoqi@199 1219 void lw (Register rt, Address src);
aoqi@199 1220 void lwl(Register rt, Address src);
aoqi@199 1221 void lwr(Register rt, Address src);
aoqi@199 1222 void lwu(Register rt, Address src);
aoqi@199 1223 void lea(Register rt, Address src);
aoqi@199 1224 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 1225
aoqi@199 1226 void mfhi (Register rd) { emit_long( ((int)rd->encoding()<<11) | mfhi_op ); }
aoqi@199 1227 void mflo (Register rd) { emit_long( ((int)rd->encoding()<<11) | mflo_op ); }
aoqi@199 1228 void mthi (Register rs) { emit_long( ((int)rs->encoding()<<21) | mthi_op ); }
aoqi@199 1229 void mtlo (Register rs) { emit_long( ((int)rs->encoding()<<21) | mtlo_op ); }
fujie@318 1230
aoqi@199 1231 void mult (Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, mult_op)); }
aoqi@199 1232 void multu(Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), 0, multu_op)); }
aoqi@1 1233
aoqi@199 1234 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 1235
aoqi@199 1236 void orr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), or_op)); }
fujie@9263 1237 void ori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(ori_op, (int)rs->encoding(), (int)rt->encoding(), simm16(imm))); }
aoqi@199 1238
aoqi@199 1239 void sb (Register rt, Register base, int off) { emit_long(insn_ORRI(sb_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1240 void sc (Register rt, Register base, int off) { emit_long(insn_ORRI(sc_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1241 void scd (Register rt, Register base, int off) { emit_long(insn_ORRI(scd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1242 void sd (Register rt, Register base, int off) { emit_long(insn_ORRI(sd_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1243 void sdl (Register rt, Register base, int off) { emit_long(insn_ORRI(sdl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1244 void sdr (Register rt, Register base, int off) { emit_long(insn_ORRI(sdr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1245 void sh (Register rt, Register base, int off) { emit_long(insn_ORRI(sh_op, (int)base->encoding(), (int)rt->encoding(), off)); }
fujie@318 1246 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 1247 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 1248 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 1249 void slti (Register rt, Register rs, int imm) { emit_long(insn_ORRI(slti_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1250 void sltiu(Register rt, Register rs, int imm) { emit_long(insn_ORRI(sltiu_op, (int)rs->encoding(), (int)rt->encoding(), imm)); }
aoqi@199 1251 void sltu (Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), sltu_op)); }
fujie@408 1252 void sra (Register rd, Register rt , int sa) { emit_long(insn_RRSO((int)rt->encoding(), (int)rd->encoding(), low(sa, 5), sra_op)); }
aoqi@199 1253 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 1254 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 1255 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 1256
aoqi@1 1257 #ifndef _LP64
aoqi@199 1258 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 1259 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 1260 #else
aoqi@199 1261 void sub (Register rd, Register rs, Register rt) { dsub (rd, rs, rt); }
aoqi@199 1262 void subu (Register rd, Register rs, Register rt) { dsubu (rd, rs, rt); }
aoqi@199 1263 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 1264 #endif
aoqi@199 1265 void sw (Register rt, Register base, int off) { emit_long(insn_ORRI(sw_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1266 void swl (Register rt, Register base, int off) { emit_long(insn_ORRI(swl_op, (int)base->encoding(), (int)rt->encoding(), off)); }
aoqi@199 1267 void swr (Register rt, Register base, int off) { emit_long(insn_ORRI(swr_op, (int)base->encoding(), (int)rt->encoding(), off)); }
jiefu@9761 1268 void synci(Register base, int off) { emit_long(insn_ORRI(regimm_op, (int)base->encoding(), synci_op, off)); }
aoqi@199 1269 void sync () { emit_long(sync_op); }
aoqi@199 1270 void syscall(int code) { emit_long( (code<<6) | syscall_op ); }
aoqi@1 1271
aoqi@199 1272 void sb(Register rt, Address dst);
aoqi@199 1273 void sc(Register rt, Address dst);
aoqi@199 1274 void scd(Register rt, Address dst);
aoqi@199 1275 void sd(Register rt, Address dst);
aoqi@199 1276 void sdl(Register rt, Address dst);
aoqi@199 1277 void sdr(Register rt, Address dst);
aoqi@199 1278 void sh(Register rt, Address dst);
aoqi@199 1279 void sw(Register rt, Address dst);
aoqi@199 1280 void swl(Register rt, Address dst);
aoqi@199 1281 void swr(Register rt, Address dst);
aoqi@1 1282
aoqi@199 1283 void teq (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, teq_op)); }
aoqi@199 1284 void teqi (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), teqi_op, imm)); }
aoqi@199 1285 void tge (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tge_op)); }
aoqi@199 1286 void tgei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgei_op, imm)); }
aoqi@199 1287 void tgeiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgeiu_op, imm)); }
aoqi@199 1288 void tgeu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tgeu_op)); }
aoqi@199 1289 void tlt (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tlt_op)); }
aoqi@199 1290 void tlti (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tlti_op, imm)); }
aoqi@199 1291 void tltiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tltiu_op, imm)); }
aoqi@199 1292 void tltu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tltu_op)); }
aoqi@199 1293 void tne (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tne_op)); }
aoqi@199 1294 void tnei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tnei_op, imm)); }
aoqi@1 1295
aoqi@199 1296 void xorr(Register rd, Register rs, Register rt) { emit_long(insn_RRRO((int)rs->encoding(), (int)rt->encoding(), (int)rd->encoding(), xor_op)); }
fujie@9265 1297 void xori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(xori_op, (int)rs->encoding(), (int)rt->encoding(), simm16(imm))); }
aoqi@1 1298
aoqi@199 1299 void nop() { emit_long(0); }
aoqi@1 1300
aoqi@1 1301
fujie@195 1302
aoqi@199 1303 void ldc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(ldc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1304 void lwc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(lwc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1305 void ldc1(FloatRegister ft, Address src);
aoqi@199 1306 void lwc1(FloatRegister ft, Address src);
aoqi@1 1307
aoqi@199 1308 //COP0
aoqi@199 1309 void mfc0 (Register rt, Register rd) { emit_long(insn_COP0( mfc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1310 void dmfc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmfc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1311 // MFGC0, DMFGC0, MTGC0, DMTGC0 not implemented yet
aoqi@199 1312 void mtc0 (Register rt, Register rd) { emit_long(insn_COP0( mtc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1313 void dmtc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmtc0_op, (int)rt->encoding(), (int)rd->encoding())); }
aoqi@199 1314 //COP0 end
aoqi@1 1315
lifangyuan@125 1316
aoqi@199 1317 //COP1
aoqi@199 1318 void mfc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1 (mfc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1319 void dmfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmfc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1320 void cfc1 (Register rt, int fs) { emit_long(insn_COP1( cfc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1321 void mfhc1(Register rt, int fs) { emit_long(insn_COP1(mfhc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1322 void mtc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( mtc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1323 void dmtc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmtc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1324 void ctc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( ctc1_op, (int)rt->encoding(), (int)fs->encoding())); }
aoqi@199 1325 void ctc1 (Register rt, int fs) { emit_long(insn_COP1(ctc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1326 void mthc1(Register rt, int fs) { emit_long(insn_COP1(mthc1_op, (int)rt->encoding(), fs)); }
aoqi@199 1327
aoqi@199 1328 void bc1f (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcf_op, off)); has_delay_slot(); }
aoqi@199 1329 void bc1fl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcfl_op, off)); has_delay_slot(); }
aoqi@199 1330 void bc1t (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bct_op, off)); has_delay_slot(); }
aoqi@199 1331 void bc1tl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bctl_op, off)); has_delay_slot(); }
aoqi@199 1332
aoqi@199 1333 void bc1f (address entry) { bc1f(offset(entry)); }
aoqi@199 1334 void bc1fl(address entry) { bc1fl(offset(entry)); }
aoqi@199 1335 void bc1t (address entry) { bc1t(offset(entry)); }
aoqi@199 1336 void bc1tl(address entry) { bc1tl(offset(entry)); }
aoqi@199 1337
aoqi@199 1338 void bc1f (Label& L) { bc1f(target(L)); }
aoqi@199 1339 void bc1fl(Label& L) { bc1fl(target(L)); }
aoqi@199 1340 void bc1t (Label& L) { bc1t(target(L)); }
aoqi@199 1341 void bc1tl(Label& L) { bc1tl(target(L)); }
aoqi@199 1342
aoqi@199 1343 //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags.
aoqi@199 1344 #define INSN_SINGLE(r1, r2, r3, op) \
aoqi@199 1345 { emit_long(insn_F3RO(single_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1346 void add_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fadd_op)}
aoqi@199 1347 void sub_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fsub_op)}
aoqi@199 1348 void mul_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fmul_op)}
aoqi@199 1349 void div_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fdiv_op)}
aoqi@199 1350 void sqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fsqrt_op)}
aoqi@199 1351 void abs_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fabs_op)}
aoqi@199 1352 void mov_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fmov_op)}
aoqi@199 1353 void neg_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fneg_op)}
aoqi@199 1354 void round_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundl_op)}
aoqi@199 1355 void trunc_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncl_op)}
aoqi@199 1356 void ceil_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceill_op)}
aoqi@199 1357 void floor_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorl_op)}
aoqi@199 1358 void round_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundw_op)}
aoqi@199 1359 void trunc_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncw_op)}
aoqi@199 1360 void ceil_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceilw_op)}
aoqi@199 1361 void floor_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorw_op)}
aoqi@199 1362 //null
aoqi@396 1363 void movf_s(FloatRegister fs, FloatRegister fd, int cc = 0) {
aoqi@396 1364 assert(cc >= 0 && cc <= 7, "cc is 3 bits");
aoqi@396 1365 emit_long((cop1_op<<26) | (single_fmt<<21) | (cc<<18) | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );}
aoqi@396 1366 void movt_s(FloatRegister fs, FloatRegister fd, int cc = 0) {
aoqi@396 1367 assert(cc >= 0 && cc <= 7, "cc is 3 bits");
aoqi@396 1368 emit_long((cop1_op<<26) | (single_fmt<<21) | (cc<<18) | 1<<16 | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );}
aoqi@199 1369 void movz_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movz_f_op)}
aoqi@199 1370 void movn_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movn_f_op)}
aoqi@199 1371 //null
aoqi@199 1372 void recip_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frecip_op)}
aoqi@199 1373 void rsqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frsqrt_op)}
aoqi@199 1374 //null
aoqi@199 1375 void cvt_d_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtd_op)}
aoqi@199 1376 //null
aoqi@199 1377 void cvt_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtw_op)}
aoqi@199 1378 void cvt_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtl_op)}
aoqi@276 1379 void cvt_ps_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fcvtps_op)}
aoqi@199 1380 //null
aoqi@199 1381 void c_f_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, f_cond)}
aoqi@199 1382 void c_un_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, un_cond)}
aoqi@199 1383 void c_eq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, eq_cond)}
aoqi@199 1384 void c_ueq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ueq_cond)}
aoqi@199 1385 void c_olt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, olt_cond)}
aoqi@199 1386 void c_ult_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ult_cond)}
aoqi@199 1387 void c_ole_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ole_cond)}
aoqi@199 1388 void c_ule_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ule_cond)}
aoqi@199 1389 void c_sf_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, sf_cond)}
aoqi@199 1390 void c_ngle_s(FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngle_cond)}
aoqi@199 1391 void c_seq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, seq_cond)}
aoqi@199 1392 void c_ngl_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngl_cond)}
aoqi@199 1393 void c_lt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, lt_cond)}
aoqi@199 1394 void c_nge_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, nge_cond)}
aoqi@199 1395 void c_le_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, le_cond)}
aoqi@199 1396 void c_ngt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngt_cond)}
aoqi@199 1397
aoqi@199 1398 #undef INSN_SINGLE
aoqi@199 1399
aoqi@199 1400
aoqi@199 1401 //R0->encoding() is 0; INSN_DOUBLE is enclosed by {} for ctags.
aoqi@199 1402 #define INSN_DOUBLE(r1, r2, r3, op) \
aoqi@199 1403 { emit_long(insn_F3RO(double_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1404
aoqi@199 1405 void add_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fadd_op)}
aoqi@199 1406 void sub_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fsub_op)}
aoqi@199 1407 void mul_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fmul_op)}
aoqi@199 1408 void div_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fdiv_op)}
aoqi@199 1409 void sqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fsqrt_op)}
aoqi@199 1410 void abs_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fabs_op)}
aoqi@199 1411 void mov_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fmov_op)}
aoqi@199 1412 void neg_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fneg_op)}
aoqi@199 1413 void round_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundl_op)}
aoqi@199 1414 void trunc_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncl_op)}
aoqi@199 1415 void ceil_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceill_op)}
aoqi@199 1416 void floor_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorl_op)}
aoqi@199 1417 void round_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundw_op)}
aoqi@199 1418 void trunc_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncw_op)}
aoqi@199 1419 void ceil_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceilw_op)}
aoqi@199 1420 void floor_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorw_op)}
aoqi@199 1421 //null
aoqi@396 1422 void movf_d(FloatRegister fs, FloatRegister fd, int cc = 0) {
aoqi@396 1423 assert(cc >= 0 && cc <= 7, "cc is 3 bits");
aoqi@396 1424 emit_long((cop1_op<<26) | (double_fmt<<21) | (cc<<18) | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );}
aoqi@396 1425 void movt_d(FloatRegister fs, FloatRegister fd, int cc = 0) {
aoqi@396 1426 assert(cc >= 0 && cc <= 7, "cc is 3 bits");
aoqi@396 1427 emit_long((cop1_op<<26) | (double_fmt<<21) | (cc<<18) | 1<<16 | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );}
aoqi@199 1428 void movz_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movz_f_op)}
aoqi@199 1429 void movn_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movn_f_op)}
aoqi@199 1430 //null
aoqi@199 1431 void recip_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frecip_op)}
aoqi@199 1432 void rsqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frsqrt_op)}
aoqi@199 1433 //null
aoqi@199 1434 void cvt_s_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvts_op)}
aoqi@199 1435 void cvt_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtl_op)}
aoqi@199 1436 //null
aoqi@199 1437 void cvt_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtw_op)}
aoqi@199 1438 //null
aoqi@199 1439 void c_f_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, f_cond)}
aoqi@199 1440 void c_un_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, un_cond)}
aoqi@199 1441 void c_eq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, eq_cond)}
aoqi@199 1442 void c_ueq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ueq_cond)}
aoqi@199 1443 void c_olt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, olt_cond)}
aoqi@199 1444 void c_ult_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ult_cond)}
aoqi@199 1445 void c_ole_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ole_cond)}
aoqi@199 1446 void c_ule_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ule_cond)}
aoqi@199 1447 void c_sf_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, sf_cond)}
aoqi@199 1448 void c_ngle_d(FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngle_cond)}
aoqi@199 1449 void c_seq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, seq_cond)}
aoqi@199 1450 void c_ngl_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngl_cond)}
aoqi@199 1451 void c_lt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, lt_cond)}
aoqi@199 1452 void c_nge_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, nge_cond)}
aoqi@199 1453 void c_le_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, le_cond)}
aoqi@199 1454 void c_ngt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngt_cond)}
aoqi@199 1455
aoqi@199 1456 #undef INSN_DOUBLE
aoqi@199 1457
aoqi@199 1458
aoqi@199 1459 //null
aoqi@199 1460 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 1461 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 1462 //null
aoqi@199 1463 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 1464 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 1465 //null
aoqi@199 1466
aoqi@199 1467
aoqi@199 1468 //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags.
aoqi@199 1469 #define INSN_PS(r1, r2, r3, op) \
aoqi@199 1470 { emit_long(insn_F3RO(ps_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1471
aoqi@199 1472 void add_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fadd_op)}
aoqi@199 1473 void sub_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fsub_op)}
aoqi@199 1474 void mul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fmul_op)}
aoqi@199 1475 //null
aoqi@199 1476 void abs_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fabs_op)}
aoqi@199 1477 void mov_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fmov_op)}
aoqi@199 1478 void neg_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fneg_op)}
aoqi@199 1479 //null
aoqi@199 1480 //void movf_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movf_ps")}
aoqi@199 1481 //void movt_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movt_ps") }
aoqi@199 1482 void movz_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movz_f_op)}
aoqi@199 1483 void movn_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movn_f_op)}
aoqi@199 1484 //null
aoqi@199 1485 void cvt_s_pu (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvts_op)}
aoqi@199 1486 //null
aoqi@199 1487 void cvt_s_pl (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvtspl_op)}
aoqi@199 1488 //null
aoqi@199 1489 void pll_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpll_op)}
aoqi@199 1490 void plu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fplu_op)}
aoqi@199 1491 void pul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpul_op)}
aoqi@199 1492 void puu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpuu_op)}
aoqi@199 1493 void c_f_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, f_cond)}
aoqi@199 1494 void c_un_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, un_cond)}
aoqi@199 1495 void c_eq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, eq_cond)}
aoqi@199 1496 void c_ueq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ueq_cond)}
aoqi@199 1497 void c_olt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, olt_cond)}
aoqi@199 1498 void c_ult_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ult_cond)}
aoqi@199 1499 void c_ole_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ole_cond)}
aoqi@199 1500 void c_ule_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ule_cond)}
aoqi@199 1501 void c_sf_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, sf_cond)}
aoqi@199 1502 void c_ngle_ps(FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngle_cond)}
aoqi@199 1503 void c_seq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, seq_cond)}
aoqi@199 1504 void c_ngl_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngl_cond)}
aoqi@199 1505 void c_lt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, lt_cond)}
aoqi@199 1506 void c_nge_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, nge_cond)}
aoqi@199 1507 void c_le_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, le_cond)}
aoqi@199 1508 void c_ngt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngt_cond)}
aoqi@199 1509 //null
aoqi@199 1510 #undef INSN_PS
aoqi@199 1511 //COP1 end
aoqi@199 1512
aoqi@199 1513
aoqi@199 1514 //COP1X
aoqi@199 1515 //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags.
aoqi@199 1516 #define INSN_COP1X(r0, r1, r2, r3, op) \
aoqi@199 1517 { emit_long(insn_F3ROX((int)r0->encoding(), (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));}
aoqi@199 1518 void madd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_s_op) }
aoqi@199 1519 void madd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_d_op) }
aoqi@199 1520 void madd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, madd_ps_op) }
aoqi@199 1521 void msub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_s_op) }
aoqi@199 1522 void msub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_d_op) }
aoqi@199 1523 void msub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, msub_ps_op) }
aoqi@199 1524 void nmadd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_s_op) }
aoqi@199 1525 void nmadd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_d_op) }
aoqi@199 1526 void nmadd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmadd_ps_op) }
aoqi@199 1527 void nmsub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_s_op) }
aoqi@199 1528 void nmsub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_d_op) }
aoqi@199 1529 void nmsub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmsub_ps_op) }
aoqi@199 1530 #undef INSN_COP1X
aoqi@199 1531 //COP1X end
aoqi@199 1532
aoqi@199 1533 //SPECIAL2
aoqi@199 1534 //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags.
aoqi@199 1535 #define INSN_S2(op) \
aoqi@199 1536 { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | op);}
aoqi@199 1537
aoqi@363 1538 void madd (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | madd_op); }
aoqi@363 1539 void maddu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | maddu_op); }
aoqi@363 1540 void mul (Register rd, Register rs, Register rt) { INSN_S2(mul_op) }
aoqi@363 1541 void gsandn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x03_op) }
aoqi@363 1542 void msub (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msub_op); }
aoqi@363 1543 void msubu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msubu_op); }
aoqi@363 1544 void gsorn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x06_op) }
aoqi@199 1545
aoqi@199 1546 void gsmult (Register rd, Register rs, Register rt) { INSN_S2(gsmult_op) }
aoqi@199 1547 void gsdmult (Register rd, Register rs, Register rt) { INSN_S2(gsdmult_op) }
aoqi@199 1548 void gsmultu (Register rd, Register rs, Register rt) { INSN_S2(gsmultu_op) }
aoqi@199 1549 void gsdmultu(Register rd, Register rs, Register rt) { INSN_S2(gsdmultu_op)}
aoqi@199 1550 void gsdiv (Register rd, Register rs, Register rt) { INSN_S2(gsdiv_op) }
aoqi@199 1551 void gsddiv (Register rd, Register rs, Register rt) { INSN_S2(gsddiv_op) }
aoqi@199 1552 void gsdivu (Register rd, Register rs, Register rt) { INSN_S2(gsdivu_op) }
aoqi@199 1553 void gsddivu (Register rd, Register rs, Register rt) { INSN_S2(gsddivu_op) }
aoqi@199 1554 void gsmod (Register rd, Register rs, Register rt) { INSN_S2(gsmod_op) }
aoqi@199 1555 void gsdmod (Register rd, Register rs, Register rt) { INSN_S2(gsdmod_op) }
aoqi@199 1556 void gsmodu (Register rd, Register rs, Register rt) { INSN_S2(gsmodu_op) }
aoqi@199 1557 void gsdmodu (Register rd, Register rs, Register rt) { INSN_S2(gsdmodu_op) }
aoqi@199 1558 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 1559 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 1560 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 1561 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 1562 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 1563 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 1564 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 1565 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 1566
aoqi@199 1567 #undef INSN_S2
aoqi@199 1568
aoqi@199 1569 //SPECIAL3
aoqi@199 1570 /*
aoqi@199 1571 // FIXME
aoqi@199 1572 #define is_0_to_32(a, b) \
aoqi@199 1573 assert (a >= 0, " just a check"); \
aoqi@199 1574 assert (a <= 0, " just a check"); \
aoqi@199 1575 assert (b >= 0, " just a check"); \
aoqi@199 1576 assert (b <= 0, " just a check"); \
aoqi@199 1577 assert (a+b >= 0, " just a check"); \
aoqi@199 1578 assert (a+b <= 0, " just a check");
aoqi@199 1579 */
aoqi@199 1580 #define is_0_to_32(a, b)
aoqi@199 1581
aoqi@199 1582 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 1583 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 1584 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); }
aoqi@6880 1585 void dins (Register rt, Register rs, int pos, int size) {
fujie@294 1586 guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)");
fujie@294 1587 guarantee((0 < size) && (size <= 32), "size must be in (0, 32]");
fujie@294 1588 guarantee((0 < pos + size) && (pos + size <= 32), "pos + size must be in (0, 32]");
fujie@294 1589
aoqi@6880 1590 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 1591 }
aoqi@199 1592
aoqi@8015 1593 void repl_qb (Register rd, int const8) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | (low(const8, 8) << 16) | ((int)rd->encoding() << 11) | repl_qb_op << 6 | re1_op); }
aoqi@8015 1594 void replv_qb(Register rd, Register rt) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_qb_op << 6 | re1_op ); }
aoqi@8015 1595 void repl_ph (Register rd, int const10) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_ph_op << 6 | re1_op); }
aoqi@8015 1596 void replv_ph(Register rd, Register rt) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_ph_op << 6 | re1_op ); }
aoqi@199 1597
aoqi@8015 1598 void repl_ob (Register rd, int const8) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | (low(const8, 8) << 16) | ((int)rd->encoding() << 11) | repl_ob_op << 6 | re2_op); }
aoqi@8015 1599 void replv_ob(Register rd, Register rt) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_ob_op << 6 | re2_op ); }
aoqi@8015 1600 void repl_qh (Register rd, int const10) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_qh_op << 6 | re2_op); }
aoqi@8015 1601 void replv_qh(Register rd, Register rt) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_qh_op << 6 | re2_op ); }
aoqi@8015 1602 void repl_pw (Register rd, int const10) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | (low(const10, 10) << 16) | ((int)rd->encoding() << 11) | repl_pw_op << 6 | re2_op); }
aoqi@8015 1603 void replv_pw(Register rd, Register rt) { assert(VM_Version::supports_dsp(), ""); emit_long((special3_op << 26) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | replv_pw_op << 6 | re2_op ); }
aoqi@199 1604
aoqi@199 1605 void sdc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(sdc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1606 void sdc1(FloatRegister ft, Address dst);
aoqi@199 1607 void swc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(swc1_op, (int)base->encoding(), (int)ft->encoding(), off)); }
aoqi@199 1608 void swc1(FloatRegister ft, Address dst);
aoqi@199 1609
aoqi@199 1610
aoqi@199 1611 void int3();
aoqi@199 1612 static void print_instruction(int);
aoqi@199 1613 int patched_branch(int dest_pos, int inst, int inst_pos);
aoqi@199 1614 int branch_destination(int inst, int pos);
aoqi@199 1615
aoqi@9459 1616 // Loongson extension
aoqi@199 1617
aoqi@199 1618 // gssq/gslq/gssqc1/gslqc1: vAddr = sign_extend(offset << 4 ) + GPR[base]. Therefore, the off should be ">> 4".
jiangshaofeng@362 1619 void gslble(Register rt, Register base, Register bound) {
jiangshaofeng@362 1620 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslble_op);
jiangshaofeng@362 1621 }
jiangshaofeng@362 1622
jiangshaofeng@362 1623 void gslbgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1624 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslbgt_op);
jiangshaofeng@362 1625 }
jiangshaofeng@362 1626
jiangshaofeng@362 1627 void gslhle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1628 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhle_op);
jiangshaofeng@362 1629 }
jiangshaofeng@362 1630
jiangshaofeng@362 1631 void gslhgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1632 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhgt_op);
jiangshaofeng@362 1633 }
jiangshaofeng@362 1634
jiangshaofeng@362 1635 void gslwle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1636 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwle_op);
jiangshaofeng@362 1637 }
jiangshaofeng@362 1638
jiangshaofeng@362 1639 void gslwgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1640 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgt_op);
jiangshaofeng@362 1641 }
jiangshaofeng@362 1642
jiangshaofeng@362 1643 void gsldle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1644 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldle_op);
jiangshaofeng@362 1645 }
jiangshaofeng@362 1646
jiangshaofeng@362 1647 void gsldgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1648 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgt_op);
jiangshaofeng@362 1649 }
jiangshaofeng@362 1650
jiangshaofeng@362 1651 void gslwlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1652 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwlec1_op);
jiangshaofeng@362 1653 }
jiangshaofeng@362 1654
jiangshaofeng@362 1655 void gslwgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1656 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgtc1_op);
jiangshaofeng@362 1657 }
jiangshaofeng@362 1658
jiangshaofeng@362 1659 void gsldlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1660 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldlec1_op);
jiangshaofeng@362 1661 }
jiangshaofeng@362 1662
jiangshaofeng@362 1663 void gsldgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1664 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgtc1_op);
jiangshaofeng@362 1665 }
jiangshaofeng@362 1666
lifangyuan@125 1667 void gslq(Register rq, Register rt, Register base, int off) {
wangxue@9457 1668 assert(!(off & 0xF), "gslq: the low 4 bits of off must be 0");
lifangyuan@125 1669 off = off >> 4;
lifangyuan@125 1670 assert(is_simm(off, 9),"gslq: off exceeds 9 bits");
lifangyuan@125 1671 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 1672 }
lifangyuan@125 1673
jingtian@9455 1674 void gslqc1(FloatRegister rq, FloatRegister rt, Register base, int off) {
wangxue@9457 1675 assert(!(off & 0xF), "gslqc1: the low 4 bits of off must be 0");
jingtian@9455 1676 off = off >> 4;
jingtian@9455 1677 assert(is_simm(off, 9),"gslqc1: off exceeds 9 bits");
jingtian@9455 1678 emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | 1 << 15 | (low(off, 9) << 6) | gslq_op | (int)rq->encoding() );
jingtian@9455 1679 }
jingtian@9455 1680
jiangshaofeng@362 1681 void gssble(Register rt, Register base, Register bound) {
jiangshaofeng@362 1682 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssble_op);
jiangshaofeng@362 1683 }
jiangshaofeng@362 1684
jiangshaofeng@362 1685 void gssbgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1686 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssbgt_op);
jiangshaofeng@362 1687 }
jiangshaofeng@362 1688
jiangshaofeng@362 1689 void gsshle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1690 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshle_op);
jiangshaofeng@362 1691 }
jiangshaofeng@362 1692
jiangshaofeng@362 1693 void gsshgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1694 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshgt_op);
jiangshaofeng@362 1695 }
jiangshaofeng@362 1696
jiangshaofeng@362 1697 void gsswle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1698 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswle_op);
jiangshaofeng@362 1699 }
jiangshaofeng@362 1700
jiangshaofeng@362 1701 void gsswgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1702 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgt_op);
jiangshaofeng@362 1703 }
jiangshaofeng@362 1704
jiangshaofeng@362 1705 void gssdle(Register rt, Register base, Register bound) {
jiangshaofeng@362 1706 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdle_op);
jiangshaofeng@362 1707 }
jiangshaofeng@362 1708
jiangshaofeng@362 1709 void gssdgt(Register rt, Register base, Register bound) {
jiangshaofeng@362 1710 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgt_op);
jiangshaofeng@362 1711 }
jiangshaofeng@362 1712
jiangshaofeng@362 1713 void gsswlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1714 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswlec1_op);
jiangshaofeng@362 1715 }
jiangshaofeng@362 1716
jiangshaofeng@362 1717 void gsswgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1718 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgtc1_op);
jiangshaofeng@362 1719 }
jiangshaofeng@362 1720
jiangshaofeng@362 1721 void gssdlec1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1722 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdlec1_op);
jiangshaofeng@362 1723 }
jiangshaofeng@362 1724
jiangshaofeng@362 1725 void gssdgtc1(FloatRegister rt, Register base, Register bound) {
jiangshaofeng@362 1726 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgtc1_op);
jiangshaofeng@362 1727 }
jiangshaofeng@362 1728
lifangyuan@125 1729 void gssq(Register rq, Register rt, Register base, int off) {
wangxue@9457 1730 assert(!(off & 0xF), "gssq: the low 4 bits of off must be 0");
lifangyuan@125 1731 off = off >> 4;
lifangyuan@125 1732 assert(is_simm(off, 9),"gssq: off exceeds 9 bits");
lifangyuan@125 1733 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 1734 }
lifangyuan@125 1735
jingtian@9455 1736 void gssqc1(FloatRegister rq, FloatRegister rt, Register base, int off) {
wangxue@9457 1737 assert(!(off & 0xF), "gssqc1: the low 4 bits of off must be 0");
jingtian@9455 1738 off = off >> 4;
jingtian@9455 1739 assert(is_simm(off, 9),"gssqc1: off exceeds 9 bits");
jingtian@9455 1740 emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | 1 << 15 | (low(off, 9) << 6) | gssq_op | (int)rq->encoding() );
jingtian@9455 1741 }
jingtian@9455 1742
aoqi@199 1743 //LDC2 & SDC2
aoqi@199 1744 #define INSN(OPS, OP) \
aoqi@199 1745 assert(is_simm(off, 8), "NAME: off exceeds 8 bits"); \
aoqi@9644 1746 assert(UseLEXT1, "check UseLEXT1"); \
aoqi@199 1747 emit_long( (OPS << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | \
aoqi@199 1748 ((int)index->encoding() << 11) | (low(off, 8) << 3) | OP);
fujie@75 1749
aoqi@199 1750 #define INSN_LDC2(NAME, op) \
aoqi@199 1751 void NAME(Register rt, Register base, Register index, int off) { \
aoqi@199 1752 INSN(gs_ldc2_op, op) \
aoqi@199 1753 }
aoqi@1 1754
aoqi@199 1755 #define INSN_LDC2_F(NAME, op) \
aoqi@199 1756 void NAME(FloatRegister rt, Register base, Register index, int off) { \
aoqi@199 1757 INSN(gs_ldc2_op, op) \
aoqi@199 1758 }
aoqi@1 1759
aoqi@199 1760 #define INSN_SDC2(NAME, op) \
aoqi@199 1761 void NAME(Register rt, Register base, Register index, int off) { \
aoqi@199 1762 INSN(gs_sdc2_op, op) \
aoqi@199 1763 }
fujie@67 1764
aoqi@199 1765 #define INSN_SDC2_F(NAME, op) \
aoqi@199 1766 void NAME(FloatRegister rt, Register base, Register index, int off) { \
aoqi@199 1767 INSN(gs_sdc2_op, op) \
aoqi@199 1768 }
fujie@67 1769
aoqi@199 1770 /*
aoqi@199 1771 void gslbx(Register rt, Register base, Register index, int off) {
aoqi@199 1772 assert(is_simm(off, 8), "gslbx: off exceeds 8 bits");
aoqi@9644 1773 assert(UseLEXT1, "check UseLEXT1");
aoqi@199 1774 emit_long( (gs_ldc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) |
aoqi@199 1775 ((int)index->encoding() << 11) | (low(off, 8) << 3) | gslbx_op);
aoqi@199 1776 void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op);}
fujie@76 1777
aoqi@199 1778 INSN_LDC2(gslbx, gslbx_op)
aoqi@199 1779 INSN_LDC2(gslhx, gslhx_op)
aoqi@199 1780 INSN_LDC2(gslwx, gslwx_op)
aoqi@199 1781 INSN_LDC2(gsldx, gsldx_op)
aoqi@199 1782 INSN_LDC2_F(gslwxc1, gslwxc1_op)
aoqi@199 1783 INSN_LDC2_F(gsldxc1, gsldxc1_op)
fujie@76 1784
aoqi@199 1785 INSN_SDC2(gssbx, gssbx_op)
aoqi@199 1786 INSN_SDC2(gsshx, gsshx_op)
aoqi@199 1787 INSN_SDC2(gsswx, gsswx_op)
aoqi@199 1788 INSN_SDC2(gssdx, gssdx_op)
aoqi@199 1789 INSN_SDC2_F(gsswxc1, gsswxc1_op)
aoqi@199 1790 INSN_SDC2_F(gssdxc1, gssdxc1_op)
aoqi@199 1791 */
aoqi@199 1792 void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op) }
aoqi@199 1793 void gslhx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslhx_op) }
aoqi@199 1794 void gslwx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwx_op) }
aoqi@199 1795 void gsldx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldx_op) }
aoqi@199 1796 void gslwxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwxc1_op) }
aoqi@199 1797 void gsldxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldxc1_op) }
fujie@65 1798
aoqi@199 1799 void gssbx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssbx_op) }
aoqi@199 1800 void gsshx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsshx_op) }
aoqi@199 1801 void gsswx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswx_op) }
aoqi@199 1802 void gssdx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdx_op) }
aoqi@199 1803 void gsswxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswxc1_op) }
aoqi@199 1804 void gssdxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdxc1_op) }
fujie@65 1805
aoqi@199 1806 #undef INSN
aoqi@199 1807 #undef INSN_LDC2
aoqi@199 1808 #undef INSN_LDC2_F
aoqi@199 1809 #undef INSN_SDC2
aoqi@199 1810 #undef INSN_SDC2_F
fujie@66 1811
aoqi@9644 1812 // cpucfg on Loongson CPUs above 3A4000
aoqi@9644 1813 void cpucfg(Register rd, Register rs) { emit_long((gs_lwc2_op << 26) | ((int)rs->encoding() << 21) | (0b01000 << 16) | ((int)rd->encoding() << 11) | ( 0b00100 << 6) | 0b011000);}
aoqi@9644 1814
fujie@66 1815
aoqi@1 1816 public:
aoqi@199 1817 // Creation
aoqi@199 1818 Assembler(CodeBuffer* code) : AbstractAssembler(code) {
aoqi@1 1819 #ifdef CHECK_DELAY
aoqi@199 1820 delay_state = no_delay;
aoqi@1 1821 #endif
aoqi@199 1822 }
aoqi@1 1823
aoqi@1 1824 // Decoding
aoqi@1 1825 static address locate_operand(address inst, WhichOperand which);
aoqi@1 1826 static address locate_next_instruction(address inst);
aoqi@1 1827 };
aoqi@1 1828
aoqi@1 1829
aoqi@1 1830
aoqi@1 1831 #endif // CPU_MIPS_VM_ASSEMBLER_MIPS_HPP

mercurial