summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/base/ccpu386/enter.c
blob: 8d6feac59e8fcf650a00be9b0dd681e055e9e1d9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*[

enter.c

LOCAL CHAR SccsID[]="@(#)enter.c	1.7 01/19/95";

ENTER CPU functions.
--------------------

]*/


#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 <enter.h>
#include <c_page.h>
#include <fault.h>


/*
   =====================================================================
   EXTERNAL ROUTINES STARTS HERE.
   =====================================================================
 */


GLOBAL VOID
ENTER16
       	    	               
IFN2(
	IU32, op1,	/* immediate data space required */
	IU32, op2	/* level (indicates parameters which must be copied) */
    )


   {
   IU32 frame_ptr;

   IS32  p_delta = 0;   /* posn of parameter relative to BP */
   IU32 p_addr;        /* memory address of parameter */
   IU32 param;         /* parameter read via BP */

   op2 &= 0x1f;   /* take level MOD 32 */

   /* check room on stack for new data */
   validate_stack_space(USE_SP, (ISM32)op2+1);

   /* check old parameters exist */
   if ( op2 > 1 )
      {
      /*
	 BP is pointing to the old stack before the parameters
	 were actually pushed, we therefore test for the presence
	 of the parameters by seeing if they could have been pushed,
	 if so they exist now.

	 We have to take care of the READ/WRITE stack addressability
	 ourselves. Because we have checked the new data can be
	 written we know the next call can not fail because of access
	 problems, however we don't yet know if the stack is readable.

	 Note we have been a bit severe on the paging unit because we
	 are asking if the old parameters could be written, if so they
	 can certainly be read from the point of view of the paging
	 unit!
       */
      /* do access check */
      if ( GET_SS_AR_R() == 0 )
	 SF((IU16)0, FAULT_ENTER16_ACCESS);

      /* now we know 'frigged' limit check is ok */
      validate_stack_space(USE_BP, (ISM32)op2-1);
      }

   /* all ok - process instruction */

   spush((IU32)GET_BP());		/* push BP */
   frame_ptr = GetStackPointer();	/* save (E)SP */

   if ( op2 > 0 )
      {
      /* level is >=1, copy stack parameters if they exist */
      while ( --op2 > 0 )
	 {
	 /* copy parameter */
	 p_delta -= 2;   /* decrement to next parameter */

	 /* calculate parameter address in 32/16bit arithmetic */
	 p_addr = get_current_BP() + p_delta;
	 if ( GET_SS_AR_X() == 0 )   /* look at SS 'B' bit */
	    p_addr &= WORD_MASK;

	 p_addr += GET_SS_BASE();

	 param = (IU32)vir_read_word(p_addr, NO_PHYSICAL_MAPPING);
	 spush(param);
	 }
      spush((IU32)frame_ptr);	/* save old (E)SP */
      }
   
   /* update (E)BP */
   set_current_BP(frame_ptr);

   /* finally allocate immediate data space on stack */
   if ( op1 )
      byte_change_SP((IS32)-op1);
   }

GLOBAL VOID
ENTER32
       	    	               
IFN2(
	IU32, op1,	/* immediate data space required */
	IU32, op2	/* level (indicates parameters which must be copied) */
    )


   {
   IU32 frame_ptr;

   IS32  p_delta = 0;   /* posn of parameter relative to EBP */
   IU32 p_addr;        /* memory address of parameter */
   IU32 param;         /* parameter read via EBP */

   op2 &= 0x1f;   /* take level MOD 32 */

   /* check room on stack for new data */
   validate_stack_space(USE_SP, (ISM32)op2+1);

   /* check old parameters exist */
   if ( op2 > 1 )
      {
      /*
	 EBP is pointing to the old stack before the parameters
	 were actually pushed, we therefore test for the presence
	 of the parameters by seeing if they could have been pushed,
	 if so they exist now.

	 We have to take care of the READ/WRITE stack addressability
	 ourselves. Because we have checked the new data can be
	 written we know the next call can not fail because of access
	 problems, however we don't yet know if the stack is readable.

	 Note we have been a bit severe on the paging unit because we
	 are asking if the old parameters could be written, if so they
	 can certainly be read from the point of view of the paging
	 unit!
       */
      /* do access check */
      if ( GET_SS_AR_R() == 0 )
	 SF((IU16)0, FAULT_ENTER32_ACCESS);

      /* now we know 'frigged' limit check is ok */
      validate_stack_space(USE_BP, (ISM32)op2-1);
      }

   /* all ok - process instruction */

   spush((IU32)GET_EBP());		/* push EBP */
   frame_ptr = GetStackPointer();	/* save (E)SP */

   if ( op2 > 0 )
      {
      /* level is >=1, copy stack parameters if they exist */
      while ( --op2 > 0 )
	 {
	 /* copy parameter */
	 p_delta -= 4;   /* decrement to next parameter */

	 /* calculate parameter address in 32/16bit arithmetic */
	 p_addr = get_current_BP() + p_delta;
	 if ( GET_SS_AR_X() == 0 )   /* look at SS 'B' bit */
	    p_addr &= WORD_MASK;

	 p_addr += GET_SS_BASE();

	 param = (IU32)vir_read_dword(p_addr, NO_PHYSICAL_MAPPING);
	 spush(param);
	 }
      spush((IU32)frame_ptr);	/* save old (E)SP */
      }
   
   /* update (E)BP */
   set_current_BP(frame_ptr);

   /* finally allocate immediate data space on stack */
   if ( op1 )
      byte_change_SP((IS32)-op1);
   }