mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9518 lines
224 KiB
9518 lines
224 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Revision 3.0
|
|
*
|
|
* Title : yoda.c
|
|
*
|
|
* Description : The Debugger of a Jedi Master
|
|
*
|
|
* Author : Obi wan (ben) Kneobi
|
|
*
|
|
* Notes : May the force be with you.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include StringH
|
|
#include "xt.h"
|
|
#include "yoda.h"
|
|
|
|
|
|
#undef STATISTICS
|
|
#undef COMPRESSED_TRACE
|
|
#undef HOST_EXTENSION
|
|
#define BREAKPOINTS
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "YODA.seg"
|
|
#endif
|
|
|
|
#ifdef SCCSID
|
|
static char SccsID[]="@(#)yoda.c 1.100 07/06/95 Copyright Insignia Solutions Ltd.";
|
|
#endif
|
|
|
|
/*
|
|
* The following dummies are necessary to make the production version
|
|
* link.
|
|
*/
|
|
|
|
#ifdef PROD
|
|
|
|
int vader = 0;
|
|
#ifdef force_yoda
|
|
#undef force_yoda
|
|
#endif
|
|
|
|
void force_yoda()
|
|
{
|
|
}
|
|
#ifdef NONPROD_CPU
|
|
|
|
/* this allows a non-prod CPU to be linked into a PROD build
|
|
* handy for pre-release demo versions if you don't fancy doing a
|
|
* full PROD cpu+vid just to keep management happy....
|
|
*/
|
|
int do_condition_checks = 0;
|
|
#undef check_I
|
|
void check_I IFN0()
|
|
{
|
|
}
|
|
#endif /* NONPROD_CPU */
|
|
#ifdef DELTA
|
|
void delta_check_I()
|
|
{
|
|
}
|
|
#endif /* DELTA */
|
|
#endif /* PROD */
|
|
|
|
#ifdef YODA
|
|
/*
|
|
* O/S includes
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include StringH
|
|
#include <ctype.h>
|
|
#ifndef PROD
|
|
#if defined(BSD4_2) || defined(SYSTEMV)
|
|
#include <signal.h>
|
|
#endif /* BSD4_2 or SYSTEMV */
|
|
|
|
/*
|
|
* SoftPC includes
|
|
*/
|
|
#include "xt.h"
|
|
#define CPU_PRIVATE
|
|
#include CpuH
|
|
#include "trace.h"
|
|
#include "sas.h"
|
|
#include "bios.h"
|
|
#include "ios.h"
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "gfi.h"
|
|
#include "gmi.h"
|
|
#include "gvi.h"
|
|
#include "video.h"
|
|
#include "dsktrace.h"
|
|
#include "idetect.h"
|
|
#include "cmos.h"
|
|
#include "quick_ev.h"
|
|
#include "gfx_upd.h"
|
|
#ifndef SFELLOW
|
|
#include "host_gfx.h"
|
|
#ifdef NEXT /* until someone sorts out the host_timeval interface */
|
|
#include "timeval.h"
|
|
#include "host_hfx.h"
|
|
#include "hfx.h"
|
|
#else /* ifdef NEXT */
|
|
#include "host_hfx.h"
|
|
#include "hfx.h"
|
|
#include "timeval.h"
|
|
#endif /* ifdef NEXT else */
|
|
#endif /* !SFELLOW */
|
|
|
|
|
|
typedef enum {
|
|
br_regAX,
|
|
br_regBX,
|
|
br_regCX,
|
|
br_regDX,
|
|
br_regCS,
|
|
br_regDS,
|
|
br_regES,
|
|
br_regSS,
|
|
br_regSI,
|
|
br_regDI,
|
|
br_regSP,
|
|
br_regBP,
|
|
#ifdef SPC386
|
|
br_regEAX,
|
|
br_regEBX,
|
|
br_regECX,
|
|
br_regEDX,
|
|
br_regFS,
|
|
br_regGS,
|
|
br_regESI,
|
|
br_regEDI,
|
|
br_regESP,
|
|
br_regEBP,
|
|
#endif /* SPC386 */
|
|
br_regAH,
|
|
br_regBH,
|
|
br_regCH,
|
|
br_regDH,
|
|
br_regAL,
|
|
br_regBL,
|
|
br_regCL,
|
|
br_regDL
|
|
}BR_REG ;
|
|
|
|
typedef struct {
|
|
BR_REG regnum;
|
|
char regname[10];
|
|
SIZE_SPECIFIER size;
|
|
} BR_REGDESC;
|
|
|
|
typedef struct br_regentry {
|
|
BR_REG regnum;
|
|
USHORT minval;
|
|
USHORT maxval;
|
|
struct br_regentry *next;
|
|
USHORT handle;
|
|
} BR_REGENTRY;
|
|
|
|
BR_REGDESC br_regdescs[br_regDL+1];
|
|
|
|
#define NUM_BR_ENTRIES 40
|
|
|
|
BR_REGENTRY br_regs[NUM_BR_ENTRIES], *free_br_regs, *head_br_regs = NULL;
|
|
|
|
static BOOL br_structs_initted = FALSE;
|
|
|
|
GLOBAL IBOOL In_yoda=FALSE;
|
|
|
|
#if defined(SYSTEMV) || defined(POSIX_SIGNALS)
|
|
#define MUST_BLOCK_TIMERS
|
|
#endif
|
|
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
int timer_blocked = 0;
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
|
|
#ifdef EGG
|
|
#include "egagraph.h"
|
|
#endif /* EGG */
|
|
|
|
#ifndef CPU_30_STYLE
|
|
#define CPU_YODA_INT 0
|
|
|
|
LOCAL VOID cpu_interrupt IFN2(int,x,int,y)
|
|
{
|
|
UNUSED(x);
|
|
UNUSED(y);
|
|
cpu_interrupt_map |= CPU_YODA_EXCEPTION_MASK;
|
|
host_cpu_interrupt();
|
|
}
|
|
#endif
|
|
|
|
|
|
#define sizeoftable(tab) (sizeof(tab)/sizeof(tab[0]))
|
|
|
|
/*
|
|
* Add in defualt define for host_tolower().
|
|
*/
|
|
#ifndef host_tolower
|
|
#define host_tolower(x) tolower(x)
|
|
#endif /* host_tolower */
|
|
|
|
/*
|
|
* Define value seen in <len> parameter to yoda commands that take
|
|
* <intel-addr> argument if no <len> value is entered.
|
|
* The value chosen is very, very big, so the chances of any poor user
|
|
* actually choosing that value are very, very small!
|
|
*/
|
|
#define YODA_LEN_UNSPECIFIED (~(LIN_ADDR)0 >> 1)
|
|
|
|
|
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*
|
|
* William Roberts 20/8/92
|
|
*
|
|
* Attempt to rationalise so that "s" really does step, without
|
|
* any stupidity about luke or yint+slow
|
|
*
|
|
* There are 3 cases:
|
|
* A3CPU others
|
|
*
|
|
* fast yoda: do_condition_checks = 0 yint = 0
|
|
* medium yoda?: (N/A) yint = 1, fast = 1
|
|
* slow yoda: do_condition_checks = 1 yint = 1, fast = 0
|
|
* && getenv("YODA") != NULL
|
|
*
|
|
* The A3CPU has already built the threads by this time, so it is too
|
|
* late to select slow_yoda f the environment variable is not set...
|
|
*
|
|
* Fast yoda is really about trace printouts etc. You have to hit ^C
|
|
* to get into it, then start use it to examine things.
|
|
*
|
|
* Slow Yoda is needed for stepping, breakpoints etc. It causes the CPU
|
|
* to examine things at every instruction.
|
|
*
|
|
* Medium Yoda means "don't clear CPU_YODA_EXCEPTION when stepping".
|
|
*/
|
|
|
|
/*
|
|
* luke variable for fast yoda
|
|
*/
|
|
int luke = 0;
|
|
int do_condition_checks = 0;
|
|
|
|
/* pre A3CPU fast yoda stuff */
|
|
int yint = 0;
|
|
int fast = 1; /* start interrupt yoda as fast by default */
|
|
|
|
static int chewy = 0; /* Up the Empire! */
|
|
static int env_check = 0; /* Is Luke completely screwed? */
|
|
|
|
int slow_needed = 0;
|
|
char *slow_reason = "why slow is required";
|
|
|
|
#ifdef GISP_SVGA
|
|
LOCAL int NoYodaThanks = FALSE;
|
|
#endif /* GISP_SVGA */
|
|
|
|
|
|
LOCAL LIN_ADDR eff_addr IFN2(IU16, seg, IU32, off)
|
|
{
|
|
if (seg == 0)
|
|
return (off);
|
|
return (effective_addr(seg, off));
|
|
}
|
|
|
|
|
|
LOCAL YODA_CMD_RETURN do_fast IPT6(char *, str, char *, com, IS32, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop);
|
|
LOCAL YODA_CMD_RETURN do_slow IPT6(char *, str, char *, com, IS32, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop);
|
|
LOCAL YODA_CMD_RETURN do_h IPT6(char *, str, char *, com, IS32, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop);
|
|
|
|
LOCAL YODA_CMD_RETURN go_slow IFN0()
|
|
{
|
|
#if defined(A3CPU) && !defined(GISP_CPU)
|
|
if (env_check == 1) {
|
|
printf("Sorry, you must do 'setenv YODA TRUE' before starting an A3CPU\n");
|
|
printf("Fast YODA: breakpoint-based features are not available\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* A3CPU && !GISP_CPU */
|
|
if (fast) {
|
|
printf("Switching to Slow YODA...\n");
|
|
yint = 1; fast = 0; do_condition_checks = 1;
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
Nano_slow_yoda(); /* Check that Nano will give us check_I's */
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
}
|
|
#if defined(A2CPU) || defined(GISP_CPU)
|
|
/* raise a YODA interrupt in the CPU */
|
|
cpu_interrupt (CPU_YODA_INT, 0);
|
|
#else
|
|
/* others already check do_condition_checks */
|
|
#endif /* A2CPU || GISP_CPU */
|
|
|
|
return(YODA_RETURN_AND_REPEAT);
|
|
}
|
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
|
|
|
|
|
|
|
#ifdef DELTA
|
|
extern void examine_delta_data_structs();
|
|
extern void print_last_dest();
|
|
#endif /* DELTA */
|
|
|
|
/* vader is referenced by delta.o */
|
|
int vader = 0;
|
|
|
|
int disable_timer = 0;
|
|
|
|
|
|
#define MAX_TABLE 0x100
|
|
#define MAX_TABLE_BREAK_WORDS 10
|
|
|
|
#ifdef macintosh
|
|
#define MAX_BREAK_WORD_RANGE 0x100
|
|
#else
|
|
#define MAX_BREAK_WORD_RANGE 0xFFF
|
|
#endif
|
|
|
|
typedef struct {
|
|
IU16 cs;
|
|
LIN_ADDR ip;
|
|
LIN_ADDR len;
|
|
LIN_ADDR start_addr;
|
|
LIN_ADDR end_addr;
|
|
LIN_ADDR stop;
|
|
long temp;
|
|
long valid;
|
|
} BPTS;
|
|
|
|
typedef struct {
|
|
IU16 cs;
|
|
LIN_ADDR ip;
|
|
IUH data_addr;
|
|
word old_value[ MAX_BREAK_WORD_RANGE ];
|
|
LIN_ADDR stop;
|
|
LIN_ADDR len;
|
|
} DATA_BPTS;
|
|
|
|
extern int disk_trace, verbose;
|
|
extern int intr(), yoda_intr IPT1(int, signo);
|
|
extern int timer_int_enabled;
|
|
|
|
int trace_type = DUMP_FLAGS | DUMP_REG | DUMP_INST;
|
|
#define INTEL_OPCODES 256
|
|
#define INSIGNIA_OPCODES 2
|
|
#define NR_ADDRS 256
|
|
#define INST_MIX_LENGTH ((INTEL_OPCODES+INSIGNIA_OPCODES)*NR_ADDRS)
|
|
/* inst_mix array declared below */
|
|
long inst_mix_count = 0;
|
|
|
|
static long big_dump=0; /* compress trace will dump all regs or just cs and ip */
|
|
static long ct_no_rom = 0; /* non-zero means exclude ROM from 'ct' */
|
|
static long ct_delta_info=0; /* compress trace can dump an extra field when in a frag */
|
|
|
|
static int bse_seg = -1;
|
|
static int last_seg = -1;
|
|
|
|
|
|
/*
|
|
** Status variables for 80286/8087/80287 break and trace.
|
|
*/
|
|
static int b286_1=0, b286_2=0; /* status of break on 80286 instructions, see the "b286-1" and "b286-2" commmands */
|
|
static int b286_1_stop=0, b286_2_stop=0; /* 0=trace 1=break to yoda */
|
|
static int bNPX=0, bNPX_stop=0;
|
|
|
|
/* I/O streams */
|
|
FILE *out_stream = NULL;
|
|
FILE *in_stream = NULL;
|
|
|
|
GLOBAL int yoda_confirm IFN1(char *, question)
|
|
{
|
|
char str [81];
|
|
|
|
#ifndef SFELLOW
|
|
if (in_stream != stdin) return TRUE;
|
|
#endif /* SFELLOW */
|
|
|
|
fputs(question, stdout);
|
|
fflush(stdout);
|
|
|
|
if (fgets (str, 80, in_stream) &&
|
|
(str[0] == 'y' || str[0] == 'Y')) {
|
|
return TRUE; /* to be on the safe side */
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Define file pointers for automatic file compare
|
|
*/
|
|
FILE *compress_stream = 0;
|
|
FILE *compress_npx = 0;
|
|
FILE *compare_stream = 0;
|
|
IUH compress_break = 0;
|
|
IUH compare_break = 0;
|
|
IUH compare_skip = 0;
|
|
|
|
/*
|
|
* EOR
|
|
*/
|
|
int disk_inst = 0;
|
|
|
|
int int_breakpoint = 0;
|
|
|
|
int inst_break_count = 0;
|
|
BPTS inst[MAX_TABLE];
|
|
|
|
int host_address_break_count = 0;
|
|
DATA_BPTS host_addresses[MAX_TABLE_BREAK_WORDS];
|
|
|
|
int data_words_break_count = 0;
|
|
DATA_BPTS data_words[MAX_TABLE_BREAK_WORDS];
|
|
|
|
int data_bytes_break_count = 0;
|
|
BPTS data_bytes[MAX_TABLE];
|
|
|
|
int opcode_break_count = 0;
|
|
typedef struct {
|
|
IU32 op;
|
|
IU32 mask;
|
|
IU32 stop;
|
|
} OPCODE_BREAK;
|
|
OPCODE_BREAK opcode_breaks[MAX_TABLE];
|
|
|
|
/*
|
|
** TF break stuff used by "btf"
|
|
*/
|
|
int tf_break_enabled = 0;
|
|
|
|
/*
|
|
** interrupt break stuff used by "bintx"
|
|
*/
|
|
int int_break_count = 0;
|
|
IU8 int_breaks[MAX_TABLE][2];
|
|
|
|
int access_break_count = 0;
|
|
long access_breaks[MAX_TABLE];
|
|
|
|
int step_count = -1;
|
|
int disable_bkpt = 0;
|
|
|
|
int refresh_screen = 0;
|
|
|
|
#ifdef DELTA
|
|
static int delta_prompt = 0;
|
|
#endif /* DELTA */
|
|
|
|
static short back_trace_flags = 0;
|
|
static IUH ct_line_num;
|
|
|
|
#ifdef CPU_40_STYLE
|
|
enum pla_type { pla_type_empty,
|
|
pla_type_rm_code,
|
|
pla_type_pm_small_code,
|
|
pla_type_pm_big_code,
|
|
pla_type_simulate,
|
|
pla_type_unsimulate,
|
|
pla_type_bop_done,
|
|
pla_type_intack,
|
|
pla_type_pig_force,
|
|
pla_type_nano_enter,
|
|
pla_type_nano_leave
|
|
};
|
|
#ifndef CCPU
|
|
#include <gdpvar.h>
|
|
#endif /* CCPU */
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#define PLA_SIZE (64*1024)
|
|
|
|
/* ----- Assorted BIG arrays, which the Mac needs to obtain using
|
|
* ----- malloc
|
|
*/
|
|
|
|
#ifndef macintosh
|
|
|
|
unsigned long inst_mix[INST_MIX_LENGTH];
|
|
word last_cs[PLA_SIZE];
|
|
LIN_ADDR last_ip[PLA_SIZE];
|
|
|
|
#ifdef CPU_40_STYLE
|
|
enum pla_type last_type[PLA_SIZE];
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#else /* !macintosh */
|
|
|
|
#include <Memory.h> /* for _NewPtrClear */
|
|
|
|
unsigned long *inst_mix;
|
|
word *last_cs;
|
|
LIN_ADDR *last_ip;
|
|
|
|
#ifdef CPU_40_STYLE
|
|
enum pla_type *last_type;
|
|
#endif
|
|
|
|
GLOBAL void mac_yoda_init IFN0()
|
|
{
|
|
/* These values should be initialised to zero */
|
|
|
|
#define ALLOCATE_ARRAY(type, name, size) \
|
|
name = (type *)NewPtrClear((size)*sizeof(*name));
|
|
|
|
ALLOCATE_ARRAY( unsigned long, inst_mix, INST_MIX_LENGTH);
|
|
ALLOCATE_ARRAY( word, last_cs, PLA_SIZE);
|
|
ALLOCATE_ARRAY( LIN_ADDR, last_ip, PLA_SIZE);
|
|
|
|
#ifdef CPU_40_STYLE
|
|
ALLOCATE_ARRAY( enum pla_type, last_type,PLA_SIZE);
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
#endif /* macintosh */
|
|
|
|
int pla_ptr=0;
|
|
|
|
GLOBAL void set_last_address IFN2( word, cs, LIN_ADDR, ip)
|
|
{
|
|
/*
|
|
* Update the last address stamp
|
|
*/
|
|
#ifdef CPU_40_STYLE
|
|
/* We need to know if the CS is "big", this is expensive to calculate
|
|
* every instruction, and almost impossible to deduce at print time
|
|
* (e.g. after changing from V86 mode)
|
|
* We compromise, by recording CsIsBig() when CS changes, and
|
|
* accept the (small) loop-hole where a V86 (i.e. small) CS has
|
|
* the same value as the PM, large, handler to which the V86code traps.
|
|
*/
|
|
SAVED IU32 previous_cs = 0xFFFFFFFF;
|
|
SAVED enum pla_type cs_code_kind;
|
|
|
|
if (cs != previous_cs)
|
|
{
|
|
if (getPE() && (getVM() == 0))
|
|
{
|
|
if (CsIsBig(cs))
|
|
cs_code_kind = pla_type_pm_big_code;
|
|
else
|
|
cs_code_kind = pla_type_pm_small_code;
|
|
}
|
|
else
|
|
cs_code_kind = pla_type_rm_code;
|
|
previous_cs = cs;
|
|
}
|
|
last_type[pla_ptr] = cs_code_kind;
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
last_cs[pla_ptr] = cs;
|
|
last_ip[pla_ptr] = ip;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL void set_last_bop_done IFN1( word, number )
|
|
{
|
|
/*
|
|
* Update the last address stamp with BOP marker
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = number;
|
|
last_type[pla_ptr] = pla_type_bop_done;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL void set_last_simulate IFN2(int, nesting_level, IBOOL, is_simulate)
|
|
{
|
|
/*
|
|
* Update the last address stamp with (UN)SIMULATE marker
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = nesting_level;
|
|
last_type[pla_ptr] = is_simulate ? pla_type_simulate: pla_type_unsimulate;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL void set_last_intack IFN1( word, line )
|
|
{
|
|
/*
|
|
* Update the last address stamp with INTACK line
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = line;
|
|
last_type[pla_ptr] = pla_type_intack;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL void set_last_pig_force IFN0()
|
|
{
|
|
/*
|
|
* Update the last address stamp with PIG FORCE marker
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = 0;
|
|
last_type[pla_ptr] = pla_type_pig_force;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
|
|
|
|
GLOBAL void set_last_nano_enter IFN0()
|
|
{
|
|
/*
|
|
* Update the last address stamp with Nano enter marker
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = 0;
|
|
last_type[pla_ptr] = pla_type_nano_enter;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
|
|
|
|
GLOBAL void set_last_nano_leave IFN0()
|
|
{
|
|
/*
|
|
* Update the last address stamp with Nano leave marker
|
|
*/
|
|
|
|
last_cs[pla_ptr] = 0;
|
|
last_ip[pla_ptr] = 0;
|
|
last_type[pla_ptr] = pla_type_nano_leave;
|
|
if (++pla_ptr==PLA_SIZE)
|
|
{
|
|
pla_ptr = 0;
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
|
|
host_addr host_dest_addr; /* address just written to by cpu */
|
|
|
|
/* Register Break Point Support */
|
|
typedef struct
|
|
{
|
|
int reg;
|
|
int value;
|
|
int stop;
|
|
} REG_BKPT;
|
|
|
|
#define MAX_REG_BKPT 5
|
|
|
|
int reg_break_count = 0;
|
|
|
|
REG_BKPT reg_bkpt[MAX_REG_BKPT];
|
|
|
|
|
|
#if defined(GENERIC_NPX) && !defined(CPU_40_STYLE)
|
|
IMPORT CHAR *NPXDebugPtr, *NPXDebugBase;
|
|
IMPORT ULONG *NPXFreq;
|
|
|
|
#define MAX_NPX_OPCODE (sizeoftable(NPXOpcodes))
|
|
|
|
static char *NPXOpcodes[] = {
|
|
"Unimplemented",
|
|
"Fadd_from_reg",
|
|
"Fadd_to_reg",
|
|
"Faddp_to_reg",
|
|
"Fadd_sr",
|
|
"Fadd_lr",
|
|
"Fmul_from_reg",
|
|
"Fmul_to_reg",
|
|
"Fmulp_to_reg",
|
|
"Fmul_sr",
|
|
"Fmul_lr",
|
|
"Fcom_reg",
|
|
"Fcomp_reg",
|
|
"Fcom_sr",
|
|
"Fcom_lr",
|
|
"Fcomp_sr",
|
|
"Fcomp_lr",
|
|
"Fsub_from_reg",
|
|
"Fsub_to_reg",
|
|
"Fsubp_reg",
|
|
"Fsub_sr",
|
|
"Fsub_lr",
|
|
"Fsubr_from_reg",
|
|
"Fsubr_to_reg",
|
|
"Fsubrp_reg",
|
|
"Fsubr_sr",
|
|
"Fsubr_lr",
|
|
"Fdiv_from_reg",
|
|
"Fdiv_to_reg",
|
|
"Fdivp_reg",
|
|
"Fdiv_sr",
|
|
"Fdiv_lr",
|
|
"Fdivr_from_reg",
|
|
"Fdivr_to_reg",
|
|
"Fdivrp_reg",
|
|
"Fdivr_sr",
|
|
"Fdivr_lr",
|
|
"Fld_reg",
|
|
"Fld_sr",
|
|
"Fld_lr",
|
|
"Fld_tr",
|
|
"Fst_reg",
|
|
"Fst_sr",
|
|
"Fst_lr",
|
|
"Fstp_reg",
|
|
"Fstp_sr",
|
|
"Fstp_lr",
|
|
"Fstp_tr",
|
|
"Fxch",
|
|
"Fiadd_si",
|
|
"Fiadd_wi",
|
|
"Fimul_si",
|
|
"Fimul_wi",
|
|
"Ficom_si",
|
|
"Ficom_wi",
|
|
"Ficomp_si",
|
|
"Ficomp_wi",
|
|
"Fisub_si",
|
|
"Fisub_wi",
|
|
"Fisubr_si",
|
|
"Fisubr_wi",
|
|
"Fidiv_si",
|
|
"Fidiv_wi",
|
|
"Fidivr_si",
|
|
"Fidivr_wi",
|
|
"Fild_si",
|
|
"Fild_wi",
|
|
"Fild_li",
|
|
"Fist_si",
|
|
"Fist_wi",
|
|
"Fistp_si",
|
|
"Fistp_wi",
|
|
"Fistp_li",
|
|
"Ffree",
|
|
"Ffreep",
|
|
"Fbld",
|
|
"Fbstp",
|
|
"Fldcw",
|
|
"Fstenv",
|
|
"Fstcw",
|
|
"Fnop",
|
|
"Fchs",
|
|
"Fabs",
|
|
"Ftst",
|
|
"Fxam",
|
|
"Fld1",
|
|
"Fldl2t",
|
|
"Fldl2e",
|
|
"Fldpi",
|
|
"Fldlg2",
|
|
"Fldln2",
|
|
"Fldz",
|
|
"F2xm1",
|
|
"Fyl2x",
|
|
"Fptan",
|
|
"Fpatan",
|
|
"Fxtract",
|
|
"Fdecstp",
|
|
"Fincstp",
|
|
"Fprem",
|
|
"Fyl2xp1",
|
|
"Fsqrt",
|
|
"Frndint",
|
|
"Fscale",
|
|
"Fclex",
|
|
"Finit",
|
|
"Frstor",
|
|
"Fsave",
|
|
"Fstsw",
|
|
"Fcompp",
|
|
"Fstswax",
|
|
"Fldenv"
|
|
};
|
|
#endif /* GENERIC_NPX && !CPU_40_STYLE */
|
|
|
|
#ifdef PM
|
|
#ifdef SPC386
|
|
struct VMM_services {
|
|
char *name;
|
|
IU16 value;
|
|
};
|
|
static struct VMM_services VMM_services[] = {
|
|
{ "Get_VMM_Version", 0x00 }, { "Get_Cur_VM_Handle", 0x01 },
|
|
{ "Test_Cur_VM_Handle", 0x02 }, { "Get_Sys_VM_Handle", 0x03 },
|
|
{ "Test_Sys_VM_Handle", 0x04 }, { "Validate_VM_Handle", 0x05 },
|
|
{ "Get_VMM_Reenter_Count", 0x06 }, { "Begin_Reentrant_Execution", 0x07 },
|
|
{ "End_Reentrant_Execution", 0x08 }, { "Install_V86_Break_Point", 0x09 },
|
|
{ "Remove_V86_Break_Point", 0x0a }, { "Allocate_V86_Call_Back", 0x0b },
|
|
{ "Allocate_PM_Call_Back", 0x0c }, { "Call_When_VM_Returns", 0x0d },
|
|
{ "Schedule_Global_Event", 0x0e }, { "Schedule_VM_Event", 0x0f },
|
|
{ "Call_Global_Event", 0x10 }, { "Call_VM_Event", 0x11 },
|
|
{ "Cancel_Global_Event", 0x12 }, { "Cancel_VM_Event", 0x13 },
|
|
{ "Call_Priority_VM_Event", 0x14 }, { "Cancel_Priority_VM_Event", 0x15 },
|
|
{ "Get_NMI_Handler_Addr", 0x16 }, { "Set_NMI_Handler_Addr", 0x17 },
|
|
{ "Hook_NMI_Event", 0x18 }, { "Call_When_VM_Ints_Enabled", 0x19 },
|
|
{ "Enable_VM_Ints", 0x1a }, { "Disable_VM_Ints", 0x1b },
|
|
{ "Map_Flat", 0x1c }, { "Map_Lin_To_VM_Addr", 0x1d },
|
|
{ "Adjust_Exec_Priority", 0x1e }, { "Begin_Critical_Section", 0x1f },
|
|
{ "End_Critical_Section", 0x20 }, { "End_Crit_And_Suspend", 0x21 },
|
|
{ "Claim_Critical_Section", 0x22 }, { "Release_Critical_Section", 0x23 },
|
|
{ "Call_When_Not_Critical", 0x24 }, { "Create_Semaphore", 0x25 },
|
|
{ "Destroy_Semaphore", 0x26 }, { "Wait_Semaphore", 0x27 },
|
|
{ "Signal_Semaphore", 0x28 }, { "Get_Crit_Section_Status", 0x29 },
|
|
{ "Call_When_Task_Switched", 0x2a }, { "Suspend_VM", 0x2b },
|
|
{ "Resume_VM", 0x2c }, { "No_Fail_Resume_VM", 0x2d },
|
|
{ "Nuke_VM", 0x2e }, { "Crash_Cur_VM", 0x2f },
|
|
{ "Get_Execution_Focus", 0x30 }, { "Set_Execution_Focus", 0x31 },
|
|
{ "Get_Time_Slice_Priority", 0x32 }, { "Set_Time_Slice_Priority", 0x33 },
|
|
{ "Get_Time_Slice_Granularity", 0x34 },{ "Set_Time_Slice_Granularity", 0x35 },
|
|
{ "Get_Time_Slice_Info", 0x36 }, { "Adjust_Execution_Time", 0x37 },
|
|
{ "Release_Time_Slice", 0x38 }, { "Wake_Up_VM", 0x39 },
|
|
{ "Call_When_Idle", 0x3a }, { "Get_Next_VM_Handle", 0x3b },
|
|
{ "Set_Global_Time_Out", 0x3c }, { "Set_VM_Time_Out", 0x3d },
|
|
{ "Cancel_Time_Out", 0x3e }, { "Get_System_Time", 0x3f },
|
|
{ "Get_VM_Exec_Time", 0x40 }, { "Hook_V86_Int_Chain", 0x41 },
|
|
{ "Get_V86_Int_Vector", 0x42 }, { "Set_V86_Int_Vector", 0x43 },
|
|
{ "Get_PM_Int_Vector", 0x44 }, { "Set_PM_Int_Vector", 0x45 },
|
|
{ "Simulate_Int", 0x46 }, { "Simulate_Iret", 0x47 },
|
|
{ "Simulate_Far_Call", 0x48 }, { "Simulate_Far_Jmp", 0x49 },
|
|
{ "Simulate_Far_Ret", 0x4a }, { "Simulate_Far_Ret_N", 0x4b },
|
|
{ "Build_Int_Stack_Frame", 0x4c }, { "Simulate_Push", 0x4d },
|
|
{ "Simulate_Pop", 0x4e }, { "_HeapAllocate", 0x4f },
|
|
{ "_HeapReAllocate", 0x50 }, { "_HeapFree", 0x51 },
|
|
{ "_HeapGetSize", 0x52 }, { "_PageAllocate", 0x53 },
|
|
{ "_PageReAllocate", 0x54 }, { "_PageFree", 0x55 },
|
|
{ "_PageLock", 0x56 }, { "_PageUnLock", 0x57 },
|
|
{ "_PageGetSizeAddr", 0x58 }, { "_PageGetAllocInfo", 0x59 },
|
|
{ "_GetFreePageCount", 0x5a }, { "_GetSysPageCount", 0x5b },
|
|
{ "_GetVMPgCount", 0x5c }, { "_MapIntoV86", 0x5d },
|
|
{ "_PhysIntoV86", 0x5e }, { "_TestGlobalV86Mem", 0x5f },
|
|
{ "_ModifyPageBits", 0x60 }, { "_CopyPageTable", 0x61 },
|
|
{ "_LinMapIntoV86", 0x62 }, { "_LinPageLock", 0x63 },
|
|
{ "_LinPageUnLock", 0x64 }, { "_SetResetV86Pageable", 0x65 },
|
|
{ "_GetV86PageableArray", 0x66 }, { "_PageCheckLinRange", 0x67 },
|
|
{ "_PageOutDirtyPages", 0x68 }, { "_PageDiscardPages", 0x69 },
|
|
{ "_GetNulPageHandle", 0x6a }, { "_GetFirstV86Page", 0x6b },
|
|
{ "_MapPhysToLinear", 0x6c }, { "_GetAppFlatDSAlias", 0x6d },
|
|
{ "_SelectorMapFlat", 0x6e }, { "_GetDemandPageInfo", 0x6f },
|
|
{ "_GetSetPageOutCount", 0x70 }, { "Hook_V86_Page", 0x71 },
|
|
{ "_Assign_Device_V86_Pages", 0x72 }, { "_DeAssign_Device_V86_Pages", 0x73 },
|
|
{ "_Get_Device_V86_Pages_Array", 0x74 },{ "MMGR_SetNULPageAddr", 0x75 },
|
|
{ "_Allocate_GDT_Selector", 0x76 }, { "_Free_GDT_Selector", 0x77 },
|
|
{ "_Allocate_LDT_Selector", 0x78 }, { "_Free_LDT_Selector", 0x79 },
|
|
{ "_BuildDescriptorDWORDs", 0x7a }, { "_GetDescriptor", 0x7b },
|
|
{ "_SetDescriptor", 0x7c }, { "_MMGR_Toggle_HMA", 0x7d },
|
|
{ "Get_Fault_Hook_Addrs", 0x7e }, { "Hook_V86_Fault", 0x7f },
|
|
{ "Hook_PM_Fault", 0x80 }, { "Hook_VMM_Fault", 0x81 },
|
|
{ "Begin_Nest_V86_Exec", 0x82 }, { "Begin_Nest_Exec", 0x83 },
|
|
{ "Exec_Int", 0x84 }, { "Resume_Exec", 0x85 },
|
|
{ "End_Nest_Exec", 0x86 }, { "Allocate_PM_App_CB_Area", 0x87 },
|
|
{ "Get_Cur_PM_App_CB", 0x88 }, { "Set_V86_Exec_Mode", 0x89 },
|
|
{ "Set_PM_Exec_Mode", 0x8a }, { "Begin_Use_Locked_PM_Stack", 0x8b },
|
|
{ "End_Use_Locked_PM_Stack", 0x8c }, { "Save_Client_State", 0x8d },
|
|
{ "Restore_Client_State", 0x8e }, { "Exec_VxD_Int", 0x8f },
|
|
{ "Hook_Device_Service", 0x90 }, { "Hook_Device_V86_API", 0x91 },
|
|
{ "Hook_Device_PM_API", 0x92 }, { "System_Control", 0x93 },
|
|
{ "Simulate_IO", 0x94 }, { "Install_Mult_IO_Handlers", 0x95 },
|
|
{ "Install_IO_Handler", 0x96 }, { "Enable_Global_Trapping", 0x97 },
|
|
{ "Enable_Local_Trapping", 0x98 }, { "Disable_Global_Trapping", 0x99 },
|
|
{ "Disable_Local_Trapping", 0x9a }, { "List_Create", 0x9b },
|
|
{ "List_Destroy", 0x9c }, { "List_Allocate", 0x9d },
|
|
{ "List_Attach", 0x9e }, { "List_Attach_Tail", 0x9f },
|
|
{ "List_Insert", 0xa0 }, { "List_Remove", 0xa1 },
|
|
{ "List_Deallocate", 0xa2 }, { "List_Get_First", 0xa3 },
|
|
{ "List_Get_Next", 0xa4 }, { "List_Remove_First", 0xa5 },
|
|
{ "_AddInstanceItem", 0xa6 }, { "_Allocate_Device_CB_Area", 0xa7 },
|
|
{ "_Allocate_Global_V86_Data_Area", 0xa8 },{ "_Allocate_Temp_V86_Data_Area", 0xa9 },
|
|
{ "_Free_Temp_V86_Data_Area", 0xaa }, { "Get_Profile_Decimal_Int", 0xab },
|
|
{ "Convert_Decimal_String", 0xac }, { "Get_Profile_Fixed_Point", 0xad },
|
|
{ "Convert_Fixed_Point_String", 0xae },{ "Get_Profile_Hex_Int", 0xaf },
|
|
{ "Convert_Hex_String", 0xb0 }, { "Get_Profile_Boolean", 0xb1 },
|
|
{ "Convert_Boolean_String", 0xb2 }, { "Get_Profile_String", 0xb3 },
|
|
{ "Get_Next_Profile_String", 0xb4 }, { "Get_Environment_String", 0xb5 },
|
|
{ "Get_Exec_Path", 0xb6 }, { "Get_Config_Directory", 0xb7 },
|
|
{ "OpenFile", 0xb8 }, { "Get_PSP_Segment", 0xb9 },
|
|
{ "GetDOSVectors", 0xba }, { "Get_Machine_Info", 0xbb },
|
|
{ "GetSet_HMA_Info", 0xbc }, { "Set_System_Exit_Code", 0xbd },
|
|
{ "Fatal_Error_Handler", 0xbe }, { "Fatal_Memory_Error", 0xbf },
|
|
{ "Update_System_Clock", 0xc0 }, { "Test_Debug_Installed", 0xc1 },
|
|
{ "Out_Debug_String", 0xc2 }, { "Out_Debug_Chr", 0xc3 },
|
|
{ "In_Debug_Chr", 0xc4 }, { "Debug_Convert_Hex_Binary", 0xc5 },
|
|
{ "Debug_Convert_Hex_Decimal", 0xc6 },{ "Debug_Test_Valid_Handle", 0xc7 },
|
|
{ "Validate_Client_Ptr", 0xc8 }, { "Test_Reenter", 0xc9 },
|
|
{ "Queue_Debug_String", 0xca }, { "Log_Proc_Call", 0xcb },
|
|
{ "Debug_Test_Cur_VM", 0xcc }, { "Get_PM_Int_Type", 0xcd },
|
|
{ "Set_PM_Int_Type", 0xce }, { "Get_Last_Updated_System_Time", 0xcf },
|
|
{ "Get_Last_Updated_VM_Exec_Time", 0xd0 },{ "Test_DBCS_Lead_Byte", 0xd1 },
|
|
{ "_AddFreePhysPage", 0xd2 }, { "_PageResetHandlePAddr", 0xd3 },
|
|
{ "_SetLastV86Page", 0xd4 }, { "_GetLastV86Page", 0xd5 },
|
|
{ "_MapFreePhysReg", 0xd6 }, { "_UnmapFreePhysReg", 0xd7 },
|
|
{ "_XchgFreePhysReg", 0xd8 }, { "_SetFreePhysRegCalBk", 0xd9 },
|
|
{ "Get_Next_Arena", 0xda }, { "Get_Name_Of_Ugly_TSR", 0xdb },
|
|
{ "Get_Debug_Options", 0xdc }, { "Set_Physical_HMA_Alias", 0xdd },
|
|
{ "_GetGlblRng0V86IntBase", 0xde }, { "_Add_Global_V86_Data_Area", 0xdf },
|
|
{ "GetSetDetailedVMError", 0xe0 }, { "Is_Debug_Chr", 0xe1 },
|
|
{ "Clear_Mono_Screen", 0xe2 }, { "Out_Mono_Chr", 0xe3 },
|
|
{ "Out_Mono_String", 0xe4 }, { "Set_Mono_Cur_Pos", 0xe5 },
|
|
{ "Get_Mono_Cur_Pos", 0xe6 }, { "Get_Mono_Chr", 0xe7 },
|
|
{ "Locate_Byte_In_ROM", 0xe8 }, { "Hook_Invalid_Page_Fault", 0xe9 },
|
|
{ "Unhook_Invalid_Page_Fault", 0xea },{ "Set_Delete_On_Exit_File", 0xeb },
|
|
{ "Close_VM", 0xec }, { "Enable_Touch_1st_Meg", 0xed },
|
|
{ "Disable_Touch_1st_Meg", 0xee }, { "Install_Exception_Handler", 0xef },
|
|
{ "Remove_Exception_Handler", 0xf0 }, { "Get_Crit_Status_No_Block", 0xf1 },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
static char *segment_names[] =
|
|
{
|
|
"INVALID",
|
|
"286_AVAILABLE_TSS",
|
|
"LDT_SEGMENT",
|
|
"286_BUSY_TSS",
|
|
"286_CALL_GATE",
|
|
"TASK_GATE",
|
|
"286_INTERRUPT_GATE",
|
|
"286_TRAP_GATE",
|
|
"INVALID",
|
|
"386_AVAILABLE_TSS",
|
|
"INVALID",
|
|
"386_BUSY_TSS",
|
|
"386_CALL_GATE",
|
|
"INVALID",
|
|
"386_INTERRUPT_GATE",
|
|
"386_TRAP_GATE",
|
|
"EXPANDUP_READONLY_DATA",
|
|
"EXPANDUP_READONLY_DATA",
|
|
"EXPANDUP_WRITEABLE_DATA",
|
|
"EXPANDUP_WRITEABLE_DATA",
|
|
"EXPANDDOWN_READONLY_DATA",
|
|
"EXPANDDOWN_READONLY_DATA",
|
|
"EXPANDDOWN_WRITEABLE_DATA",
|
|
"EXPANDDOWN_WRITEABLE_DATA",
|
|
"NONCONFORM_NOREAD_CODE",
|
|
"NONCONFORM_NOREAD_CODE",
|
|
"NONCONFORM_READABLE_CODE",
|
|
"NONCONFORM_READABLE_CODE",
|
|
"CONFORM_NOREAD_CODE",
|
|
"CONFORM_NOREAD_CODE",
|
|
"CONFORM_READABLE_CODE",
|
|
"CONFORM_READABLE_CODE"
|
|
};
|
|
#else
|
|
static char *segment_names[] =
|
|
{
|
|
"INVALID",
|
|
"AVAILABLE_TSS",
|
|
"LDT_SEGMENT",
|
|
"BUSY_TSS",
|
|
"CALL_GATE",
|
|
"TASK_GATE",
|
|
"INTERRUPT_GATE",
|
|
"TRAP_GATE",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"INVALID",
|
|
"EXPANDUP_READONLY_DATA",
|
|
"EXPANDUP_READONLY_DATA",
|
|
"EXPANDUP_WRITEABLE_DATA",
|
|
"EXPANDUP_WRITEABLE_DATA",
|
|
"EXPANDDOWN_READONLY_DATA",
|
|
"EXPANDDOWN_READONLY_DATA",
|
|
"EXPANDDOWN_WRITEABLE_DATA",
|
|
"EXPANDDOWN_WRITEABLE_DATA",
|
|
"NONCONFORM_NOREAD_CODE",
|
|
"NONCONFORM_NOREAD_CODE",
|
|
"NONCONFORM_READABLE_CODE",
|
|
"NONCONFORM_READABLE_CODE",
|
|
"CONFORM_NOREAD_CODE",
|
|
"CONFORM_NOREAD_CODE",
|
|
"CONFORM_READABLE_CODE",
|
|
"CONFORM_READABLE_CODE"
|
|
};
|
|
#endif /* SPC386 */
|
|
|
|
static int descr_trace = 0x3f;
|
|
|
|
#endif /* PM */
|
|
|
|
static int low_trace_limit = 0x0;
|
|
static int high_trace_limit = 0x400000;
|
|
|
|
#ifdef SFELLOW
|
|
LOCAL char SfNotImp[] = "This function is not implemented on Stringfellows.\n";
|
|
#endif /* SFELLOW */
|
|
|
|
#ifdef SPC386
|
|
#define DASM_INTERNAL
|
|
#include <dasm.h>
|
|
#else /* SPC386 */
|
|
IMPORT word dasm IPT5(char *, i_output_stream, word, i_atomicsegover, word, i_segreg, word, i_segoff, int, i_nInstr);
|
|
#endif /* SPC386 */
|
|
|
|
/*
|
|
* ==========================================================================
|
|
* Imported functions
|
|
* ==========================================================================
|
|
*/
|
|
|
|
IMPORT VOID host_yoda_help_extensions IPT0();
|
|
IMPORT int host_force_yoda_extensions IPT5(char *,com, long,cs, long,ip, long,len, char *, str);
|
|
IMPORT int host_yoda_check_I_extensions IPT0();
|
|
IMPORT int btrace IPT1(int, flags);
|
|
IMPORT void axe_ticks IPT1(int, ticks);
|
|
IMPORT void dump_Display IPT0();
|
|
IMPORT void dump_EGA_CPU IPT0();
|
|
IMPORT void dump_ega_planes IPT0();
|
|
IMPORT void read_ega_planes IPT0();
|
|
IMPORT void set_hfx_severity IPT0();
|
|
IMPORT void com_debug IPT0();
|
|
#ifdef DPMI
|
|
IMPORT void set_dpmi_severity IPT0();
|
|
#endif /* DPMI */
|
|
IMPORT void com_debug IPT0();
|
|
#ifndef GISP_CPU
|
|
#ifdef A3CPU
|
|
IMPORT void D2DmpBinaryImage IPT1(LONG, csbase24);
|
|
IMPORT void IH_dump_frag_hist IPT1(ULONG, n);
|
|
IMPORT void D2ForceTraceInit IPT0();
|
|
#endif
|
|
#endif /* GISP_CPU */
|
|
/*
|
|
* ==========================================================================
|
|
* Local functions
|
|
* ==========================================================================
|
|
*/
|
|
|
|
LOCAL void set_reg_break IPT3(char*, regstr, IU32,minv, IU32,maxv);
|
|
LOCAL void show_phys_addr IPT1(LIN_ADDR, lin);
|
|
LOCAL void guess_lin_phys IPT1(PHY_ADDR, phys);
|
|
LOCAL void guess_lin_pte IPT1(PHY_ADDR, pte_addr);
|
|
LOCAL void dump_page_table IPT2(IS32, cs, IS32, len);
|
|
GLOBAL void da_block IPT3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len) ;
|
|
LOCAL void dump_bytes IPT3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len);
|
|
LOCAL void dump_words IPT3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len);
|
|
LOCAL void dump_dwords IPT3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len);
|
|
|
|
#ifdef ANSI
|
|
LOCAL void clear_reg_break(char*);
|
|
LOCAL void print_reg_break();
|
|
LOCAL BOOL check_reg_break();
|
|
LOCAL void set_inst_break(IU16, LIN_ADDR, LIN_ADDR, LIN_ADDR, long);
|
|
LOCAL void dump_phys_bytes(IS32, IS32);
|
|
LOCAL void print_inst_break(void);
|
|
LOCAL void set_data_break_words(LIN_ADDR,LIN_ADDR,LIN_ADDR);
|
|
LOCAL void set_host_address_break(LIN_ADDR, LIN_ADDR, LIN_ADDR);
|
|
LOCAL void print_host_address_breaks(void);
|
|
LOCAL void print_data_break_words();
|
|
LOCAL void set_opcode_break(IU32, IU32);
|
|
LOCAL void set_int_break(IU8, IU8);
|
|
LOCAL void print_int_break(void);
|
|
LOCAL void print_opcode_break(void);
|
|
LOCAL void set_access_break(int);
|
|
LOCAL void print_access_break(void);
|
|
LOCAL void print_inst_mix(int);
|
|
LOCAL void cga_test(void);
|
|
LOCAL void do_back_trace(void);
|
|
LOCAL void add_inst_mix(void);
|
|
#ifdef NPX
|
|
LOCAL void do_compress_npx(FILE *);
|
|
#endif
|
|
#else /* ANSI */
|
|
LOCAL void clear_reg_break();
|
|
LOCAL void print_reg_break();
|
|
LOCAL BOOL check_reg_break();
|
|
LOCAL void set_inst_break();
|
|
LOCAL void dump_phys_bytes();
|
|
LOCAL void print_inst_break();
|
|
LOCAL void set_data_break_words();
|
|
LOCAL void set_host_address_break();
|
|
LOCAL void print_host_address_breaks();
|
|
LOCAL void print_data_break_words();
|
|
LOCAL void set_opcode_break();
|
|
LOCAL void set_int_break();
|
|
LOCAL void print_int_break();
|
|
LOCAL void print_opcode_break();
|
|
LOCAL void set_access_break();
|
|
LOCAL void print_access_break();
|
|
LOCAL void print_inst_mix();
|
|
LOCAL void cga_test();
|
|
LOCAL void do_back_trace();
|
|
LOCAL void add_inst_mix();
|
|
#ifdef NPX
|
|
LOCAL void do_compress_npx();
|
|
#endif
|
|
#endif
|
|
|
|
LOCAL dump_descr IPT2(LIN_ADDR, address, IUM32, num);
|
|
|
|
/*
|
|
* YODA COMMAND HANDLERS
|
|
* =====================
|
|
*/
|
|
|
|
#ifdef GISP_SVGA
|
|
|
|
/* Allow us to turn Yoda "off" - this is so that if SoftPC is running full
|
|
screen a force_yoda() won't leave you wanting to type c into a window you can't
|
|
get at */
|
|
LOCAL YODA_COMMAND(doNoYoda)
|
|
{
|
|
char * NotStr;
|
|
|
|
if( !NoYodaThanks )
|
|
{
|
|
stop = yoda_confirm("Are you really sure that you want to turn yoda off?");
|
|
|
|
if( stop )
|
|
{
|
|
NoYodaThanks = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NoYodaThanks = FALSE;
|
|
}
|
|
|
|
if( NoYodaThanks )
|
|
{
|
|
printf( "On your head be it....call doNoYoda() from your debugger\nor set the global variable noYodaThanks FALSE to re-enable yoda\n" );
|
|
}
|
|
else
|
|
{
|
|
printf( "Yoda re-enabled\n" );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* GISP_SVGA */
|
|
/*(
|
|
*========================== do_pmt ==================================
|
|
* do_pmt
|
|
*
|
|
* Purpose
|
|
* This routine prints a map of the different memory types across the
|
|
* whole of M.
|
|
*
|
|
* Input
|
|
* Is not used.
|
|
*
|
|
* Outputs
|
|
* None.
|
|
*
|
|
* Description
|
|
* We step through each 4K page in turn, printing out a new line every
|
|
* time the memory type changes.
|
|
*
|
|
)*/
|
|
|
|
LOCAL YODA_COMMAND(do_pmt)
|
|
{
|
|
PHY_ADDR currPage;
|
|
PHY_ADDR endOfM;
|
|
IU8 currType = SAS_MAX_TYPE + 1; /*cause type at addr 0 to print*/
|
|
IU8 newType;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
currPage = 0;
|
|
endOfM = sas_memory_size();
|
|
|
|
while (currPage < endOfM) {
|
|
newType = sas_memory_type(currPage);
|
|
if (newType != currType) {
|
|
currType = newType;
|
|
printf("\t0x%.08x %.80s\n", currPage,
|
|
SAS_TYPE_TO_STRING(newType));
|
|
}
|
|
currPage += 0x1000;
|
|
}
|
|
printf("\t0x%.08x END OF MEMORY\n", endOfM);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
|
|
#if defined(GENERIC_NPX) && !defined(CPU_40_STYLE)
|
|
LOCAL YODA_COMMAND(do_NPXdisp)
|
|
{
|
|
CHAR *myNPXPtr = NPXDebugPtr;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
while (cs--) {
|
|
fprintf(trace_file,"%s\n", NPXOpcodes[*--myNPXPtr]);
|
|
if (myNPXPtr < NPXDebugBase)
|
|
myNPXPtr = NPXDebugBase + 0x1000;
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_NPXfreq)
|
|
{
|
|
ULONG *myNPXPtr = NPXFreq;
|
|
int i;
|
|
ULONG count;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
UNUSED(cs);
|
|
|
|
for (i=0;i<MAX_NPX_OPCODE;i++) {
|
|
if ((count = *myNPXPtr++))
|
|
fprintf(trace_file,"%s\t=\t%d\n", NPXOpcodes[i],count);
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_resetNPXfreq)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
UNUSED(cs);
|
|
|
|
printf("Resetting NPX frequency information\n");
|
|
memset((char *)NPXFreq,0,0x101*sizeof(ULONG));
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* GENERIC_NPX && !CPU_40_STYLE */
|
|
|
|
|
|
#ifdef PM
|
|
LOCAL YODA_COMMAND(do_pm)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Set Protected Mode */
|
|
setPE(1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dump_phys)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
|
|
/* Dump physical address*/
|
|
dump_phys_bytes(cs, len ? len : 32);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_show_phys_addr)
|
|
{
|
|
UNUSED(str); UNUSED(com); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
show_phys_addr((LIN_ADDR)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_phys)
|
|
{
|
|
LIN_ADDR lin;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print physical address*/
|
|
lin = eff_addr(cs,ip);
|
|
if (getPG())
|
|
show_phys_addr(lin);
|
|
else
|
|
fprintf(trace_file, "LinearAddress %08x\n", lin);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_guess_lin_phys)
|
|
{
|
|
UNUSED(str); UNUSED(com); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
guess_lin_phys((PHY_ADDR)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_guess_lin_pte)
|
|
{
|
|
UNUSED(str); UNUSED(com); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
guess_lin_pte((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dump_page_table)
|
|
{
|
|
UNUSED(str); UNUSED(com); UNUSED(ip); UNUSED(stop);
|
|
|
|
dump_page_table(cs, len);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_rtc)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
/* Re-initialise rtc */
|
|
printf("Re-initialising rtc\n");
|
|
rtc_init();
|
|
q_event_init();
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ica)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
ica_dump(0);
|
|
ica_dump(1);
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef LIM
|
|
LOCAL YODA_COMMAND(do_zaplim)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* ZAP LIM */
|
|
sas_disconnect_memory(0xd0000,0xf0000);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* LIM */
|
|
|
|
LOCAL YODA_COMMAND(do_rm)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Set Real Mode */
|
|
setPE(0);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pg)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Set paging Mode on/off */
|
|
setPG(cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pgdt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Global Descriptor Table Register */
|
|
ip = (getGDT_LIMIT() + 1) / 8; /* calc number descrs */
|
|
fprintf(trace_file, "BASE: %6x LIMIT:%4x ENTRIES:%4x\n",
|
|
getGDT_BASE(), getGDT_LIMIT(), ip);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pidt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Interrupt Descriptor Table Register */
|
|
ip = (getIDT_LIMIT() + 1) / 8; /* calc number descrs */
|
|
fprintf(trace_file, "BASE: %6x LIMIT:%4x ENTRIES:%4x\n",
|
|
getIDT_BASE(), getIDT_LIMIT(), ip);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ptr)
|
|
{
|
|
LIN_ADDR addr;
|
|
DESCR entry;
|
|
char *what;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Task Register */
|
|
|
|
if (cs == 0)
|
|
{
|
|
cs = getTR_SELECTOR();
|
|
fprintf(trace_file, "SELECTOR:%4x BASE: %6x LIMIT:%4x\n",
|
|
cs, getTR_BASE(), getTR_LIMIT());
|
|
if ( selector_outside_table(cs, &addr) )
|
|
{
|
|
fprintf(trace_file, "Bad TR selector\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( selector_outside_table(cs, &addr) )
|
|
{
|
|
fprintf(trace_file, "Bad selector\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
}
|
|
|
|
read_descriptor(addr, &entry);
|
|
addr = entry.base;
|
|
switch (entry.AR & 0x9f)
|
|
{
|
|
case 0x81: what = "286 AVALIABLE"; break;
|
|
case 0x83: what = "286 BUSY"; break;
|
|
case 0x89: what = "386 AVALIABLE"; break;
|
|
case 0x8b: what = "386 BUSY"; break;
|
|
default:
|
|
fprintf(trace_file, "Bad TSS selector\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
fprintf(trace_file, "TSS descriptor in memory is %s\n", what);
|
|
fprintf(trace_file, "TSS segment at %08x:\n", addr);
|
|
if (entry.AR & 0x08)
|
|
{
|
|
/* 386 style TSS */
|
|
|
|
fprintf(trace_file, "%-9s: %04x\n", "old TSS", sas_w_at (addr + 0x00));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ESP0", sas_dw_at (addr + 0x04));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS0", sas_w_at (addr + 0x08));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ESP1", sas_dw_at (addr + 0x0C));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS1", sas_w_at (addr + 0x10));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ESP2", sas_dw_at (addr + 0x14));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS2", sas_w_at (addr + 0x18));
|
|
fprintf(trace_file, "%-9s: %08x\n", "PDBR", sas_dw_at (addr + 0x1C));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EIP", sas_dw_at (addr + 0x20));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EFLAGS", sas_dw_at (addr + 0x24));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EAX", sas_dw_at (addr + 0x28));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ECX", sas_dw_at (addr + 0x2c));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EDX", sas_dw_at (addr + 0x30));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EBX", sas_dw_at (addr + 0x34));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ESP", sas_dw_at (addr + 0x38));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EBP", sas_dw_at (addr + 0x3c));
|
|
fprintf(trace_file, "%-9s: %08x\n", "ESI", sas_dw_at (addr + 0x40));
|
|
fprintf(trace_file, "%-9s: %08x\n", "EDI", sas_dw_at (addr + 0x44));
|
|
fprintf(trace_file, "%-9s: %04x\n", "ES", sas_w_at (addr + 0x48));
|
|
fprintf(trace_file, "%-9s: %04x\n", "CS", sas_w_at (addr + 0x4c));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS", sas_w_at (addr + 0x50));
|
|
fprintf(trace_file, "%-9s: %04x\n", "DS", sas_w_at (addr + 0x54));
|
|
fprintf(trace_file, "%-9s: %04x\n", "FS", sas_w_at (addr + 0x58));
|
|
fprintf(trace_file, "%-9s: %04x\n", "GS", sas_w_at (addr + 0x5c));
|
|
fprintf(trace_file, "%-9s: %04x\n", "LDT", sas_w_at (addr + 0x60));
|
|
fprintf(trace_file, "%-9s: %02x\n", "Trap", sas_hw_at (addr + 0x64));
|
|
}
|
|
else
|
|
{
|
|
/* 286 style TSS */
|
|
fprintf(trace_file, "%-9s: %04x\n", "old TSS", sas_w_at (addr + 0));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SP0", sas_w_at (addr + 2));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS0", sas_w_at (addr + 4));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SP1", sas_w_at (addr + 6));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS1", sas_w_at (addr + 8));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SP2", sas_w_at (addr + 10));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS2", sas_w_at (addr + 12));
|
|
fprintf(trace_file, "%-9s: %04x\n", "IP", sas_w_at (addr + 14));
|
|
fprintf(trace_file, "%-9s: %04x\n", "FLAGS", sas_w_at (addr + 16));
|
|
fprintf(trace_file, "%-9s: %04x\n", "AX", sas_w_at (addr + 18));
|
|
fprintf(trace_file, "%-9s: %04x\n", "CX", sas_w_at (addr + 20));
|
|
fprintf(trace_file, "%-9s: %04x\n", "DX", sas_w_at (addr + 22));
|
|
fprintf(trace_file, "%-9s: %04x\n", "BX", sas_w_at (addr + 24));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SP", sas_w_at (addr + 26));
|
|
fprintf(trace_file, "%-9s: %04x\n", "BP", sas_w_at (addr + 28));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SI", sas_w_at (addr + 30));
|
|
fprintf(trace_file, "%-9s: %04x\n", "DI", sas_w_at (addr + 32));
|
|
fprintf(trace_file, "%-9s: %04x\n", "ES", sas_w_at (addr + 34));
|
|
fprintf(trace_file, "%-9s: %04x\n", "CS", sas_w_at (addr + 36));
|
|
fprintf(trace_file, "%-9s: %04x\n", "SS", sas_w_at (addr + 38));
|
|
fprintf(trace_file, "%-9s: %04x\n", "DS", sas_w_at (addr + 40));
|
|
fprintf(trace_file, "%-9s: %04x\n", "LDT", sas_w_at (addr + 42));
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pldt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Local Descriptor Table Register */
|
|
ip = (getLDT_LIMIT() + 1) / 8; /* calc number descrs */
|
|
fprintf(trace_file, "SELECTOR:%4x BASE: %6x LIMIT:%4x ENTRIES:%4x\n",
|
|
getLDT_SELECTOR(), getLDT_BASE(), getLDT_LIMIT(), ip);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_par)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SPC386
|
|
fprintf(trace_file, "CS: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getCS_BASE(), getCS_LIMIT(), getCS_AR());
|
|
fprintf(trace_file, "SS: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getSS_BASE(), getSS_LIMIT(), getSS_AR());
|
|
fprintf(trace_file, "DS: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getDS_BASE(), getDS_LIMIT(), getDS_AR());
|
|
fprintf(trace_file, "ES: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getES_BASE(), getES_LIMIT(), getES_AR());
|
|
fprintf(trace_file, "FS: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getFS_BASE(), getFS_LIMIT(), getFS_AR());
|
|
fprintf(trace_file, "GS: BASE:%08x LIMIT:%08x AR:%04x\n",
|
|
getGS_BASE(), getGS_LIMIT(), getGS_AR());
|
|
#else /* SPC386 */
|
|
#ifdef CPU_30_STYLE
|
|
fprintf(trace_file, "3.0 CPU doesn't support this yet!\n");
|
|
#else
|
|
fprintf(trace_file, "CS: %d DS: %d ES: %d SS: %d\n",
|
|
ALC_CS, ALC_DS, ALC_ES, ALC_SS);
|
|
#endif /* CPU_30_STYLE */
|
|
#endif /* SPC386 */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pdtrc)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if ( cs == 0 )
|
|
{
|
|
descr_trace = 0x3f;
|
|
fprintf(stderr, " 0x01 - INVALID\n");
|
|
fprintf(stderr, " 0x02 - SPECIAL\n");
|
|
fprintf(stderr, " 0x04 - CALL GATE\n");
|
|
fprintf(stderr, " 0x08 - INTERRUPT/TRAP/TASK GATE\n");
|
|
fprintf(stderr, " 0x10 - DATA\n");
|
|
fprintf(stderr, " 0x20 - CODE\n");
|
|
}
|
|
else
|
|
descr_trace = cs;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pseg)
|
|
{
|
|
#ifndef CPU_30_STYLE
|
|
/* Print Segment Registers */
|
|
cs = (getCS_AR() & 0x60) >> 5; /* dpl */
|
|
ip = (getCS_AR() & 0x1f); /* super */
|
|
fprintf(trace_file, "CS:: SELECTOR:%4x DPL:%1d TYPE:%25s BASE: %6x LIMIT:%4x\n",
|
|
getCS_SELECTOR(), cs, segment_names[ip], getCS_BASE(), getCS_LIMIT());
|
|
cs = (getSS_AR() & 0x60) >> 5; /* dpl */
|
|
ip = (getSS_AR() & 0x1f); /* super */
|
|
fprintf(trace_file, "SS:: SELECTOR:%4x DPL:%1d TYPE:%25s BASE: %6x LIMIT:%4x\n",
|
|
getSS_SELECTOR(), cs, segment_names[ip], getSS_BASE(), getSS_LIMIT());
|
|
cs = (getDS_AR() & 0x60) >> 5; /* dpl */
|
|
ip = (getDS_AR() & 0x1f); /* super */
|
|
fprintf(trace_file, "DS:: SELECTOR:%4x DPL:%1d TYPE:%25s BASE: %6x LIMIT:%4x\n",
|
|
getDS_SELECTOR(), cs, segment_names[ip], getDS_BASE(), getDS_LIMIT());
|
|
cs = (getES_AR() & 0x60) >> 5; /* dpl */
|
|
ip = (getES_AR() & 0x1f); /* super */
|
|
fprintf(trace_file, "ES:: SELECTOR:%4x DPL:%1d TYPE:%25s BASE: %6x LIMIT:%4x\n",
|
|
getES_SELECTOR(), cs, segment_names[ip], getES_BASE(), getES_LIMIT());
|
|
#else
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
fprintf(trace_file, "Function not supported anymore\n");
|
|
#endif
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pd)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Descriptor */
|
|
if ( ip == 0 ) /* 2nd arg defaults to 1 */
|
|
ip = 1;
|
|
dump_descr((LIN_ADDR)cs, (IUM32)ip);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pdseg)
|
|
{
|
|
double_word ip_as_double_word = ip;
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Print Descriptor of a given selector */
|
|
if ( selector_outside_table(cs, &ip_as_double_word) )
|
|
{
|
|
fprintf(trace_file, "Bad selector\n");
|
|
}
|
|
else
|
|
{
|
|
cs = ip_as_double_word;
|
|
ip = 1;
|
|
dump_descr((LIN_ADDR)cs, (IUM32)ip);
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#endif
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
LOCAL YODA_COMMAND(do_blt)
|
|
{
|
|
if ( timer_blocked) {
|
|
printf("\nTimer already blocked\n");
|
|
}
|
|
else {
|
|
timer_blocked=1;
|
|
printf("\nTimer blocked\n");
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ubt)
|
|
{
|
|
if ( !timer_blocked) {
|
|
printf("\nTimer not blocked\n");
|
|
}
|
|
else {
|
|
timer_blocked=0;
|
|
printf("\nTimer unblocked\n");
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
|
|
#ifdef BSD4_2
|
|
LOCAL YODA_COMMAND(do_bs)
|
|
{
|
|
int oldmask;
|
|
|
|
if ( cs > 0 && cs < 32 )
|
|
oldmask = sigblock( 1 << ( cs - 1 ) );
|
|
else
|
|
printf("\nInvalid signal no. ( <= 0x0 or >= 0x20 )\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_us)
|
|
{
|
|
int oldmask;
|
|
|
|
if ( cs > 0 && cs < 32 )
|
|
{
|
|
oldmask = sigblock(0);
|
|
if ( (oldmask & (1 << (cs -1))) != 0 )
|
|
{
|
|
oldmask ^= (1 << ( cs - 1));
|
|
oldmask = sigsetmask(oldmask);
|
|
}
|
|
else
|
|
printf("signal not currently blocked\n");
|
|
}
|
|
else
|
|
printf("Invalid signal no. ( <= 0x0 or >= 0x20 )\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* BSD4_2 */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined (SFELLOW) && !defined (NTVDM)
|
|
extern IBOOL DoingVDDStuff;
|
|
extern IBOOL enableDebugVDD;
|
|
|
|
LOCAL YODA_COMMAND(do_vdd)
|
|
{
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
DoingVDDStuff = (cs == 0)?FALSE:TRUE;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_debug_vdd)
|
|
{
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
enableDebugVDD = (cs == 0)?FALSE:TRUE;
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE && !SFELLOW */
|
|
|
|
LOCAL YODA_COMMAND(do_tf)
|
|
{
|
|
char newtrace[100];
|
|
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
newtrace[0] = '\0';
|
|
sscanf(str, "%s %s", com, newtrace);
|
|
if ((trace_file != stderr) && (trace_file != stdout))
|
|
fclose(trace_file);
|
|
if (newtrace[0] == '\0')
|
|
trace_file = stdout;
|
|
else {
|
|
if ((trace_file = fopen(newtrace, "w")) == NULL) {
|
|
printf("couldnt open %s\n", newtrace);
|
|
trace_file = stdout;
|
|
}
|
|
}
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_read)
|
|
{
|
|
char newfile [100];
|
|
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
newfile [0] = '\0';
|
|
|
|
sscanf (str, "%s %s", com, newfile);
|
|
|
|
/* if already reading a script close it */
|
|
if (in_stream != stdin)
|
|
fclose (in_stream);
|
|
|
|
/* do we have a new pathname */
|
|
if (newfile [0])
|
|
{
|
|
/* try to open it */
|
|
if (in_stream = fopen (newfile, "r"))
|
|
{
|
|
printf ("Reading '%s'\n", newfile);
|
|
}
|
|
else
|
|
{
|
|
/* oops - provide useful error message */
|
|
perror (newfile);
|
|
|
|
/* return to reading stdin */
|
|
in_stream = stdin;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
puts ("No pathname supplied, reading stdin");
|
|
}
|
|
#endif /* SFELLOW */
|
|
return (YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_toff)
|
|
{
|
|
#ifdef SFELLOW
|
|
IU8 value;
|
|
|
|
inb(0x21, &value);
|
|
outb(0x21, value | 0x1);
|
|
#else /* SFELLOW */
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
timer_int_enabled = 0;
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ton)
|
|
{
|
|
#ifdef SFELLOW
|
|
IU8 value;
|
|
|
|
inb(0x21, &value);
|
|
outb(0x21, value & 0xfe);
|
|
#else /* SFELLOW */
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
timer_int_enabled = 1;
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_toff2)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
if (chewy) {
|
|
printf("Take care!\nThe power of the force is strong, and it can do evil as well as good.\n");
|
|
}
|
|
axe_ticks( -1 );
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ton2)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
axe_ticks( 0 );
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_query)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
trace("", trace_type);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef GISP_CPU
|
|
LOCAL YODA_COMMAND(do_hgps)
|
|
{
|
|
IMPORT VOID Hg_print_stats IPT0();
|
|
Hg_print_stats();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_hgcs)
|
|
{
|
|
IMPORT VOID Hg_clear_stats IPT0();
|
|
Hg_clear_stats();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_vex)
|
|
{
|
|
IMPORT IBOOL show_exceptions;
|
|
show_exceptions = !show_exceptions;
|
|
printf ("Verbose exceptions now %sabled.\n", (show_exceptions ? "en" : "dis"));
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bex)
|
|
{
|
|
IMPORT IBOOL trap_exceptions;
|
|
trap_exceptions = !trap_exceptions;
|
|
printf ("Break on faults now %sabled.\n", (trap_exceptions ? "en" : "dis"));
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* GISP_CPU */
|
|
#ifdef A3CPU
|
|
#ifndef GISP_CPU
|
|
LOCAL YODA_COMMAND(do_dcs)
|
|
{
|
|
long temp1, temp2, temp3;
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
temp1 = -1;
|
|
sscanf(str, "%s %lx:%lx %lx", com, &temp1, &temp2, &temp3);
|
|
if (temp1 != -1)
|
|
{
|
|
D2DmpBinaryImage((LONG)temp1);
|
|
printf ("Use the dfih command to dump the instruction history for a fragment.\n");
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dfih)
|
|
{
|
|
unsigned long temp1, temp2, temp3;
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
temp1 = -1;
|
|
sscanf(str, "%s %i:%lx %lx", com, &temp1, &temp2, &temp3);
|
|
if (temp1 != -1)
|
|
{
|
|
IH_dump_frag_hist((ULONG)temp1);
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_d2)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
D2ForceTraceInit();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_d2threshold)
|
|
{
|
|
IMPORT D2LowerThreshold, D2UpperThreshold;
|
|
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str, "%s %lx lx", com,&D2LowerThreshold,&D2UpperThreshold);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* GISP_CPU */
|
|
#endif /* A3CPU */
|
|
|
|
LOCAL YODA_COMMAND(do_u)
|
|
{
|
|
char com_args[100];
|
|
|
|
SAVED IBOOL first_time = TRUE;
|
|
SAVED IU32 last_dasm_cs, last_dasm_ip;
|
|
SAVED IU16 entryCs;
|
|
SAVED IU32 entryIp;
|
|
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
* We treat the special case of a blank argument as "continue
|
|
* from where we were last time" rather than CS:IP=0:0 which the
|
|
* address processing will have assumed. We do this unless this is
|
|
* the first time that we have been called in which case a blank
|
|
* command line means current CS:IP (which we need to get for
|
|
* ourselves.
|
|
*
|
|
* However, if the processor cs and ip has moved on from the last
|
|
* time we did a 'u', we assume that the user would probably prefer
|
|
* a 'u' from there, rather than following on.
|
|
*/
|
|
if (sscanf(str, "%*s %s", com_args) != 1) {
|
|
/*
|
|
* Blank command line ..
|
|
*/
|
|
if (first_time) {
|
|
last_dasm_cs = getCS();
|
|
last_dasm_ip = GetInstructionPointer();
|
|
entryIp = last_dasm_ip;
|
|
entryCs = last_dasm_cs;
|
|
first_time = FALSE;
|
|
} else if ((entryIp != GetInstructionPointer())
|
|
|| (entryCs != getCS()))
|
|
{
|
|
entryIp = GetInstructionPointer();
|
|
entryCs = getCS();
|
|
last_dasm_ip = entryIp;
|
|
last_dasm_cs = entryCs;
|
|
}
|
|
cs = last_dasm_cs;
|
|
ip = last_dasm_ip;
|
|
} else {
|
|
last_dasm_cs = cs;
|
|
last_dasm_ip = ip;
|
|
first_time = FALSE;
|
|
}
|
|
if ((len == 0) || (len == YODA_LEN_UNSPECIFIED))
|
|
len = 0x10;
|
|
disable_bkpt = 1;
|
|
|
|
#ifdef SPC386
|
|
{
|
|
char buff[256];
|
|
IBOOL size = CsIsBig(cs) ? THIRTY_TWO_BIT: SIXTEEN_BIT;
|
|
|
|
while (len-- > 0){
|
|
last_dasm_ip += dasm(buff, (word)cs, (IU32)last_dasm_ip, size);
|
|
fprintf (trace_file, "%s", buff);
|
|
}
|
|
}
|
|
#else /* SPC386 */
|
|
last_dasm_ip = dasm((char *)0,(word)0,(word)cs, (word)ip, (word)len);
|
|
#endif /* SPC386 */
|
|
disable_bkpt = 0;
|
|
return(YODA_LOOP_AND_REPEAT);
|
|
}
|
|
|
|
#ifdef DELTA
|
|
LOCAL YODA_COMMAND(do_del)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
examine_delta_data_structs(stdout,stdin);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* DELTA */
|
|
|
|
LOCAL YODA_COMMAND(do_j)
|
|
{
|
|
LIN_ADDR nextip;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
|
|
disable_bkpt = 1;
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
|
|
#ifdef SPC386
|
|
nextip = GetInstructionPointer();
|
|
while (len-- > 0){
|
|
nextip += dasm((char *)-1, (word)getCS(), getEIP(), 0);
|
|
}
|
|
#else /* SPC386 */
|
|
nextip = dasm((char *)-1,(word)1,(word)getCS(), (word)getIP(), (word)len);
|
|
#endif /* SPC386 */
|
|
disable_bkpt = 0;
|
|
set_inst_break(getCS(), nextip, 1, 1, 1);
|
|
disable_timer = 0;
|
|
|
|
return(go_slow());
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ctnpx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
compress_npx = fopen("comp_npx","w");
|
|
printf("compress_npx is %x\n",compress_npx);
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_r)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
disable_bkpt = 1;
|
|
trace("", DUMP_FLAGS | DUMP_REG);
|
|
disable_bkpt = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef NPX
|
|
LOCAL YODA_COMMAND(do_287r)
|
|
{
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
extern ULONG get_287_status_word IPT0();
|
|
extern ULONG get_287_control_word IPT0();
|
|
extern ULONG get_287_sp IPT0();
|
|
|
|
ULONG sw287 = get_287_status_word () | ((get_287_sp() & 0x7) << 11);
|
|
ULONG cw287 = get_287_control_word ();
|
|
int cc287;
|
|
|
|
static char *precision_cntrl[] =
|
|
{"24bit", "RESERVED(?) precision", "53bit", "64bit"};
|
|
static char *rounding_cntrl[] =
|
|
{"round to nearest/even",
|
|
"round down (towards -Inf)",
|
|
"round up (towards +Inf)",
|
|
"chop (towards zero)"};
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Decode 80287 control word */
|
|
|
|
printf ("NPX Control [%04lx]: %s, %s, %s\n", cw287,
|
|
precision_cntrl[(cw287 >> 8) & 0x3],
|
|
rounding_cntrl[(cw287 >> 10) & 0x3],
|
|
cw287 & 0x1000 ? "affine infinity" : "projective infinity");
|
|
|
|
if (cw287 & 0x3f) {
|
|
printf ("Masked Exceptions: ");
|
|
if (cw287 & 0x01) printf ("INVALID ");
|
|
if (cw287 & 0x02) printf ("DENORMAL ");
|
|
if (cw287 & 0x04) printf ("ZERO-DIVIDE ");
|
|
if (cw287 & 0x08) printf ("OVERFLOW ");
|
|
if (cw287 & 0x10) printf ("UNDERFLOW ");
|
|
if (cw287 & 0x20) printf ("PRECISION ");
|
|
printf ("\n");
|
|
} else
|
|
printf ("No exceptions masked\n");
|
|
|
|
/* Decode 80287 status word */
|
|
|
|
printf ("NPX Status [%04lx]: stack bottom = ST(%d), ", sw287,
|
|
(sw287 >> 11) & 0x7);
|
|
|
|
cc287 = (sw287 >> 8) & 0x7;
|
|
if (sw287 & 0x4000)
|
|
cc287 |= 0x80;
|
|
|
|
printf ("condition code = %1x, ", cc287);
|
|
|
|
printf ("%s\n", sw287 & 0x8000 ? "BUSY" : "not busy");
|
|
|
|
if (sw287 & 0x3f) {
|
|
printf ("Exceptions flagged (ES=%d): ", sw287 & 0x80 ? 1 : 0);
|
|
if (sw287 & 0x01) printf ("INVALID ");
|
|
if (sw287 & 0x02) printf ("DENORMAL ");
|
|
if (sw287 & 0x04) printf ("ZERO-DIVIDE ");
|
|
if (sw287 & 0x08) printf ("OVERFLOW ");
|
|
if (sw287 & 0x10) printf ("UNDERFLOW ");
|
|
if (sw287 & 0x20) printf ("PRECISION ");
|
|
printf ("\n");
|
|
} else
|
|
printf ("No exceptions flagged (ES=%d)\n",
|
|
sw287 & 0x80 ? 1 : 0);
|
|
|
|
/*
|
|
* Dump out the rest of the stack etc ..
|
|
*/
|
|
do_compress_npx(stdout);
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* NPX */
|
|
|
|
LOCAL YODA_COMMAND(do_inb)
|
|
{
|
|
half_word tempbyte;
|
|
int portNo;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x", &portNo);
|
|
inb(portNo,&tempbyte);
|
|
printf("port %04lx contains %02x\n", cs, tempbyte);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_inw)
|
|
{
|
|
IU16 tempword;
|
|
int portNo;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x", &portNo);
|
|
inw(portNo, &tempword);
|
|
printf("port %04lx contains %04x\n", cs, tempword);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_ind)
|
|
{
|
|
IU32 templong;
|
|
int portNo;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x", &portNo);
|
|
ind(portNo, &templong);
|
|
printf("port %04lx contains %08x\n", cs, templong);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_outb)
|
|
{
|
|
int portNo, value;
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x %x", &portNo, &value);
|
|
outb(portNo,(half_word)value);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_outw)
|
|
{
|
|
int portNo, value;
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x %x", &portNo, &value);
|
|
outw(portNo, (IU16)value);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_outd)
|
|
{
|
|
int portNo;
|
|
IU32 value;
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%*s %x %x", &portNo, &value);
|
|
outd(portNo, value);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_luke)
|
|
{
|
|
if (fast) {
|
|
return do_slow(str, com, cs, ip, len, stop);
|
|
}
|
|
return do_fast(str, com, cs, ip, len, stop);
|
|
}
|
|
|
|
#ifndef macintosh
|
|
LOCAL char * fff_strings[] = {
|
|
"Hmm, looks like a hardware problem to me.",
|
|
"Unexpected unary expression",
|
|
"\n/tmp> rm -rf $WD/*\n\nProblem cured.",
|
|
"It's probably the optimiser again.",
|
|
"So how long have you thought that you had these problems?",
|
|
"Looks like the SoftWindows team have broken the base again.",
|
|
"I think it's another management screw-up.",
|
|
"It's the hair - I'm sorry, but you're going to have to do something about\nthat hair.",
|
|
"Wearing silk underwear will cure most static problems.",
|
|
"You have an unitialised variable.",
|
|
"You always get that sort of problem with Quick Events.",
|
|
"Say \"William, have you seen this very interesting bug?\".",
|
|
"Time for a coffee, I think.",
|
|
"Your problem is that you are attempting to emulate an Intel processor.",
|
|
"Whoever wrote this code must have been drunk at the time.",
|
|
"It's not a bug, it's a feature",
|
|
"Why are you always finding fault? Can't you appreciate me for what I am?",
|
|
#ifdef SUNOS50
|
|
"You're running Solaris, and you don't KNOW what the problem is?????",
|
|
#endif /* SUNOS50 */
|
|
"Sorry, there is no faul "
|
|
};
|
|
#endif /* !macintosh */
|
|
|
|
LOCAL YODA_COMMAND(do_fff)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
#ifdef macintosh
|
|
printf("Sorry, the Macintosh doesn't have faults.\n");
|
|
#else
|
|
if (chewy)
|
|
printf("%s\n", fff_strings[(rand()/3) % (sizeof(fff_strings) / sizeof(char *))]);
|
|
#endif /* macintosh else */
|
|
#endif /* SFELLOW */
|
|
}
|
|
|
|
#if !defined(REAL_VGA) && !defined(SFELLOW)
|
|
LOCAL YODA_COMMAND(do_time_Display)
|
|
{
|
|
int i;
|
|
float elapsed;
|
|
struct host_timezone dummy;
|
|
struct host_timeval tstart,tend;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if( !cs ) cs=100; /* fairly long time by default */
|
|
|
|
host_clear_screen(); /* Indicate start for hand timing */
|
|
host_gettimeofday(&tstart, &dummy);
|
|
for(i=0; i<cs; i++)
|
|
{
|
|
screen_refresh_required(); /* Force full screen repaint */
|
|
(*update_alg.calc_update)(); /* and do it */
|
|
}
|
|
host_gettimeofday(&tend, &dummy);
|
|
host_clear_screen(); /* Indicate end for hand timing */
|
|
|
|
/* Now restore the original image */
|
|
screen_refresh_required();
|
|
(*update_alg.calc_update)();
|
|
|
|
/* And print out the results */
|
|
elapsed = tend.tv_sec - tstart.tv_sec + (float)(tend.tv_usec - tstart.tv_usec)/1000000.0;
|
|
printf("%d repaints of BIOS mode %d took %f seconds\n",cs,sas_hw_at_no_check(vd_video_mode),elapsed);
|
|
printf("%f seconds per refresh\n",elapsed/cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
#ifdef EGG
|
|
LOCAL YODA_COMMAND(do_dump_Display)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
dump_Display();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dump_EGA_GRAPH)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
dump_EGA_GRAPH();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dump_EGA_CPU)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
dump_EGA_CPU();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dump_planes)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
dump_ega_planes();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_read_planes)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
read_ega_planes();
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* EGG */
|
|
#endif /* not REAL_VGA and not SFELLOW */
|
|
|
|
LOCAL YODA_COMMAND(do_db)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
|
|
dump_bytes((IU16)cs, ip, (len > 0) ? len : 1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dw)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
|
|
dump_words((IU16)cs, ip, (len > 0) ? len : 1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_dd)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
|
|
dump_dwords((IU16)cs, ip, (len > 0) ? len : 1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
static int last_da_cs;
|
|
static int last_da_ip;
|
|
|
|
LOCAL YODA_COMMAND(do_da)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
da_block((IU16)cs, ip, len);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_t)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (cs)
|
|
trace_type = cs;
|
|
else
|
|
{
|
|
trace_type = DUMP_FLAGS | DUMP_REG | DUMP_INST;
|
|
if (bNPX)
|
|
trace_type |= DUMP_NPX;
|
|
}
|
|
verbose = 1;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_it)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (cs == 0L)
|
|
io_verbose = 0L;
|
|
else
|
|
{
|
|
io_verbose = cs;
|
|
if (io_verbose & HFX_VERBOSE)
|
|
#ifdef SFELLOW
|
|
printf("HFX_VERBOSE is not implemented on Stringfellows.\n");
|
|
#else /* SFELLOW */
|
|
set_hfx_severity();
|
|
#endif /* SFELLOW */
|
|
|
|
if (io_verbose & HDA_VERBOSE)
|
|
#ifdef SFELLOW
|
|
printf("HDA_VERBOSE is not implemented on Stringfellows.\n");
|
|
#else /* SFELLOW */
|
|
setdisktrace();
|
|
#endif /* SFELLOW */
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_sit)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (cs == 0L)
|
|
sub_io_verbose = 0L;
|
|
else
|
|
{
|
|
sub_io_verbose = cs;
|
|
#ifdef DPMI
|
|
if (sub_io_verbose & DPMI_VERBOSE)
|
|
set_dpmi_severity();
|
|
#endif /* DPMI */
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
|
|
LOCAL YODA_COMMAND(do_dt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
disk_trace = 1;
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_trace)
|
|
{
|
|
static char* titles[] =
|
|
{"Primary trace flags:\n",
|
|
"\n\nDisk BIOS subsidiary trace flags (enabled by primary hda flag):\n",
|
|
"\n\nFSA subsidiary trace flags (enabled by primary hfx flag):\n"};
|
|
|
|
static struct trace_flag_t {
|
|
char *name;
|
|
IU32 mask;
|
|
IU32 *addr;
|
|
int title_id;
|
|
}
|
|
trace_flags[] =
|
|
{
|
|
{"general", GENERAL_VERBOSE, &io_verbose, 1},
|
|
{"timer", TIMER_VERBOSE, &io_verbose, 0},
|
|
{"ica", ICA_VERBOSE, &io_verbose, 0},
|
|
{"cga", CGA_VERBOSE, &io_verbose, 0},
|
|
{"fla", FLA_VERBOSE, &io_verbose, 0},
|
|
{"hda", HDA_VERBOSE, &io_verbose, 0},
|
|
{"rs232", RS232_VERBOSE, &io_verbose, 0},
|
|
{"printer", PRINTER_VERBOSE, &io_verbose, 0},
|
|
{"ppi", PPI_VERBOSE, &io_verbose, 0},
|
|
{"dma", DMA_VERBOSE, &io_verbose, 0},
|
|
{"gfi", GFI_VERBOSE, &io_verbose, 0},
|
|
{"mouse", MOUSE_VERBOSE, &io_verbose, 0},
|
|
{"mda", MDA_VERBOSE, &io_verbose, 0},
|
|
{"ica_lock", ICA_VERBOSE, &io_verbose, 0},
|
|
{"diskbios", DISKBIOS_VERBOSE, &io_verbose, 0},
|
|
{"ega_ports", EGA_PORTS_VERBOSE, &io_verbose, 0},
|
|
{"ega_write", EGA_WRITE_VERBOSE, &io_verbose, 0},
|
|
{"ega_read", EGA_READ_VERBOSE, &io_verbose, 0},
|
|
{"ega_display",EGA_DISPLAY_VERBOSE, &io_verbose, 0},
|
|
{"ega_routine",EGA_ROUTINE_ENTRY, &io_verbose, 0},
|
|
{"flopbios", FLOPBIOS_VERBOSE, &io_verbose, 0},
|
|
{"at_kyb", AT_KBD_VERBOSE, &io_verbose, 0},
|
|
{"bios_kb", BIOS_KB_VERBOSE, &io_verbose, 0},
|
|
{"cmos", CMOS_VERBOSE, &io_verbose, 0},
|
|
{"hunter", HUNTER_VERBOSE, &io_verbose, 0},
|
|
{"pty", PTY_VERBOSE, &io_verbose, 0},
|
|
{"gen_drvr", GEN_DRVR_VERBOSE, &io_verbose, 0},
|
|
#if defined(HERC)
|
|
{"herc", HERC_VERBOSE, &io_verbose, 0},
|
|
#endif
|
|
{"ipc", IPC_VERBOSE, &io_verbose, 0},
|
|
{"lim", LIM_VERBOSE, &io_verbose, 0},
|
|
{"hfx", HFX_VERBOSE, &io_verbose, 0},
|
|
{"net", NET_VERBOSE, &io_verbose, 0},
|
|
{"map", MAP_VERBOSE, &sub_io_verbose, 0},
|
|
{"cursor", CURSOR_VERBOSE, &sub_io_verbose, 0},
|
|
{"nhfx", NHFX_VERBOSE, &sub_io_verbose, 0},
|
|
{"cdrom", CDROM_VERBOSE, &sub_io_verbose, 0},
|
|
{"cga_host", CGA_HOST_VERBOSE, &sub_io_verbose, 0},
|
|
{"ega_host", EGA_HOST_VERBOSE, &sub_io_verbose, 0},
|
|
{"q_event", Q_EVENT_VERBOSE, &sub_io_verbose, 0},
|
|
{"worm", WORM_VERBOSE, &sub_io_verbose, 0},
|
|
{"worm_vbose", WORM_VERY_VERBOSE, &sub_io_verbose, 0},
|
|
{"herc_host", HERC_HOST_VERBOSE, &sub_io_verbose, 0},
|
|
{"gore", GORE_VERBOSE, &sub_io_verbose, 0},
|
|
{"gore_err", GORE_ERR_VERBOSE, &sub_io_verbose, 0},
|
|
{"glue", GLUE_VERBOSE, &sub_io_verbose, 0},
|
|
{"sas", SAS_VERBOSE, &sub_io_verbose, 0},
|
|
{"ios", IOS_VERBOSE, &sub_io_verbose, 0},
|
|
{"scsi", SCSI_VERBOSE, &sub_io_verbose, 0},
|
|
{"swin", SWIN_VERBOSE, &sub_io_verbose, 0},
|
|
{"mswdvr", MSW_VERBOSE, &sub_io_verbose, 0},
|
|
{"api", API_VERBOSE, &sub_io_verbose, 0},
|
|
{"hda_call", CALL, &disktraceinfo, 2},
|
|
{"hda_cmdinfo",CMDINFO, &disktraceinfo, 0},
|
|
{"hda_xinfo", XINFO, &disktraceinfo, 0},
|
|
{"hda_xstat", XSTAT, &disktraceinfo, 0},
|
|
{"hda_pad", PAD, &disktraceinfo, 0},
|
|
{"hda_ioad", IOAD, &disktraceinfo, 0},
|
|
{"hda_portio", PORTIO, &disktraceinfo, 0},
|
|
{"hda_intrupt",INTRUPT, &disktraceinfo, 0},
|
|
{"hda_hwxinfo",HWXINFO, &disktraceinfo, 0},
|
|
{"hda_ddata", DDATA, &disktraceinfo, 0},
|
|
{"hda_physio", PHYSIO, &disktraceinfo, 0},
|
|
{"hda_dhw", DHW, &disktraceinfo, 0},
|
|
{"hda_dbios", DBIOS, &disktraceinfo, 0},
|
|
#ifdef WDCTRL_BOP
|
|
{"hda_wdctrl", WDCTRL, &disktraceinfo, 0},
|
|
#endif /* WDCTRL */
|
|
#ifdef HFX
|
|
{"hfx_input", DEBUG_INPUT, &severity, 3},
|
|
{"hfx_reg", DEBUG_REG, &severity, 0},
|
|
{"hfx_func", DEBUG_FUNC, &severity, 0},
|
|
{"hfx_host", DEBUG_HOST, &severity, 0},
|
|
{"hfx_init", DEBUG_INIT, &severity, 0}
|
|
#endif /* HFX */
|
|
};
|
|
|
|
static int n_flags = sizeof(trace_flags)/sizeof(struct trace_flag_t);
|
|
int n, n_found, negate;
|
|
IU32 mask;
|
|
char *flag_name;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
* strip off command and get first flag name
|
|
*/
|
|
n_found = 0;
|
|
(void) strtok (str, " \t");
|
|
|
|
while (flag_name = strtok(NULL, " \t")) {
|
|
/*
|
|
* Pick out symbolic flag name and see whther is is being set
|
|
* or reset.
|
|
*/
|
|
n_found += 1;
|
|
negate = (flag_name[0] == '-');
|
|
if (negate)
|
|
flag_name += 1;
|
|
|
|
/*
|
|
* Find flag and twiddle bits as appropriate.
|
|
*/
|
|
for (n = 0; n < n_flags; n++)
|
|
if (!strcmp(flag_name, trace_flags[n].name)) {
|
|
if (negate)
|
|
*trace_flags[n].addr &=
|
|
~trace_flags[n].mask;
|
|
else
|
|
*trace_flags[n].addr |=
|
|
trace_flags[n].mask;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Handle special cases of all & none. -all is none and -none
|
|
* is all.
|
|
*/
|
|
if (n == n_flags) {
|
|
mask = 1;
|
|
if (!strcmp(flag_name, "none"))
|
|
mask = 0;
|
|
else if (!strcmp(flag_name, "all"))
|
|
mask = ~0;
|
|
else {
|
|
printf ("Unknown trace flag: '%s'\n",
|
|
flag_name);
|
|
n_found -= 1;
|
|
}
|
|
|
|
if (mask != 1) /* YUK ! */
|
|
#ifdef SFELLOW
|
|
io_verbose = sub_io_verbose
|
|
#else /* SFELLOW */
|
|
#ifdef HFX
|
|
io_verbose = sub_io_verbose =
|
|
disktraceinfo = severity
|
|
#else /* HFX */
|
|
io_verbose = sub_io_verbose =
|
|
disktraceinfo
|
|
#endif /* HFX */
|
|
#endif /* SFELLOW */
|
|
= negate ? ~mask : mask;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Print current trace flags if no recognised flags passed in command.
|
|
* (or empty command line).
|
|
*/
|
|
if (n_found == 0) {
|
|
int items = 0;
|
|
for (n = 0; n < n_flags; n++) {
|
|
if (trace_flags[n].title_id) {
|
|
printf ("%s", titles[trace_flags[n].title_id-1]);
|
|
items = 0;
|
|
}
|
|
if (!(items % 4))
|
|
printf ("\n");
|
|
printf ("%14s: %-2s", trace_flags[n].name,
|
|
*trace_flags[n].addr & trace_flags[n].mask ?
|
|
"ON" : "-");
|
|
items += 1;
|
|
}
|
|
printf ("\n\n");
|
|
}
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef CPU_40_STYLE
|
|
LOCAL IBOOL check_trace_environment IFN1(char *, cmd)
|
|
{
|
|
#ifdef SYNCH_TIMERS
|
|
if (getenv("InitialJumpCounter") == NULL)
|
|
{
|
|
printf("Must have done \"setenv InitialJumpCounter ...\" to use %s\n", cmd);
|
|
return FALSE;
|
|
}
|
|
if (getenv("DisableQuickTickRecal") == NULL)
|
|
{
|
|
printf("Must have done \"setenv DisableQuickTickRecal ...\" to use %s\n", cmd);
|
|
return FALSE;
|
|
}
|
|
if (getenv("DEFAULT_QTIMER_RATE") == NULL)
|
|
{
|
|
printf("Must have done \"setenv DisableQuickTickRecal ...\" to use %s\n", cmd);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
#else /* !SYNCH_TIMERS */
|
|
|
|
printf("%s command is only available if the SoftPC has been built with -DSYNCH_TIMERS\n");
|
|
return FALSE;
|
|
|
|
#endif /* SYNCH_TIMERS */
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
LOCAL void ct_initialise IPT0();
|
|
|
|
LOCAL YODA_COMMAND(do_ct)
|
|
{
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
if (!check_trace_environment("ct"))
|
|
return(YODA_LOOP);
|
|
|
|
if ((compress_stream = fopen("compress", "w")) != NULL){
|
|
printf ("'compress' has been opened and will contain the compressed trace.\n");
|
|
}else{
|
|
printf ("Couldn't open 'compress' for output; no compressed trace will be generated.\n");
|
|
}
|
|
ct_initialise();
|
|
if (cs != 0)
|
|
{
|
|
compress_break = strtol(str + 2, (char **)0, 10);
|
|
printf("Will break after producing %ld. instructions\n", compress_break);
|
|
}
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
LOCAL YODA_COMMAND(do_ttOFF)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
compare_stream = (FILE *)0;
|
|
compare_break = 0;
|
|
compare_skip = 0;
|
|
big_dump = 0;
|
|
ct_delta_info = 0;
|
|
printf( "Compare trace is OFF\n" );
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
LOCAL YODA_COMMAND(do_tt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
if (!check_trace_environment("tt"))
|
|
return(YODA_LOOP);
|
|
|
|
ct_initialise();
|
|
|
|
if ((compare_stream = fopen("compare", "r")) != NULL)
|
|
{
|
|
printf ("'compare' has been opened to read the compressed trace.\n");
|
|
}
|
|
else
|
|
{
|
|
printf ("Couldn't open 'compare' for input; no compressed trace will be tested.\n");
|
|
}
|
|
if (ip != 0)
|
|
{
|
|
char *p = strchr(&str[2], ':');
|
|
IUH n = 0;
|
|
|
|
if (p)
|
|
n = strtol(p + 1, (char **)0, 10);
|
|
if (n)
|
|
{
|
|
compare_skip = n;
|
|
printf("Will skip first %ld. instructions\n", compare_skip);
|
|
}
|
|
else
|
|
printf("Bad skip value in %s\n", str);
|
|
}
|
|
if (cs != 0)
|
|
{
|
|
compare_break = strtol(&str[2], (char **)0, 10);
|
|
}
|
|
if (compare_skip && (compare_break <= compare_skip))
|
|
compare_break = compare_skip + 1;
|
|
if (compare_break)
|
|
printf("Will break after %ld. instructions\n", compare_break);
|
|
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
LOCAL YODA_COMMAND(do_ctOFF)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (compress_stream)
|
|
fclose(compress_stream);
|
|
compress_stream = (FILE *)0;
|
|
|
|
printf( "Compress trace is OFF\n" );
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
LOCAL YODA_COMMAND(do_nt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
disk_trace = verbose = io_verbose = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_c)
|
|
{
|
|
disable_timer = 0;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* Are you going fast, even though you could go slow and
|
|
* you seem to need to go slow?
|
|
*/
|
|
if (env_check != 2 && slow_needed && fast) {
|
|
fputs(slow_reason, stdout);
|
|
return go_slow();
|
|
}
|
|
/* otherwise we assume that you know what you are doing... */
|
|
|
|
return(YODA_RETURN);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bi)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
set_inst_break((IU16)cs, ip, (len > 0) ? len : 1, stop, 0);
|
|
(void)go_slow();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_br)
|
|
{
|
|
char regstr[20], *str2;
|
|
long minv,maxv;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
strtok(str," \t"); /* get rid of command */
|
|
strcpy(regstr,strtok(NULL," \t")); /* get register name */
|
|
minv = strtol(strtok(NULL," \t"),NULL,16); /* get min value */
|
|
str2 = strtok(NULL," \t"); /* get max value (or null if absent) */
|
|
if (str2 ==NULL)
|
|
maxv = minv;
|
|
else
|
|
maxv = strtol(str2,NULL,16);
|
|
set_reg_break(regstr, (IU32)minv, (IU32)maxv);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cr)
|
|
{
|
|
char handle[20], *strp;
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
strtok(str," \t"); /* get rid of command */
|
|
strp = strtok(NULL," \t");
|
|
if (strp == NULL)
|
|
strcpy(handle,"all");
|
|
else
|
|
strcpy(handle, strp);
|
|
clear_reg_break(handle);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pr)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_reg_break();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bint)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
int_breakpoint = 1;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cint)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
int_breakpoint = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pi)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_inst_break();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bw)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
set_data_break_words((LIN_ADDR)cs, ip, len );
|
|
(void)go_slow();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bh)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
|
|
set_host_address_break((LIN_ADDR)cs, len, stop);
|
|
(void)go_slow();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ph)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_host_address_breaks();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pw)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_data_break_words();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bo)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
|
|
set_opcode_break(cs, len); /* for len read stop */
|
|
(void)go_slow();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_vmm_call)
|
|
{
|
|
struct VMM_services *vmm_ptr;
|
|
char service_name[100], *p;
|
|
long stop_code;
|
|
long service_number;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str, "%s %100s %l", com, service_name, &stop_code);
|
|
|
|
if (service_name[0] == '?')
|
|
{
|
|
for (vmm_ptr = VMM_services; vmm_ptr->name; vmm_ptr++)
|
|
{
|
|
fprintf(trace_file, "VMM Call %s, index %d.\n",
|
|
vmm_ptr->name, vmm_ptr->value);
|
|
}
|
|
return (YODA_LOOP);
|
|
}
|
|
|
|
service_number = strtol(service_name, &p, 0);
|
|
if (service_name == p)
|
|
{
|
|
/* Name supplied, find the number */
|
|
service_number = -1;
|
|
for (vmm_ptr = VMM_services; vmm_ptr->name; vmm_ptr++)
|
|
{
|
|
if (strcmp(service_name, vmm_ptr->name) == 0)
|
|
break;
|
|
}
|
|
if (vmm_ptr->name)
|
|
service_number = vmm_ptr->value;
|
|
}
|
|
else
|
|
{
|
|
/* Number supplied, find the name */
|
|
for (vmm_ptr = VMM_services; vmm_ptr->name; vmm_ptr++)
|
|
{
|
|
if (vmm_ptr->value == service_number)
|
|
{
|
|
strcpy(service_name, vmm_ptr->name);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (service_number < 0)
|
|
{
|
|
printf("Unknown VMM Call service \"%s\"\n", service_name);
|
|
}
|
|
else
|
|
{
|
|
if (service_number >= 0x100)
|
|
set_opcode_break(0xCD200000 | (service_number & 0xffff), stop_code);
|
|
else
|
|
set_opcode_break(0xCD2000 | service_number, stop_code);
|
|
printf("Break on VMM Call service \"%s\"\n", service_name);
|
|
(void)go_slow();
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_btf)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** break on TF=1.
|
|
*/
|
|
tf_break_enabled = 1;
|
|
printf( "break on TF=1 enabled.\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ptf)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
printf( "break on TF=1 %sabled.\n", (tf_break_enabled ? "en" : "dis"));
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ctf)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
tf_break_enabled = 0;
|
|
printf( "break on TF=1 disabled.\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bintx)
|
|
{
|
|
long temp1, temp2;
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(com);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** break on specified interrupt with specified AH value.
|
|
*/
|
|
sscanf(str,"%*s %lx %lx", &temp1, &temp2);
|
|
printf( "int=%lx AH=%lx\n", temp1, temp2 );
|
|
set_int_break( (IU8)temp1, (IU8)temp2 );
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pintx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_int_break();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cintx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
int_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bse)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
bse_seg = cs;
|
|
last_seg = getCS();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cse)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
bse_seg = -1;
|
|
last_seg = -1;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pse)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (bse_seg != -1){
|
|
printf ("Break on entry to segment 0x%04x.\n", bse_seg);
|
|
}else{
|
|
printf ("Break on segment entry not active.\n");
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_b286_1)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** Break on 80286 specific opcodes.
|
|
*/
|
|
b286_1 = 1;
|
|
b286_1_stop = cs;
|
|
if( b286_1_stop )
|
|
printf( "BREAK " );
|
|
else
|
|
printf( "TRACE " );
|
|
printf( "enabled upon 80286 instructions that do not exist on 8088.\n" );
|
|
set_opcode_break( 0x60 , 1); /* push all */
|
|
set_opcode_break( 0x61 , 1); /* pop all */
|
|
set_opcode_break( 0x62 , 1); /* bound */
|
|
set_opcode_break( 0x63 , 1); /* arpl */
|
|
set_opcode_break( 0x64 , 1); /* illegal */
|
|
set_opcode_break( 0x65 , 1); /* illegal */
|
|
set_opcode_break( 0x66 , 1); /* illegal */
|
|
set_opcode_break( 0x67 , 1); /* illegal */
|
|
set_opcode_break( 0x68 , 1); /* push imm w */
|
|
set_opcode_break( 0x69 , 1); /* imul imm w */
|
|
set_opcode_break( 0x6a , 1); /* push imm b */
|
|
set_opcode_break( 0x6b , 1); /* imul imm b */
|
|
set_opcode_break( 0x6c , 1); /* ins b */
|
|
set_opcode_break( 0x6d , 1); /* ins w */
|
|
set_opcode_break( 0x6e , 1); /* outs b*/
|
|
set_opcode_break( 0x6f , 1); /* outs w */
|
|
set_opcode_break( 0xc0 , 1); /* shift imm b */
|
|
set_opcode_break( 0xc1 , 1); /* shift imm w */
|
|
set_opcode_break( 0xc8 , 1); /* enter */
|
|
set_opcode_break( 0xc9 , 1); /* leave */
|
|
set_opcode_break( 0x0f , 1); /* protected mode prefix */
|
|
set_opcode_break( 0xf36c , 1); /* rep prefix for ins and outs */
|
|
set_opcode_break( 0xf36d , 1); /* rep prefix for ins and outs */
|
|
set_opcode_break( 0xf36e , 1); /* rep prefix for ins and outs */
|
|
set_opcode_break( 0xf36f , 1); /* rep prefix for ins and outs */
|
|
set_opcode_break( 0x54 , 1); /* push sp, should not really be in this section but is rarely used */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_b286_2)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
b286_2 = 1;
|
|
b286_2_stop = cs;
|
|
if( b286_2_stop )
|
|
printf( "BREAK " );
|
|
else
|
|
printf( "TRACE " );
|
|
printf( "enabled upon 80286 instructions that behave differently to 8088.\n" );
|
|
printf( "PushF is not done because there are so many of them\n" );
|
|
printf( "If you want to break on PushF do a bo 9c\n" );
|
|
set_opcode_break( 0x54 , 1); /* push sp */
|
|
set_opcode_break( 0xd2 , 1); /* shift / rotate */
|
|
set_opcode_break( 0xd3 , 1); /* shift / rotate */
|
|
set_opcode_break( 0xf6 , 1); /* idiv */
|
|
set_opcode_break( 0xf7 , 1); /* idiv */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cNPX)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** clear break/trace on 8087/80287 instructions.
|
|
** The Numeric Coprocesseor Extention.
|
|
*/
|
|
bNPX = 0;
|
|
bNPX_stop = 0;
|
|
trace_type &= ~DUMP_NPX;
|
|
printf( "BREAK/TRACE disabled for NPX instructions\n" );
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_tNPX)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** trace on 8087/80287 instructions.
|
|
** The Numeric Coprocesseor Extention.
|
|
*/
|
|
bNPX = 1;
|
|
bNPX_stop = 0;
|
|
trace_type |= DUMP_NPX;
|
|
printf( "TRACE enabled for NPX instructions\n" );
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_bNPX)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/*
|
|
** break on 8087/80287 instructions.
|
|
** The Numeric Coprocesseor Extention.
|
|
*/
|
|
bNPX = 1;
|
|
bNPX_stop = 1;
|
|
trace_type |= DUMP_NPX;
|
|
printf( "BREAK enabled for NPX instructions\n" );
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_po)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
print_opcode_break();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ba)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
set_access_break(cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pa)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_access_break();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ci)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
inst_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ch)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
host_address_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cw)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
data_words_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_co)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
opcode_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ca)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
access_break_count = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_eric)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
inst_mix_count = 1;
|
|
if (cs == 1)
|
|
{
|
|
out_stream = fopen("inst_mix", "a");
|
|
disk_inst = 1;
|
|
}
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_nic)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
inst_mix_count = 0;
|
|
if (disk_inst == 1)
|
|
{
|
|
print_inst_mix(0);
|
|
fclose(out_stream);
|
|
out_stream = stdout;
|
|
disk_inst = 0;
|
|
printf("Instruction mix results dumped to file\n");
|
|
}
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pic)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
print_inst_mix(cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cic)
|
|
{
|
|
int temp;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
for(temp=0; temp<256; temp++)
|
|
{
|
|
inst_mix[temp] = 0;
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ax)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setAX((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_eax)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEAX((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_bx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setBX((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_ebx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEBX((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_cx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setCX((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_ecx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setECX((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_if)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setIF((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ip)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setIP((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_eip)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEIP((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_dx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setDX((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_edx)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEDX((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_si)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setSI((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_esi)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setESI((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_di)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setDI((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_edi)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEDI((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_bp)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setBP((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_ebp)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setEBP((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_sp)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setSP((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_esp)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setESP((IU32)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_es)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setES((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_fs)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setFS((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
#ifdef SPC386
|
|
LOCAL YODA_COMMAND(do_gs)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setGS((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SPC386 */
|
|
|
|
LOCAL YODA_COMMAND(do_ss)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
printf("Powerful is the force of the ss command,\nFar too powerful for an untrained jeda such as you.\nUse the sseg command must you.\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_sseg)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setSS((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_ds)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setDS((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cs)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
setCS((IU16)cs);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_byte)
|
|
{
|
|
LIN_ADDR temp;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED) {
|
|
printf ("Must specify <value>\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
temp = eff_addr( (IU16)cs, ip );
|
|
sas_store (temp, len);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_word)
|
|
{
|
|
LIN_ADDR temp;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(stop);
|
|
|
|
if (len == YODA_LEN_UNSPECIFIED) {
|
|
printf ("Must specify <value>\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
temp = eff_addr( (IU16)cs, ip );
|
|
sas_store (temp, len & 0xff);
|
|
sas_store (temp+1, (len >> 8) & 0xff);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_s)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
disable_bkpt = 1;
|
|
if (cs == 0)
|
|
step_count = 1;
|
|
else
|
|
step_count = cs;
|
|
disable_timer = 0;
|
|
|
|
return(go_slow());
|
|
}
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL IBOOL effective_lin_addr IFN5(IBOOL, pe,
|
|
IBOOL, vm,
|
|
IU16, seg,
|
|
IU32, off,
|
|
LIN_ADDR *, linaddr_p)
|
|
{
|
|
LIN_ADDR descr_addr;
|
|
DESCR entry;
|
|
|
|
if (!pe || vm) {
|
|
*linaddr_p = ((LIN_ADDR)seg << 4) + off;
|
|
return TRUE;
|
|
} else {
|
|
#if defined(SWIN_CPU_OPTS) || defined(CPU_40_STYLE)
|
|
LIN_ADDR base;
|
|
|
|
if (Cpu_find_dcache_entry( seg, &base ))
|
|
{
|
|
/* Cache Hit!! */
|
|
*linaddr_p = base + off;
|
|
return TRUE;
|
|
}
|
|
#endif /* SWIN_CPU_OPTS or CPU_40_STYLE*/
|
|
|
|
if ( !selector_outside_table(seg, &descr_addr) ) {
|
|
read_descriptor(descr_addr, &entry);
|
|
*linaddr_p = entry.base + off;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
LOCAL IS32 read_from_la IFN1(LIN_ADDR, addr)
|
|
{
|
|
return (IS32)Sas.Sas_hw_at(addr);
|
|
}
|
|
|
|
LOCAL void yoda_dasm IFN5(IBOOL, code_size,
|
|
IBOOL, pe_not_vm,
|
|
char *, buff,
|
|
IU16, cs,
|
|
LIN_ADDR, eip)
|
|
{
|
|
LIN_ADDR la;
|
|
char *fmt, *newline;
|
|
|
|
if ( eip & 0xffff0000 )
|
|
{
|
|
fmt = "%04x:%08x ";
|
|
newline = "\n ";
|
|
}
|
|
else
|
|
{
|
|
fmt = "%04x:%04x ";
|
|
newline = "\n ";
|
|
}
|
|
if (effective_lin_addr( pe_not_vm, FALSE, cs, eip, &la))
|
|
{
|
|
(void)dasm_internal(buff,
|
|
cs,
|
|
eip,
|
|
code_size,
|
|
la,
|
|
read_from_la,
|
|
fmt,
|
|
newline);
|
|
}
|
|
else
|
|
{
|
|
sprintf(buff, fmt, cs, eip);
|
|
strcat(buff, "<<Unable to decode CS:EIP>>\n");
|
|
}
|
|
}
|
|
|
|
LOCAL void
|
|
print_pla IFN3(IU16, cs, LIN_ADDR, ip, enum pla_type, what)
|
|
{
|
|
char buff[256];
|
|
|
|
switch (what)
|
|
{
|
|
case pla_type_empty:
|
|
break;
|
|
#ifdef CPU_40_STYLE
|
|
case pla_type_rm_code:
|
|
yoda_dasm(SIXTEEN_BIT, FALSE, buff, cs, ip);
|
|
fprintf (trace_file, "%s", buff);
|
|
break;
|
|
case pla_type_pm_small_code:
|
|
yoda_dasm(SIXTEEN_BIT, TRUE, buff, cs, ip);
|
|
fprintf (trace_file, "%s", buff);
|
|
break;
|
|
case pla_type_pm_big_code:
|
|
yoda_dasm(THIRTY_TWO_BIT, TRUE, buff, cs, ip);
|
|
fprintf (trace_file, "%s", buff);
|
|
break;
|
|
#else /* CPU_40_STYLE */
|
|
case pla_type_code:
|
|
(void)dasm(buff,
|
|
(word)cs,
|
|
ip,
|
|
CsIsBig(cs) ? THIRTY_TWO_BIT: SIXTEEN_BIT);
|
|
fprintf (trace_file, "%s", buff);
|
|
break;
|
|
#endif /* CPU_40_STYLE */
|
|
case pla_type_bop_done:
|
|
fprintf(trace_file, "---- %16s ---- BOP %02x completed\n", "", ip);
|
|
break;
|
|
case pla_type_simulate:
|
|
fprintf(trace_file, "---- %16s ---- SIMULATE level %d\n", "", ip);
|
|
break;
|
|
case pla_type_unsimulate:
|
|
fprintf(trace_file, "---- %16s ---- UNSIMULATE level %d\n", "", ip);
|
|
break;
|
|
case pla_type_intack:
|
|
fprintf(trace_file, "---- %16s ---- INTACK line %d\n", "", ip);
|
|
break;
|
|
case pla_type_pig_force:
|
|
fprintf(trace_file, "---- %16s ---- PIG FORCED\n", "");
|
|
break;
|
|
case pla_type_nano_enter:
|
|
fprintf(trace_file, "---- %16s ---- Entering NANO\n", "");
|
|
break;
|
|
case pla_type_nano_leave:
|
|
fprintf(trace_file, "---- %16s ---- Leaving NANO\n", "");
|
|
break;
|
|
default:
|
|
fprintf(trace_file,
|
|
"%04x:%08x *** Bad pla type %d\n",
|
|
cs, ip, what);
|
|
break;
|
|
}
|
|
}
|
|
#else /* CPU_40_STYLE */
|
|
LOCAL void
|
|
print_pla IFN2(IU16, cs, LIN_ADDR, ip)
|
|
{
|
|
fprintf(trace_file, "Last address = %04x:%04x\n", cs, ip);
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
LOCAL YODA_COMMAND(do_pla)
|
|
{
|
|
LIN_ADDR i;
|
|
LIN_ADDR pla_length;
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (cs)
|
|
pla_length = (LIN_ADDR)cs;
|
|
else
|
|
pla_length = 100; /* default */
|
|
|
|
if (pla_length > PLA_SIZE)
|
|
pla_length = PLA_SIZE;
|
|
|
|
/* Print the end of the buffer if necessary. */
|
|
for (i = PLA_SIZE - (pla_length - pla_ptr); i < PLA_SIZE; i++)
|
|
#ifdef CPU_40_STYLE
|
|
print_pla(last_cs[i], last_ip[i], last_type[i]);
|
|
#else
|
|
print_pla(last_cs[i], last_ip[i]);
|
|
#endif
|
|
|
|
/* Print the start of the buffer. */
|
|
if (pla_length > pla_ptr)
|
|
i = 0;
|
|
else
|
|
i = pla_ptr - pla_length;
|
|
|
|
for ( ; i < pla_ptr; i++)
|
|
#ifdef CPU_40_STYLE
|
|
print_pla(last_cs[i], last_ip[i], last_type[i]);
|
|
#else
|
|
print_pla(last_cs[i], last_ip[i]);
|
|
#endif
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cgat)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
cga_test();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(old_times_sake)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (chewy) {
|
|
printf("Remember --- you must FEEL the force...\n");
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_fast)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (!fast) {
|
|
printf("Switching to Fast YODA...\n");
|
|
}
|
|
yint = 0; fast = 1; do_condition_checks = 0;
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_slow)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
(void)go_slow();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_q)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
|
|
#ifdef SFELLOW
|
|
printf("Welcome to the Hotel California.\n");
|
|
printf("You can check out any time you like, but you can never leave...\n");
|
|
#else /* SFELLOW */
|
|
if (*com == 'Q') {
|
|
terminate(); /* no saving throw - requested by Wayne */
|
|
} else {
|
|
stop = yoda_confirm("Are you sure that you want to quit? ");
|
|
if (stop) {
|
|
if (chewy) {
|
|
printf("\nMind what you have learned....\n");
|
|
printf("Serve you it can !!!\n");
|
|
printf("MAY THE FORCE BE WITH YOU\n\n");
|
|
terminate();
|
|
}
|
|
terminate();
|
|
}
|
|
}
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
|
|
LOCAL YODA_COMMAND(do_bt)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
/* back trace set up and dump */
|
|
do_back_trace();
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_idle)
|
|
{
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
char tempstr1[10],tempstr2[10];
|
|
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
sscanf(str,"%s %s",tempstr1,tempstr2);
|
|
/* enable/disable idle detect */
|
|
if ((strcmp(tempstr2,"ON")==0) || (strcmp(tempstr2,"on")==0))
|
|
{
|
|
idle_ctl(1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
if ((strcmp(tempstr2,"OFF")==0) || (strcmp(tempstr2,"off")==0))
|
|
{
|
|
idle_ctl(0);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
printf("unrecognised string '%s'\n",tempstr2);
|
|
#endif /* SFELLOW */
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cdebug)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
com_debug();
|
|
#endif /* SFELLOW */
|
|
return (YODA_LOOP);
|
|
}
|
|
|
|
LOCAL void do_screen_refresh IFN0()
|
|
{
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
extern host_timer_event();
|
|
|
|
host_mark_screen_refresh();
|
|
host_flush_screen();
|
|
|
|
host_timer_event();
|
|
#endif /* SFELLOW */
|
|
}
|
|
|
|
YODA_CMD_RETURN do_rfrsh IFN6(char *, str, char *, com, IS32, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
do_screen_refresh();
|
|
refresh_screen = !refresh_screen;
|
|
return (YODA_LOOP);
|
|
}
|
|
|
|
#ifdef EGA_DUMP
|
|
|
|
/*
|
|
* add check point to ega dump file so that different activities can be
|
|
* delimited
|
|
*/
|
|
|
|
LOCAL int do_dumpcp IFN0()
|
|
{
|
|
dump_add_checkpoint();
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* EGA_DUMP */
|
|
|
|
LOCAL YODA_COMMAND(do_chewy)
|
|
{
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
chewy = (chewy? 0 : 1);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifndef GISP_CPU
|
|
#ifdef A3CPU
|
|
LOCAL YODA_COMMAND(do_3c)
|
|
{
|
|
extern void Mgr_yoda();
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
Mgr_yoda();
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif
|
|
#endif /* GISP_CPU */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
LOCAL YODA_COMMAND(do_4c)
|
|
{
|
|
extern void FmDebug IPT1(IUH, hook);
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
FmDebug(0);
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_imdst)
|
|
{
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
#ifdef SFELLOW
|
|
|
|
UNUSED(cs);
|
|
printf(SfNotImp);
|
|
|
|
#else /* SFELLOW */
|
|
|
|
IntelMsgDest = cs & 3;
|
|
printf("Intel messages to trace output %s\n", IntelMsgDest & IM_DST_TRACE?"ON":"OFF");
|
|
printf("Intel messages to ring buffer %s\n", IntelMsgDest & IM_DST_RING?"ON":"OFF");
|
|
|
|
#endif /* SFELLOW */
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
|
|
#ifdef PIG
|
|
LOCAL YODA_COMMAND(do_pig)
|
|
{
|
|
extern void pig_yoda();
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
pig_yoda();
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SYNCH_TIMERS
|
|
LOCAL YODA_COMMAND(do_qtrate)
|
|
{
|
|
extern IU32 Q_timer_restart_val;
|
|
extern IU32 Q_timer_microsecs;
|
|
extern void IdealTimeInit();
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
if (cs == 0)
|
|
{
|
|
printf("quick timer rate is 0x%x (%d)\n", Q_timer_restart_val, Q_timer_restart_val);
|
|
}
|
|
else
|
|
{
|
|
printf("setting quick timer rate to 0x%x (%d)\n", cs, cs);
|
|
Q_timer_restart_val = cs;
|
|
Q_timer_microsecs = cs;
|
|
IdealTimeInit();
|
|
}
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* SYNCH_TIMERS */
|
|
|
|
#ifdef PROFILE
|
|
LOCAL YODA_COMMAND(doDumpProfiling)
|
|
{
|
|
extern void GenerateAllProfileInfo();
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(len);
|
|
UNUSED(stop);
|
|
|
|
GenerateAllProfileInfo(trace_file);
|
|
return(YODA_LOOP);
|
|
}
|
|
#endif /* PROFILE */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
|
|
#define N_DATA_BREAKPOINTS 4
|
|
|
|
struct {
|
|
IBOOL active;
|
|
IBOOL write;
|
|
IU8 dataSz;
|
|
IU32 linAddr;
|
|
} dataBreakpoint[N_DATA_BREAKPOINTS];
|
|
|
|
IU32 dataSzLut[] = {0x0,0x0,0x4,0x0,0xC};
|
|
char *sizeString[] = {"BAD0", "byte", "word", "BAD3", "dbl."};
|
|
|
|
VOID
|
|
printDataBreakPoints IFN1 (
|
|
IU32, hitMask
|
|
)
|
|
{
|
|
IU32 i;
|
|
IBOOL doneOne = FALSE;
|
|
|
|
for (i=0; i<N_DATA_BREAKPOINTS; i++)
|
|
{
|
|
if (dataBreakpoint[i].active)
|
|
{
|
|
if (!doneOne)
|
|
{
|
|
fprintf (trace_file, "# Access LinAddr\n");
|
|
fprintf (trace_file, "-------------------\n");
|
|
doneOne = TRUE;
|
|
}
|
|
fprintf (trace_file, "%d: %s %s 0x%08x %s\n", i,
|
|
dataBreakpoint[i].write?"WT":"RW",
|
|
sizeString[dataBreakpoint[i].dataSz],
|
|
dataBreakpoint[i].linAddr,
|
|
(hitMask&(1<<i))?"<====TRIGGERED":"");
|
|
}
|
|
}
|
|
if (doneOne)
|
|
{
|
|
fprintf (trace_file, "--------------------\n");
|
|
}else{
|
|
fprintf (trace_file, "No Data Breakpoints Active.\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* data_debug_exception - this function is called by the EDL CPU when a
|
|
* data debug exception goes off and the snaffleDataDebugExcpn flag is set
|
|
* indicating that yoda is driving the debug registers.
|
|
*/
|
|
VOID
|
|
data_debug_exception IFN0()
|
|
{
|
|
fprintf (trace_file, "data_debug_exception occurred... debug status reg = 0x%08x\n", getDREG6());
|
|
|
|
printDataBreakPoints (getDREG6());
|
|
|
|
moveToDebugRegister (6, getDREG6()&(~0xF));
|
|
|
|
force_yoda();
|
|
}
|
|
|
|
VOID
|
|
add_debug_breakpoint IFN3 (
|
|
IBOOL, write,
|
|
IU8, dataSz,
|
|
IU32, linAddr
|
|
)
|
|
{
|
|
IU32 i, debugControl;
|
|
|
|
for (i=0; i<N_DATA_BREAKPOINTS; i++)
|
|
{
|
|
if (!dataBreakpoint[i].active)
|
|
{
|
|
dataBreakpoint[i].active = TRUE;
|
|
dataBreakpoint[i].write = write;
|
|
dataBreakpoint[i].dataSz = dataSz;
|
|
dataBreakpoint[i].linAddr = linAddr;
|
|
|
|
moveToDebugRegister (i, linAddr);
|
|
|
|
debugControl = getDREG7();
|
|
|
|
debugControl &= ~((0xF << ((4*i) + 16)) | (0x3 << (2*i)));
|
|
|
|
debugControl |= (0x2 << (2*i));
|
|
|
|
debugControl |= (((dataSzLut[dataSz])|(write?0x1:0x3)) << ((4*i) + 16));
|
|
|
|
moveToDebugRegister (7, debugControl);
|
|
setSnaffleDataDebugExcpn (TRUE);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
fprintf (stderr, "Only %d data breakpoints available... sorry!\n", N_DATA_BREAKPOINTS);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_pdb)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(cs); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
printDataBreakPoints (0);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_cdb)
|
|
{
|
|
IU32 i;
|
|
IBOOL stillActive = FALSE;
|
|
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
dataBreakpoint[cs].active = FALSE;
|
|
|
|
for (i=0; i<N_DATA_BREAKPOINTS; i++)
|
|
{
|
|
stillActive |= dataBreakpoint[i].active;
|
|
}
|
|
|
|
setSnaffleDataDebugExcpn (stillActive);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blrb)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (FALSE, 1, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blrw)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (FALSE, 2, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blrd)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (FALSE, 4, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blwb)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (TRUE, 1, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blww)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (TRUE, 2, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
LOCAL YODA_COMMAND(do_blwd)
|
|
{
|
|
UNUSED(com); UNUSED(str); UNUSED(ip); UNUSED(len); UNUSED(stop);
|
|
|
|
add_debug_breakpoint (TRUE, 4, cs);
|
|
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
/*
|
|
* YODA COMMAND TABLE
|
|
* ==================
|
|
*/
|
|
|
|
static struct
|
|
{
|
|
char *name;
|
|
YODA_CMD_RETURN (*function) IPT6(char *, str, char *, com, IS32, cs,
|
|
LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop);
|
|
IBOOL decode_iaddr;
|
|
char *args;
|
|
char *comment;
|
|
} yoda_command[] =
|
|
{
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
{ "blt", do_blt, FALSE, NULL, "Block the timer signal" },
|
|
{ "ubt", do_ubt, FALSE, NULL, "Unblock the timer signal" },
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
|
|
#ifdef BSD4_2
|
|
{ "bs", do_bs, FALSE, "<signo>", "Block signal <signo>" },
|
|
{ "us", do_us, FALSE, "<signo>", "Unblock signal <signo>" },
|
|
#endif /* BSD4_2 */
|
|
|
|
{ "tf", do_tf, FALSE, "<filename>", "Re-direct trace output" },
|
|
{ "read", do_read, FALSE, "<filename>", "Take commands from file" },
|
|
{ "toff", do_toff, FALSE, NULL, "Disable HW timer interrupts (may be turned on by application)" },
|
|
{ "ton", do_ton, FALSE, NULL, "Enable HW timer interrupts" },
|
|
{ "toff2", do_toff2, FALSE, NULL, "Stop HW timer interrupts" },
|
|
{ "ton2", do_ton2, FALSE, NULL, "Restart HW timer interrupts" },
|
|
{ "?", do_query, FALSE, NULL, "Where am I?" },
|
|
{ "u", do_u, TRUE, "<len>", "Unassemble memory" },
|
|
|
|
#ifdef DELTA
|
|
{ "del", do_del, FALSE, NULL, "Go to delta debugger" },
|
|
#endif /* DELTA */
|
|
|
|
{ "j", do_j, FALSE, NULL, "Jump over call or int" },
|
|
{ "ctnpx", do_ctnpx, FALSE, NULL, "Compress trace npx" },
|
|
{ "r", do_r, FALSE, NULL, "Print 286 registers" },
|
|
|
|
#ifdef NPX
|
|
{ "287r", do_287r, FALSE, NULL, "Print 287 registers" },
|
|
#endif /* NPX */
|
|
|
|
{ "inb", do_inb, FALSE, "<port>", "display the contents of a port" },
|
|
{ "outb", do_outb, FALSE, "<port> <val>", "change the contents of a port" },
|
|
{ "inw", do_inw, FALSE, "<port>", "display the contents of a 16 bit port" },
|
|
{ "outw", do_outw, FALSE, "<port> <val>", "change the contents of a 16 bit port" },
|
|
#ifdef SPC386
|
|
{ "ind", do_ind, FALSE, "<port>", "display the contents of a 32 bit port" },
|
|
{ "outd", do_outd, FALSE, "<port> <val>", "change the contents of a 32 bit port" },
|
|
#endif /* SPC386 */
|
|
{ "i", do_inb, FALSE, "<port>", "alias for inb" },
|
|
{ "o", do_outb, FALSE, "<port> <val>", "alias for outb" },
|
|
{ "luke", do_luke, FALSE, NULL, "Switch between fast/slow yoda" },
|
|
{ "fff", do_fff, FALSE, NULL, "Find, and fix fault"},
|
|
|
|
#if !defined(REAL_VGA) && !defined(SFELLOW)
|
|
{ "time_Display", do_time_Display,
|
|
FALSE, "<count>", "Time current screen refresh" },
|
|
|
|
#ifdef EGG
|
|
{ "dump_Display", do_dump_Display,
|
|
FALSE, NULL, "Dump general display variables" },
|
|
{ "dump_EGA_GRAPH", do_dump_EGA_GRAPH,
|
|
FALSE, NULL, "Dump EGA specific display variables" },
|
|
{ "dump_EGA_CPU", do_dump_EGA_CPU,
|
|
FALSE, NULL, "Dump EGA/CPU interface variables" },
|
|
{ "dump_planes", do_dump_planes,
|
|
FALSE, NULL, "Dump EGA planes" },
|
|
{ "read_planes", do_read_planes,
|
|
FALSE, NULL, "Read EGA planes" },
|
|
#endif /* EGG */
|
|
#endif /* !REAL_VGA && !SFELLOW */
|
|
|
|
{ "db", do_db, TRUE, "<len>", "Display bytes" },
|
|
{ "dw", do_dw, TRUE, "<len>", "Display words" },
|
|
#ifdef SPC386
|
|
{ "dd", do_dd, TRUE, "<len>", "Display dwords" },
|
|
#endif /* SPC386 */
|
|
{ "da", do_da, TRUE, "<len>", "Display in hex/ascii" },
|
|
{ "t", do_t, FALSE, NULL, "Trace all CPU instructions" },
|
|
{ "it", do_it, FALSE, "<val>", "Set trace bits (use trace!)" },
|
|
{ "sit", do_sit, FALSE, "<val>", "Set subsidiary trace bits (use trace!)" },
|
|
{ "trace", do_trace, FALSE, "[-]<flag_name> [...]", "Set/reset trace flag(s)" },
|
|
{ "dt", do_dt, FALSE, NULL, "Set disk verbose tracing" },
|
|
#ifdef CPU_40_STYLE
|
|
{ "ct", do_ct, FALSE, "<type> <del>", "Create compressed trace file" },
|
|
{ "ttOFF", do_ttOFF, FALSE, NULL, "Switch compare trace off" },
|
|
{ "tt", do_tt, FALSE, NULL, "test Compressed trace file" },
|
|
{ "ctOFF", do_ctOFF, FALSE, NULL, "Switch compress trace off" },
|
|
#endif /* CPU_40_STYLE */
|
|
{ "nt", do_nt, FALSE, NULL, "Disable all tracing" },
|
|
{ "c", do_c, FALSE, NULL, "Continue execution" },
|
|
{ "bint", do_bint, FALSE, NULL, "Break on interrupt" },
|
|
{ "cint", do_cint, FALSE, NULL, "Clear break on interrupt" },
|
|
{ "bintx", do_bintx, FALSE, "<int> <ah>", "Break on interrupt <int> when ah = <ah>" },
|
|
{ "pintx", do_pintx, FALSE, NULL, "print intx breakpoints" },
|
|
{ "cintx", do_cintx, FALSE, NULL, "clear intx breakpoints" },
|
|
{ "br", do_br, FALSE, "<reg> <min> <max>", "Break on register value" },
|
|
{ "cr", do_cr, FALSE, "<handle>|'all'", "Clear register value breakpoint(s)" },
|
|
{ "pr", do_pr, FALSE, NULL, "Print register value breakpoints" },
|
|
{ "bse", do_bse, FALSE, NULL, "Break on segment entry" },
|
|
{ "cse", do_cse, FALSE, NULL, "Clear segment entry breakpoints" },
|
|
{ "pse", do_pse, FALSE, NULL, "Print segment entry breakpoints" },
|
|
{ "btf", do_btf, FALSE, NULL, "Break on trap flag set" },
|
|
{ "ptf", do_ptf, FALSE, NULL, "Print trap flag breakpoint" },
|
|
{ "ctf", do_ctf, FALSE, NULL, "Clear trap flag breakpoint" },
|
|
{ "b286-1", do_b286_1, FALSE, "<type>", "Break/trace on new 80286 opcodes" },
|
|
{ "b286-2", do_b286_2, FALSE, "<type>", "Break/trace on other 80286 opcodes" },
|
|
{ "bNPX", do_bNPX, FALSE, NULL, "Break on NPX opcodes, 8087/80287" },
|
|
{ "tNPX", do_tNPX, FALSE, NULL, "Trace on NPX opcodes, 8087/80287" },
|
|
{ "cNPX", do_cNPX, FALSE, NULL, "Clear break/trace NPX opcodes, 8087/80287" },
|
|
{ "ba", do_ba, FALSE, "<port>", "Break on port access" },
|
|
{ "bh", do_bh, FALSE, "<hostadd> <len> <type>", "Break on host address change" },
|
|
{ "bi", do_bi, TRUE, "<len> <type>", "Break at address/instruction" },
|
|
{ "bo", do_bo, FALSE, "<opcode> <type>", "Break on opcode of 8, 16, 24, or 32 bits" },
|
|
{ "vmm_call", do_vmm_call, FALSE, "<service> <stop>", "Break Windows VMM Call -- ? for service names" },
|
|
{ "bw", do_bw, FALSE, "<sysadd> <len> <type>", "Break on word change" },
|
|
{ "pa", do_pa, FALSE, NULL, "Print a breakpoints" },
|
|
{ "ph", do_ph, FALSE, NULL, "Print h breakpoints" },
|
|
{ "pi", do_pi, FALSE, NULL, "Print i breakpoints" },
|
|
{ "po", do_po, FALSE, NULL, "Print o breakpoints" },
|
|
{ "pw", do_pw, FALSE, NULL, "Print w breakpoints" },
|
|
{ "ca", do_ca, FALSE, NULL, "Clear a breakpoints" },
|
|
{ "ch", do_ch, FALSE, NULL, "Clear h breakpoints" },
|
|
{ "ci", do_ci, FALSE, NULL, "Clear i breakpoints" },
|
|
{ "co", do_co, FALSE, NULL, "Clear o breakpoints" },
|
|
{ "cw", do_cw, FALSE, NULL, "Clear w breakpoints" },
|
|
{ "eric", do_eric, FALSE, NULL, "Enable reduced instruction counting" },
|
|
{ "nic", do_nic, FALSE, NULL, "Disable instruction counting" },
|
|
{ "pic", do_pic, FALSE, NULL, "Print instruction mix" },
|
|
{ "cic", do_cic, FALSE, NULL, "" },
|
|
{ "ax", do_ax, FALSE, "<value>", "Set AX to <value>" },
|
|
{ "bx", do_bx, FALSE, "<value>", "Set BX to <value>" },
|
|
{ "cx", do_cx, FALSE, "<value>", "Set CX to <value>" },
|
|
{ "dx", do_dx, FALSE, "<value>", "Set DX to <value>" },
|
|
{ "si", do_si, FALSE, "<value>", "Set SI to <value>" },
|
|
{ "di", do_di, FALSE, "<value>", "Set DI to <value>" },
|
|
{ "bp", do_bp, FALSE, "<value>", "Set BP to <value>" },
|
|
{ "sp", do_sp, FALSE, "<value>", "Set SP to <value>" },
|
|
{ "if", do_if, FALSE, "<value>", "Set IF to <value>" },
|
|
{ "ip", do_ip, FALSE, "<value>", "Set IP to <value>" },
|
|
#ifdef SPC386
|
|
{ "eax", do_eax, FALSE, "<value>", "Set EAX to <value>" },
|
|
{ "ebx", do_ebx, FALSE, "<value>", "Set EBX to <value>" },
|
|
{ "ecx", do_ecx, FALSE, "<value>", "Set ECX to <value>" },
|
|
{ "edx", do_edx, FALSE, "<value>", "Set EDX to <value>" },
|
|
{ "esi", do_esi, FALSE, "<value>", "Set ESI to <value>" },
|
|
{ "edi", do_edi, FALSE, "<value>", "Set EDI to <value>" },
|
|
{ "ebp", do_ebp, FALSE, "<value>", "Set EBP to <value>" },
|
|
{ "esp", do_esp, FALSE, "<value>", "Set ESP to <value>" },
|
|
{ "eip", do_eip, FALSE, "<value>", "Set EIP to <value>" },
|
|
#endif /* SPC386 */
|
|
{ "cs", do_cs, FALSE, "<value>", "Set CS to <value>" },
|
|
{ "ds", do_ds, FALSE, "<value>", "Set DS to <value>" },
|
|
{ "es", do_es, FALSE, "<value>", "Set ES to <value>" },
|
|
{ "ss", do_ss, FALSE, NULL, NULL }, /* backwards compatibility */
|
|
#ifdef SPC386
|
|
{ "fs", do_fs, FALSE, "<value>", "Set FS to <value>" },
|
|
{ "gs", do_gs, FALSE, "<value>", "Set GS to <value>" },
|
|
#endif /* SPC386 */
|
|
{ "sseg", do_sseg, FALSE, "<value>", "Set SS to value" },
|
|
{ "byte", do_byte, TRUE, "<value>", "Set byte memory location to value" },
|
|
{ "word", do_word, TRUE, "<value>", "Set word memory location to value" },
|
|
{ "s", do_s, FALSE, "<len>", "Single step <len> instructions" },
|
|
{ "pla", do_pla, FALSE, "<len>", "Print addresses of previous instructions" },
|
|
{ "cgat", do_cgat, FALSE, NULL, "CGA tester" },
|
|
{ "yint", old_times_sake, FALSE, NULL, "Enable pseudo-int driven yoda" },
|
|
{ "nyint", do_fast, FALSE, NULL, NULL },
|
|
{ "quit", do_q, FALSE, NULL, "Quit (with confirmation)" },
|
|
{ "q", do_q, FALSE, NULL, NULL },
|
|
{ "Q", do_q, FALSE, NULL, "Quit (without confirmation)" },
|
|
{ "help", do_h, FALSE, NULL, "Help!" },
|
|
{ "h", do_h, FALSE, NULL, NULL},
|
|
{ "jeddi", do_chewy, FALSE, NULL, NULL},
|
|
{ "bt", do_bt, FALSE, NULL, "Back trace mode" },
|
|
{ "idle", do_idle, FALSE, "<ON|OFF>", "Turn idle detect on/off" },
|
|
{ "fast", do_fast, FALSE, NULL, "Fast yoda (no breakpoints)" },
|
|
{ "slow", do_slow, FALSE, NULL, "Slow yoda" },
|
|
{ "cd", do_cdebug, FALSE, NULL, "COM1 register debugger"},
|
|
|
|
#ifdef EGA_DUMP
|
|
{ "dumpcp", do_dumpcp, FALSE, NULL, "Add check point to EGA dump trace" },
|
|
#endif /* EGA_DUMP */
|
|
|
|
#ifdef GISP_CPU
|
|
{ "hgps", do_hgps, FALSE, NULL, "Print GISP CPU stats" },
|
|
{ "hgcs", do_hgcs, FALSE, NULL, "Clear GISP CPU stats" },
|
|
{ "vex", do_vex, FALSE, NULL, "Toggle verbose faults" },
|
|
{ "bex", do_bex, FALSE, NULL, "Toggle break on faults" },
|
|
#endif /* GISP_CPU */
|
|
|
|
#ifdef SYNCH_TIMERS
|
|
{ "qtrate", do_qtrate, FALSE, "<rate>", "set quick timer rate" },
|
|
#endif
|
|
#ifdef A3CPU
|
|
#ifndef GISP_CPU
|
|
{ "d2", do_d2, FALSE, NULL, "Force D2 interact" },
|
|
{ "dcs", do_dcs, FALSE, "<seg>", "Dump binary in code segment to 'csegbin'" },
|
|
{ "dfih", do_dfih, FALSE, "<fragnr>", "Dump fragment history to 'fih_nnnn'" },
|
|
{ "th", do_d2threshold, FALSE, "<lower> <upper>", "Set delta2 thresholds" },
|
|
#endif /* GISP_CPU */
|
|
#endif /* A3CPU */
|
|
|
|
#ifdef PM
|
|
{ "pm", do_pm, FALSE, NULL, "Set protected mode" },
|
|
#ifdef LIM
|
|
{ "zaplim", do_zaplim, FALSE, NULL, "Zap LIM" },
|
|
#endif /* :IM */
|
|
{ "rm", do_rm, FALSE, NULL, "Set real mode" },
|
|
{ "pg", do_pg, FALSE, NULL, "Set paging mode 1 (enabled) or 0 (disabled)" },
|
|
{ "pgdt", do_pgdt, FALSE, NULL, "Print global descriptor table" },
|
|
{ "pidt", do_pidt, FALSE, NULL, "Print interrupt descriptor table" },
|
|
{ "ptr", do_ptr, FALSE, NULL, "Print task register" },
|
|
{ "pldt", do_pldt, FALSE, NULL, "Print local descriptor table reg." },
|
|
{ "par", do_par, FALSE, NULL, "" },
|
|
{ "pseg", do_pseg, FALSE, NULL, "Print segment registers" },
|
|
{ "pd", do_pd, FALSE, "<phys-addr>:<num>", "Print descriptor(s)" },
|
|
{ "pdseg", do_pdseg, FALSE, NULL, "Print descriptor of selector" },
|
|
{ "phys", do_phys, TRUE, NULL, "Print physical address" },
|
|
{ "dphys", do_dump_phys, FALSE, "<phys-addr> <len>", "Dump from physical address" },
|
|
{ "spa", do_show_phys_addr, FALSE, "<lin-addr>", "Show physical address from linear" },
|
|
{ "gla", do_guess_lin_phys, FALSE, "<phys-addr>", "Guess linear address from physical" },
|
|
{ "gpte", do_guess_lin_pte, FALSE, "<pte-addr>", "Guess linear address from pte address" },
|
|
{ "dpt", do_dump_page_table, FALSE, "<phys-addr> <entry>", "Dump all or specific entry from Page Table" },
|
|
{ "rtc", do_rtc, FALSE, NULL, "Re-initialise the rtc" },
|
|
{ "ica", do_ica, FALSE, NULL, "Show status of ica" },
|
|
#endif
|
|
#ifdef CPU_40_STYLE
|
|
{ "blrb", do_blrb, FALSE, NULL, "Break on linear read byte" },
|
|
{ "blrw", do_blrw, FALSE, NULL, "Break on linear read word" },
|
|
{ "blrd", do_blrd, FALSE, NULL, "Break on linear read double" },
|
|
{ "blwb", do_blwb, FALSE, NULL, "Break on linear write byte" },
|
|
{ "blww", do_blww, FALSE, NULL, "Break on linear write word" },
|
|
{ "blwd", do_blwd, FALSE, NULL, "Break on linear write double" },
|
|
{ "pdb", do_pdb, FALSE, NULL, "Print data breakpoints" },
|
|
{ "cdb", do_cdb, FALSE, NULL, "Clear data breakpoint" },
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined (SFELLOW) && !defined(NTVDM)
|
|
{ "vdd", do_vdd, FALSE, "0 or 1", "Turn Windows VDD trapping off or on" },
|
|
{ "debug_vdd", do_debug_vdd, FALSE, "0 or 1", "Turn Windows VDD debugging off or on" },
|
|
#endif /* CPU_40_STYLE && !SFELLOW && !NTVDM*/
|
|
|
|
{ "rfrsh", do_rfrsh, FALSE, NULL, "Toggle Yoda screen refresh" },
|
|
|
|
#ifndef GISP_CPU
|
|
#ifdef A3CPU
|
|
{ "3c", do_3c, FALSE, NULL, "3.0 CPU interface" },
|
|
#endif
|
|
#endif /* GISP_CPU */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
{ "4c", do_4c, FALSE, NULL, "4.0 CPU interface" },
|
|
{ "imdst", do_imdst, FALSE, "[0|1|2|3]", "Direct Intel debug message output (trace=bit0, ring=bit1)" },
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
|
|
#ifdef PIG
|
|
{ "pig", do_pig, FALSE, NULL, "Pig interface" },
|
|
#endif
|
|
|
|
#if defined(GENERIC_NPX) && !defined(CPU_40_STYLE)
|
|
{ "NPXdisp", do_NPXdisp, FALSE, "<len>", "Display last <len> NPX instructions" },
|
|
{ "NPXfreq", do_NPXfreq, FALSE, NULL, "Display frequency of NPX instructions" },
|
|
{ "resetNPXfreq", do_resetNPXfreq, FALSE, NULL, "Reset frequency of NPX instructions" },
|
|
#endif /* GENERIC_NPX && !CPU_40_STYLE */
|
|
|
|
#ifdef MSWDVR_DEBUG
|
|
{ "mswdvr_debug", do_mswdvr_debug, FALSE, "<0|1|2|3>", "Set MSWDVR debug verbosity"},
|
|
#endif /* MSWDVR_DEBUG */
|
|
|
|
#ifdef GISP_SVGA
|
|
{ "noyoda", doNoYoda, FALSE, NULL, "Toggle force_yoda on/off" },
|
|
#endif /* GISP_SVGA */
|
|
#ifdef PROFILE
|
|
{ "pinfo", doDumpProfiling,FALSE, NULL, "Dump all profiling info collected" },
|
|
#endif /* PROFILE */
|
|
{ "pmt", do_pmt, FALSE, NULL, "Print map of SAS memory types"}
|
|
};
|
|
|
|
LOCAL YODA_COMMAND(do_h)
|
|
{
|
|
int i;
|
|
char args[50];
|
|
|
|
UNUSED(str);
|
|
UNUSED(com);
|
|
UNUSED(cs);
|
|
UNUSED(ip);
|
|
UNUSED(stop);
|
|
UNUSED(len);
|
|
|
|
if (chewy) printf("Master Yoda's commands are:\n\n");
|
|
|
|
for(i = 0; i < sizeoftable(yoda_command); ) {
|
|
args[0] = 0;
|
|
if (yoda_command[i].decode_iaddr)
|
|
strcpy (args, "<intel-addr> ");
|
|
strcat (args, yoda_command[i].args ? yoda_command[i].args : "");
|
|
printf("%14s %-20s - %s\n", yoda_command[i].name, args,
|
|
yoda_command[i].comment?yoda_command[i].comment:"");
|
|
if (++i%20 == 0)
|
|
if (!yoda_confirm("-- continue? -- ")) return(YODA_LOOP);
|
|
}
|
|
|
|
host_yoda_help_extensions();
|
|
|
|
printf("\nAll data input is treated as hex\n");
|
|
printf(" <type> is the type of breakpoint : 1 - stop at, 0 - trace only.\n");
|
|
printf(" <reg> is the symbol for a 16 bit register ie: ax, sp, etc ...\n");
|
|
printf(" <intel-addr> examples: ffe, f000:45, ds:BX, si+8, BX+DI+1, es:[SI-2], etc ...\n\t& all combinations thereof.\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
|
|
#ifdef PCLABS_STATS
|
|
int stats_counter;
|
|
#endif
|
|
|
|
/*
|
|
* Convert string to lowercase in-situ. We assume that tolower() doesn't
|
|
* corrupt non-upper case characters (which is assumed elsewhere in the
|
|
* base code.
|
|
*/
|
|
LOCAL void string_tolower IFN1 (char *, s)
|
|
{
|
|
while (*s) {
|
|
*s = host_tolower(*s);
|
|
s++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Decode the offset portion of an Intel address expression.
|
|
*/
|
|
LOCAL IBOOL decode_offset IFN3(char *, coffset, IU32 *, offset, IS32 *, seg)
|
|
{
|
|
int n;
|
|
IS32 const_offset; /* constant hex offset */
|
|
IS32 ireg_offset; /* value of index reg offset */
|
|
unsigned long iaddr16b;
|
|
char sign, junk, morejunk;
|
|
char cbase[50], ireg[2], *pbase = coffset;
|
|
IBOOL retVal = FALSE;
|
|
SAVED IBOOL cold = TRUE;
|
|
|
|
/*
|
|
* Data required to decode segment offset register names and
|
|
* get default segment value.
|
|
*/
|
|
static struct DECODE_SEGOFFSET {
|
|
char *reg_name;
|
|
word (*get_offset_val) IPT0();
|
|
word (*get_segreg_val) IPT0();
|
|
}
|
|
decode_segoffset[] =
|
|
{
|
|
{"bx", NULL, NULL},
|
|
{"si", NULL, NULL},
|
|
{"di", NULL, NULL},
|
|
{"sp", NULL, NULL},
|
|
{"bp", NULL, NULL},
|
|
{"ip", NULL, NULL}
|
|
};
|
|
|
|
#ifdef SPC386
|
|
/*
|
|
* Note that there have to be the same number of extended
|
|
* register decodes as standard register decodes, or the search
|
|
* function will break!
|
|
*/
|
|
|
|
static struct DECODE_SEGOFFSET2 {
|
|
char *reg_name;
|
|
IU32 (*get_offset_val) IPT0();
|
|
word (*get_segreg_val) IPT0();
|
|
}
|
|
decode_segoffset2[] =
|
|
{
|
|
{"ebx", NULL, NULL},
|
|
{"esi", NULL, NULL},
|
|
{"edi", NULL, NULL},
|
|
{"esp", NULL, NULL},
|
|
{"ebp", NULL, NULL},
|
|
{"eip", NULL, NULL}
|
|
};
|
|
#endif /* SPC386 */
|
|
|
|
if( cold )
|
|
{
|
|
#ifdef CCPU
|
|
decode_segoffset[0].get_offset_val = c_getBX;
|
|
decode_segoffset[0].get_segreg_val = c_getDS;
|
|
decode_segoffset[1].get_offset_val = c_getSI;
|
|
decode_segoffset[1].get_segreg_val = c_getDS;
|
|
decode_segoffset[2].get_offset_val = c_getDI;
|
|
decode_segoffset[2].get_segreg_val = c_getDS;
|
|
decode_segoffset[3].get_offset_val = c_getSP;
|
|
decode_segoffset[3].get_segreg_val = c_getSS;
|
|
decode_segoffset[4].get_offset_val = c_getBP;
|
|
decode_segoffset[4].get_segreg_val = c_getSS;
|
|
decode_segoffset[5].get_offset_val = c_getIP;
|
|
decode_segoffset[5].get_segreg_val = c_getCS;
|
|
#ifdef SPC386
|
|
decode_segoffset2[0].get_offset_val = c_getEBX;
|
|
decode_segoffset2[0].get_segreg_val = c_getDS;
|
|
decode_segoffset2[1].get_offset_val = c_getESI;
|
|
decode_segoffset2[1].get_segreg_val = c_getDS;
|
|
decode_segoffset2[2].get_offset_val = c_getEDI;
|
|
decode_segoffset2[2].get_segreg_val = c_getDS;
|
|
decode_segoffset2[3].get_offset_val = c_getESP;
|
|
decode_segoffset2[3].get_segreg_val = c_getSS;
|
|
decode_segoffset2[4].get_offset_val = c_getEBP;
|
|
decode_segoffset2[4].get_segreg_val = c_getSS;
|
|
decode_segoffset2[5].get_offset_val = c_getEIP;
|
|
decode_segoffset2[5].get_segreg_val = c_getCS;
|
|
#endif /* SPC386 */
|
|
#else /* !CCPU */
|
|
#ifdef CPU_40_STYLE
|
|
decode_segoffset[0].get_offset_val = Cpu.GetBX;
|
|
decode_segoffset[0].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset[1].get_offset_val = Cpu.GetSI;
|
|
decode_segoffset[1].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset[2].get_offset_val = Cpu.GetDI;
|
|
decode_segoffset[2].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset[3].get_offset_val = Cpu.GetSP;
|
|
decode_segoffset[3].get_segreg_val = Cpu.GetSS;
|
|
decode_segoffset[4].get_offset_val = Cpu.GetBP;
|
|
decode_segoffset[4].get_segreg_val = Cpu.GetSS;
|
|
decode_segoffset[5].get_offset_val = Cpu.GetIP;
|
|
decode_segoffset[5].get_segreg_val = Cpu.GetCS;
|
|
decode_segoffset2[0].get_offset_val = Cpu.GetEBX;
|
|
decode_segoffset2[0].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset2[1].get_offset_val = Cpu.GetESI;
|
|
decode_segoffset2[1].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset2[2].get_offset_val = Cpu.GetEDI;
|
|
decode_segoffset2[2].get_segreg_val = Cpu.GetDS;
|
|
decode_segoffset2[3].get_offset_val = Cpu.GetESP;
|
|
decode_segoffset2[3].get_segreg_val = Cpu.GetSS;
|
|
decode_segoffset2[4].get_offset_val = Cpu.GetEBP;
|
|
decode_segoffset2[4].get_segreg_val = Cpu.GetSS;
|
|
decode_segoffset2[5].get_offset_val = Cpu.GetEIP;
|
|
decode_segoffset2[5].get_segreg_val = Cpu.GetCS;
|
|
#else /* !CPU_40_STYLE */
|
|
decode_segoffset[0].get_offset_val = getBX;
|
|
decode_segoffset[0].get_segreg_val = getDS;
|
|
decode_segoffset[1].get_offset_val = getSI;
|
|
decode_segoffset[1].get_segreg_val = getDS;
|
|
decode_segoffset[2].get_offset_val = getDI;
|
|
decode_segoffset[2].get_segreg_val = getDS;
|
|
decode_segoffset[3].get_offset_val = getSP;
|
|
decode_segoffset[3].get_segreg_val = getSS;
|
|
decode_segoffset[4].get_offset_val = getBP;
|
|
decode_segoffset[4].get_segreg_val = getSS;
|
|
decode_segoffset[5].get_offset_val = getIP;
|
|
decode_segoffset[5].get_segreg_val = getCS;
|
|
#ifdef SPC386
|
|
decode_segoffset2[0].get_offset_val = getEBX;
|
|
decode_segoffset2[0].get_segreg_val = getDS;
|
|
decode_segoffset2[1].get_offset_val = getESI;
|
|
decode_segoffset2[1].get_segreg_val = getDS;
|
|
decode_segoffset2[2].get_offset_val = getEDI;
|
|
decode_segoffset2[2].get_segreg_val = getDS;
|
|
decode_segoffset2[3].get_offset_val = getESP;
|
|
decode_segoffset2[3].get_segreg_val = getSS;
|
|
decode_segoffset2[4].get_offset_val = getEBP;
|
|
decode_segoffset2[4].get_segreg_val = getSS;
|
|
decode_segoffset2[5].get_offset_val = getEIP;
|
|
decode_segoffset2[5].get_segreg_val = getCS;
|
|
#endif /* SPC386 */
|
|
#endif /* !CPU_40_STYLE */
|
|
#endif /* !CCPU */
|
|
cold = FALSE;
|
|
}
|
|
|
|
/*
|
|
* Decode character string that represents offset into segment.
|
|
* This can either be numeric address, register name, and in
|
|
* either case with optional addition/subtraction of constant
|
|
* hex number or SI/DI register. Return -1 for invalid offset.
|
|
*/
|
|
|
|
*offset = *seg = -1;
|
|
|
|
/*
|
|
* Throw away any [..] around the offset; this lets us cut/paste
|
|
* addresses from the disassember listing. Then convert to lower
|
|
* case for the same reason.
|
|
*/
|
|
if (sscanf(coffset, "[%[^]]%c%c", cbase, &junk, &morejunk) == 2)
|
|
strcpy(coffset, cbase);
|
|
|
|
string_tolower(coffset);
|
|
|
|
/*
|
|
* Determine any additional constant value or register that is
|
|
* being added/subtracted to base of offset.
|
|
*/
|
|
|
|
const_offset = ireg_offset = 0;
|
|
|
|
if (sscanf(coffset, "%[^+-]%c%lx%c", cbase, &sign,
|
|
&const_offset, &junk) == 3) {
|
|
pbase = cbase;
|
|
if (sign == '-')
|
|
const_offset = -const_offset;
|
|
|
|
} else if (((n = sscanf(coffset, "%[^+]+%c%c%c%lx%c", cbase, &ireg[0],
|
|
&ireg[1], &sign, &const_offset, &junk)) >= 3) &&
|
|
((ireg[0] == 's') || (ireg[0] == 'd')) &&
|
|
(ireg[1] == 'i')) {
|
|
/*
|
|
* We allow SI/DI to be added to any offset base. Note that
|
|
* this allows things like ip+di but theres no point in
|
|
* prohibiting naff addresses like this. We also allow things
|
|
* like bp+si+4 (yuk).
|
|
*/
|
|
if ((n == 3) || (n == 5)) {
|
|
pbase = cbase;
|
|
|
|
/*
|
|
* Get index register value ..
|
|
*/
|
|
if (ireg[0] == 'd')
|
|
ireg_offset = getDI();
|
|
if (ireg[0] == 's')
|
|
ireg_offset = getSI();
|
|
|
|
/*
|
|
* Get any additional constant if present; resetting
|
|
* pbase to coffset if the format is wrong effectively
|
|
* throws the expression out as invalid.
|
|
*/
|
|
if (n == 5) {
|
|
if (sign == '-')
|
|
const_offset = -const_offset;
|
|
else if (sign != '+')
|
|
pbase = coffset;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Decode the base of the offset.
|
|
*/
|
|
if (sscanf(pbase, "%lx%c", &iaddr16b, &junk) == 1) {
|
|
/*
|
|
* Simple numeric offset, we use DS as the default
|
|
* segment register in this case.
|
|
*/
|
|
#ifdef SPC386
|
|
*offset = iaddr16b;
|
|
#else
|
|
*offset = iaddr16b & 0xffff;
|
|
#endif
|
|
*seg = getDS();
|
|
retVal = TRUE;
|
|
|
|
} else {
|
|
/*
|
|
* Should be symbolic register name; decode it.
|
|
*/
|
|
ISM8 n;
|
|
for (n = 0; n < sizeof(decode_segoffset)/
|
|
sizeof(struct DECODE_SEGOFFSET); n++) {
|
|
if (!strcmp(pbase, decode_segoffset[n].reg_name)) {
|
|
*offset = decode_segoffset[n].get_offset_val();
|
|
*seg = decode_segoffset[n].get_segreg_val();
|
|
retVal = TRUE;
|
|
break;
|
|
}
|
|
#ifdef SPC386
|
|
if (!strcmp(pbase, decode_segoffset2[n].reg_name)) {
|
|
*offset = decode_segoffset2[n].get_offset_val();
|
|
*seg = decode_segoffset2[n].get_segreg_val();
|
|
retVal = TRUE;
|
|
break;
|
|
}
|
|
#endif /* SPC386 */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Add/subtract any constant supplied to offset, and return the
|
|
* default segment that applies to this offset.
|
|
*/
|
|
if (retVal)
|
|
#ifdef SPC386
|
|
*offset = (*offset + ireg_offset + const_offset);
|
|
#else
|
|
*offset = (*offset + ireg_offset + const_offset) & 0xffff;
|
|
#endif
|
|
|
|
return(retVal);
|
|
}
|
|
|
|
/*
|
|
* Decode a full Intel address expression.
|
|
*/
|
|
LOCAL IBOOL decode_iaddr_ok IFN3 (char *, iaddr, IS32 *, seg, LIN_ADDR *, offset)
|
|
{
|
|
char junk;
|
|
char cseg[50], coffset[50];
|
|
IU32 iaddr16b;
|
|
IS32 dummy;
|
|
SAVED IBOOL cold = TRUE;
|
|
|
|
/*
|
|
* Data required to decode segment register names.
|
|
*/
|
|
static struct DECODE_SEGREG {
|
|
char *reg_name;
|
|
word (*get_segreg_val) IPT0();
|
|
}
|
|
decode_segreg[] =
|
|
{
|
|
{"cs", NULL},
|
|
{"ds", NULL},
|
|
{"ss", NULL},
|
|
{"es", NULL}
|
|
#ifdef SPC386
|
|
,{"fs", NULL},
|
|
{"gs", NULL}
|
|
#endif /* SPC 386 */
|
|
};
|
|
|
|
if( cold )
|
|
{
|
|
#ifdef CCPU
|
|
decode_segreg[0].get_segreg_val = c_getCS;
|
|
decode_segreg[1].get_segreg_val = c_getDS;
|
|
decode_segreg[2].get_segreg_val = c_getSS;
|
|
decode_segreg[3].get_segreg_val = c_getES;
|
|
#ifdef SPC386
|
|
decode_segreg[4].get_segreg_val = c_getFS;
|
|
decode_segreg[5].get_segreg_val = c_getGS;
|
|
#endif /* SPC386 */
|
|
#else /* !CCPU */
|
|
#ifdef CPU_40_STYLE
|
|
decode_segreg[0].get_segreg_val = Cpu.GetCS;
|
|
decode_segreg[1].get_segreg_val = Cpu.GetDS;
|
|
decode_segreg[2].get_segreg_val = Cpu.GetSS;
|
|
decode_segreg[3].get_segreg_val = Cpu.GetES;
|
|
decode_segreg[4].get_segreg_val = Cpu.GetFS;
|
|
decode_segreg[5].get_segreg_val = Cpu.GetGS;
|
|
#else /* !CPU_40_STYLE */
|
|
decode_segreg[0].get_segreg_val = getCS;
|
|
decode_segreg[1].get_segreg_val = getDS;
|
|
decode_segreg[2].get_segreg_val = getSS;
|
|
decode_segreg[3].get_segreg_val = getES;
|
|
#ifdef SPC386
|
|
decode_segreg[4].get_segreg_val = getFS;
|
|
decode_segreg[5].get_segreg_val = getGS;
|
|
#endif /* SPC386 */
|
|
#endif /* !CPU_40_STYLE */
|
|
#endif /* !CCPU */
|
|
cold = FALSE;
|
|
}
|
|
|
|
/*
|
|
* Decode intel address string that has been given to command.
|
|
* If the address is not understood then return in one or both
|
|
* of the cs:ip fields.
|
|
*/
|
|
|
|
if (iaddr[0] == 0) {
|
|
|
|
/*
|
|
* Blank command line means 0:0. This is naff but is
|
|
* required to make the "da" command work as it used to which
|
|
* I can't be bothered to change at the moment. CS:IP would
|
|
* be a more sensible option.
|
|
*/
|
|
*seg = *offset = 0;
|
|
return(TRUE);
|
|
|
|
} else if (!strcmp(iaddr, ".")) {
|
|
|
|
/*
|
|
* Address of just "." means CS:IP.
|
|
*/
|
|
*seg = getCS();
|
|
*offset = GetInstructionPointer();
|
|
return(TRUE);
|
|
|
|
} else if (sscanf(iaddr, "%[^:]:%s", cseg, coffset) == 2) {
|
|
|
|
/*
|
|
* Address given in segment/offset format; decode it.
|
|
* First do the segment; either simple numeric or
|
|
* assembler name (CS, DS etc).
|
|
*/
|
|
if (sscanf(cseg, "%lx%c", &iaddr16b, &junk) == 1) {
|
|
#ifdef SPC386
|
|
*seg = iaddr16b;
|
|
#else
|
|
*seg = iaddr16b & 0xffff;
|
|
#endif
|
|
} else {
|
|
ISM8 n;
|
|
|
|
string_tolower(cseg);
|
|
for (n = 0; n < sizeof(decode_segreg)/
|
|
sizeof(struct DECODE_SEGREG); n++)
|
|
if (!strcmp(cseg, decode_segreg[n].reg_name))
|
|
*seg = decode_segreg[n].get_segreg_val();
|
|
}
|
|
|
|
/*
|
|
* Decode the offset into segment.
|
|
*/
|
|
return(decode_offset (coffset, offset, &dummy));
|
|
|
|
} else {
|
|
/*
|
|
* This is probably just an offset expressed as BX, SI-2 or
|
|
* the like, so decode it and setup the default segment.
|
|
*/
|
|
return(decode_offset (iaddr, offset, seg));
|
|
}
|
|
}
|
|
|
|
LOCAL YODA_CMD_RETURN do_force_yoda_command IFN5(char *, str, char *, com, char *, iaddr, LIN_ADDR, len, LIN_ADDR, stop)
|
|
{
|
|
int i, retvalue = YODA_HELP;
|
|
unsigned long temp1, temp2;
|
|
|
|
IS32 cs;
|
|
LIN_ADDR ip;
|
|
|
|
for (i = 0; i < sizeoftable(yoda_command); i++) {
|
|
if (strcmp(yoda_command[i].name, com) == 0) {
|
|
/*
|
|
* Decode any Intel address expected by the command.
|
|
* Different stuff done for commands that
|
|
* understand new generic address parsing.
|
|
*/
|
|
if (yoda_command[i].decode_iaddr) {
|
|
/*
|
|
* Decode Intel address ..
|
|
*/
|
|
if (!decode_iaddr_ok(iaddr, &cs, &ip)) {
|
|
printf ("Bad <intel-addr> expression\n");
|
|
return(YODA_LOOP);
|
|
}
|
|
} else {
|
|
/*
|
|
* Either doesn't want address at all or wants
|
|
* it old style; this is how it used to be
|
|
* for everyone ...
|
|
*/
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1;
|
|
temp1 = temp2 = 0;
|
|
sscanf (iaddr, "%lx:%lx", &temp1, &temp2);
|
|
cs = temp1;
|
|
ip = temp2;
|
|
}
|
|
|
|
/*
|
|
* Go do the command ...
|
|
*/
|
|
retvalue = (*yoda_command[i].function)(str,
|
|
com, cs, ip, len, stop);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(retvalue);
|
|
}
|
|
|
|
|
|
LOCAL IBOOL entry_pending = FALSE;
|
|
|
|
#ifdef CPU_40_STYLE
|
|
/* The EDL CPU prefers to be entered via an interrupt, but this
|
|
* may not always work. So if the UIF button is used twice before
|
|
* we get into yoda, the second is treated as a force.
|
|
*
|
|
* If we are running a Prod-in-a-Pig LCIF then a single button select
|
|
* does a force_yoda().
|
|
*/
|
|
|
|
GLOBAL VOID Enter_yoda IFN0()
|
|
{
|
|
#ifdef PIG
|
|
GLOBAL IHP GetSadInfo IPT1(char *, name);
|
|
|
|
/* Check to see if LCIF has been built with Pig capability */
|
|
|
|
if (!(IBOOL)GetSadInfo("PigSupported"))
|
|
{
|
|
fprintf(stderr, "*** LCIF has not been built with Pig support\n");
|
|
entry_pending = TRUE;
|
|
}
|
|
#endif /* PIG */
|
|
|
|
if (entry_pending)
|
|
{
|
|
printf("Forced entry to yoda...\n");
|
|
force_yoda();
|
|
}
|
|
else
|
|
{
|
|
entry_pending = TRUE;
|
|
cpu_interrupt(CPU_SAD_INT, 0);
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
/* Use the integrated command line reader from FmDebug.c */
|
|
|
|
GLOBAL IBOOL GetCpuCmdLine IPT4(char *, buff, int, size, FILE *, stream, char *, who);
|
|
|
|
#else /* CPU_40_STYLE && !CCPU */
|
|
|
|
GLOBAL IBOOL GetCpuCmdLine IFN4(char *, buff, int, size, FILE *, stream, char *, who)
|
|
{
|
|
char prompt[256], *p;
|
|
int i;
|
|
|
|
if (stream == stdin)
|
|
{
|
|
strcpy(prompt, who);
|
|
strcat(prompt, "> ");
|
|
fprintf(stdout, prompt);
|
|
}
|
|
fflush(stdout);
|
|
fflush(trace_file);
|
|
if (fgets(buff, size, stream) != NULL)
|
|
{
|
|
p = strchr(buff, '\n');
|
|
if (p != NULL)
|
|
*p = '\0';
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
|
|
GLOBAL IBOOL AlreadyInYoda = FALSE;
|
|
|
|
void force_yoda IFN0()
|
|
{
|
|
IS32 cs;
|
|
LIN_ADDR ip, len, stop;
|
|
long temp1, temp2; /* used in calls to scanf */
|
|
char str [84]; /* input string buffer */
|
|
char com [16]; /* command name buffer */
|
|
char iaddr[50]; /* first parameter/ intel address buffer */
|
|
char slen[20];
|
|
char junk; /* for decoding the cmd line */
|
|
int n_args;
|
|
char *prompt;
|
|
SAVED IBOOL firstTime = TRUE;
|
|
SAVED char repeat_command [sizeof(str)];/* copy of previous input string buffer */
|
|
#ifdef SFELLOW
|
|
IU32 oldEE;
|
|
#endif /* SFELLOW */
|
|
|
|
entry_pending = FALSE;
|
|
|
|
#ifdef PCLABS_STATS
|
|
return;
|
|
#endif
|
|
#ifdef GISP_SVGA
|
|
if( NoYodaThanks )
|
|
{
|
|
|
|
return;
|
|
}
|
|
#endif /* GISP_SVGA */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
|
|
EnterDebug("Yoda");
|
|
prompt = "";
|
|
|
|
#else /* CPU_40_STYLE && !CCPU */
|
|
|
|
if (AlreadyInYoda) {
|
|
printf("Recursive call to force_yoda() disallowed!\n");
|
|
return;
|
|
} else {
|
|
AlreadyInYoda = TRUE;
|
|
}
|
|
prompt = "yoda";
|
|
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
|
|
#ifdef SFELLOW
|
|
oldEE = DisableEE();
|
|
#endif /* SFELLOW */
|
|
|
|
if (firstTime) {
|
|
firstTime = FALSE;
|
|
if (host_getenv("QUIET_YODA"))
|
|
{
|
|
chewy = 0;
|
|
} else {
|
|
chewy = 1;
|
|
#if !defined(macintosh) && !defined(SFELLOW)
|
|
(void)srand(time(NULL));
|
|
#endif /* !macintosh && !SFELLOW */
|
|
#if defined(SPC386) && !defined(GISP_CPU)
|
|
printf("\nRemember, not everything is as it seems! An experienced Jedi will know\nthe difference between the physical world and the logical world at all times.\n\n");
|
|
#endif /* SPC386 & !GISP_CPU */
|
|
|
|
if (in_stream == NULL)
|
|
in_stream = stdin;
|
|
|
|
if (out_stream == NULL)
|
|
out_stream = stdout;
|
|
|
|
}
|
|
}
|
|
#ifdef A3CPU
|
|
/* The A3CPU thread generation has already happened, and if
|
|
* the YODA environment variable was not defined then you
|
|
* aren't going to be able to use the YODA_INTERRUPT system
|
|
*/
|
|
#ifndef SFELLOW
|
|
if (env_check == 0) {
|
|
env_check = (host_getenv("YODA") == NULL)? 1: 2;
|
|
if (env_check == 1) {
|
|
printf("Slow YODA not available (no breakpoint-based features)\n");
|
|
printf("If you want Slow YODA facilities, you must do\n");
|
|
printf("'setenv YODA TRUE' before starting an A3 CPU.\n");
|
|
}
|
|
}
|
|
#endif /* !SFELLOW */
|
|
#endif /* A3CPU */
|
|
|
|
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
if( !timer_blocked )
|
|
host_block_timer();
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
|
|
disable_timer = 1;
|
|
disable_bkpt = 1;
|
|
if (compare_stream)
|
|
printf("Compare line number %d.\n", ct_line_num);
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
|
|
while(1)
|
|
{
|
|
if (refresh_screen)
|
|
do_screen_refresh();
|
|
|
|
#ifdef SFELLOW
|
|
if (! GetCpuCmdLine(str, 80, stdin, prompt))
|
|
{
|
|
/* if read fails on stdin */
|
|
perror("failed to read from stdin");
|
|
continue;
|
|
}
|
|
#else /* SFELLOW */
|
|
if (! GetCpuCmdLine(str, 80, in_stream, prompt))
|
|
{
|
|
/* if read fails on file */
|
|
if (in_stream == stdin) {
|
|
perror("failed to read from stdin");
|
|
} else
|
|
{
|
|
/* close script */
|
|
fclose (in_stream);
|
|
|
|
/* return to stdin */
|
|
in_stream = stdin;
|
|
|
|
/* tell user his script has finished */
|
|
puts ("(eof)");
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* if reading a script echo the command */
|
|
if (in_stream != stdin) {
|
|
puts(str);
|
|
} else if (str[0] == '\0') {
|
|
/*
|
|
* If no command is specified then copy previous
|
|
* command (if it was repeatable)
|
|
*/
|
|
strcpy(str, repeat_command);
|
|
}
|
|
#endif /* SFELLOW */
|
|
|
|
/*
|
|
* Setup default command arguments and do initial command
|
|
* line decoding.
|
|
*/
|
|
|
|
com[0] = 0;
|
|
|
|
temp1 = 1;
|
|
len = YODA_LEN_UNSPECIFIED;
|
|
|
|
/*
|
|
* the lengths here relate to the buffer sizes of com, iaddr and slen
|
|
* [BCN 2582]
|
|
*/
|
|
n_args = sscanf (str, "%15s %49s %19s %lx", com, iaddr, slen, &temp1);
|
|
stop = temp1;
|
|
if (n_args < 2)
|
|
iaddr[0] = 0;
|
|
|
|
if (n_args >= 3) {
|
|
/*
|
|
* The <len> parameter was provided; this is supposed to
|
|
* be numeric but we accept (SR), (LR), (TR), (WI), (SI),
|
|
* (LI) and (PD) to allow NPX addresses to be cut/pasted
|
|
* directly out of the dissasembler. They equate to the
|
|
* size in bytes of the corresponding data item.
|
|
* Useful for pasting into, for example, the "db" command.
|
|
*/
|
|
string_tolower(slen);
|
|
if (sscanf(slen, "%lx%c", &temp1, &junk) == 1) {
|
|
if (temp1 == YODA_LEN_UNSPECIFIED) {
|
|
printf("That length only by a master be used may, given you 1 I have\n");
|
|
len = 1;
|
|
} else {
|
|
len = temp1;
|
|
}
|
|
} else {
|
|
if (!strcmp(slen, "(wi)"))
|
|
len = 2;
|
|
else if (!strcmp(slen, "(sr)") || !strcmp(slen, "(si)"))
|
|
len = 4;
|
|
else if (!strcmp(slen, "(lr)") || !strcmp(slen, "(li)"))
|
|
len = 8;
|
|
else if (!strcmp(slen, "(tr)") || !strcmp(slen, "(pd)"))
|
|
len = 12;
|
|
else
|
|
len = YODA_LEN_UNSPECIFIED;
|
|
}
|
|
}
|
|
|
|
repeat_command[0] = '\0'; /* Default is dont-repeat on null command */
|
|
/*
|
|
* Do the command & take action on the return code ...
|
|
*/
|
|
switch (do_force_yoda_command(str, com, iaddr, len, stop))
|
|
{
|
|
case YODA_RETURN_AND_REPEAT:
|
|
/* Remember this command, when it completes a null command will
|
|
* do this command again. I.e. "s", followed by <return> will
|
|
* do "s" twice.
|
|
*/
|
|
strcpy(repeat_command, str);
|
|
/* Fall through */
|
|
case YODA_RETURN:
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
if( !timer_blocked )
|
|
host_release_timer();
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
In_yoda = FALSE;
|
|
AlreadyInYoda = FALSE;
|
|
|
|
#ifdef SFELLOW
|
|
RestoreEE(oldEE);
|
|
#endif /* SFELLOW */
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
LeaveDebug();
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
return;
|
|
case YODA_HELP:
|
|
/*
|
|
* Following assignment & scanf is the way that all yoda
|
|
* commands used to get their arguments; the host extensions
|
|
* will still always get the old stuff. AJO 29/8/93.
|
|
*/
|
|
if (len == YODA_LEN_UNSPECIFIED)
|
|
len = 1; /* old default */
|
|
temp1 = temp2 = 0;
|
|
sscanf(iaddr, "%lx:%lx", &temp1, &temp2);
|
|
cs = temp1;
|
|
ip = temp2;
|
|
|
|
if ( (host_force_yoda_extensions(com,cs,ip,len,str)!=0)
|
|
&& (strcmp(com,"") != 0))
|
|
{
|
|
printf ("Unknown command '%s'\n", com);
|
|
if (chewy) {
|
|
printf ("Use the 'h' command if you must.\n");
|
|
printf ("Remember - a jedi's strength FLOWS through his fingers\n");
|
|
}
|
|
}
|
|
/* Fall through (we dont care!) */
|
|
case YODA_LOOP_AND_REPEAT:
|
|
/* Remember this command, when it completes a null command will
|
|
* do this command again. I.e. "u", followed by <return> will
|
|
* do "u" twice.
|
|
*/
|
|
strcpy(repeat_command, str);
|
|
/* Fall through */
|
|
case YODA_LOOP:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Should never get here.
|
|
*/
|
|
}
|
|
|
|
#ifdef PM
|
|
LOCAL dump_descr IFN2(LIN_ADDR, address, IUM32, num)
|
|
/* address of first descriptor to dump */
|
|
/* number of descriptors to dump */
|
|
{
|
|
int i;
|
|
int output_type;
|
|
char *output_name;
|
|
int p; /* Bits of descriptor */
|
|
int a; /* ... */
|
|
int dpl; /* ... */
|
|
half_word AR; /* ... */
|
|
word limit; /* ... */
|
|
word low_base; /* ... */
|
|
half_word high_base; /* ... */
|
|
word high_limit; /* ... */
|
|
sys_addr base;
|
|
int scroll;
|
|
sys_addr tlimit;
|
|
|
|
scroll = 0;
|
|
for ( i = 0; i < (num * 8); i+=8, address += 8, scroll++ )
|
|
{
|
|
if (scroll == 20) {
|
|
if (!yoda_confirm("-- more descriptors? -- "))
|
|
break;
|
|
scroll = 0;
|
|
}
|
|
AR = sas_hw_at(address+5); /* get access rights */
|
|
p = (AR & 0x80) >> 7; /* hence P(Present) */
|
|
dpl = (AR & 0x60) >> 5; /* and DPL */
|
|
AR = AR & 0x1f; /* and super type */
|
|
a = AR & 0x1; /* and A(Accessed) */
|
|
limit = sas_w_at(address); /* 1st word of descr */
|
|
low_base = sas_w_at(address+2); /* 2nd word of descr */
|
|
high_base = sas_hw_at(address+4); /* 5th byte of descr */
|
|
#ifdef SPC386
|
|
high_limit = sas_w_at(address+6); /* 4th word of descr */
|
|
#else /* SPC386 */
|
|
high_limit = 0;
|
|
#endif /* SPC386 */
|
|
|
|
output_name = segment_names[AR];
|
|
|
|
/* find output format */
|
|
switch ( (int)AR )
|
|
{
|
|
case 0x00: /* INVALID */
|
|
case 0x08:
|
|
case 0x0a:
|
|
case 0x0d:
|
|
output_type = 2;
|
|
break;
|
|
|
|
#ifdef SPC386
|
|
case 0x09:
|
|
case 0x0b:
|
|
output_type = 1;
|
|
break;
|
|
case 0x0c:
|
|
output_type = 8;
|
|
break;
|
|
case 0x0e:
|
|
case 0x0f:
|
|
output_type = 9;
|
|
break;
|
|
#else /* SPC386 */
|
|
case 0x09:
|
|
case 0x0b:
|
|
case 0x0c:
|
|
case 0x0e:
|
|
case 0x0f:
|
|
output_type = 2;
|
|
break;
|
|
#endif /* SPC386 */
|
|
|
|
case 0x01: /* SPECIAL */
|
|
case 0x02:
|
|
case 0x03:
|
|
output_type = 1;
|
|
break;
|
|
|
|
case 0x04: /* CONTROL */
|
|
output_type = 4;
|
|
break;
|
|
|
|
case 0x05: /* CONTROL */
|
|
output_type = 5;
|
|
break;
|
|
|
|
case 0x06: /* CONTROL */
|
|
case 0x07:
|
|
output_type = 3;
|
|
break;
|
|
|
|
case 0x10: /* DATA */
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x13:
|
|
case 0x14:
|
|
case 0x15:
|
|
case 0x16:
|
|
case 0x17:
|
|
output_type = 6;
|
|
break;
|
|
|
|
case 0x18: /* CODE */
|
|
case 0x19:
|
|
case 0x1a:
|
|
case 0x1b:
|
|
case 0x1c:
|
|
case 0x1d:
|
|
case 0x1e:
|
|
case 0x1f:
|
|
output_type = 7;
|
|
break;
|
|
}
|
|
|
|
switch ( output_type )
|
|
{
|
|
case 1:
|
|
if ( descr_trace & 0x02 )
|
|
#ifdef SPC386
|
|
{
|
|
base = ((high_limit & 0xff00) << 16) |
|
|
(high_base << 16 ) |
|
|
low_base;
|
|
tlimit = ((high_limit & 0xf) << 16) | limit;
|
|
if ( high_limit & 0x80 )
|
|
tlimit = tlimit << 12 | 0xfff;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s BASE:%08x LIMIT:%08x\n",
|
|
i, p, dpl, output_name, base, tlimit);
|
|
}
|
|
#else /* SPC386 */
|
|
{
|
|
base = ((sys_addr)high_base << 16 ) | low_base;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s BASE:%6x LIMIT:%4x\n",
|
|
i, p, dpl, output_name, base, limit);
|
|
}
|
|
#endif /* SPC386 */
|
|
break;
|
|
|
|
case 2:
|
|
if ( descr_trace & 0x01 )
|
|
{
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s\n",
|
|
i, p, dpl, output_name);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if ( descr_trace & 0x08 )
|
|
{
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s SELECTOR:%4x OFFSET:%4x\n",
|
|
i, p, dpl, output_name, low_base, limit);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if ( descr_trace & 0x04 )
|
|
{
|
|
high_base = high_base & 0x1f;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s SELECTOR:%4x OFFSET:%4x WD:%2x\n",
|
|
i, p, dpl, output_name, low_base, limit, high_base);
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if ( descr_trace & 0x08 )
|
|
{
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s TSS SELECTOR:%4x\n",
|
|
i, p, dpl, output_name, low_base);
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
if ( descr_trace & 0x10 )
|
|
{
|
|
base = ((high_limit & 0xff00) << 16) |
|
|
(high_base << 16 ) |
|
|
low_base;
|
|
tlimit = ((high_limit & 0xf) << 16) | limit;
|
|
if ( high_limit & 0x80 )
|
|
tlimit = tlimit << 12 | 0xfff;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d %s TYPE:%25s BASE:%08x LIMIT:%08x A:%1d\n",
|
|
i, p, dpl, (high_limit & 0x40) ? "Big": " ", output_name, base, tlimit, a);
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
if ( descr_trace & 0x20 )
|
|
{
|
|
base = ((high_limit & 0xff00) << 16) |
|
|
(high_base << 16 ) |
|
|
low_base;
|
|
tlimit = ((high_limit & 0xf) << 16) | limit;
|
|
if ( high_limit & 0x80 )
|
|
tlimit = tlimit << 12 | 0xfff;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d %s TYPE:%25s BASE:%08x LIMIT:%08x A:%1d\n",
|
|
i, p, dpl, (high_limit & 0x40) ? "Big": " ", output_name, base, tlimit, a);
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
if ( descr_trace & 0x04 )
|
|
{
|
|
high_base = high_base & 0xf;
|
|
tlimit = (high_limit << 16) | limit;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s SELECTOR:%04x OFFSET:%08x DW:%2x\n",
|
|
i, p, dpl, output_name, low_base, tlimit, high_base);
|
|
}
|
|
break;
|
|
|
|
case 9:
|
|
if ( descr_trace & 0x08 )
|
|
{
|
|
tlimit = (high_limit << 16) | limit;
|
|
fprintf(trace_file, "(%04x)P:%1d DPL:%1d TYPE:%25s SELECTOR:%04x OFFSET:%08x\n",
|
|
i, p, dpl, output_name, low_base, tlimit);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* PM */
|
|
|
|
/*
|
|
Dump Readable String.
|
|
*/
|
|
dump_string IFN4(IU16, selector, LIN_ADDR, offset, LIN_ADDR, len, long, mode)
|
|
|
|
#ifdef DOCUMENTATION
|
|
long selector; /* Selector:Offset to start address for dump */
|
|
long offset; /* " */
|
|
long len; /* Nr. bytes to dump */
|
|
long mode; /* =1 Simple byte string dump */
|
|
/* =2 Dump every other byte starting with first */
|
|
/* =3 Dump every other byte starting with second */
|
|
#endif /* DOCUMENTATION */
|
|
|
|
{
|
|
int i;
|
|
int pc = 0;
|
|
half_word value;
|
|
LIN_ADDR addr;
|
|
|
|
addr = eff_addr(selector, offset);
|
|
|
|
for ( i = 0; i < len; i++ )
|
|
{
|
|
/* Get next byte to be shown */
|
|
switch ( mode )
|
|
{
|
|
case 1:
|
|
value = sas_hw_at(addr+i);
|
|
break;
|
|
|
|
case 2:
|
|
value = sas_hw_at(addr+i);
|
|
i++;
|
|
break;
|
|
|
|
case 3:
|
|
i++;
|
|
value = sas_hw_at(addr+i);
|
|
break;
|
|
}
|
|
|
|
/* Filter out the unprintable */
|
|
if ( iscntrl(value) )
|
|
value = '.';
|
|
|
|
/* Print it */
|
|
fprintf(trace_file, "%c", value);
|
|
/* With a line feed every eighty characters */
|
|
if ( ++pc == 80 )
|
|
{
|
|
fprintf(trace_file, "\n");
|
|
pc = 0;
|
|
}
|
|
}
|
|
|
|
/* Print final line feed if needed */
|
|
if ( pc )
|
|
fprintf(trace_file, "\n");
|
|
}
|
|
|
|
|
|
/* Do pretty printing for page table entry */
|
|
LOCAL void dump_page_table_entries IFN3(int, first_index, int, last_index, IU32, entry)
|
|
{
|
|
if (first_index == last_index)
|
|
fprintf(trace_file, "%03x %08x ", first_index, entry);
|
|
else
|
|
fprintf(trace_file, "%03x..%03x %08x ", first_index, last_index, entry);
|
|
|
|
if ( entry & 1 )
|
|
{
|
|
/* Present */
|
|
fprintf(trace_file, "%08x %c %c %c %c.\n",
|
|
entry & 0xfffff000,
|
|
(entry & 0x40) ? 'D' : ' ',
|
|
(entry & 0x20) ? 'A' : ' ',
|
|
(entry & 0x04) ? 'U' : 'S',
|
|
(entry & 0x02) ? 'W' : 'R');
|
|
}
|
|
#ifndef CCPU
|
|
else if ((((entry >> 9) & 7) == 6) && Sas.IsPageInstanceData(entry))
|
|
{
|
|
/* Not Present, but Windows instance data */
|
|
fprintf(trace_file, "Not Present, Instance data\n");
|
|
}
|
|
#endif /* CCPU */
|
|
else
|
|
{
|
|
/* Not Present */
|
|
fprintf(trace_file, "Not Present.\n");
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void dump_page_table IFN2(
|
|
IS32, cs, /* Physical address to dump table from */
|
|
IS32, len /* Entry Number (0-3ff) to dump, else dump all */
|
|
)
|
|
{
|
|
#ifdef CPU_40_STYLE
|
|
PHY_ADDR addr;
|
|
int start, end;
|
|
int i;
|
|
IU32 entry;
|
|
|
|
/* Special case tell them Page Directory Base Register contents */
|
|
if ( cs == 0 )
|
|
{
|
|
fprintf(trace_file,
|
|
"Page Directory Base Register = %08x.\n", getCR3());
|
|
return;
|
|
}
|
|
|
|
if ( len < 0 || len > 1023 )
|
|
{
|
|
/* dump whole table */
|
|
start = 0;
|
|
end = 1024;
|
|
addr = (PHY_ADDR)cs;
|
|
}
|
|
else
|
|
{
|
|
/* dump just one entry */
|
|
start = len;
|
|
end = len + 1;
|
|
addr = (PHY_ADDR)(cs + (start * 4));
|
|
}
|
|
|
|
disable_bkpt = 1;
|
|
|
|
i = start;
|
|
while (i < end)
|
|
{
|
|
IU32 next_entry;
|
|
PHY_ADDR next_addr;
|
|
IU32 next_i;
|
|
|
|
/* Get next Page Table Entry */
|
|
entry = sas_PR32(addr);
|
|
next_addr = addr+4;
|
|
for (next_i = i+1; next_i < end;)
|
|
{
|
|
next_entry = sas_PR32(next_addr);
|
|
if (next_entry != entry)
|
|
break;
|
|
next_addr += 4;
|
|
next_i++;
|
|
}
|
|
if (next_i < end)
|
|
{
|
|
/* We exited early, entry at next_i is different */
|
|
dump_page_table_entries(i, next_i - 1, entry);
|
|
i = next_i;
|
|
addr = next_addr;
|
|
}
|
|
else
|
|
{
|
|
dump_page_table_entries(i, end - 1, entry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
disable_bkpt = 0;
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
LOCAL void show_phys_addr IFN1(LIN_ADDR, lin)
|
|
{
|
|
IU32 dir, tbl;
|
|
PHY_ADDR addr, pde, pte;
|
|
/* Split linear address (lin) into DIR, TBL and OFFSET components */
|
|
|
|
dir = (lin >> 22) & 0x3ff;
|
|
tbl = (lin >> 12) & 0x3ff;
|
|
fprintf(trace_file,
|
|
"LinearAddress %08x => Directory %03x Table %03x Offset %03x.\n",
|
|
lin,
|
|
dir,
|
|
tbl,
|
|
lin & 0xfff);
|
|
#ifdef CPU_40_STYLE
|
|
addr = (getCR3() & ~0x3ff) + (dir * 4);
|
|
disable_bkpt = 1;
|
|
pde = sas_PR32(addr);
|
|
disable_bkpt = 0;
|
|
fprintf(trace_file, " Directory entry @ %08p ", addr);
|
|
dump_page_table_entries(dir, dir, pde);
|
|
if (pde & 1)
|
|
{
|
|
addr = (pde & ~0xfff) + (tbl * 4);
|
|
disable_bkpt = 1;
|
|
pte = sas_PR32(addr);
|
|
disable_bkpt = 0;
|
|
fprintf(trace_file, " Table entry @ %08p ", addr);
|
|
dump_page_table_entries(tbl, tbl, pte);
|
|
if (pte & 1)
|
|
{
|
|
fprintf(trace_file, " Final Physical Address %08x\n", (pte & ~0xfff) + (lin & 0xfff));
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
LOCAL void guess_lin_phys IFN1(PHY_ADDR, phys)
|
|
{
|
|
IU32 dir, tbl, pdbr;
|
|
PHY_ADDR addr, pde, pte;
|
|
int nPrinted = 0;
|
|
/* Guess linear address(es) from given phys address */
|
|
|
|
fprintf(trace_file,
|
|
"Phys addr @ %08x could be linear address(es)\n",
|
|
phys);
|
|
#ifdef CPU_40_STYLE
|
|
pdbr = getCR3() & ~0xFFF;
|
|
for (dir = 0; dir <= 0x3ff; dir++)
|
|
{
|
|
addr = pdbr + (dir * 4);
|
|
|
|
disable_bkpt = 1;
|
|
pde = sas_PR32(addr);
|
|
disable_bkpt = 0;
|
|
if (pde & 1)
|
|
{
|
|
for (tbl = 0; tbl <= 0x3ff; tbl++)
|
|
{
|
|
addr = (pde & ~0xfff) + (tbl * 4);
|
|
disable_bkpt = 1;
|
|
pte = sas_PR32(addr);
|
|
disable_bkpt = 0;
|
|
if ((pte & 1) && ((pte ^ phys) <= 0xfff))
|
|
{
|
|
fprintf(trace_file, "%08x ",
|
|
(dir << 22) + (tbl << 12) + (phys & 0xFFF));
|
|
if (nPrinted++ == 8)
|
|
{
|
|
fprintf(trace_file, "\n");
|
|
nPrinted = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (nPrinted)
|
|
{
|
|
fprintf(trace_file, "\n");
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
LOCAL void guess_lin_pte IFN1(PHY_ADDR, pte_addr)
|
|
{
|
|
IU32 dir, tbl, pdbr;
|
|
PHY_ADDR addr, pde, pte;
|
|
int nPrinted = 0;
|
|
/* Guess linear address(es) from given PTE address */
|
|
|
|
fprintf(trace_file,
|
|
"PTE @ %08x could be defining linear address(es)\n",
|
|
pte_addr);
|
|
#ifdef CPU_40_STYLE
|
|
pdbr = getCR3() & ~0xFFF;
|
|
for (dir = 0; dir <= 0x3ff; dir++)
|
|
{
|
|
addr = pdbr + (dir * 4);
|
|
|
|
disable_bkpt = 1;
|
|
pde = sas_PR32(addr);
|
|
disable_bkpt = 0;
|
|
if ((pde & 1) && ((pde ^ pte_addr) <= 0xfff))
|
|
{
|
|
fprintf(trace_file, "%05x000 ", (dir << 10) + ((pte_addr & 0xFFF) >> 2));
|
|
if (nPrinted++ == 8)
|
|
{
|
|
fprintf(trace_file, "\n");
|
|
nPrinted = 0;
|
|
}
|
|
}
|
|
}
|
|
if (nPrinted)
|
|
{
|
|
fprintf(trace_file, "\n");
|
|
}
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
LOCAL void dump_phys_bytes IFN2(IS32, cs, IS32, len)
|
|
{
|
|
#ifdef CPU_40_STYLE
|
|
int i, j, x, y;
|
|
|
|
if (len < 0)
|
|
len = 1;
|
|
|
|
x = len % 16;
|
|
y = len / 16;
|
|
|
|
for (i=0;i<y;i++)
|
|
{
|
|
fprintf(trace_file,"%08lx:", cs);
|
|
for (j=0;j<16;j++)
|
|
{
|
|
fprintf(trace_file," %02x", sas_PR8((PHY_ADDR)(cs + j)));
|
|
}
|
|
fprintf(trace_file,"\n");
|
|
cs += 16;
|
|
}
|
|
|
|
if(x != 0)
|
|
fprintf(trace_file,"%08lx:", cs);
|
|
|
|
for (j=0;j<x;j++)
|
|
{
|
|
fprintf(trace_file," %02x", sas_PR8((PHY_ADDR)(cs + j)));
|
|
}
|
|
fprintf(trace_file,"\n");
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
|
|
LOCAL void dump_bytes IFN3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len)
|
|
{
|
|
half_word val[MAX_TABLE];
|
|
int i, j, k, x, y;
|
|
if ((len == 0) || (len == YODA_LEN_UNSPECIFIED))
|
|
return;
|
|
if(len > MAX_TABLE)
|
|
len = MAX_TABLE;
|
|
disable_bkpt = 1;
|
|
sas_loads(eff_addr(cs,ip), val, len);
|
|
disable_bkpt = 0;
|
|
x = len % 16;
|
|
y = len / 16;
|
|
k = 0;
|
|
for (i=0;i<y;i++) {
|
|
fprintf(trace_file,"%04lx:%04lx", cs, ip);
|
|
for (j=0;j<16;j++)
|
|
fprintf(trace_file," %02x", val[k++]);
|
|
fprintf(trace_file,"\n");
|
|
ip += 16;
|
|
}
|
|
if(x != 0)
|
|
fprintf(trace_file,"%04lx:%04lx", cs, ip);
|
|
for (i=0;i<x;i++)
|
|
fprintf(trace_file," %02x", val[k++]);
|
|
fprintf(trace_file,"\n");
|
|
}
|
|
|
|
LOCAL void dump_words IFN3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len)
|
|
{
|
|
int i;
|
|
word val;
|
|
|
|
disable_bkpt = 1;
|
|
for (i=0;i<len;i++) {
|
|
if (i%8 == 0) fprintf(trace_file,"%04lx:%04lx", cs, ip);
|
|
val = sas_w_at(eff_addr(cs,ip));
|
|
ip += 2;
|
|
fprintf(trace_file," %04x", val);
|
|
if (i%8 == 7) fprintf(trace_file,"\n");
|
|
}
|
|
if (i%8 != 7) fprintf(trace_file,"\n");
|
|
disable_bkpt = 0;
|
|
}
|
|
|
|
LOCAL void dump_dwords IFN3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len)
|
|
{
|
|
int i;
|
|
IU32 val;
|
|
|
|
disable_bkpt = 1;
|
|
for (i=0;i<len;i++) {
|
|
if (i%8 == 0) fprintf(trace_file,"%04lx:%04lx", cs, ip);
|
|
val = sas_dw_at(eff_addr(cs,ip));
|
|
ip += 4;
|
|
fprintf(trace_file," %08x", val);
|
|
if (i%8 == 7) fprintf(trace_file,"\n");
|
|
}
|
|
if (i%8 != 7) fprintf(trace_file,"\n");
|
|
disable_bkpt = 0;
|
|
}
|
|
|
|
LOCAL void init_br_regentry IFN3(BR_REG, regst, char *, str, SIZE_SPECIFIER, size)
|
|
{
|
|
br_regdescs[regst].regnum = regst;
|
|
strcpy(br_regdescs[regst].regname, str);
|
|
br_regdescs[regst].size = size;
|
|
}
|
|
|
|
LOCAL void init_br_structs IFN0()
|
|
{
|
|
int loop;
|
|
|
|
init_br_regentry(br_regAX,"AX",SIXTEEN_BIT);
|
|
init_br_regentry(br_regBX,"BX",SIXTEEN_BIT);
|
|
init_br_regentry(br_regCX,"CX",SIXTEEN_BIT);
|
|
init_br_regentry(br_regDX,"DX",SIXTEEN_BIT);
|
|
init_br_regentry(br_regCS,"CS",SIXTEEN_BIT);
|
|
init_br_regentry(br_regDS,"DS",SIXTEEN_BIT);
|
|
init_br_regentry(br_regES,"ES",SIXTEEN_BIT);
|
|
init_br_regentry(br_regSS,"SS",SIXTEEN_BIT);
|
|
init_br_regentry(br_regSI,"SI",SIXTEEN_BIT);
|
|
init_br_regentry(br_regDI,"DI",SIXTEEN_BIT);
|
|
init_br_regentry(br_regSP,"SP",SIXTEEN_BIT);
|
|
init_br_regentry(br_regBP,"BP",SIXTEEN_BIT);
|
|
#ifdef SPC386
|
|
init_br_regentry(br_regEAX,"EAX",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regEBX,"EBX",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regECX,"ECX",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regEDX,"EDX",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regFS,"FS",SIXTEEN_BIT);
|
|
init_br_regentry(br_regGS,"GS",SIXTEEN_BIT);
|
|
init_br_regentry(br_regESI,"ESI",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regEDI,"EDI",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regESP,"ESP",THIRTY_TWO_BIT);
|
|
init_br_regentry(br_regEBP,"EBP",THIRTY_TWO_BIT);
|
|
#endif
|
|
init_br_regentry(br_regAH,"AH",EIGHT_BIT);
|
|
init_br_regentry(br_regBH,"BH",EIGHT_BIT);
|
|
init_br_regentry(br_regCH,"CH",EIGHT_BIT);
|
|
init_br_regentry(br_regDH,"DH",EIGHT_BIT);
|
|
init_br_regentry(br_regAL,"AL",EIGHT_BIT);
|
|
init_br_regentry(br_regBL,"BL",EIGHT_BIT);
|
|
init_br_regentry(br_regCL,"CL",EIGHT_BIT);
|
|
init_br_regentry(br_regDL,"DL",EIGHT_BIT);
|
|
|
|
free_br_regs = &br_regs[0];
|
|
head_br_regs = NULL;
|
|
|
|
for (loop=0;loop<(NUM_BR_ENTRIES-1);loop++)
|
|
{
|
|
br_regs[loop].next = &br_regs[loop+1];
|
|
br_regs[loop].handle = loop;
|
|
}
|
|
br_regs[NUM_BR_ENTRIES-1].next = NULL;
|
|
br_structs_initted = TRUE;
|
|
}
|
|
|
|
LOCAL void set_reg_break IFN3(char*, regstr, IU32,minv, IU32,maxv)
|
|
{
|
|
BOOL found;
|
|
BR_REGENTRY *brp;
|
|
USHORT regn;
|
|
|
|
if (!br_structs_initted)
|
|
init_br_structs();
|
|
|
|
if (free_br_regs == NULL)
|
|
{
|
|
printf("We have run out of register breakpoint entries, try deleting some.\n");
|
|
return;
|
|
}
|
|
|
|
found = FALSE;
|
|
regn = 0;
|
|
while (!found && (regn <= br_regDL))
|
|
{
|
|
if (strcmp(br_regdescs[regn].regname,regstr) == 0)
|
|
found = TRUE;
|
|
else
|
|
regn++;
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
printf("unknown register '%s'\n",regstr);
|
|
return;
|
|
}
|
|
|
|
brp = free_br_regs;
|
|
free_br_regs = free_br_regs->next;
|
|
|
|
brp->next = head_br_regs;
|
|
head_br_regs = brp;
|
|
|
|
switch(br_regdescs[regn].size) {
|
|
case EIGHT_BIT :
|
|
brp->minval = minv & 0xff;
|
|
brp->maxval = maxv & 0xff;
|
|
break;
|
|
|
|
case SIXTEEN_BIT :
|
|
brp->minval = minv & 0xffff;
|
|
brp->maxval = maxv & 0xffff;
|
|
break;
|
|
|
|
case THIRTY_TWO_BIT :
|
|
brp->minval = minv & 0xff;
|
|
brp->maxval = maxv & 0xff;
|
|
break;
|
|
}
|
|
|
|
|
|
brp->regnum = br_regdescs[regn].regnum;
|
|
}
|
|
|
|
LOCAL void clear_reg_break IFN1(char *, regstr)
|
|
{
|
|
BOOL found;
|
|
BR_REGENTRY *brp, *last_brp;
|
|
BR_REG regn;
|
|
USHORT dhandle;
|
|
|
|
if (strcmp(regstr,"all")==0)
|
|
{
|
|
init_br_structs();
|
|
return;
|
|
}
|
|
|
|
dhandle = atoi(regstr);
|
|
|
|
if (!br_structs_initted || (head_br_regs == NULL))
|
|
{
|
|
printf("no reg breakpoints to clear\n");
|
|
init_br_structs();
|
|
return;
|
|
}
|
|
|
|
found = FALSE;
|
|
regn = 0;
|
|
while (!found && (regn <= br_regDL))
|
|
{
|
|
if (strcmp(br_regdescs[regn].regname,regstr) == 0)
|
|
found = TRUE;
|
|
else
|
|
regn++;
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
printf("clearing all breakpoints for register '%s'\n",regstr);
|
|
brp = head_br_regs;
|
|
last_brp = NULL;
|
|
while(brp != NULL)
|
|
{
|
|
if (brp->regnum == regn)
|
|
{
|
|
if (last_brp == NULL)
|
|
head_br_regs = brp->next;
|
|
else
|
|
last_brp->next = brp->next;
|
|
brp->next = free_br_regs;
|
|
free_br_regs = brp;
|
|
}
|
|
else
|
|
{
|
|
last_brp = brp;
|
|
brp = brp->next;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
brp = head_br_regs;
|
|
last_brp = NULL;
|
|
while(!found && (brp != NULL))
|
|
{
|
|
if (brp->handle == dhandle)
|
|
found = TRUE;
|
|
else
|
|
{
|
|
last_brp = brp;
|
|
brp = brp->next;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
printf("breakpoint handle %d is not currently active\n",dhandle);
|
|
return;
|
|
}
|
|
|
|
if (last_brp == NULL)
|
|
head_br_regs = brp->next;
|
|
else
|
|
last_brp->next = brp->next;
|
|
brp->next = free_br_regs;
|
|
free_br_regs = brp;
|
|
}
|
|
}
|
|
|
|
LOCAL void print_reg_break IFN0()
|
|
{
|
|
BR_REGENTRY *brp;
|
|
|
|
if (!br_structs_initted)
|
|
{
|
|
printf("no reg breakpoints to print\n");
|
|
init_br_structs();
|
|
return;
|
|
}
|
|
|
|
brp = head_br_regs;
|
|
while(brp != NULL)
|
|
{
|
|
printf("%d: break if %s is ",brp->handle, br_regdescs[brp->regnum].regname);
|
|
|
|
if (brp->minval == brp->maxval)
|
|
{
|
|
printf("%#x\n",brp->minval);
|
|
}
|
|
else
|
|
{
|
|
printf("between %#x and %#x\n",brp->minval,brp->maxval);
|
|
}
|
|
brp = brp->next;
|
|
}
|
|
}
|
|
|
|
LOCAL BOOL check_reg_break IFN0()
|
|
{
|
|
BR_REGENTRY *brp;
|
|
USHORT val;
|
|
|
|
if (!br_structs_initted)
|
|
{
|
|
init_br_structs();
|
|
return(FALSE);
|
|
}
|
|
|
|
brp = head_br_regs;
|
|
while(brp != NULL)
|
|
{
|
|
switch(brp->regnum)
|
|
{
|
|
case br_regAX:
|
|
val = getAX();
|
|
break;
|
|
case br_regBX:
|
|
val = getBX();
|
|
break;
|
|
case br_regCX:
|
|
val = getCX();
|
|
break;
|
|
case br_regDX:
|
|
val = getDX();
|
|
break;
|
|
case br_regCS:
|
|
val = getCS();
|
|
break;
|
|
case br_regDS:
|
|
val = getDS();
|
|
break;
|
|
case br_regES:
|
|
val = getES();
|
|
break;
|
|
case br_regSS:
|
|
val = getSS();
|
|
break;
|
|
case br_regSI:
|
|
val = getSI();
|
|
break;
|
|
case br_regDI:
|
|
val = getDI();
|
|
break;
|
|
case br_regSP:
|
|
val = getSP();
|
|
break;
|
|
case br_regBP:
|
|
val = getBP();
|
|
break;
|
|
case br_regAH:
|
|
val = getAH();
|
|
break;
|
|
case br_regBH:
|
|
val = getBH();
|
|
break;
|
|
case br_regCH:
|
|
val = getCH();
|
|
break;
|
|
case br_regDH:
|
|
val = getDH();
|
|
break;
|
|
case br_regAL:
|
|
val = getAL();
|
|
break;
|
|
case br_regBL:
|
|
val = getBL();
|
|
break;
|
|
case br_regCL:
|
|
val = getCL();
|
|
break;
|
|
case br_regDL:
|
|
val = getDL();
|
|
break;
|
|
#ifdef SPC386
|
|
case br_regEAX:
|
|
val = getEAX();
|
|
break;
|
|
case br_regEBX:
|
|
val = getEBX();
|
|
break;
|
|
case br_regECX:
|
|
val = getECX();
|
|
break;
|
|
case br_regEDX:
|
|
val = getEDX();
|
|
break;
|
|
case br_regFS:
|
|
val = getFS();
|
|
break;
|
|
case br_regGS:
|
|
val = getGS();
|
|
break;
|
|
case br_regESI:
|
|
val = getESI();
|
|
break;
|
|
case br_regEDI:
|
|
val = getEDI();
|
|
break;
|
|
case br_regESP:
|
|
val = getESP();
|
|
break;
|
|
case br_regEBP:
|
|
val = getEBP();
|
|
break;
|
|
|
|
#endif /* SPC386 */
|
|
}
|
|
if ((val >= brp->minval) && (val <= brp->maxval))
|
|
{
|
|
printf("register `%s` contains %x !!\n",br_regdescs[brp->regnum].regname,val);
|
|
return(TRUE);
|
|
}
|
|
brp = brp->next;
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
LOCAL void set_inst_break IFN5(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop,long, temp)
|
|
{
|
|
BPTS *ptr, *freeslot;
|
|
unsigned int i;
|
|
|
|
/* Scan used slots for vacant slot */
|
|
for (ptr = freeslot = (BPTS *)0, i = inst_break_count; i--;)
|
|
{
|
|
if (inst[i].valid)
|
|
{
|
|
/* What if a break range encloses this trace address ? */
|
|
if (inst[i].cs == cs && inst[i].ip == ip)
|
|
return;
|
|
}
|
|
else
|
|
/* Keep a record of earliest vacant slot */
|
|
ptr = inst + i;
|
|
}
|
|
|
|
if (!ptr)
|
|
{
|
|
/* No match and no freed slot try for a new one */
|
|
if (inst_break_count >= MAX_TABLE)
|
|
{
|
|
printf("Location watch table full !!!\n");
|
|
return;
|
|
}
|
|
|
|
/* Next unused slot */
|
|
ptr = inst + inst_break_count++;
|
|
}
|
|
|
|
ptr->cs = cs;
|
|
ptr->ip = ip;
|
|
ptr->len = len;
|
|
ptr->start_addr = eff_addr(cs,ip);
|
|
ptr->end_addr = ptr->start_addr + len - 1;
|
|
ptr->stop = stop;
|
|
ptr->temp = temp;
|
|
ptr->valid = 1;
|
|
}
|
|
|
|
/* Tim did this
|
|
set_data_break_bytes IFN4(IS32, cs, LIN_ADDR, ip, LIN_ADDR, len, LIN_ADDR, stop)
|
|
{
|
|
BPTS *ptr;
|
|
if(data_bytes_break_count >= MAX_TABLE) {
|
|
printf("Location watch table full !!!\n");
|
|
return;
|
|
}
|
|
ptr = &data_bytes[data_bytes_break_count++];
|
|
ptr->cs = cs;
|
|
ptr->ip = ip;
|
|
if (len==0)
|
|
len=1;
|
|
ptr->len = len;
|
|
ptr->start_addr = eff_addr(cs,ip);
|
|
ptr->end_addr = ptr->start_addr + len - 1;
|
|
ptr->stop = stop;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
* set_opcode_break
|
|
*
|
|
* Consider the two byte opcode 0f ab. The user will have typed 0fab,
|
|
* but when we do our compare against the instruction stream, the 0f will
|
|
* come first, and hence be the LS byte. Hence we need to swap things.
|
|
* This is nothing to do with host-endianness or BACK_M!
|
|
* This code may not be the prettiest, but I think it's safe.
|
|
*/
|
|
|
|
LOCAL void set_opcode_break IFN2(IU32, opcode, IU32, stop)
|
|
{
|
|
if(opcode_break_count >= MAX_TABLE) {
|
|
printf("Opcode breakpoint watch table full !!!\n");
|
|
return;
|
|
}
|
|
if (opcode <= 0xff) {
|
|
opcode_breaks[opcode_break_count].mask = 0xff;
|
|
opcode_breaks[opcode_break_count].op = opcode;
|
|
} else if (opcode <= 0xffff) {
|
|
opcode_breaks[opcode_break_count].mask = 0xffff;
|
|
opcode_breaks[opcode_break_count].op =
|
|
((opcode & 0xff00) >> 8) +
|
|
((opcode & 0xff) << 8);
|
|
} else if (opcode <= 0xffffff) {
|
|
opcode_breaks[opcode_break_count].mask = 0xffffff;
|
|
opcode_breaks[opcode_break_count].op =
|
|
((opcode & 0xff0000) >> 16) +
|
|
((opcode & 0xff00)) +
|
|
((opcode & 0xff) << 16);
|
|
} else if (opcode <= 0xffffffff) {
|
|
opcode_breaks[opcode_break_count].mask = 0xffffffff;
|
|
opcode_breaks[opcode_break_count].op =
|
|
((opcode & 0xff000000) >> 24) +
|
|
((opcode & 0xff0000) >> 8) +
|
|
((opcode & 0xff00) << 8) +
|
|
((opcode & 0xff) << 24);
|
|
}
|
|
if (stop)
|
|
opcode_breaks[opcode_break_count].stop = 1;
|
|
else
|
|
if ((opcode_breaks[opcode_break_count].op & 0xff) == 0xcd)
|
|
opcode_breaks[opcode_break_count].stop = 2;
|
|
else
|
|
opcode_breaks[opcode_break_count].stop = 0;
|
|
opcode_break_count++;
|
|
}
|
|
|
|
/*
|
|
** called by yoda command bintx <int> <ah>
|
|
** set up interrupt number and ah value to break upon
|
|
*/
|
|
LOCAL void set_int_break IFN2(IU8, interrupt_number, IU8, ah )
|
|
{
|
|
printf( "Interrupt breakpoint: INT:%lx AH:%lx\n", interrupt_number, ah );
|
|
if(int_break_count >= MAX_TABLE) {
|
|
printf("Interrupt breakpoint watch table full !!!\n");
|
|
return;
|
|
}
|
|
int_breaks[int_break_count][0] = interrupt_number;
|
|
int_breaks[int_break_count][1] = ah;
|
|
printf( "i_b[%x] [0]=%lx [1]=%lx\n",
|
|
int_break_count, int_breaks[int_break_count][0], int_breaks[int_break_count][1] );
|
|
++int_break_count;
|
|
}
|
|
|
|
LOCAL void set_access_break IFN1(int, port)
|
|
{
|
|
if(access_break_count >= MAX_TABLE) {
|
|
printf("Access breakpoint table full !!!\n");
|
|
return;
|
|
}
|
|
access_breaks[access_break_count++] = port;
|
|
}
|
|
|
|
/*
|
|
** Break on write to specified address range
|
|
** Currently allow only one of these breaks as have to store the complete data range.
|
|
*/
|
|
LOCAL void set_host_address_break IFN3(LIN_ADDR, cs, LIN_ADDR, len, LIN_ADDR, stop)
|
|
|
|
#ifdef DOCUMENTATION
|
|
long cs; /* start address */
|
|
long len; /* length to check */
|
|
long stop; /* stop or trace when changed */
|
|
#endif /* DOCUMENTATION */
|
|
|
|
{
|
|
DATA_BPTS *ptr;
|
|
int i;
|
|
IU8 *old, *now;
|
|
|
|
if(host_address_break_count >= MAX_TABLE_BREAK_WORDS) {
|
|
printf("BREAK on HOST ADDRESS change table full !!\n" );
|
|
return;
|
|
}
|
|
if( len > MAX_BREAK_WORD_RANGE ){
|
|
printf( "Range too big. More training you require.\n" );
|
|
return;
|
|
}
|
|
ptr = &host_addresses[host_address_break_count++];
|
|
ptr->cs = cs;
|
|
ptr->ip = 0;
|
|
ptr->stop = stop;
|
|
ptr->len = len;
|
|
|
|
/*
|
|
* saves Host address and data, will look for a change after every instruction
|
|
*/
|
|
|
|
ptr->data_addr = cs;
|
|
now = (IU8 *)ptr->data_addr;
|
|
old = (IU8 *)&ptr->old_value[0];
|
|
for( i=0; i<len; i++ ){
|
|
old[ i ] = now[ i ];
|
|
}
|
|
printf( "Break on host address change set from %lx length %x\n", ptr->data_addr, ptr->len );
|
|
}
|
|
|
|
/*
|
|
** Break on write to specified address range
|
|
** Currently allow only one of these breaks as have to store the complete data range.
|
|
*/
|
|
LOCAL void set_data_break_words IFN3(LIN_ADDR, cs, LIN_ADDR, len, LIN_ADDR, stop)
|
|
|
|
#ifdef DOCUMENTATION
|
|
long cs; /* start address */
|
|
long len; /* length to check */
|
|
long stop; /* stop or trace when changed */
|
|
#endif /* DOCUMENTATION */
|
|
|
|
{
|
|
DATA_BPTS *ptr;
|
|
int i;
|
|
|
|
if(data_words_break_count >= MAX_TABLE_BREAK_WORDS) {
|
|
printf("BREAK on WORD CHANGE table full !!\n" );
|
|
return;
|
|
}
|
|
if( len > MAX_BREAK_WORD_RANGE ){
|
|
printf( "Range too big. More training you require.\n" );
|
|
return;
|
|
}
|
|
ptr = &data_words[data_words_break_count++];
|
|
ptr->stop = stop;
|
|
if (len==0)
|
|
len=1;
|
|
ptr->len = len;
|
|
|
|
/*
|
|
* saves Intel 32-bit address and data, will look for a change after every instruction
|
|
*/
|
|
|
|
ptr->data_addr = cs;
|
|
ptr->cs = cs;
|
|
for( i=0; i<len; i++ ){
|
|
ptr->old_value[i] = sas_w_at( (ptr->data_addr)+(i * 2) ) ;
|
|
}
|
|
printf( "Break on word change set from %lx length %lx\n", ptr->data_addr, ptr->len );
|
|
}
|
|
|
|
LOCAL void print_inst_break IFN0()
|
|
{
|
|
int i;
|
|
BPTS *ptr;
|
|
|
|
for (i=0;i<inst_break_count;i++) {
|
|
ptr = &inst[i];
|
|
printf("%04lx:%04lx+%04lx %lx\n", ptr->cs, ptr->ip, ptr->len,
|
|
ptr->stop);
|
|
}
|
|
}
|
|
|
|
print_data_break_bytes IFN0()
|
|
{
|
|
int i;
|
|
BPTS *ptr;
|
|
|
|
for (i=0;i<data_bytes_break_count;i++) {
|
|
ptr = &data_bytes[i];
|
|
printf("%04lx:%04lx+%04lx %lx\n", ptr->cs, ptr->ip, ptr->len,
|
|
ptr->stop);
|
|
}
|
|
}
|
|
|
|
LOCAL void print_host_address_breaks IFN0()
|
|
{
|
|
int i;
|
|
DATA_BPTS *ptr;
|
|
|
|
for (i=0;i<host_address_break_count;i++) {
|
|
int j;
|
|
IU8 *old;
|
|
|
|
ptr = &host_addresses[i];
|
|
old = (IU8 *)&ptr->old_value[0];
|
|
printf("host address change break Len=%04lx", ptr->len );
|
|
for (j = 0; j < ptr->len; j++)
|
|
{
|
|
if ((j & 0x1f) == 0)
|
|
printf("\n\t%08p:", ptr->data_addr + j);
|
|
printf(" %02x", old[ j ]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
LOCAL void print_data_break_words IFN0()
|
|
{
|
|
int i;
|
|
DATA_BPTS *ptr;
|
|
|
|
for (i=0;i<data_words_break_count;i++) {
|
|
ptr = &data_words[i];
|
|
printf("Word change break %08lx Len=%04lx\n", ptr->data_addr, ptr->len);
|
|
}
|
|
}
|
|
|
|
LOCAL void print_opcode_break IFN0()
|
|
{
|
|
int i;
|
|
|
|
printf("Note instruction streams are reversed\n");
|
|
for (i=0;i<opcode_break_count;i++)
|
|
printf("%04lx\n", opcode_breaks[i].op);
|
|
}
|
|
|
|
/*
|
|
** prints the intx break points set by the "bintx" command
|
|
*/
|
|
LOCAL void print_int_break IFN0()
|
|
{
|
|
int i;
|
|
for( i=0; i < int_break_count; i++ )
|
|
printf( "int:%lx AH:%lx\n", int_breaks[i][0], int_breaks[i][1] );
|
|
}
|
|
|
|
LOCAL void print_access_break IFN0()
|
|
{
|
|
int i;
|
|
|
|
for(i=0;i<access_break_count;i++)
|
|
printf("%04x\n", access_breaks[i]);
|
|
}
|
|
|
|
valid_for_compress IFN2(word, cs, word, ip)
|
|
{
|
|
double_word ea;
|
|
|
|
ea = ((((double_word)cs)<<4)+((double_word)ip));
|
|
if (ct_no_rom){
|
|
return ((ea < 0xF0000) || (ea >= 0x100000) );
|
|
}else{
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
#ifdef CCPU
|
|
#define GLOBAL_PigSynchCount PigSynchCount
|
|
extern IUH PigSynchCount;
|
|
#endif /* !CCPU */
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
LOCAL void ct_get_regs IFN1(IU32 *, regs)
|
|
{
|
|
/* Pseudo-hex digits 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
|
|
/* represent 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
|
|
|
/* +ve -ve */
|
|
/* already written EIP */ /* ` @ */
|
|
/* already written CS */ /* a A */
|
|
*regs++ = getDS(); /* b B */
|
|
*regs++ = getES(); /* c C */
|
|
*regs++ = getSS(); /* d D */
|
|
*regs++ = getTR_SELECTOR(); /* e E */
|
|
*regs++ = getLDT_SELECTOR(); /* f F */
|
|
*regs++ = getGDT_BASE(); /* g G */
|
|
*regs++ = getIDT_BASE(); /* h H */
|
|
*regs++ = getEAX(); /* i I */
|
|
*regs++ = getEBX(); /* j J */
|
|
*regs++ = getECX(); /* k K */
|
|
*regs++ = getEDX(); /* l L */
|
|
*regs++ = getESI(); /* m M */
|
|
*regs++ = getEDI(); /* n N */
|
|
*regs++ = getESP(); /* o O */
|
|
*regs++ = getEBP(); /* p P */
|
|
*regs++ = getCR0(); /* q R */
|
|
*regs++ = getFS(); /* r R */
|
|
*regs++ = getGS(); /* s S */
|
|
*regs++ = getCR3(); /* PDBR */ /* t T */
|
|
*regs++ = getCR2(); /* PFLA */ /* u U */
|
|
*regs++ = GLOBAL_PigSynchCount; /* w W */
|
|
*regs++ = host_q_ev_get_count();/* x X */
|
|
*regs++ = getEFLAGS() & 0xFFFFF72A;/* Y */
|
|
/* z Z */
|
|
/* { [ */
|
|
/* | \ */
|
|
/* } ] */
|
|
/* ~ ^ */
|
|
}
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
LOCAL IBOOL ct_show_reg_diffs IFN4(FILE *, f, IU32 *, good_regs, IU32 *, bad_regs, IU32 *, old_regs)
|
|
{
|
|
IBOOL problem = FALSE;
|
|
#define test4(name) \
|
|
{ \
|
|
if (*good_regs != *bad_regs) \
|
|
{ \
|
|
fprintf(f, "Register %-6s: should be %04x is %04x", name, *good_regs, *bad_regs); \
|
|
if (*bad_regs == *old_regs) \
|
|
fprintf(f, " (did not change)\n"); \
|
|
else \
|
|
fprintf(f, " (previous value was %04x)\n", *old_regs); \
|
|
problem = TRUE; \
|
|
} \
|
|
good_regs++; \
|
|
bad_regs++; \
|
|
old_regs++; \
|
|
}
|
|
#define test8(name) \
|
|
{ \
|
|
if (*good_regs != *bad_regs) \
|
|
{ \
|
|
fprintf(f, "Register %-6s: should be %08x is %08x", name, *good_regs, *bad_regs); \
|
|
if (*bad_regs == *old_regs) \
|
|
fprintf(f, " (did not change)\n"); \
|
|
else \
|
|
fprintf(f, " (previous value was %08x)\n", *old_regs); \
|
|
problem = TRUE; \
|
|
} \
|
|
good_regs++; \
|
|
bad_regs++; \
|
|
old_regs++; \
|
|
}
|
|
|
|
/* The order of the items is defined by ct_get_regs() */
|
|
test8("EIP");
|
|
test4("CS");
|
|
test4("DS");
|
|
test4("ES");
|
|
test4("SS");
|
|
test4("TR");
|
|
test4("LDT");
|
|
test8("GDT_BASE");
|
|
test8("IDT_BASE");
|
|
test8("EAX");
|
|
test8("EBX");
|
|
test8("ECX");
|
|
test8("EDX");
|
|
test8("ESI");
|
|
test8("EDI");
|
|
test8("ESP");
|
|
test8("EBP");
|
|
test8("CR0");
|
|
|
|
test4("FS");
|
|
test4("GS");
|
|
test8("PDBR");
|
|
test8("PFLA");
|
|
test8("Synchs");
|
|
test8("QevCtr");
|
|
test8("FLAGS&");
|
|
return (problem);
|
|
}
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
|
|
#define MAX_REGS ('`' - '@')
|
|
LOCAL IU32 *ct_next, *ct_last;
|
|
|
|
LOCAL void ct_initialise IFN0()
|
|
{
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
SAVED IU32 regs_a[MAX_REGS], regs_b[MAX_REGS];
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_REGS; i++)
|
|
{
|
|
regs_a[i] = regs_b[i] = 0;
|
|
}
|
|
ct_next = regs_b;
|
|
ct_last = regs_a;
|
|
ct_line_num = 0;
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
}
|
|
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
LOCAL void ct_make_line IFN3(char *, line, IU32 *, old, IU32 *, new)
|
|
{
|
|
IUH diff;
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_REGS; i++, old++, new++)
|
|
{
|
|
if (*new == *old)
|
|
continue;
|
|
if (*new > *old)
|
|
{
|
|
if (i == 0)
|
|
; /* This is the usual optimised case -- we use '\n' */
|
|
else
|
|
*line++ = '`' + i;
|
|
diff = *new - *old;
|
|
}
|
|
else
|
|
{
|
|
*line++ = '@' + i;
|
|
diff = *old - *new;
|
|
}
|
|
while (diff)
|
|
{
|
|
/* Dump line as "human" readable pseudo-hex
|
|
* -- i.e. we dont care that this is backwards
|
|
*/
|
|
*line++ = (diff & 0xf) + '0';
|
|
diff >>= 4;
|
|
}
|
|
}
|
|
*line++ = '\n';
|
|
*line = '\0';
|
|
}
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
|
|
/* This is the decryption algorithm for the gobblygook produced by the function
|
|
* above. Trust us, it will reconstruct the register set so they can be printed
|
|
* if an error occurs!
|
|
*/
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
LOCAL void ct_read_line IFN3(char *, line, IU32 *, old, IU32 *, new)
|
|
{
|
|
IUH diff;
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_REGS; i++, old++, new++)
|
|
{
|
|
IBOOL pos;
|
|
IUH val; /* MUST be unsigned */
|
|
int shift;
|
|
|
|
*new = *old;
|
|
|
|
if ((*line == '\n') || (*line == 0))
|
|
continue; /* All the rest are the same */
|
|
|
|
if ((i == 0) && ((*line - '0') <= 0xF))
|
|
{
|
|
/* A special optimisation for the most common case IP+... */
|
|
|
|
pos = TRUE;
|
|
/* Point line at the imaginary '`' which was optimised
|
|
* when the line was written.
|
|
*/
|
|
line--;
|
|
}
|
|
else if (*line == ('`' + i))
|
|
pos = TRUE;
|
|
else if (*line == ('@' + i))
|
|
pos = FALSE;
|
|
else
|
|
continue;
|
|
|
|
/* reverse the pseudo-hex "printing" */
|
|
shift = 0;
|
|
diff = *++line - '0';
|
|
while ((val = (*++line - '0')) <= 0xF)
|
|
{
|
|
shift += 4;
|
|
diff += (val << shift);
|
|
}
|
|
if (pos)
|
|
*new += diff;
|
|
else
|
|
*new -= diff;
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
|
|
int tpending = 0;
|
|
/*
|
|
* EOR
|
|
*/
|
|
/*
|
|
* Here it is, check_I, probably one of the most grotty, hacked around functions
|
|
* ever written. I've (Mike) made an attempt to speed it up a bit, by doing
|
|
* things like vastly reducing the number of accesses to sas (which can be
|
|
* VERY expensive on a 386, and checking whether a for loop needs executing
|
|
* before it starts (might save that variable initialisation!)
|
|
*
|
|
* Please think before you add anything that might slow it down...
|
|
*/
|
|
|
|
#define ACCESS8 ((opcode32 & 0xff00) >> 8)
|
|
|
|
void check_I IFN0()
|
|
{
|
|
IU32 i, j;
|
|
LIN_ADDR addr;
|
|
BPTS *ptr;
|
|
DATA_BPTS *dptr;
|
|
half_word temp_opcode;
|
|
IU16 check_I_cs;
|
|
LIN_ADDR check_I_ip;
|
|
IU32 opcode32;
|
|
IU32 current_opcode;
|
|
|
|
/*
|
|
* The guts of the automatic file compare
|
|
*/
|
|
|
|
#if defined(CPU_40_STYLE) && defined(SYNCH_TIMERS)
|
|
if (compress_stream || compare_stream)
|
|
{
|
|
char buff[(MAX_REGS*(1+8))+2];
|
|
IU32 *tmp;
|
|
|
|
ct_line_num++;
|
|
if ((ct_line_num & 0xfffff) == 0)
|
|
{
|
|
/* Say still working every 1,000,000 instructions. */
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
if (ct_line_num <= compare_skip)
|
|
{
|
|
char junk[(MAX_REGS*(1+8))+2];
|
|
|
|
/* Junk the line, we wre not there yet... */
|
|
if (fgets(junk, sizeof(junk), compare_stream) == NULL)
|
|
{
|
|
printf("End of compare file at instruction %ld.\n", ct_line_num);
|
|
fclose(compare_stream);
|
|
compare_stream = (FILE *)0;
|
|
compare_skip = 0;
|
|
force_yoda();
|
|
}
|
|
if (ct_line_num == compare_skip)
|
|
{
|
|
char junk[(MAX_REGS*(1+8))+2];
|
|
|
|
/* Now set up the last from the current state. */
|
|
ct_last[0] = GetInstructionPointer();
|
|
ct_last[1] = getCS();
|
|
ct_get_regs(&ct_last[2]);
|
|
printf("Compare skip point reached, checking enabled...\n");
|
|
}
|
|
return;
|
|
}
|
|
check_I_cs = getCS();
|
|
check_I_ip = GetInstructionPointer();
|
|
|
|
ct_next[0] = check_I_ip;
|
|
ct_next[1] = check_I_cs;
|
|
|
|
ct_get_regs(&ct_next[2]);
|
|
ct_make_line(buff, ct_last, ct_next);
|
|
|
|
if (compress_stream)
|
|
fprintf(compress_stream, "%s", buff);
|
|
if (compare_stream)
|
|
{
|
|
char from_trace[(MAX_REGS*(1+8))+2];
|
|
|
|
if (fgets(from_trace, sizeof(from_trace), compare_stream) == NULL)
|
|
{
|
|
printf("End of compare file at instruction %ld.\n", ct_line_num);
|
|
fclose(compare_stream);
|
|
compare_stream = (FILE *)0;
|
|
compare_skip = 0;
|
|
force_yoda();
|
|
}
|
|
else
|
|
if (strcmp(buff, from_trace) != 0)
|
|
{
|
|
IU32 ct_fixup[MAX_REGS];
|
|
|
|
ct_read_line(from_trace, ct_last, ct_fixup);
|
|
|
|
if (ct_show_reg_diffs(stdout, ct_fixup, ct_next, ct_last))
|
|
{
|
|
printf("\nCompress trace does not match at line %ld.\n", ct_line_num);
|
|
/* Force us to agree, else we will fail all future lines! */
|
|
ct_read_line(from_trace, ct_last, ct_next);
|
|
|
|
fflush(compress_stream);
|
|
force_yoda();
|
|
/* It is believed (honest guv) that there is sufficient
|
|
* information in ct_last[] and prev to "correct" the
|
|
* registers. I.e We can get into Win/E if it kills us!
|
|
* It is just necessary to copy ct_fixup to ct_next
|
|
* and stomp on the registers that differ!
|
|
*/
|
|
ct_make_line(from_trace, ct_last, ct_next);
|
|
}
|
|
}
|
|
|
|
}
|
|
tmp = ct_next;
|
|
ct_next = ct_last;
|
|
ct_last = tmp;
|
|
if ((ct_line_num == compare_break) || (ct_line_num == compress_break))
|
|
{
|
|
printf("\ncompare/compress instruction break encountered\n");
|
|
fflush(compress_stream);
|
|
force_yoda();
|
|
}
|
|
}
|
|
#endif /* CPU_40_STYLE && SYNCH_TIMERS */
|
|
|
|
/*
|
|
* EOR
|
|
*/
|
|
|
|
check_I_cs = getCS();
|
|
check_I_ip = GetInstructionPointer();
|
|
addr = eff_addr(check_I_cs, check_I_ip);
|
|
|
|
#ifdef PCLABS_STATS
|
|
log_stats(addr, sas_hw_at(addr), sas_hw_at(addr+1), sas_hw_at(addr+2));
|
|
return;
|
|
#endif
|
|
|
|
/* Lets get the next 4 bytes of code */
|
|
|
|
opcode32 = sas_dw_at(addr);
|
|
temp_opcode = opcode32 & 0xff;
|
|
|
|
#ifdef NPX
|
|
if (compress_npx) {
|
|
if (((temp_opcode == 0x26 || temp_opcode == 0x2e || temp_opcode == 0x36 || temp_opcode == 0x3e) &&
|
|
(ACCESS8 >= 0xd8 && ACCESS8 <= 0xdf)) || (temp_opcode >= 0xd8 && temp_opcode <= 0xdf))
|
|
{
|
|
do_compress_npx(compress_npx);
|
|
}
|
|
}
|
|
#endif /* NPX */
|
|
|
|
/*
|
|
* EOR
|
|
*/
|
|
if(inst_mix_count)
|
|
add_inst_mix();
|
|
|
|
if (back_trace_flags)
|
|
btrace(back_trace_flags);
|
|
|
|
#ifdef MUST_BLOCK_TIMERS
|
|
if (timer_blocked)
|
|
{
|
|
host_graphics_tick();
|
|
}
|
|
#endif /* MUST_BLOCK_TIMERS */
|
|
|
|
if (head_br_regs != NULL)
|
|
{
|
|
if (check_reg_break())
|
|
vader = 1;
|
|
}
|
|
|
|
host_yoda_check_I_extensions();
|
|
|
|
if (vader)
|
|
{
|
|
force_yoda();
|
|
vader = 0;
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
|
|
if ((temp_opcode >= 0xE4) && (temp_opcode <= 0xEF)) {
|
|
if(temp_opcode == 0xE4 || temp_opcode == 0xE5 || temp_opcode == 0xE6 || temp_opcode == 0xE7){
|
|
/* get port from next argument */
|
|
for (i=0;i<access_break_count;i++){
|
|
if((access_breaks[i] < 0x100) && (access_breaks[i] == ACCESS8)){
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if(temp_opcode == 0xEC || temp_opcode == 0xED || temp_opcode == 0xEE || temp_opcode == 0xEF){
|
|
/* get port from DX */
|
|
for (i=0;i<access_break_count;i++){
|
|
if(access_breaks[i] == getDX()){
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (int_break_count) {
|
|
/*
|
|
** Check for "bintx" breakpoints.
|
|
*/
|
|
IU8 val;
|
|
|
|
val = getAH();
|
|
for( i=0; i < int_break_count; i++ ){
|
|
if( temp_opcode == 0xCC || temp_opcode == 0xCD || temp_opcode == 0xCF ){
|
|
if((int_breaks[i][0] == sas_hw_at(addr+1)) && (int_breaks[i][1]==val)){
|
|
printf( "BINTX break\n" );
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check for "btf" breakpoint.
|
|
*/
|
|
if (tf_break_enabled && getTF()){
|
|
printf( "BTF break\n" );
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Check for "bse" breakpoint.
|
|
*/
|
|
if (bse_seg != -1 && last_seg != bse_seg && check_I_cs == bse_seg){
|
|
printf( "Break on entry to segment 0x%04x.\n", bse_seg);
|
|
force_yoda();
|
|
last_seg = check_I_cs;
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
last_seg = check_I_cs;
|
|
|
|
/*
|
|
** Check for NPX opcode break/tracepoints
|
|
*/
|
|
if (bNPX && (
|
|
(
|
|
(temp_opcode == 0x26 ||
|
|
temp_opcode == 0x2e ||
|
|
temp_opcode == 0x36 ||
|
|
temp_opcode == 0x3e) &&
|
|
(ACCESS8 >= 0xd8 && ACCESS8 <= 0xdf)
|
|
) ||
|
|
(temp_opcode == 0x9b)
|
|
||
|
|
(temp_opcode >= 0xd8 && temp_opcode <= 0xdf)
|
|
)
|
|
)
|
|
{
|
|
{
|
|
if( bNPX_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (opcode_break_count) {
|
|
/*
|
|
** Check for opcode breakpoints: 8, 16, 24 or 32 bits.
|
|
*/
|
|
for (i = 0; i < opcode_break_count; i++) {
|
|
|
|
/*
|
|
** Check the current opcode against the set of requested break opcodes.
|
|
** When "b286-2" mode is ON we get a bit more selective.
|
|
** This mode breaks upon instructions that do exist on an 8088 but behave
|
|
** differently on an 80286.
|
|
** These opcodes are:
|
|
** 0x54 - push sp, pushes decremented sp
|
|
** 0xd2 and 0xd3 - shift/rotate only uses low 5 bits of shift count in CL
|
|
** 0xf6 and 0xf7 - idiv does not cause exception if quotient 80 or 8000
|
|
** Attempt to break when one of these opcodes will behave differently not just when
|
|
** they are used because there are lots and lots of shifts and rotates.
|
|
*/
|
|
|
|
if ((opcode32 & opcode_breaks[i].mask) == opcode_breaks[i].op){
|
|
current_opcode = opcode_breaks[i].op;
|
|
if( b286_2 ){
|
|
/*
|
|
** Is it a b286_2 group opcode ?
|
|
*/
|
|
switch( current_opcode ){
|
|
case 0xd2:
|
|
case 0xd3:
|
|
/* shift/rotate */
|
|
if( (getCL()) > 31 ){
|
|
/*
|
|
** either stop at yoda prompt or print out trace info
|
|
*/
|
|
if( b286_2_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
}
|
|
return;
|
|
case 0xf6: /* IDIV byte */
|
|
if( (getAL()) == 0x80 ){
|
|
if( b286_2_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
}
|
|
return;
|
|
case 0xf7: /* IDIV word */
|
|
if( (getAX()) == 0x8000 ){
|
|
if( b286_2_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
}
|
|
return;
|
|
case 0x54: /* PUSH SP */
|
|
if( b286_2_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
default:
|
|
/*
|
|
** Was not a b286-2 instruction so carry on.
|
|
*/
|
|
break;
|
|
} /* end SWITCH */
|
|
}
|
|
if( b286_1 ){
|
|
switch( current_opcode ){
|
|
case 0x60 : /* push all */
|
|
case 0x61 : /* pop all */
|
|
case 0x62 : /* bound */
|
|
case 0x63 : /* arpl */
|
|
case 0x64 : /* illegal */
|
|
case 0x65 : /* illegal */
|
|
case 0x66 : /* illegal */
|
|
case 0x67 : /* illegal */
|
|
case 0x68 : /* push imm w */
|
|
case 0x69 : /* imul imm w */
|
|
case 0x6a : /* push imm b */
|
|
case 0x6b : /* imul imm b */
|
|
case 0x6c : /* ins b */
|
|
case 0x6d : /* ins w */
|
|
case 0x6e : /* outs b*/
|
|
case 0x6f : /* outs w */
|
|
case 0xc0 : /* shift imm b */
|
|
case 0xc1 : /* shift imm w */
|
|
case 0xc8 : /* enter */
|
|
case 0xc9 : /* leave */
|
|
case 0x0f : /* protected mode prefix */
|
|
case 0xf36c : /* rep prefix for ins and outs */
|
|
case 0xf36d : /* rep prefix for ins and outs */
|
|
case 0xf36e : /* rep prefix for ins and outs */
|
|
case 0xf36f : /* rep prefix for ins and outs */
|
|
case 0x54 : /* push sp, should not really be in this section but is rarely used */
|
|
if( b286_2_stop )
|
|
force_yoda();
|
|
else
|
|
trace("", trace_type);
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
default:
|
|
/*
|
|
** Was not a b286-1 instruction so carry on.
|
|
*/
|
|
break;
|
|
} /* end SWITCH */
|
|
}
|
|
#ifdef SPC386
|
|
if (((current_opcode & 0xffff) == 0x20cd)
|
|
&& getPE() && CsIsBig(check_I_cs))
|
|
{
|
|
IU16 service;
|
|
LIN_ADDR nextip;
|
|
char *name;
|
|
struct VMM_services *vmm_ptr;
|
|
|
|
/* This is a Windows VMM call break */
|
|
|
|
nextip = GetInstructionPointer();
|
|
nextip += dasm((char *)-1, check_I_cs, check_I_ip, 0);
|
|
service = sas_w_at(effective_addr(check_I_cs, nextip));
|
|
for (vmm_ptr = VMM_services; vmm_ptr->name; vmm_ptr++)
|
|
{
|
|
if (vmm_ptr->value == service)
|
|
break;
|
|
}
|
|
printf("Windows VMM Call %04x %s\n", service, vmm_ptr->name);
|
|
}
|
|
#endif /* SPC386 */
|
|
/*
|
|
** A normal break on opcode so lets break then.
|
|
*/
|
|
if (opcode_breaks[i].stop == 1)
|
|
force_yoda();
|
|
else
|
|
{
|
|
int dbs = disable_bkpt;
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
if (opcode_breaks[i].stop == 2)
|
|
{
|
|
LIN_ADDR nextip;
|
|
|
|
#ifdef SPC386
|
|
nextip = GetInstructionPointer();
|
|
nextip += dasm((char *)-1, (word)getCS(), getEIP(), 0);
|
|
#else /* SPC386 */
|
|
nextip = dasm((char *)-1, (word)1, (word)getCS(), (word)getIP(), (word)1);
|
|
#endif /* SPC386 */
|
|
set_inst_break(getCS(), nextip, 1, 0, 1);
|
|
disable_timer = 0;
|
|
}
|
|
disable_bkpt = dbs;
|
|
}
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (int_breakpoint && (temp_opcode == 0xCC || temp_opcode == 0xCD || temp_opcode == 0xCE))
|
|
{
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
|
|
if(step_count != -1)
|
|
if(step_count <= 1) {
|
|
disable_bkpt = 0;
|
|
step_count = -1;
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
else
|
|
step_count--;
|
|
|
|
for (i=0;i<inst_break_count;i++) {
|
|
ptr = &inst[i];
|
|
if (!(ptr->valid)) continue;
|
|
if(check_I_cs == ptr->cs && check_I_ip == ptr->ip) {
|
|
if(ptr->stop == 1) {
|
|
if (ptr->temp)
|
|
{
|
|
ptr->valid == 0;
|
|
ptr->temp == 0;
|
|
if (ptr++ == &inst[inst_break_count])
|
|
inst_break_count--;
|
|
}
|
|
force_yoda();
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
else {
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Looking for change at address in HOST space over specified range.
|
|
*/
|
|
|
|
if (host_address_break_count) {
|
|
for (i=0;i<host_address_break_count;i++) {
|
|
IU8 *old, *now;
|
|
dptr = &host_addresses[i];
|
|
|
|
old = (IU8 *)&dptr->old_value[0];
|
|
now = (IU8 *)dptr->data_addr;
|
|
if (memcmp(old, now, dptr->len) != 0)
|
|
{
|
|
for( j=0; j < dptr->len; j++ ){
|
|
if( old[ j ] != now[ j ] ){
|
|
printf( "host address change at %08p old:%2x new:%2x\n",
|
|
(IU8 *)((dptr->data_addr)+j),
|
|
old[ j ],
|
|
now[ j ]
|
|
);
|
|
}
|
|
}
|
|
if(dptr->stop) {
|
|
force_yoda();
|
|
}
|
|
else {
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
}
|
|
for( j=0; j < dptr->len; j++ )
|
|
old[ j ] = now[ j ];
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (data_words_break_count) {
|
|
for (i=0;i<data_words_break_count;i++) {
|
|
IBOOL changed = FALSE;
|
|
|
|
dptr = &data_words[i];
|
|
for( j=0; j < dptr->len; j++ ){
|
|
if( dptr->old_value[ j ] != sas_w_at( dptr->data_addr + (j * 2)) ){
|
|
printf( "Word change at %lx old:%x new:%x\n",
|
|
(LIN_ADDR)((dptr->data_addr)+(j*2)),
|
|
dptr->old_value[ j ],
|
|
sas_w_at( (dptr->data_addr)+(j*2) )
|
|
);
|
|
changed = TRUE;
|
|
}
|
|
}
|
|
if (changed) {
|
|
if (dptr->stop) {
|
|
force_yoda();
|
|
}
|
|
else {
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
}
|
|
for( j=0; j < dptr->len; j++ )
|
|
dptr->old_value[ j ] = sas_w_at( (dptr->data_addr)+(j*2) );
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if(verbose)
|
|
trace("Instruction Trace", trace_type);
|
|
|
|
set_last_address(check_I_cs, check_I_ip);
|
|
#if defined(A2CPU) || defined(GISP_CPU)
|
|
if (!fast)
|
|
{
|
|
cpu_interrupt (CPU_YODA_INT, 0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef DELTA
|
|
void delta_check_I IFN0()
|
|
{
|
|
delta_prompt = 1;
|
|
check_I();
|
|
delta_prompt = 0;
|
|
}
|
|
#endif /* DELTA */
|
|
|
|
|
|
void check_D IFN2(LIN_ADDR, addr, IS32, len)
|
|
{
|
|
int i;
|
|
BPTS *ptr;
|
|
if(disable_bkpt == 1)
|
|
return;
|
|
for (i=0;i<data_bytes_break_count;i++) {
|
|
ptr = &data_bytes[i];
|
|
if ((addr <= ptr->end_addr && addr >= ptr->start_addr ) ||
|
|
((addr + len) <= ptr->end_addr && (addr + len) >= ptr->start_addr ) ||
|
|
(addr < ptr->start_addr && (addr + len) > ptr->end_addr )) {
|
|
printf("Mem Address : %08x+%04x b\n", addr, len);
|
|
if(ptr->stop == 1)
|
|
force_yoda();
|
|
else {
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
}
|
|
}
|
|
}
|
|
/* for (i=0;i<data_words_break_count;i++) {
|
|
ptr = &data_words[i];
|
|
if(ptr->end_addr > addr && ptr->start_addr <= addr + len) {
|
|
printf("Mem Address : %08x+%04x w\n", addr,len);
|
|
if(ptr->stop == 1)
|
|
force_yoda();
|
|
else {
|
|
disable_bkpt = 1;
|
|
trace("", trace_type);
|
|
disable_bkpt = 0;
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
|
|
LOCAL void print_inst_mix IFN1(int, key)
|
|
{
|
|
int i /*,y*/;
|
|
|
|
#ifndef SFELLOW
|
|
if (out_stream == NULL)
|
|
out_stream = stdout;
|
|
#endif /* !SFELLOW */
|
|
|
|
if (key != 0)
|
|
printf("Opcode %x has been called %d times\n", key, inst_mix[key]);
|
|
else
|
|
{
|
|
fprintf(trace_file, "Instruction Mix Dump Start:\n");
|
|
for(i = 0; i < INST_MIX_LENGTH; i++)
|
|
if(inst_mix[i] != 0)
|
|
fprintf(trace_file, "%05x %d\n", i, inst_mix[i]);
|
|
fprintf(trace_file, "Instruction Mix Dump End:\n");
|
|
}
|
|
}
|
|
|
|
LOCAL void add_inst_mix IFN0()
|
|
{
|
|
LIN_ADDR addr;
|
|
addr = eff_addr( getCS(), GetInstructionPointer() );
|
|
inst_mix[(sas_hw_at(addr) << 8) + sas_hw_at(addr + 1)]++;
|
|
}
|
|
|
|
LOCAL void cga_test IFN0()
|
|
{
|
|
#ifdef SFELLOW
|
|
printf(SfNotImp);
|
|
#else /* SFELLOW */
|
|
/*
|
|
* Write test pattern to cga
|
|
*/
|
|
|
|
sys_addr addr;
|
|
char str[80];
|
|
int num_it, j, bytes, mode;
|
|
char ch;
|
|
|
|
addr = 0xb8000L;
|
|
|
|
printf("Number of iterations: ");
|
|
gets(str);
|
|
sscanf(str,"%d", &num_it);
|
|
|
|
if (num_it == 0)
|
|
{
|
|
reset();
|
|
}
|
|
else
|
|
{
|
|
printf("Number of bytes per write: ");
|
|
gets(str);
|
|
sscanf(str,"%d", &bytes);
|
|
|
|
if (bytes == 1)
|
|
{
|
|
printf("Use single byte function ? [y/n]: ");
|
|
gets(str);
|
|
sscanf(str,"%c", &ch);
|
|
|
|
if (ch == 'Y' || ch == 'y')
|
|
mode = 0;
|
|
else
|
|
mode = 1;
|
|
}
|
|
else
|
|
mode = 1;
|
|
|
|
setAH(0);
|
|
setAL(4);
|
|
bop(BIOS_VIDEO_IO);
|
|
|
|
switch (mode)
|
|
{
|
|
case 0: for(j = 0; j < num_it; j++)
|
|
{
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0, 0x4000);
|
|
addr = addr + 0x2000;
|
|
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0x55, 0x4000);
|
|
addr = addr + 0x2000;
|
|
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0xff, 0x4000);
|
|
addr = addr + 0x2000;
|
|
}
|
|
break;
|
|
case 1: for(j = 0; j < num_it; j++)
|
|
{
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0, 0x4000);
|
|
addr = addr + 0x2000;
|
|
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0x55, 0x4000);
|
|
addr = addr + 0x2000;
|
|
|
|
addr = 0xb8000L;
|
|
sas_fills(addr, 0xff, 0x4000);
|
|
addr = addr + 0x2000;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
#endif /* SFELLOW */
|
|
}
|
|
|
|
/*
|
|
* Back trace mode
|
|
* set up info to go into back trace cyclic buffer
|
|
* print current back trace buffer
|
|
*/
|
|
|
|
LOCAL void do_back_trace IFN0()
|
|
{
|
|
char ans[81];
|
|
char file[80];
|
|
|
|
printf("back trace: regs, inst, code, flags, CS:IP, print, status, zero ");
|
|
|
|
#ifdef DELTA
|
|
printf( "last_dest_addr " );
|
|
#endif /* DELTA */
|
|
|
|
printf( "\n" );
|
|
printf("Enter: r/i/c/f/C/p/s/Z/l/F ? ");
|
|
gets(ans);
|
|
switch (ans[0]) {
|
|
case 'r': back_trace_flags |= DUMP_REG; break;
|
|
case 'i': back_trace_flags |= DUMP_INST; break;
|
|
case 'c': back_trace_flags |= DUMP_CODE; break;
|
|
case 'f': back_trace_flags |= DUMP_FLAGS; break;
|
|
case 'C': back_trace_flags |= DUMP_CSIP; break;
|
|
case 'p': print_back_trace(); break;
|
|
case 's': printf("back trace flags:%x\n", back_trace_flags);
|
|
if (back_trace_flags & DUMP_REG) printf ("registers\n");
|
|
if (back_trace_flags & DUMP_INST) printf ("instructions\n");
|
|
if (back_trace_flags & DUMP_CODE) printf ("code\n");
|
|
if (back_trace_flags & DUMP_FLAGS) printf ("flags\n");
|
|
if (back_trace_flags & DUMP_CSIP) printf ("CS:IP\n");
|
|
break;
|
|
case 'Z': back_trace_flags = 0; break;
|
|
case 'F':
|
|
#ifdef SFELLOW
|
|
printf("F option is not supported on Stringfellows.\n");
|
|
#else /* SFELLOW */
|
|
printf("file to be written to ? ");
|
|
gets(file);
|
|
file_back_trace(file);
|
|
#endif /* SFELLOW */
|
|
break;
|
|
|
|
#ifdef DELTA
|
|
case 'l': back_trace_flags |= LAST_DEST; break;
|
|
#endif /* DELTA */
|
|
|
|
default : printf("bad choice\n");
|
|
}
|
|
}
|
|
|
|
intr IFN0()
|
|
{
|
|
/* Control-C has been typed !! */
|
|
|
|
vader = 1;
|
|
}
|
|
|
|
yoda_intr IFN1(int, signo)
|
|
{
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
|
|
EnterDebug("Intr");
|
|
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
|
|
#ifndef SFELLOW
|
|
printf("Intercepted signal %d\n", signo);
|
|
#endif /* !SFELLOW */
|
|
|
|
if (trace_file != stdout)
|
|
printf("Output is redirected to a file\n");
|
|
|
|
force_yoda();
|
|
|
|
#if defined(CPU_40_STYLE) && !defined(CCPU)
|
|
|
|
LeaveDebug();
|
|
|
|
#endif /* CPU_40_STYLE && !CCPU */
|
|
}
|
|
|
|
#ifdef NPX
|
|
LOCAL void do_compress_npx IFN1(FILE *, fp)
|
|
{
|
|
int ip = eff_addr(getCS(), GetInstructionPointer() );
|
|
int i;
|
|
extern CHAR *host_get_287_reg_as_string IPT2(int, reg_no, BOOL, in_nex);
|
|
extern ULONG get_287_sp IPT0();
|
|
extern USHORT get_287_tag_word IPT0();
|
|
extern ULONG get_287_status_word IPT0();
|
|
extern ULONG get_287_control_word IPT0();
|
|
|
|
ULONG sw287 = get_287_status_word () | ((get_287_sp() & 0x7) << 11);
|
|
ULONG cw287 = get_287_control_word ();
|
|
ULONG tw287 = get_287_tag_word();
|
|
|
|
double register_287;
|
|
char buff[256];
|
|
|
|
#ifdef SPC386
|
|
dasm(buff, (word)getCS(), (IU32)GetInstructionPointer(), SIXTEEN_BIT);
|
|
#else
|
|
dasm((char *)0,(word)0,(word)getCS(), (word)GetInstructionPointer(), (word)1);
|
|
#endif /* SPC386 */
|
|
fprintf(fp,"%sc%04x s%04x t%04x", buff, cw287, sw287, tw287);
|
|
for (i=0;i<8;i++)
|
|
fprintf(fp," %s", host_get_287_reg_as_string(i, FALSE));
|
|
fprintf(fp,"\n");
|
|
}
|
|
#endif /* NPX */
|
|
|
|
GLOBAL void da_block IFN3(IU16, cs, LIN_ADDR, ip, LIN_ADDR, len)
|
|
{
|
|
LIN_ADDR loop, loop1;
|
|
half_word ch;
|
|
LIN_ADDR addr;
|
|
|
|
if ((len == 0) || (len == YODA_LEN_UNSPECIFIED)) {
|
|
len=0x100;
|
|
if ((cs==0) && (ip==0)) {
|
|
cs=last_da_cs;
|
|
ip=last_da_ip;
|
|
}
|
|
}
|
|
addr = eff_addr(cs,ip);
|
|
if (len >= 16) {
|
|
for (loop=0; loop<=(len-16); loop+=16) {
|
|
if (loop != len) {
|
|
fprintf(trace_file,"%04x:%04x ",cs,ip+loop);
|
|
}
|
|
for (loop1=0;loop1<16;loop1++) {
|
|
fprintf(trace_file,"%02x ",sas_hw_at(addr+loop+loop1));
|
|
}
|
|
fprintf(trace_file," ");
|
|
for (loop1=0;loop1<16;loop1++) {
|
|
ch=sas_hw_at(addr+loop+loop1);
|
|
if ((ch < 32) || (ch >127)) {
|
|
fprintf(trace_file,".");
|
|
} else {
|
|
fprintf(trace_file,"%c",ch);
|
|
}
|
|
}
|
|
if ((loop+16)<len) {
|
|
fprintf(trace_file,"\n");
|
|
}
|
|
}
|
|
len -= loop;
|
|
ip += loop;
|
|
addr = eff_addr(cs,ip);
|
|
}
|
|
if (len >0) {
|
|
fprintf(trace_file,"%04x:%04x ",cs,ip);
|
|
for (loop=0;loop<len;loop++) {
|
|
fprintf(trace_file,"%02x ",sas_hw_at(addr+loop));
|
|
}
|
|
for (;loop<16;loop++) {
|
|
fprintf(trace_file," ");
|
|
}
|
|
fprintf(trace_file," ");
|
|
for (loop=0;loop<len;loop++) {
|
|
ch=sas_hw_at(addr+loop);
|
|
if ((ch < 32) || (ch >127)) {
|
|
fprintf(trace_file,".");
|
|
} else {
|
|
fprintf(trace_file,"%c",ch);
|
|
}
|
|
}
|
|
}
|
|
fprintf(trace_file,"\n");
|
|
ip += len;
|
|
if (ip & 0xf0000L) {
|
|
cs += ((ip & 0xf0000L)>>4);
|
|
ip &= 0xffff;
|
|
}
|
|
cs &= 0xffff;
|
|
last_da_cs=cs;
|
|
last_da_ip=ip;
|
|
}
|
|
#endif /* nPROD */
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* PCLABS STATS */
|
|
/*----------------------------------------------------------------------*/
|
|
#ifdef PCLABS_STATS
|
|
|
|
#define N 0
|
|
#define Y 1
|
|
|
|
LOCAL UTINY single_byte_instruction[256] = {
|
|
/* 0 */ N,N,N,N, Y,Y,Y,Y, N,N,N,N, Y,Y,Y,N,
|
|
/* 1 */ N,N,N,N, Y,Y,Y,Y, N,N,N,N, Y,Y,Y,Y,
|
|
/* 2 */ N,N,N,N, Y,Y,Y,Y, N,N,N,N, Y,Y,Y,Y,
|
|
/* 3 */ N,N,N,N, Y,Y,Y,Y, N,N,N,N, Y,Y,Y,Y,
|
|
|
|
/* 4 */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* 5 */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* 6 */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* 7 */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
|
|
/* 8 */ N,N,N,N, N,N,N,N, N,N,N,N, N,N,N,N,
|
|
/* 9 */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* A */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* B */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
|
|
/* C */ Y,Y,Y,Y, N,N,N,N, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* D */ N,N,N,N, Y,Y,Y,Y, N,N,N,N, N,N,N,N,
|
|
/* E */ Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y, Y,Y,Y,Y,
|
|
/* F */ Y,Y,Y,Y, Y,Y,N,N, Y,Y,Y,Y, Y,Y,N,N };
|
|
|
|
FILE *stats_file;
|
|
|
|
LOCAL ULONG instr_counts[0x10000];
|
|
LOCAL ULONG zerof_instr_counts[0x10000];
|
|
|
|
LOCAL ULONG es_prefixes;
|
|
LOCAL ULONG ss_prefixes;
|
|
LOCAL ULONG ds_prefixes;
|
|
LOCAL ULONG cs_prefixes;
|
|
LOCAL ULONG rep_prefixes;
|
|
LOCAL ULONG repe_prefixes;
|
|
LOCAL ULONG lock_prefixes;
|
|
|
|
LOCAL BOOL was_a_conditional_jump;
|
|
LOCAL BOOL was_a_0f;
|
|
LOCAL ULONG previous_addr;
|
|
LOCAL ULONG previous_index;
|
|
|
|
|
|
LOCAL BOOL is_it_a_conditional_jump IFN1(ULONG, b1)
|
|
{
|
|
if (b1 >= 0x70 && b1 <= 0x7f)
|
|
return (TRUE);
|
|
if (b1 >= 0xe0 && b1 <= 0xe3)
|
|
return (TRUE);
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
LOCAL log_stats IFN4(LIN_ADDR, addr, ULONG, b1, ULONG, b2, ULONG, b3)
|
|
{
|
|
BOOL is_a_conditional_jump, is_a_0f;
|
|
ULONG index;
|
|
|
|
addr = getCS_BASE() + GetInstructionPointer();
|
|
|
|
b1 &= 0xff;
|
|
b2 &= 0xff;
|
|
b3 &= 0xff;
|
|
|
|
/* determine instruction key */
|
|
/* ------------------------- */
|
|
|
|
is_a_0f = FALSE;
|
|
if (b1 == 0x0f)
|
|
{
|
|
/* 0f case */
|
|
/* ------- */
|
|
|
|
is_a_0f = TRUE;
|
|
is_a_conditional_jump = FALSE;
|
|
index = (b2 << 8) | b3;
|
|
}
|
|
else if (b1 == 0x26 || b1 == 0x36 || b1 == 0x2E || b1 == 0x3E ||
|
|
b1 == 0xF2 || b1 == 0xF3 || b1 == 0xF0)
|
|
{
|
|
/* prefix case */
|
|
/* ----------- */
|
|
|
|
is_a_conditional_jump = is_it_a_conditional_jump(b2);
|
|
if (single_byte_instruction[b2])
|
|
index = b2 << 8;
|
|
else
|
|
index = (b2 << 8) | b3;
|
|
switch (b1)
|
|
{
|
|
case 0x26:
|
|
es_prefixes++;
|
|
break;
|
|
|
|
case 0x36:
|
|
ss_prefixes++;
|
|
break;
|
|
|
|
case 0x2E:
|
|
ds_prefixes++;
|
|
break;
|
|
|
|
case 0x3E:
|
|
cs_prefixes++;
|
|
break;
|
|
|
|
case 0xF2:
|
|
rep_prefixes++;
|
|
break;
|
|
|
|
case 0xF3:
|
|
repe_prefixes++;
|
|
break;
|
|
|
|
case 0xF0:
|
|
lock_prefixes++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* non prefix case */
|
|
/* --------------- */
|
|
|
|
is_a_conditional_jump = is_it_a_conditional_jump(b1);
|
|
if (single_byte_instruction[b1])
|
|
index = b1 << 8;
|
|
else
|
|
index = (b1 << 8) | b2;
|
|
}
|
|
|
|
if (was_a_conditional_jump)
|
|
{
|
|
if (addr != (previous_addr + 2))
|
|
previous_index++;
|
|
}
|
|
if (was_a_0f)
|
|
zerof_instr_counts[previous_index]++;
|
|
else
|
|
instr_counts[previous_index]++;
|
|
previous_index = index;
|
|
previous_addr = addr;
|
|
was_a_conditional_jump = is_a_conditional_jump;
|
|
was_a_0f = is_a_0f;
|
|
}
|
|
|
|
|
|
LOCAL clear_stats IFN0()
|
|
{
|
|
ULONG i;
|
|
for (i = 0; i < 0x10000; i++)
|
|
{
|
|
instr_counts[i] = 0;
|
|
zerof_instr_counts[i] = 0;
|
|
}
|
|
|
|
es_prefixes = 0;
|
|
ss_prefixes = 0;
|
|
ds_prefixes = 0;
|
|
cs_prefixes = 0;
|
|
rep_prefixes = 0;
|
|
repe_prefixes = 0;
|
|
lock_prefixes = 0;
|
|
was_a_conditional_jump = FALSE;
|
|
was_a_0f = FALSE;
|
|
}
|
|
|
|
|
|
struct DISPLAY_COMMAND {
|
|
ULONG command;
|
|
ULONG from;
|
|
ULONG to;
|
|
ULONG number;
|
|
char *string;
|
|
char *group;
|
|
};
|
|
|
|
LOCAL char *previous_group;
|
|
|
|
#define RANGE 1
|
|
#define LOCK 2
|
|
#define REPNZ 3
|
|
#define REP 4
|
|
#define SELMEM 5
|
|
#define SELREG 6
|
|
#define POINT 7
|
|
#define ALLMEM 8
|
|
#define ALLREG 9
|
|
#define ALL 10
|
|
#define SEL5 11
|
|
#define ES_PREFIX 12
|
|
#define CS_PREFIX 13
|
|
#define SS_PREFIX 14
|
|
#define DS_PREFIX 15
|
|
#define USE_NORMAL 16
|
|
#define USE_ZEROF 17
|
|
#define SELALL 18
|
|
#define FPINVALID 19
|
|
|
|
LOCAL struct DISPLAY_COMMAND commands[] = {
|
|
|
|
POINT, 0x7001, 0, 112, "JO_Ib", "jcc_Taken",
|
|
POINT, 0x7101, 0, 113, "JNO_Ib", "jcc_Taken",
|
|
POINT, 0x7201, 0, 114, "JC_Ib", "jcc_Taken",
|
|
POINT, 0x7301, 0, 115, "JNC_Ib", "jcc_Taken",
|
|
POINT, 0x7401, 0, 116, "JZ_Ib", "jcc_Taken",
|
|
POINT, 0x7501, 0, 117, "JNZ_Ib", "jcc_Taken",
|
|
POINT, 0x7601, 0, 118, "JBE_Ib", "jcc_Taken",
|
|
POINT, 0x7701, 0, 119, "JNBE_Ib", "jcc_Taken",
|
|
POINT, 0x7801, 0, 120, "JS_Ib", "jcc_Taken",
|
|
POINT, 0x7901, 0, 121, "JNS_Ib", "jcc_Taken",
|
|
POINT, 0x7A01, 0, 122, "JP_Ib", "jcc_Taken",
|
|
POINT, 0x7B01, 0, 123, "JNP_Ib", "jcc_Taken",
|
|
POINT, 0x7C01, 0, 124, "JL_Ib", "jcc_Taken",
|
|
POINT, 0x7D01, 0, 125, "JNL_Ib", "jcc_Taken",
|
|
POINT, 0x7E01, 0, 126, "JLE_Ib", "jcc_Taken",
|
|
POINT, 0x7F01, 0, 127, "JNLE_Ib", "jcc_Taken",
|
|
LOCK, 0, 0, 240, "LOCK_prefix", "jcc_Taken",
|
|
REPNZ, 0, 0, 242, "REPNZ_prefix", "jcc_Taken",
|
|
REP, 0, 0, 243, "REP_prefix", "jcc_Taken",
|
|
|
|
POINT, 0x7000, 0x7000, 112, "JO_Ib", "jcc_Ntaken",
|
|
POINT, 0x7100, 0x7100, 113, "JNO_Ib", "jcc_Ntaken",
|
|
POINT, 0x7200, 0x7200, 114, "JC_Ib", "jcc_Ntaken",
|
|
POINT, 0x7300, 0x7300, 115, "JNC_Ib", "jcc_Ntaken",
|
|
POINT, 0x7400, 0x7400, 116, "JZ_Ib", "jcc_Ntaken",
|
|
POINT, 0x7500, 0x7500, 117, "JNZ_Ib", "jcc_Ntaken",
|
|
POINT, 0x7600, 0x7600, 118, "JBE_Ib", "jcc_Ntaken",
|
|
POINT, 0x7700, 0x7700, 119, "JNBE_Ib", "jcc_Ntaken",
|
|
POINT, 0x7800, 0x7800, 120, "JS_Ib", "jcc_Ntaken",
|
|
POINT, 0x7900, 0x7900, 121, "JNS_Ib", "jcc_Ntaken",
|
|
POINT, 0x7A00, 0x7A00, 122, "JP_Ib", "jcc_Ntaken",
|
|
POINT, 0x7B00, 0x7B00, 123, "JNP_Ib", "jcc_Ntaken",
|
|
POINT, 0x7C00, 0x7C00, 124, "JL_Ib", "jcc_Ntaken",
|
|
POINT, 0x7D00, 0x7D00, 125, "JNL_Ib", "jcc_Ntaken",
|
|
POINT, 0x7E00, 0x7E00, 126, "JLE_Ib", "jcc_Ntaken",
|
|
POINT, 0x7F00, 0x7F00, 127, "JNLE_Ib", "jcc_Ntaken",
|
|
|
|
POINT, 0xE900, 0xE900, 233, "JMPn_Iw", "jump",
|
|
POINT, 0xEB00, 0xEB00, 235, "JMPn_Ib", "jump",
|
|
|
|
SELMEM, 0xFF00, 0x20, 660, "JMPn_EA", "jump_in",
|
|
SELREG, 0xFF00, 0x20, 660, "JMPn_EA", "jump_in_r",
|
|
POINT, 0xE800, 0, 232, "CALLn_Iw", "call",
|
|
SELMEM, 0xFF00, 0x10, 658, "CALLn_EA", "call_in",
|
|
SELREG, 0xFF00, 0x10, 658, "CALLn_EA", "call_in_r",
|
|
POINT, 0xC200, 0, 194, "RET_Is", "ret",
|
|
POINT, 0xC300, 0, 195, "RETn", "ret",
|
|
|
|
POINT, 0xE001, 0, 224, "LOOPNZb_Ib", "loop/jcx_Taken",
|
|
POINT, 0xE101, 0, 225, "LOOPNb_Ib", "loop/jcx_Taken",
|
|
POINT, 0xE201, 0, 226, "LOOP_Ib", "loop/jcx_Taken",
|
|
POINT, 0xE301, 0, 227, "JCXZb_Ib", "loop/jcx_Taken",
|
|
|
|
POINT, 0xE000, 0, 224, "LOOPNZb_Ib", "loop/jcx_NTaken",
|
|
POINT, 0xE100, 0, 225, "LOOPNb_Ib", "loop/jcx_NTaken",
|
|
POINT, 0xE200, 0, 226, "LOOP_Ib", "loop/jcx_NTaken",
|
|
POINT, 0xE300, 0, 227, "JCXZb_Ib", "loop/jcx_NTaken",
|
|
|
|
ALLMEM, 0x8800, 0, 136, "MOVb_R_EA", "mov_r,m",
|
|
ALLMEM, 0x8900, 0, 137, "MOVw_R_EA", "mov_r,m",
|
|
POINT, 0xA200, 0, 162, "MOVb_AL_EA", "mov_r,m",
|
|
POINT, 0xA300, 0, 163, "MOVb_AX_EA", "mov_r,m",
|
|
|
|
ALLREG, 0x8600, 0, 134, "XCHGb_EA_R", "mov_r,r",
|
|
ALLREG, 0x8700, 0, 135, "XCHGw_EA_R", "mov_r,r",
|
|
ALLREG, 0x8800, 0, 136, "MOVb_R_EA", "mov_r,r",
|
|
ALLREG, 0x8900, 0, 137, "MOVw_R_EA", "mov_r,r",
|
|
ALLREG, 0x8A00, 0, 138, "MOVb_EA_R", "mov_r,r",
|
|
ALLREG, 0x8B00, 0, 139, "MOVw_EA_R", "mov_r,r",
|
|
POINT, 0x9100, 0, 145, "XCHG_CX_AX", "mov_r,r",
|
|
POINT, 0x9200, 0, 146, "XCHG_DX_AX", "mov_r,r",
|
|
POINT, 0x9300, 0, 147, "XCHG_BX_AX", "mov_r,r",
|
|
POINT, 0x9400, 0, 148, "XCHG_SP_AX", "mov_r,r",
|
|
POINT, 0x9500, 0, 149, "XCHG_BP_AX", "mov_r,r",
|
|
POINT, 0x9600, 0, 150, "XCHG_SI_AX", "mov_r,r",
|
|
POINT, 0x9700, 0, 151, "XCHG_DI_AX", "mov_r,r",
|
|
|
|
ALLMEM, 0x8600, 0, 134, "XCHGb_EA_R", "mov_m,r",
|
|
ALLMEM, 0x8700, 0, 135, "XCHGw_EA_R", "mov_m,r",
|
|
ALLMEM, 0x8A00, 0, 138, "MOVb_EA_R", "mov_m,r",
|
|
ALLMEM, 0x8B00, 0, 139, "MOVw_EA_R", "mov_m,r",
|
|
POINT, 0xA000, 0, 160, "MOVb_EA_AL", "mov_m,r",
|
|
POINT, 0xA100, 0, 161, "MOVw_EA_AX", "mov_m,r",
|
|
|
|
POINT, 0xB000, 0, 176, "MOVb_Ib_AL", "mov_i,r",
|
|
POINT, 0xB100, 0, 177, "MOVb_Ib_CL", "mov_i,r",
|
|
POINT, 0xB200, 0, 178, "MOVb_Ib_DL", "mov_i,r",
|
|
POINT, 0xB300, 0, 179, "MOVb_Ib_BL", "mov_i,r",
|
|
POINT, 0xB400, 0, 180, "MOVb_Ib_AH", "mov_i,r",
|
|
POINT, 0xB500, 0, 181, "MOVb_Ib_CH", "mov_i,r",
|
|
POINT, 0xB600, 0, 182, "MOVb_Ib_DH", "mov_i,r",
|
|
POINT, 0xB700, 0, 183, "MOVb_Ib_BH", "mov_i,r",
|
|
POINT, 0xB800, 0, 184, "MOVw_Iw_AX", "mov_i,r",
|
|
POINT, 0xB900, 0, 185, "MOVw_Iw_CX", "mov_i,r",
|
|
POINT, 0xBA00, 0, 186, "MOVw_Iw_DX", "mov_i,r",
|
|
POINT, 0xBB00, 0, 187, "MOVw_Iw_BX", "mov_i,r",
|
|
POINT, 0xBC00, 0, 188, "MOVw_Iw_SP", "mov_i,r",
|
|
POINT, 0xBD00, 0, 189, "MOVw_Iw_BP", "mov_i,r",
|
|
POINT, 0xBE00, 0, 190, "MOVw_Iw_SI", "mov_i,r",
|
|
POINT, 0xBF00, 0, 191, "MOVw_Iw_DI", "mov_i,r",
|
|
SELREG, 0xC600, 0, 198, "MOVb_Ib_EA", "mov_i,r",
|
|
SELREG, 0xC700, 0, 199, "MOVw_Iw_EA", "mov_i,r",
|
|
|
|
SELMEM, 0xC600, 0, 198, "MOVb_Ib_EA", "mov_i,m",
|
|
SELMEM, 0xC700, 0, 199, "MOVw_Iw_EA", "mov_i,m",
|
|
|
|
POINT, 0x5000, 0, 80, "PUSHw_AX", "push_r",
|
|
POINT, 0x5100, 0, 81, "PUSHw_CX", "push_r",
|
|
POINT, 0x5200, 0, 82, "PUSHw_DX", "push_r",
|
|
POINT, 0x5300, 0, 83, "PUSHw_BX", "push_r",
|
|
POINT, 0x5400, 0, 84, "PUSHw_SP", "push_r",
|
|
POINT, 0x5500, 0, 85, "PUSHw_BP", "push_r",
|
|
POINT, 0x5600, 0, 86, "PUSHw_SI", "push_r",
|
|
POINT, 0x5700, 0, 87, "PUSHw_DI", "push_r",
|
|
SELREG, 0xFF00, 0x30, 662, "PUSHw_EA", "push_r",
|
|
|
|
SELMEM, 0xFF00, 0x30, 662, "PUSHw_EA", "push_m",
|
|
|
|
POINT, 0x6800, 0, 104, "PUSHw_Iw", "push_i",
|
|
POINT, 0x6A00, 0, 106, "PUSHb_Ib", "push_i",
|
|
|
|
POINT, 0x5800, 0, 88, "POPw_AX", "pop_r",
|
|
POINT, 0x5900, 0, 89, "POPw_CX", "pop_r",
|
|
POINT, 0x5A00, 0, 90, "POPw_DX", "pop_r",
|
|
POINT, 0x5B00, 0, 91, "POPw_BX", "pop_r",
|
|
POINT, 0x5C00, 0, 92, "POPw_SP", "pop_r",
|
|
POINT, 0x5D00, 0, 93, "POPw_BP", "pop_r",
|
|
POINT, 0x5E00, 0, 94, "POPw_SI", "pop_r",
|
|
POINT, 0x5F00, 0, 95, "POPw_DI", "pop_r",
|
|
SELREG, 0x8F00, 0x0, 143, "POPw_EA", "pop_r",
|
|
|
|
SELMEM, 0x8F00, 0x0, 143, "POPw_EA", "pop_m",
|
|
|
|
ALLMEM, 0x3800, 0, 56, "CMPb_R_EA", "cmp_m,r",
|
|
ALLMEM, 0x3900, 0, 57, "CMPw_R_EA", "cmp_m,r",
|
|
ALLMEM, 0x3A00, 0, 58, "CMPb_EA_R", "cmp_m,r",
|
|
ALLMEM, 0x3B00, 0, 59, "CMPw_EA_R", "cmp_m,r",
|
|
ALLMEM, 0x8400, 0, 132, "TESTb_R_EA", "cmp_m,r",
|
|
ALLMEM, 0x8500, 0, 133, "TESTw_R_EA", "cmp_m,r",
|
|
|
|
ALLREG, 0x3800, 0, 56, "CMPb_R_EA", "cmp_r,r",
|
|
ALLREG, 0x3900, 0, 57, "CMPw_R_EA", "cmp_r,r",
|
|
ALLREG, 0x3A00, 0, 58, "CMPb_EA_R", "cmp_r,r",
|
|
ALLREG, 0x3B00, 0, 59, "CMPw_EA_R", "cmp_r,r",
|
|
ALLREG, 0x8400, 0, 132, "TESTb_R_EA", "cmp_r,r",
|
|
ALLREG, 0x8500, 0, 133, "TESTw_R_EA", "cmp_r,r",
|
|
|
|
POINT, 0x3C00, 0, 60, "CMPb_Ib_AL", "cmp_i,r",
|
|
POINT, 0x3D00, 0, 61, "CMPw_Iw_AX", "cmp_i,r",
|
|
POINT, 0xA800, 0, 168, "TESTb_Ib_AL", "cmp_i,r",
|
|
POINT, 0xA900, 0, 169, "TESTw_Iw_AX", "cmp_i,r",
|
|
SELREG, 0x8000, 0x38, 519, "CMPb_Ib_EA", "cmp_i,r",
|
|
SELREG, 0x8100, 0x38, 527, "CMPw_Iw_EA", "cmp_i,r",
|
|
SELREG, 0x8300, 0x38, 543, "CMPw_Ib_EA", "cmp_i,r",
|
|
SELREG, 0xF600, 0x0, 632, "TESTb_Ib_EA", "cmp_i,r",
|
|
SELREG, 0xF700, 0x0, 640, "TESTw_Iw_EA", "cmp_i,r",
|
|
|
|
SELMEM, 0x8000, 0x38, 519, "CMPb_Ib_EA", "cmp_i,m",
|
|
SELMEM, 0x8100, 0x38, 527, "CMPw_Iw_EA", "cmp_i,m",
|
|
SELMEM, 0x8300, 0x38, 543, "CMPw_Ib_EA", "cmp_i,m",
|
|
SELMEM, 0xF600, 0x0, 632, "TESTb_Ib_EA", "cmp_i,m",
|
|
SELMEM, 0xF700, 0x0, 640, "TESTw_Iw_EA", "cmp_i,m",
|
|
|
|
ALLMEM, 0x0200, 0, 2, "ADDb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x0300, 0, 3, "ADDw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x0A00, 0, 10, "ORb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x0B00, 0, 11, "ORw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x1200, 0, 18, "ADCb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x1300, 0, 19, "ADCw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x1A00, 0, 26, "SBBb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x1B00, 0, 27, "SBBw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x2200, 0, 34, "ANDb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x2300, 0, 35, "ANDw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x2A00, 0, 42, "SUBb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x2B00, 0, 43, "SUBw_EA_R", "alu_m,r",
|
|
ALLMEM, 0x3200, 0, 50, "XORb_EA_R", "alu_m,r",
|
|
ALLMEM, 0x3300, 0, 51, "XORw_EA_R", "alu_m,r",
|
|
|
|
ALLREG, 0x0000, 0, 0, "ADDb_R_EA", "alu_r,r",
|
|
ALLREG, 0x0100, 0, 1, "ADDw_R_EA", "alu_r,r",
|
|
ALLREG, 0x0200, 0, 2, "ADDb_EA_R", "alu_r,r",
|
|
ALLREG, 0x0300, 0, 3, "ADDw_EA_R", "alu_r,r",
|
|
ALLREG, 0x0800, 0, 8, "ORb_R_EA", "alu_r,r",
|
|
ALLREG, 0x0900, 0, 9, "ORw_R_EA", "alu_r,r",
|
|
ALLREG, 0x0A00, 0, 10, "ORb_EA_R", "alu_r,r",
|
|
ALLREG, 0x0B00, 0, 11, "ORw_EA_R", "alu_r,r",
|
|
ALLREG, 0x1000, 0, 16, "ADCb_R_EA", "alu_r,r",
|
|
ALLREG, 0x1100, 0, 17, "ADCw_R_EA", "alu_r,r",
|
|
ALLREG, 0x1200, 0, 18, "ADCb_EA_R", "alu_r,r",
|
|
ALLREG, 0x1300, 0, 19, "ADCw_EA_R", "alu_r,r",
|
|
ALLREG, 0x1800, 0, 24, "SBBb_R_EA", "alu_r,r",
|
|
ALLREG, 0x1900, 0, 25, "SBBw_R_EA", "alu_r,r",
|
|
ALLREG, 0x1A00, 0, 26, "SBBb_EA_R", "alu_r,r",
|
|
ALLREG, 0x1B00, 0, 27, "SBBw_EA_R", "alu_r,r",
|
|
ALLREG, 0x2000, 0, 32, "ANDb_R_EA", "alu_r,r",
|
|
ALLREG, 0x2100, 0, 33, "ANDw_R_EA", "alu_r,r",
|
|
ALLREG, 0x2200, 0, 34, "ANDb_EA_R", "alu_r,r",
|
|
ALLREG, 0x2300, 0, 35, "ANDw_EA_R", "alu_r,r",
|
|
ALLREG, 0x2800, 0, 40, "SUBb_R_EA", "alu_r,r",
|
|
ALLREG, 0x2900, 0, 41, "SUBw_R_EA", "alu_r,r",
|
|
ALLREG, 0x2A00, 0, 42, "SUBb_EA_R", "alu_r,r",
|
|
ALLREG, 0x2B00, 0, 43, "SUBw_EA_R", "alu_r,r",
|
|
ALLREG, 0x3000, 0, 48, "XORb_R_EA", "alu_r,r",
|
|
ALLREG, 0x3100, 0, 49, "XORw_R_EA", "alu_r,r",
|
|
ALLREG, 0x3200, 0, 50, "XORb_EA_R", "alu_r,r",
|
|
ALLREG, 0x3300, 0, 51, "XORw_EA_R", "alu_r,r",
|
|
|
|
ALLMEM, 0x0000, 0, 0, "ADDb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x0100, 0, 1, "ADDw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x0800, 0, 8, "ORb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x0900, 0, 9, "ORw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x1000, 0, 16, "ADCb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x1100, 0, 17, "ADCw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x1800, 0, 24, "SBBb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x1900, 0, 25, "SBBw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x2000, 0, 32, "ANDb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x2100, 0, 33, "ANDw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x2800, 0, 40, "SUBb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x2900, 0, 41, "SUBw_R_EA", "alu_r,m",
|
|
ALLMEM, 0x3000, 0, 48, "XORb_R_EA", "alu_r,m",
|
|
ALLMEM, 0x3100, 0, 49, "XORw_R_EA", "alu_r,m",
|
|
|
|
POINT, 0x0400, 0, 4, "ADDb_Ib_AL", "alu_i,r",
|
|
POINT, 0x0500, 0, 5, "ADDw_Iw_AX", "alu_i,r",
|
|
POINT, 0x0C00, 0, 12, "ORb_Ib_AL", "alu_i,r",
|
|
POINT, 0x0D00, 0, 13, "ORw_Iw_AX", "alu_i,r",
|
|
POINT, 0x1400, 0, 20, "ADCb_Ib_AL", "alu_i,r",
|
|
POINT, 0x1500, 0, 21, "ADCw_Iw_AX", "alu_i,r",
|
|
POINT, 0x1C00, 0, 28, "SBBb_Ib_AL", "alu_i,r",
|
|
POINT, 0x1D00, 0, 29, "SBBw_Iw_AX", "alu_i,r",
|
|
POINT, 0x2400, 0, 36, "ANDb_Ib_AL", "alu_i,r",
|
|
POINT, 0x2500, 0, 37, "ANDw_Iw_AX", "alu_i,r",
|
|
POINT, 0x2C00, 0, 44, "SUBb_Ib_AL", "alu_i,r",
|
|
POINT, 0x2D00, 0, 45, "SUBw_Iw_AX", "alu_i,r",
|
|
POINT, 0x3400, 0, 52, "XORb_Ib_AL", "alu_i,r",
|
|
POINT, 0x3500, 0, 53, "XORw_Iw_AX", "alu_i,r",
|
|
SELREG, 0x8000, 0x0, 512, "ADDb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x8, 513, "ORb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x10, 514, "ADCb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x18, 515, "SBBb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x20, 516, "ANDb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x28, 517, "SUBb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8000, 0x30, 518, "XORb_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x0, 520, "ADDw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x8, 521, "ORw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x10, 522, "ADCw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x18, 523, "SBBw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x20, 524, "ANDw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x28, 525, "SUBw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8100, 0x30, 526, "XORw_Iw_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x0, 536, "ADDw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x8, 537, "ORw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x10, 538, "ADCw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x18, 539, "SBBw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x20, 540, "ANDw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x28, 541, "SUBw_Ib_EA", "alu_i,r",
|
|
SELREG, 0x8300, 0x30, 542, "XORw_Ib_EA", "alu_i,r",
|
|
|
|
SELMEM, 0x8000, 0x0, 512, "ADDb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x8, 513, "ORb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x10, 514, "ADCb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x18, 515, "SBBb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x20, 516, "ANDb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x28, 517, "SUBb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8000, 0x30, 518, "XORb_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x0, 520, "ADDw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x8, 521, "ORw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x10, 522, "ADCw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x18, 523, "SBBw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x20, 524, "ANDw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x28, 525, "SUBw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8100, 0x30, 526, "XORw_Iw_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x0, 536, "ADDw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x8, 537, "ORw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x10, 538, "ADCw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x18, 539, "SBBw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x20, 540, "ANDw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x28, 541, "SUBw_Ib_EA", "alu_i,m",
|
|
SELMEM, 0x8300, 0x30, 542, "XORw_Ib_EA", "alu_i,m",
|
|
|
|
POINT, 0x4000, 0, 64, "INCw_AX", "alu_r",
|
|
POINT, 0x4100, 0, 65, "INCw_CX", "alu_r",
|
|
POINT, 0x4200, 0, 66, "INCw_DX", "alu_r",
|
|
POINT, 0x4300, 0, 67, "INCw_BX", "alu_r",
|
|
POINT, 0x4400, 0, 68, "INCw_SP", "alu_r",
|
|
POINT, 0x4500, 0, 69, "INCw_BP", "alu_r",
|
|
POINT, 0x4600, 0, 70, "INCw_SI", "alu_r",
|
|
POINT, 0x4700, 0, 71, "INCw_DI", "alu_r",
|
|
POINT, 0x4800, 0, 72, "DECw_AX", "alu_r",
|
|
POINT, 0x4900, 0, 73, "DECw_CX", "alu_r",
|
|
POINT, 0x4A00, 0, 74, "DECw_DX", "alu_r",
|
|
POINT, 0x4B00, 0, 75, "DECw_BX", "alu_r",
|
|
POINT, 0x4C00, 0, 76, "DECw_SP", "alu_r",
|
|
POINT, 0x4D00, 0, 77, "DECw_BP", "alu_r",
|
|
POINT, 0x4E00, 0, 78, "DECw_SI", "alu_r",
|
|
POINT, 0x4F00, 0, 79, "DECw_DI", "alu_r",
|
|
POINT, 0x9800, 0, 152, "CBW", "alu_r",
|
|
POINT, 0x9900, 0, 153, "CBD", "alu_r",
|
|
SELREG, 0xF600, 0x10, 634, "NOTb_EA", "alu_r",
|
|
SELREG, 0xF600, 0x18, 635, "NEGb_EA", "alu_r",
|
|
SELREG, 0xF700, 0x10, 642, "NOTw_EA", "alu_r",
|
|
SELREG, 0xF700, 0x18, 643, "NEGw_EA", "alu_r",
|
|
SELREG, 0xFE00, 0x0, 648, "INCb_EA", "alu_r",
|
|
SELREG, 0xFE00, 0x8, 649, "DECb_EA", "alu_r",
|
|
SELREG, 0xFF00, 0x0, 656, "INCw_EA", "alu_r",
|
|
SELREG, 0xFF00, 0x8, 657, "DECw_EA", "alu_r",
|
|
|
|
SELMEM, 0xF600, 0x10, 634, "NOTb_EA", "alu_m",
|
|
SELMEM, 0xF600, 0x18, 635, "NEGb_EA", "alu_m",
|
|
SELMEM, 0xF700, 0x10, 642, "NOTw_EA", "alu_m",
|
|
SELMEM, 0xF700, 0x18, 643, "NEGw_EA", "alu_m",
|
|
SELMEM, 0xFE00, 0x0, 648, "INCb_EA", "alu_m",
|
|
SELMEM, 0xFE00, 0x8, 649, "DECb_EA", "alu_m",
|
|
SELMEM, 0xFF00, 0x0, 656, "INCw_EA", "alu_m",
|
|
SELMEM, 0xFF00, 0x8, 657, "DECw_EA", "alu_m",
|
|
|
|
ALL, 0x8D00, 0, 141, "LEAw_EA_R", "lea",
|
|
|
|
POINT, 0x9000, 0, 144, "NOP", "nop",
|
|
|
|
ALL, 0x6900, 0, 105, "IMULw_EA_Iw_R","mul",
|
|
ALL, 0x6B00, 0, 107, "IMULb_EA_Ib_R","mul",
|
|
SELALL, 0xF600, 0x20, 636, "MULb_EA", "mul",
|
|
SELALL, 0xF600, 0x28, 637, "IMULb_EA", "mul",
|
|
SELALL, 0xF700, 0x20, 644, "MULw_EA", "mul",
|
|
SELALL, 0xF700, 0x28, 645, "IMULw_EA", "mul",
|
|
|
|
SELALL, 0xF600, 0x30, 638, "DIVb_EA", "div",
|
|
SELALL, 0xF600, 0x38, 639, "IDIVb_EA", "div",
|
|
SELALL, 0xF700, 0x30, 646, "DIVw_EA", "div",
|
|
SELALL, 0xF700, 0x38, 647, "IDIVw_EA", "div",
|
|
|
|
POINT, 0x2700, 0, 39, "DAA", "ascii/dec",
|
|
POINT, 0x2F00, 0, 47, "DAS", "ascii/dec",
|
|
POINT, 0x3700, 0, 55, "AAA", "ascii/dec",
|
|
POINT, 0x3F00, 0, 63, "AAS", "ascii/dec",
|
|
POINT, 0xD400, 0, 212, "AAM", "ascii/dec",
|
|
POINT, 0xD500, 0, 213, "AAD", "ascii/dec",
|
|
|
|
SELALL, 0xD000, 0x00, 600, "ROLb_1_EA", "sh_rot_1",
|
|
SELALL, 0xD000, 0x08, 601, "RORb_1_EA", "sh_rot_1",
|
|
SELALL, 0xD000, 0x20, 604, "SHLb_1_EA", "sh_rot_1",
|
|
SELALL, 0xD000, 0x28, 605, "SHRb_1_EA", "sh_rot_1",
|
|
SELALL, 0xD000, 0x38, 607, "SARb_1_EA", "sh_rot_1",
|
|
SELALL, 0xD100, 0x00, 608, "ROLw_1_EA", "sh_rot_1",
|
|
SELALL, 0xD100, 0x08, 609, "RORw_1_EA", "sh_rot_1",
|
|
SELALL, 0xD100, 0x20, 612, "SHLw_1_EA", "sh_rot_1",
|
|
SELALL, 0xD100, 0x28, 613, "SHRw_1_EA", "sh_rot_1",
|
|
SELALL, 0xD100, 0x38, 615, "SARw_1_EA", "sh_rot_1",
|
|
|
|
SELALL, 0xC000, 0x00, 568, "ROLb_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC000, 0x08, 569, "RORb_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC000, 0x20, 572, "SHLb_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC000, 0x28, 573, "SHRb_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC000, 0x38, 575, "SARb_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC100, 0x00, 576, "ROLw_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC100, 0x08, 577, "RORw_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC100, 0x20, 580, "SHLw_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC100, 0x28, 581, "SHRw_Ib_EA", "sh_rot_i",
|
|
SELALL, 0xC100, 0x38, 583, "SARw_Ib_EA", "sh_rot_i",
|
|
|
|
SELALL, 0xD200, 0x00, 616, "ROLb_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD200, 0x08, 617, "RORb_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD200, 0x20, 620, "SHLb_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD200, 0x28, 621, "SHRb_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD200, 0x38, 623, "SARb_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD300, 0x00, 624, "ROLw_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD300, 0x08, 625, "RORw_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD300, 0x20, 628, "SHLw_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD300, 0x28, 629, "SHRw_CL_EA", "sh_rot_cl",
|
|
SELALL, 0xD300, 0x38, 631, "SARw_CL_EA", "sh_rot_cl",
|
|
|
|
SELALL, 0xD000, 0x10, 602, "RCLb_1_EA", "sh_rot_c_1",
|
|
SELALL, 0xD000, 0x18, 603, "RCRb_1_EA", "sh_rot_c_1",
|
|
SELALL, 0xD100, 0x10, 610, "RCLw_1_EA", "sh_rot_c_1",
|
|
SELALL, 0xD100, 0x18, 611, "RCRw_1_EA", "sh_rot_c_1",
|
|
|
|
SELALL, 0xC000, 0x10, 570, "RCLb_Ib_EA", "sh_rot_c_i",
|
|
SELALL, 0xC000, 0x18, 571, "RCRb_Ib_EA", "sh_rot_c_i",
|
|
SELALL, 0xC100, 0x10, 578, "RCLw_Ib_EA", "sh_rot_c_i",
|
|
SELALL, 0xC100, 0x18, 579, "RCRw_Ib_EA", "sh_rot_c_i",
|
|
|
|
SELALL, 0xD200, 0x10, 618, "RCLb_CL_EA", "sh_rot_c_cl",
|
|
SELALL, 0xD200, 0x18, 619, "RCRb_CL_EA", "sh_rot_c_cl",
|
|
SELALL, 0xD300, 0x10, 626, "RCLw_CL_EA", "sh_rot_c_cl",
|
|
SELALL, 0xD300, 0x18, 627, "RCRw_CL_EA", "sh_rot_c_cl",
|
|
|
|
POINT, 0xCC00, 0, 204, "INT_3", "int",
|
|
POINT, 0xCD00, 0, 205, "INT_TYPE", "int",
|
|
POINT, 0xCE00, 0, 206, "INTO", "int",
|
|
POINT, 0xCF00, 0, 207, "IRETf", "int",
|
|
|
|
POINT, 0x9E00, 0, 158, "SAHF", "flag",
|
|
POINT, 0x9F00, 0, 159, "LAHF", "flag",
|
|
POINT, 0xF500, 0, 245, "CMC", "flag",
|
|
POINT, 0xF800, 0, 248, "CLC", "flag",
|
|
POINT, 0xF900, 0, 249, "STC", "flag",
|
|
POINT, 0xFC00, 0, 252, "CLD", "flag",
|
|
POINT, 0xFD00, 0, 253, "STD", "flag",
|
|
|
|
SELALL, 0xD800, 0x00, 688, "FADDs_EA", "fp",
|
|
SELALL, 0xD800, 0x08, 689, "FMULs_EA", "fp",
|
|
SELALL, 0xD800, 0x10, 690, "FCOMs_EA", "fp",
|
|
SELALL, 0xD800, 0x18, 691, "FCOMPs_EA", "fp",
|
|
SELALL, 0xD800, 0x20, 692, "FSUBs_EA", "fp",
|
|
SELALL, 0xD800, 0x28, 693, "FSUBRs_EA", "fp",
|
|
SELALL, 0xD800, 0x30, 694, "FDIVs_EA", "fp",
|
|
SELALL, 0xD800, 0x38, 695, "FDIVRs_EA", "fp",
|
|
|
|
SEL5, 0xD800, 0xC0, 696, "FADD_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xC8, 697, "FMUL_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xD0, 698, "FCOM_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xD8, 699, "FCOMP_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xE0, 700, "FSUB_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xE8, 701, "FSUBR_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xF0, 702, "FDIV_Si_S0", "fp",
|
|
SEL5, 0xD800, 0xF8, 703, "FDIVR_Si_S0", "fp",
|
|
|
|
SELALL, 0xDA00, 0x00, 704, "FIADDs_EA", "fp",
|
|
SELALL, 0xDA00, 0x08, 705, "FIMULs_EA", "fp",
|
|
SELALL, 0xDA00, 0x10, 706, "FICOMs_EA", "fp",
|
|
SELALL, 0xDA00, 0x18, 707, "FICOMPs_EA", "fp",
|
|
SELALL, 0xDA00, 0x20, 708, "FISUBs_EA", "fp",
|
|
SELALL, 0xDA00, 0x28, 709, "FISUBRs_EA", "fp",
|
|
SELALL, 0xDA00, 0x30, 710, "FIDIVs_EA", "fp",
|
|
SELALL, 0xDA00, 0x38, 711, "FIDIVRs_EA", "fp",
|
|
|
|
FPINVALID,0, 0, 712, "FP_INVALID", "fp",
|
|
|
|
POINT, 0xDED9, 0, 713, "FUCOMPP", "fp",
|
|
|
|
SELALL, 0xDB00, 0x00, 720, "FILDs_EA", "fp",
|
|
SELALL, 0xDB00, 0x10, 722, "FISTs_EA", "fp",
|
|
SELALL, 0xDB00, 0x18, 723, "FISTPs_EA", "fp",
|
|
SELALL, 0xDB00, 0x28, 725, "FLDer_EA", "fp",
|
|
SELALL, 0xDB00, 0x38, 727, "FSTPer_EA", "fp",
|
|
|
|
POINT, 0xDBE0, 0, 728, "FENI_1", "fp",
|
|
POINT, 0xDBE1, 0, 729, "FDISI_2", "fp",
|
|
POINT, 0xDBE2, 0, 730, "FCLEX", "fp",
|
|
POINT, 0xDBE3, 0, 731, "FINIT", "fp",
|
|
POINT, 0xDBE4, 0, 732, "FSETPM", "fp",
|
|
|
|
SELALL, 0xDC00, 0x00, 736, "FADDl_EA", "fp",
|
|
SELALL, 0xDC00, 0x08, 737, "FMULl_EA", "fp",
|
|
SELALL, 0xDC00, 0x10, 738, "FCOMl_EA", "fp",
|
|
SELALL, 0xDC00, 0x18, 739, "FCOMPl_EA", "fp",
|
|
SELALL, 0xDC00, 0x20, 740, "FSUBl_EA", "fp",
|
|
SELALL, 0xDC00, 0x28, 741, "FSUBRl_EA", "fp",
|
|
SELALL, 0xDC00, 0x30, 742, "FDIVl_EA", "fp",
|
|
SELALL, 0xDC00, 0x38, 743, "FDIVRl_EA", "fp",
|
|
|
|
SEL5, 0xDC00, 0xC0, 744, "FADD_S0_Si", "fp",
|
|
SEL5, 0xDC00, 0xC8, 745, "FMUL_S0_Si", "fp",
|
|
SEL5, 0xDC00, 0xD0, 746, "FCOM_2_S0_Si","fp",
|
|
SEL5, 0xDC00, 0xD8, 747, "FCOMP_3_S0_Si","fp",
|
|
SEL5, 0xDC00, 0xE0, 748, "FSUB_S0_Si", "fp",
|
|
SEL5, 0xDC00, 0xE8, 749, "FSUBR_S0_Si", "fp",
|
|
SEL5, 0xDC00, 0xF0, 750, "FDIV_S0_Si", "fp",
|
|
SEL5, 0xDC00, 0xF8, 751, "FDIVR_S0_Si", "fp",
|
|
|
|
SELALL, 0xDD00, 0x00, 752, "FLDl_EA", "fp",
|
|
SELALL, 0xDD00, 0x10, 754, "FSTl_EA", "fp",
|
|
SELALL, 0xDD00, 0x18, 755, "FSTPl_EA", "fp",
|
|
SELALL, 0xDD00, 0x20, 756, "FRSTOR_EA", "fp",
|
|
SELALL, 0xDD00, 0x30, 758, "FSAVE_EA", "fp",
|
|
SELALL, 0xDD00, 0x38, 759, "FSTSW_EA", "fp",
|
|
|
|
SEL5, 0xDD00, 0xC0, 760, "FFREE_Si", "fp",
|
|
SEL5, 0xDD00, 0xC8, 761, "FXCH_4_Si_S0", "fp",
|
|
SEL5, 0xDD00, 0xD0, 762, "FSTl_Si", "fp",
|
|
SEL5, 0xDD00, 0xD8, 763, "FSTPl_Si", "fp",
|
|
|
|
SELALL, 0xDE00, 0x00, 768, "FIADDw_EA", "fp",
|
|
SELALL, 0xDE00, 0x08, 769, "FIMULw_EA", "fp",
|
|
SELALL, 0xDE00, 0x10, 770, "FICOMw_EA", "fp",
|
|
SELALL, 0xDE00, 0x18, 771, "FICOMPw_EA", "fp",
|
|
SELALL, 0xDE00, 0x20, 772, "FISUBw_EA", "fp",
|
|
SELALL, 0xDE00, 0x28, 773, "FISUBRw_EA", "fp",
|
|
SELALL, 0xDE00, 0x30, 774, "FIDIVw_EA", "fp",
|
|
SELALL, 0xDE00, 0x38, 775, "FIDIVRw_EA", "fp",
|
|
|
|
SEL5, 0xDE00, 0xC0, 776, "FADDP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xC8, 777, "FMULP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xD0, 778, "FCOMP_5_Si_S0","fp",
|
|
POINT, 0xDED9, 0, 779, "FCOMPP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xE0, 780, "FSUBRP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xE8, 781, "FSUBP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xF0, 782, "FDIVRP_Si_S0", "fp",
|
|
SEL5, 0xDE00, 0xF8, 783, "FDIVP_Si_S0", "fp",
|
|
|
|
SELALL, 0xDF00, 0x00, 784, "FILDw_EA", "fp",
|
|
SELALL, 0xDF00, 0x10, 786, "FISTw_EA", "fp",
|
|
SELALL, 0xDF00, 0x18, 787, "FISTPw_EA", "fp",
|
|
SELALL, 0xDF00, 0x20, 788, "FBLD_EA", "fp",
|
|
SELALL, 0xDF00, 0x28, 789, "FILDl_EA", "fp",
|
|
SELALL, 0xDF00, 0x30, 790, "FBSTP_EA", "fp",
|
|
SELALL, 0xDF00, 0x38, 791, "FISTPl_EA", "fp",
|
|
|
|
SEL5, 0xDF00, 0xC0, 792, "FFREE_6_Si", "fp",
|
|
SEL5, 0xDF00, 0xC8, 793, "FXCH_7_S0_Si", "fp",
|
|
SEL5, 0xDF00, 0xD0, 794, "FSTP_8_Si","fp",
|
|
SEL5, 0xDF00, 0xD8, 795, "FSTP_9_Si","fp",
|
|
POINT, 0xDFE0, 0, 796, "FSTSW_AX", "fp",
|
|
|
|
SELALL, 0xD900, 0x00, 800, "FLDs_EA", "fp",
|
|
SELALL, 0xD900, 0x10, 802, "FSTs_EA", "fp",
|
|
SELALL, 0xD900, 0x18, 803, "FSTPs_EA", "fp",
|
|
SELALL, 0xD900, 0x20, 804, "FLDENV_EA", "fp",
|
|
SELALL, 0xD900, 0x28, 805, "FLDCW_EA", "fp",
|
|
SELALL, 0xD900, 0x30, 806, "FSTENV_EA", "fp",
|
|
SELALL, 0xD900, 0x38, 807, "FSTCW_EA", "fp",
|
|
|
|
SEL5, 0xD900, 0xC0, 808, "FLD_Si", "fp",
|
|
SEL5, 0xD900, 0xC8, 809, "FXCH_Si_S0", "fp",
|
|
POINT, 0xD9D0, 0, 810, "FNOP", "fp",
|
|
SEL5, 0xD900, 0xD8, 811, "FSTP_1_Si", "fp",
|
|
POINT, 0xD9E0, 0, 812, "FCHS", "fp",
|
|
POINT, 0xD9E1, 0, 813, "FABS", "fp",
|
|
POINT, 0xD9E4, 0, 814, "FTST", "fp",
|
|
POINT, 0xD9E5, 0, 815, "FXAM", "fp",
|
|
POINT, 0xD9E8, 0, 816, "FLD1", "fp",
|
|
POINT, 0xD9E9, 0, 817, "FLDL2T", "fp",
|
|
POINT, 0xD9EA, 0, 818, "FLDL2E", "fp",
|
|
POINT, 0xD9EB, 0, 819, "FLDLPI", "fp",
|
|
POINT, 0xD9EC, 0, 820, "FLDLG2", "fp",
|
|
POINT, 0xD9ED, 0, 821, "FLDLN2", "fp",
|
|
POINT, 0xD9EE, 0, 822, "FLDZ", "fp",
|
|
POINT, 0xD9F0, 0, 824, "F2XM1", "fp",
|
|
POINT, 0xD9F1, 0, 825, "FYL2X", "fp",
|
|
POINT, 0xD9F2, 0, 826, "FPTAN", "fp",
|
|
POINT, 0xD9F3, 0, 827, "FPATAN", "fp",
|
|
POINT, 0xD9F4, 0, 828, "FXTRACT", "fp",
|
|
POINT, 0xD9F5, 0, 829, "FPREM1", "fp",
|
|
POINT, 0xD9F6, 0, 830, "FDECSTP", "fp",
|
|
POINT, 0xD9F7, 0, 831, "FINCSTP", "fp",
|
|
POINT, 0xD9F8, 0, 832, "FPREM", "fp",
|
|
POINT, 0xD9F9, 0, 833, "FYL2XP1", "fp",
|
|
POINT, 0xD9FA, 0, 834, "FSQRT", "fp",
|
|
POINT, 0xD9FB, 0, 835, "FSINCOS", "fp",
|
|
POINT, 0xD9FC, 0, 836, "FRNDINT", "fp",
|
|
POINT, 0xD9FD, 0, 837, "F_SCALE", "fp",
|
|
POINT, 0xD9FE, 0, 838, "FSIN", "fp",
|
|
POINT, 0xD9FF, 0, 839, "FCOS", "fp",
|
|
|
|
POINT, 0x9B00, 0, 155, "FWAIT", "fwait",
|
|
|
|
POINT, 0xA400, 0, 164, "MOVSb", "movs",
|
|
POINT, 0xA500, 0, 165, "MOVSw", "movs",
|
|
|
|
POINT, 0xA600, 0, 166, "CMPSb", "cmps",
|
|
POINT, 0xA700, 0, 167, "CMPSw", "cmps",
|
|
|
|
POINT, 0xAE00, 0, 174, "SCASb", "scas",
|
|
POINT, 0xAF00, 0, 175, "SCASw", "scas",
|
|
|
|
POINT, 0xAA00, 0, 170, "STOSb", "stos",
|
|
POINT, 0xAB00, 0, 171, "STOSw", "stos",
|
|
|
|
POINT, 0xAC00, 0, 172, "LODSb", "lods",
|
|
POINT, 0xAD00, 0, 173, "LODSw", "lods",
|
|
|
|
POINT, 0x6C00, 0, 108, "INSb", "ins",
|
|
POINT, 0x6D00, 0, 109, "INSw", "ins",
|
|
|
|
POINT, 0x6E00, 0, 110, "OUTSb", "outs",
|
|
POINT, 0x6F00, 0, 111, "OUTSw", "outs",
|
|
|
|
POINT, 0xD700, 0, 215, "XLATb", "xlat",
|
|
|
|
POINT, 0xEA00, 0, 234, "JMPf_Ip", "jmp_far",
|
|
|
|
POINT, 0x9A00, 0, 154, "CALLf_Ip", "call_far",
|
|
|
|
POINT, 0xCA00, 0, 202, "RETf_Is", "ret_far",
|
|
POINT, 0xCB00, 0, 203, "RETf", "ret_far",
|
|
|
|
SELMEM, 0xFF00, 0x28, 661, "JMPf_EA", "jmp_far_in",
|
|
|
|
SELMEM, 0xFF00, 0x18, 659, "CALLf_EA", "call_far_in",
|
|
|
|
POINT, 0x0600, 0, 6, "PUSH_ES", "push_s",
|
|
POINT, 0x0E00, 0, 14, "PUSH_CS", "push_s",
|
|
POINT, 0x1600, 0, 22, "PUSH_SS", "push_s",
|
|
POINT, 0x1E00, 0, 30, "PUSH_DS", "push_s",
|
|
|
|
POINT, 0x0700, 0, 6, "POP_ES", "pop_s",
|
|
POINT, 0x1700, 0, 22, "POP_SS", "pop_s",
|
|
POINT, 0x1F00, 0, 30, "POP_DS", "pop_s",
|
|
|
|
SELREG, 0x8C00, 0x00, 544, "MOVw_ES_EA", "mov_s,r",
|
|
SELREG, 0x8C00, 0x08, 545, "MOVw_CS_EA", "mov_s,r",
|
|
SELREG, 0x8C00, 0x10, 546, "MOVw_SS_EA", "mov_s,r",
|
|
SELREG, 0x8C00, 0x18, 547, "MOVw_DS_EA", "mov_s,r",
|
|
|
|
SELREG, 0x8E00, 0x00, 552, "MOVw_EA_ES", "mov_r,s",
|
|
SELREG, 0x8E00, 0x10, 554, "MOVw_EA_SS", "mov_r,s",
|
|
SELREG, 0x8E00, 0x18, 555, "MOVw_EA_DS", "mov_r,s",
|
|
|
|
SELMEM, 0x8E00, 0x00, 552, "MOVw_EA_ES", "mov_m,s",
|
|
SELMEM, 0x8E00, 0x10, 554, "MOVw_EA_SS", "mov_m,s",
|
|
SELMEM, 0x8E00, 0x18, 555, "MOVw_EA_DS", "mov_m,s",
|
|
|
|
SELMEM, 0x8C00, 0x00, 999, "MOVw_ES_EA", "mov_s,m",
|
|
SELMEM, 0x8C00, 0x08, 999, "MOVw_CS_EA", "mov_s,m",
|
|
SELMEM, 0x8C00, 0x10, 999, "MOVw_SS_EA", "mov_s,m",
|
|
SELMEM, 0x8C00, 0x18, 999, "MOVw_DS_EA", "mov_s,m",
|
|
|
|
ALLMEM, 0xC400, 0, 196, "LESw_EA_R", "mov_m,p",
|
|
ALLMEM, 0xC500, 0, 197, "LDSw_EA_R", "mov_m,p",
|
|
|
|
POINT, 0xC800, 0, 200, "ENTER", "enter",
|
|
POINT, 0xC900, 0, 201, "LEAVE", "leave",
|
|
|
|
POINT, 0xE400, 0, 228, "INb_Ib_AL", "io",
|
|
POINT, 0xE500, 0, 229, "INw_Iw_AX", "io",
|
|
POINT, 0xE600, 0, 230, "OUTb_Ib_AL", "io",
|
|
POINT, 0xE700, 0, 231, "OUTw_Iw_AX", "io",
|
|
POINT, 0xEC00, 0, 236, "INb_DX_AL", "io",
|
|
POINT, 0xED00, 0, 237, "INw_DX_AX", "io",
|
|
POINT, 0xEE00, 0, 238, "OUTb_DX_AL", "io",
|
|
POINT, 0xEF00, 0, 239, "OUTw_DX_AX", "io",
|
|
|
|
POINT, 0x9C00, 0, 156, "PUSHF", "VM_sensitive",
|
|
POINT, 0x9D00, 0, 157, "POPF", "VM_sensitive",
|
|
POINT, 0xFA00, 0, 250, "CLI", "VM_sensitive",
|
|
POINT, 0xFB00, 0, 251, "STI", "VM_sensitive",
|
|
|
|
ES_PREFIX,0, 0, 38, "ES_prefix", "other86",
|
|
DS_PREFIX,0, 0, 46, "DS_prefix", "other86",
|
|
SS_PREFIX,0, 0, 54, "SS_prefix", "other86",
|
|
CS_PREFIX,0, 0, 62, "CS_prefix", "other86",
|
|
POINT, 0x6000, 0, 96, "PUSHA", "other86",
|
|
POINT, 0x6100, 0, 97, "POPA", "other86",
|
|
ALLMEM, 0x6200, 0, 98, "BOUND", "other86",
|
|
|
|
POINT, 0x6300, 0, 99, "ARPL", "other286",
|
|
|
|
USE_ZEROF,0, 0, 0, "", "",
|
|
|
|
ALL, 0x0200, 0, 258, "LARw_EA_R", "other286",
|
|
ALL, 0x0300, 0, 259, "LSLw_EA_R", "other286",
|
|
ALL, 0x0600, 0, 262, "CLTS", "other286",
|
|
SELALL, 0x0000, 0x00, 664, "SLDTw_EA", "other286",
|
|
SELALL, 0x0000, 0x08, 665, "STRw_EA", "other286",
|
|
SELALL, 0x0000, 0x10, 666, "LLDTw_EA", "other286",
|
|
SELALL, 0x0000, 0x18, 667, "LTRw_EA", "other286",
|
|
SELALL, 0x0000, 0x20, 668, "VERRw_EA", "other286",
|
|
SELALL, 0x0000, 0x28, 669, "VERWw_EA", "other286",
|
|
SELALL, 0x0100, 0x00, 672, "SGDTw_EA", "other286",
|
|
SELALL, 0x0100, 0x08, 673, "SIDTw_EA", "other286",
|
|
SELALL, 0x0100, 0x10, 674, "LGDTw_EA", "other286",
|
|
SELALL, 0x0100, 0x18, 675, "LIDTw_EA", "other286",
|
|
SELALL, 0x0100, 0x20, 676, "SMSWw_EA", "other286",
|
|
SELALL, 0x0100, 0x30, 678, "LMSWw_EA", "other286",
|
|
ALL, 0x0500, 0, 999, "LOADALL", "other286",
|
|
|
|
USE_NORMAL,0, 0, 0, "", "",
|
|
|
|
RANGE, 0x7000, 0x7001, 112, "JO_Ib", ".jcc",
|
|
RANGE, 0x7100, 0x7101, 113, "JNO_Ib", ".jcc",
|
|
RANGE, 0x7200, 0x7201, 114, "JC_Ib", ".jcc",
|
|
RANGE, 0x7300, 0x7301, 115, "JNC_Ib", ".jcc",
|
|
RANGE, 0x7400, 0x7401, 116, "JZ_Ib", ".jcc",
|
|
RANGE, 0x7500, 0x7501, 117, "JNZ_Ib", ".jcc",
|
|
RANGE, 0x7600, 0x7601, 118, "JBE_Ib", ".jcc",
|
|
RANGE, 0x7700, 0x7701, 119, "JNBE_Ib", ".jcc",
|
|
RANGE, 0x7800, 0x7801, 120, "JS_Ib", ".jcc",
|
|
RANGE, 0x7900, 0x7901, 121, "JNS_Ib", ".jcc",
|
|
RANGE, 0x7A00, 0x7A01, 122, "JP_Ib", ".jcc",
|
|
RANGE, 0x7B00, 0x7B01, 123, "JNP_Ib", ".jcc",
|
|
RANGE, 0x7C00, 0x7C01, 124, "JL_Ib", ".jcc",
|
|
RANGE, 0x7D00, 0x7D01, 125, "JNL_Ib", ".jcc",
|
|
RANGE, 0x7E00, 0x7E01, 126, "JLE_Ib", ".jcc",
|
|
RANGE, 0x7F00, 0x7F01, 127, "JNLE_Ib", ".jcc",
|
|
|
|
RANGE, 0xE000, 0xE001, 224, "LOOPNZb_Ib", ".loop",
|
|
RANGE, 0xE100, 0xE101, 225, "LOOPNb_Ib", ".loop",
|
|
RANGE, 0xE200, 0xE201, 226, "LOOP_Ib", ".loop",
|
|
RANGE, 0xE300, 0xE301, 227, "JCXZb_Ib", ".loop",
|
|
|
|
POINT, 0x9A00, 0, 154, "CALLf_Ip", ".genT",
|
|
POINT, 0xC200, 0, 194, "RET_Is", ".genT",
|
|
POINT, 0xC300, 0, 195, "RETn", ".genT",
|
|
POINT, 0xCA00, 0, 202, "RETf_Is", ".genT",
|
|
POINT, 0xCB00, 0, 203, "RETf", ".genT",
|
|
POINT, 0xCC00, 0, 204, "INT_3", ".genT",
|
|
POINT, 0xCD00, 0, 205, "INT_TYPE", ".genT",
|
|
POINT, 0xCE00, 0, 206, "INTO", ".genT",
|
|
POINT, 0xCF00, 0, 207, "IRETf", ".genT",
|
|
POINT, 0xE800, 0, 232, "CALLn_Iw", ".genT",
|
|
POINT, 0xE900, 0xE900, 233, "JMPn_Iw", ".genT",
|
|
POINT, 0xEA00, 0, 234, "JMPf_Ip", ".genT",
|
|
POINT, 0xEB00, 0xEB00, 235, "JMPn_Ib", ".genT",
|
|
SELALL, 0xFF00, 0x10, 658, "CALLn_EA", ".genT",
|
|
SELMEM, 0xFF00, 0x18, 659, "CALLf_EA", ".genT",
|
|
SELALL, 0xFF00, 0x20, 660, "JMPn_EA", ".genT",
|
|
SELMEM, 0xFF00, 0x28, 661, "JMPf_EA", ".genT",
|
|
|
|
0, 0, 0, 0, "", ""};
|
|
|
|
LOCAL print_stats IFN0()
|
|
{
|
|
ULONG i, j, total, sub_total, super_total, command, from, to, item;
|
|
char *group;
|
|
ULONG *counts_array;
|
|
|
|
previous_group = "";
|
|
counts_array = &instr_counts[0];
|
|
item = 0;
|
|
total = 0;
|
|
super_total = 0;
|
|
while (commands[item].command != 0)
|
|
{
|
|
command = commands[item].command;
|
|
from = commands[item].from;
|
|
to = commands[item].to;
|
|
group = commands[item].group;
|
|
switch (command)
|
|
{
|
|
case USE_NORMAL:
|
|
counts_array = &instr_counts[0];
|
|
break;
|
|
|
|
case USE_ZEROF:
|
|
counts_array = &zerof_instr_counts[0];
|
|
break;
|
|
|
|
case RANGE:
|
|
sub_total = 0;
|
|
for (i = from; i <= to; i++)
|
|
sub_total += counts_array[i];
|
|
break;
|
|
|
|
case ES_PREFIX:
|
|
sub_total = es_prefixes;
|
|
break;
|
|
|
|
case CS_PREFIX:
|
|
sub_total = cs_prefixes;
|
|
break;
|
|
|
|
case SS_PREFIX:
|
|
sub_total = ss_prefixes;
|
|
break;
|
|
|
|
case DS_PREFIX:
|
|
sub_total = ds_prefixes;
|
|
break;
|
|
|
|
case LOCK:
|
|
sub_total = lock_prefixes;
|
|
break;
|
|
|
|
case REPNZ:
|
|
sub_total = repe_prefixes;
|
|
break;
|
|
|
|
case REP:
|
|
sub_total = rep_prefixes;
|
|
break;
|
|
|
|
case POINT:
|
|
sub_total = counts_array[from];
|
|
break;
|
|
|
|
case SELMEM:
|
|
sub_total = 0;
|
|
for (i = 0; i < 192; i++)
|
|
if ((i & 0x38) == to)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case ALLMEM:
|
|
sub_total = 0;
|
|
for (i = 0; i < 192; i++)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case SELREG:
|
|
sub_total = 0;
|
|
for (i = 192; i < 256; i++)
|
|
if ((i & 0x38) == to)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case SELALL:
|
|
sub_total = 0;
|
|
for (i = 0; i < 256; i++)
|
|
if ((i & 0x38) == to)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case SEL5:
|
|
sub_total = 0;
|
|
for (i = 0; i < 256; i++)
|
|
if ((i & 0xF8) == to)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case ALLREG:
|
|
sub_total = 0;
|
|
for (i = 192; i < 256; i++)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case ALL:
|
|
sub_total = 0;
|
|
for (i = 0; i < 256; i++)
|
|
sub_total += counts_array[from + i];
|
|
break;
|
|
|
|
case FPINVALID:
|
|
sub_total = 0;
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown command\n");
|
|
}
|
|
|
|
#if 0
|
|
switch (command)
|
|
{
|
|
case RANGE:
|
|
for (i = from; i <= to; i++)
|
|
counts_array[i] = 0;
|
|
break;
|
|
|
|
case POINT:
|
|
counts_array[from] = 0;
|
|
break;
|
|
|
|
case SELMEM:
|
|
for (i = 0; i < 192; i++)
|
|
if ((i & 0x38) == to)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case ALLMEM:
|
|
for (i = 0; i < 192; i++)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case SELREG:
|
|
for (i = 192; i < 256; i++)
|
|
if ((i & 0x38) == to)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case SELALL:
|
|
for (i = 0; i < 256; i++)
|
|
if ((i & 0x38) == to)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case SEL5:
|
|
for (i = 0; i < 256; i++)
|
|
if ((i & 0xF8) == to)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case ALLREG:
|
|
for (i = 192; i < 256; i++)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
case ALL:
|
|
for (i = 0; i < 256; i++)
|
|
counts_array[from + i] = 0;
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown command\n");
|
|
}
|
|
#endif
|
|
|
|
if (command != USE_NORMAL && command != USE_ZEROF)
|
|
{
|
|
if (strcmp(group, previous_group) != 0)
|
|
{
|
|
if (item != 0)
|
|
fprintf(stats_file, "%s TOTAL = %d\n", previous_group, total);
|
|
super_total += total;
|
|
total = 0;
|
|
fprintf(stats_file, "\n%s\n", group);
|
|
previous_group = group;
|
|
}
|
|
total += sub_total;
|
|
fprintf(stats_file,"\t%d\t%-20s%d\n", commands[item].number,
|
|
commands[item].string,
|
|
sub_total);
|
|
}
|
|
|
|
item++;
|
|
}
|
|
fprintf(stats_file,"%s TOTAL = %d\n", previous_group, total);
|
|
fprintf(stats_file,"\nGRAND TOTAL = %d\n", super_total);
|
|
|
|
#if 0
|
|
for (i = 0; i < 0x10000; i++)
|
|
{
|
|
if (instr_counts[i])
|
|
printf("%d normals at %x\n", instr_counts[i], i);
|
|
if (zerof_instr_counts[i])
|
|
printf("%d zerofs at %x\n", zerof_instr_counts[i], i);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCAL char stats_file_name[20];
|
|
LOCAL ULONG stats_file_number;
|
|
|
|
GLOBAL start_pclabs IFN0()
|
|
{
|
|
IMPORT int tick_multiple;
|
|
do_condition_checks = 1;
|
|
tick_multiple = 10;
|
|
clear_stats();
|
|
sprintf(&stats_file_name[0], "stats.%d", ++stats_file_number);
|
|
stats_file = fopen(&stats_file_name[0], "w");
|
|
}
|
|
|
|
|
|
GLOBAL print_pclabs IFN0()
|
|
{
|
|
IMPORT int tick_multiple;
|
|
do_condition_checks = 0;
|
|
tick_multiple = 0;
|
|
print_stats();
|
|
fclose(stats_file);
|
|
}
|
|
|
|
#endif /* PCLABS STATS */
|
|
|
|
/* extra functions called in FmDebug.c which support suspension and resumption
|
|
of a separate filter process. BCN 3406 */
|
|
GLOBAL yoda_suspend_filter_process IFN0 ()
|
|
{
|
|
#ifdef host_suspend_filter_process
|
|
host_suspend_filter_process();
|
|
#endif
|
|
}
|
|
|
|
GLOBAL yoda_resume_filter_process IFN0 ()
|
|
{
|
|
#ifdef host_resume_filter_process
|
|
host_resume_filter_process();
|
|
#endif
|
|
}
|
|
|
|
GLOBAL yoda_kill_filter_process IFN0 ()
|
|
{
|
|
#ifdef host_kill_filter_process
|
|
host_kill_filter_process();
|
|
#endif
|
|
}
|
|
#endif /* YODA */
|