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