Tue, 24 Oct 2017 14:04:09 +0800
[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 };