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)

     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     assert(false, "should not use j/jal here");
   241     break;
   242   default:
   243     assert(is_simm16(v), "must be simm16");
   244 #ifndef PRODUCT
   245     if(!is_simm16(v))
   246     {
   247       tty->print_cr("must be simm16");
   248       tty->print_cr("Inst: %lx", inst);
   249     }
   250 #endif
   252     v = low16(v);
   253     inst &= 0xffff0000;
   254     break;
   255   }
   257   return inst | v;
   258 }
   260 int Assembler::branch_destination(int inst, int pos) {
   261   int off;
   263   switch(opcode(inst)) {
   264   case j_op:
   265   case jal_op:
   266     assert(false, "should not use j/jal here");
   267     break;
   268   default:
   269     off = expand(low16(inst), 15);
   270     break;
   271   }
   273   return off ? pos + 4 + (off<<2) : 0;
   274 }
   276 int AbstractAssembler::code_fill_byte() {
   277     return 0x00;                  // illegal instruction 0x00000000
   278 }
   280 // Now the Assembler instruction (identical for 32/64 bits)
   282 void Assembler::lb(Register rt, Address src) {
   283   lb(rt, src.base(), src.disp());
   284 }
   286 void Assembler::lbu(Register rt, Address src) {
   287   lbu(rt, src.base(), src.disp());
   288 }
   290 void Assembler::ld(Register rt, Address src){
   291   ld(rt, src.base(), src.disp());
   292 }
   294 void Assembler::ldl(Register rt, Address src){
   295   ldl(rt, src.base(), src.disp());
   296 }
   298 void Assembler::ldr(Register rt, Address src){
   299   ldr(rt, src.base(), src.disp());
   300 }
   302 void Assembler::lh(Register rt, Address src){
   303   lh(rt, src.base(), src.disp());
   304 }
   306 void Assembler::lhu(Register rt, Address src){
   307   lhu(rt, src.base(), src.disp());
   308 }
   310 void Assembler::ll(Register rt, Address src){
   311   ll(rt, src.base(), src.disp());
   312 }
   314 void Assembler::lld(Register rt, Address src){
   315   lld(rt, src.base(), src.disp());
   316 }
   318 void Assembler::lw(Register rt, Address src){
   319   lw(rt, src.base(), src.disp());
   320 }
   321 void Assembler::lea(Register rt, Address src) {
   322   Register dst   = rt;
   323   Register base  = src.base();
   324   Register index = src.index();
   326   int scale = src.scale();
   327   int disp  = src.disp();
   329   if (index == noreg) {
   330     if (is_simm16(disp)) {
   331       daddiu(dst, base, disp);
   332     } else {
   333       lui(AT, split_low(disp >> 16));
   334       if (split_low(disp)) ori(AT, AT, split_low(disp));
   335       daddu(dst, base, AT);
   336     }
   337   } else {
   338     if (scale == 0) {
   339       if (is_simm16(disp)) {
   340         daddu(AT, base, index);
   341         daddiu(dst, AT, disp);
   342       } else {
   343         lui(AT, split_low(disp >> 16));
   344         if (split_low(disp)) ori(AT, AT, split_low(disp));
   345         daddu(AT, base, AT);
   346         daddu(dst, AT, index);
   347       }
   348     } else {
   349       if (is_simm16(disp)) {
   350         dsll(AT, index, scale);
   351         daddu(AT, AT, base);
   352         daddiu(dst, AT, disp);
   353       } else {
   354         lui(AT, split_low(disp >> 16));
   355         if (split_low(disp)) ori(AT, AT, split_low(disp));
   356         daddu(AT, AT, base);
   357         dsll(dst, index, scale);
   358         daddu(dst, dst, AT);
   359       }
   360     }
   361   } 
   362 }
   364 void Assembler::lwl(Register rt, Address src){
   365   lwl(rt, src.base(), src.disp());
   366 }
   368 void Assembler::lwr(Register rt, Address src){
   369   lwr(rt, src.base(), src.disp());
   370 }
   372 void Assembler::lwu(Register rt, Address src){
   373   lwu(rt, src.base(), src.disp());
   374 }
   376 void Assembler::sb(Register rt, Address dst) {
   377   sb(rt, dst.base(), dst.disp());
   378 }
   380 void Assembler::sc(Register rt, Address dst) {
   381   sc(rt, dst.base(), dst.disp());
   382 }
   384 void Assembler::scd(Register rt, Address dst) {
   385   scd(rt, dst.base(), dst.disp());
   386 }
   388 void Assembler::sd(Register rt, Address dst) {
   389   Register src   = rt;
   390   Register base  = dst.base();
   391   Register index = dst.index();
   393   int scale = dst.scale();
   394   int disp  = dst.disp();
   396   if(index != noreg) {
   397     if(is_simm16(disp)) {
   398       if( UseLoongsonISA && is_simm(disp, 8)) {
   399         if (scale == 0) {
   400           gssdx(src, base, index, disp);
   401         } else {
   402           dsll(AT, index, scale);
   403           gssdx(src, base, AT, disp);
   404         }
   405       } else {
   406         if (scale == 0) {
   407           daddu(AT, base, index);
   408         } else {
   409           dsll(AT, index, scale);
   410           daddu(AT, base, AT);
   411         }
   412         sd(src, AT, disp);
   413       }
   414     } else {
   415       if (scale == 0) {
   416         lui(AT, split_low(disp >> 16));
   417         if (split_low(disp)) ori(AT, AT, split_low(disp));
   418         daddu(AT, AT, base);
   419         if(UseLoongsonISA) {
   420           gssdx(src, AT, index, 0);
   421         } else {
   422           daddu(AT, AT, index);
   423           sd(src, AT, 0);
   424         }
   425       } else {
   426         dsll(AT, index, scale);
   427         daddu(AT, base, AT);
   428         lui(T9, split_low(disp >> 16));
   429         if (split_low(disp)) ori(T9, T9, split_low(disp));
   430         if(UseLoongsonISA) {
   431           gssdx(src, AT, T9, 0);
   432         } else {
   433           daddu(AT, AT, T9);
   434           sd(src, AT, 0);
   435         }
   436       }
   437     }
   438   } else {
   439     if(is_simm16(disp)) {
   440       sd(src, base, disp);
   441     } else {
   442       lui(AT, split_low(disp >> 16));
   443       if (split_low(disp)) ori(AT, AT, split_low(disp));
   445       if(UseLoongsonISA) {
   446         gssdx(src, base, AT, 0);
   447       } else {
   448         daddu(AT, base, AT);
   449         sd(src, AT, 0);
   450       }
   451     }
   452   }
   453 }
   455 void Assembler::sdl(Register rt, Address dst) {
   456   sdl(rt, dst.base(), dst.disp());
   457 }
   459 void Assembler::sdr(Register rt, Address dst) {
   460   sdr(rt, dst.base(), dst.disp());
   461 }
   463 void Assembler::sh(Register rt, Address dst) {
   464   sh(rt, dst.base(), dst.disp());
   465 }
   467 void Assembler::sw(Register rt, Address dst) {
   468   Register src   = rt;
   469   Register base  = dst.base();
   470   Register index = dst.index();
   472   int scale = dst.scale();
   473   int disp  = dst.disp();
   475   if(index != noreg) {
   476     if( Assembler::is_simm16(disp) ) {
   477       if( UseLoongsonISA && Assembler::is_simm(disp, 8) ) {
   478         if (scale == 0) {
   479           gsswx(src, base, index, disp);
   480         } else {
   481           dsll(AT, index, scale);
   482           gsswx(src, base, AT, disp);
   483         }
   484       } else {
   485         if (scale == 0) {
   486           daddu(AT, base, index);
   487         } else {
   488           dsll(AT, index, scale);
   489           daddu(AT, base, AT);
   490         }
   491         sw(src, AT, disp);
   492       }
   493     } else {
   494       if (scale == 0) {
   495         lui(AT, split_low(disp >> 16));
   496         if (split_low(disp)) ori(AT, AT, split_low(disp));
   497         daddu(AT, AT, base);
   498         if( UseLoongsonISA ) {
   499           gsswx(src, AT, index, 0);
   500         } else {
   501           daddu(AT, AT, index);
   502           sw(src, AT, 0);
   503         }
   504       } else {
   505         dsll(AT, index, scale);
   506         daddu(AT, base, AT);
   507         lui(T9, split_low(disp >> 16));
   508         if (split_low(disp)) ori(T9, T9, split_low(disp));
   509         if( UseLoongsonISA ) {
   510           gsswx(src, AT, T9, 0);
   511         } else {
   512           daddu(AT, AT, T9);
   513           sw(src, AT, 0);
   514         }
   515       }
   516     }
   517   } else {
   518     if( Assembler::is_simm16(disp) ) {
   519       sw(src, base, disp);
   520     } else {
   521       lui(AT, split_low(disp >> 16));
   522       if (split_low(disp)) ori(AT, AT, split_low(disp));
   524       if( UseLoongsonISA ) {
   525         gsswx(src, base, AT, 0);
   526       } else {
   527         daddu(AT, base, AT);
   528         sw(src, AT, 0);
   529       }
   530     }
   531   }
   532 }
   534 void Assembler::swl(Register rt, Address dst) {
   535   swl(rt, dst.base(), dst.disp());
   536 }
   538 void Assembler::swr(Register rt, Address dst) {
   539   swr(rt, dst.base(), dst.disp());
   540 }
   542 void Assembler::lwc1(FloatRegister rt, Address src) {
   543   lwc1(rt, src.base(), src.disp());
   544 }
   546 void Assembler::ldc1(FloatRegister rt, Address src) {
   547   ldc1(rt, src.base(), src.disp());
   548 }
   550 void Assembler::swc1(FloatRegister rt, Address dst) {
   551   swc1(rt, dst.base(), dst.disp());
   552 }
   554 void Assembler::sdc1(FloatRegister rt, Address dst) {
   555   sdc1(rt, dst.base(), dst.disp());
   556 }
   558 void Assembler::j(address entry) {
   559 #ifdef MIPS64
   560   int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xfffffffff0000000))>>2;
   561 #else
   562   int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xf0000000))>>2;
   563 #endif
   564   emit_long((j_op<<26) | dest);
   565   has_delay_slot();
   566 }
   568 void Assembler::jal(address entry) {
   569 #ifdef MIPS64
   570   int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xfffffffff0000000))>>2;
   571 #else
   572   int dest = ((intptr_t)entry - (((intptr_t)pc() + 4) & 0xf0000000))>>2;
   573 #endif
   574   emit_long((jal_op<<26) | dest);
   575   has_delay_slot();
   576 }
   579 class ControlWord {
   580         public:
   581                 int32_t _value;
   583   int  rounding_control() const        { return  (_value >> 10) & 3      ; }
   584   int  precision_control() const       { return  (_value >>  8) & 3      ; }
   585   bool precision() const               { return ((_value >>  5) & 1) != 0; }
   586   bool underflow() const               { return ((_value >>  4) & 1) != 0; }
   587   bool overflow() const                { return ((_value >>  3) & 1) != 0; }
   588   bool zero_divide() const             { return ((_value >>  2) & 1) != 0; }
   589   bool denormalized() const            { return ((_value >>  1) & 1) != 0; }
   590   bool invalid() const                 { return ((_value >>  0) & 1) != 0; }
   592   void print() const {
   593     // rounding control
   594     const char* rc;
   595     switch (rounding_control()) {
   596       case 0: rc = "round near"; break;
   597       case 1: rc = "round down"; break;
   598       case 2: rc = "round up  "; break;
   599       case 3: rc = "chop      "; break;
   600     };
   601     // precision control
   602     const char* pc;
   603     switch (precision_control()) {
   604       case 0: pc = "24 bits "; break;
   605       case 1: pc = "reserved"; break;
   606       case 2: pc = "53 bits "; break;
   607       case 3: pc = "64 bits "; break;
   608     };
   609     // flags
   610     char f[9];
   611     f[0] = ' ';
   612     f[1] = ' ';
   613     f[2] = (precision   ()) ? 'P' : 'p';
   614     f[3] = (underflow   ()) ? 'U' : 'u';
   615     f[4] = (overflow    ()) ? 'O' : 'o';
   616     f[5] = (zero_divide ()) ? 'Z' : 'z';
   617     f[6] = (denormalized()) ? 'D' : 'd';
   618     f[7] = (invalid     ()) ? 'I' : 'i';
   619     f[8] = '\x0';
   620     // output
   621     printf("%04x  masks = %s, %s, %s", _value & 0xFFFF, f, rc, pc);
   622   }
   624 };
   626 class StatusWord {
   627  public:
   628   int32_t _value;
   630   bool busy() const                    { return ((_value >> 15) & 1) != 0; }
   631   bool C3() const                      { return ((_value >> 14) & 1) != 0; }
   632   bool C2() const                      { return ((_value >> 10) & 1) != 0; }
   633   bool C1() const                      { return ((_value >>  9) & 1) != 0; }
   634   bool C0() const                      { return ((_value >>  8) & 1) != 0; }
   635   int  top() const                     { return  (_value >> 11) & 7      ; }
   636   bool error_status() const            { return ((_value >>  7) & 1) != 0; }
   637   bool stack_fault() const             { return ((_value >>  6) & 1) != 0; }
   638   bool precision() const               { return ((_value >>  5) & 1) != 0; }
   639   bool underflow() const               { return ((_value >>  4) & 1) != 0; }
   640   bool overflow() const                { return ((_value >>  3) & 1) != 0; }
   641   bool zero_divide() const             { return ((_value >>  2) & 1) != 0; }
   642   bool denormalized() const            { return ((_value >>  1) & 1) != 0; }
   643   bool invalid() const                 { return ((_value >>  0) & 1) != 0; }
   645   void print() const {
   646     // condition codes
   647     char c[5];
   648     c[0] = (C3()) ? '3' : '-';
   649     c[1] = (C2()) ? '2' : '-';
   650     c[2] = (C1()) ? '1' : '-';
   651     c[3] = (C0()) ? '0' : '-';
   652     c[4] = '\x0';
   653     // flags
   654     char f[9];
   655     f[0] = (error_status()) ? 'E' : '-';
   656     f[1] = (stack_fault ()) ? 'S' : '-';
   657     f[2] = (precision   ()) ? 'P' : '-';
   658     f[3] = (underflow   ()) ? 'U' : '-';
   659     f[4] = (overflow    ()) ? 'O' : '-';
   660     f[5] = (zero_divide ()) ? 'Z' : '-';
   661     f[6] = (denormalized()) ? 'D' : '-';
   662     f[7] = (invalid     ()) ? 'I' : '-';
   663     f[8] = '\x0';
   664     // output
   665     printf("%04x  flags = %s, cc =  %s, top = %d", _value & 0xFFFF, f, c, top());
   666   }
   668 };
   670 class TagWord {
   671  public:
   672   int32_t _value;
   674   int tag_at(int i) const              { return (_value >> (i*2)) & 3; }
   676   void print() const {
   677     printf("%04x", _value & 0xFFFF);
   678   }
   680 };
   682 class FPU_Register {
   683  public:
   684   int32_t _m0;
   685   int32_t _m1;
   686   int16_t _ex;
   688   bool is_indefinite() const           {
   689     return _ex == -1 && _m1 == (int32_t)0xC0000000 && _m0 == 0;
   690   }
   692   void print() const {
   693     char  sign = (_ex < 0) ? '-' : '+';
   694     const char* kind = (_ex == 0x7FFF || _ex == (int16_t)-1) ? "NaN" : "   ";
   695     printf("%c%04hx.%08x%08x  %s", sign, _ex, _m1, _m0, kind);
   696   };
   698 };
   700 class FPU_State {
   701  public:
   702   enum {
   703     register_size       = 10,
   704     number_of_registers =  8,
   705     register_mask       =  7
   706   };
   708   ControlWord  _control_word;
   709   StatusWord   _status_word;
   710   TagWord      _tag_word;
   711   int32_t      _error_offset;
   712   int32_t      _error_selector;
   713   int32_t      _data_offset;
   714   int32_t      _data_selector;
   715   int8_t       _register[register_size * number_of_registers];
   717   int tag_for_st(int i) const          { return _tag_word.tag_at((_status_word.top() + i) & register_mask); }
   718   FPU_Register* st(int i) const        { return (FPU_Register*)&_register[register_size * i]; }
   720   const char* tag_as_string(int tag) const {
   721     switch (tag) {
   722       case 0: return "valid";
   723       case 1: return "zero";
   724       case 2: return "special";
   725       case 3: return "empty";
   726     }
   727     ShouldNotReachHere();
   728     return NULL;
   729   }
   731   void print() const {
   732     // print computation registers
   733     { int t = _status_word.top();
   734       for (int i = 0; i < number_of_registers; i++) {
   735         int j = (i - t) & register_mask;
   736         printf("%c r%d = ST%d = ", (j == 0 ? '*' : ' '), i, j);
   737         st(j)->print();
   738         printf(" %s\n", tag_as_string(_tag_word.tag_at(i)));
   739       }
   740     }
   741     printf("\n");
   742     // print control registers
   743     printf("ctrl = "); _control_word.print(); printf("\n");
   744     printf("stat = "); _status_word .print(); printf("\n");
   745     printf("tags = "); _tag_word    .print(); printf("\n");
   746   }
   748 };
   750 class Flag_Register {
   751  public:
   752   int32_t _value;
   754   bool overflow() const                { return ((_value >> 11) & 1) != 0; }
   755   bool direction() const               { return ((_value >> 10) & 1) != 0; }
   756   bool sign() const                    { return ((_value >>  7) & 1) != 0; }
   757   bool zero() const                    { return ((_value >>  6) & 1) != 0; }
   758   bool auxiliary_carry() const         { return ((_value >>  4) & 1) != 0; }
   759   bool parity() const                  { return ((_value >>  2) & 1) != 0; }
   760   bool carry() const                   { return ((_value >>  0) & 1) != 0; }
   762   void print() const {
   763     // flags
   764     char f[8];
   765     f[0] = (overflow       ()) ? 'O' : '-';
   766     f[1] = (direction      ()) ? 'D' : '-';
   767     f[2] = (sign           ()) ? 'S' : '-';
   768     f[3] = (zero           ()) ? 'Z' : '-';
   769     f[4] = (auxiliary_carry()) ? 'A' : '-';
   770     f[5] = (parity         ()) ? 'P' : '-';
   771     f[6] = (carry          ()) ? 'C' : '-';
   772     f[7] = '\x0';
   773     // output
   774     printf("%08x  flags = %s", _value, f);
   775   }
   777 };
   779 class IU_Register {
   780  public:
   781   int32_t _value;
   783   void print() const {
   784     printf("%08x  %11d", _value, _value);
   785   }
   787 };
   789 class IU_State {
   790  public:
   791   Flag_Register _eflags;
   792   IU_Register   _rdi;
   793   IU_Register   _rsi;
   794   IU_Register   _rbp;
   795   IU_Register   _rsp;
   796   IU_Register   _rbx;
   797   IU_Register   _rdx;
   798   IU_Register   _rcx;
   799   IU_Register   _rax;
   801   void print() const {
   802     // computation registers
   803     printf("rax,  = "); _rax.print(); printf("\n");
   804     printf("rbx,  = "); _rbx.print(); printf("\n");
   805     printf("rcx  = "); _rcx.print(); printf("\n");
   806     printf("rdx  = "); _rdx.print(); printf("\n");
   807     printf("rdi  = "); _rdi.print(); printf("\n");
   808     printf("rsi  = "); _rsi.print(); printf("\n");
   809     printf("rbp,  = "); _rbp.print(); printf("\n");
   810     printf("rsp  = "); _rsp.print(); printf("\n");
   811     printf("\n");
   812     // control registers
   813     printf("flgs = "); _eflags.print(); printf("\n");
   814   }
   815 };
   818 class CPU_State {
   819  public:
   820   FPU_State _fpu_state;
   821   IU_State  _iu_state;
   823   void print() const {
   824     printf("--------------------------------------------------\n");
   825     _iu_state .print();
   826     printf("\n");
   827     _fpu_state.print();
   828     printf("--------------------------------------------------\n");
   829   }
   831 };

mercurial