ms.h 44.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */


	/*
	 *  ms.h  -  Generic definitions for the MXS simulator component
	 *
	 *	Jim Bennett
	 *	1993, 1994, 1995
	 */

#ifdef MIPSY_MXS
#include <sys/types.h>
#include "annotations.h"
#if 0
#include "cpu_state.h"
#endif
#endif

#include <stdio.h>
#include "ms_param.h"
#include "ms_cache.h"
#include "ms_wrklst.h"
#include "mc_opc.h"

	/*
	 *  Global variables in the simulator
	 */

extern	int	true_inst_hi;		/* Instruction count (optional)	*/
extern	int	true_inst_lo;

extern	int	min_special_preg;	/* Range of special physical reg's */
extern	int	max_special_preg;

#define	preg_is_special(rg)	\
	(((rg) >= min_special_preg) && ((rg) <= max_special_preg))

extern	char	*statfilename;		/* File for MXS statistics	*/
#ifdef TRACE
extern	char	*tracefilename;
extern	FILE	*tracefile;		/* File for address trace	*/
extern	int	trace_writes;		/* If only writes should be traced */
#endif

#ifdef BREAKPOINT
extern	int	brkpt;			/* Global breakpoint register	*/
extern	int	jmpbrk;			/* Branch target breakpoint	*/
extern	int	cycbrk;			/* Cycle count breakpoint	*/
extern	int	linbrk;			/* Cache line breakpoint	*/
extern	int	membrk;			/* Memory breakpoint		*/
extern	int	opcbrk;			/* Opcode breakpoint		*/

extern	int	trace_reg;		/* Register for tracing		*/
extern	int	trace_preg;		/* Physical version of above	*/
#endif

#ifdef PRINT_INSTRUCTIONS
extern	int	enable_iprint;		/* Instruction print control	*/
extern	int	enable_fprint;		/* Branch processing print ctrl	*/
extern	int	enable_eprint;		/* Exception processing  "   "	*/
extern	int	iprint_frequency;	/* Sampling frequency for iprint */
#endif

	/*
	 *  Common parameters and fixed definitions.  Typically the
	 *	parameters are set large enough so that they don't cause
	 *	any slowdown.
	 */

#define	MAX_WORK_ITEMS	128		/* Size of worklist array	*/
#define	MAX_CALLBACK	 64		/* Number of memory system callbacks */

#define	MAX_FP		TOT_REG
#define	MIN_IVAR	MAX_FP
#define	MAX_VAR		MAX_FP

					/* Bound on physical registers	*/
#define	MAX_PREG	((TOT_REG + TOTAL_INST)*2)
					/* Pregs are allocated in pairs	*/

#define	SYSREG_L	2		/* Registers used by system calls */
#define	SYSREG_U	7

#ifdef MIPSY_MXS
#define	PC_INC	4
#else
#define	PC_INC	1
#endif



#ifndef MIPSY_MXS
extern	int	*symbuf;		/* Symbol table			*/
extern	int	symsize;

/************************************************************************/
/*									*/
/*	File header for the MXS executable (simulatable?) format	*/
/*									*/
/************************************************************************/

#define	MS_MAGIC	0x4d58534d

struct	ms_header
	{
	uint	magic;			/* Identify file type and	*/
	uint	version;		/* version of compiler		*/
	uint	revision;

	int	renamed;		/* Compiler options		*/
	int	scheduled;
	float	miss_probability;

	uint	data_base;		/* Location and length of data	*/
	uint	max_data;
	uint	text_base;		/* Location and length of text	*/
	uint	max_text;
	uint	start;
	uint	ct_size;		/* Compiled code segment	*/
	uint	sym_size;		/* Symbol table segment length	*/

	uint	hashsize;		/* Size of hash table		*/
	uint	hashprime;		/* Prime to access hash table	*/
	uint	entry_valid;		/* How many valid entries?	*/
	uint	entry_coll;		/* How many are collisions?	*/
	uint	collisions;		/* Number of overflow entries	*/
	uint	maxdepth;		/* Worst case collisions	*/
	uint	synonyms;		/* Number of address synonyms	*/
	};

struct	s_coll				/* Collision record from hash table */
	{
	uint	addr;
	uint	cadr;
	};

struct s_clnk				/* Linked list of collisions	*/
	{
	struct	s_clnk	*next;
	uint	addr;
	uint	cadr;
	};

struct s_sym				/* Symbol table entry		*/
	{
	uint	addr;
	int	height;
	int	cycle;
	int	len;
	};

#define	OUTSIDE_ADDR	((uint)0xffffffff)
#define	UNKNOWN_ADDR	((uint)0xfffffffe)
#define	COLLISION_ADDR	((uint)0xfffffffd)


	/*
	 *  Structure for mapping of text and data addresses
	 */

struct	s_procmap
	{
	uint	text_base;		/* Offset of text segment	*/
	uint	max_text;
	uint	data_base;		/* Offset of data segment	*/
	uint	data_top;		/* Top of data segment		*/

	char	*text_buf;		/* Pointers to segments		*/
	char	*data_buf;
	INST	*ctbuf;			/* Compiled code buffer		*/
	int	ctsize;

	uint	*bbhash;		/* Hash table for conversion	*/
	uint	*bbaddr;		/* of branch addresses to	*/
	struct s_clnk **bbcoll;		/* offsets into compiled code	*/

	uint	*adrhash;		/* And for branch addresses	*/
	struct s_clnk **adrcoll;	/* back to offsets		*/

	int	hashsize;		/* offsets into compiled code	*/
	int	hashprime;
	};

extern	struct	s_procmap	pmap;

#endif		/* !MIPSY_MXS	*/

/************************************************************************/
/*									*/
/*	Definitions for statistics gathering.				*/
/*									*/
/************************************************************************/


#define	ST_NO_EXCUSE		 0	/* Stalled for no reason	*/

	/* Fetch efficiency statistics	*/

