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.
652 lines
13 KiB
652 lines
13 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Revision 3.0
|
|
*
|
|
* Title : Global variable definitions
|
|
*
|
|
* Description : Contains definitions for registers and general
|
|
* variables required by all modules.
|
|
*
|
|
* Author : Henry Nash
|
|
*
|
|
* Notes : None
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* static char SccsID[]="@(#)xt.c 1.22 01/23/95 Copyright Insignia Solutions Ltd.";
|
|
*/
|
|
|
|
|
|
/*
|
|
* O/S include files.
|
|
*/
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
|
|
/*
|
|
* SoftPC include files
|
|
*/
|
|
#include "xt.h"
|
|
#include CpuH
|
|
#include "sas.h"
|
|
|
|
/*
|
|
* ============================================================================
|
|
* Global data
|
|
* ============================================================================
|
|
*/
|
|
|
|
/*
|
|
specific CPU variables.
|
|
*/
|
|
word cpu_interrupt_map; /* Bit map of ints outstanding */
|
|
|
|
half_word cpu_int_translate[16]; /* this will go very soon! */
|
|
/*
|
|
*
|
|
* The current usage is:
|
|
*
|
|
* 0 - Hardware interrupt
|
|
* 1-7 - Not Used
|
|
* 8 - Software Int - set by cpu_sw_interrupt() - REMOVED!
|
|
* 9 - Trap
|
|
* 10 - Reset IP after a POP/MOV CS.
|
|
* 11 - Trap flag changed - this has delay.
|
|
* 12-15 - Not Used
|
|
*/
|
|
|
|
word cpu_int_delay; /* Delay before pending interrupt */
|
|
|
|
int trap_delay_count;
|
|
|
|
/*
|
|
* The lock flag prevents the Interrupt Controller Adapter from being
|
|
* called from a signal handler while it is already active in the mainline.
|
|
*/
|
|
|
|
half_word ica_lock;
|
|
|
|
/*
|
|
* The actual CCPU registers
|
|
*/
|
|
|
|
#if defined(CCPU) && !defined(CPU_30_STYLE)
|
|
#ifndef MAC_LIKE
|
|
reg A; /* Accumulator */
|
|
reg B; /* Base */
|
|
reg C; /* Count */
|
|
reg D; /* Data */
|
|
reg BP; /* Base pointer */
|
|
reg SI; /* Source Index */
|
|
reg DI; /* Destination Index */
|
|
#endif /* MAC_LIKE */
|
|
reg SP; /* Stack Pointer */
|
|
|
|
reg IP; /* Instruction Pointer */
|
|
|
|
reg CS; /* Code Segment */
|
|
reg DS; /* Data Segment */
|
|
reg SS; /* Stack Segment */
|
|
reg ES; /* Extra Segment */
|
|
|
|
/* Code Segment Register */
|
|
half_word CS_AR; /* Access Rights Byte */
|
|
sys_addr CS_base; /* Base Address */
|
|
word CS_limit; /* Segment 'size' */
|
|
int CPL; /* Current Privilege Level */
|
|
|
|
/* Data Segment Register */
|
|
half_word DS_AR; /* Access Rights Byte */
|
|
sys_addr DS_base; /* Base Address */
|
|
word DS_limit; /* Segment 'size' */
|
|
|
|
/* Stack Segment Register */
|
|
half_word SS_AR; /* Access Rights Byte */
|
|
sys_addr SS_base; /* Base Address */
|
|
word SS_limit; /* Segment 'size' */
|
|
|
|
/* Extra Segment Register */
|
|
half_word ES_AR; /* Access Rights Byte */
|
|
sys_addr ES_base; /* Base Address */
|
|
word ES_limit; /* Segment 'size' */
|
|
|
|
/* Global Descriptor Table Register */
|
|
sys_addr GDTR_base; /* Base Address */
|
|
word GDTR_limit; /* Segment 'size' */
|
|
|
|
/* Interrupt Descriptor Table Register */
|
|
sys_addr IDTR_base; /* Base Address */
|
|
word IDTR_limit; /* Segment 'size' */
|
|
|
|
/* Local Descriptor Table Register */
|
|
reg LDTR; /* Selector */
|
|
sys_addr LDTR_base; /* Base Address */
|
|
word LDTR_limit; /* Segment 'size' */
|
|
|
|
/* Task Register */
|
|
reg TR; /* Selector */
|
|
sys_addr TR_base; /* Base Address */
|
|
word TR_limit; /* Segment 'size' */
|
|
|
|
mreg MSW; /* Machine Status Word */
|
|
|
|
int STATUS_CF;
|
|
int STATUS_SF;
|
|
int STATUS_ZF;
|
|
int STATUS_AF;
|
|
int STATUS_OF;
|
|
int STATUS_PF;
|
|
int STATUS_TF;
|
|
int STATUS_IF;
|
|
int STATUS_DF;
|
|
int STATUS_NT;
|
|
int STATUS_IOPL;
|
|
#endif /* defined(CCPU) && !defined(CPU_30_STYLE) */
|
|
|
|
/*
|
|
* Global Flags and variables
|
|
*/
|
|
|
|
int verbose; /* TRUE => trace instructions */
|
|
|
|
/*
|
|
* Misc. Prot Mode support routines which are independant of CPU type
|
|
* ---------------------------------
|
|
*/
|
|
#ifdef CPU_30_STYLE
|
|
#ifndef GISP_CPU /* GISP has its own versions of these internal to the CPU */
|
|
|
|
#define GET_SELECTOR_INDEX_TIMES8(x) ((x) & 0xfff8)
|
|
#define GET_SELECTOR_TI(x) (((x) & 0x0004) >> 2)
|
|
|
|
#if defined(CPU_40_STYLE)
|
|
#if defined(PROD) && !defined(CCPU)
|
|
#undef effective_addr
|
|
GLOBAL LIN_ADDR effective_addr IFN2(IU16, seg, IU32, off)
|
|
{
|
|
return (*(Cpu.EffectiveAddr))(seg, off);
|
|
}
|
|
#endif /* PROD & !CCPU */
|
|
#else /* !CPU_40_STYLE */
|
|
#if !(defined(NTVDM) && defined(MONITOR)) /* MS NT monitor has own effective_addr fn */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
/* Calculate effective address. */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
GLOBAL LIN_ADDR effective_addr IFN2(IU16, seg, IU32, off)
|
|
{
|
|
LIN_ADDR descr_addr;
|
|
DESCR entry;
|
|
|
|
if ((!getPE()) || getVM()) {
|
|
return ((LIN_ADDR)seg << 4) + off;
|
|
} else {
|
|
#if defined(SWIN_CPU_OPTS) || defined(CPU_40_STYLE)
|
|
LIN_ADDR base;
|
|
|
|
if (Cpu_find_dcache_entry( seg, &base ))
|
|
{
|
|
/* Cache Hit!! */
|
|
return base + off;
|
|
}
|
|
#endif /* SWIN_CPU_OPTS or CPU_40_STYLE*/
|
|
|
|
if ( selector_outside_table(seg, &descr_addr) == 1 ) {
|
|
|
|
/*
|
|
* This is probably not a major disaster, just a result
|
|
* of the fact that after protected mode is invoked it
|
|
* will take say 5-10 instructions for an application
|
|
* to update all the segment registers. We just
|
|
* maintain real mode semantics while this error occurs.
|
|
*/
|
|
|
|
return ((LIN_ADDR)seg << 4) + off;
|
|
}
|
|
else
|
|
{
|
|
read_descriptor(descr_addr, &entry);
|
|
return entry.base + off;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* !(NTVDM & MONITOR) */
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
/* Read a decriptor table entry from memory. */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
#endif /* !CPU_40_STYLE */
|
|
|
|
GLOBAL void read_descriptor IFN2(LIN_ADDR, addr, DESCR *, descr)
|
|
{
|
|
IU32 first_dword, second_dword;
|
|
IU32 limit;
|
|
|
|
/*
|
|
* The format of a 286 descriptor is:-
|
|
*
|
|
* ===========================
|
|
* +1 | LIMIT 15-0 | +0
|
|
* ===========================
|
|
* +3 | BASE 15-0 | +2
|
|
* ===========================
|
|
* +5 | AR | BASE 23-16 | +4
|
|
* ===========================
|
|
* +7 | RESERVED | +6
|
|
* ===========================
|
|
*/
|
|
/*
|
|
* The format of a 386 descriptor is:-
|
|
*
|
|
* ============================= AR = Access Rights.
|
|
* +1 | LIMIT 15-0 | +0 AVL = Available.
|
|
* ============================= D = Default Operand
|
|
* +3 | BASE 15-0 | +2 Size, = 0 16-bit
|
|
* ============================= = 1 32-bit.
|
|
* +5 | AR | BASE 23-16 | +4 G = Granularity,
|
|
* ============================= = 0 byte limit
|
|
* | | | | |A|LIMIT| = 1 page limit.
|
|
* +7 | BASE 31-24 |G|D|0|V|19-16| +6
|
|
* | | | | |L| |
|
|
* =============================
|
|
*
|
|
*/
|
|
|
|
/* read in decriptor with minimum interaction with memory */
|
|
#if defined(NTVDM) && defined(CPU_40_STYLE)
|
|
/* On NT, this routine can be called from non-CPU threads, so we don't */
|
|
/* want to use SAS at all. Instead, we rely on NtGetPtrToLinAddrByte, */
|
|
/* which is provided by the CPU and is safe for multi-threading. We are*/
|
|
/* also relying on the fact the NT is always little-endian. */
|
|
{
|
|
IU32 *desc_addr = (IU32 *) NtGetPtrToLinAddrByte(addr);
|
|
|
|
first_dword = *desc_addr;
|
|
second_dword = *(desc_addr + 1);
|
|
}
|
|
#else
|
|
first_dword = sas_dw_at(addr);
|
|
second_dword = sas_dw_at(addr+4);
|
|
#endif
|
|
|
|
/* load attributes and access rights */
|
|
descr->AR = (second_dword >> 8) & 0xff;
|
|
|
|
/* unpack the base */
|
|
descr->base = (first_dword >> 16) |
|
|
#ifdef SPC386
|
|
(second_dword & 0xff000000) |
|
|
#endif
|
|
(second_dword << 16 & 0xff0000 );
|
|
|
|
/* unpack the limit */
|
|
#ifndef SPC386
|
|
descr->limit = first_dword & 0xffff;
|
|
#else
|
|
limit = (first_dword & 0xffff) | (second_dword & 0x000f0000);
|
|
|
|
if ( second_dword & 0x00800000 ) /* check bit 23 */
|
|
{
|
|
/* Granularity Bit Set. Limit is expressed in pages
|
|
(4k bytes), convert to byte limit */
|
|
limit = limit << 12 | 0xfff;
|
|
}
|
|
descr->limit = limit;
|
|
#endif /* ifndef SPC386 else */
|
|
|
|
}
|
|
|
|
#if !(defined(NTVDM) && defined(MONITOR)) /* MS NT monitor has own selector_outside_table fn */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
/* Check if selector outside bounds of GDT or LDT */
|
|
/* Return 1 for outside table, 0 for inside table. */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
GLOBAL boolean selector_outside_table IFN2(IU16, selector, LIN_ADDR *, descr_addr)
|
|
{
|
|
/* selector (I) selector to be checked */
|
|
/* descr_addr (O) address of related descriptor */
|
|
|
|
LIN_ADDR offset;
|
|
|
|
offset = GET_SELECTOR_INDEX_TIMES8(selector);
|
|
|
|
/* choose a table */
|
|
if ( GET_SELECTOR_TI(selector) == 0 )
|
|
{
|
|
/* GDT - trap NULL selector or outside table */
|
|
if ( offset == 0 || offset + 7 > getGDT_LIMIT() )
|
|
return 1;
|
|
*descr_addr = getGDT_BASE() + offset;
|
|
}
|
|
else
|
|
{
|
|
/* LDT - trap invalid LDT or outside table */
|
|
if ( getLDT_SELECTOR() == 0 || offset + 7 > getLDT_LIMIT() )
|
|
return 1;
|
|
*descr_addr = getLDT_BASE() + offset;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* !(NTVDM & MONITOR) */
|
|
|
|
#endif /* !GISP_CPU */
|
|
#endif /* CPU_30_STYLE */
|
|
|
|
|
|
/*
|
|
* The following is a table lookup for finding parity of a byte
|
|
*/
|
|
|
|
#if !defined(MAC_LIKE) && !defined(CPU_30_STYLE)
|
|
|
|
half_word pf_table[] = {
|
|
1, /* 00 */
|
|
0, /* 01 */
|
|
0, /* 02 */
|
|
1, /* 03 */
|
|
0, /* 04 */
|
|
1, /* 05 */
|
|
1, /* 06 */
|
|
0, /* 07 */
|
|
0, /* 08 */
|
|
1, /* 09 */
|
|
1, /* 0a */
|
|
0, /* 0b */
|
|
1, /* 0c */
|
|
0, /* 0d */
|
|
0, /* 0e */
|
|
1, /* 0f */
|
|
0, /* 10 */
|
|
1, /* 11 */
|
|
1, /* 12 */
|
|
0, /* 13 */
|
|
1, /* 14 */
|
|
0, /* 15 */
|
|
0, /* 16 */
|
|
1, /* 17 */
|
|
1, /* 18 */
|
|
0, /* 19 */
|
|
0, /* 1a */
|
|
1, /* 1b */
|
|
0, /* 1c */
|
|
1, /* 1d */
|
|
1, /* 1e */
|
|
0, /* 1f */
|
|
0, /* 20 */
|
|
1, /* 21 */
|
|
1, /* 22 */
|
|
0, /* 23 */
|
|
1, /* 24 */
|
|
0, /* 25 */
|
|
0, /* 26 */
|
|
1, /* 27 */
|
|
1, /* 28 */
|
|
0, /* 29 */
|
|
0, /* 2a */
|
|
1, /* 2b */
|
|
0, /* 2c */
|
|
1, /* 2d */
|
|
1, /* 2e */
|
|
0, /* 2f */
|
|
1, /* 30 */
|
|
0, /* 31 */
|
|
0, /* 32 */
|
|
1, /* 33 */
|
|
0, /* 34 */
|
|
1, /* 35 */
|
|
1, /* 36 */
|
|
0, /* 37 */
|
|
0, /* 38 */
|
|
1, /* 39 */
|
|
1, /* 3a */
|
|
0, /* 3b */
|
|
1, /* 3c */
|
|
0, /* 3d */
|
|
0, /* 3e */
|
|
1, /* 3f */
|
|
0, /* 40 */
|
|
1, /* 41 */
|
|
1, /* 42 */
|
|
0, /* 43 */
|
|
1, /* 44 */
|
|
0, /* 45 */
|
|
0, /* 46 */
|
|
1, /* 47 */
|
|
1, /* 48 */
|
|
0, /* 49 */
|
|
0, /* 4a */
|
|
1, /* 4b */
|
|
0, /* 4c */
|
|
1, /* 4d */
|
|
1, /* 4e */
|
|
0, /* 4f */
|
|
1, /* 50 */
|
|
0, /* 51 */
|
|
0, /* 52 */
|
|
1, /* 53 */
|
|
0, /* 54 */
|
|
1, /* 55 */
|
|
1, /* 56 */
|
|
0, /* 57 */
|
|
0, /* 58 */
|
|
1, /* 59 */
|
|
1, /* 5a */
|
|
0, /* 5b */
|
|
1, /* 5c */
|
|
0, /* 5d */
|
|
0, /* 5e */
|
|
1, /* 5f */
|
|
1, /* 60 */
|
|
0, /* 61 */
|
|
0, /* 62 */
|
|
1, /* 63 */
|
|
0, /* 64 */
|
|
1, /* 65 */
|
|
1, /* 66 */
|
|
0, /* 67 */
|
|
0, /* 68 */
|
|
1, /* 69 */
|
|
1, /* 6a */
|
|
0, /* 6b */
|
|
1, /* 6c */
|
|
0, /* 6d */
|
|
0, /* 6e */
|
|
1, /* 6f */
|
|
0, /* 70 */
|
|
1, /* 71 */
|
|
1, /* 72 */
|
|
0, /* 73 */
|
|
1, /* 74 */
|
|
0, /* 75 */
|
|
0, /* 76 */
|
|
1, /* 77 */
|
|
1, /* 78 */
|
|
0, /* 79 */
|
|
0, /* 7a */
|
|
1, /* 7b */
|
|
0, /* 7c */
|
|
1, /* 7d */
|
|
1, /* 7e */
|
|
0, /* 7f */
|
|
0, /* 80 */
|
|
1, /* 81 */
|
|
1, /* 82 */
|
|
0, /* 83 */
|
|
1, /* 84 */
|
|
0, /* 85 */
|
|
0, /* 86 */
|
|
1, /* 87 */
|
|
1, /* 88 */
|
|
0, /* 89 */
|
|
0, /* 8a */
|
|
1, /* 8b */
|
|
0, /* 8c */
|
|
1, /* 8d */
|
|
1, /* 8e */
|
|
0, /* 8f */
|
|
1, /* 90 */
|
|
0, /* 91 */
|
|
0, /* 92 */
|
|
1, /* 93 */
|
|
0, /* 94 */
|
|
1, /* 95 */
|
|
1, /* 96 */
|
|
0, /* 97 */
|
|
0, /* 98 */
|
|
1, /* 99 */
|
|
1, /* 9a */
|
|
0, /* 9b */
|
|
1, /* 9c */
|
|
0, /* 9d */
|
|
0, /* 9e */
|
|
1, /* 9f */
|
|
1, /* a0 */
|
|
0, /* a1 */
|
|
0, /* a2 */
|
|
1, /* a3 */
|
|
0, /* a4 */
|
|
1, /* a5 */
|
|
1, /* a6 */
|
|
0, /* a7 */
|
|
0, /* a8 */
|
|
1, /* a9 */
|
|
1, /* aa */
|
|
0, /* ab */
|
|
1, /* ac */
|
|
0, /* ad */
|
|
0, /* ae */
|
|
1, /* af */
|
|
0, /* b0 */
|
|
1, /* b1 */
|
|
1, /* b2 */
|
|
0, /* b3 */
|
|
1, /* b4 */
|
|
0, /* b5 */
|
|
0, /* b6 */
|
|
1, /* b7 */
|
|
1, /* b8 */
|
|
0, /* b9 */
|
|
0, /* ba */
|
|
1, /* bb */
|
|
0, /* bc */
|
|
1, /* bd */
|
|
1, /* be */
|
|
0, /* bf */
|
|
1, /* c0 */
|
|
0, /* c1 */
|
|
0, /* c2 */
|
|
1, /* c3 */
|
|
0, /* c4 */
|
|
1, /* c5 */
|
|
1, /* c6 */
|
|
0, /* c7 */
|
|
0, /* c8 */
|
|
1, /* c9 */
|
|
1, /* ca */
|
|
0, /* cb */
|
|
1, /* cc */
|
|
0, /* cd */
|
|
0, /* ce */
|
|
1, /* cf */
|
|
0, /* d0 */
|
|
1, /* d1 */
|
|
1, /* d2 */
|
|
0, /* d3 */
|
|
1, /* d4 */
|
|
0, /* d5 */
|
|
0, /* d6 */
|
|
1, /* d7 */
|
|
1, /* d8 */
|
|
0, /* d9 */
|
|
0, /* da */
|
|
1, /* db */
|
|
0, /* dc */
|
|
1, /* dd */
|
|
1, /* de */
|
|
0, /* df */
|
|
0, /* e0 */
|
|
1, /* e1 */
|
|
1, /* e2 */
|
|
0, /* e3 */
|
|
1, /* e4 */
|
|
0, /* e5 */
|
|
0, /* e6 */
|
|
1, /* e7 */
|
|
1, /* e8 */
|
|
0, /* e9 */
|
|
0, /* ea */
|
|
1, /* eb */
|
|
0, /* ec */
|
|
1, /* ed */
|
|
1, /* ee */
|
|
0, /* ef */
|
|
1, /* f0 */
|
|
0, /* f1 */
|
|
0, /* f2 */
|
|
1, /* f3 */
|
|
0, /* f4 */
|
|
1, /* f5 */
|
|
1, /* f6 */
|
|
0, /* f7 */
|
|
0, /* f8 */
|
|
1, /* f9 */
|
|
1, /* fa */
|
|
0, /* fb */
|
|
1, /* fc */
|
|
0, /* fd */
|
|
0, /* fe */
|
|
1 /* ff */
|
|
};
|
|
#endif /* !defined(MAC_LIKE) && !defined(CPU_30_STYLE) */
|
|
|
|
|
|
/*(
|
|
*========================== CsIsBig ===================================
|
|
* CsIsBig
|
|
*
|
|
* Purpose
|
|
* This function returns true if the indicated code segment is a 32 bit
|
|
* one, and false if it isn't.
|
|
*
|
|
* Input
|
|
* csVal The selector to check
|
|
*
|
|
* Outputs
|
|
* None.
|
|
*
|
|
* Description
|
|
* Look at the descriptor.
|
|
)*/
|
|
|
|
GLOBAL IBOOL
|
|
CsIsBig IFN1(IU16, csVal)
|
|
{
|
|
#ifdef SPC386
|
|
LIN_ADDR base, offset; /* Of the descriptor to use */
|
|
|
|
if(getVM() || !getPE()) {
|
|
return(FALSE); /* no 32 bit CS in V86 or real modes */
|
|
} else {
|
|
offset = csVal & (~7); /* remove the RPL and TI gives offset */
|
|
if (csVal & 4) { /* check TI bit */
|
|
base = getLDT_BASE();
|
|
} else {
|
|
base = getGDT_BASE();
|
|
}
|
|
|
|
/*
|
|
* Return true if the big bit in the descriptor is set.
|
|
*/
|
|
|
|
return(sas_hw_at(base + offset + 6) & 0x40);
|
|
}
|
|
#else /* SPC386 */
|
|
return (FALSE);
|
|
#endif /* SPC386 */
|
|
}
|