Thu, 24 May 2018 19:26:50 +0800
#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 };