#define	ST_FETCHES_TRIED	 1	/* Fetches attempted		*/
#define	ST_FETCHES		 2	/* Successful fetches		*/
#define ST_FETCH_EXPEND		 3	/* Failure  - Exception pending. */
#define	ST_FETCH_IW_FULL	 4	/* Failures - issue window full	*/
#define	ST_FETCH_RB_FULL	 5	/* Failures - reorder buf. full	*/
#define	ST_FETCH_THREAD		 6	/* Ran out of threads		*/
#define	ST_FETCH_NAME		 7	/* Rename failed, due to one of: */
#define	ST_REG_ERROR		 8	/* Reference to poisoned reg.	*/
#define	ST_REG_BUSY		 9	/* All registers in use		*/
#define	ST_REG_CLAIMED		10	/* Register preclaimed		*/
#define	ST_REG_SPEC		11	/* Special register still in use */

#define	ST_FETCH_STALL		20	/* Failures - threads stalled	*/
#define	ST_FETCH_STALLTHREAD	21	/* Fetch stall - not enough threads */
#define ST_FETCH_STALLBRANCH	22
#define ST_FETCH_STALLFPC	23
#define ST_FETCH_STALLICACHE	24
#define ST_FETCH_STALLITLB	25
#define ST_FETCH_STALLEXCEPT	26
#define	ST_FETCH_STALLSYS	27
#define	ST_FETCH_STALLCP0	28
#define	ST_FETCH_STALLSC	29

#define	ST_FETCH_STALL_OTH	30	/* Fetch stall - unidentified	*/
#define	ST_FETCH_STALL_INV	31	/* Fetch stall - invalid addr	*/
#define ST_FETCH_CACHEFAILURE   32

	/* Of the fetched instructions, what is their disposition?	*/

#define	ST_EXECUTED		40	/* Instructions executed	*/
#define	ST_EXBRANCH		41	/* Executed in branch unit	*/
#define	ST_PRUNED		42	/* Instructions squashed	*/
#define	ST_EXPRUNE		43	/* Executed, then squashed	*/

	/* Issue efficiency statistics	*/

#define	ST_ISSUE_STALLED	44	/* No issues this cycle		*/
#define	ST_EXCEPT		45	/* Interrupt stall cycles	*/
#define	ST_LSQ_FULL		46	/* Load/store queue is full	*/
#define	ST_SYSCALL		47	/* Force synchronization for syscall */
#define	ST_FPC			48	/* Force sync. for FP control write */

	/* Of the attempted issues, either they are executed	*/
	/* (ST_EXECUTED, above), or they are PhaseA issues,	*/
	/* or they fail, either due to an empty instruction	*/
	/* window, or to a stall waiting for results.		*/

#define	ST_ISSUE_TRIED		49	/* Count of issues attempted	*/
#define	ST_PHASE_A		50	/* Number of Phase A issues	*/
#define	ST_IWIN_EMPTY		51	/* No instructions available	*/
#define	ST_INST_STALLED		52	/* Instruction not ready	*/

	/* Reasons why instruction not ready	*/

#define	ST_IWIN_FLUSH		53	/* Waiting for IWIN to empty out */
#define	ST_LDST_DEP		54	/* Waiting on load/store dependency */
#define	ST_LDST_FULL		55	/* Couldn't reserve ldst buffer	*/
#define	ST_BR_DLY		56	/* Need to fetch opcode in branch delay	*/
#define	ST_SPEC_CTL		57	/* Speculative control write	*/
#define	ST_REG_DEP		58	/* Stalled on register dependency */

	/* Reasons for register dependencies	*/

#define	ST_NOT_ISSUED		60	/* Source inst not issued yet	*/
#define	ST_PC_DLY		61	/* Primary cache delay slot	*/
#define	ST_IMUL			62	/* Waiting for integer multiply	*/
#define	ST_IDIV			63	/* Waiting for integer divide	*/
#define	ST_FPADD		64	/* Waiting for FP add operation	*/
#define	ST_FPMUL		65	/* Waiting for FP multiply	*/
#define	ST_FPDIV		66	/* Waiting for FP divide	*/
#define	ST_FPSQRT		67	/* Waiting for FP square root	*/
#define	ST_FPCMP		68	/* Waiting for FP compare	*/
#define	ST_FPABS		69	/* Waiting for FP absolute value */
#define	ST_FPNEG		70	/* Waiting for FP negate	*/
#define	ST_FPCVT		71	/* Waiting for FP convert	*/
#define	ST_CACHE_LSQ		72	/* Waiting for load in queue	*/
#define	ST_CACHE_LBSY		73	/* Waiting in cache line busy q	*/
#define	ST_CACHE_BUS		74	/* Waiting for bus completion	*/

	/* Wasted or useless instructions	*/

#define	ST_NOP			75	/* No-op instruction		*/
#define	ST_BR_NOP		76	/* No-op in branch delay slot	*/

	/* Branch prediction statistics		*/

#define	ST_UNCOND_BR		80	/* Unconditional branch		*/
#define	ST_COND_BR		81	/* Number of conditional branches */
#define	ST_IND_BR		82	/* Number of indirect branches	*/

#define	ST_CORRECT_FALLTHRU	83	/* Correctly predicted branches	*/
#define	ST_CORRECT_W_FALLTHRU	84
#define	ST_CORRECT_W_TAKEN	85
#define	ST_CORRECT_TAKEN	86
#define	ST_CORRECT_IND_BR	87
#define ST_CORRECT_JRET		88
#define ST_CORRECT_LIKELY	89

#define	ST_INCORRECT_FALLTHRU	90	/* Incorrectly predicted branches */
#define	ST_INCORRECT_W_FALLTHRU	91
#define	ST_INCORRECT_TAKEN	92
#define	ST_INCORRECT_W_TAKEN	93
#define	ST_INCORRECT_IND_BR	94
#define ST_INCORRECT_JRET	95
#define ST_INCORRECT_LIKELY	96

	/* Memory subsystem statistics		*/

#define	ST_NLOADS		100	/* Total number of loads	*/
#define	ST_NSTORES		101	/* Total number of stores	*/
#define ST_LSOP_UNCACHED_LOAD	103
#define ST_LSOP_UNCACHED_STORE  104

	/* From standalone cache subsystem	*/

#define	ST_DREADMISS		105	/* Dirty read misses		*/
#define	ST_DWRITEMISS		106	/* Dirty write misses		*/
#define	ST_READMISS		107	/* Total read misses		*/
#define	ST_WRITEMISS		108	/* Total write misses		*/

	/* Load/store buffer statistics	*/

