blob: 8b9fc3e48b4b7fcbeb7a3cdc917f0d58cb608f13 [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"
Brian Osman569f12f2019-06-13 11:23:57 -040011#include "include/private/SkVx.h"
Mike Klein7a177b42019-06-17 17:17:47 -050012#include "src/core/SkUtils.h" // sk_unaligned_load
Brian Osman80164412019-06-07 13:00:23 -040013#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070014#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040015#include "src/sksl/SkSLExternalValue.h"
Brian Osman80164412019-06-07 13:00:23 -040016
17#include <vector>
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040018
19namespace SkSL {
Brian Osman80164412019-06-07 13:00:23 -040020namespace Interpreter {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040021
Brian Osman569f12f2019-06-13 11:23:57 -040022constexpr int VecWidth = 16;
23
24using F32 = skvx::Vec<VecWidth, float>;
25using I32 = skvx::Vec<VecWidth, int32_t>;
26using U32 = skvx::Vec<VecWidth, uint32_t>;
27
Mike Kleine7007382019-05-21 08:36:32 -050028#define READ8() (*(ip++))
Mike Klein7a177b42019-06-17 17:17:47 -050029#define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
30#define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040031
Brian Osman3e833e12019-05-23 13:23:24 -070032#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040033 case ByteCodeInstruction::op: printf(text); break; \
34 case ByteCodeInstruction::op##2: printf(text "2"); break; \
35 case ByteCodeInstruction::op##3: printf(text "3"); break; \
36 case ByteCodeInstruction::op##4: printf(text "4"); break;
37
Brian Osman1e855b22019-05-29 15:21:52 -040038#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
39 case ByteCodeInstruction::op: printf(text); break; \
40 case ByteCodeInstruction::op##2: printf(text "2"); break; \
41 case ByteCodeInstruction::op##3: printf(text "3"); break; \
42 case ByteCodeInstruction::op##4: printf(text "4"); break; \
43 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
44
Brian Osman3e833e12019-05-23 13:23:24 -070045static const uint8_t* disassemble_instruction(const uint8_t* ip) {
46 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040047 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070048 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040049 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070050 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
51 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
52 case ByteCodeInstruction::kCallExternal: {
53 int argumentCount = READ8();
54 int returnCount = READ8();
55 int externalValue = READ8();
56 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
57 break;
58 }
59 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
60 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040061 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
62 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070063 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
64 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
65 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
66 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
67 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
68 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
69 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
70 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
71 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
72 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
73 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
74 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Brian Osman3e833e12019-05-23 13:23:24 -070075 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
76 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
77 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
78 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040079 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070080 VECTOR_DISASSEMBLE(kDivideS, "divideS")
81 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040082 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -070083 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
84 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
85 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
86 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
87 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
88 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
89 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
90 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
91 case ByteCodeInstruction::kLoadSwizzle: {
92 int target = READ8();
93 int count = READ8();
94 printf("loadswizzle %d %d", target, count);
95 for (int i = 0; i < count; ++i) {
96 printf(", %d", READ8());
97 }
98 break;
99 }
100 case ByteCodeInstruction::kLoadSwizzleGlobal: {
101 int target = READ8();
102 int count = READ8();
103 printf("loadswizzleglobal %d %d", target, count);
104 for (int i = 0; i < count; ++i) {
105 printf(", %d", READ8());
106 }
107 break;
108 }
109 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
110 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
111 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400112 case ByteCodeInstruction::kMatrixToMatrix: {
113 int srcCols = READ8();
114 int srcRows = READ8();
115 int dstCols = READ8();
116 int dstRows = READ8();
117 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
118 break;
119 }
Brian Osman909231c2019-05-29 15:34:36 -0400120 case ByteCodeInstruction::kMatrixMultiply: {
121 int lCols = READ8();
122 int lRows = READ8();
123 int rCols = READ8();
124 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
125 break;
126 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400127 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400128 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700129 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400130 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700131 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400132 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400133 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400134 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700135 case ByteCodeInstruction::kPushImmediate: {
136 uint32_t v = READ32();
137 union { uint32_t u; float f; } pun = { v };
138 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
139 break;
140 }
141 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
142 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
143 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
144 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
145 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
146 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
147 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
148 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400149 case ByteCodeInstruction::kScalarToMatrix: {
150 int cols = READ8();
151 int rows = READ8();
152 printf("scalartomatrix %dx%d", cols, rows);
153 break;
154 }
Brian Osman3e833e12019-05-23 13:23:24 -0700155 VECTOR_DISASSEMBLE(kSin, "sin")
156 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
157 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
158 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
159 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
160 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
161 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
162 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
163 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
164 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
165 case ByteCodeInstruction::kStoreSwizzle: {
166 int target = READ8();
167 int count = READ8();
168 printf("storeswizzle %d %d", target, count);
169 for (int i = 0; i < count; ++i) {
170 printf(", %d", READ8());
171 }
172 break;
173 }
174 case ByteCodeInstruction::kStoreSwizzleGlobal: {
175 int target = READ8();
176 int count = READ8();
177 printf("storeswizzleglobal %d %d", target, count);
178 for (int i = 0; i < count; ++i) {
179 printf(", %d", READ8());
180 }
181 break;
182 }
183 case ByteCodeInstruction::kStoreSwizzleIndirect: {
184 int count = READ8();
185 printf("storeswizzleindirect %d", count);
186 for (int i = 0; i < count; ++i) {
187 printf(", %d", READ8());
188 }
189 break;
190 }
191 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
192 int count = READ8();
193 printf("storeswizzleindirectglobal %d", count);
194 for (int i = 0; i < count; ++i) {
195 printf(", %d", READ8());
196 }
197 break;
198 }
199 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
200 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
201 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400202 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700203 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
204 case ByteCodeInstruction::kSwizzle: {
205 printf("swizzle %d, ", READ8());
206 int count = READ8();
207 printf("%d", count);
208 for (int i = 0; i < count; ++i) {
209 printf(", %d", READ8());
210 }
211 break;
212 }
213 VECTOR_DISASSEMBLE(kTan, "tan")
214 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
215 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
216 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
217 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400218 case ByteCodeInstruction::kXorB: printf("xorb"); break;
219 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
220 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
221 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
222 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
223 case ByteCodeInstruction::kBranchIfAllFalse:
224 printf("branchifallfalse %d", READ16());
225 break;
226 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
227 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
228 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
229 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
230 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
231 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700232 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
233 }
234 return ip;
235}
236
Mike Klein459aed12019-05-21 15:46:36 -0500237#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500238 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500239 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500240 POP(); \
241 /* fall through */ \
242 case ByteCodeInstruction::base ## 3: { \
243 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500244 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500245 POP(); \
246 } /* fall through */ \
247 case ByteCodeInstruction::base ## 2: { \
248 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500249 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500250 POP(); \
251 } /* fall through */ \
252 case ByteCodeInstruction::base: { \
253 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500254 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500255 POP(); \
256 break; \
257 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400258
Brian Osman1e855b22019-05-29 15:21:52 -0400259#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
260 VECTOR_BINARY_OP(base, field, op) \
261 case ByteCodeInstruction::base ## N: { \
262 int count = READ8(); \
263 for (int i = count; i > 0; --i) { \
264 sp[-count] = sp[-count].field op sp[0].field; \
265 POP(); \
266 } \
267 break; \
268 }
269
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400270#define VECTOR_BINARY_FN(base, field, fn) \
271 case ByteCodeInstruction::base ## 4: \
272 sp[-4] = fn(sp[-4].field, sp[0].field); \
273 POP(); \
274 /* fall through */ \
275 case ByteCodeInstruction::base ## 3: { \
276 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
277 sp[target] = fn(sp[target].field, sp[0].field); \
278 POP(); \
279 } /* fall through */ \
280 case ByteCodeInstruction::base ## 2: { \
281 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
282 sp[target] = fn(sp[target].field, sp[0].field); \
283 POP(); \
284 } /* fall through */ \
285 case ByteCodeInstruction::base: { \
286 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
287 sp[target] = fn(sp[target].field, sp[0].field); \
288 POP(); \
289 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500290 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400291
Mike Klein459aed12019-05-21 15:46:36 -0500292#define VECTOR_UNARY_FN(base, fn, field) \
293 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
294 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
295 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
296 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400297 break;
298
Brian Osman569f12f2019-06-13 11:23:57 -0400299#define VECTOR_UNARY_FN_VEC(base, fn) \
300 case ByteCodeInstruction::base ## 4: \
301 case ByteCodeInstruction::base ## 3: \
302 case ByteCodeInstruction::base ## 2: \
303 case ByteCodeInstruction::base : { \
304 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
305 float* v = (float*)sp - count + 1; \
306 for (int i = VecWidth * count; i > 0; --i, ++v) { \
307 *v = fn(*v); \
308 } \
309 break; \
310 }
311
312union VValue {
313 VValue() {}
314
315 VValue(F32 f)
316 : fFloat(f) {
317 }
318
319 VValue(I32 s)
320 : fSigned(s) {
321 }
322
323 VValue(U32 u)
324 : fUnsigned(u) {
325 }
326
327 F32 fFloat;
328 I32 fSigned;
329 U32 fUnsigned;
330};
331
Brian Osman226668a2019-05-14 16:47:30 -0400332struct StackFrame {
333 const uint8_t* fCode;
334 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400335 VValue* fStack;
Brian Osman226668a2019-05-14 16:47:30 -0400336};
337
Brian Osman569f12f2019-06-13 11:23:57 -0400338static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400339 return start * (1 - t) + end * t;
340}
341
Brian Osman569f12f2019-06-13 11:23:57 -0400342// TODO: trunc on integers?
343template <typename T>
344static T vec_mod(T a, T b) {
345 return a - skvx::trunc(a / b) * b;
346}
Mike Kleine7007382019-05-21 08:36:32 -0500347
Brian Osman08a84962019-06-14 10:17:16 -0400348void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
349 float* outReturn, I32 initMask, VValue globals[]) {
Brian Osman569f12f2019-06-13 11:23:57 -0400350 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
351
352 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
353 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500354
Brian Osman80164412019-06-07 13:00:23 -0400355 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400356 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400357 std::vector<StackFrame> frames;
358
Brian Osman569f12f2019-06-13 11:23:57 -0400359 I32 condStack[16]; // Independent condition masks
360 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
361 I32 contStack[16]; // Continue flags for loops
362 I32 loopStack[16]; // Loop execution masks
363 condStack[0] = maskStack[0] = initMask;
364 contStack[0] = I32( 0);
365 loopStack[0] = I32(~0);
366 I32* condPtr = condStack;
367 I32* maskPtr = maskStack;
368 I32* contPtr = contStack;
369 I32* loopPtr = loopStack;
370
371 auto mask = [&]() { return *maskPtr & *loopPtr; };
372
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400373 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400374#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700375 printf("at %3d ", (int) (ip - code));
376 disassemble_instruction(ip);
377 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400378#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700379 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400380 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500381 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400382 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400383
384 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400385 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400386 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
387 POP();
388 break;
389 case ByteCodeInstruction::kNotB:
390 sp[0] = ~sp[0].fSigned;
391 break;
392 case ByteCodeInstruction::kOrB:
393 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
394 POP();
395 break;
396 case ByteCodeInstruction::kXorB:
397 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400398 POP();
399 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400400
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400401 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400402 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400403 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400404
Brian Osman226668a2019-05-14 16:47:30 -0400405 case ByteCodeInstruction::kCall: {
406 // Precursor code has pushed all parameters to the stack. Update our bottom of
407 // stack to point at the first parameter, and our sp to point past those parameters
408 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500409 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400410 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400411 if (skvx::any(mask())) {
412 frames.push_back({ code, ip, stack });
413 ip = code = fun->fCode.data();
414 stack = sp - fun->fParameterCount + 1;
415 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
416 } else {
417 sp -= fun->fParameterCount;
418 sp += fun->fReturnCount;
419 }
Brian Osman226668a2019-05-14 16:47:30 -0400420 break;
421 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400422
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400423 case ByteCodeInstruction::kCallExternal: {
424 int argumentCount = READ8();
425 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500426 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400427 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400428 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500429
Brian Osman08a84962019-06-14 10:17:16 -0400430 int32_t tmpArgs[4];
431 int32_t tmpReturn[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400432 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
433 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
434
435 I32 m = mask();
436 for (int i = 0; i < VecWidth; ++i) {
437 if (m[i]) {
438 for (int j = 0; j < argumentCount; ++j) {
Brian Osman08a84962019-06-14 10:17:16 -0400439 tmpArgs[j] = sp[j].fSigned[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400440 }
441 v->call(tmpArgs, tmpReturn);
442 for (int j = 0; j < returnCount; ++j) {
Brian Osman08a84962019-06-14 10:17:16 -0400443 sp[j].fSigned[i] = tmpReturn[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400444 }
445 }
446 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400447 sp += returnCount - 1;
448 break;
449 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400450
Mike Kleinc1999982019-05-21 13:03:49 -0500451 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400452 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500453 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400454 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500455 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
456 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
457 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
458 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
459 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
460 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
461 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
462 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
463 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
464 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
465 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
466 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400467
Brian Osman569f12f2019-06-13 11:23:57 -0400468 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
469 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
470 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
471 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400472 break;
473
Brian Osman569f12f2019-06-13 11:23:57 -0400474 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
475 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
476 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
477 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400478 break;
479
Brian Osman569f12f2019-06-13 11:23:57 -0400480 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
481 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
482 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
483 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400484 break;
485
Brian Osman569f12f2019-06-13 11:23:57 -0400486 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400487
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400488 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400489 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
490 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
491 F32 cx = ay*bz - az*by,
492 cy = az*bx - ax*bz,
493 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400494 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400495 sp[-2] = cx;
496 sp[-1] = cy;
497 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400498 break;
499 }
500
Mike Kleinc1999982019-05-21 13:03:49 -0500501 VECTOR_BINARY_OP(kDivideS, fSigned, /)
502 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400503 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500504
505 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
506 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
507 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
508 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
509 break;
510
Brian Osman07c117b2019-05-23 12:51:06 -0700511 case ByteCodeInstruction::kDupN: {
512 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400513 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700514 sp += count;
515 break;
516 }
517
Mike Kleine7007382019-05-21 08:36:32 -0500518 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
519 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
520 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
521 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
522 ++ip;
523 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
524 break;
525
Brian Osman80164412019-06-07 13:00:23 -0400526 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
527 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
528 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
529 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500530 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700531 sp += (int)inst -
532 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500533 break;
534
Brian Osman07c117b2019-05-23 12:51:06 -0700535 case ByteCodeInstruction::kLoadExtended: {
536 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400537 I32 src = POP().fSigned;
538 I32 m = mask();
539 for (int i = 0; i < count; ++i) {
540 for (int j = 0; j < VecWidth; ++j) {
541 if (m[j]) {
542 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
543 }
544 }
545 }
Brian Osman07c117b2019-05-23 12:51:06 -0700546 sp += count;
547 break;
548 }
549
550 case ByteCodeInstruction::kLoadExtendedGlobal: {
551 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400552 I32 src = POP().fSigned;
553 I32 m = mask();
554 for (int i = 0; i < count; ++i) {
555 for (int j = 0; j < VecWidth; ++j) {
556 if (m[j]) {
557 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
558 }
559 }
560 }
Brian Osman07c117b2019-05-23 12:51:06 -0700561 sp += count;
562 break;
563 }
564
Mike Kleine7007382019-05-21 08:36:32 -0500565 case ByteCodeInstruction::kLoadSwizzle: {
566 int src = READ8();
567 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400568 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400569 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400570 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400571 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400572 break;
Mike Kleine7007382019-05-21 08:36:32 -0500573 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400574
Mike Kleine7007382019-05-21 08:36:32 -0500575 case ByteCodeInstruction::kLoadSwizzleGlobal: {
576 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500577 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400578 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400579 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400580 }
581 ip += count;
582 break;
Mike Kleine7007382019-05-21 08:36:32 -0500583 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400584
Brian Osman29e013d2019-05-28 17:16:03 -0400585 case ByteCodeInstruction::kMatrixToMatrix: {
586 int srcCols = READ8();
587 int srcRows = READ8();
588 int dstCols = READ8();
589 int dstRows = READ8();
590 SkASSERT(srcCols >= 2 && srcCols <= 4);
591 SkASSERT(srcRows >= 2 && srcRows <= 4);
592 SkASSERT(dstCols >= 2 && dstCols <= 4);
593 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400594 F32 tmp[16];
595 memset(tmp, 0, sizeof(tmp));
596 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400597 for (int c = srcCols - 1; c >= 0; --c) {
598 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400599 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400600 }
601 }
602 for (int c = 0; c < dstCols; ++c) {
603 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400604 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400605 }
606 }
607 break;
608 }
609
Brian Osman909231c2019-05-29 15:34:36 -0400610 case ByteCodeInstruction::kMatrixMultiply: {
611 int lCols = READ8();
612 int lRows = READ8();
613 int rCols = READ8();
614 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400615 F32 tmp[16] = { 0.0f };
616 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
617 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400618 for (int c = 0; c < rCols; ++c) {
619 for (int r = 0; r < lRows; ++r) {
620 for (int j = 0; j < lCols; ++j) {
621 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
622 }
623 }
624 }
625 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400626 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400627 sp += (rCols * lRows);
628 break;
629 }
630
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400631 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
632 case ByteCodeInstruction::kMix4:
633 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
634 // fall through
635 case ByteCodeInstruction::kMix3: {
636 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
637 int target = 2 - count * 2;
638 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
639 // fall through
640 }
641 case ByteCodeInstruction::kMix2: {
642 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
643 int target = 1 - count * 2;
644 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
645 // fall through
646 }
647 case ByteCodeInstruction::kMix: {
648 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
649 int target = -count * 2;
650 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
651 sp -= 1 + count;
652 break;
653 }
654
Mike Kleinc1999982019-05-21 13:03:49 -0500655 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400656 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400657
Mike Kleinc1999982019-05-21 13:03:49 -0500658 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
659 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
660 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
661 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500662 break;
663
Brian Osman1e855b22019-05-29 15:21:52 -0400664 case ByteCodeInstruction::kNegateFN: {
665 int count = READ8();
666 for (int i = count - 1; i >= 0; --i) {
667 sp[-i] = -sp[-i].fFloat;
668 }
669 break;
670 }
671
Mike Kleinc1999982019-05-21 13:03:49 -0500672 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
673 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
674 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400675 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500676 break;
677
678 case ByteCodeInstruction::kPop4: POP();
679 case ByteCodeInstruction::kPop3: POP();
680 case ByteCodeInstruction::kPop2: POP();
681 case ByteCodeInstruction::kPop : POP();
682 break;
683
Brian Osman07c117b2019-05-23 12:51:06 -0700684 case ByteCodeInstruction::kPopN:
685 sp -= READ8();
686 break;
687
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400688 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400689 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400690 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400691
Brian Osman569f12f2019-06-13 11:23:57 -0400692 case ByteCodeInstruction::kReadExternal:
693 case ByteCodeInstruction::kReadExternal2:
694 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500695 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400696 // TODO: Support striped external values, or passing lane index? This model is odd.
697 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500698 int src = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400699 int32_t tmp[4];
700 I32 m = mask();
701 for (int i = 0; i < VecWidth; ++i) {
702 if (m[i]) {
703 byteCode->fExternalValues[src]->read(tmp);
704 for (int j = 0; j < count; ++j) {
705 sp[j + 1].fSigned[i] = tmp[j];
706 }
707 }
708 }
709 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400710 break;
Mike Kleine7007382019-05-21 08:36:32 -0500711 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400712
Brian Osman569f12f2019-06-13 11:23:57 -0400713 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
714 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
715 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400716
Mike Kleine7007382019-05-21 08:36:32 -0500717 case ByteCodeInstruction::kReturn: {
718 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400719 if (frames.empty()) {
720 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400721 // TODO: This can be smarter, knowing that mask is left-justified
722 I32 m = mask();
723 VValue* src = sp - count + 1;
724 for (int i = 0; i < count; ++i) {
725 for (int j = 0; j < VecWidth; ++j) {
726 if (m[j]) {
Brian Osman08a84962019-06-14 10:17:16 -0400727 outReturn[count * j] = src->fFloat[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400728 }
729 }
730 ++outReturn;
731 ++src;
732 }
Brian Osman226668a2019-05-14 16:47:30 -0400733 }
734 return;
735 } else {
736 // When we were called, 'stack' was positioned at the old top-of-stack (where
737 // our parameters were placed). So copy our return values to that same spot.
Brian Osman569f12f2019-06-13 11:23:57 -0400738 memmove(stack, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400739
740 // Now move the stack pointer to the end of the just-pushed return values,
741 // and restore everything else.
742 const StackFrame& frame(frames.back());
743 sp = stack + count - 1;
744 stack = frame.fStack;
745 code = frame.fCode;
746 ip = frame.fIP;
747 frames.pop_back();
748 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400749 }
Mike Kleine7007382019-05-21 08:36:32 -0500750 }
751
Brian Osman29e013d2019-05-28 17:16:03 -0400752 case ByteCodeInstruction::kScalarToMatrix: {
753 int cols = READ8();
754 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400755 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400756 for (int c = 0; c < cols; ++c) {
757 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400758 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400759 }
760 }
761 break;
762 }
763
Brian Osman569f12f2019-06-13 11:23:57 -0400764 VECTOR_UNARY_FN_VEC(kSin, sinf)
765 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400766
Brian Osman569f12f2019-06-13 11:23:57 -0400767 case ByteCodeInstruction::kStore4:
768 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
769 case ByteCodeInstruction::kStore3:
770 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
771 case ByteCodeInstruction::kStore2:
772 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
773 case ByteCodeInstruction::kStore :
774 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
775 ++ip;
776 break;
Mike Kleine7007382019-05-21 08:36:32 -0500777
Brian Osman569f12f2019-06-13 11:23:57 -0400778 case ByteCodeInstruction::kStoreGlobal4:
779 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
780 case ByteCodeInstruction::kStoreGlobal3:
781 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
782 case ByteCodeInstruction::kStoreGlobal2:
783 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
784 case ByteCodeInstruction::kStoreGlobal :
785 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
786 ++ip;
787 break;
Mike Kleine7007382019-05-21 08:36:32 -0500788
Brian Osman07c117b2019-05-23 12:51:06 -0700789 case ByteCodeInstruction::kStoreExtended: {
790 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400791 I32 target = POP().fSigned;
792 VValue* src = sp - count + 1;
793 I32 m = mask();
794 for (int i = 0; i < count; ++i) {
795 for (int j = 0; j < VecWidth; ++j) {
796 if (m[j]) {
797 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
798 }
799 }
800 }
Brian Osman07c117b2019-05-23 12:51:06 -0700801 sp -= count;
802 break;
803 }
804 case ByteCodeInstruction::kStoreExtendedGlobal: {
805 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400806 I32 target = POP().fSigned;
807 VValue* src = sp - count + 1;
808 I32 m = mask();
809 for (int i = 0; i < count; ++i) {
810 for (int j = 0; j < VecWidth; ++j) {
811 if (m[j]) {
812 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
813 }
814 }
815 }
Brian Osman07c117b2019-05-23 12:51:06 -0700816 sp -= count;
817 break;
818 }
819
Mike Kleine7007382019-05-21 08:36:32 -0500820 case ByteCodeInstruction::kStoreSwizzle: {
821 int target = READ8();
822 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400823 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400824 stack[target + *(ip + i)] = skvx::if_then_else(
825 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400826 }
Brian Osman1091f022019-05-16 09:42:16 -0400827 ip += count;
828 break;
Mike Kleine7007382019-05-21 08:36:32 -0500829 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400830
Mike Kleine7007382019-05-21 08:36:32 -0500831 case ByteCodeInstruction::kStoreSwizzleGlobal: {
832 int target = READ8();
833 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400834 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400835 globals[target + *(ip + i)] = skvx::if_then_else(
836 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400837 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400838 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400839 break;
Mike Kleine7007382019-05-21 08:36:32 -0500840 }
Brian Osman569f12f2019-06-13 11:23:57 -0400841
Brian Osman07c117b2019-05-23 12:51:06 -0700842 case ByteCodeInstruction::kStoreSwizzleIndirect: {
Brian Osman07c117b2019-05-23 12:51:06 -0700843 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400844 I32 target = POP().fSigned;
845 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700846 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400847 I32 v = POP().fSigned;
848 for (int j = 0; j < VecWidth; ++j) {
849 if (m[j]) {
850 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
851 }
852 }
Brian Osman07c117b2019-05-23 12:51:06 -0700853 }
854 ip += count;
855 break;
856 }
Brian Osman569f12f2019-06-13 11:23:57 -0400857
Brian Osman07c117b2019-05-23 12:51:06 -0700858 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700859 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400860 I32 target = POP().fSigned;
861 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700862 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400863 I32 v = POP().fSigned;
864 for (int j = 0; j < VecWidth; ++j) {
865 if (m[j]) {
866 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
867 }
868 }
Brian Osman07c117b2019-05-23 12:51:06 -0700869 }
870 ip += count;
871 break;
872 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400873
Mike Kleinc1999982019-05-21 13:03:49 -0500874 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400875 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400876
Mike Kleine7007382019-05-21 08:36:32 -0500877 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400878 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400879 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400880 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400881 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400882 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400883 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400884 }
885 break;
Mike Kleine7007382019-05-21 08:36:32 -0500886 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400887
Brian Osman569f12f2019-06-13 11:23:57 -0400888 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400889
Brian Osman569f12f2019-06-13 11:23:57 -0400890 case ByteCodeInstruction::kWriteExternal:
891 case ByteCodeInstruction::kWriteExternal2:
892 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500893 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400894 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500895 int target = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400896 int32_t tmp[4];
897 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400898 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -0400899 for (int i = 0; i < VecWidth; ++i) {
900 if (m[i]) {
901 for (int j = 0; j < count; ++j) {
902 tmp[j] = sp[j + 1].fSigned[i];
903 }
904 byteCode->fExternalValues[target]->write(tmp);
905 }
906 }
907 break;
908 }
909
910 case ByteCodeInstruction::kMaskPush:
911 condPtr[1] = POP().fSigned;
912 maskPtr[1] = maskPtr[0] & condPtr[1];
913 ++condPtr; ++maskPtr;
914 break;
915 case ByteCodeInstruction::kMaskPop:
916 --condPtr; --maskPtr;
917 break;
918 case ByteCodeInstruction::kMaskNegate:
919 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
920 break;
921 case ByteCodeInstruction::kMaskBlend: {
922 int count = READ8();
923 I32 m = condPtr[0];
924 --condPtr; --maskPtr;
925 for (int i = 0; i < count; ++i) {
926 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
927 --sp;
928 }
929 break;
930 }
931 case ByteCodeInstruction::kBranchIfAllFalse: {
932 int target = READ16();
933 if (!skvx::any(mask())) {
934 ip = code + target;
935 }
936 break;
937 }
938
939 case ByteCodeInstruction::kLoopBegin:
940 *(++contPtr) = 0;
941 *(++loopPtr) = ~0;
942 break;
943 case ByteCodeInstruction::kLoopNext:
944 *loopPtr |= *contPtr;
945 *contPtr = 0;
946 break;
947 case ByteCodeInstruction::kLoopMask:
948 *loopPtr &= POP().fSigned;
949 break;
950 case ByteCodeInstruction::kLoopEnd:
951 --contPtr; --loopPtr;
952 break;
953 case ByteCodeInstruction::kLoopBreak:
954 *loopPtr &= ~mask();
955 break;
956 case ByteCodeInstruction::kLoopContinue: {
957 I32 m = mask();
958 *contPtr |= m;
959 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400960 break;
Mike Kleine7007382019-05-21 08:36:32 -0500961 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400962
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400963 default:
Mike Kleine7007382019-05-21 08:36:32 -0500964 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400965 }
Brian Osman569f12f2019-06-13 11:23:57 -0400966 }
967}
968
Brian Osman08a84962019-06-14 10:17:16 -0400969} // namespace Interpreter
970
971void ByteCodeFunction::disassemble() const {
972 const uint8_t* ip = fCode.data();
973 while (ip < fCode.data() + fCode.size()) {
974 printf("%d: ", (int)(ip - fCode.data()));
975 ip = Interpreter::disassemble_instruction(ip);
976 printf("\n");
977 }
978}
979
980void ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
981 const float* uniforms, int uniformCount) const {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400982#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -0400983 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400984#endif
Brian Osman08a84962019-06-14 10:17:16 -0400985 Interpreter::VValue smallStack[128];
Brian Osman569f12f2019-06-13 11:23:57 -0400986
Brian Osmanef787f72019-06-13 13:07:12 -0400987 // Needs to be the first N non-negative integers, at least as large as VecWidth
Brian Osman08a84962019-06-14 10:17:16 -0400988 static const Interpreter::I32 gLanes = {
989 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
990 };
Brian Osmanef787f72019-06-13 13:07:12 -0400991
Brian Osman08a84962019-06-14 10:17:16 -0400992 SkASSERT(uniformCount == (int)fInputSlots.size());
993 Interpreter::VValue globals[32];
994 SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
995 for (uint8_t slot : fInputSlots) {
996 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -0400997 }
998
999 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001000 Interpreter::VValue* stack = smallStack;
Brian Osman569f12f2019-06-13 11:23:57 -04001001
Brian Osman08a84962019-06-14 10:17:16 -04001002 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001003 N -= w;
1004
1005 // Transpose args into stack
1006 {
Brian Osman08a84962019-06-14 10:17:16 -04001007 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001008 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001009 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001010 for (int j = f->fParameterCount; j > 0; --j) {
1011 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001012 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001013 }
1014 }
1015 }
1016
1017 auto mask = w > gLanes;
Brian Osman08a84962019-06-14 10:17:16 -04001018 innerRun(this, f, stack, outReturn, mask, globals);
Brian Osman569f12f2019-06-13 11:23:57 -04001019
1020 // Transpose out parameters back
1021 {
Brian Osman08a84962019-06-14 10:17:16 -04001022 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001023 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001024 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001025 for (const auto& p : f->fParameters) {
1026 if (p.fIsOutParameter) {
1027 for (int j = p.fSlotCount; j > 0; --j) {
1028 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001029 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001030 }
1031 } else {
1032 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001033 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001034 }
1035 }
1036 }
1037 }
1038
1039 args += f->fParameterCount * w;
1040 outReturn += f->fReturnCount * w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001041 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001042}
1043
Brian Osman80164412019-06-07 13:00:23 -04001044} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001045
1046#endif