blob: a0553f76a79942d83686f3e5010e6133c37f13af [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_STANDALONE
9
Ethan Nicholasae9633b2019-05-24 12:46:34 -040010#include "include/core/SkPoint3.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkRasterPipeline.h"
Brian Osman07c117b2019-05-23 12:51:06 -070012#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040013#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/sksl/SkSLInterpreter.h"
15#include "src/sksl/ir/SkSLBinaryExpression.h"
16#include "src/sksl/ir/SkSLExpressionStatement.h"
17#include "src/sksl/ir/SkSLForStatement.h"
18#include "src/sksl/ir/SkSLFunctionCall.h"
19#include "src/sksl/ir/SkSLFunctionReference.h"
20#include "src/sksl/ir/SkSLIfStatement.h"
21#include "src/sksl/ir/SkSLIndexExpression.h"
22#include "src/sksl/ir/SkSLPostfixExpression.h"
23#include "src/sksl/ir/SkSLPrefixExpression.h"
24#include "src/sksl/ir/SkSLProgram.h"
25#include "src/sksl/ir/SkSLStatement.h"
26#include "src/sksl/ir/SkSLTernaryExpression.h"
27#include "src/sksl/ir/SkSLVarDeclarations.h"
28#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
29#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040030
31namespace SkSL {
32
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040033static constexpr int UNINITIALIZED = 0xDEADBEEF;
34
Mike Kleine7007382019-05-21 08:36:32 -050035Interpreter::Interpreter(std::unique_ptr<Program> program,
36 std::unique_ptr<ByteCode> byteCode,
Ethan Nicholasdfcad062019-05-07 12:53:34 -040037 Interpreter::Value inputs[])
38 : fProgram(std::move(program))
Mike Kleine7007382019-05-21 08:36:32 -050039 , fByteCode(std::move(byteCode))
40 , fGlobals(fByteCode->fGlobalCount, UNINITIALIZED) {
Brian Osmand369a5e2019-05-09 13:13:25 -040041 this->setInputs(inputs);
42}
43
44void Interpreter::setInputs(Interpreter::Value inputs[]) {
Mike Kleine7007382019-05-21 08:36:32 -050045 for (uint8_t slot : fByteCode->fInputSlots) {
46 fGlobals[slot] = *inputs++;
Ethan Nicholasdfcad062019-05-07 12:53:34 -040047 }
48}
49
50void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
51 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040052#ifdef TRACE
53 this->disassemble(f);
54#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040055 Value smallStack[128];
56 std::unique_ptr<Value[]> largeStack;
57 Value* stack = smallStack;
Brian Osman226668a2019-05-14 16:47:30 -040058 if ((int) SK_ARRAY_COUNT(smallStack) < f.fStackCount) {
59 largeStack.reset(new Value[f.fStackCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040060 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040061 }
Mike Kleine7007382019-05-21 08:36:32 -050062
63 if (f.fParameterCount) {
64 memcpy(stack, args, f.fParameterCount * sizeof(Value));
65 }
66 this->innerRun(f, stack, outReturn);
67
68 for (const Variable* p : f.fDeclaration.fParameters) {
Brian Osman07c117b2019-05-23 12:51:06 -070069 const int nvalues = ByteCodeGenerator::SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040070 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
Mike Kleine7007382019-05-21 08:36:32 -050071 memcpy(args, stack, nvalues * sizeof(Value));
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040072 }
Mike Kleine7007382019-05-21 08:36:32 -050073 args += nvalues;
74 stack += nvalues;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040075 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040076}
77
Mike Klein76346ac2019-05-17 11:57:10 -050078template <typename T>
79static T unaligned_load(const void* ptr) {
80 T val;
81 memcpy(&val, ptr, sizeof(val));
82 return val;
83}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040084
Mike Kleine7007382019-05-21 08:36:32 -050085#define READ8() (*(ip++))
Mike Klein76346ac2019-05-17 11:57:10 -050086#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
87#define READ32() (ip += 4, unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040088
Brian Osman3e833e12019-05-23 13:23:24 -070089#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040090 case ByteCodeInstruction::op: printf(text); break; \
91 case ByteCodeInstruction::op##2: printf(text "2"); break; \
92 case ByteCodeInstruction::op##3: printf(text "3"); break; \
93 case ByteCodeInstruction::op##4: printf(text "4"); break;
94
Brian Osman1e855b22019-05-29 15:21:52 -040095#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
96 case ByteCodeInstruction::op: printf(text); break; \
97 case ByteCodeInstruction::op##2: printf(text "2"); break; \
98 case ByteCodeInstruction::op##3: printf(text "3"); break; \
99 case ByteCodeInstruction::op##4: printf(text "4"); break; \
100 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
101
Brian Osman3e833e12019-05-23 13:23:24 -0700102static const uint8_t* disassemble_instruction(const uint8_t* ip) {
103 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -0400104 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -0700105 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman16e6fd52019-05-29 11:19:00 -0400106 VECTOR_DISASSEMBLE(kAndB, "andb")
107 VECTOR_DISASSEMBLE(kAndI, "andb")
Brian Osman3e833e12019-05-23 13:23:24 -0700108 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
109 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
110 case ByteCodeInstruction::kCallExternal: {
111 int argumentCount = READ8();
112 int returnCount = READ8();
113 int externalValue = READ8();
114 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
115 break;
116 }
117 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
118 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -0400119 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
120 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -0700121 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
122 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
123 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
124 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
125 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
126 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
127 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
128 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
129 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
130 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
131 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
132 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
133 case ByteCodeInstruction::kConditionalBranch:
134 printf("conditionalbranch %d", READ16());
135 break;
136 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
137 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
138 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
139 VECTOR_DISASSEMBLE(kCos, "cos")
140 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400141 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -0700142 VECTOR_DISASSEMBLE(kDivideS, "divideS")
143 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -0400144 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -0700145 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
146 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
147 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
148 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
149 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
150 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
151 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
152 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
153 case ByteCodeInstruction::kLoadSwizzle: {
154 int target = READ8();
155 int count = READ8();
156 printf("loadswizzle %d %d", target, count);
157 for (int i = 0; i < count; ++i) {
158 printf(", %d", READ8());
159 }
160 break;
161 }
162 case ByteCodeInstruction::kLoadSwizzleGlobal: {
163 int target = READ8();
164 int count = READ8();
165 printf("loadswizzleglobal %d %d", target, count);
166 for (int i = 0; i < count; ++i) {
167 printf(", %d", READ8());
168 }
169 break;
170 }
171 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
172 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
173 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400174 case ByteCodeInstruction::kMatrixToMatrix: {
175 int srcCols = READ8();
176 int srcRows = READ8();
177 int dstCols = READ8();
178 int dstRows = READ8();
179 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
180 break;
181 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400182 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400183 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700184 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400185 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700186 VECTOR_DISASSEMBLE(kNegateI, "negatei")
187 VECTOR_DISASSEMBLE(kNot, "not")
188 VECTOR_DISASSEMBLE(kOrB, "orb")
189 VECTOR_DISASSEMBLE(kOrI, "ori")
Brian Osman1e855b22019-05-29 15:21:52 -0400190 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700191 case ByteCodeInstruction::kPushImmediate: {
192 uint32_t v = READ32();
193 union { uint32_t u; float f; } pun = { v };
194 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
195 break;
196 }
197 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
198 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
199 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
200 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
201 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
202 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
203 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
204 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400205 case ByteCodeInstruction::kScalarToMatrix: {
206 int cols = READ8();
207 int rows = READ8();
208 printf("scalartomatrix %dx%d", cols, rows);
209 break;
210 }
Brian Osman3e833e12019-05-23 13:23:24 -0700211 VECTOR_DISASSEMBLE(kSin, "sin")
212 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
213 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
214 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
215 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
216 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
217 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
218 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
219 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
220 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
221 case ByteCodeInstruction::kStoreSwizzle: {
222 int target = READ8();
223 int count = READ8();
224 printf("storeswizzle %d %d", target, count);
225 for (int i = 0; i < count; ++i) {
226 printf(", %d", READ8());
227 }
228 break;
229 }
230 case ByteCodeInstruction::kStoreSwizzleGlobal: {
231 int target = READ8();
232 int count = READ8();
233 printf("storeswizzleglobal %d %d", target, count);
234 for (int i = 0; i < count; ++i) {
235 printf(", %d", READ8());
236 }
237 break;
238 }
239 case ByteCodeInstruction::kStoreSwizzleIndirect: {
240 int count = READ8();
241 printf("storeswizzleindirect %d", count);
242 for (int i = 0; i < count; ++i) {
243 printf(", %d", READ8());
244 }
245 break;
246 }
247 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
248 int count = READ8();
249 printf("storeswizzleindirectglobal %d", count);
250 for (int i = 0; i < count; ++i) {
251 printf(", %d", READ8());
252 }
253 break;
254 }
255 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
256 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
257 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400258 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700259 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
260 case ByteCodeInstruction::kSwizzle: {
261 printf("swizzle %d, ", READ8());
262 int count = READ8();
263 printf("%d", count);
264 for (int i = 0; i < count; ++i) {
265 printf(", %d", READ8());
266 }
267 break;
268 }
269 VECTOR_DISASSEMBLE(kTan, "tan")
270 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
271 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
272 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
273 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
274 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
275 }
276 return ip;
277}
278
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400279void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400280 const uint8_t* ip = f.fCode.data();
281 while (ip < f.fCode.data() + f.fCode.size()) {
282 printf("%d: ", (int) (ip - f.fCode.data()));
Brian Osman3e833e12019-05-23 13:23:24 -0700283 ip = disassemble_instruction(ip);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400284 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400285 }
286}
287
Mike Klein459aed12019-05-21 15:46:36 -0500288#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500289 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500290 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500291 POP(); \
292 /* fall through */ \
293 case ByteCodeInstruction::base ## 3: { \
294 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500295 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500296 POP(); \
297 } /* fall through */ \
298 case ByteCodeInstruction::base ## 2: { \
299 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500300 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500301 POP(); \
302 } /* fall through */ \
303 case ByteCodeInstruction::base: { \
304 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500305 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500306 POP(); \
307 break; \
308 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400309
Brian Osman1e855b22019-05-29 15:21:52 -0400310#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
311 VECTOR_BINARY_OP(base, field, op) \
312 case ByteCodeInstruction::base ## N: { \
313 int count = READ8(); \
314 for (int i = count; i > 0; --i) { \
315 sp[-count] = sp[-count].field op sp[0].field; \
316 POP(); \
317 } \
318 break; \
319 }
320
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400321#define VECTOR_BINARY_FN(base, field, fn) \
322 case ByteCodeInstruction::base ## 4: \
323 sp[-4] = fn(sp[-4].field, sp[0].field); \
324 POP(); \
325 /* fall through */ \
326 case ByteCodeInstruction::base ## 3: { \
327 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
328 sp[target] = fn(sp[target].field, sp[0].field); \
329 POP(); \
330 } /* fall through */ \
331 case ByteCodeInstruction::base ## 2: { \
332 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
333 sp[target] = fn(sp[target].field, sp[0].field); \
334 POP(); \
335 } /* fall through */ \
336 case ByteCodeInstruction::base: { \
337 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
338 sp[target] = fn(sp[target].field, sp[0].field); \
339 POP(); \
340 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500341 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400342
Mike Klein459aed12019-05-21 15:46:36 -0500343#define VECTOR_UNARY_FN(base, fn, field) \
344 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
345 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
346 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
347 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400348 break;
349
Brian Osman226668a2019-05-14 16:47:30 -0400350struct StackFrame {
351 const uint8_t* fCode;
352 const uint8_t* fIP;
353 Interpreter::Value* fStack;
354};
355
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400356static float mix(float start, float end, float t) {
357 return start * (1 - t) + end * t;
358}
359
Mike Kleine7007382019-05-21 08:36:32 -0500360void Interpreter::innerRun(const ByteCodeFunction& f, Value* stack, Value* outReturn) {
361 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
362
363 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
364 auto PUSH = [&](Value v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
365
Brian Osman226668a2019-05-14 16:47:30 -0400366 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400367 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400368 std::vector<StackFrame> frames;
369
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400370 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400371#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700372 printf("at %3d ", (int) (ip - code));
373 disassemble_instruction(ip);
374 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400375#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700376 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500378 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400379 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman16e6fd52019-05-29 11:19:00 -0400380 VECTOR_BINARY_OP(kAndB, fBool, &&)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400381
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400382 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400383 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400384 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400385
Brian Osman226668a2019-05-14 16:47:30 -0400386 case ByteCodeInstruction::kCall: {
387 // Precursor code has pushed all parameters to the stack. Update our bottom of
388 // stack to point at the first parameter, and our sp to point past those parameters
389 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500390 int target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400391 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
392 frames.push_back({ code, ip, stack });
393 ip = code = fun->fCode.data();
394 stack = sp - fun->fParameterCount + 1;
395 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
396 break;
397 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400398
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400399 case ByteCodeInstruction::kCallExternal: {
400 int argumentCount = READ8();
401 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500402 int target = READ8();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400403 ExternalValue* v = fByteCode->fExternalValues[target];
404 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500405
406 Value tmp[4];
407 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmp));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400408 v->call(sp, tmp);
409 memcpy(sp, tmp, returnCount * sizeof(Value));
410 sp += returnCount - 1;
411 break;
412 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400413
Mike Kleinc1999982019-05-21 13:03:49 -0500414 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400415 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500416 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400417 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500418 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
419 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
420 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
421 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
422 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
423 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
424 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
425 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
426 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
427 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
428 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
429 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400430
Mike Kleine7007382019-05-21 08:36:32 -0500431 case ByteCodeInstruction::kConditionalBranch: {
432 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400433 if (POP().fBool) {
Mike Kleine7007382019-05-21 08:36:32 -0500434 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400435 }
436 break;
Mike Kleine7007382019-05-21 08:36:32 -0500437 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400438
439 case ByteCodeInstruction::kConvertFtoI4: sp[-3].fSigned = (int)sp[-3].fFloat;
440 case ByteCodeInstruction::kConvertFtoI3: sp[-2].fSigned = (int)sp[-2].fFloat;
441 case ByteCodeInstruction::kConvertFtoI2: sp[-1].fSigned = (int)sp[-1].fFloat;
442 case ByteCodeInstruction::kConvertFtoI: sp[ 0].fSigned = (int)sp[ 0].fFloat;
443 break;
444
445 case ByteCodeInstruction::kConvertStoF4: sp[-3].fFloat = sp[-3].fSigned;
446 case ByteCodeInstruction::kConvertStoF3: sp[-2].fFloat = sp[-2].fSigned;
447 case ByteCodeInstruction::kConvertStoF2: sp[-1].fFloat = sp[-1].fSigned;
448 case ByteCodeInstruction::kConvertStoF : sp[ 0].fFloat = sp[ 0].fSigned;
449 break;
450
451 case ByteCodeInstruction::kConvertUtoF4: sp[-3].fFloat = sp[-3].fUnsigned;
452 case ByteCodeInstruction::kConvertUtoF3: sp[-2].fFloat = sp[-2].fUnsigned;
453 case ByteCodeInstruction::kConvertUtoF2: sp[-1].fFloat = sp[-1].fUnsigned;
454 case ByteCodeInstruction::kConvertUtoF : sp[ 0].fFloat = sp[ 0].fUnsigned;
455 break;
456
Mike Klein459aed12019-05-21 15:46:36 -0500457 VECTOR_UNARY_FN(kCos, cosf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400458
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400459 case ByteCodeInstruction::kCross: {
460 SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(sp[-5].fFloat,
461 sp[-4].fFloat,
462 sp[-3].fFloat),
463 SkPoint3::Make(sp[-2].fFloat,
464 sp[-1].fFloat,
465 sp[ 0].fFloat));
466 sp -= 3;
467 sp[-2] = cross.fX;
468 sp[-1] = cross.fY;
469 sp[ 0] = cross.fZ;
470 break;
471 }
472
Mike Kleine7007382019-05-21 08:36:32 -0500473 case ByteCodeInstruction::kDebugPrint: {
474 Value v = POP();
475 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400476 break;
Mike Kleine7007382019-05-21 08:36:32 -0500477 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400478
Mike Kleinc1999982019-05-21 13:03:49 -0500479 VECTOR_BINARY_OP(kDivideS, fSigned, /)
480 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400481 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500482
483 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
484 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
485 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
486 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
487 break;
488
Brian Osman07c117b2019-05-23 12:51:06 -0700489 case ByteCodeInstruction::kDupN: {
490 int count = READ8();
491 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
492 sp += count;
493 break;
494 }
495
Mike Kleine7007382019-05-21 08:36:32 -0500496 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
497 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
498 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
499 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
500 ++ip;
501 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
502 break;
503
504 case ByteCodeInstruction::kLoadGlobal4: sp[4] = fGlobals[*ip + 3];
505 case ByteCodeInstruction::kLoadGlobal3: sp[3] = fGlobals[*ip + 2];
506 case ByteCodeInstruction::kLoadGlobal2: sp[2] = fGlobals[*ip + 1];
507 case ByteCodeInstruction::kLoadGlobal : sp[1] = fGlobals[*ip + 0];
508 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700509 sp += (int)inst -
510 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500511 break;
512
Brian Osman07c117b2019-05-23 12:51:06 -0700513 case ByteCodeInstruction::kLoadExtended: {
514 int count = READ8();
515 int src = POP().fSigned;
516 memcpy(sp + 1, &stack[src], count * sizeof(Value));
517 sp += count;
518 break;
519 }
520
521 case ByteCodeInstruction::kLoadExtendedGlobal: {
522 int count = READ8();
523 int src = POP().fSigned;
524 SkASSERT(src + count <= (int) fGlobals.size());
525 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
526 sp += count;
527 break;
528 }
529
Mike Kleine7007382019-05-21 08:36:32 -0500530 case ByteCodeInstruction::kLoadSwizzle: {
531 int src = READ8();
532 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400533 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400534 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400535 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400536 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400537 break;
Mike Kleine7007382019-05-21 08:36:32 -0500538 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400539
Mike Kleine7007382019-05-21 08:36:32 -0500540 case ByteCodeInstruction::kLoadSwizzleGlobal: {
541 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400542 SkASSERT(src < (int) fGlobals.size());
Mike Kleine7007382019-05-21 08:36:32 -0500543 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400544 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400545 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400546 }
547 ip += count;
548 break;
Mike Kleine7007382019-05-21 08:36:32 -0500549 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400550
Brian Osman29e013d2019-05-28 17:16:03 -0400551 case ByteCodeInstruction::kMatrixToMatrix: {
552 int srcCols = READ8();
553 int srcRows = READ8();
554 int dstCols = READ8();
555 int dstRows = READ8();
556 SkASSERT(srcCols >= 2 && srcCols <= 4);
557 SkASSERT(srcRows >= 2 && srcRows <= 4);
558 SkASSERT(dstCols >= 2 && dstCols <= 4);
559 SkASSERT(dstRows >= 2 && dstRows <= 4);
560 SkMatrix44 m;
561 for (int c = srcCols - 1; c >= 0; --c) {
562 for (int r = srcRows - 1; r >= 0; --r) {
563 m.set(r, c, POP().fFloat);
564 }
565 }
566 for (int c = 0; c < dstCols; ++c) {
567 for (int r = 0; r < dstRows; ++r) {
568 PUSH(m.get(r, c));
569 }
570 }
571 break;
572 }
573
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400574 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
575 case ByteCodeInstruction::kMix4:
576 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
577 // fall through
578 case ByteCodeInstruction::kMix3: {
579 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
580 int target = 2 - count * 2;
581 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
582 // fall through
583 }
584 case ByteCodeInstruction::kMix2: {
585 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
586 int target = 1 - count * 2;
587 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
588 // fall through
589 }
590 case ByteCodeInstruction::kMix: {
591 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
592 int target = -count * 2;
593 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
594 sp -= 1 + count;
595 break;
596 }
597
Mike Kleinc1999982019-05-21 13:03:49 -0500598 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400599 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400600
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400601 case ByteCodeInstruction::kNot:
Mike Kleine7007382019-05-21 08:36:32 -0500602 sp[0].fBool = !sp[0].fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400603 break;
Mike Kleine7007382019-05-21 08:36:32 -0500604
Mike Kleinc1999982019-05-21 13:03:49 -0500605 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
606 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
607 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
608 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500609 break;
610
Brian Osman1e855b22019-05-29 15:21:52 -0400611 case ByteCodeInstruction::kNegateFN: {
612 int count = READ8();
613 for (int i = count - 1; i >= 0; --i) {
614 sp[-i] = -sp[-i].fFloat;
615 }
616 break;
617 }
618
Mike Kleinc1999982019-05-21 13:03:49 -0500619 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
620 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
621 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
622 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp [0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500623 break;
624
Brian Osman16e6fd52019-05-29 11:19:00 -0400625 VECTOR_BINARY_OP(kOrB, fBool, ||)
626
Mike Kleine7007382019-05-21 08:36:32 -0500627 case ByteCodeInstruction::kPop4: POP();
628 case ByteCodeInstruction::kPop3: POP();
629 case ByteCodeInstruction::kPop2: POP();
630 case ByteCodeInstruction::kPop : POP();
631 break;
632
Brian Osman07c117b2019-05-23 12:51:06 -0700633 case ByteCodeInstruction::kPopN:
634 sp -= READ8();
635 break;
636
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400637 case ByteCodeInstruction::kPushImmediate:
Mike Kleine7007382019-05-21 08:36:32 -0500638 PUSH(READ32());
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400639 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400640
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400641 case ByteCodeInstruction::kReadExternal: // fall through
642 case ByteCodeInstruction::kReadExternal2: // fall through
643 case ByteCodeInstruction::kReadExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500644 case ByteCodeInstruction::kReadExternal4: {
645 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400646 fByteCode->fExternalValues[src]->read(sp + 1);
Mike Kleine7007382019-05-21 08:36:32 -0500647 sp += (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400648 break;
Mike Kleine7007382019-05-21 08:36:32 -0500649 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400650
Mike Kleinc1999982019-05-21 13:03:49 -0500651 VECTOR_BINARY_FN(kRemainderF, fFloat, fmodf)
652 VECTOR_BINARY_OP(kRemainderS, fSigned, %)
653 VECTOR_BINARY_OP(kRemainderU, fUnsigned, %)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400654
Mike Kleine7007382019-05-21 08:36:32 -0500655 case ByteCodeInstruction::kReturn: {
656 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400657 if (frames.empty()) {
658 if (outReturn) {
659 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
660 }
661 return;
662 } else {
663 // When we were called, 'stack' was positioned at the old top-of-stack (where
664 // our parameters were placed). So copy our return values to that same spot.
665 memmove(stack, sp - count + 1, count * sizeof(Value));
666
667 // Now move the stack pointer to the end of the just-pushed return values,
668 // and restore everything else.
669 const StackFrame& frame(frames.back());
670 sp = stack + count - 1;
671 stack = frame.fStack;
672 code = frame.fCode;
673 ip = frame.fIP;
674 frames.pop_back();
675 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400676 }
Mike Kleine7007382019-05-21 08:36:32 -0500677 }
678
Brian Osman29e013d2019-05-28 17:16:03 -0400679 case ByteCodeInstruction::kScalarToMatrix: {
680 int cols = READ8();
681 int rows = READ8();
682 Value v = POP();
683 for (int c = 0; c < cols; ++c) {
684 for (int r = 0; r < rows; ++r) {
685 PUSH(c == r ? v : 0.0f);
686 }
687 }
688 break;
689 }
690
Mike Klein459aed12019-05-21 15:46:36 -0500691 VECTOR_UNARY_FN(kSin, sinf, fFloat)
692 VECTOR_UNARY_FN(kSqrt, sqrtf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400693
Mike Kleine7007382019-05-21 08:36:32 -0500694 case ByteCodeInstruction::kStore4: stack[*ip + 3] = POP();
695 case ByteCodeInstruction::kStore3: stack[*ip + 2] = POP();
696 case ByteCodeInstruction::kStore2: stack[*ip + 1] = POP();
697 case ByteCodeInstruction::kStore : stack[*ip + 0] = POP();
698 ++ip;
699 break;
700
701 case ByteCodeInstruction::kStoreGlobal4: fGlobals[*ip + 3] = POP();
702 case ByteCodeInstruction::kStoreGlobal3: fGlobals[*ip + 2] = POP();
703 case ByteCodeInstruction::kStoreGlobal2: fGlobals[*ip + 1] = POP();
704 case ByteCodeInstruction::kStoreGlobal : fGlobals[*ip + 0] = POP();
705 ++ip;
706 break;
707
Brian Osman07c117b2019-05-23 12:51:06 -0700708 case ByteCodeInstruction::kStoreExtended: {
709 int count = READ8();
710 int target = POP().fSigned;
711 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
712 sp -= count;
713 break;
714 }
715 case ByteCodeInstruction::kStoreExtendedGlobal: {
716 int count = READ8();
717 int target = POP().fSigned;
718 SkASSERT(target + count <= (int) fGlobals.size());
719 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
720 sp -= count;
721 break;
722 }
723
Mike Kleine7007382019-05-21 08:36:32 -0500724 case ByteCodeInstruction::kStoreSwizzle: {
725 int target = READ8();
726 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400727 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400728 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400729 }
Brian Osman1091f022019-05-16 09:42:16 -0400730 ip += count;
731 break;
Mike Kleine7007382019-05-21 08:36:32 -0500732 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400733
Mike Kleine7007382019-05-21 08:36:32 -0500734 case ByteCodeInstruction::kStoreSwizzleGlobal: {
735 int target = READ8();
736 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400737 for (int i = count - 1; i >= 0; --i) {
738 fGlobals[target + *(ip + i)] = POP();
739 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400740 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400741 break;
Mike Kleine7007382019-05-21 08:36:32 -0500742 }
Brian Osman07c117b2019-05-23 12:51:06 -0700743 case ByteCodeInstruction::kStoreSwizzleIndirect: {
744 int target = POP().fSigned;
745 int count = READ8();
746 for (int i = count - 1; i >= 0; --i) {
747 stack[target + *(ip + i)] = POP();
748 }
749 ip += count;
750 break;
751 }
752 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
753 int target = POP().fSigned;
754 int count = READ8();
755 for (int i = count - 1; i >= 0; --i) {
756 fGlobals[target + *(ip + i)] = POP();
757 }
758 ip += count;
759 break;
760 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400761
Mike Kleinc1999982019-05-21 13:03:49 -0500762 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400763 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400764
Mike Kleine7007382019-05-21 08:36:32 -0500765 case ByteCodeInstruction::kSwizzle: {
766 Value tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400767 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400768 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400769 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400770 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400771 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400772 }
773 break;
Mike Kleine7007382019-05-21 08:36:32 -0500774 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400775
Mike Klein459aed12019-05-21 15:46:36 -0500776 VECTOR_UNARY_FN(kTan, tanf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400777
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400778 case ByteCodeInstruction::kWriteExternal: // fall through
779 case ByteCodeInstruction::kWriteExternal2: // fall through
780 case ByteCodeInstruction::kWriteExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500781 case ByteCodeInstruction::kWriteExternal4: {
782 int count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
783 int target = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400784 fByteCode->fExternalValues[target]->write(sp - count + 1);
785 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400786 break;
Mike Kleine7007382019-05-21 08:36:32 -0500787 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400788
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400789 default:
Mike Kleine7007382019-05-21 08:36:32 -0500790 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400791 }
792#ifdef TRACE
Mike Kleine7007382019-05-21 08:36:32 -0500793 int stackSize = (int) (sp - stack + 1);
794 printf("STACK(%d):", stackSize);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400795 for (int i = 0; i < stackSize; ++i) {
Brian Osmane85b6a52019-05-22 14:50:59 -0700796 printf(" %d(%g)", stack[i].fSigned, stack[i].fFloat);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400797 }
798 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400799#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400800 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400801}
802
803} // namespace
804
805#endif