#define	ST_LDSTDEP_CONISSUE	110
#define ST_LDSTDEP		111
#define ST_LDSTDEP_FAIL		112
#define ST_LDSTDEP_CONFLICT	113

#define ST_LDST_RETIRE_LOAD	114
#define ST_LDST_RETIRE_STORE	115
#define ST_LDST_INVALIDLOAD	116
#define ST_LDST_WAIT		117
#define ST_LDST_RETIRE_SQUASH	118
#define ST_LDST_REFETCH		119
#define ST_LDST_BUF_SQUASH_ACT  120
#define ST_LDST_BUF_SQUASH	121

	/* Calls to ms_cache	*/

#define ST_CACHE		130
#define ST_CACHE_SQUASHED	131
#define ST_CACHE_CONFLICT	132
#define ST_CACHE_LOAD		133
#define ST_CACHE_STORE		134
#define ST_CACHE_HIT		135
#define ST_CACHE_MISS		136
#define ST_CACHE_FAILURE	137
#define ST_CACHE_LOADHIT	138
#define ST_CACHE_SCFAILURE	139


#define	ST_VCYCS		140	/* Number of cycles in valid	*/
					/* (renameable) procedures.	*/
#define ST_RUN_CYCLES		141	/* Number of calls to ms_cycle_once */
					/* (for Mipsy version).		*/

	/* Exception handling statistics	*/

#define ST_EXCEPT_INST		151
#define ST_EXCEPT_LDST		152
#define ST_EXCEPT_SQUASH	153

#define ST_EXCEPT_WAIT		154	/* Waiting with except pending	*/
#define ST_EXCEPT_ITLB		155
#define ST_EXCEPT_INTR		156
#define ST_EXCEPT_TAKEN		157
#define ST_EXCEPT_COHERENCY	158
#define ST_EXCEPT_SWITCH	159
#define ST_EXCEPT_SWITCH_INST	160
#define ST_EXCEPT_COHER_INST	161
#define ST_EXCEPT_COHER_LDST	162
#define ST_EXCEPT_COHER_SQUASH  163

	/* Graduation statistics	*/

#define ST_GRAD_PHASEASTALL     166
#define ST_GRAD_ISSUESTALL      167
#define ST_GRAD_ICACHESTALL     168
#define ST_GRAD_FLUSHSTALL      169
#define ST_GRADS_TRIED		170
#define ST_GRAD_EXPEND		171
#define ST_GRAD_LDSTALL		172
#define ST_GRAD_SQUASHED	173
#define ST_GRAD_SQUASHED_LDST	174
#define ST_GRAD_INST		175
#define ST_GRAD_INST_LDST	176
#define ST_GRAD_STSTALL         177
#define ST_GRAD_EMPTYSTALL      178
#define ST_GRAD_MISCSTALL       179

#define	ST_NTYPES		180	/* Number of stall types	*/


	/*
	 *  Macro for incrementing a statistics counter
	 */

#define	TICK_COUNT	100000		/* Number of cycles per tick mark */
#define	TICK_DIGITS	5		/* Digits in tick count		*/

#ifdef MIPSY_MXS
#define SIM_MEMORY(x) ((x))
#define CPUNUM(_st) (((CPUState *)((_st)->mipsyPtr))->myNum)
#define bp_pc_to_index(_pc) (((_pc)>>2)&(BP_TABLE_SIZE-1))
#define _smode(_st) CURRENT_MODE((((CPUState *)(_st)->mipsyPtr)))

/* SAH - Warning -> this used to use modes. */
#define	IncStat(sttype)	 st->stats[0][(sttype)]++;


#define	AddToStat(sttype,cnt)	st->stats[_smode(st)][(sttype)] += (cnt);    

#else /* MIPSY_MXS */

#define	NUM_MODES	1

#define	IncStat(sttype)							\
	{ st->stats[0].stat_cycles[(sttype)]++;				\
	  if (st->stats[0].stat_cycles[(sttype)] >= TICK_COUNT)		\
		{ st->stats[0].stat_cycles[(sttype)] -= TICK_COUNT;	\
		st->stats[0].stat_ticks[(sttype)]++; } }

#define	AddToStat(sttype,cnt)						\
	{ st->stats[0].stat_cycles[(sttype)] += (cnt);			\
	  if (st->stats[0].stat_cycles[(sttype)] >= TICK_COUNT)		\
		{ st->stats[0].stat_cycles[(sttype)] -= TICK_COUNT;	\
		st->stats[0].stat_ticks[(sttype)]++; } }

	/*
	 *  Define the conversion from the virtual address of the process
	 *  being simulated to the real address of the data (in the
	 *  simulator's address space).  Needed in order to make system
	 *  calls in behalf of the simulated process
	 */

#define	SIM_MEMORY(x) ((x) >= pmap.data_base ? \
			&pmap.data_buf [(x) - pmap.data_base] : \
			((x) >= pmap.text_base ? \
				&pmap.text_buf [(x) - pmap.text_base] : \
				(void *)(x)) )
#define	CPUNUM(st)		(0)
#define bp_pc_to_index(_pc) ((_pc)&(BP_TABLE_SIZE-1))

#endif /* MIPSY_MXS */


/************************************************************************/
/*									*/
/*		Simulated machine state					*/
/*									*/
/************************************************************************/

typedef	struct			/* Branch tree structure		*/
	{
	int	thread;			/* Thread number of this node	*/
	int	thread_st;		/* Thread status		*/
	int	lchild;			/* Indices of nodes children	*/
	int	rchild;
	int	condition;		/* How to resolve branch	*/
	int	resolution;
	int	indirect;		/* If indirect branch		*/
	int	jret;			/* If subroutine return		*/
	int	call;			/* If a call			*/
	int	uncond;			/* If immediate unconditional	*/
	int	restore;		/* If branch stack needs restore */
	int	iwin_head_th;		/* Chain of instructions for	*/
	int	iwin_tail_th;		/* this node.			*/
	} BrTREE;


