blob: 4e81a338249cd470ff5a1143d21c922d3aec5f3a [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 }
Brian Osman909231c2019-05-29 15:34:36 -0400182 case ByteCodeInstruction::kMatrixMultiply: {
183 int lCols = READ8();
184 int lRows = READ8();
185 int rCols = READ8();
186 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
187 break;
188 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400189 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400190 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700191 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400192 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700193 VECTOR_DISASSEMBLE(kNegateI, "negatei")
194 VECTOR_DISASSEMBLE(kNot, "not")
195 VECTOR_DISASSEMBLE(kOrB, "orb")
196 VECTOR_DISASSEMBLE(kOrI, "ori")
Brian Osman1e855b22019-05-29 15:21:52 -0400197 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700198 case ByteCodeInstruction::kPushImmediate: {
199 uint32_t v = READ32();
200 union { uint32_t u; float f; } pun = { v };
201 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
202 break;
203 }
204 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
205 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
206 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
207 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
208 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
209 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
210 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
211 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400212 case ByteCodeInstruction::kScalarToMatrix: {
213 int cols = READ8();
214 int rows = READ8();
215 printf("scalartomatrix %dx%d", cols, rows);
216 break;
217 }
Brian Osman3e833e12019-05-23 13:23:24 -0700218 VECTOR_DISASSEMBLE(kSin, "sin")
219 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
220 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
221 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
222 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
223 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
224 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
225 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
226 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
227 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
228 case ByteCodeInstruction::kStoreSwizzle: {
229 int target = READ8();
230 int count = READ8();
231 printf("storeswizzle %d %d", target, count);
232 for (int i = 0; i < count; ++i) {
233 printf(", %d", READ8());
234 }
235 break;
236 }
237 case ByteCodeInstruction::kStoreSwizzleGlobal: {
238 int target = READ8();
239 int count = READ8();
240 printf("storeswizzleglobal %d %d", target, count);
241 for (int i = 0; i < count; ++i) {
242 printf(", %d", READ8());
243 }
244 break;
245 }
246 case ByteCodeInstruction::kStoreSwizzleIndirect: {
247 int count = READ8();
248 printf("storeswizzleindirect %d", count);
249 for (int i = 0; i < count; ++i) {
250 printf(", %d", READ8());
251 }
252 break;
253 }
254 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
255 int count = READ8();
256 printf("storeswizzleindirectglobal %d", count);
257 for (int i = 0; i < count; ++i) {
258 printf(", %d", READ8());
259 }
260 break;
261 }
262 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
263 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
264 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400265 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700266 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
267 case ByteCodeInstruction::kSwizzle: {
268 printf("swizzle %d, ", READ8());
269 int count = READ8();
270 printf("%d", count);
271 for (int i = 0; i < count; ++i) {
272 printf(", %d", READ8());
273 }
274 break;
275 }
276 VECTOR_DISASSEMBLE(kTan, "tan")
277 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
278 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
279 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
280 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
281 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
282 }
283 return ip;
284}
285
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400286void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400287 const uint8_t* ip = f.fCode.data();
288 while (ip < f.fCode.data() + f.fCode.size()) {
289 printf("%d: ", (int) (ip - f.fCode.data()));
Brian Osman3e833e12019-05-23 13:23:24 -0700290 ip = disassemble_instruction(ip);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400291 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400292 }
293}
294
Mike Klein459aed12019-05-21 15:46:36 -0500295#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500296 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500297 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500298 POP(); \
299 /* fall through */ \
300 case ByteCodeInstruction::base ## 3: { \
301 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500302 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500303 POP(); \
304 } /* fall through */ \
305 case ByteCodeInstruction::base ## 2: { \
306 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500307 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500308 POP(); \
309 } /* fall through */ \
310 case ByteCodeInstruction::base: { \
311 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500312 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500313 POP(); \
314 break; \
315 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400316
Brian Osman1e855b22019-05-29 15:21:52 -0400317#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
318 VECTOR_BINARY_OP(base, field, op) \
319 case ByteCodeInstruction::base ## N: { \
320 int count = READ8(); \
321 for (int i = count; i > 0; --i) { \
322 sp[-count] = sp[-count].field op sp[0].field; \
323 POP(); \
324 } \
325 break; \
326 }
327
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400328#define VECTOR_BINARY_FN(base, field, fn) \
329 case ByteCodeInstruction::base ## 4: \
330 sp[-4] = fn(sp[-4].field, sp[0].field); \
331 POP(); \
332 /* fall through */ \
333 case ByteCodeInstruction::base ## 3: { \
334 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
335 sp[target] = fn(sp[target].field, sp[0].field); \
336 POP(); \
337 } /* fall through */ \
338 case ByteCodeInstruction::base ## 2: { \
339 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
340 sp[target] = fn(sp[target].field, sp[0].field); \
341 POP(); \
342 } /* fall through */ \
343 case ByteCodeInstruction::base: { \
344 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
345 sp[target] = fn(sp[target].field, sp[0].field); \
346 POP(); \
347 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500348 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400349
Mike Klein459aed12019-05-21 15:46:36 -0500350#define VECTOR_UNARY_FN(base, fn, field) \
351 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
352 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
353 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
354 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400355 break;
356
Brian Osman226668a2019-05-14 16:47:30 -0400357struct StackFrame {
358 const uint8_t* fCode;
359 const uint8_t* fIP;
360 Interpreter::Value* fStack;
361};
362
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400363static float mix(float start, float end, float t) {
364 return start * (1 - t) + end * t;
365}
366
Mike Kleine7007382019-05-21 08:36:32 -0500367void Interpreter::innerRun(const ByteCodeFunction& f, Value* stack, Value* outReturn) {
368 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
369
370 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
371 auto PUSH = [&](Value v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
372
Brian Osman226668a2019-05-14 16:47:30 -0400373 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400374 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400375 std::vector<StackFrame> frames;
376
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400377 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400378#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700379 printf("at %3d ", (int) (ip - code));
380 disassemble_instruction(ip);
381 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400382#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700383 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400384 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500385 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400386 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman16e6fd52019-05-29 11:19:00 -0400387 VECTOR_BINARY_OP(kAndB, fBool, &&)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400388
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400389 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400390 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400391 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400392
Brian Osman226668a2019-05-14 16:47:30 -0400393 case ByteCodeInstruction::kCall: {
394 // Precursor code has pushed all parameters to the stack. Update our bottom of
395 // stack to point at the first parameter, and our sp to point past those parameters
396 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500397 int target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400398 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
399 frames.push_back({ code, ip, stack });
400 ip = code = fun->fCode.data();
401 stack = sp - fun->fParameterCount + 1;
402 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
403 break;
404 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400405
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400406 case ByteCodeInstruction::kCallExternal: {
407 int argumentCount = READ8();
408 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500409 int target = READ8();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400410 ExternalValue* v = fByteCode->fExternalValues[target];
411 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500412
413 Value tmp[4];
414 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmp));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400415 v->call(sp, tmp);
416 memcpy(sp, tmp, returnCount * sizeof(Value));
417 sp += returnCount - 1;
418 break;
419 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400420
Mike Kleinc1999982019-05-21 13:03:49 -0500421 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400422 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500423 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400424 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500425 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
426 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
427 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
428 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
429 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
430 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
431 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
432 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
433 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
434 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
435 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
436 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400437
Mike Kleine7007382019-05-21 08:36:32 -0500438 case ByteCodeInstruction::kConditionalBranch: {
439 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400440 if (POP().fBool) {
Mike Kleine7007382019-05-21 08:36:32 -0500441 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400442 }
443 break;
Mike Kleine7007382019-05-21 08:36:32 -0500444 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400445
446 case ByteCodeInstruction::kConvertFtoI4: sp[-3].fSigned = (int)sp[-3].fFloat;
447 case ByteCodeInstruction::kConvertFtoI3: sp[-2].fSigned = (int)sp[-2].fFloat;
448 case ByteCodeInstruction::kConvertFtoI2: sp[-1].fSigned = (int)sp[-1].fFloat;
449 case ByteCodeInstruction::kConvertFtoI: sp[ 0].fSigned = (int)sp[ 0].fFloat;
450 break;
451
452 case ByteCodeInstruction::kConvertStoF4: sp[-3].fFloat = sp[-3].fSigned;
453 case ByteCodeInstruction::kConvertStoF3: sp[-2].fFloat = sp[-2].fSigned;
454 case ByteCodeInstruction::kConvertStoF2: sp[-1].fFloat = sp[-1].fSigned;
455 case ByteCodeInstruction::kConvertStoF : sp[ 0].fFloat = sp[ 0].fSigned;
456 break;
457
458 case ByteCodeInstruction::kConvertUtoF4: sp[-3].fFloat = sp[-3].fUnsigned;
459 case ByteCodeInstruction::kConvertUtoF3: sp[-2].fFloat = sp[-2].fUnsigned;
460 case ByteCodeInstruction::kConvertUtoF2: sp[-1].fFloat = sp[-1].fUnsigned;
461 case ByteCodeInstruction::kConvertUtoF : sp[ 0].fFloat = sp[ 0].fUnsigned;
462 break;
463
Mike Klein459aed12019-05-21 15:46:36 -0500464 VECTOR_UNARY_FN(kCos, cosf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400465
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400466 case ByteCodeInstruction::kCross: {
467 SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(sp[-5].fFloat,
468 sp[-4].fFloat,
469 sp[-3].fFloat),
470 SkPoint3::Make(sp[-2].fFloat,
471 sp[-1].fFloat,
472 sp[ 0].fFloat));
473 sp -= 3;
474 sp[-2] = cross.fX;
475 sp[-1] = cross.fY;
476 sp[ 0] = cross.fZ;
477 break;
478 }
479
Mike Kleine7007382019-05-21 08:36:32 -0500480 case ByteCodeInstruction::kDebugPrint: {
481 Value v = POP();
482 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400483 break;
Mike Kleine7007382019-05-21 08:36:32 -0500484 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400485
Mike Kleinc1999982019-05-21 13:03:49 -0500486 VECTOR_BINARY_OP(kDivideS, fSigned, /)
487 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400488 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500489
490 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
491 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
492 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
493 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
494 break;
495
Brian Osman07c117b2019-05-23 12:51:06 -0700496 case ByteCodeInstruction::kDupN: {
497 int count = READ8();
498 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
499 sp += count;
500 break;
501 }
502
Mike Kleine7007382019-05-21 08:36:32 -0500503 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
504 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
505 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
506 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
507 ++ip;
508 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
509 break;
510
511 case ByteCodeInstruction::kLoadGlobal4: sp[4] = fGlobals[*ip + 3];
512 case ByteCodeInstruction::kLoadGlobal3: sp[3] = fGlobals[*ip + 2];
513 case ByteCodeInstruction::kLoadGlobal2: sp[2] = fGlobals[*ip + 1];
514 case ByteCodeInstruction::kLoadGlobal : sp[1] = fGlobals[*ip + 0];
515 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700516 sp += (int)inst -
517 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500518 break;
519
Brian Osman07c117b2019-05-23 12:51:06 -0700520 case ByteCodeInstruction::kLoadExtended: {
521 int count = READ8();
522 int src = POP().fSigned;
523 memcpy(sp + 1, &stack[src], count * sizeof(Value));
524 sp += count;
525 break;
526 }
527
528 case ByteCodeInstruction::kLoadExtendedGlobal: {
529 int count = READ8();
530 int src = POP().fSigned;
531 SkASSERT(src + count <= (int) fGlobals.size());
532 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
533 sp += count;
534 break;
535 }
536
Mike Kleine7007382019-05-21 08:36:32 -0500537 case ByteCodeInstruction::kLoadSwizzle: {
538 int src = READ8();
539 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400540 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400541 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400542 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400543 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400544 break;
Mike Kleine7007382019-05-21 08:36:32 -0500545 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400546
Mike Kleine7007382019-05-21 08:36:32 -0500547 case ByteCodeInstruction::kLoadSwizzleGlobal: {
548 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400549 SkASSERT(src < (int) fGlobals.size());
Mike Kleine7007382019-05-21 08:36:32 -0500550 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400551 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400552 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400553 }
554 ip += count;
555 break;
Mike Kleine7007382019-05-21 08:36:32 -0500556 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400557
Brian Osman29e013d2019-05-28 17:16:03 -0400558 case ByteCodeInstruction::kMatrixToMatrix: {
559 int srcCols = READ8();
560 int srcRows = READ8();
561 int dstCols = READ8();
562 int dstRows = READ8();
563 SkASSERT(srcCols >= 2 && srcCols <= 4);
564 SkASSERT(srcRows >= 2 && srcRows <= 4);
565 SkASSERT(dstCols >= 2 && dstCols <= 4);
566 SkASSERT(dstRows >= 2 && dstRows <= 4);
567 SkMatrix44 m;
568 for (int c = srcCols - 1; c >= 0; --c) {
569 for (int r = srcRows - 1; r >= 0; --r) {
570 m.set(r, c, POP().fFloat);
571 }
572 }
573 for (int c = 0; c < dstCols; ++c) {
574 for (int r = 0; r < dstRows; ++r) {
575 PUSH(m.get(r, c));
576 }
577 }
578 break;
579 }
580
Brian Osman909231c2019-05-29 15:34:36 -0400581 case ByteCodeInstruction::kMatrixMultiply: {
582 int lCols = READ8();
583 int lRows = READ8();
584 int rCols = READ8();
585 int rRows = lCols;
586 float tmp[16] = { 0.0f };
587 float* B = &(sp - (rCols * rRows) + 1)->fFloat;
588 float* A = B - (lCols * lRows);
589 for (int c = 0; c < rCols; ++c) {
590 for (int r = 0; r < lRows; ++r) {
591 for (int j = 0; j < lCols; ++j) {
592 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
593 }
594 }
595 }
596 sp -= (lCols * lRows) + (rCols * rRows);
597 memcpy(sp + 1, tmp, rCols * lRows * sizeof(Value));
598 sp += (rCols * lRows);
599 break;
600 }
601
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400602 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
603 case ByteCodeInstruction::kMix4:
604 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
605 // fall through
606 case ByteCodeInstruction::kMix3: {
607 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
608 int target = 2 - count * 2;
609 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
610 // fall through
611 }
612 case ByteCodeInstruction::kMix2: {
613 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
614 int target = 1 - count * 2;
615 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
616 // fall through
617 }
618 case ByteCodeInstruction::kMix: {
619 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
620 int target = -count * 2;
621 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
622 sp -= 1 + count;
623 break;
624 }
625
Mike Kleinc1999982019-05-21 13:03:49 -0500626 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400627 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400628
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400629 case ByteCodeInstruction::kNot:
Mike Kleine7007382019-05-21 08:36:32 -0500630 sp[0].fBool = !sp[0].fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400631 break;
Mike Kleine7007382019-05-21 08:36:32 -0500632
Mike Kleinc1999982019-05-21 13:03:49 -0500633 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
634 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
635 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
636 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500637 break;
638
Brian Osman1e855b22019-05-29 15:21:52 -0400639 case ByteCodeInstruction::kNegateFN: {
640 int count = READ8();
641 for (int i = count - 1; i >= 0; --i) {
642 sp[-i] = -sp[-i].fFloat;
643 }
644 break;
645 }
646
Mike Kleinc1999982019-05-21 13:03:49 -0500647 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
648 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
649 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
650 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp [0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500651 break;
652
Brian Osman16e6fd52019-05-29 11:19:00 -0400653 VECTOR_BINARY_OP(kOrB, fBool, ||)
654
Mike Kleine7007382019-05-21 08:36:32 -0500655 case ByteCodeInstruction::kPop4: POP();
656 case ByteCodeInstruction::kPop3: POP();
657 case ByteCodeInstruction::kPop2: POP();
658 case ByteCodeInstruction::kPop : POP();
659 break;
660
Brian Osman07c117b2019-05-23 12:51:06 -0700661 case ByteCodeInstruction::kPopN:
662 sp -= READ8();
663 break;
664
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400665 case ByteCodeInstruction::kPushImmediate:
Mike Kleine7007382019-05-21 08:36:32 -0500666 PUSH(READ32());
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400667 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400668
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400669 case ByteCodeInstruction::kReadExternal: // fall through
670 case ByteCodeInstruction::kReadExternal2: // fall through
671 case ByteCodeInstruction::kReadExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500672 case ByteCodeInstruction::kReadExternal4: {
673 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400674 fByteCode->fExternalValues[src]->read(sp + 1);
Mike Kleine7007382019-05-21 08:36:32 -0500675 sp += (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400676 break;
Mike Kleine7007382019-05-21 08:36:32 -0500677 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400678
Mike Kleinc1999982019-05-21 13:03:49 -0500679 VECTOR_BINARY_FN(kRemainderF, fFloat, fmodf)
680 VECTOR_BINARY_OP(kRemainderS, fSigned, %)
681 VECTOR_BINARY_OP(kRemainderU, fUnsigned, %)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400682
Mike Kleine7007382019-05-21 08:36:32 -0500683 case ByteCodeInstruction::kReturn: {
684 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400685 if (frames.empty()) {
686 if (outReturn) {
687 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
688 }
689 return;
690 } else {
691 // When we were called, 'stack' was positioned at the old top-of-stack (where
692 // our parameters were placed). So copy our return values to that same spot.
693 memmove(stack, sp - count + 1, count * sizeof(Value));
694
695 // Now move the stack pointer to the end of the just-pushed return values,
696 // and restore everything else.
697 const StackFrame& frame(frames.back());
698 sp = stack + count - 1;
699 stack = frame.fStack;
700 code = frame.fCode;
701 ip = frame.fIP;
702 frames.pop_back();
703 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400704 }
Mike Kleine7007382019-05-21 08:36:32 -0500705 }
706
Brian Osman29e013d2019-05-28 17:16:03 -0400707 case ByteCodeInstruction::kScalarToMatrix: {
708 int cols = READ8();
709 int rows = READ8();
710 Value v = POP();
711 for (int c = 0; c < cols; ++c) {
712 for (int r = 0; r < rows; ++r) {
713 PUSH(c == r ? v : 0.0f);
714 }
715 }
716 break;
717 }
718
Mike Klein459aed12019-05-21 15:46:36 -0500719 VECTOR_UNARY_FN(kSin, sinf, fFloat)
720 VECTOR_UNARY_FN(kSqrt, sqrtf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400721
Mike Kleine7007382019-05-21 08:36:32 -0500722 case ByteCodeInstruction::kStore4: stack[*ip + 3] = POP();
723 case ByteCodeInstruction::kStore3: stack[*ip + 2] = POP();
724 case ByteCodeInstruction::kStore2: stack[*ip + 1] = POP();
725 case ByteCodeInstruction::kStore : stack[*ip + 0] = POP();
726 ++ip;
727 break;
728
729 case ByteCodeInstruction::kStoreGlobal4: fGlobals[*ip + 3] = POP();
730 case ByteCodeInstruction::kStoreGlobal3: fGlobals[*ip + 2] = POP();
731 case ByteCodeInstruction::kStoreGlobal2: fGlobals[*ip + 1] = POP();
732 case ByteCodeInstruction::kStoreGlobal : fGlobals[*ip + 0] = POP();
733 ++ip;
734 break;
735
Brian Osman07c117b2019-05-23 12:51:06 -0700736 case ByteCodeInstruction::kStoreExtended: {
737 int count = READ8();
738 int target = POP().fSigned;
739 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
740 sp -= count;
741 break;
742 }
743 case ByteCodeInstruction::kStoreExtendedGlobal: {
744 int count = READ8();
745 int target = POP().fSigned;
746 SkASSERT(target + count <= (int) fGlobals.size());
747 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
748 sp -= count;
749 break;
750 }
751
Mike Kleine7007382019-05-21 08:36:32 -0500752 case ByteCodeInstruction::kStoreSwizzle: {
753 int target = READ8();
754 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400755 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400756 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400757 }
Brian Osman1091f022019-05-16 09:42:16 -0400758 ip += count;
759 break;
Mike Kleine7007382019-05-21 08:36:32 -0500760 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400761
Mike Kleine7007382019-05-21 08:36:32 -0500762 case ByteCodeInstruction::kStoreSwizzleGlobal: {
763 int target = READ8();
764 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400765 for (int i = count - 1; i >= 0; --i) {
766 fGlobals[target + *(ip + i)] = POP();
767 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400768 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400769 break;
Mike Kleine7007382019-05-21 08:36:32 -0500770 }
Brian Osman07c117b2019-05-23 12:51:06 -0700771 case ByteCodeInstruction::kStoreSwizzleIndirect: {
772 int target = POP().fSigned;
773 int count = READ8();
774 for (int i = count - 1; i >= 0; --i) {
775 stack[target + *(ip + i)] = POP();
776 }
777 ip += count;
778 break;
779 }
780 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
781 int target = POP().fSigned;
782 int count = READ8();
783 for (int i = count - 1; i >= 0; --i) {
784 fGlobals[target + *(ip + i)] = POP();
785 }
786 ip += count;
787 break;
788 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400789
Mike Kleinc1999982019-05-21 13:03:49 -0500790 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400791 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400792
Mike Kleine7007382019-05-21 08:36:32 -0500793 case ByteCodeInstruction::kSwizzle: {
794 Value tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400795 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400796 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400797 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400798 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400799 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400800 }
801 break;
Mike Kleine7007382019-05-21 08:36:32 -0500802 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400803
Mike Klein459aed12019-05-21 15:46:36 -0500804 VECTOR_UNARY_FN(kTan, tanf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400805
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400806 case ByteCodeInstruction::kWriteExternal: // fall through
807 case ByteCodeInstruction::kWriteExternal2: // fall through
808 case ByteCodeInstruction::kWriteExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500809 case ByteCodeInstruction::kWriteExternal4: {
810 int count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
811 int target = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400812 fByteCode->fExternalValues[target]->write(sp - count + 1);
813 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400814 break;
Mike Kleine7007382019-05-21 08:36:32 -0500815 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400816
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400817 default:
Mike Kleine7007382019-05-21 08:36:32 -0500818 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400819 }
820#ifdef TRACE
Mike Kleine7007382019-05-21 08:36:32 -0500821 int stackSize = (int) (sp - stack + 1);
822 printf("STACK(%d):", stackSize);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400823 for (int i = 0; i < stackSize; ++i) {
Brian Osmane85b6a52019-05-22 14:50:59 -0700824 printf(" %d(%g)", stack[i].fSigned, stack[i].fFloat);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400825 }
826 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400827#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400828 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400829}
830
831} // namespace
832
833#endif