]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/T0/CPU.cs
MFV r358511,r358532:
[FreeBSD/FreeBSD.git] / contrib / bearssl / T0 / CPU.cs
1 /*
2  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining 
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be 
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 using System;
26 using System.Collections.Generic;
27
28 /*
29  * Execution of code during compilation is done in a virtual CPU
30  * incarnated by this class, that contains the relevant registers.
31  *
32  * Accesses to the data on the stack are mapped to accesses to an
33  * internal array, with no explicit control on boundaries. Since the
34  * internal array may be larger than the actual stack contents,
35  * nonsensical accesses may still "work" to some extent. The whole
36  * thing won't derail beyond the CLR VM, though.
37  */
38
39 class CPU {
40
41         /*
42          * Next instruction to execute is in ipBuf[ipOff].
43          */
44         internal Opcode[] ipBuf;
45         internal int ipOff;
46
47         /*
48          * stackBuf and stackPtr implement the data stack. The system
49          * stack uses frames; 'rsp' points to the current top frame.
50          */
51         TValue[] stackBuf;
52         int stackPtr;
53         Frame rsp;
54
55         internal CPU()
56         {
57                 stackBuf = new TValue[16];
58                 stackPtr = -1;
59                 rsp = null;
60         }
61
62         /*
63          * Enter a function, reserving space for 'numLocals' local variables.
64          */
65         internal void Enter(Opcode[] code, int numLocals)
66         {
67                 Frame f = new Frame(rsp, numLocals);
68                 rsp = f;
69                 f.savedIpBuf = ipBuf;
70                 f.savedIpOff = ipOff;
71                 ipBuf = code;
72                 ipOff = 0;
73         }
74
75         /*
76          * Exit the current function.
77          */
78         internal void Exit()
79         {
80                 ipBuf = rsp.savedIpBuf;
81                 ipOff = rsp.savedIpOff;
82                 rsp = rsp.upper;
83         }
84
85         /*
86          * Get the current stack depth (number of elements).
87          */
88         internal int Depth {
89                 get {
90                         return stackPtr + 1;
91                 }
92         }
93
94         /*
95          * Pop a value from the stack.
96          */
97         internal TValue Pop()
98         {
99                 return stackBuf[stackPtr --];
100         }
101
102         /*
103          * Push a value on the stack.
104          */
105         internal void Push(TValue v)
106         {
107                 int len = stackBuf.Length;
108                 if (++ stackPtr == len) {
109                         TValue[] nbuf = new TValue[len << 1];
110                         Array.Copy(stackBuf, 0, nbuf, 0, len);
111                         stackBuf = nbuf;
112                 }
113                 stackBuf[stackPtr] = v;
114         }
115
116         /*
117          * Look at the value at depth 'depth' (0 is top of stack). The
118          * stack is unchanged.
119          */
120         internal TValue Peek(int depth)
121         {
122                 return stackBuf[stackPtr - depth];
123         }
124
125         /*
126          * Rotate the stack at depth 'depth': the value at that depth
127          * is moved to the top of stack.
128          */
129         internal void Rot(int depth)
130         {
131                 TValue v = stackBuf[stackPtr - depth];
132                 Array.Copy(stackBuf, stackPtr - (depth - 1),
133                         stackBuf, stackPtr - depth, depth);
134                 stackBuf[stackPtr] = v;
135         }
136
137         /*
138          * Inverse-rotate the stack at depth 'depth': the value at the
139          * top of stack is moved to that depth.
140          */
141         internal void NRot(int depth)
142         {
143                 TValue v = stackBuf[stackPtr];
144                 Array.Copy(stackBuf, stackPtr - depth,
145                         stackBuf, stackPtr - (depth - 1), depth);
146                 stackBuf[stackPtr - depth] = v;
147         }
148
149         /*
150          * Get the current contents of the local variable 'num'.
151          */
152         internal TValue GetLocal(int num)
153         {
154                 return rsp.locals[num];
155         }
156
157         /*
158          * Set the contents of the local variable 'num'.
159          */
160         internal void PutLocal(int num, TValue v)
161         {
162                 rsp.locals[num] = v;
163         }
164
165         /*
166          * The system stack really is a linked list of Frame instances.
167          */
168         class Frame {
169
170                 internal Frame upper;
171                 internal Opcode[] savedIpBuf;
172                 internal int savedIpOff;
173                 internal TValue[] locals;
174
175                 internal Frame(Frame upper, int numLocals)
176                 {
177                         this.upper = upper;
178                         locals = new TValue[numLocals];
179                 }
180         }
181 }