struct	s_thread		/* Per thread of control state		*/
	{
	int	pc;			/* Program counter (per thread)	*/
	int	thread_st;		/* Thread status		*/
	int	stall_fetch;		/* If instruction fetch stalled	*/
	int	branch_dly;		/* In branch delay slot		*/
	int	branch_likely;		/* Ditto for branch likely inst's */
	int	stall_fpc;		/* If stall due to FP control write */
	int	stall_branch;		/* Stalled waiting for branch	*/
	int	stall_thread;		/* Stalled waiting for branch -	*/
					/* no free threads		*/
	int	stall_icache;		/* Problem fetching inst. from cache */
        int     icache_stall_reason;    /* Cause of icache stall */
	int	stall_except;		/* Stall due to exception	*/
	int	stall_itlbmiss;		/* Stall due to ITLB miss	*/
	int	stall_sys;		/* Stall due to system call	*/
	int	stall_sc;		/* Stall due to an SC		*/
	int	stall_cp0;		/* Stall due to an CP0 inst	*/
	int	returnpc;		/* Return address PC		*/
	int	branch_sp;		/* Branch stack pointer		*/
	int	old_prediction;		/* Previous value of branch stack */
	int	branch_inum;		/* Index of branch inst.	*/
	int	branch_node;		/* Index of branch tree node	*/
	int	branch_pc;		/* Branch target address	*/
	int	branch_likely_pc;	/* Ditto for branch likely inst's */
	int	except;			/* Type of exception		*/
	struct s_thread *active_thread;	/* Next active thread		*/
	int	debugpc;		/* User PC for debugging	*/
	int	regnames [MAX_VAR];	/* Register names, indexed by	*/
					/* logical register (from inst)	*/
	int	half_def [MAX_VAR/2];	/* Flags for double registers	*/
	};

typedef struct s_thread THREAD;

#define	TH_ACTIVE	0x01			/* If thread active	*/
#define	TH_SPEC		0x02			/* If thread speculative */
#define	TH_BRANCH	0x04			/* If branch graduated	*/

#define	UpdateStallFetch(th)	\
	(th)->stall_fetch = (th)->stall_fpc || (th)->stall_branch ||	\
		(th)->stall_icache || (th)->stall_except ||		\
		(th)->stall_itlbmiss || (th)->stall_sys ||		\
		(th)->stall_sc || (th)->stall_cp0

#define	REGNAME_MASK	0x0ffff
#define	REGNAME_CLAIM	0x10000


struct	s_regstat		/* Register state needed for fast	*/
	{			/* access:				*/
	int	reg_status;		/* Status flags			*/
	int	reg_ref;		/* Reference count for register	*/
	int	reg_nmap;		/* Map count for register	*/
	int	reg_nclaims;		/* Claim count for register	*/
	};

typedef	struct s_regstat REGSTAT;

#define	REG_BUSY	0x0001		/* Physical registers		*/
#define	REG_IN_WIN	0x0002
#define	REG_MAPPED	0x0004
#define	REG_DMAP	0x0008

#define	REG_ERROR	0x0010		/* Indicates a fault		*/
#define	REG_CLAIMED	0x0020		/* Reg belongs to thread	*/
#define	REG_FREED	0x0040		/* Reg should be freed		*/


	/*
	 *  MemCallback  -  This structure holds information about
	 *		    how to handle callbacks from the memory
	 *		    subsystem.
	 */

typedef	struct
	{
	int	next_cb;
	int	action;
	} MemCallback;

#define	ACT_NULL		0	/* Do nothing on callback	*/
#define	ACT_UNSTALL_ICACHE	1	/* Unstall icache on callback	*/
#define ACT_DCACHE_MISS		2	/* A dcache miss finishes	*/


