toctave.jitter (4762B)
1 # toctave VM specification 2 3 # Copyright (C) 2020-2021, Mohammad-Reza Nabipoor 4 # SPDX-License-Identifier: GPL-3.0-or-later 5 6 vm 7 set prefix "toctave" 8 end 9 10 stack s 11 long-name "mainstack" 12 c-element-type "double" 13 c-initial-value "0.0" 14 element-no 4096 15 guard-underflow 16 guard-overflow 17 tos-optimized 18 end 19 20 wrapped-functions 21 pow 22 toctave_var 23 toctave_var_set 24 end 25 26 state-struct-runtime-c 27 code 28 double result; 29 30 jitter_program_point point; 31 int status; 32 void* env; 33 end 34 end 35 36 state-initialization-c 37 code 38 jitter_state_runtime->result = 0.0 / 0.0; // NaN 39 jitter_state_runtime->point = NULL; 40 jitter_state_runtime->status = -1; 41 end 42 end 43 44 early-header-c 45 code 46 #include <math.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <stdint.h> 50 51 _Bool toctave_var(void* env, const char* name, double* val); 52 void toctave_var_set(void* env, const char* name, double val); 53 54 union double_uint64 55 { 56 double d; 57 uint64_t u64; 58 }; 59 60 #define TOCTAVE_STATUS_DONE 0 61 #define TOCTAVE_STATUS_YIELD 1 62 end 63 end 64 65 initial-vm1-c 66 code 67 #define nan_unbox_uint(p) (((p) & /*mask*/(((uint64_t)1 << 51) - 1)) << 3) 68 #define nan_unbox(dbl) nan_unbox_uint(((union double_uint64){ .d = (dbl) }).u64) 69 end 70 end 71 72 initial-vm2-c 73 code 74 #define nan_unbox_uint(p) (((p) & /*mask*/(((uint64_t)1 << 51) - 1)) << 3) 75 #define nan_unbox(dbl) nan_unbox_uint(((union double_uint64){ .d = (dbl) }).u64) 76 end 77 end 78 79 printer-c 80 code 81 82 // Jitter uses this function to print literal values in instructions (like 83 // push instruction) 84 static void 85 double_literal_printer(jitter_print_context ctx, uintptr_t n) 86 { 87 union double_uint64 x; 88 89 x.u64 = n; 90 jitter_print_double(ctx, x.d); 91 } 92 93 static void 94 var_literal_printer(jitter_print_context ctx, uintptr_t n) 95 { 96 union double_uint64 x; 97 98 x.u64 = n; 99 n = nan_unbox(x.d); // reusing `n` 100 jitter_print_char_star(ctx, (const char*)n); 101 } 102 103 end 104 end 105 106 # Stack manipulation 107 108 # Push a double on the stack 109 # Stack: ( -- a) 110 instruction push (?n double_literal_printer) 111 code 112 union double_uint64 x; 113 114 x.u64 = JITTER_ARGN0; 115 TOCTAVE_PUSH_MAINSTACK(x.d); 116 end 117 end 118 119 # Pop the value on stack and save it into `result` field 120 # Stack: (a -- ) 121 instruction pop () 122 code 123 TOCTAVE_STATE_RUNTIME_FIELD(result) = TOCTAVE_TOP_MAINSTACK(); 124 TOCTAVE_DROP_MAINSTACK(); 125 end 126 end 127 128 # Drop the value on stack 129 # Stack: (a -- ) 130 instruction drop () 131 code 132 TOCTAVE_DROP_MAINSTACK(); 133 end 134 end 135 136 # Push the value of variable onto the stack 137 # Stack: ( -- a) 138 instruction pushvar (?n var_literal_printer) # , ?f) 139 code 140 const char* name = (const char*)nan_unbox_uint(JITTER_ARGN0); 141 // For simplicity, we assume the variable is defined 142 double d; 143 _Bool found = toctave_var(TOCTAVE_STATE_RUNTIME_FIELD(env), name, &d); 144 145 // JITTER_BRANCH_FAST_IF_NONZERO(found, JITTER_ARGF1); 146 if (!found) 147 d = 0.0 / 0.0; // Put a NaN there 148 TOCTAVE_PUSH_MAINSTACK(d); 149 end 150 end 151 152 # Pop the value on the stack and save it into variable 153 # Stack: (a -- ) 154 instruction popvar (?n var_literal_printer) 155 code 156 const char* name = (const char*)nan_unbox_uint(JITTER_ARGN0); 157 158 toctave_var_set( 159 TOCTAVE_STATE_RUNTIME_FIELD(env), name, TOCTAVE_TOP_MAINSTACK()); 160 TOCTAVE_DROP_MAINSTACK(); 161 end 162 end 163 164 instruction pushnan () 165 code 166 TOCTAVE_PUSH_MAINSTACK(0.0 / 0.0); 167 end 168 end 169 170 # Arithmetic 171 172 # Stack: (a b -- a^b) 173 instruction pow () 174 code 175 TOCTAVE_TOP_MAINSTACK() = 176 pow(/* a */ TOCTAVE_UNDER_TOP_MAINSTACK(), 177 /* b */ TOCTAVE_TOP_MAINSTACK()); /* Stack: (a a^b) */ 178 TOCTAVE_NIP_MAINSTACK(); /* Stack: (a^b) */ 179 end 180 end 181 182 # Stack: (a b -- a*b) 183 instruction mul () 184 code 185 TOCTAVE_TOP_MAINSTACK() = 186 /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() * 187 /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */ 188 TOCTAVE_NIP_MAINSTACK(); /* Stack: (a*b) */ 189 end 190 end 191 192 # Stack: (a b -- a/b) 193 instruction div () 194 non-relocatable 195 code 196 TOCTAVE_TOP_MAINSTACK() = 197 /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() / 198 /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */ 199 end 200 end 201 202 # Stack: (a b -- a+b) 203 instruction add () 204 code 205 TOCTAVE_TOP_MAINSTACK() = 206 /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() + 207 /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */ 208 end 209 end 210 211 # Stack: (a b -- a-b) 212 instruction sub () 213 code 214 TOCTAVE_TOP_MAINSTACK() = 215 /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() - 216 /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */ 217 end 218 end 219 220 # Control Flow 221 222 instruction yield (?l) 223 code 224 TOCTAVE_STATE_RUNTIME_FIELD(point) = JITTER_ARGP0; 225 TOCTAVE_STATE_RUNTIME_FIELD(status) = TOCTAVE_STATUS_YIELD; 226 end 227 end 228 229 instruction done () 230 code 231 TOCTAVE_STATE_RUNTIME_FIELD(point) = NULL; 232 TOCTAVE_STATE_RUNTIME_FIELD(status) = TOCTAVE_STATUS_DONE; 233 end 234 end