Mon, 18 Nov 2019 10:41:48 +0800
#10052 Backport of #9904 compiler/floatingpoint/TestFloatSyncJNIArgs.java failed
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)); } |
aoqi@199 | 1268 | void sync () { emit_long(sync_op); } |
aoqi@199 | 1269 | void syscall(int code) { emit_long( (code<<6) | syscall_op ); } |
aoqi@1 | 1270 | |
aoqi@199 | 1271 | void sb(Register rt, Address dst); |
aoqi@199 | 1272 | void sc(Register rt, Address dst); |
aoqi@199 | 1273 | void scd(Register rt, Address dst); |
aoqi@199 | 1274 | void sd(Register rt, Address dst); |
aoqi@199 | 1275 | void sdl(Register rt, Address dst); |
aoqi@199 | 1276 | void sdr(Register rt, Address dst); |
aoqi@199 | 1277 | void sh(Register rt, Address dst); |
aoqi@199 | 1278 | void sw(Register rt, Address dst); |
aoqi@199 | 1279 | void swl(Register rt, Address dst); |
aoqi@199 | 1280 | void swr(Register rt, Address dst); |
aoqi@1 | 1281 | |
aoqi@199 | 1282 | void teq (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, teq_op)); } |
aoqi@199 | 1283 | void teqi (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), teqi_op, imm)); } |
aoqi@199 | 1284 | void tge (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tge_op)); } |
aoqi@199 | 1285 | void tgei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgei_op, imm)); } |
aoqi@199 | 1286 | void tgeiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tgeiu_op, imm)); } |
aoqi@199 | 1287 | void tgeu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tgeu_op)); } |
aoqi@199 | 1288 | void tlt (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tlt_op)); } |
aoqi@199 | 1289 | void tlti (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tlti_op, imm)); } |
aoqi@199 | 1290 | void tltiu(Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tltiu_op, imm)); } |
aoqi@199 | 1291 | void tltu (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tltu_op)); } |
aoqi@199 | 1292 | void tne (Register rs, Register rt, int code) { emit_long(insn_RRCO((int)rs->encoding(), (int)rt->encoding(), code, tne_op)); } |
aoqi@199 | 1293 | void tnei (Register rs, int imm) { emit_long(insn_ORRI(regimm_op, (int)rs->encoding(), tnei_op, imm)); } |
aoqi@1 | 1294 | |
aoqi@199 | 1295 | 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 | 1296 | void xori(Register rt, Register rs, int imm) { emit_long(insn_ORRI(xori_op, (int)rs->encoding(), (int)rt->encoding(), simm16(imm))); } |
aoqi@1 | 1297 | |
aoqi@199 | 1298 | void nop() { emit_long(0); } |
aoqi@1 | 1299 | |
aoqi@1 | 1300 | |
fujie@195 | 1301 | |
aoqi@199 | 1302 | void ldc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(ldc1_op, (int)base->encoding(), (int)ft->encoding(), off)); } |
aoqi@199 | 1303 | void lwc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(lwc1_op, (int)base->encoding(), (int)ft->encoding(), off)); } |
aoqi@199 | 1304 | void ldc1(FloatRegister ft, Address src); |
aoqi@199 | 1305 | void lwc1(FloatRegister ft, Address src); |
aoqi@1 | 1306 | |
aoqi@199 | 1307 | //COP0 |
aoqi@199 | 1308 | void mfc0 (Register rt, Register rd) { emit_long(insn_COP0( mfc0_op, (int)rt->encoding(), (int)rd->encoding())); } |
aoqi@199 | 1309 | void dmfc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmfc0_op, (int)rt->encoding(), (int)rd->encoding())); } |
aoqi@199 | 1310 | // MFGC0, DMFGC0, MTGC0, DMTGC0 not implemented yet |
aoqi@199 | 1311 | void mtc0 (Register rt, Register rd) { emit_long(insn_COP0( mtc0_op, (int)rt->encoding(), (int)rd->encoding())); } |
aoqi@199 | 1312 | void dmtc0 (Register rt, FloatRegister rd) { emit_long(insn_COP0(dmtc0_op, (int)rt->encoding(), (int)rd->encoding())); } |
aoqi@199 | 1313 | //COP0 end |
aoqi@1 | 1314 | |
lifangyuan@125 | 1315 | |
aoqi@199 | 1316 | //COP1 |
aoqi@199 | 1317 | void mfc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1 (mfc1_op, (int)rt->encoding(), (int)fs->encoding())); } |
aoqi@199 | 1318 | void dmfc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmfc1_op, (int)rt->encoding(), (int)fs->encoding())); } |
aoqi@199 | 1319 | void cfc1 (Register rt, int fs) { emit_long(insn_COP1( cfc1_op, (int)rt->encoding(), fs)); } |
aoqi@199 | 1320 | void mfhc1(Register rt, int fs) { emit_long(insn_COP1(mfhc1_op, (int)rt->encoding(), fs)); } |
aoqi@199 | 1321 | void mtc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( mtc1_op, (int)rt->encoding(), (int)fs->encoding())); } |
aoqi@199 | 1322 | void dmtc1(Register rt, FloatRegister fs) { emit_long(insn_COP1(dmtc1_op, (int)rt->encoding(), (int)fs->encoding())); } |
aoqi@199 | 1323 | void ctc1 (Register rt, FloatRegister fs) { emit_long(insn_COP1( ctc1_op, (int)rt->encoding(), (int)fs->encoding())); } |
aoqi@199 | 1324 | void ctc1 (Register rt, int fs) { emit_long(insn_COP1(ctc1_op, (int)rt->encoding(), fs)); } |
aoqi@199 | 1325 | void mthc1(Register rt, int fs) { emit_long(insn_COP1(mthc1_op, (int)rt->encoding(), fs)); } |
aoqi@199 | 1326 | |
aoqi@199 | 1327 | void bc1f (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcf_op, off)); has_delay_slot(); } |
aoqi@199 | 1328 | void bc1fl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bcfl_op, off)); has_delay_slot(); } |
aoqi@199 | 1329 | void bc1t (int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bct_op, off)); has_delay_slot(); } |
aoqi@199 | 1330 | void bc1tl(int off) { emit_long(insn_ORRI(cop1_op, bc1f_op, bctl_op, off)); has_delay_slot(); } |
aoqi@199 | 1331 | |
aoqi@199 | 1332 | void bc1f (address entry) { bc1f(offset(entry)); } |
aoqi@199 | 1333 | void bc1fl(address entry) { bc1fl(offset(entry)); } |
aoqi@199 | 1334 | void bc1t (address entry) { bc1t(offset(entry)); } |
aoqi@199 | 1335 | void bc1tl(address entry) { bc1tl(offset(entry)); } |
aoqi@199 | 1336 | |
aoqi@199 | 1337 | void bc1f (Label& L) { bc1f(target(L)); } |
aoqi@199 | 1338 | void bc1fl(Label& L) { bc1fl(target(L)); } |
aoqi@199 | 1339 | void bc1t (Label& L) { bc1t(target(L)); } |
aoqi@199 | 1340 | void bc1tl(Label& L) { bc1tl(target(L)); } |
aoqi@199 | 1341 | |
aoqi@199 | 1342 | //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags. |
aoqi@199 | 1343 | #define INSN_SINGLE(r1, r2, r3, op) \ |
aoqi@199 | 1344 | { emit_long(insn_F3RO(single_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));} |
aoqi@199 | 1345 | void add_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fadd_op)} |
aoqi@199 | 1346 | void sub_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fsub_op)} |
aoqi@199 | 1347 | void mul_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fmul_op)} |
aoqi@199 | 1348 | void div_s (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fdiv_op)} |
aoqi@199 | 1349 | void sqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fsqrt_op)} |
aoqi@199 | 1350 | void abs_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fabs_op)} |
aoqi@199 | 1351 | void mov_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fmov_op)} |
aoqi@199 | 1352 | void neg_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fneg_op)} |
aoqi@199 | 1353 | void round_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundl_op)} |
aoqi@199 | 1354 | void trunc_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncl_op)} |
aoqi@199 | 1355 | void ceil_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceill_op)} |
aoqi@199 | 1356 | void floor_l_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorl_op)} |
aoqi@199 | 1357 | void round_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, froundw_op)} |
aoqi@199 | 1358 | void trunc_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ftruncw_op)} |
aoqi@199 | 1359 | void ceil_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fceilw_op)} |
aoqi@199 | 1360 | void floor_w_s(FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, ffloorw_op)} |
aoqi@199 | 1361 | //null |
aoqi@396 | 1362 | void movf_s(FloatRegister fs, FloatRegister fd, int cc = 0) { |
aoqi@396 | 1363 | assert(cc >= 0 && cc <= 7, "cc is 3 bits"); |
aoqi@396 | 1364 | emit_long((cop1_op<<26) | (single_fmt<<21) | (cc<<18) | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );} |
aoqi@396 | 1365 | void movt_s(FloatRegister fs, FloatRegister fd, int cc = 0) { |
aoqi@396 | 1366 | assert(cc >= 0 && cc <= 7, "cc is 3 bits"); |
aoqi@396 | 1367 | 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 | 1368 | void movz_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movz_f_op)} |
aoqi@199 | 1369 | void movn_s (FloatRegister fd, FloatRegister fs, Register rt) {INSN_SINGLE(rt, fs, fd, movn_f_op)} |
aoqi@199 | 1370 | //null |
aoqi@199 | 1371 | void recip_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frecip_op)} |
aoqi@199 | 1372 | void rsqrt_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, frsqrt_op)} |
aoqi@199 | 1373 | //null |
aoqi@199 | 1374 | void cvt_d_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtd_op)} |
aoqi@199 | 1375 | //null |
aoqi@199 | 1376 | void cvt_w_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtw_op)} |
aoqi@199 | 1377 | void cvt_l_s (FloatRegister fd, FloatRegister fs) {INSN_SINGLE(R0, fs, fd, fcvtl_op)} |
aoqi@276 | 1378 | void cvt_ps_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, fd, fcvtps_op)} |
aoqi@199 | 1379 | //null |
aoqi@199 | 1380 | void c_f_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, f_cond)} |
aoqi@199 | 1381 | void c_un_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, un_cond)} |
aoqi@199 | 1382 | void c_eq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, eq_cond)} |
aoqi@199 | 1383 | void c_ueq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ueq_cond)} |
aoqi@199 | 1384 | void c_olt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, olt_cond)} |
aoqi@199 | 1385 | void c_ult_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ult_cond)} |
aoqi@199 | 1386 | void c_ole_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ole_cond)} |
aoqi@199 | 1387 | void c_ule_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ule_cond)} |
aoqi@199 | 1388 | void c_sf_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, sf_cond)} |
aoqi@199 | 1389 | void c_ngle_s(FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngle_cond)} |
aoqi@199 | 1390 | void c_seq_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, seq_cond)} |
aoqi@199 | 1391 | void c_ngl_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngl_cond)} |
aoqi@199 | 1392 | void c_lt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, lt_cond)} |
aoqi@199 | 1393 | void c_nge_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, nge_cond)} |
aoqi@199 | 1394 | void c_le_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, le_cond)} |
aoqi@199 | 1395 | void c_ngt_s (FloatRegister fs, FloatRegister ft) {INSN_SINGLE(ft, fs, R0, ngt_cond)} |
aoqi@199 | 1396 | |
aoqi@199 | 1397 | #undef INSN_SINGLE |
aoqi@199 | 1398 | |
aoqi@199 | 1399 | |
aoqi@199 | 1400 | //R0->encoding() is 0; INSN_DOUBLE is enclosed by {} for ctags. |
aoqi@199 | 1401 | #define INSN_DOUBLE(r1, r2, r3, op) \ |
aoqi@199 | 1402 | { emit_long(insn_F3RO(double_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));} |
aoqi@199 | 1403 | |
aoqi@199 | 1404 | void add_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fadd_op)} |
aoqi@199 | 1405 | void sub_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fsub_op)} |
aoqi@199 | 1406 | void mul_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fmul_op)} |
aoqi@199 | 1407 | void div_d (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, fd, fdiv_op)} |
aoqi@199 | 1408 | void sqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fsqrt_op)} |
aoqi@199 | 1409 | void abs_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fabs_op)} |
aoqi@199 | 1410 | void mov_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fmov_op)} |
aoqi@199 | 1411 | void neg_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fneg_op)} |
aoqi@199 | 1412 | void round_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundl_op)} |
aoqi@199 | 1413 | void trunc_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncl_op)} |
aoqi@199 | 1414 | void ceil_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceill_op)} |
aoqi@199 | 1415 | void floor_l_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorl_op)} |
aoqi@199 | 1416 | void round_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, froundw_op)} |
aoqi@199 | 1417 | void trunc_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ftruncw_op)} |
aoqi@199 | 1418 | void ceil_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fceilw_op)} |
aoqi@199 | 1419 | void floor_w_d(FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, ffloorw_op)} |
aoqi@199 | 1420 | //null |
aoqi@396 | 1421 | void movf_d(FloatRegister fs, FloatRegister fd, int cc = 0) { |
aoqi@396 | 1422 | assert(cc >= 0 && cc <= 7, "cc is 3 bits"); |
aoqi@396 | 1423 | emit_long((cop1_op<<26) | (double_fmt<<21) | (cc<<18) | ((int)fs->encoding()<<11) | ((int)fd->encoding()<<6) | movf_f_op );} |
aoqi@396 | 1424 | void movt_d(FloatRegister fs, FloatRegister fd, int cc = 0) { |
aoqi@396 | 1425 | assert(cc >= 0 && cc <= 7, "cc is 3 bits"); |
aoqi@396 | 1426 | 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 | 1427 | void movz_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movz_f_op)} |
aoqi@199 | 1428 | void movn_d (FloatRegister fd, FloatRegister fs, Register rt) {INSN_DOUBLE(rt, fs, fd, movn_f_op)} |
aoqi@199 | 1429 | //null |
aoqi@199 | 1430 | void recip_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frecip_op)} |
aoqi@199 | 1431 | void rsqrt_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, frsqrt_op)} |
aoqi@199 | 1432 | //null |
aoqi@199 | 1433 | void cvt_s_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvts_op)} |
aoqi@199 | 1434 | void cvt_l_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtl_op)} |
aoqi@199 | 1435 | //null |
aoqi@199 | 1436 | void cvt_w_d (FloatRegister fd, FloatRegister fs) {INSN_DOUBLE(R0, fs, fd, fcvtw_op)} |
aoqi@199 | 1437 | //null |
aoqi@199 | 1438 | void c_f_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, f_cond)} |
aoqi@199 | 1439 | void c_un_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, un_cond)} |
aoqi@199 | 1440 | void c_eq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, eq_cond)} |
aoqi@199 | 1441 | void c_ueq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ueq_cond)} |
aoqi@199 | 1442 | void c_olt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, olt_cond)} |
aoqi@199 | 1443 | void c_ult_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ult_cond)} |
aoqi@199 | 1444 | void c_ole_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ole_cond)} |
aoqi@199 | 1445 | void c_ule_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ule_cond)} |
aoqi@199 | 1446 | void c_sf_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, sf_cond)} |
aoqi@199 | 1447 | void c_ngle_d(FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngle_cond)} |
aoqi@199 | 1448 | void c_seq_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, seq_cond)} |
aoqi@199 | 1449 | void c_ngl_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngl_cond)} |
aoqi@199 | 1450 | void c_lt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, lt_cond)} |
aoqi@199 | 1451 | void c_nge_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, nge_cond)} |
aoqi@199 | 1452 | void c_le_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, le_cond)} |
aoqi@199 | 1453 | void c_ngt_d (FloatRegister fs, FloatRegister ft) {INSN_DOUBLE(ft, fs, R0, ngt_cond)} |
aoqi@199 | 1454 | |
aoqi@199 | 1455 | #undef INSN_DOUBLE |
aoqi@199 | 1456 | |
aoqi@199 | 1457 | |
aoqi@199 | 1458 | //null |
aoqi@199 | 1459 | 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 | 1460 | 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 | 1461 | //null |
aoqi@199 | 1462 | 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 | 1463 | 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 | 1464 | //null |
aoqi@199 | 1465 | |
aoqi@199 | 1466 | |
aoqi@199 | 1467 | //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags. |
aoqi@199 | 1468 | #define INSN_PS(r1, r2, r3, op) \ |
aoqi@199 | 1469 | { emit_long(insn_F3RO(ps_fmt, (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));} |
aoqi@199 | 1470 | |
aoqi@199 | 1471 | void add_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fadd_op)} |
aoqi@199 | 1472 | void sub_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fsub_op)} |
aoqi@199 | 1473 | void mul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fmul_op)} |
aoqi@199 | 1474 | //null |
aoqi@199 | 1475 | void abs_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fabs_op)} |
aoqi@199 | 1476 | void mov_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fmov_op)} |
aoqi@199 | 1477 | void neg_ps (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fneg_op)} |
aoqi@199 | 1478 | //null |
aoqi@199 | 1479 | //void movf_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movf_ps")} |
aoqi@199 | 1480 | //void movt_ps(FloatRegister rd, FloatRegister rs, FPConditionCode cc) { unimplemented(" movt_ps") } |
aoqi@199 | 1481 | void movz_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movz_f_op)} |
aoqi@199 | 1482 | void movn_ps (FloatRegister fd, FloatRegister fs, Register rt) {INSN_PS(rt, fs, fd, movn_f_op)} |
aoqi@199 | 1483 | //null |
aoqi@199 | 1484 | void cvt_s_pu (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvts_op)} |
aoqi@199 | 1485 | //null |
aoqi@199 | 1486 | void cvt_s_pl (FloatRegister fd, FloatRegister fs) {INSN_PS(R0, fs, fd, fcvtspl_op)} |
aoqi@199 | 1487 | //null |
aoqi@199 | 1488 | void pll_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpll_op)} |
aoqi@199 | 1489 | void plu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fplu_op)} |
aoqi@199 | 1490 | void pul_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpul_op)} |
aoqi@199 | 1491 | void puu_ps (FloatRegister fd, FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, fd, fpuu_op)} |
aoqi@199 | 1492 | void c_f_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, f_cond)} |
aoqi@199 | 1493 | void c_un_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, un_cond)} |
aoqi@199 | 1494 | void c_eq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, eq_cond)} |
aoqi@199 | 1495 | void c_ueq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ueq_cond)} |
aoqi@199 | 1496 | void c_olt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, olt_cond)} |
aoqi@199 | 1497 | void c_ult_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ult_cond)} |
aoqi@199 | 1498 | void c_ole_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ole_cond)} |
aoqi@199 | 1499 | void c_ule_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ule_cond)} |
aoqi@199 | 1500 | void c_sf_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, sf_cond)} |
aoqi@199 | 1501 | void c_ngle_ps(FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngle_cond)} |
aoqi@199 | 1502 | void c_seq_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, seq_cond)} |
aoqi@199 | 1503 | void c_ngl_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngl_cond)} |
aoqi@199 | 1504 | void c_lt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, lt_cond)} |
aoqi@199 | 1505 | void c_nge_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, nge_cond)} |
aoqi@199 | 1506 | void c_le_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, le_cond)} |
aoqi@199 | 1507 | void c_ngt_ps (FloatRegister fs, FloatRegister ft) {INSN_PS(ft, fs, R0, ngt_cond)} |
aoqi@199 | 1508 | //null |
aoqi@199 | 1509 | #undef INSN_PS |
aoqi@199 | 1510 | //COP1 end |
aoqi@199 | 1511 | |
aoqi@199 | 1512 | |
aoqi@199 | 1513 | //COP1X |
aoqi@199 | 1514 | //R0->encoding() is 0; INSN_SINGLE is enclosed by {} for ctags. |
aoqi@199 | 1515 | #define INSN_COP1X(r0, r1, r2, r3, op) \ |
aoqi@199 | 1516 | { emit_long(insn_F3ROX((int)r0->encoding(), (int)r1->encoding(), (int)r2->encoding(), (int)r3->encoding(), op));} |
aoqi@199 | 1517 | void madd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_s_op) } |
aoqi@199 | 1518 | void madd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, madd_d_op) } |
aoqi@199 | 1519 | void madd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, madd_ps_op) } |
aoqi@199 | 1520 | void msub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_s_op) } |
aoqi@199 | 1521 | void msub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, msub_d_op) } |
aoqi@199 | 1522 | void msub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, msub_ps_op) } |
aoqi@199 | 1523 | void nmadd_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_s_op) } |
aoqi@199 | 1524 | void nmadd_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmadd_d_op) } |
aoqi@199 | 1525 | void nmadd_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmadd_ps_op) } |
aoqi@199 | 1526 | void nmsub_s(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_s_op) } |
aoqi@199 | 1527 | void nmsub_d(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft) {INSN_COP1X(fr, ft, fs, fd, nmsub_d_op) } |
aoqi@199 | 1528 | void nmsub_ps(FloatRegister fd, FloatRegister fr, FloatRegister fs, FloatRegister ft){INSN_COP1X(fr, ft, fs, fd, nmsub_ps_op) } |
aoqi@199 | 1529 | #undef INSN_COP1X |
aoqi@199 | 1530 | //COP1X end |
aoqi@199 | 1531 | |
aoqi@199 | 1532 | //SPECIAL2 |
aoqi@199 | 1533 | //R0->encoding() is 0; INSN_PS is enclosed by {} for ctags. |
aoqi@199 | 1534 | #define INSN_S2(op) \ |
aoqi@199 | 1535 | { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)rd->encoding() << 11) | op);} |
aoqi@199 | 1536 | |
aoqi@363 | 1537 | void madd (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | madd_op); } |
aoqi@363 | 1538 | void maddu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | maddu_op); } |
aoqi@363 | 1539 | void mul (Register rd, Register rs, Register rt) { INSN_S2(mul_op) } |
aoqi@363 | 1540 | void gsandn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x03_op) } |
aoqi@363 | 1541 | void msub (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msub_op); } |
aoqi@363 | 1542 | void msubu (Register rs, Register rt) { emit_long((special2_op << 26) | ((int)rs->encoding() << 21) | ((int)rt->encoding() << 16) | msubu_op); } |
aoqi@363 | 1543 | void gsorn (Register rd, Register rs, Register rt) { INSN_S2((0x12 << 6) | gs0x06_op) } |
aoqi@199 | 1544 | |
aoqi@199 | 1545 | void gsmult (Register rd, Register rs, Register rt) { INSN_S2(gsmult_op) } |
aoqi@199 | 1546 | void gsdmult (Register rd, Register rs, Register rt) { INSN_S2(gsdmult_op) } |
aoqi@199 | 1547 | void gsmultu (Register rd, Register rs, Register rt) { INSN_S2(gsmultu_op) } |
aoqi@199 | 1548 | void gsdmultu(Register rd, Register rs, Register rt) { INSN_S2(gsdmultu_op)} |
aoqi@199 | 1549 | void gsdiv (Register rd, Register rs, Register rt) { INSN_S2(gsdiv_op) } |
aoqi@199 | 1550 | void gsddiv (Register rd, Register rs, Register rt) { INSN_S2(gsddiv_op) } |
aoqi@199 | 1551 | void gsdivu (Register rd, Register rs, Register rt) { INSN_S2(gsdivu_op) } |
aoqi@199 | 1552 | void gsddivu (Register rd, Register rs, Register rt) { INSN_S2(gsddivu_op) } |
aoqi@199 | 1553 | void gsmod (Register rd, Register rs, Register rt) { INSN_S2(gsmod_op) } |
aoqi@199 | 1554 | void gsdmod (Register rd, Register rs, Register rt) { INSN_S2(gsdmod_op) } |
aoqi@199 | 1555 | void gsmodu (Register rd, Register rs, Register rt) { INSN_S2(gsmodu_op) } |
aoqi@199 | 1556 | void gsdmodu (Register rd, Register rs, Register rt) { INSN_S2(gsdmodu_op) } |
aoqi@199 | 1557 | 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 | 1558 | 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 | 1559 | 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 | 1560 | 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 | 1561 | 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 | 1562 | 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 | 1563 | 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 | 1564 | 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 | 1565 | |
aoqi@199 | 1566 | #undef INSN_S2 |
aoqi@199 | 1567 | |
aoqi@199 | 1568 | //SPECIAL3 |
aoqi@199 | 1569 | /* |
aoqi@199 | 1570 | // FIXME |
aoqi@199 | 1571 | #define is_0_to_32(a, b) \ |
aoqi@199 | 1572 | assert (a >= 0, " just a check"); \ |
aoqi@199 | 1573 | assert (a <= 0, " just a check"); \ |
aoqi@199 | 1574 | assert (b >= 0, " just a check"); \ |
aoqi@199 | 1575 | assert (b <= 0, " just a check"); \ |
aoqi@199 | 1576 | assert (a+b >= 0, " just a check"); \ |
aoqi@199 | 1577 | assert (a+b <= 0, " just a check"); |
aoqi@199 | 1578 | */ |
aoqi@199 | 1579 | #define is_0_to_32(a, b) |
aoqi@199 | 1580 | |
aoqi@199 | 1581 | 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 | 1582 | 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 | 1583 | 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 | 1584 | void dins (Register rt, Register rs, int pos, int size) { |
fujie@294 | 1585 | guarantee((0 <= pos) && (pos < 32), "pos must be in [0, 32)"); |
fujie@294 | 1586 | guarantee((0 < size) && (size <= 32), "size must be in (0, 32]"); |
fujie@294 | 1587 | guarantee((0 < pos + size) && (pos + size <= 32), "pos + size must be in (0, 32]"); |
fujie@294 | 1588 | |
aoqi@6880 | 1589 | 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 | 1590 | } |
aoqi@199 | 1591 | |
aoqi@8015 | 1592 | 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 | 1593 | 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 | 1594 | 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 | 1595 | 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 | 1596 | |
aoqi@8015 | 1597 | 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 | 1598 | 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 | 1599 | 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 | 1600 | 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 | 1601 | 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 | 1602 | 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 | 1603 | |
aoqi@199 | 1604 | void sdc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(sdc1_op, (int)base->encoding(), (int)ft->encoding(), off)); } |
aoqi@199 | 1605 | void sdc1(FloatRegister ft, Address dst); |
aoqi@199 | 1606 | void swc1(FloatRegister ft, Register base, int off) { emit_long(insn_ORRI(swc1_op, (int)base->encoding(), (int)ft->encoding(), off)); } |
aoqi@199 | 1607 | void swc1(FloatRegister ft, Address dst); |
aoqi@199 | 1608 | |
aoqi@199 | 1609 | |
aoqi@199 | 1610 | void int3(); |
aoqi@199 | 1611 | static void print_instruction(int); |
aoqi@199 | 1612 | int patched_branch(int dest_pos, int inst, int inst_pos); |
aoqi@199 | 1613 | int branch_destination(int inst, int pos); |
aoqi@199 | 1614 | |
aoqi@9459 | 1615 | // Loongson extension |
aoqi@199 | 1616 | |
aoqi@199 | 1617 | // gssq/gslq/gssqc1/gslqc1: vAddr = sign_extend(offset << 4 ) + GPR[base]. Therefore, the off should be ">> 4". |
jiangshaofeng@362 | 1618 | void gslble(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1619 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslble_op); |
jiangshaofeng@362 | 1620 | } |
jiangshaofeng@362 | 1621 | |
jiangshaofeng@362 | 1622 | void gslbgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1623 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslbgt_op); |
jiangshaofeng@362 | 1624 | } |
jiangshaofeng@362 | 1625 | |
jiangshaofeng@362 | 1626 | void gslhle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1627 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhle_op); |
jiangshaofeng@362 | 1628 | } |
jiangshaofeng@362 | 1629 | |
jiangshaofeng@362 | 1630 | void gslhgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1631 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslhgt_op); |
jiangshaofeng@362 | 1632 | } |
jiangshaofeng@362 | 1633 | |
jiangshaofeng@362 | 1634 | void gslwle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1635 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwle_op); |
jiangshaofeng@362 | 1636 | } |
jiangshaofeng@362 | 1637 | |
jiangshaofeng@362 | 1638 | void gslwgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1639 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgt_op); |
jiangshaofeng@362 | 1640 | } |
jiangshaofeng@362 | 1641 | |
jiangshaofeng@362 | 1642 | void gsldle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1643 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldle_op); |
jiangshaofeng@362 | 1644 | } |
jiangshaofeng@362 | 1645 | |
jiangshaofeng@362 | 1646 | void gsldgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1647 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgt_op); |
jiangshaofeng@362 | 1648 | } |
jiangshaofeng@362 | 1649 | |
jiangshaofeng@362 | 1650 | void gslwlec1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1651 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwlec1_op); |
jiangshaofeng@362 | 1652 | } |
jiangshaofeng@362 | 1653 | |
jiangshaofeng@362 | 1654 | void gslwgtc1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1655 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gslwgtc1_op); |
jiangshaofeng@362 | 1656 | } |
jiangshaofeng@362 | 1657 | |
jiangshaofeng@362 | 1658 | void gsldlec1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1659 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldlec1_op); |
jiangshaofeng@362 | 1660 | } |
jiangshaofeng@362 | 1661 | |
jiangshaofeng@362 | 1662 | void gsldgtc1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1663 | emit_long((gs_lwc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsldgtc1_op); |
jiangshaofeng@362 | 1664 | } |
jiangshaofeng@362 | 1665 | |
lifangyuan@125 | 1666 | void gslq(Register rq, Register rt, Register base, int off) { |
wangxue@9457 | 1667 | assert(!(off & 0xF), "gslq: the low 4 bits of off must be 0"); |
lifangyuan@125 | 1668 | off = off >> 4; |
lifangyuan@125 | 1669 | assert(is_simm(off, 9),"gslq: off exceeds 9 bits"); |
lifangyuan@125 | 1670 | 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 | 1671 | } |
lifangyuan@125 | 1672 | |
jingtian@9455 | 1673 | void gslqc1(FloatRegister rq, FloatRegister rt, Register base, int off) { |
wangxue@9457 | 1674 | assert(!(off & 0xF), "gslqc1: the low 4 bits of off must be 0"); |
jingtian@9455 | 1675 | off = off >> 4; |
jingtian@9455 | 1676 | assert(is_simm(off, 9),"gslqc1: off exceeds 9 bits"); |
jingtian@9455 | 1677 | 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 | 1678 | } |
jingtian@9455 | 1679 | |
jiangshaofeng@362 | 1680 | void gssble(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1681 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssble_op); |
jiangshaofeng@362 | 1682 | } |
jiangshaofeng@362 | 1683 | |
jiangshaofeng@362 | 1684 | void gssbgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1685 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssbgt_op); |
jiangshaofeng@362 | 1686 | } |
jiangshaofeng@362 | 1687 | |
jiangshaofeng@362 | 1688 | void gsshle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1689 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshle_op); |
jiangshaofeng@362 | 1690 | } |
jiangshaofeng@362 | 1691 | |
jiangshaofeng@362 | 1692 | void gsshgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1693 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsshgt_op); |
jiangshaofeng@362 | 1694 | } |
jiangshaofeng@362 | 1695 | |
jiangshaofeng@362 | 1696 | void gsswle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1697 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswle_op); |
jiangshaofeng@362 | 1698 | } |
jiangshaofeng@362 | 1699 | |
jiangshaofeng@362 | 1700 | void gsswgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1701 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgt_op); |
jiangshaofeng@362 | 1702 | } |
jiangshaofeng@362 | 1703 | |
jiangshaofeng@362 | 1704 | void gssdle(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1705 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdle_op); |
jiangshaofeng@362 | 1706 | } |
jiangshaofeng@362 | 1707 | |
jiangshaofeng@362 | 1708 | void gssdgt(Register rt, Register base, Register bound) { |
jiangshaofeng@362 | 1709 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgt_op); |
jiangshaofeng@362 | 1710 | } |
jiangshaofeng@362 | 1711 | |
jiangshaofeng@362 | 1712 | void gsswlec1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1713 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswlec1_op); |
jiangshaofeng@362 | 1714 | } |
jiangshaofeng@362 | 1715 | |
jiangshaofeng@362 | 1716 | void gsswgtc1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1717 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gsswgtc1_op); |
jiangshaofeng@362 | 1718 | } |
jiangshaofeng@362 | 1719 | |
jiangshaofeng@362 | 1720 | void gssdlec1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1721 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdlec1_op); |
jiangshaofeng@362 | 1722 | } |
jiangshaofeng@362 | 1723 | |
jiangshaofeng@362 | 1724 | void gssdgtc1(FloatRegister rt, Register base, Register bound) { |
jiangshaofeng@362 | 1725 | emit_long((gs_swc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | ((int)bound->encoding() << 11) | 0 << 6 | gssdgtc1_op); |
jiangshaofeng@362 | 1726 | } |
jiangshaofeng@362 | 1727 | |
lifangyuan@125 | 1728 | void gssq(Register rq, Register rt, Register base, int off) { |
wangxue@9457 | 1729 | assert(!(off & 0xF), "gssq: the low 4 bits of off must be 0"); |
lifangyuan@125 | 1730 | off = off >> 4; |
lifangyuan@125 | 1731 | assert(is_simm(off, 9),"gssq: off exceeds 9 bits"); |
lifangyuan@125 | 1732 | 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 | 1733 | } |
lifangyuan@125 | 1734 | |
jingtian@9455 | 1735 | void gssqc1(FloatRegister rq, FloatRegister rt, Register base, int off) { |
wangxue@9457 | 1736 | assert(!(off & 0xF), "gssqc1: the low 4 bits of off must be 0"); |
jingtian@9455 | 1737 | off = off >> 4; |
jingtian@9455 | 1738 | assert(is_simm(off, 9),"gssqc1: off exceeds 9 bits"); |
jingtian@9455 | 1739 | 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 | 1740 | } |
jingtian@9455 | 1741 | |
aoqi@199 | 1742 | //LDC2 & SDC2 |
aoqi@199 | 1743 | #define INSN(OPS, OP) \ |
aoqi@199 | 1744 | assert(is_simm(off, 8), "NAME: off exceeds 8 bits"); \ |
aoqi@9644 | 1745 | assert(UseLEXT1, "check UseLEXT1"); \ |
aoqi@199 | 1746 | emit_long( (OPS << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | \ |
aoqi@199 | 1747 | ((int)index->encoding() << 11) | (low(off, 8) << 3) | OP); |
fujie@75 | 1748 | |
aoqi@199 | 1749 | #define INSN_LDC2(NAME, op) \ |
aoqi@199 | 1750 | void NAME(Register rt, Register base, Register index, int off) { \ |
aoqi@199 | 1751 | INSN(gs_ldc2_op, op) \ |
aoqi@199 | 1752 | } |
aoqi@1 | 1753 | |
aoqi@199 | 1754 | #define INSN_LDC2_F(NAME, op) \ |
aoqi@199 | 1755 | void NAME(FloatRegister rt, Register base, Register index, int off) { \ |
aoqi@199 | 1756 | INSN(gs_ldc2_op, op) \ |
aoqi@199 | 1757 | } |
aoqi@1 | 1758 | |
aoqi@199 | 1759 | #define INSN_SDC2(NAME, op) \ |
aoqi@199 | 1760 | void NAME(Register rt, Register base, Register index, int off) { \ |
aoqi@199 | 1761 | INSN(gs_sdc2_op, op) \ |
aoqi@199 | 1762 | } |
fujie@67 | 1763 | |
aoqi@199 | 1764 | #define INSN_SDC2_F(NAME, op) \ |
aoqi@199 | 1765 | void NAME(FloatRegister rt, Register base, Register index, int off) { \ |
aoqi@199 | 1766 | INSN(gs_sdc2_op, op) \ |
aoqi@199 | 1767 | } |
fujie@67 | 1768 | |
aoqi@199 | 1769 | /* |
aoqi@199 | 1770 | void gslbx(Register rt, Register base, Register index, int off) { |
aoqi@199 | 1771 | assert(is_simm(off, 8), "gslbx: off exceeds 8 bits"); |
aoqi@9644 | 1772 | assert(UseLEXT1, "check UseLEXT1"); |
aoqi@199 | 1773 | emit_long( (gs_ldc2_op << 26) | ((int)base->encoding() << 21) | ((int)rt->encoding() << 16) | |
aoqi@199 | 1774 | ((int)index->encoding() << 11) | (low(off, 8) << 3) | gslbx_op); |
aoqi@199 | 1775 | void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op);} |
fujie@76 | 1776 | |
aoqi@199 | 1777 | INSN_LDC2(gslbx, gslbx_op) |
aoqi@199 | 1778 | INSN_LDC2(gslhx, gslhx_op) |
aoqi@199 | 1779 | INSN_LDC2(gslwx, gslwx_op) |
aoqi@199 | 1780 | INSN_LDC2(gsldx, gsldx_op) |
aoqi@199 | 1781 | INSN_LDC2_F(gslwxc1, gslwxc1_op) |
aoqi@199 | 1782 | INSN_LDC2_F(gsldxc1, gsldxc1_op) |
fujie@76 | 1783 | |
aoqi@199 | 1784 | INSN_SDC2(gssbx, gssbx_op) |
aoqi@199 | 1785 | INSN_SDC2(gsshx, gsshx_op) |
aoqi@199 | 1786 | INSN_SDC2(gsswx, gsswx_op) |
aoqi@199 | 1787 | INSN_SDC2(gssdx, gssdx_op) |
aoqi@199 | 1788 | INSN_SDC2_F(gsswxc1, gsswxc1_op) |
aoqi@199 | 1789 | INSN_SDC2_F(gssdxc1, gssdxc1_op) |
aoqi@199 | 1790 | */ |
aoqi@199 | 1791 | void gslbx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslbx_op) } |
aoqi@199 | 1792 | void gslhx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslhx_op) } |
aoqi@199 | 1793 | void gslwx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwx_op) } |
aoqi@199 | 1794 | void gsldx(Register rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldx_op) } |
aoqi@199 | 1795 | void gslwxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gslwxc1_op) } |
aoqi@199 | 1796 | void gsldxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_ldc2_op, gsldxc1_op) } |
fujie@65 | 1797 | |
aoqi@199 | 1798 | void gssbx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssbx_op) } |
aoqi@199 | 1799 | void gsshx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsshx_op) } |
aoqi@199 | 1800 | void gsswx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswx_op) } |
aoqi@199 | 1801 | void gssdx(Register rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdx_op) } |
aoqi@199 | 1802 | void gsswxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gsswxc1_op) } |
aoqi@199 | 1803 | void gssdxc1(FloatRegister rt, Register base, Register index, int off) {INSN(gs_sdc2_op, gssdxc1_op) } |
fujie@65 | 1804 | |
aoqi@199 | 1805 | #undef INSN |
aoqi@199 | 1806 | #undef INSN_LDC2 |
aoqi@199 | 1807 | #undef INSN_LDC2_F |
aoqi@199 | 1808 | #undef INSN_SDC2 |
aoqi@199 | 1809 | #undef INSN_SDC2_F |
fujie@66 | 1810 | |
aoqi@9644 | 1811 | // cpucfg on Loongson CPUs above 3A4000 |
aoqi@9644 | 1812 | 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 | 1813 | |
fujie@66 | 1814 | |
aoqi@1 | 1815 | public: |
aoqi@199 | 1816 | // Creation |
aoqi@199 | 1817 | Assembler(CodeBuffer* code) : AbstractAssembler(code) { |
aoqi@1 | 1818 | #ifdef CHECK_DELAY |
aoqi@199 | 1819 | delay_state = no_delay; |
aoqi@1 | 1820 | #endif |
aoqi@199 | 1821 | } |
aoqi@1 | 1822 | |
aoqi@1 | 1823 | // Decoding |
aoqi@1 | 1824 | static address locate_operand(address inst, WhichOperand which); |
aoqi@1 | 1825 | static address locate_next_instruction(address inst); |
aoqi@1 | 1826 | }; |
aoqi@1 | 1827 | |
aoqi@1 | 1828 | |
aoqi@1 | 1829 | |
aoqi@1 | 1830 | #endif // CPU_MIPS_VM_ASSEMBLER_MIPS_HPP |