struct	s_cpu_state		/* Holds all processor state.		*/
	{
	int	regs [MAX_PREG];	/* All of the machine registers	*/

	THREAD	threads [THREAD_WIDTH];	/* Threads of execution		*/
	THREAD	*active_thread;		/* First active thread		*/
	int	free_thread;		/* Free list for threads	*/
	int	nthreads;		/* Number of threads		*/
	int	nactive;		/* Number of active threads	*/

	BrTREE	branch_tree [2*THREAD_WIDTH]; /* Active branch tree	*/
	int	free_branch_node;	/* Free list for branch tree	*/

	int	round_mode;		/* FP rounding mode		*/
	int	stall_issue;		/* If instruction issue stalled	*/
	int	stall_type;		/* Reason for inst issue stall	*/
	int	wbacks;			/* Count of write backs this cycle */

		/* Physical register status	*/
	int	reg_owner [MAX_PREG];	/* Owner of this register	*/
	REGSTAT	reg_rstat [MAX_PREG/2];	/* Status of register		*/
	int	reg_excuse [MAX_PREG/2]; /* Reason why reg not yet available */
	int	new_excuse [MAX_PREG/2]; /* Yet another reason why reg ... */
	int	reg_freelist [MAX_PREG/2];
	int	reg_otherhalf2 [MAX_PREG/2]; /* Dependency on first def	*/
	int	reg_otherhalf3 [MAX_PREG/2]; /* carried by r2 or r3	*/
	int	reg_nextfree;

		/* Instruction window, handles dependencies between	*/
		/* instructions, and issues instructions out-of-order.	*/
		/* Includes instructions in execution also.		*/

	int	iwin_ninst;		/* Number of instructions in	*/
					/* window and not yet executing	*/
	INST	iwin [TOTAL_INST];	/* Instruction window		*/
	int	iwin_addr [TOTAL_INST];	/* Address field for load/stores */
	int	iwin_paddr [TOTAL_INST]; /* paddr field for load/stores */
	int	iwin_flags [TOTAL_INST];
	int	iwin_freelist [TOTAL_INST];
					/* Instructions dependent on	*/
					/* this one.			*/
	int	iwin_dep2 [TOTAL_INST] [TOTAL_INST];
	int	iwin_dep3 [TOTAL_INST] [TOTAL_INST];
	int	iwin_index2 [TOTAL_INST];
	int	iwin_index3 [TOTAL_INST];
	int	iwin_pri [TOTAL_INST];	/* Priority chain for insts	*/
	int	iwin_bpri [TOTAL_INST];	/* Back pointers in chain	*/

#ifdef PRECISE
	THREAD	grad;			/* Thread state at graduation point */

	int	iwin_headgrad;		/* Head and tail of graduation queue */
	int	iwin_tailgrad;
	int	iwin_grad [TOTAL_INST];		/* Graduation queue	*/
	int	iwin_bgrd [TOTAL_INST];

	int	iwin_lr1 [TOTAL_INST];		/* Saved logical reg's	*/
	int	iwin_lr2 [TOTAL_INST];
	int	iwin_lr3 [TOTAL_INST];
#endif
	int	iwin_avail_list [TOTAL_INST];	/* Instructions ready	*/
						/* to be executed.	*/
	int	iwin_pc [TOTAL_INST];
#ifdef BREAKPOINT
	int	iwin_curi;
#endif
	int	iwin_nextfree;
	int	iwin_headpri;		/* Prioritized list of instructions */
	int	iwin_tailpri;
	int	iwin_next_avail;	/* Head and tail of available list */
	int	iwin_last_avail;

		/* Special support for speculative execution.		*/

	int	iwin_br_node [TOTAL_INST];	/* Branch tree node	*/
	int	iwin_thread [TOTAL_INST];	/* Thread inst chain	*/
	int	iwin_branch_pc [TOTAL_INST];	/* PC of branch target	*/
	int	iwin_bthread [TOTAL_INST];

		/* Support for memory callbacks into MXS		*/

	int	ms_action;		/* Action to take on callback	*/
					/* (index into callback table)	*/
	int	cb_free;
	MemCallback	callbacks [MAX_CALLBACK];

		/* Special support for load/store ordering.	*/

	int	iwin_ldst [TOTAL_INST];	/* Load/store chain		*/
	int	iwin_bldst [TOTAL_INST];
	int	iwin_head_ldst;
	int	iwin_tail_ldst;
	int	iwin_nldst;		/* Number of items in ldst chain */
#ifdef ONE_PHASE_LS
	int	iwin_nstores;
#endif

		/* Support for exceptions			*/

	int	iwin_except [TOTAL_INST];
	int	exception_pending;
	int	except;

		/* Branch prediction counters and addresses	*/

	int	bp_bits [BP_TABLE_SIZE];
	int	bp_targets [BP_TABLE_SIZE];
	int	branch_stack[BP_RETURN_STACK];
	int	branch_sp;

		/* Execution unit, pointers to executing instructions	*/

	int	ex [2*ISSUE_WIDTH];
	int	ex_count;

		/* Worklist mechanism, handles instruction completion	*/

	int	work_cycle;		/* Total cycles			*/
	int	work_ticks;		/* Total ticks (TICK_COUNT cycles) */

	WorkList *work_head;		/* Prioritized queue of time	*/
	WorkList *work_tail;		/* delayed work items (e.g.	*/
	WorkList *free_head;		/* FP operation write back,	*/
	WorkList *free_tail;		/* or memory load completion).	*/
	WorkList worklist [MAX_WORK_ITEMS];

		/* Load/store buffer, for the memory subsystem		*/

	struct s_ldst_buffer ldst_buffer[LDST_BUFFER_SIZE];
	struct	s_lsq	lsq [LDST_BUFFER_SIZE];
	struct s_ldst_buffer *ldst_nextAvail;
	struct s_ldst_buffer *ldst_nextReserved;
	struct s_ldst_buffer *ldst_head;
	struct s_ldst_buffer *ldst_tail;
	struct s_ldst_buffer *inum2ldst[TOTAL_INST];

		/* Cycle by cycle statistics				*/
        uint64 stats[NUM_MODES][ST_NTYPES];

               /* Sample stats */
        struct {
          uint64 samples;
          uint64 nthreads_hist[THREAD_WIDTH+1];
          uint64 reg_hist[MAX_PREG/2+1];
          struct {
              uint64 inst;       /* Number of instruction in window */
              uint64 specInst;   /* Number of speculative instructions */
              uint64 ldstInst;   /* Number of load/store instructions */
              uint64 ldstdepInst;/* Nubmer of instructions with LDST_DEP */
              uint64 regdepInst; /* Number of inst with REG_DEP* */
              uint64 squashInst; /* Number of squashed instructions */
          } iwin_hist[TOTAL_INST+1];
          struct {
             uint64 inst;        /* Number of inst in ldst buffer */
             uint64 doneInst;    /* Number of finished inst in ldst buffer */
             uint64 pendInst;    /* Number of pending inst */
             uint64 conflictInst; /* Number of conflicted inst */
             uint64 failedInst;  /* Number of failed inst. */
             uint64 stallInst;   /* Number of stalled inst. */
          } ldst_hist[LDST_BUFFER_SIZE+1]; 
          
        } sample_stats[NUM_MODES];

	int	icount;
	void	*mipsyPtr;
	};

extern	struct	s_cpu_state	cpu_state;

	/*
	 *  Status bit definitions for the various components of the model
	 */

#define	IWIN_BUSY	0x0001			/* Inst window: slot busy */
#define	IWIN_DEP2	0x0002			/* Dependency on reg 2	*/
#define	IWIN_DEP3	0x0004			/* Dependency on reg 3	*/
#define	IWIN_FLUSH	0x0008			/* Force instruction	*/
						/* window to empty out.	*/

#define	IWIN_AVAIL	0x0010			/* Ready to be executed	*/
#define	IWIN_LDST	0x0020			/* Is a load or store	*/
#define	IWIN_ISSUED	0x0040			/* Inst has been issued	*/
#define	IWIN_BRDLY	0x0080			/* Waiting for branch	*/
						/* delay to be fetched	*/

#define	IWIN_SPEC	0x0100			/* Speculative inst.	*/
#define	IWIN_SQUASH	0x0200			/* Squashed inst.	*/
#define	IWIN_STORE	0x0400			/* Is a store inst.	*/
#define	IWIN_CTL	0x0800			/* Dest is a special reg */

#define	IWIN_FAULT	0x1000			/* Instruction faulted	*/
#define	IWIN_LDST_DEP	0x2000			/* Load/store dependency */
#define	IWIN_ADDR_VALID	0x4000			/* Address field is valid */

					/* For precise interrupts:	*/
#define	IWIN_FREED	0x08000			/* Instruction can be freed */
#define	IWIN_DEFINE	0x10000			/* Instruction defines a reg */

