aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/proti3.c
diff options
context:
space:
mode:
authorNick Barnes2001-10-31 14:40:56 +0000
committerNick Barnes2001-10-31 14:40:56 +0000
commit7acfca905d76140f4cc0b09c9a12de237de364cd (patch)
tree3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/proti3.c
parentb7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff)
downloademacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz
emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip
Branch imports for masters.
Copied from Perforce Change: 23678 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/proti3.c')
-rw-r--r--mps/code/proti3.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/mps/code/proti3.c b/mps/code/proti3.c
new file mode 100644
index 00000000000..1056ec5a96e
--- /dev/null
+++ b/mps/code/proti3.c
@@ -0,0 +1,240 @@
1/* impl.c.proti3: PROTECTION MUTATOR CONTEXT (INTEL 386)
2 *
3 * $HopeName: MMsrc!proti3.c(trunk.1) $
4 * Copyright (C) 1999 Harlequin Limited. All rights reserved.
5 *
6 * .design: See design.mps.prot for the generic design of the interface
7 * which is implemented in this module, including the contracts for the
8 * functions.
9 *
10 * .purpose: This module implements the part of the protection module
11 * that implements the MutatorFaultContext type.
12 *
13 * .requirements: Current requirements are for limited support only, for
14 * stepping the sorts of instructions that the Dylan compiler might
15 * generate for table vector access - i.e., a restricted subset of MOV
16 * addressing modes. This avoids the need to scan entire weak tables at
17 * an inappropriate rank when a page fault occurs.
18 *
19 *
20 * SOURCES
21 *
22 * .source.i486: Intel486 Microprocessor Family Programmer's
23 * Reference Manual
24 *
25 * .source.dylan: Dylan table code implementation. Especially the
26 * following HOPE units:
27 * D-lib-dylan!table.dylan (class <entry-vector>, slot entry-element)
28 * D-dfmc-harp-cg!harp-primitives.dylan (method op--repeated-slot-element)
29 * D-harp-pentium-harp!moves.dylan (pentium-template ld-index)
30 *
31 *
32 * ASSUMPTIONS
33 *
34 * .assume.null: It's always safe for Prot*StepInstruction to return
35 * ResUNIMPL. A null implementation of this module would be overly
36 * conservative but otherwise correct.
37 *
38 * .assume.want: The Dylan implementation is likely to access a
39 * weak table vector using either MOV r/m32,r32 or MOV r32,r/m32
40 * instructions, where the r/m32 operand will be of one of the forms
41 * disp8[reg], disp8[reg1][reg2], disp8[reg1][reg2*4] (see .source.dylan
42 * and .source.i486)
43 *
44 * .assume.i3: Assume the following about the i386 environment:
45 * Steppable instructions (.assume.want) use the CS, DS & SS
46 * segment registers only (see .source.i486 Table 2-3).
47 * The procesor runs in 32 bit mode.
48 * The CS, DS and SS segment registers all describe identical 32-
49 * bit flat address spaces.
50 */
51
52#include "mpm.h"
53#include "prmci3.h"
54
55SRCID(proti3, "$HopeName$");
56
57
58/* DecodeCB -- Decode an Intel x86 control byte into Hi, Medium & Low fields */
59
60static void DecodeCB(unsigned int *hReturn,
61 unsigned int *mReturn,
62 unsigned int *lReturn,
63 Byte op)
64{
65 /* see .source.i486 Figure 26-2 */
66 unsigned int uop = (unsigned int)op;
67 *lReturn = uop & 7;
68 uop = uop >> 3;
69 *mReturn = uop & 7;
70 uop = uop >> 3;
71 *hReturn = uop & 3;
72}
73
74
75/* DecodeSIB -- Decode a Scale Index Base byte for an Intel x86 instruction */
76
77static void DecodeSIB(unsigned int *sReturn,
78 unsigned int *iReturn,
79 unsigned int *bReturn,
80 Byte op)
81{
82 DecodeCB(sReturn, iReturn, bReturn, op);
83}
84
85
86/* DecodeModRM -- Decode a ModR/M byte for an Intel x86 instruction */
87
88static void DecodeModRM(unsigned int *modReturn,
89 unsigned int *rReturn,
90 unsigned int *mReturn,
91 Byte op)
92{
93 DecodeCB(modReturn, rReturn, mReturn, op);
94}
95
96
97/* RegValue -- Return the value of a machine register from a context */
98
99static Word RegValue(MutatorFaultContext context, unsigned int regnum)
100{
101 MRef addr;
102
103 addr = Prmci3AddressHoldingReg(context, regnum);
104 return *addr;
105}
106
107
108/* Return a byte element of an instruction vector as a
109 * Word value, with sign extension
110 */
111static Word SignedInsElt(Byte insvec[], Count i)
112{
113 signed char eltb;
114
115 eltb = ((signed char*)insvec)[i];
116 return (Word)eltb;
117}
118
119
120/* If a MOV instruction is a sufficiently simple example of a
121 * move between a register and memory (in either direction),
122 * then find the register, the effective address and the size
123 * of the instruction. The instruction is considered sufficiently
124 * simple if it uses a single byte displacement, a base register,
125 * and either no index or a (possibly scaled) register.
126 */
127static Bool DecodeSimpleMov(unsigned int *regnumReturn,
128 MRef *memReturn,
129 Size *inslenReturn,
130 MutatorFaultContext context,
131 Byte insvec[])
132{
133 unsigned int mod;
134 unsigned int r;
135 unsigned int m;
136
137 DecodeModRM(&mod, &r, &m, insvec[1]); /* .source.i486 Table 26-3 */
138 if (1 == mod) {
139 /* only know about single byte displacements, .assume.want */
140 Word base;
141 Word index;
142 Word disp;
143
144 if (4 == m) {
145 /* There is an index */
146 unsigned int s;
147 unsigned int i;
148 unsigned int b;
149
150 DecodeSIB(&s, &i, &b, insvec[2]); /* .source.i486 Table 26-3 */
151 if (4 == i)
152 return FALSE; /* degenerate SIB form - unused by Dylan compiler */
153 disp = SignedInsElt(insvec, 3);
154 base = RegValue(context, b);
155 index = RegValue(context, i) << s;
156 *inslenReturn = 4;
157 } else {
158 /* MOV with reg1 & [reg2+byte] parameters */
159 disp = SignedInsElt(insvec, 2);
160 base = RegValue(context, m);
161 index = 0;
162 *inslenReturn = 3;
163 }
164 *regnumReturn = r;
165 *memReturn = (MRef)(base + index + disp); /* .assume.i3 */
166 return TRUE;
167 }
168
169 return FALSE;
170}
171
172
173static Bool IsSimpleMov(Size *inslenReturn,
174 MRef *srcReturn,
175 MRef *destReturn,
176 MutatorFaultContext context)
177{
178 Byte *insvec;
179 unsigned int regnum;
180 MRef mem;
181 MRef faultmem;
182
183 Prmci3DecodeFaultContext(&faultmem, &insvec, context);
184
185 /* .assume.want */
186 /* .source.i486 Page 26-210 */
187 if ((Byte)0x8b == insvec[0]) {
188 /* This is an instruction of type MOV reg, r/m32 */
189 if (DecodeSimpleMov(&regnum, &mem, inslenReturn, context, insvec)) {
190 AVER(faultmem == mem); /* Ensure computed address matches exception */
191 *srcReturn = mem;
192 *destReturn = Prmci3AddressHoldingReg(context, regnum);
193 return TRUE;
194 }
195 } else if ((Byte)0x89 == insvec[0]) {
196 /* This is an instruction of type MOV r/m32, reg */
197 if (DecodeSimpleMov(&regnum, &mem, inslenReturn, context, insvec)) {
198 AVER(faultmem == mem); /* Ensure computed address matches exception */
199 *destReturn = mem;
200 *srcReturn = Prmci3AddressHoldingReg(context, regnum);
201 return TRUE;
202 }
203 }
204
205 return FALSE;
206}
207
208
209Bool ProtCanStepInstruction(MutatorFaultContext context)
210{
211 Size inslen;
212 MRef src;
213 MRef dest;
214
215 /* .assume.null */
216 /* .assume.want */
217 if (IsSimpleMov(&inslen, &src, &dest, context)) {
218 return TRUE;
219 }
220
221 return FALSE;
222}
223
224
225Res ProtStepInstruction(MutatorFaultContext context)
226{
227 Size inslen;
228 MRef src;
229 MRef dest;
230
231 /* .assume.null */
232 /* .assume.want */
233 if (IsSimpleMov(&inslen, &src, &dest, context)) {
234 *dest = *src;
235 Prmci3StepOverIns(context, inslen);
236 return ResOK;
237 }
238
239 return ResUNIMPL;
240}