1 //******************************************************************************
2 ///
3 /// @file vm/fnpovfpu.h
4 ///
5 /// This module contains declarations for the virtual machine executing
6 /// render-time functions.
7 ///
8 /// This module is inspired by code by D. Skarda, T. Bily and R. Suzuki.
9 ///
10 /// @copyright
11 /// @parblock
12 ///
13 /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8.
14 /// Copyright 1991-2018 Persistence of Vision Raytracer Pty. Ltd.
15 ///
16 /// POV-Ray is free software: you can redistribute it and/or modify
17 /// it under the terms of the GNU Affero General Public License as
18 /// published by the Free Software Foundation, either version 3 of the
19 /// License, or (at your option) any later version.
20 ///
21 /// POV-Ray is distributed in the hope that it will be useful,
22 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
23 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 /// GNU Affero General Public License for more details.
25 ///
26 /// You should have received a copy of the GNU Affero General Public License
27 /// along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 ///
29 /// ----------------------------------------------------------------------------
30 ///
31 /// POV-Ray is based on the popular DKB raytracer version 2.12.
32 /// DKBTrace was originally written by David K. Buck.
33 /// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
34 ///
35 /// @endparblock
36 ///
37 //******************************************************************************
38 
39 #ifndef POVRAY_VM_FNPOVFPU_H
40 #define POVRAY_VM_FNPOVFPU_H
41 
42 // Module config header file must be the first file included within POV-Ray unit header files
43 #include "vm/configvm.h"
44 
45 #include <set>
46 #include <vector>
47 
48 #include "base/textstream.h"
49 
50 #include "core/coretypes.h"
51 
52 namespace pov
53 {
54 
55 class FunctionVM;
56 
57 #define MAX_CALL_STACK_SIZE 1024
58 #define INITIAL_DBL_STACK_SIZE 256
59 
60 #define MAX_K ((unsigned int)0x000fffff)
61 
62 enum
63 {
64     ITYPE_R = 0,
65     ITYPE_I,
66     ITYPE_S,
67     ITYPE_J,
68     ITYPE_X,
69     ITYPE_M
70 };
71 
72 struct Opcode
73 {
74     const char *name;
75     unsigned int code;
76     int type;
77 };
78 
79 enum
80 {
81     TRAP_SYS1_SIN = 0,
82     TRAP_SYS1_COS,
83     TRAP_SYS1_TAN,
84     TRAP_SYS1_ASIN,
85     TRAP_SYS1_ACOS,
86     TRAP_SYS1_ATAN,
87     TRAP_SYS1_SINH,
88     TRAP_SYS1_COSH,
89     TRAP_SYS1_TANH,
90     TRAP_SYS1_ASINH,
91     TRAP_SYS1_ACOSH,
92     TRAP_SYS1_ATANH,
93     TRAP_SYS1_FLOOR,
94     TRAP_SYS1_CEIL,
95     TRAP_SYS1_SQRT,
96     TRAP_SYS1_EXP,
97     TRAP_SYS1_LN,
98     TRAP_SYS1_LOG,
99     TRAP_SYS1_INT
100 };
101 
102 enum
103 {
104     TRAP_SYS2_POW = 0,
105     TRAP_SYS2_ATAN2,
106     TRAP_SYS2_MOD,
107     TRAP_SYS2_DIV
108 };
109 
110 typedef SYS_MATH_RETURN (*Sys1)(SYS_MATH_PARAM r0);
111 typedef SYS_MATH_RETURN (*Sys2)(SYS_MATH_PARAM r0,SYS_MATH_PARAM r1);
112 
113 typedef unsigned int Instruction;
114 
115 const int MAX_FUNCTION_PARAMETER_LIST = 56;
116 
117 typedef void *(*FNCODE_PRIVATE_COPY_METHOD)(void *);
118 typedef void (*FNCODE_PRIVATE_DESTROY_METHOD)(void *);
119 
120 struct FunctionCode
121 {
122     Instruction *program;
123     unsigned int program_size;
124     unsigned char return_size;
125     unsigned char parameter_cnt;
126     unsigned char localvar_cnt;
127     unsigned int localvar_pos[MAX_FUNCTION_PARAMETER_LIST];
128     char *localvar[MAX_FUNCTION_PARAMETER_LIST];
129     char *parameter[MAX_FUNCTION_PARAMETER_LIST];
130     SourceInfo sourceInfo;
131     unsigned int flags;
132     FNCODE_PRIVATE_COPY_METHOD private_copy_method;
133     FNCODE_PRIVATE_DESTROY_METHOD private_destroy_method;
134     void *private_data;
135 };
136 
137 typedef unsigned int FUNCTION;
138 typedef FUNCTION * FUNCTION_PTR;
139 
140 // WARNING: Do not change this structure without notice!!!
141 // Platform specific code may depend on the exact layout and size! [trf]
142 struct FunctionEntry
143 {
144     union {
145         FunctionCode fn;            // valid if reference_count != 0
146         FUNCTION next_unreferenced; // valid if reference_count == 0
147     };
148     unsigned int reference_count;
149     SYS_FUNCTION_ENTRY
150 };
151 
152 // WARNING: Do not change this structure without notice!!!
153 // Platform specific code may depend on the exact layout and size! [trf]
154 struct StackFrame
155 {
156     unsigned int pc;
157     FUNCTION fn;
158 };
159 
160 // WARNING: Do not change this structure without notice!!!
161 // Platform specific code may depend on the exact layout and size! [trf]
162 class FPUContext : public GenericFunctionContext
163 {
164     public:
165         FPUContext(FunctionVM* pVm, TraceThreadData* pThreadData);
166         virtual ~FPUContext();
167 
168         StackFrame *pstackbase;
169         DBL *dblstackbase;
170         unsigned int maxdblstacksize;
171         intrusive_ptr<FunctionVM> functionvm;
172         TraceThreadData *threaddata;
173         #if (SYS_FUNCTIONS == 1)
174         DBL *dblstack;
175         #endif
176         int nextArgument;
177 
178         void SetLocal(unsigned int k, DBL v);
179         DBL GetLocal(unsigned int k);
180 };
181 
182 
183 #define OPCODE(i,s,d) ((i << 6) | (s << 3) | d)
184 
185 #define OPCODE_ADD    OPCODE(0,0,0)
186 #define OPCODE_SUB    OPCODE(1,0,0)
187 #define OPCODE_MUL    OPCODE(2,0,0)
188 #define OPCODE_DIV    OPCODE(3,0,0)
189 #define OPCODE_MOD    OPCODE(4,0,0)
190 #define OPCODE_MOVE   OPCODE(5,0,0)
191 #define OPCODE_CMP    OPCODE(6,0,0)
192 #define OPCODE_NEG    OPCODE(7,0,0)
193 #define OPCODE_ABS    OPCODE(8,0,0)
194 #define OPCODE_ADDI   OPCODE(9,0,0)
195 #define OPCODE_SUBI   OPCODE(9,1,0)
196 #define OPCODE_MULI   OPCODE(9,2,0)
197 #define OPCODE_DIVI   OPCODE(9,3,0)
198 #define OPCODE_MODI   OPCODE(9,4,0)
199 #define OPCODE_LOADI  OPCODE(9,5,0)
200 #define OPCODE_CMPI   OPCODE(9,6,0)
201 #define OPCODE_SEQ    OPCODE(10,0,0)
202 #define OPCODE_SNE    OPCODE(10,1,0)
203 #define OPCODE_SLT    OPCODE(10,2,0)
204 #define OPCODE_SLE    OPCODE(10,3,0)
205 #define OPCODE_SGT    OPCODE(10,4,0)
206 #define OPCODE_SGE    OPCODE(10,5,0)
207 #define OPCODE_TEQ    OPCODE(10,6,0)
208 #define OPCODE_TNE    OPCODE(10,7,0)
209 #define OPCODE_LOAD   OPCODE(11,0,0)
210 #define OPCODE_STORE  OPCODE(12,0,0)
211 #define OPCODE_BEQ    OPCODE(13,0,0)
212 #define OPCODE_BNE    OPCODE(13,1,0)
213 #define OPCODE_BLT    OPCODE(13,2,0)
214 #define OPCODE_BLE    OPCODE(13,3,0)
215 #define OPCODE_BGT    OPCODE(13,4,0)
216 #define OPCODE_BGE    OPCODE(13,5,0)
217 #define OPCODE_XEQ    OPCODE(14,0,0)
218 #define OPCODE_XNE    OPCODE(14,1,0)
219 #define OPCODE_XLT    OPCODE(14,2,0)
220 #define OPCODE_XLE    OPCODE(14,3,0)
221 #define OPCODE_XGT    OPCODE(14,4,0)
222 #define OPCODE_XGE    OPCODE(14,5,0)
223 #define OPCODE_XDZ    OPCODE(14,6,0)
224 // #define OPCODE_XINF   OPCODE(14,7,0)
225 #define OPCODE_JSR    OPCODE(15,0,0)
226 #define OPCODE_JMP    OPCODE(15,0,1)
227 #define OPCODE_RTS    OPCODE(15,0,2)
228 #define OPCODE_CALL   OPCODE(15,0,3)
229 #define OPCODE_SYS1   OPCODE(15,0,4)
230 #define OPCODE_SYS2   OPCODE(15,0,5)
231 #define OPCODE_TRAP   OPCODE(15,0,6)
232 #define OPCODE_TRAPS  OPCODE(15,0,7)
233 #define OPCODE_GROW   OPCODE(15,1,0)
234 #define OPCODE_PUSH   OPCODE(15,1,1)
235 #define OPCODE_POP    OPCODE(15,1,2)
236 #define OPCODE_DEBUG  OPCODE(15,1,5)
237 #define OPCODE_NOP    OPCODE(15,3,7)
238 
239 #define MAKE_INSTRUCTION(op, k) ((((k) << 12) & 0xfffff000) | ((op) & 0x00000fff))
240 
241 #define GET_OP(w) ((w) & 0x00000fff)
242 #define GET_K(w) (((w) >> 12) & 0x000fffff)
243 
244 extern const Opcode POVFPU_Opcodes[];
245 
246 extern const Sys1 POVFPU_Sys1Table[];
247 extern const Sys2 POVFPU_Sys2Table[];
248 
249 extern const unsigned int POVFPU_Sys1TableSize;
250 extern const unsigned int POVFPU_Sys2TableSize;
251 
252 void POVFPU_Exception(FPUContext *context, FUNCTION fn, const char *msg = nullptr);
253 DBL POVFPU_RunDefault(FPUContext *context, FUNCTION k);
254 
255 void FNCode_Delete(FunctionCode *);
256 
257 class FunctionVM : public GenericFunctionContextFactory
258 {
259         friend void POVFPU_Exception(FPUContext *, FUNCTION, const char *);
260         friend DBL POVFPU_RunDefault(FPUContext *, FUNCTION);
261 
262     public:
263 
264         class CustomFunction : public GenericScalarFunction
265         {
266             public:
267                 CustomFunction(FunctionVM* pVm, FUNCTION_PTR pFn);
268                 virtual ~CustomFunction();
269                 virtual GenericFunctionContextPtr AcquireContext(TraceThreadData* pThreadData);
270                 virtual void ReleaseContext(GenericFunctionContextPtr pContext);
271                 virtual void InitArguments(GenericFunctionContextPtr pContext);
272                 virtual void PushArgument(GenericFunctionContextPtr pContext, DBL arg);
273                 virtual DBL Execute(GenericFunctionContextPtr pContext);
274                 virtual GenericScalarFunctionPtr Clone() const;
275                 virtual const SourceInfo* GetSourceInfo() const;
276             protected:
277                 intrusive_ptr<FunctionVM> mpVm;
278                 FUNCTION_PTR mpFn;
279                 static inline FPUContext* GetFPUContextPtr(GenericFunctionContextPtr pContext);
280         };
281 
282         FunctionVM();
283         virtual ~FunctionVM();
284 
285         void Reset();
286 
287         void SetGlobal(unsigned int k, DBL v);
288         DBL GetGlobal(unsigned int k);
289 
290         FunctionCode *GetFunction(FUNCTION k);
291         FunctionCode *GetFunctionAndReference(FUNCTION k);
292 
293         unsigned int AddConstant(DBL v);
294 
295         FUNCTION AddFunction(FunctionCode *f);
296         void RemoveFunction(FUNCTION fn);
297 
298         FUNCTION_PTR CopyFunction(FUNCTION_PTR pK);
299         void DestroyFunction(FUNCTION_PTR pK);
300 
301         virtual GenericFunctionContextPtr CreateFunctionContext(TraceThreadData* pTd);
302 
303     private:
304 
305         vector<FunctionEntry> functions;
306         FUNCTION nextUnreferenced;
307         vector<DBL> globals;
308         vector<DBL> consts;
309 };
310 
311 }
312 
313 #endif // POVRAY_VM_FNPOVFPU_H
314