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.
395 lines
8.7 KiB
395 lines
8.7 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*[
|
|
Name: illegal_op.c
|
|
Derived From: Base 2.0
|
|
Author: William Gulland
|
|
Created On: Unknown
|
|
Sccs ID: @(#)illegal_op.c 1.19 07/04/95
|
|
Notes: Called from the CPU.
|
|
Purpose: The CPU has encountered an illegal op code.
|
|
|
|
(c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
|
|
|
|
]*/
|
|
|
|
#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 "SOFTPC_ERROR.seg"
|
|
#endif
|
|
|
|
|
|
/*
|
|
* O/S include files.
|
|
*/
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
|
|
/*
|
|
* SoftPC include files
|
|
*/
|
|
#include "xt.h"
|
|
#include "sas.h"
|
|
#include CpuH
|
|
#include "bios.h"
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "debug.h"
|
|
#include "yoda.h"
|
|
|
|
#ifndef PROD
|
|
IU32 IntelMsgDest = IM_DST_TRACE;
|
|
#endif
|
|
|
|
/* Routine to produce human readable form of where an illegal instruction occured */
|
|
LOCAL VOID where IFN3(CHAR *, string, word, cs, LIN_ADDR, ip)
|
|
{
|
|
double_word ea = effective_addr(cs, ip);
|
|
|
|
sprintf(string,
|
|
#ifdef PROD
|
|
"CS:%04x IP:%04x OP:%02x %02x %02x %02x %02x",
|
|
#else /* PROD */
|
|
"CS:IP %04x:%04x OP:%02x %02x %02x %02x %02x",
|
|
#endif /* PROD */
|
|
cs, ip,
|
|
sas_hw_at(ea), sas_hw_at(ea+1), sas_hw_at(ea+2),
|
|
sas_hw_at(ea+3),sas_hw_at(ea+4));
|
|
}
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
#define GetInstructionPointer() getEIP()
|
|
#endif
|
|
|
|
|
|
void illegal_op()
|
|
{
|
|
#ifndef PROD
|
|
CHAR string[100];
|
|
|
|
where(string, getCS(), GetInstructionPointer());
|
|
host_error(EG_BAD_OP, ERR_QU_CO_RE, string);
|
|
#endif
|
|
}
|
|
|
|
void illegal_op_int()
|
|
{
|
|
CHAR string[100];
|
|
word cs, ip;
|
|
|
|
#ifdef NTVDM
|
|
UCHAR opcode;
|
|
double_word ea;
|
|
#endif
|
|
|
|
/* the cs and ip of the faulting instruction should be on the top of the stack */
|
|
sys_addr stack;
|
|
|
|
stack=effective_addr(getSS(),getESP());
|
|
|
|
ip = sas_hw_at(stack) + (sas_hw_at(stack+1)<<8);
|
|
cs = sas_hw_at(stack+2) + (sas_hw_at(stack+3)<<8);
|
|
|
|
where(string, cs, ip);
|
|
|
|
#ifndef NTVDM
|
|
#ifdef PROD
|
|
host_error(EG_BAD_OP, ERR_QU_CO_RE, string);
|
|
#else /* PROD */
|
|
assert1( NO, "Illegal instruction\n%s\n", string );
|
|
force_yoda();
|
|
#endif /* PROD */
|
|
|
|
#else /* NTVDM */
|
|
#ifdef PROD
|
|
#if define(MONITOR) || define(CPU_40_STYLE)
|
|
host_error(EG_BAD_OP, ERR_QU_CO_RE, string);
|
|
#else
|
|
ea = effective_addr(cs, ip);
|
|
opcode = sas_hw_at(ea);
|
|
if (opcode == 0x66 || opcode == 0x67)
|
|
host_error(EG_BAD_OP386, ERR_QU_CO_RE, string);
|
|
else
|
|
host_error(EG_BAD_OP, ERR_QU_CO_RE, string);
|
|
#endif /* MONITOR */
|
|
#endif /* PROD */
|
|
#endif /* NTVDM */
|
|
|
|
|
|
|
|
/* the user has requested a `continue` */
|
|
/* we don't know how many bytes this instr should be, so guess 1 */
|
|
if (ip == 0xffff) {
|
|
cs ++;
|
|
sas_store (stack+2, cs & 0xff);
|
|
sas_store (stack+3, (cs >> 8) & 0xff);
|
|
}
|
|
ip ++;
|
|
sas_store (stack , ip & 0xff);
|
|
sas_store (stack+1, (ip >> 8) & 0xff);
|
|
unexpected_int();
|
|
}
|
|
|
|
|
|
void illegal_dvr_bop IFN0()
|
|
{
|
|
#ifndef NTVDM
|
|
sys_addr bop_addr;
|
|
CHAR buf[256];
|
|
|
|
/* This is called when an Insignia Intel driver decides that
|
|
* this (old) SoftWindows is not compatible.
|
|
*
|
|
* We should:
|
|
* a) Put up a localised panel complaining that
|
|
* the named driver CS:[eIP] with decimal
|
|
* version AX is incompatible with the SoftWindows.
|
|
* N.B. The most compatible way to pass the
|
|
* name of the driver is by embedded bytes just
|
|
* after the BOP. The problem is caused by the
|
|
* fact that the driver may be either 16-bit RM
|
|
* or a 32-bit flat VxD so the address of the
|
|
* string can be either 16/32 bits, and we
|
|
* need to be able to execute (and do nothing)
|
|
* on the shipping SoftPC 1.xx which prevents
|
|
* us doing anything with 32-bit registers!
|
|
*
|
|
* BOP driver_incompat
|
|
* jmp SHORT over_name
|
|
* db 'somename.drv', 0
|
|
* over_name:
|
|
*
|
|
* b) setCF(0)
|
|
*/
|
|
|
|
buf[0] = '\0';
|
|
bop_addr = effective_addr(getCS(), GetInstructionPointer());
|
|
if (sas_hw_at(bop_addr) == 0xEB)
|
|
{
|
|
IU8 data;
|
|
char *p;
|
|
|
|
p = buf;
|
|
bop_addr += 2; /* Skip the xEB xXX */
|
|
do {
|
|
data = sas_hw_at(bop_addr++);
|
|
*p++ = data;
|
|
} while (data != 0);
|
|
sprintf(p-1, " v%d.%02d", getAX() / 100, getAX() % 100);
|
|
}
|
|
host_error(EG_DRIVER_MISMATCH, ERR_CONT, buf);
|
|
setCF(0);
|
|
#endif /* ! NTVDM */
|
|
}
|
|
|
|
|
|
#ifndef PROD
|
|
LOCAL void print_msg IPT1( IU32, ofs );
|
|
|
|
void dvr_bop_trace IFN0()
|
|
{
|
|
sys_addr bop_addr;
|
|
|
|
/*
|
|
* BOP driver_incompat
|
|
* jmp SHORT over_name
|
|
* db 'somename.drv', 0
|
|
* over_name:
|
|
*
|
|
*/
|
|
|
|
bop_addr = effective_addr(getCS(), GetInstructionPointer());
|
|
if (sas_hw_at(bop_addr) == 0xEB)
|
|
{
|
|
print_msg(bop_addr+2); /* Skip the xEB xXX */
|
|
}
|
|
}
|
|
|
|
GLOBAL void trace_msg_bop IFN0()
|
|
{
|
|
sys_addr ea, ofs;
|
|
|
|
/*
|
|
Stack frame expected:
|
|
N.B. VxDs lives in a flat segment, (mostly) protected mode world!
|
|
This code expects the address to have been converted to a base-0
|
|
linear address already.
|
|
|
|
| |
|
|
--------------
|
|
| 4 byte |
|
|
ESP--> | eff. addr |
|
|
--------------
|
|
*/
|
|
|
|
if (sas_hw_at(BIOS_VIRTUALISING_BYTE) != 0)
|
|
fprintf(trace_file, "** WARNING ** Virtual byte non-zero\n");
|
|
|
|
ea = getESP();
|
|
ea = effective_addr(getSS(), ea);
|
|
ofs = sas_dw_at_no_check(ea);
|
|
print_msg(ofs);
|
|
}
|
|
|
|
LOCAL void print_msg IFN1( IU32, ofs )
|
|
{
|
|
SAVED IBOOL start_buffer = TRUE;
|
|
SAVED char string[164], *p = NULL;
|
|
char finalStr[180];
|
|
IU32 res, width;
|
|
|
|
if (start_buffer)
|
|
{
|
|
memset(string, 0, sizeof(string));
|
|
p = string;
|
|
start_buffer = FALSE;
|
|
}
|
|
|
|
do
|
|
{
|
|
/* do things which must be done at the start of a line. */
|
|
*p = sas_hw_at(ofs++);
|
|
if (*p == '#')
|
|
{
|
|
/* found poss reg. sequence in string */
|
|
|
|
p++;
|
|
p[0] = sas_hw_at(ofs);
|
|
if (('A' <= p[0]) && (p[0] <= 'Z'))
|
|
p[0] += 'a' - 'A';
|
|
p[1] = sas_hw_at(ofs+1);
|
|
if (('A' <= p[1]) && (p[1] <= 'Z'))
|
|
p[1] += 'a' - 'A';
|
|
if (p[0] == 'e')
|
|
{
|
|
/* may be esp, esi, eax, etc... */
|
|
|
|
p[2] = sas_hw_at(ofs+2);
|
|
if (('A' <= p[2]) && (p[2] <= 'Z'))
|
|
p[2] += 'a' - 'A';
|
|
p[3] = '\0';
|
|
width = 8;
|
|
}
|
|
else
|
|
{
|
|
/* If not eXX then can only be two letters long */
|
|
p[2] = '\0';
|
|
width = 4;
|
|
}
|
|
|
|
if (strcmp(p, "al") == 0)
|
|
{ res = getAL(); width = 2; }
|
|
else if (strcmp(p, "ah") == 0)
|
|
{ res = getAH(); width = 2; }
|
|
else if (strcmp(p, "bl") == 0)
|
|
{ res = getBL(); width = 2; }
|
|
else if (strcmp(p, "bh") == 0)
|
|
{ res = getBH(); width = 2; }
|
|
else if (strcmp(p, "cl") == 0)
|
|
{ res = getCL(); width = 2; }
|
|
else if (strcmp(p, "ch") == 0)
|
|
{ res = getCH(); width = 2; }
|
|
else if (strcmp(p, "dl") == 0)
|
|
{ res = getDL(); width = 2; }
|
|
else if (strcmp(p, "dh") == 0)
|
|
{ res = getDH(); width = 2; }
|
|
else if (strcmp(p, "ax") == 0)
|
|
res = getAX();
|
|
else if (strcmp(p, "bx") == 0)
|
|
res = getBX();
|
|
else if (strcmp(p, "cx") == 0)
|
|
res = getCX();
|
|
else if (strcmp(p, "dx") == 0)
|
|
res = getDX();
|
|
else if (strcmp(p, "si") == 0)
|
|
res = getSI();
|
|
else if (strcmp(p, "di") == 0)
|
|
res = getDI();
|
|
else if (strcmp(p, "sp") == 0)
|
|
res = getSP();
|
|
else if (strcmp(p, "bp") == 0)
|
|
res = getBP();
|
|
else if (strcmp(p, "eax") == 0)
|
|
res = getEAX();
|
|
else if (strcmp(p, "ebx") == 0)
|
|
res = getEBX();
|
|
else if (strcmp(p, "ecx") == 0)
|
|
res = getECX();
|
|
else if (strcmp(p, "edx") == 0)
|
|
res = getEDX();
|
|
else if (strcmp(p, "esi") == 0)
|
|
res = getESI();
|
|
else if (strcmp(p, "edi") == 0)
|
|
res = getEDI();
|
|
else if (strcmp(p, "esp") == 0)
|
|
res = getESP();
|
|
else if (strcmp(p, "ebp") == 0)
|
|
res = getEBP();
|
|
else if (strcmp(p, "cs") == 0)
|
|
res = getCS();
|
|
else if (strcmp(p, "ds") == 0)
|
|
res = getDS();
|
|
else if (strncmp(p, "es", 2) == 0)
|
|
{ res = getES(); width = 4; p[2] = '\0'; }
|
|
else if (strcmp(p, "fs") == 0)
|
|
res = getFS();
|
|
else if (strcmp(p, "gs") == 0)
|
|
res = getGS();
|
|
else if (strcmp(p, "fl") == 0)
|
|
res = getFLAGS();
|
|
else if (strcmp(p, "efl") == 0)
|
|
res = getEFLAGS();
|
|
else
|
|
*p = '\0'; /* else just write the '#' */
|
|
if (*p)
|
|
{
|
|
/* Overwrite the "#xx" with it's value */
|
|
|
|
ofs += (p[2] ? 3: 2);
|
|
p--;
|
|
if (width == 8)
|
|
sprintf(p, "%08x", res);
|
|
else if (width == 4)
|
|
sprintf(p, "%04x", res);
|
|
else
|
|
sprintf(p, "%02x", res);
|
|
p += strlen(p);
|
|
}
|
|
}
|
|
else if (*p != '\r') /* ignore CR's */
|
|
{
|
|
if (*p == '\n' || (p - string >= (sizeof(string) - 4)))
|
|
{
|
|
p[1] = '\0';
|
|
sprintf(finalStr, "intel msg at %04x:%04x : %s",
|
|
getCS(), GetInstructionPointer(), string);
|
|
#ifdef CPU_40_STYLE
|
|
if (IntelMsgDest & IM_DST_TRACE)
|
|
{
|
|
fprintf(trace_file, finalStr);
|
|
}
|
|
#ifndef CCPU
|
|
if (IntelMsgDest & IM_DST_RING)
|
|
{
|
|
AddToTraceXBuffer( ((GLOBAL_TraceVectorSize - 2) << 4) + 0,
|
|
finalStr );
|
|
}
|
|
#endif /* CCPU */
|
|
#else /* CPU_40_STYLE */
|
|
fprintf(trace_file, finalStr);
|
|
#endif /* CPU_40_STYLE */
|
|
memset(string, 0, sizeof(string));
|
|
p = string;
|
|
}
|
|
else if (*p == '\0') /* no more - stop */
|
|
break;
|
|
else
|
|
p++;
|
|
}
|
|
} while ((p - string) < sizeof(string) - 4);
|
|
}
|
|
#endif /* ! PROD */
|