src/cpu/mips/vm/assembler_mips.cpp

Thu, 24 May 2018 19:26:50 +0800

author
aoqi
date
Thu, 24 May 2018 19:26:50 +0800
changeset 8862
fd13a567f179
parent 8027
23d8d77777e0
child 8863
5376ce0dc552
permissions
-rw-r--r--

#7046 C2 supports long branch
Contributed-by: fujie

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

mercurial