summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/base/ccpu386/c_seg.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/softpc.new/base/ccpu386/c_seg.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/mvdm/softpc.new/base/ccpu386/c_seg.c')
-rw-r--r--private/mvdm/softpc.new/base/ccpu386/c_seg.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/base/ccpu386/c_seg.c b/private/mvdm/softpc.new/base/ccpu386/c_seg.c
new file mode 100644
index 000000000..f98d4336e
--- /dev/null
+++ b/private/mvdm/softpc.new/base/ccpu386/c_seg.c
@@ -0,0 +1,396 @@
+/*[
+
+c_seg.c
+
+LOCAL CHAR SccsID[]="@(#)c_seg.c 1.10 03/02/95";
+
+Segment Register Support.
+-------------------------
+
+]*/
+
+
+#include <insignia.h>
+
+#include <host_def.h>
+#include <xt.h>
+
+#include <c_main.h>
+#include <c_addr.h>
+#include <c_bsic.h>
+#include <c_prot.h>
+#include <c_seg.h>
+#include <c_stack.h>
+#include <c_xcptn.h>
+#include <c_reg.h>
+#include <c_page.h>
+#include <fault.h>
+
+
+/*
+ =====================================================================
+ EXTERNAL ROUTINES STARTS HERE.
+ =====================================================================
+ */
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load CS, both selector and hidden cache. Selector must be valid. */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_CS_cache
+
+IFN3(
+ IU16, selector, /* (I) 16-bit selector to code segment */
+ IU32, descr_addr, /* (I) address of code segment descriptor */
+ CPU_DESCR *, entry /* (I) the decoded descriptor */
+ )
+
+
+ {
+ if ( GET_PE() == 0 || GET_VM() == 1 )
+ {
+ /* Real Mode or V86 Mode */
+ SET_CS_SELECTOR(selector);
+ SET_CS_BASE((IU32)selector << 4);
+
+ /* LIMIT is untouched. (cf 80386 PRM Pg14-4) */
+ /* (cf i486 PRM Pg22-4) */
+
+ /* But access rights are updated */
+ SET_CS_AR_W(1); /* allow write access */
+ SET_CS_AR_R(1); /* allow read access */
+ SET_CS_AR_E(0); /* expand up */
+ SET_CS_AR_C(0); /* not conforming */
+ SET_CS_AR_X(0); /* not big (16-bit) */
+
+ if ( GET_VM() == 1 )
+ SET_CS_AR_DPL(3);
+ else
+ SET_CS_AR_DPL(0);
+ }
+ else
+ {
+ /* Protected Mode */
+
+ /* show segment has been accessed (i486 only writes if changed) */
+#ifdef SPC486
+ if ((entry->AR & ACCESSED) == 0)
+#endif /* SPC486 */
+ spr_write_byte(descr_addr+5, (IU8)entry->AR | ACCESSED);
+ entry->AR |= ACCESSED;
+
+ /* the visible bit */
+ SET_CS_SELECTOR(selector);
+
+ /* load hidden cache */
+ SET_CS_BASE(entry->base);
+ SET_CS_LIMIT(entry->limit);
+ /* load attributes from descriptor */
+ SET_CS_AR_DPL(GET_AR_DPL(entry->AR));
+ SET_CS_AR_R(GET_AR_R(entry->AR));
+ SET_CS_AR_C(GET_AR_C(entry->AR));
+ SET_CS_AR_X(GET_AR_X(entry->AR));
+
+ SET_CS_AR_E(0); /* expand up */
+ SET_CS_AR_W(0); /* deny write */
+ }
+ }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load SS, both selector and hidden cache. Selector must be valid. */
+/* Only invoked in protected mode. */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_SS_cache
+
+IFN3(
+ IU16, selector, /* (I) 16-bit selector to stack segment */
+ IU32, descr_addr, /* (I) address of stack segment descriptor */
+ CPU_DESCR *, entry /* (I) the decoded descriptor */
+ )
+
+
+ {
+ /* show segment has been accessed (i486 only writes if changed) */
+#ifdef SPC486
+ if ((entry->AR & ACCESSED) == 0)
+#endif /* SPC486 */
+ spr_write_byte(descr_addr+5, (IU8)entry->AR | ACCESSED);
+ entry->AR |= ACCESSED;
+
+ /* the visible bit */
+ SET_SS_SELECTOR(selector);
+
+ /* load hidden cache */
+ SET_SS_BASE(entry->base);
+ SET_SS_LIMIT(entry->limit);
+ /* load attributes from descriptor */
+ SET_SS_AR_DPL(GET_AR_DPL(entry->AR));
+ SET_SS_AR_E(GET_AR_E(entry->AR));
+ SET_SS_AR_X(GET_AR_X(entry->AR));
+
+ SET_SS_AR_W(1); /* must be writeable */
+ SET_SS_AR_R(1); /* must be readable */
+ SET_SS_AR_C(0); /* not conforming */
+ }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load CS selector. */
+/* Take #GP if segment not valid */
+/* Take #NP if segment not present */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_code_seg
+
+IFN1(
+ IU16, new_cs
+ )
+
+
+ {
+ IU32 cs_descr_addr; /* code segment descriptor address */
+ CPU_DESCR cs_entry; /* code segment descriptor entry */
+
+ /*
+ Given that the CPU should be started from a valid state, we
+ check CS selectors as if a far call to the same privilege
+ level was being generated. This is in effect saying yes the
+ CS could have been loaded by a valid Intel instruction.
+ This logic may have to be revised if strange LOADALL usage is
+ found.
+ */
+
+ if ( GET_PE() == 0 || GET_VM() == 1 )
+ {
+ /* Real Mode or V86 Mode */
+ load_CS_cache(new_cs, (IU32)0, (CPU_DESCR *)0);
+ }
+ else
+ {
+ /* Protected Mode */
+
+ if ( selector_outside_GDT_LDT(new_cs, &cs_descr_addr) )
+ GP(new_cs, FAULT_LOADCS_SELECTOR);
+
+ /* load descriptor */
+ read_descriptor_linear(cs_descr_addr, &cs_entry);
+
+ /* validate possible types of target */
+ switch ( descriptor_super_type(cs_entry.AR) )
+ {
+ case CONFORM_NOREAD_CODE:
+ case CONFORM_READABLE_CODE:
+ /* access check requires DPL <= CPL */
+ if ( GET_AR_DPL(cs_entry.AR) > GET_CPL() )
+ GP(new_cs, FAULT_LOADCS_ACCESS_1);
+
+ /* it must be present */
+ if ( GET_AR_P(cs_entry.AR) == NOT_PRESENT )
+ NP(new_cs, FAULT_LOADCS_NOTPRESENT_1);
+ break;
+
+ case NONCONFORM_NOREAD_CODE:
+ case NONCONFORM_READABLE_CODE:
+ /* access check requires RPL <= CPL and DPL == CPL */
+ if ( GET_SELECTOR_RPL(new_cs) > GET_CPL() ||
+ GET_AR_DPL(cs_entry.AR) != GET_CPL() )
+ GP(new_cs, FAULT_LOADCS_ACCESS_2);
+
+ /* it must be present */
+ if ( GET_AR_P(cs_entry.AR) == NOT_PRESENT )
+ NP(new_cs, FAULT_LOADCS_NOTPRESENT_2);
+ break;
+
+ default:
+ GP(new_cs, FAULT_LOADCS_BAD_SEG_TYPE);
+ }
+
+ /* stamp new selector with CPL */
+ SET_SELECTOR_RPL(new_cs, GET_CPL());
+
+ load_CS_cache(new_cs, cs_descr_addr, &cs_entry);
+ }
+ }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load A Data Segment Register. (DS, ES, FS, GS) */
+/* Take #GP if segment not valid */
+/* Take #NP if segment not present */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_data_seg
+
+IFN2(
+ ISM32, indx,
+ IU16, selector
+ )
+
+
+ {
+ IU32 descr_addr;
+ CPU_DESCR entry;
+ ISM32 super;
+ ISM32 dpl;
+ BOOL is_data;
+
+ if ( GET_PE() == 0 || GET_VM() == 1 )
+ {
+ /* Real Mode or V86 Mode */
+ SET_SR_SELECTOR(indx, selector);
+ SET_SR_BASE(indx, (IU32)selector << 4);
+ }
+ else
+ {
+ /* Protected Mode */
+ if ( selector_is_null(selector) )
+ {
+ /* load is allowed - but later access will fail
+ * Since the program can not see the internal changes
+ * performed to achieve this, we make the behaviour
+ * match the easiest implementation in the A4CPU
+ */
+ SET_SR_SELECTOR(indx, selector);
+
+ /* the following lines were added to make the C-CPU behave like
+ * the Soft 486 CPU - an investigation is being made to see if this
+ * behaviour corresponds with the real i486 - this code may have to
+ * change.
+ */
+ SET_SR_BASE(indx, 0);
+ SET_SR_LIMIT(indx, 0);
+ SET_SR_AR_W(indx, 0);
+ SET_SR_AR_R(indx, 0);
+ }
+ else
+ {
+ if ( selector_outside_GDT_LDT(selector, &descr_addr) )
+ GP(selector, FAULT_LOADDS_SELECTOR);
+
+ read_descriptor_linear(descr_addr, &entry);
+
+ /* check type */
+ switch ( super = descriptor_super_type(entry.AR) )
+ {
+ case CONFORM_READABLE_CODE:
+ case NONCONFORM_READABLE_CODE:
+ is_data = FALSE;
+ break;
+
+ case EXPANDUP_READONLY_DATA:
+ case EXPANDUP_WRITEABLE_DATA:
+ case EXPANDDOWN_READONLY_DATA:
+ case EXPANDDOWN_WRITEABLE_DATA:
+ is_data = TRUE;
+ break;
+
+ default:
+ GP(selector, FAULT_LOADDS_BAD_SEG_TYPE); /* bad type */
+ }
+
+ /* for data and non-conforming code the access check applies */
+ if ( super != CONFORM_READABLE_CODE )
+ {
+ /* access check requires CPL <= DPL and RPL <= DPL */
+ dpl = GET_AR_DPL(entry.AR);
+ if ( GET_CPL() > dpl || GET_SELECTOR_RPL(selector) > dpl )
+ GP(selector, FAULT_LOADDS_ACCESS);
+ }
+
+ /* must be present */
+ if ( GET_AR_P(entry.AR) == NOT_PRESENT )
+ NP(selector, FAULT_LOADDS_NOTPRESENT);
+
+ /* show segment has been accessed (i486 only writes if changed) */
+#ifdef SPC486
+ if ((entry.AR & ACCESSED) == 0)
+#endif /* SPC486 */
+ spr_write_byte(descr_addr+5, (IU8)entry.AR | ACCESSED);
+ entry.AR |= ACCESSED;
+
+ /* OK - load up */
+
+ /* the visible bit */
+ SET_SR_SELECTOR(indx, selector);
+
+ /* load hidden cache */
+ SET_SR_BASE(indx, entry.base);
+ SET_SR_LIMIT(indx, entry.limit);
+ /* load attributes from descriptor */
+ SET_SR_AR_DPL(indx, GET_AR_DPL(entry.AR));
+
+ if ( is_data )
+ {
+ SET_SR_AR_W(indx, GET_AR_W(entry.AR));
+ SET_SR_AR_E(indx, GET_AR_E(entry.AR));
+ SET_SR_AR_C(indx, 0); /* not conforming */
+ }
+ else
+ {
+ SET_SR_AR_C(indx, GET_AR_C(entry.AR));
+ SET_SR_AR_W(indx, 0); /* deny write access */
+ SET_SR_AR_E(indx, 0); /* expand up */
+ }
+
+ SET_SR_AR_X(indx, GET_AR_X(entry.AR));
+
+ SET_SR_AR_R(indx, 1); /* must be readable */
+ }
+ }
+ }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load Pseudo Descriptor Semantics for Real Mode or V86 Mode. */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_pseudo_descr
+
+IFN1(
+ ISM32, index /* index to segment register */
+ )
+
+
+ {
+ SET_SR_LIMIT(index, 0xffff);
+ SET_SR_AR_W(index, 1); /* allow write access */
+ SET_SR_AR_R(index, 1); /* allow read access */
+ SET_SR_AR_E(index, 0); /* expand up */
+ SET_SR_AR_C(index, 0); /* not conforming */
+ SET_SR_AR_X(index, 0); /* not big (16-bit) */
+
+ if ( GET_VM() == 1 )
+ SET_SR_AR_DPL(index, 3);
+ else
+ SET_SR_AR_DPL(index, 0);
+ }
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Load Stack Segment Register. (SS) */
+/* Take #GP if segment not valid */
+/* Take #SF if segment not present */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GLOBAL VOID
+load_stack_seg
+
+IFN1(
+ IU16, selector
+ )
+
+
+ {
+ IU32 descr_addr;
+ CPU_DESCR entry;
+
+ if ( GET_PE() == 0 || GET_VM() == 1 )
+ {
+ /* Real Mode or V86 Mode */
+ SET_SS_SELECTOR(selector);
+ SET_SS_BASE((IU32)selector << 4);
+ }
+ else
+ {
+ /* Protected Mode */
+ check_SS(selector, (ISM32)GET_CPL(), &descr_addr, &entry);
+ load_SS_cache(selector, descr_addr, &entry);
+ }
+ }