src/cpu/mips/vm/assembler_mips.cpp

Tue, 24 Oct 2017 14:04:09 +0800

author
fujie
date
Tue, 24 Oct 2017 14:04:09 +0800
changeset 8001
76b73e112cb7
parent 6880
52ea28d233d2
child 8004
941851413ebf
permissions
-rw-r--r--

[Assembler] Complex address modes support for Assembler::lea(Register rt, Address src), Assembler::sd(Register rt, Address dst) and Assembler::sw(Register rt, Address dst)

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@1 3 * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
aoqi@1 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@1 5 *
aoqi@1 6 * This code is free software; you can redistribute it and/or modify it
aoqi@1 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@1 8 * published by the Free Software Foundation.
aoqi@1 9 *
aoqi@1 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@1 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@1 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@1 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@1 14 * accompanied this code).
aoqi@1 15 *
aoqi@1 16 * You should have received a copy of the GNU General Public License version
aoqi@1 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@1 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@1 19 *
aoqi@1 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@1 21 * or visit www.oracle.com if you need additional information or have any
aoqi@1 22 * questions.
aoqi@1 23 *
aoqi@1 24 */
aoqi@1 25
aoqi@1 26 #include "precompiled.hpp"
aoqi@1 27 #include "asm/assembler.hpp"
aoqi@1 28 #include "asm/assembler.inline.hpp"
aoqi@1 29 #include "gc_interface/collectedHeap.inline.hpp"
aoqi@1 30 #include "interpreter/interpreter.hpp"
aoqi@1 31 #include "memory/cardTableModRefBS.hpp"
aoqi@1 32 #include "memory/resourceArea.hpp"
aoqi@1 33 #include "prims/methodHandles.hpp"
aoqi@1 34 #include "runtime/biasedLocking.hpp"
aoqi@1 35 #include "runtime/interfaceSupport.hpp"
aoqi@1 36 #include "runtime/objectMonitor.hpp"
aoqi@1 37 #include "runtime/os.hpp"
aoqi@1 38 #include "runtime/sharedRuntime.hpp"
aoqi@1 39 #include "runtime/stubRoutines.hpp"
aoqi@6880 40 #if INCLUDE_ALL_GCS
aoqi@1 41 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
aoqi@1 42 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
aoqi@1 43 #include "gc_implementation/g1/heapRegion.hpp"
aoqi@6880 44 #endif // INCLUDE_ALL_GCS
aoqi@6880 45
aoqi@1 46 #ifdef PRODUCT
aoqi@1 47 #define BLOCK_COMMENT(str) /* nothing */
aoqi@1 48 #define STOP(error) stop(error)
aoqi@1 49 #else
aoqi@1 50 #define BLOCK_COMMENT(str) block_comment(str)
aoqi@1 51 #define STOP(error) block_comment(error); stop(error)
aoqi@1 52 #endif
aoqi@1 53
aoqi@1 54 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
aoqi@1 55
aoqi@1 56 // Implementation of AddressLiteral
aoqi@1 57
aoqi@1 58 AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) {
aoqi@1 59 _is_lval = false;
aoqi@1 60 _target = target;
aoqi@1 61 _rspec = rspec_from_rtype(rtype, target);
aoqi@1 62 }
aoqi@1 63
aoqi@1 64 // Implementation of Address
aoqi@1 65
aoqi@1 66
aoqi@1 67 Address Address::make_array(ArrayAddress adr) {
aoqi@1 68 AddressLiteral base = adr.base();
aoqi@1 69 Address index = adr.index();
aoqi@1 70 assert(index._disp == 0, "must not have disp"); // maybe it can?
aoqi@1 71 Address array(index._base, index._index, index._scale, (intptr_t) base.target());
aoqi@1 72 array._rspec = base._rspec;
aoqi@1 73 return array;
aoqi@1 74 }
aoqi@1 75
aoqi@1 76 // exceedingly dangerous constructor
aoqi@1 77 Address::Address(address loc, RelocationHolder spec) {
aoqi@1 78 _base = noreg;
aoqi@1 79 _index = noreg;
aoqi@1 80 _scale = no_scale;
aoqi@1 81 _disp = (intptr_t) loc;
aoqi@1 82 _rspec = spec;
aoqi@1 83 }
aoqi@1 84
aoqi@1 85
aoqi@1 86 // Implementation of Assembler
aoqi@1 87 const char *Assembler::ops_name[] = {
aoqi@6880 88 "special", "regimm", "j", "jal", "beq", "bne", "blez", "bgtz",
aoqi@6880 89 "addi", "addiu", "slti", "sltiu", "andi", "ori", "xori", "lui",
aoqi@6880 90 "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "bleql", "bgtzl",
aoqi@6880 91 "daddi", "daddiu", "ldl", "ldr", "", "", "", "",
aoqi@6880 92 "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
aoqi@6880 93 "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
aoqi@6880 94 "ll", "lwc1", "", "", "lld", "ldc1", "", "ld",
aoqi@6880 95 "sc", "swc1", "", "", "scd", "sdc1", "", "sd"
aoqi@1 96 };
aoqi@1 97
aoqi@1 98 const char* Assembler::special_name[] = {
aoqi@6880 99 "sll", "", "srl", "sra", "sllv", "", "srlv", "srav",
aoqi@6880 100 "jr", "jalr", "movz", "movn", "syscall", "break", "", "sync",
aoqi@6880 101 "mfhi", "mthi", "mflo", "mtlo", "dsll", "", "dsrl", "dsra",
aoqi@6880 102 "mult", "multu", "div", "divu", "dmult", "dmultu", "ddiv", "ddivu",
aoqi@6880 103 "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
aoqi@6880 104 "", "", "slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
aoqi@6880 105 "tge", "tgeu", "tlt", "tltu", "teq", "", "tne", "",
aoqi@6880 106 "dsll", "", "dsrl", "dsra", "dsll32", "", "dsrl32", "dsra32"
aoqi@1 107 };
aoqi@1 108
aoqi@199 109 const char* Assembler::cop1_name[] = {
aoqi@339 110 "add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
aoqi@339 111 "round.l", "trunc.l", "ceil.l", "floor.l", "round.w", "trunc.w", "ceil.w", "floor.w",
aoqi@339 112 "", "", "", "", "", "", "", "",
aoqi@339 113 "", "", "", "", "", "", "", "",
aoqi@339 114 "", "", "", "", "", "", "", "",
aoqi@339 115 "", "", "", "", "", "", "", "",
aoqi@339 116 "c.f", "c.un", "c.eq", "c.ueq", "c.olt", "c.ult", "c.ole", "c.ule",
aoqi@339 117 "c.sf", "c.ngle", "c.seq", "c.ngl", "c.lt", "c.nge", "c.le", "c.ngt"
aoqi@199 118 };
aoqi@199 119
aoqi@199 120 const char* Assembler::cop1x_name[] = {
aoqi@6880 121 "lwxc1", "ldxc1", "", "", "", "luxc1", "", "",
aoqi@6880 122 "swxc1", "sdxc1", "", "", "", "suxc1", "", "prefx",
aoqi@6880 123 "", "", "", "", "", "", "alnv.ps", "",
aoqi@6880 124 "", "", "", "", "", "", "", "",
aoqi@6880 125 "madd.s", "madd.d", "", "", "", "", "madd.ps", "",
aoqi@6880 126 "msub.s", "msub.d", "", "", "", "", "msub.ps", "",
aoqi@6880 127 "nmadd.s", "nmadd.d", "", "", "", "", "nmadd.ps", "",
aoqi@6880 128 "nmsub.s", "nmsub.d", "", "", "", "", "nmsub.ps", ""
aoqi@199 129 };
aoqi@199 130
fujie@41 131 const char* Assembler::special2_name[] = {
aoqi@6880 132 "madd", "", "mul", "", "msub", "", "", "",
aoqi@6880 133 "", "", "", "", "", "", "", "",
aoqi@6880 134 "", "gsdmult", "", "", "gsdiv", "gsddiv", "", "",
aoqi@6880 135 "", "", "", "", "gsmod", "gsdmod", "", "",
aoqi@6880 136 "", "", "", "", "", "", "", "",
aoqi@6880 137 "", "", "", "", "", "", "", "",
aoqi@6880 138 "", "", "", "", "", "", "", "",
aoqi@6880 139 "", "", "", "", "", "", "", ""
fujie@41 140 };
fujie@41 141
aoqi@199 142 const char* Assembler::special3_name[] = {
aoqi@6880 143 "ext", "", "", "", "ins", "dinsm", "dinsu", "dins",
aoqi@6880 144 "", "", "", "", "", "", "", "",
aoqi@6880 145 "", "", "", "", "", "", "", "",
aoqi@6880 146 "", "", "", "", "", "", "", "",
aoqi@6880 147 "bshfl", "", "", "", "", "", "", "",
aoqi@6880 148 "", "", "", "", "", "", "", "",
aoqi@6880 149 "", "", "", "", "", "", "", "",
aoqi@6880 150 "", "", "", "", "", "", "", "",
aoqi@199 151 };
aoqi@199 152
aoqi@1 153 const char* Assembler::regimm_name[] = {
aoqi@6880 154 "bltz", "bgez", "bltzl", "bgezl", "", "", "", "",
aoqi@6880 155 "tgei", "tgeiu", "tlti", "tltiu", "teqi", "", "tnei", "",
aoqi@6880 156 "bltzal", "bgezal", "bltzall", "bgezall"
aoqi@1 157 };
aoqi@6880 158
fujie@44 159 const char* Assembler::gs_ldc2_name[] = {
aoqi@6880 160 "gslbx", "gslhx", "gslwx", "gsldx", "", "", "gslwxc1", "gsldxc1"
fujie@44 161 };
fujie@44 162
lifangyuan@125 163
lifangyuan@125 164 const char* Assembler::gs_lwc2_name[] = {
jiangshaofeng@362 165 "", "", "", "", "", "", "", "",
jiangshaofeng@362 166 "", "", "", "", "", "", "", "",
jiangshaofeng@362 167 "gslble", "gslbgt", "gslhle", "gslhgt", "gslwle", "gslwgt", "gsldle", "gsldgt",
jiangshaofeng@362 168 "", "", "", "gslwlec1", "gslwgtc1", "gsldlec1", "gsldgtc1", "",/*LWDIR, LWPTE, LDDIR and LDPTE have the same low 6 bits.*/
jiangshaofeng@362 169 "gslq", ""
lifangyuan@125 170 };
lifangyuan@125 171
fujie@65 172 const char* Assembler::gs_sdc2_name[] = {
aoqi@6880 173 "gssbx", "gsshx", "gsswx", "gssdx", "", "", "gsswxc1", "gssdxc1"
fujie@65 174 };
fujie@65 175
lifangyuan@125 176 const char* Assembler::gs_swc2_name[] = {
jiangshaofeng@362 177 "", "", "", "", "", "", "", "",
jiangshaofeng@362 178 "", "", "", "", "", "", "", "",
jiangshaofeng@362 179 "gssble", "gssbgt", "gsshle", "gsshgt", "gsswle", "gsswgt", "gssdle", "gssdgt",
jiangshaofeng@362 180 "", "", "", "", "gsswlec1", "gsswgtc1", "gssdlec1", "gssdgtc1",
jiangshaofeng@362 181 "gssq", ""
lifangyuan@125 182 };
lifangyuan@125 183
aoqi@6880 184 //misleading name, print only branch/jump instruction
aoqi@1 185 void Assembler::print_instruction(int inst) {
aoqi@6880 186 const char *s;
aoqi@6880 187 switch( opcode(inst) ) {
aoqi@6880 188 default:
aoqi@6880 189 s = ops_name[opcode(inst)];
aoqi@6880 190 break;
aoqi@6880 191 case special_op:
aoqi@6880 192 s = special_name[special(inst)];
aoqi@6880 193 break;
aoqi@6880 194 case regimm_op:
aoqi@6880 195 s = special_name[rt(inst)];
aoqi@6880 196 break;
aoqi@1 197 }
aoqi@1 198
aoqi@6880 199 ::tty->print("%s", s);
aoqi@1 200 }
aoqi@1 201
fujie@293 202 int Assembler::is_int_mask(int x) {
fujie@293 203 int xx = x;
fujie@293 204 int count = 0;
fujie@293 205
fujie@293 206 while (x != 0) {
fujie@293 207 x &= (x - 1);
fujie@293 208 count++;
fujie@293 209 }
fujie@293 210
fujie@293 211 if ((1<<count) == (xx+1)) {
fujie@293 212 return count;
fujie@293 213 } else {
fujie@293 214 return -1;
fujie@293 215 }
fujie@293 216 }
fujie@293 217
fujie@301 218 int Assembler::is_jlong_mask(jlong x) {
fujie@301 219 jlong xx = x;
fujie@301 220 int count = 0;
fujie@301 221
fujie@301 222 while (x != 0) {
fujie@301 223 x &= (x - 1);
fujie@301 224 count++;
fujie@301 225 }
fujie@301 226
fujie@301 227 if ((1<<count) == (xx+1)) {
fujie@301 228 return count;
fujie@301 229 } else {
fujie@301 230 return -1;
fujie@301 231 }
fujie@301 232 }
fujie@301 233
aoqi@1 234 //without check, maybe fixed
aoqi@1 235 int Assembler::patched_branch(int dest_pos, int inst, int inst_pos) {
aoqi@6880 236 int v = (dest_pos - inst_pos - 4)>>2;
aoqi@6880 237 switch(opcode(inst)) {
aoqi@6880 238 case j_op:
aoqi@6880 239 case jal_op:
aoqi@6880 240 assert(false, "should not use j/jal here");
aoqi@6880 241 break;
aoqi@6880 242 default:
aoqi@6880 243 assert(is_simm16(v), "must be simm16");
aoqi@1 244 #ifndef PRODUCT
aoqi@6880 245 if(!is_simm16(v))
aoqi@6880 246 {
aoqi@6880 247 tty->print_cr("must be simm16");
aoqi@6880 248 tty->print_cr("Inst: %lx", inst);
aoqi@6880 249 }
aoqi@1 250 #endif
aoqi@1 251
aoqi@6880 252 v = low16(v);
aoqi@6880 253 inst &= 0xffff0000;
aoqi@6880 254 break;
aoqi@6880 255 }
aoqi@6880 256
aoqi@6880 257 return inst | v;
aoqi@1 258 }
aoqi@1 259
aoqi@1 260 int Assembler::branch_destination(int inst, int pos) {
aoqi@6880 261 int off;
aoqi@6880 262
aoqi@6880 263 switch(opcode(inst)) {
aoqi@6880 264 case j_op:
aoqi@6880 265 case jal_op:
aoqi@6880 266 assert(false, "should not use j/jal here");
aoqi@6880 267 break;
aoqi@6880 268 default:
aoqi@6880 269 off = expand(low16(inst), 15);
aoqi@6880 270 break;
aoqi@6880 271 }
aoqi@6880 272
aoqi@6880 273 return off ? pos + 4 + (off<<2) : 0;
aoqi@1 274 }
aoqi@1 275
aoqi@1 276 int AbstractAssembler::code_fill_byte() {
aoqi@6880 277 return 0x00; // illegal instruction 0x00000000
aoqi@1 278 }
aoqi@1 279
aoqi@1 280 // Now the Assembler instruction (identical for 32/64 bits)
aoqi@1 281
aoqi@1 282 void Assembler::lb(Register rt, Address src) {
aoqi@6880 283 lb(rt, src.base(), src.disp());
aoqi@1 284 }
aoqi@1 285
aoqi@1 286 void Assembler::lbu(Register rt, Address src) {
aoqi@6880 287 lbu(rt, src.base(), src.disp());
aoqi@1 288 }
aoqi@1 289
aoqi@1 290 void Assembler::ld(Register rt, Address src){
aoqi@6880 291 ld(rt, src.base(), src.disp());
aoqi@1 292 }
aoqi@1 293
aoqi@1 294 void Assembler::ldl(Register rt, Address src){
aoqi@6880 295 ldl(rt, src.base(), src.disp());
aoqi@1 296 }
aoqi@1 297
aoqi@1 298 void Assembler::ldr(Register rt, Address src){
aoqi@6880 299 ldr(rt, src.base(), src.disp());
aoqi@1 300 }
aoqi@1 301
aoqi@1 302 void Assembler::lh(Register rt, Address src){
aoqi@6880 303 lh(rt, src.base(), src.disp());
aoqi@1 304 }
aoqi@1 305
aoqi@1 306 void Assembler::lhu(Register rt, Address src){
aoqi@6880 307 lhu(rt, src.base(), src.disp());
aoqi@1 308 }
aoqi@1 309
aoqi@1 310 void Assembler::ll(Register rt, Address src){
aoqi@6880 311 ll(rt, src.base(), src.disp());
aoqi@1 312 }
aoqi@1 313
aoqi@1 314 void Assembler::lld(Register rt, Address src){
aoqi@6880 315 lld(rt, src.base(), src.disp());
aoqi@1 316 }
aoqi@1 317
aoqi@1 318 void Assembler::lw(Register rt, Address src){
aoqi@6880 319 lw(rt, src.base(), src.disp());
aoqi@1 320 }
aoqi@1 321 void Assembler::lea(Register rt, Address src) {
fujie@8001 322 Register dst = rt;
fujie@8001 323 Register base = src.base();
fujie@8001 324 Register index = src.index();
fujie@8001 325
fujie@8001 326 int scale = src.scale();
fujie@8001 327 int disp = src.disp();
fujie@8001 328
fujie@8001 329 if (index == noreg) {
fujie@8001 330 if (is_simm16(disp)) {
fujie@8001 331 daddiu(dst, base, disp);
fujie@8001 332 } else {
fujie@8001 333 lui(AT, split_low(disp >> 16));
fujie@8001 334 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 335 daddu(dst, base, AT);
fujie@8001 336 }
fujie@8001 337 } else {
fujie@8001 338 if (scale == 0) {
fujie@8001 339 if (is_simm16(disp)) {
fujie@8001 340 daddu(AT, base, index);
fujie@8001 341 daddiu(dst, AT, disp);
fujie@8001 342 } else {
fujie@8001 343 lui(AT, split_low(disp >> 16));
fujie@8001 344 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 345 daddu(AT, base, AT);
fujie@8001 346 daddu(dst, AT, index);
fujie@8001 347 }
fujie@8001 348 } else {
fujie@8001 349 if (is_simm16(disp)) {
fujie@8001 350 dsll(AT, index, scale);
fujie@8001 351 daddu(AT, AT, base);
fujie@8001 352 daddiu(dst, AT, disp);
fujie@8001 353 } else {
fujie@8001 354 lui(AT, split_low(disp >> 16));
fujie@8001 355 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 356 daddu(AT, AT, base);
fujie@8001 357 dsll(dst, index, scale);
fujie@8001 358 daddu(dst, dst, AT);
fujie@8001 359 }
fujie@8001 360 }
fujie@8001 361 }
aoqi@1 362 }
aoqi@1 363
aoqi@1 364 void Assembler::lwl(Register rt, Address src){
aoqi@6880 365 lwl(rt, src.base(), src.disp());
aoqi@1 366 }
aoqi@1 367
aoqi@1 368 void Assembler::lwr(Register rt, Address src){
aoqi@6880 369 lwr(rt, src.base(), src.disp());
aoqi@1 370 }
aoqi@1 371
aoqi@1 372 void Assembler::lwu(Register rt, Address src){
aoqi@6880 373 lwu(rt, src.base(), src.disp());
aoqi@1 374 }
aoqi@1 375
aoqi@1 376 void Assembler::sb(Register rt, Address dst) {
aoqi@6880 377 sb(rt, dst.base(), dst.disp());
aoqi@1 378 }
aoqi@1 379
aoqi@1 380 void Assembler::sc(Register rt, Address dst) {
aoqi@6880 381 sc(rt, dst.base(), dst.disp());
aoqi@1 382 }
aoqi@1 383
aoqi@1 384 void Assembler::scd(Register rt, Address dst) {
aoqi@6880 385 scd(rt, dst.base(), dst.disp());
aoqi@1 386 }
aoqi@1 387
aoqi@1 388 void Assembler::sd(Register rt, Address dst) {
fujie@8001 389 Register src = rt;
fujie@8001 390 Register base = dst.base();
fujie@8001 391 Register index = dst.index();
fujie@8001 392
fujie@8001 393 int scale = dst.scale();
fujie@8001 394 int disp = dst.disp();
fujie@8001 395
fujie@8001 396 if(index != noreg) {
fujie@8001 397 if(is_simm16(disp)) {
fujie@8001 398 if( UseLoongsonISA && is_simm(disp, 8)) {
fujie@8001 399 if (scale == 0) {
fujie@8001 400 gssdx(src, base, index, disp);
fujie@8001 401 } else {
fujie@8001 402 dsll(AT, index, scale);
fujie@8001 403 gssdx(src, base, AT, disp);
fujie@8001 404 }
fujie@8001 405 } else {
fujie@8001 406 if (scale == 0) {
fujie@8001 407 daddu(AT, base, index);
fujie@8001 408 } else {
fujie@8001 409 dsll(AT, index, scale);
fujie@8001 410 daddu(AT, base, AT);
fujie@8001 411 }
fujie@8001 412 sd(src, AT, disp);
fujie@8001 413 }
fujie@8001 414 } else {
fujie@8001 415 if (scale == 0) {
fujie@8001 416 lui(AT, split_low(disp >> 16));
fujie@8001 417 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 418 daddu(AT, AT, base);
fujie@8001 419 if(UseLoongsonISA) {
fujie@8001 420 gssdx(src, AT, index, 0);
fujie@8001 421 } else {
fujie@8001 422 daddu(AT, AT, index);
fujie@8001 423 sd(src, AT, 0);
fujie@8001 424 }
fujie@8001 425 } else {
fujie@8001 426 dsll(AT, index, scale);
fujie@8001 427 daddu(AT, base, AT);
fujie@8001 428 lui(T9, split_low(disp >> 16));
fujie@8001 429 if (split_low(disp)) ori(T9, T9, split_low(disp));
fujie@8001 430 if(UseLoongsonISA) {
fujie@8001 431 gssdx(src, AT, T9, 0);
fujie@8001 432 } else {
fujie@8001 433 daddu(AT, AT, T9);
fujie@8001 434 sd(src, AT, 0);
fujie@8001 435 }
fujie@8001 436 }
fujie@8001 437 }
fujie@8001 438 } else {
fujie@8001 439 if(is_simm16(disp)) {
fujie@8001 440 sd(src, base, disp);
fujie@8001 441 } else {
fujie@8001 442 lui(AT, split_low(disp >> 16));
fujie@8001 443 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 444
fujie@8001 445 if(UseLoongsonISA) {
fujie@8001 446 gssdx(src, base, AT, 0);
fujie@8001 447 } else {
fujie@8001 448 daddu(AT, base, AT);
fujie@8001 449 sd(src, AT, 0);
fujie@8001 450 }
fujie@8001 451 }
fujie@8001 452 }
aoqi@1 453 }
aoqi@1 454
aoqi@1 455 void Assembler::sdl(Register rt, Address dst) {
aoqi@6880 456 sdl(rt, dst.base(), dst.disp());
aoqi@1 457 }
aoqi@1 458
aoqi@1 459 void Assembler::sdr(Register rt, Address dst) {
aoqi@6880 460 sdr(rt, dst.base(), dst.disp());
aoqi@1 461 }
aoqi@1 462
aoqi@1 463 void Assembler::sh(Register rt, Address dst) {
aoqi@6880 464 sh(rt, dst.base(), dst.disp());
aoqi@1 465 }
aoqi@1 466
aoqi@1 467 void Assembler::sw(Register rt, Address dst) {
fujie@8001 468 Register src = rt;
fujie@8001 469 Register base = dst.base();
fujie@8001 470 Register index = dst.index();
fujie@8001 471
fujie@8001 472 int scale = dst.scale();
fujie@8001 473 int disp = dst.disp();
fujie@8001 474
fujie@8001 475 if(index != noreg) {
fujie@8001 476 if( Assembler::is_simm16(disp) ) {
fujie@8001 477 if( UseLoongsonISA && Assembler::is_simm(disp, 8) ) {
fujie@8001 478 if (scale == 0) {
fujie@8001 479 gsswx(src, base, index, disp);
fujie@8001 480 } else {
fujie@8001 481 dsll(AT, index, scale);
fujie@8001 482 gsswx(src, base, AT, disp);
fujie@8001 483 }
fujie@8001 484 } else {
fujie@8001 485 if (scale == 0) {
fujie@8001 486 daddu(AT, base, index);
fujie@8001 487 } else {
fujie@8001 488 dsll(AT, index, scale);
fujie@8001 489 daddu(AT, base, AT);
fujie@8001 490 }
fujie@8001 491 sw(src, AT, disp);
fujie@8001 492 }
fujie@8001 493 } else {
fujie@8001 494 if (scale == 0) {
fujie@8001 495 lui(AT, split_low(disp >> 16));
fujie@8001 496 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 497 daddu(AT, AT, base);
fujie@8001 498 if( UseLoongsonISA ) {
fujie@8001 499 gsswx(src, AT, index, 0);
fujie@8001 500 } else {
fujie@8001 501 daddu(AT, AT, index);
fujie@8001 502 sw(src, AT, 0);
fujie@8001 503 }
fujie@8001 504 } else {
fujie@8001 505 dsll(AT, index, scale);
fujie@8001 506 daddu(AT, base, AT);
fujie@8001 507 lui(T9, split_low(disp >> 16));
fujie@8001 508 if (split_low(disp)) ori(T9, T9, split_low(disp));
fujie@8001 509 if( UseLoongsonISA ) {
fujie@8001 510 gsswx(src, AT, T9, 0);
fujie@8001 511 } else {
fujie@8001 512 daddu(AT, AT, T9);
fujie@8001 513 sw(src, AT, 0);
fujie@8001 514 }
fujie@8001 515 }
fujie@8001 516 }
fujie@8001 517 } else {
fujie@8001 518 if( Assembler::is_simm16(disp) ) {
fujie@8001 519 sw(src, base, disp);
fujie@8001 520 } else {
fujie@8001 521 lui(AT, split_low(disp >> 16));
fujie@8001 522 if (split_low(disp)) ori(AT, AT, split_low(disp));
fujie@8001 523
fujie@8001 524 if( UseLoongsonISA ) {
fujie@8001 525 gsswx(src, base, AT, 0);
fujie@8001 526 } else {
fujie@8001 527 daddu(AT, base, AT);
fujie@8001 528 sw(src, AT, 0);
fujie@8001 529 }
fujie@8001 530 }
fujie@8001 531 }
aoqi@1 532 }
aoqi@1 533
aoqi@1 534 void Assembler::swl(Register rt, Address dst) {
aoqi@6880 535 swl(rt, dst.base(), dst.disp());
aoqi@1 536 }
aoqi@1 537
aoqi@1 538 void Assembler::swr(Register rt, Address dst) {
aoqi@6880 539 swr(rt, dst.base(), dst.disp());
aoqi@1 540 }
aoqi@1 541
aoqi@1 542 void Assembler::lwc1(FloatRegister rt, Address src) {
aoqi@6880 543 lwc1(rt, src.base(), src.disp());
aoqi@1 544 }
aoqi@1 545
aoqi@1 546 void Assembler::ldc1(FloatRegister rt, Address src) {
aoqi@6880 547 ldc1(rt, src.base(), src.disp());
aoqi@1 548 }
aoqi@1 549
aoqi@1 550 void Assembler::swc1(FloatRegister rt, Address dst) {
aoqi@6880 551 swc1(rt, dst.base(), dst.disp());
aoqi@1 552 }
aoqi@1 553
aoqi@1 554 void Assembler::sdc1(FloatRegister rt, Address dst) {
aoqi@6880 555 sdc1(rt, dst.base(), dst.disp());
aoqi@1 556 }
aoqi@1 557
aoqi@1 558 void Assembler::j(address entry) {
fujie@378 559 #ifdef MIPS64
aoqi@6880 560 int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xfffffffff0000000))>>2;
fujie@378 561 #else
aoqi@6880 562 int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xf0000000))>>2;
fujie@378 563 #endif
aoqi@6880 564 emit_long((j_op<<26) | dest);
aoqi@6880 565 has_delay_slot();
aoqi@1 566 }
aoqi@1 567
aoqi@1 568 void Assembler::jal(address entry) {
fujie@378 569 #ifdef MIPS64
aoqi@6880 570 int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xfffffffff0000000))>>2;
fujie@378 571 #else
aoqi@6880 572 int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xf0000000))>>2;
fujie@378 573 #endif
aoqi@6880 574 emit_long((jal_op<<26) | dest);
aoqi@6880 575 has_delay_slot();
aoqi@1 576 }
aoqi@1 577
aoqi@30 578
aoqi@1 579 class ControlWord {
aoqi@6880 580 public:
aoqi@6880 581 int32_t _value;
aoqi@1 582
aoqi@1 583 int rounding_control() const { return (_value >> 10) & 3 ; }
aoqi@1 584 int precision_control() const { return (_value >> 8) & 3 ; }
aoqi@1 585 bool precision() const { return ((_value >> 5) & 1) != 0; }
aoqi@1 586 bool underflow() const { return ((_value >> 4) & 1) != 0; }
aoqi@1 587 bool overflow() const { return ((_value >> 3) & 1) != 0; }
aoqi@1 588 bool zero_divide() const { return ((_value >> 2) & 1) != 0; }
aoqi@1 589 bool denormalized() const { return ((_value >> 1) & 1) != 0; }
aoqi@1 590 bool invalid() const { return ((_value >> 0) & 1) != 0; }
aoqi@1 591
aoqi@1 592 void print() const {
aoqi@1 593 // rounding control
aoqi@1 594 const char* rc;
aoqi@1 595 switch (rounding_control()) {
aoqi@1 596 case 0: rc = "round near"; break;
aoqi@1 597 case 1: rc = "round down"; break;
aoqi@1 598 case 2: rc = "round up "; break;
aoqi@1 599 case 3: rc = "chop "; break;
aoqi@1 600 };
aoqi@1 601 // precision control
aoqi@1 602 const char* pc;
aoqi@1 603 switch (precision_control()) {
aoqi@1 604 case 0: pc = "24 bits "; break;
aoqi@1 605 case 1: pc = "reserved"; break;
aoqi@1 606 case 2: pc = "53 bits "; break;
aoqi@1 607 case 3: pc = "64 bits "; break;
aoqi@1 608 };
aoqi@1 609 // flags
aoqi@1 610 char f[9];
aoqi@1 611 f[0] = ' ';
aoqi@1 612 f[1] = ' ';
aoqi@1 613 f[2] = (precision ()) ? 'P' : 'p';
aoqi@1 614 f[3] = (underflow ()) ? 'U' : 'u';
aoqi@1 615 f[4] = (overflow ()) ? 'O' : 'o';
aoqi@1 616 f[5] = (zero_divide ()) ? 'Z' : 'z';
aoqi@1 617 f[6] = (denormalized()) ? 'D' : 'd';
aoqi@1 618 f[7] = (invalid ()) ? 'I' : 'i';
aoqi@1 619 f[8] = '\x0';
aoqi@1 620 // output
aoqi@1 621 printf("%04x masks = %s, %s, %s", _value & 0xFFFF, f, rc, pc);
aoqi@1 622 }
aoqi@1 623
aoqi@1 624 };
aoqi@1 625
aoqi@1 626 class StatusWord {
aoqi@1 627 public:
aoqi@1 628 int32_t _value;
aoqi@1 629
aoqi@1 630 bool busy() const { return ((_value >> 15) & 1) != 0; }
aoqi@1 631 bool C3() const { return ((_value >> 14) & 1) != 0; }
aoqi@1 632 bool C2() const { return ((_value >> 10) & 1) != 0; }
aoqi@1 633 bool C1() const { return ((_value >> 9) & 1) != 0; }
aoqi@1 634 bool C0() const { return ((_value >> 8) & 1) != 0; }
aoqi@1 635 int top() const { return (_value >> 11) & 7 ; }
aoqi@1 636 bool error_status() const { return ((_value >> 7) & 1) != 0; }
aoqi@1 637 bool stack_fault() const { return ((_value >> 6) & 1) != 0; }
aoqi@1 638 bool precision() const { return ((_value >> 5) & 1) != 0; }
aoqi@1 639 bool underflow() const { return ((_value >> 4) & 1) != 0; }
aoqi@1 640 bool overflow() const { return ((_value >> 3) & 1) != 0; }
aoqi@1 641 bool zero_divide() const { return ((_value >> 2) & 1) != 0; }
aoqi@1 642 bool denormalized() const { return ((_value >> 1) & 1) != 0; }
aoqi@1 643 bool invalid() const { return ((_value >> 0) & 1) != 0; }
aoqi@1 644
aoqi@1 645 void print() const {
aoqi@1 646 // condition codes
aoqi@1 647 char c[5];
aoqi@1 648 c[0] = (C3()) ? '3' : '-';
aoqi@1 649 c[1] = (C2()) ? '2' : '-';
aoqi@1 650 c[2] = (C1()) ? '1' : '-';
aoqi@1 651 c[3] = (C0()) ? '0' : '-';
aoqi@1 652 c[4] = '\x0';
aoqi@1 653 // flags
aoqi@1 654 char f[9];
aoqi@1 655 f[0] = (error_status()) ? 'E' : '-';
aoqi@1 656 f[1] = (stack_fault ()) ? 'S' : '-';
aoqi@1 657 f[2] = (precision ()) ? 'P' : '-';
aoqi@1 658 f[3] = (underflow ()) ? 'U' : '-';
aoqi@1 659 f[4] = (overflow ()) ? 'O' : '-';
aoqi@1 660 f[5] = (zero_divide ()) ? 'Z' : '-';
aoqi@1 661 f[6] = (denormalized()) ? 'D' : '-';
aoqi@1 662 f[7] = (invalid ()) ? 'I' : '-';
aoqi@1 663 f[8] = '\x0';
aoqi@1 664 // output
aoqi@1 665 printf("%04x flags = %s, cc = %s, top = %d", _value & 0xFFFF, f, c, top());
aoqi@1 666 }
aoqi@1 667
aoqi@1 668 };
aoqi@1 669
aoqi@1 670 class TagWord {
aoqi@1 671 public:
aoqi@1 672 int32_t _value;
aoqi@1 673
aoqi@1 674 int tag_at(int i) const { return (_value >> (i*2)) & 3; }
aoqi@1 675
aoqi@1 676 void print() const {
aoqi@1 677 printf("%04x", _value & 0xFFFF);
aoqi@1 678 }
aoqi@1 679
aoqi@1 680 };
aoqi@1 681
aoqi@1 682 class FPU_Register {
aoqi@1 683 public:
aoqi@1 684 int32_t _m0;
aoqi@1 685 int32_t _m1;
aoqi@1 686 int16_t _ex;
aoqi@1 687
aoqi@1 688 bool is_indefinite() const {
aoqi@1 689 return _ex == -1 && _m1 == (int32_t)0xC0000000 && _m0 == 0;
aoqi@1 690 }
aoqi@1 691
aoqi@1 692 void print() const {
aoqi@1 693 char sign = (_ex < 0) ? '-' : '+';
aoqi@1 694 const char* kind = (_ex == 0x7FFF || _ex == (int16_t)-1) ? "NaN" : " ";
aoqi@1 695 printf("%c%04hx.%08x%08x %s", sign, _ex, _m1, _m0, kind);
aoqi@1 696 };
aoqi@1 697
aoqi@1 698 };
aoqi@1 699
aoqi@1 700 class FPU_State {
aoqi@1 701 public:
aoqi@1 702 enum {
aoqi@1 703 register_size = 10,
aoqi@1 704 number_of_registers = 8,
aoqi@1 705 register_mask = 7
aoqi@1 706 };
aoqi@1 707
aoqi@1 708 ControlWord _control_word;
aoqi@1 709 StatusWord _status_word;
aoqi@1 710 TagWord _tag_word;
aoqi@1 711 int32_t _error_offset;
aoqi@1 712 int32_t _error_selector;
aoqi@1 713 int32_t _data_offset;
aoqi@1 714 int32_t _data_selector;
aoqi@1 715 int8_t _register[register_size * number_of_registers];
aoqi@1 716
aoqi@1 717 int tag_for_st(int i) const { return _tag_word.tag_at((_status_word.top() + i) & register_mask); }
aoqi@1 718 FPU_Register* st(int i) const { return (FPU_Register*)&_register[register_size * i]; }
aoqi@1 719
aoqi@1 720 const char* tag_as_string(int tag) const {
aoqi@1 721 switch (tag) {
aoqi@1 722 case 0: return "valid";
aoqi@1 723 case 1: return "zero";
aoqi@1 724 case 2: return "special";
aoqi@1 725 case 3: return "empty";
aoqi@1 726 }
aoqi@1 727 ShouldNotReachHere();
aoqi@1 728 return NULL;
aoqi@1 729 }
aoqi@1 730
aoqi@1 731 void print() const {
aoqi@1 732 // print computation registers
aoqi@1 733 { int t = _status_word.top();
aoqi@1 734 for (int i = 0; i < number_of_registers; i++) {
aoqi@1 735 int j = (i - t) & register_mask;
aoqi@1 736 printf("%c r%d = ST%d = ", (j == 0 ? '*' : ' '), i, j);
aoqi@1 737 st(j)->print();
aoqi@1 738 printf(" %s\n", tag_as_string(_tag_word.tag_at(i)));
aoqi@1 739 }
aoqi@1 740 }
aoqi@1 741 printf("\n");
aoqi@1 742 // print control registers
aoqi@1 743 printf("ctrl = "); _control_word.print(); printf("\n");
aoqi@1 744 printf("stat = "); _status_word .print(); printf("\n");
aoqi@1 745 printf("tags = "); _tag_word .print(); printf("\n");
aoqi@1 746 }
aoqi@1 747
aoqi@1 748 };
aoqi@1 749
aoqi@1 750 class Flag_Register {
aoqi@1 751 public:
aoqi@1 752 int32_t _value;
aoqi@1 753
aoqi@1 754 bool overflow() const { return ((_value >> 11) & 1) != 0; }
aoqi@1 755 bool direction() const { return ((_value >> 10) & 1) != 0; }
aoqi@1 756 bool sign() const { return ((_value >> 7) & 1) != 0; }
aoqi@1 757 bool zero() const { return ((_value >> 6) & 1) != 0; }
aoqi@1 758 bool auxiliary_carry() const { return ((_value >> 4) & 1) != 0; }
aoqi@1 759 bool parity() const { return ((_value >> 2) & 1) != 0; }
aoqi@1 760 bool carry() const { return ((_value >> 0) & 1) != 0; }
aoqi@1 761
aoqi@1 762 void print() const {
aoqi@1 763 // flags
aoqi@1 764 char f[8];
aoqi@1 765 f[0] = (overflow ()) ? 'O' : '-';
aoqi@1 766 f[1] = (direction ()) ? 'D' : '-';
aoqi@1 767 f[2] = (sign ()) ? 'S' : '-';
aoqi@1 768 f[3] = (zero ()) ? 'Z' : '-';
aoqi@1 769 f[4] = (auxiliary_carry()) ? 'A' : '-';
aoqi@1 770 f[5] = (parity ()) ? 'P' : '-';
aoqi@1 771 f[6] = (carry ()) ? 'C' : '-';
aoqi@1 772 f[7] = '\x0';
aoqi@1 773 // output
aoqi@1 774 printf("%08x flags = %s", _value, f);
aoqi@1 775 }
aoqi@1 776
aoqi@1 777 };
aoqi@1 778
aoqi@1 779 class IU_Register {
aoqi@1 780 public:
aoqi@1 781 int32_t _value;
aoqi@1 782
aoqi@1 783 void print() const {
aoqi@1 784 printf("%08x %11d", _value, _value);
aoqi@1 785 }
aoqi@1 786
aoqi@1 787 };
aoqi@1 788
aoqi@1 789 class IU_State {
aoqi@1 790 public:
aoqi@1 791 Flag_Register _eflags;
aoqi@1 792 IU_Register _rdi;
aoqi@1 793 IU_Register _rsi;
aoqi@1 794 IU_Register _rbp;
aoqi@1 795 IU_Register _rsp;
aoqi@1 796 IU_Register _rbx;
aoqi@1 797 IU_Register _rdx;
aoqi@1 798 IU_Register _rcx;
aoqi@1 799 IU_Register _rax;
aoqi@1 800
aoqi@1 801 void print() const {
aoqi@1 802 // computation registers
aoqi@1 803 printf("rax, = "); _rax.print(); printf("\n");
aoqi@1 804 printf("rbx, = "); _rbx.print(); printf("\n");
aoqi@1 805 printf("rcx = "); _rcx.print(); printf("\n");
aoqi@1 806 printf("rdx = "); _rdx.print(); printf("\n");
aoqi@1 807 printf("rdi = "); _rdi.print(); printf("\n");
aoqi@1 808 printf("rsi = "); _rsi.print(); printf("\n");
aoqi@1 809 printf("rbp, = "); _rbp.print(); printf("\n");
aoqi@1 810 printf("rsp = "); _rsp.print(); printf("\n");
aoqi@1 811 printf("\n");
aoqi@1 812 // control registers
aoqi@1 813 printf("flgs = "); _eflags.print(); printf("\n");
aoqi@1 814 }
aoqi@1 815 };
aoqi@1 816
aoqi@1 817
aoqi@1 818 class CPU_State {
aoqi@1 819 public:
aoqi@1 820 FPU_State _fpu_state;
aoqi@1 821 IU_State _iu_state;
aoqi@1 822
aoqi@1 823 void print() const {
aoqi@1 824 printf("--------------------------------------------------\n");
aoqi@1 825 _iu_state .print();
aoqi@1 826 printf("\n");
aoqi@1 827 _fpu_state.print();
aoqi@1 828 printf("--------------------------------------------------\n");
aoqi@1 829 }
aoqi@1 830
aoqi@1 831 };
aoqi@1 832
aoqi@1 833
aoqi@1 834
aoqi@1 835

mercurial