#define	IWIN_BRANCH	0x20000			/* Branch instruction	*/
#define IWIN_UNCACHED	0x40000			/* Is an uncached load/store */
#define	IWIN_TLBFAULT	0x80000			/* Op suffered a TLB fault */
#define	IWIN_LDSTBUF	0x100000		/* In ldst_buffer	*/
#define	IWIN_ANNOTATED	0x200000		/* Invoke annotation at	*/
						/* graduation time	*/
#define IWIN_TAKENBR    0x400000                /* If branch, was taken. */

#define	BP_TAKEN	0x04			/* Branch prediction bits */
#define	BP_BOTH		0x02			/* Follow both threads?	*/
#define	BP_MAX_VAL	0x07			/* Clamp to this value	*/

#define	PredictTaken(pbits, likely)	\
		(((pbits) & BP_TAKEN) || ((likely) && ((pbits) >= BP_BOTH)))

#define	PRUNE_RIGHT	0x00			/* Which branch to prune? */
#define	PRUNE_LEFT	0x01

	/* Floating point condition code bit.	*/

#define	CONDBIT		0x00800000


	/*
	 *  PhaseA  -  Determine if the instruction is a load/store which
	 *		hasn't yet completed Phase A execution.  In a one
	 *		phase load operation, Phase A is always false.
	 */

#ifdef ONE_PHASE_LS

#define	PhaseA(inum)	0

#else

#define	PhaseA(inum)	\
	((st->iwin_flags [(inum)] & (IWIN_LDST|IWIN_ADDR_VALID)) == IWIN_LDST)

#endif



/************************************************************************/
/*									*/
/*		Macros for register access				*/
/*									*/
/************************************************************************/

	/* Fixed offsets to HI and LO registers	*/

#ifdef LITTLE_ENDIAN

#define	HIREG	(HILOREG+1)
#define	LOREG	HILOREG

#else

#define	HIREG	HILOREG
#define	LOREG	(HILOREG+1)

#endif

	/* Macros for coercing register types		*/

#define	Ireg(r1)	(st->regs[(r1)])
#define	Ureg(r1)	(((unsigned *)st->regs)[(r1)  ])
#define	Freg(r1)	(((float    *)st->regs)[(r1)  ])
#define	Dreg(r1)	(((double   *)st->regs)[(r1)/2])


/************************************************************************/
/*									*/
/*		Function Prototypes					*/
/*									*/
/************************************************************************/

extern	void (*optab[MAX_OP])(struct s_cpu_state *st, INST *ip, THREAD *th);

	/*
	 *  Procedures that implement the opcodes
	 */

extern void opILL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opJ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opJAL(struct s_cpu_state *st, INST *ip, THREAD *th);

extern void opBEQ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBNE(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLEZ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGTZ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLTZ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGEZ(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLTZAL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGEZAL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBC1F(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBC1T(struct s_cpu_state *st, INST *ip, THREAD *th);

extern void opBEQL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBNEL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLEZL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGTZL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLTZL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGEZL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBLTZALL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBGEZALL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBC1FL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBC1TL(struct s_cpu_state *st, INST *ip, THREAD *th);

extern void opADDI(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opADDIU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLTI(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLTIU(struct s_cpu_state *st, INST *ip, THREAD *th);

extern void opANDI(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opORI(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opXORI(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opHCPY(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLB(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLH(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLWL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLW(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLBU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLHU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLWR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLWC1(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLDC1(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSB(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSH(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSWL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSW(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSWR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSWC1(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSDC1(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSRL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSRA(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLLV(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSRLV(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSRAV(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opJR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opJALR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSYSCALL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBREAK(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opMULT(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opMULTU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opDIV(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opDIVU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opADD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opADDU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSUB(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSUBU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opAND(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opOR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opXOR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opNOR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLT(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSLTU(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCPY(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTSW(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTDW(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFADDS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFSUBS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFMULS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFDIVS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFSQRTS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFABSS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFNEGS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFROUNDS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFTRUNCS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFCEILS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFFLOORS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTDS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTWS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCFS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCUNS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCEQS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCUEQS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCOLTS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCULTS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCOLES(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCULES(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCSFS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGLES(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCSEQS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGLS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCLTS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGES(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCLES(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGTS(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFADDD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFSUBD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFMULD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFDIVD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFSQRTD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFABSD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFMOVD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFNEGD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFROUNDD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFTRUNCD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFCEILD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opFFLOORD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTSD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCVTWD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCEQD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCUEQD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCOLTD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCULTD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCOLED(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCULED(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCSEQD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGLD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCLTD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGED(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCLED(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCNGTD(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opJRET(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCTL_FPC(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCTL_CFC(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCTL_DLY(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opCP0(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opBDOOR(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLL(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSC(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opPREF(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opLDHACK(struct s_cpu_state *st, INST *ip, THREAD *th);
extern void opSDHACK(struct s_cpu_state *st, INST *ip, THREAD *th);

extern	void	opsysc (struct s_cpu_state *st, THREAD *th);
extern	void	opmult (struct s_cpu_state *st, INST *ip);
extern	void	opmltu (struct s_cpu_state *st, INST *ip);
extern	void	opdiv (struct s_cpu_state *st, INST *ip);
extern	void	opdivu (struct s_cpu_state *st, INST *ip);

extern	void	unstall_fetch (void *st, void *ix);
extern	void	finish_call (void *st, void *ix);
extern	void	finish_branch (void *st, void *ix);
extern	void	update_excuse (void *st, void *ix);
extern	void	reg_writeback (void *st, void *ix);
extern	void	reg0_writeback (void *st, void *ix);
extern	void	free_spec_inst (struct s_cpu_state *st, int inum);

extern	void	ms_graduate (struct s_cpu_state *st);
extern	void	ms_grad_dequeue (struct s_cpu_state *st, int inum);
extern	void	ms_grad_enqueue (struct s_cpu_state *st, int inum);
extern	void	ms_except (struct s_cpu_state *st);

extern	void	ms_pri_dequeue (struct s_cpu_state *st, int pri);
extern	void	ms_pri_enqueue (struct s_cpu_state *st, int pri);
extern	void	ms_ldst_dequeue (struct s_cpu_state *st, int inum);
extern	void	ms_ldst_enqueue (struct s_cpu_state *st, int inum);

extern	void	ms_st_init (struct s_cpu_state *st);
extern	void	ms_iwin_init (struct s_cpu_state *st);

extern	void	ms_branch (struct s_cpu_state *st, THREAD *th, int likely);
extern	void	prune_branch (struct s_cpu_state *st, int branch_node);
extern	void	speculate_reparent (struct s_cpu_state *st,
					int branch_node, int id_node);
extern	void	speculate_flush (struct s_cpu_state *st, int branch_node);
extern	void	CheckSquash (struct s_cpu_state *st, INST *ip);

extern void	ms_fetch(struct s_cpu_state *st);
extern void	free_inst(struct s_cpu_state *st, int inum);

					/* The load/store buffer	*/
extern void ms_lsq (struct s_cpu_state *st, int addr,
				int reg, int reg2, int lstype, int inum);

extern	void	ms_cycle_once (struct s_cpu_state *st);
extern	void	DoMxsIntervention(struct s_cpu_state *st, int paddr, int size, 
				int writebackonly);
extern	int	CheckIntervention (struct s_cpu_state *st,
					void *mtag, int paddr, int size);
extern	void	DoMxsAction(struct s_cpu_state *st, void *mtag, int ms_action);
extern	int	GetMxsAction(struct s_cpu_state *st);

extern  void MxsSampleStats(struct s_cpu_state *st, int mode);
extern  int MxsApproveImiss(struct s_cpu_state *st,int paddr);

#ifndef MIPSY_MXS
extern	void	ms_init_hash (uint *bbhash, uint *bbaddr,
			struct s_clnk ***bbcoll, uint *adrhash,
			struct s_clnk ***adrcoll, int hashsize, int hashprime,
			struct s_coll *bbclst, int ncoll,
			struct s_coll *syn_list, int nsyns);
#endif
extern	void	ms_cycle_loop (struct s_cpu_state *st);
extern	void	init_cache (struct s_cpu_state *st);

extern	void	compile_inst (uint inst, uint addr, INST *ip,
				int *squashed, int *branch_shadow);

extern	void set_rm (int mode);
extern	void print_inst (FILE *stream, INST *ip);
extern	void print_reg (FILE *stream, int r);
extern	void print_reg_contents (FILE *stream, int r, void *ptr);
extern	void print_stats (struct s_cpu_state *st);
extern  void dump_stats (struct s_cpu_state *st);
extern  void MxsPrintStatus (struct s_cpu_state *st);

#ifdef BREAKPOINT
extern	void	ms_break (struct s_cpu_state *st, INST *ip, char *typ);
#else
#define	ms_break(st,ip,typ)	abort()
#endif

#ifdef PROCSTATS
					/* Per procedure statistics	*/
extern	void	push_stats (struct s_cpu_state *st, int pc);
extern	void	pop_stats (struct s_cpu_state *st);

#endif

extern	void	ms_bus_init (struct s_cpu_state *st);
extern	void	ms_debus (void *st, void *unused);
extern	void	flush_cache (struct s_cpu_state *st,
			int addr, int cnt, int empty);
extern	int	ms_bus_busy (void);

extern	void	ldst_init (struct s_cpu_state *st);
extern	int	ldst_buffer_reserve (struct s_cpu_state *st);
extern	void	ldst_buffer_release (struct s_cpu_state *st);
extern	int	ldst_buffer_retire (struct s_cpu_state *st, int inum);
extern	void	ldst_buffer_squash (struct s_cpu_state *st, int inum);

extern  void    record_ldst_stall (struct s_cpu_state *st, int inum, int stall);
extern  void    record_icache_stall (struct s_cpu_state *st, int pc, int stall);
extern  void    record_pipeline_stall (struct s_cpu_state *st, int pc, int stall);

/* STATRECORD ROUTINES */
#define MS_STALL_EVENT(_cpu, _vAddr, _pc, _stall, _type) \
  ms_attribute_stall(_cpu, _vAddr, _pc, _stall, _type);
extern void     ms_events_init(void);
extern void     ms_attribute_stall(int cpuNum, int vAddr, int pc, 
                                   int stall, int stallType);


#ifdef INLINE
	/* See ms.c for comments on these in-lined routines	*/

#define UnthreadInst(st, inum)	{					\
	int	br_node = (st)->iwin_br_node [(inum)];			\
	if (br_node >= 0) {						\
		int	tmpi; BrTREE	*br;				\
		br = &(st)->branch_tree [br_node];			\
		if ((tmpi = (st)->iwin_bthread [(inum)]) >= 0)		\
			(st)->iwin_thread [tmpi] = (st)->iwin_thread [(inum)]; \
		else br->iwin_head_th = (st)->iwin_thread [(inum)];	\
		if ((tmpi = (st)->iwin_thread [(inum)]) >= 0)		\
			(st)->iwin_bthread [tmpi] = (st)->iwin_bthread [(inum)]; \
		else br->iwin_tail_th = (st)->iwin_bthread [(inum)];	\
		}							\
	(st)->iwin_freelist [(inum)] = (st)->iwin_nextfree;		\
	(st)->iwin_nextfree = (inum);					\
	(st)->iwin_flags [(inum)] = 0;					\
	(st)->iwin_index2 [(inum)] = 0;					\
	(st)->iwin_index3 [(inum)] = 0;					\
	}

#define AcquireRegMap(rs, th, lreg) {					\
	(rs)->reg_nmap++;						\
	(rs)->reg_status |= REG_MAPPED;					\
	if (((rs)->reg_status & REG_CLAIMED) &&				\
	    ((th)->half_def[(lreg) >> 1] & REGNAME_CLAIM))		\
		(rs)->reg_nclaims++;					\
	}

#ifdef PRECISE
#define CheckRegFree(st, rs, reg_ix) {					\
	if (((rs)->reg_status & REG_CLAIMED) && ((rs)->reg_nclaims <= 0) && \
	   ((rs)->reg_ref <= 0) && (((rs)->reg_status & REG_IN_WIN) == 0) ) \
		(rs)->reg_status &= ~REG_CLAIMED;			\
	if ((rs)->reg_status & REG_FREED) {				\
		if ((rs)->reg_status & REG_MAPPED)			\
			(rs)->reg_status = REG_MAPPED;			\
		else {							\
			(rs)->reg_status = 0;				\
			(st)->reg_freelist [(reg_ix)] = (st)->reg_nextfree; \
			(st)->reg_nextfree = (reg_ix);			\
			}						\
		}							\
	if (preg_is_special ((reg_ix)) && (((rs)->reg_status &		\
			  (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP)) \
						== (REG_BUSY + REG_MAPPED)) ) \
			(rs)->reg_status = REG_MAPPED;			\
	}
#else
#define CheckRegFree(st, rs, reg_ix) {					\
	if (((rs)->reg_status & REG_CLAIMED) && ((rs)->reg_nclaims <= 0) && \
	   ((rs)->reg_ref <= 0) && (((rs)->reg_status & REG_IN_WIN) == 0) ) \
		(rs)->reg_status &= ~REG_CLAIMED;			\
	if (((rs)->reg_nclaims <= 0) && ((rs)->reg_ref <= 0) &&		\
	    (((rs)->reg_status & REG_IN_WIN) == 0) ) {			\
		if (((rs)->reg_status &					\
		    (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP))	\
						== REG_BUSY) {		\
			(rs)->reg_status = 0;				\
			(st)->reg_freelist [(reg_ix)] = (st)->reg_nextfree; \
			(st)->reg_nextfree = (reg_ix);			\
			}						\
		else if (preg_is_special ((reg_ix)) && (((rs)->reg_status & \
			  (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP)) \
						== (REG_BUSY + REG_MAPPED)) ) \
			(rs)->reg_status = REG_MAPPED;			\
		}							\
	}
#endif

#define ReleaseRegMap(st, th, reg_ix, lreg) {				\
	int	lreg_ix; REGSTAT *rs = &(st)->reg_rstat[(reg_ix)];	\
	rs->reg_nmap--;							\
	if (rs->reg_nmap == 0) {					\
		rs->reg_status &= ~REG_MAPPED;				\
		CheckRegFree ((st), rs, (reg_ix));			\
		}							\
	lreg_ix = (lreg)>>1;						\
	if ((rs->reg_status & REG_CLAIMED) &&				\
	    ((th)->half_def[lreg_ix] & REGNAME_CLAIM)) {		\
		rs->reg_nclaims--;					\
		CheckRegFree ((st), rs, (reg_ix));			\
		if ((rs->reg_status & REG_CLAIMED) == 0)		\
			(th)->half_def[lreg_ix] &= ~REGNAME_CLAIM;	\
		}							\
	}

#ifdef PRIORITIZE_AVAIL_LIST

#define CheckInstAvail(st, inum) while (1) {				\
	int	pri, avail, last_avail;					\
	if ((st)->iwin_flags [(inum)] &					\
(IWIN_DEP2 | IWIN_DEP3 | IWIN_FLUSH | IWIN_AVAIL | IWIN_LDST_DEP | IWIN_BRDLY)) \
		 break;							\
	if (((st)->iwin_flags [(inum)] & (IWIN_SPEC | IWIN_CTL)) ==	\
						(IWIN_SPEC | IWIN_CTL)) \
		break;							\
	(st)->iwin_flags [(inum)] |= IWIN_AVAIL;			\
	pri = (st)->iwin_headpri;					\
	avail = (st)->iwin_next_avail;					\
	last_avail = -1;						\
	while (pri != (inum)) {						\
		if (pri == avail) {					\
			last_avail = avail;				\
			avail = (st)->iwin_avail_list [avail];		\
			}						\
		pri = (st)->iwin_pri [pri];				\
		}							\
	(st)->iwin_avail_list [(inum)] = avail;				\
	if (last_avail < 0)						\
		(st)->iwin_next_avail = (inum);				\
	else	(st)->iwin_avail_list [last_avail] = (inum);		\
	break; }

#else  /* PRIORITIZE_AVAIL_LIST */

#define CheckInstAvail(st, inum) while (1) {				\
	int	pri, avail, last_avail;					\
	if ((st)->iwin_flags [(inum)] &					\
(IWIN_DEP2 | IWIN_DEP3 | IWIN_FLUSH | IWIN_AVAIL | IWIN_LDST_DEP | IWIN_BRDLY)) \
		break;							\
	if (((st)->iwin_flags [(inum)] & (IWIN_SPEC | IWIN_CTL)) ==	\
						(IWIN_SPEC | IWIN_CTL)) \
		break;							\
	(st)->iwin_flags [(inum)] |= IWIN_AVAIL;			\
	if ((st)->iwin_next_avail >= 0) {				\
		(st)->iwin_avail_list [(st)->iwin_last_avail] = (inum);	\
		(st)->iwin_last_avail = (inum);				\
		}							\
	else {								\
		(st)->iwin_next_avail = (inum);				\
		(st)->iwin_last_avail = (inum);				\
		}							\
	(st)->iwin_avail_list [(inum)] = -1;				\
	break; }

#endif  /* PRIORITIZE_AVAIL_LIST */


#else  /* INLINE */

	/*
	 *  If we aren't inlining these functions, then include function
	 *  prototypes, and make the declarations vacuous.
	 */

extern	void	UnthreadInst (struct s_cpu_state *st, int inum);
extern	void	AcquireRegMap (REGSTAT *rs, THREAD *th, int lreg);
extern	void	ReleaseRegMap (struct s_cpu_state *st, THREAD *th,
						int reg_ix, int lreg);
extern	void	CheckRegFree(struct s_cpu_state *st, REGSTAT *rs, int reg_ix);
extern	void	CheckInstAvail (struct s_cpu_state *st, int inum);

extern void Add_to_worklist(struct s_cpu_state *st, int inc,
		void (*func)(void *st, void *a2),
		void *argument2);

#define	WorkDecls

#endif  /* INLINE */

#ifdef MIPSY_MXS

	/*
	 *  For the MIPSY_MXS version, the address and the compiled address
	 *  of the code is the same.
	 */

#define addr_to_cadr(st,addr) (addr)
#define	cadr_to_addr(st,cadr) (cadr)

#else
extern	int	addr_to_cadr (struct s_cpu_state *st, uint addr);
extern	uint	cadr_to_addr (struct s_cpu_state *st, int cadr);
extern	int	DoPrivInst(struct s_cpu_state *st, int inst,
				uint srcreg, uint *dstreg, int *hack);
extern	int	FPusable(struct s_cpu_state *st);
extern	int	GetLastException (struct s_cpu_state *st);
#endif