blob: 22fec065cf3b5cec31f93c1678601fee48d72f0b [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"
Brian Osman80164412019-06-07 13:00:23 -040012#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070013#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040014#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/SkSLInterpreter.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
28// Needs to be the first N non-negative integers, at least as large as VecWidth
29static const I32 gLanes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
30 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
31
Mike Klein76346ac2019-05-17 11:57:10 -050032template <typename T>
33static T unaligned_load(const void* ptr) {
34 T val;
35 memcpy(&val, ptr, sizeof(val));
36 return val;
37}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040038
Mike Kleine7007382019-05-21 08:36:32 -050039#define READ8() (*(ip++))
Mike Klein76346ac2019-05-17 11:57:10 -050040#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
41#define READ32() (ip += 4, unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040042
Brian Osman3e833e12019-05-23 13:23:24 -070043#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040044 case ByteCodeInstruction::op: printf(text); break; \
45 case ByteCodeInstruction::op##2: printf(text "2"); break; \
46 case ByteCodeInstruction::op##3: printf(text "3"); break; \
47 case ByteCodeInstruction::op##4: printf(text "4"); break;
48
Brian Osman1e855b22019-05-29 15:21:52 -040049#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
50 case ByteCodeInstruction::op: printf(text); break; \
51 case ByteCodeInstruction::op##2: printf(text "2"); break; \
52 case ByteCodeInstruction::op##3: printf(text "3"); break; \
53 case ByteCodeInstruction::op##4: printf(text "4"); break; \
54 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
55
Brian Osman3e833e12019-05-23 13:23:24 -070056static const uint8_t* disassemble_instruction(const uint8_t* ip) {
57 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040058 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070059 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040060 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070061 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
62 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
63 case ByteCodeInstruction::kCallExternal: {
64 int argumentCount = READ8();
65 int returnCount = READ8();
66 int externalValue = READ8();
67 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
68 break;
69 }
70 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
71 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040072 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
73 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070074 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
75 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
76 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
77 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
78 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
79 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
80 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
81 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
82 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
83 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
84 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
85 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Brian Osman3e833e12019-05-23 13:23:24 -070086 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
87 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
88 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
89 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040090 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070091 VECTOR_DISASSEMBLE(kDivideS, "divideS")
92 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040093 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -070094 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
95 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
96 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
97 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
98 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
99 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
100 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
101 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
102 case ByteCodeInstruction::kLoadSwizzle: {
103 int target = READ8();
104 int count = READ8();
105 printf("loadswizzle %d %d", target, count);
106 for (int i = 0; i < count; ++i) {
107 printf(", %d", READ8());
108 }
109 break;
110 }
111 case ByteCodeInstruction::kLoadSwizzleGlobal: {
112 int target = READ8();
113 int count = READ8();
114 printf("loadswizzleglobal %d %d", target, count);
115 for (int i = 0; i < count; ++i) {
116 printf(", %d", READ8());
117 }
118 break;
119 }
120 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
121 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
122 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400123 case ByteCodeInstruction::kMatrixToMatrix: {
124 int srcCols = READ8();
125 int srcRows = READ8();
126 int dstCols = READ8();
127 int dstRows = READ8();
128 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
129 break;
130 }
Brian Osman909231c2019-05-29 15:34:36 -0400131 case ByteCodeInstruction::kMatrixMultiply: {
132 int lCols = READ8();
133 int lRows = READ8();
134 int rCols = READ8();
135 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
136 break;
137 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400138 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400139 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700140 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400141 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700142 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400143 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400144 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400145 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700146 case ByteCodeInstruction::kPushImmediate: {
147 uint32_t v = READ32();
148 union { uint32_t u; float f; } pun = { v };
149 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
150 break;
151 }
152 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
153 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
154 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
155 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
156 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
157 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
158 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
159 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400160 case ByteCodeInstruction::kScalarToMatrix: {
161 int cols = READ8();
162 int rows = READ8();
163 printf("scalartomatrix %dx%d", cols, rows);
164 break;
165 }
Brian Osman3e833e12019-05-23 13:23:24 -0700166 VECTOR_DISASSEMBLE(kSin, "sin")
167 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
168 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
169 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
170 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
171 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
172 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
173 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
174 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
175 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
176 case ByteCodeInstruction::kStoreSwizzle: {
177 int target = READ8();
178 int count = READ8();
179 printf("storeswizzle %d %d", target, count);
180 for (int i = 0; i < count; ++i) {
181 printf(", %d", READ8());
182 }
183 break;
184 }
185 case ByteCodeInstruction::kStoreSwizzleGlobal: {
186 int target = READ8();
187 int count = READ8();
188 printf("storeswizzleglobal %d %d", target, count);
189 for (int i = 0; i < count; ++i) {
190 printf(", %d", READ8());
191 }
192 break;
193 }
194 case ByteCodeInstruction::kStoreSwizzleIndirect: {
195 int count = READ8();
196 printf("storeswizzleindirect %d", count);
197 for (int i = 0; i < count; ++i) {
198 printf(", %d", READ8());
199 }
200 break;
201 }
202 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
203 int count = READ8();
204 printf("storeswizzleindirectglobal %d", count);
205 for (int i = 0; i < count; ++i) {
206 printf(", %d", READ8());
207 }
208 break;
209 }
210 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
211 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
212 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400213 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700214 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
215 case ByteCodeInstruction::kSwizzle: {
216 printf("swizzle %d, ", READ8());
217 int count = READ8();
218 printf("%d", count);
219 for (int i = 0; i < count; ++i) {
220 printf(", %d", READ8());
221 }
222 break;
223 }
224 VECTOR_DISASSEMBLE(kTan, "tan")
225 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
226 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
227 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
228 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400229 case ByteCodeInstruction::kXorB: printf("xorb"); break;
230 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
231 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
232 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
233 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
234 case ByteCodeInstruction::kBranchIfAllFalse:
235 printf("branchifallfalse %d", READ16());
236 break;
237 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
238 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
239 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
240 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
241 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
242 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700243 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
244 }
245 return ip;
246}
247
Brian Osman80164412019-06-07 13:00:23 -0400248void Disassemble(const ByteCodeFunction* f) {
249 const uint8_t* ip = f->fCode.data();
250 while (ip < f->fCode.data() + f->fCode.size()) {
251 printf("%d: ", (int) (ip - f->fCode.data()));
Brian Osman3e833e12019-05-23 13:23:24 -0700252 ip = disassemble_instruction(ip);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400253 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400254 }
255}
256
Mike Klein459aed12019-05-21 15:46:36 -0500257#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500258 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500259 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500260 POP(); \
261 /* fall through */ \
262 case ByteCodeInstruction::base ## 3: { \
263 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500264 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500265 POP(); \
266 } /* fall through */ \
267 case ByteCodeInstruction::base ## 2: { \
268 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500269 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500270 POP(); \
271 } /* fall through */ \
272 case ByteCodeInstruction::base: { \
273 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500274 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500275 POP(); \
276 break; \
277 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400278
Brian Osman1e855b22019-05-29 15:21:52 -0400279#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
280 VECTOR_BINARY_OP(base, field, op) \
281 case ByteCodeInstruction::base ## N: { \
282 int count = READ8(); \
283 for (int i = count; i > 0; --i) { \
284 sp[-count] = sp[-count].field op sp[0].field; \
285 POP(); \
286 } \
287 break; \
288 }
289
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400290#define VECTOR_BINARY_FN(base, field, fn) \
291 case ByteCodeInstruction::base ## 4: \
292 sp[-4] = fn(sp[-4].field, sp[0].field); \
293 POP(); \
294 /* fall through */ \
295 case ByteCodeInstruction::base ## 3: { \
296 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
297 sp[target] = fn(sp[target].field, sp[0].field); \
298 POP(); \
299 } /* fall through */ \
300 case ByteCodeInstruction::base ## 2: { \
301 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
302 sp[target] = fn(sp[target].field, sp[0].field); \
303 POP(); \
304 } /* fall through */ \
305 case ByteCodeInstruction::base: { \
306 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
307 sp[target] = fn(sp[target].field, sp[0].field); \
308 POP(); \
309 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500310 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400311
Mike Klein459aed12019-05-21 15:46:36 -0500312#define VECTOR_UNARY_FN(base, fn, field) \
313 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
314 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
315 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
316 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400317 break;
318
Brian Osman569f12f2019-06-13 11:23:57 -0400319#define VECTOR_UNARY_FN_VEC(base, fn) \
320 case ByteCodeInstruction::base ## 4: \
321 case ByteCodeInstruction::base ## 3: \
322 case ByteCodeInstruction::base ## 2: \
323 case ByteCodeInstruction::base : { \
324 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
325 float* v = (float*)sp - count + 1; \
326 for (int i = VecWidth * count; i > 0; --i, ++v) { \
327 *v = fn(*v); \
328 } \
329 break; \
330 }
331
332union VValue {
333 VValue() {}
334
335 VValue(F32 f)
336 : fFloat(f) {
337 }
338
339 VValue(I32 s)
340 : fSigned(s) {
341 }
342
343 VValue(U32 u)
344 : fUnsigned(u) {
345 }
346
347 F32 fFloat;
348 I32 fSigned;
349 U32 fUnsigned;
350};
351
Brian Osman226668a2019-05-14 16:47:30 -0400352struct StackFrame {
353 const uint8_t* fCode;
354 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400355 VValue* fStack;
Brian Osman226668a2019-05-14 16:47:30 -0400356};
357
Brian Osman569f12f2019-06-13 11:23:57 -0400358static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400359 return start * (1 - t) + end * t;
360}
361
Brian Osman569f12f2019-06-13 11:23:57 -0400362// TODO: trunc on integers?
363template <typename T>
364static T vec_mod(T a, T b) {
365 return a - skvx::trunc(a / b) * b;
366}
Mike Kleine7007382019-05-21 08:36:32 -0500367
Brian Osman569f12f2019-06-13 11:23:57 -0400368void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack, Value* outReturn,
369 I32 initMask, VValue globals[], int globalCount) {
370 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
371
372 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
373 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500374
Brian Osman80164412019-06-07 13:00:23 -0400375 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400376 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400377 std::vector<StackFrame> frames;
378
Brian Osman569f12f2019-06-13 11:23:57 -0400379 I32 condStack[16]; // Independent condition masks
380 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
381 I32 contStack[16]; // Continue flags for loops
382 I32 loopStack[16]; // Loop execution masks
383 condStack[0] = maskStack[0] = initMask;
384 contStack[0] = I32( 0);
385 loopStack[0] = I32(~0);
386 I32* condPtr = condStack;
387 I32* maskPtr = maskStack;
388 I32* contPtr = contStack;
389 I32* loopPtr = loopStack;
390
391 auto mask = [&]() { return *maskPtr & *loopPtr; };
392
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400393 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400394#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700395 printf("at %3d ", (int) (ip - code));
396 disassemble_instruction(ip);
397 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400398#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700399 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400400 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500401 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400402 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400403
404 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400405 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400406 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
407 POP();
408 break;
409 case ByteCodeInstruction::kNotB:
410 sp[0] = ~sp[0].fSigned;
411 break;
412 case ByteCodeInstruction::kOrB:
413 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
414 POP();
415 break;
416 case ByteCodeInstruction::kXorB:
417 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400418 POP();
419 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400420
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400421 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400422 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400423 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400424
Brian Osman226668a2019-05-14 16:47:30 -0400425 case ByteCodeInstruction::kCall: {
426 // Precursor code has pushed all parameters to the stack. Update our bottom of
427 // stack to point at the first parameter, and our sp to point past those parameters
428 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500429 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400430 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400431 if (skvx::any(mask())) {
432 frames.push_back({ code, ip, stack });
433 ip = code = fun->fCode.data();
434 stack = sp - fun->fParameterCount + 1;
435 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
436 } else {
437 sp -= fun->fParameterCount;
438 sp += fun->fReturnCount;
439 }
Brian Osman226668a2019-05-14 16:47:30 -0400440 break;
441 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400442
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400443 case ByteCodeInstruction::kCallExternal: {
444 int argumentCount = READ8();
445 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500446 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400447 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400448 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500449
Brian Osman569f12f2019-06-13 11:23:57 -0400450 Value tmpArgs[4];
451 Value tmpReturn[4];
452 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
453 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
454
455 I32 m = mask();
456 for (int i = 0; i < VecWidth; ++i) {
457 if (m[i]) {
458 for (int j = 0; j < argumentCount; ++j) {
459 tmpArgs[j].fSigned = sp[j].fSigned[i];
460 }
461 v->call(tmpArgs, tmpReturn);
462 for (int j = 0; j < returnCount; ++j) {
463 sp[j].fSigned[i] = tmpReturn[j].fSigned;
464 }
465 }
466 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400467 sp += returnCount - 1;
468 break;
469 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400470
Mike Kleinc1999982019-05-21 13:03:49 -0500471 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400472 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500473 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400474 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500475 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
476 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
477 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
478 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
479 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
480 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
481 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
482 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
483 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
484 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
485 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
486 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400487
Brian Osman569f12f2019-06-13 11:23:57 -0400488 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
489 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
490 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
491 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400492 break;
493
Brian Osman569f12f2019-06-13 11:23:57 -0400494 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
495 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
496 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
497 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400498 break;
499
Brian Osman569f12f2019-06-13 11:23:57 -0400500 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
501 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
502 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
503 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400504 break;
505
Brian Osman569f12f2019-06-13 11:23:57 -0400506 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400507
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400508 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400509 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
510 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
511 F32 cx = ay*bz - az*by,
512 cy = az*bx - ax*bz,
513 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400514 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400515 sp[-2] = cx;
516 sp[-1] = cy;
517 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400518 break;
519 }
520
Mike Kleinc1999982019-05-21 13:03:49 -0500521 VECTOR_BINARY_OP(kDivideS, fSigned, /)
522 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400523 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500524
525 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
526 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
527 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
528 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
529 break;
530
Brian Osman07c117b2019-05-23 12:51:06 -0700531 case ByteCodeInstruction::kDupN: {
532 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400533 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700534 sp += count;
535 break;
536 }
537
Mike Kleine7007382019-05-21 08:36:32 -0500538 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
539 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
540 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
541 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
542 ++ip;
543 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
544 break;
545
Brian Osman80164412019-06-07 13:00:23 -0400546 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
547 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
548 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
549 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500550 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700551 sp += (int)inst -
552 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500553 break;
554
Brian Osman07c117b2019-05-23 12:51:06 -0700555 case ByteCodeInstruction::kLoadExtended: {
556 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400557 I32 src = POP().fSigned;
558 I32 m = mask();
559 for (int i = 0; i < count; ++i) {
560 for (int j = 0; j < VecWidth; ++j) {
561 if (m[j]) {
562 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
563 }
564 }
565 }
Brian Osman07c117b2019-05-23 12:51:06 -0700566 sp += count;
567 break;
568 }
569
570 case ByteCodeInstruction::kLoadExtendedGlobal: {
571 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400572 I32 src = POP().fSigned;
573 I32 m = mask();
574 for (int i = 0; i < count; ++i) {
575 for (int j = 0; j < VecWidth; ++j) {
576 if (m[j]) {
577 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
578 }
579 }
580 }
Brian Osman07c117b2019-05-23 12:51:06 -0700581 sp += count;
582 break;
583 }
584
Mike Kleine7007382019-05-21 08:36:32 -0500585 case ByteCodeInstruction::kLoadSwizzle: {
586 int src = READ8();
587 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400588 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400589 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400590 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400591 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400592 break;
Mike Kleine7007382019-05-21 08:36:32 -0500593 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400594
Mike Kleine7007382019-05-21 08:36:32 -0500595 case ByteCodeInstruction::kLoadSwizzleGlobal: {
596 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500597 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400598 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400599 SkASSERT(src + *(ip + i) < globalCount);
600 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400601 }
602 ip += count;
603 break;
Mike Kleine7007382019-05-21 08:36:32 -0500604 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400605
Brian Osman29e013d2019-05-28 17:16:03 -0400606 case ByteCodeInstruction::kMatrixToMatrix: {
607 int srcCols = READ8();
608 int srcRows = READ8();
609 int dstCols = READ8();
610 int dstRows = READ8();
611 SkASSERT(srcCols >= 2 && srcCols <= 4);
612 SkASSERT(srcRows >= 2 && srcRows <= 4);
613 SkASSERT(dstCols >= 2 && dstCols <= 4);
614 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400615 F32 tmp[16];
616 memset(tmp, 0, sizeof(tmp));
617 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400618 for (int c = srcCols - 1; c >= 0; --c) {
619 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400620 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400621 }
622 }
623 for (int c = 0; c < dstCols; ++c) {
624 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400625 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400626 }
627 }
628 break;
629 }
630
Brian Osman909231c2019-05-29 15:34:36 -0400631 case ByteCodeInstruction::kMatrixMultiply: {
632 int lCols = READ8();
633 int lRows = READ8();
634 int rCols = READ8();
635 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400636 F32 tmp[16] = { 0.0f };
637 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
638 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400639 for (int c = 0; c < rCols; ++c) {
640 for (int r = 0; r < lRows; ++r) {
641 for (int j = 0; j < lCols; ++j) {
642 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
643 }
644 }
645 }
646 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400647 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400648 sp += (rCols * lRows);
649 break;
650 }
651
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400652 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
653 case ByteCodeInstruction::kMix4:
654 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
655 // fall through
656 case ByteCodeInstruction::kMix3: {
657 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
658 int target = 2 - count * 2;
659 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
660 // fall through
661 }
662 case ByteCodeInstruction::kMix2: {
663 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
664 int target = 1 - count * 2;
665 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
666 // fall through
667 }
668 case ByteCodeInstruction::kMix: {
669 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
670 int target = -count * 2;
671 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
672 sp -= 1 + count;
673 break;
674 }
675
Mike Kleinc1999982019-05-21 13:03:49 -0500676 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400677 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400678
Mike Kleinc1999982019-05-21 13:03:49 -0500679 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
680 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
681 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
682 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500683 break;
684
Brian Osman1e855b22019-05-29 15:21:52 -0400685 case ByteCodeInstruction::kNegateFN: {
686 int count = READ8();
687 for (int i = count - 1; i >= 0; --i) {
688 sp[-i] = -sp[-i].fFloat;
689 }
690 break;
691 }
692
Mike Kleinc1999982019-05-21 13:03:49 -0500693 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
694 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
695 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400696 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500697 break;
698
699 case ByteCodeInstruction::kPop4: POP();
700 case ByteCodeInstruction::kPop3: POP();
701 case ByteCodeInstruction::kPop2: POP();
702 case ByteCodeInstruction::kPop : POP();
703 break;
704
Brian Osman07c117b2019-05-23 12:51:06 -0700705 case ByteCodeInstruction::kPopN:
706 sp -= READ8();
707 break;
708
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400709 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400710 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400711 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400712
Brian Osman569f12f2019-06-13 11:23:57 -0400713 case ByteCodeInstruction::kReadExternal:
714 case ByteCodeInstruction::kReadExternal2:
715 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500716 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400717 // TODO: Support striped external values, or passing lane index? This model is odd.
718 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500719 int src = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400720 int32_t tmp[4];
721 I32 m = mask();
722 for (int i = 0; i < VecWidth; ++i) {
723 if (m[i]) {
724 byteCode->fExternalValues[src]->read(tmp);
725 for (int j = 0; j < count; ++j) {
726 sp[j + 1].fSigned[i] = tmp[j];
727 }
728 }
729 }
730 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400731 break;
Mike Kleine7007382019-05-21 08:36:32 -0500732 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400733
Brian Osman569f12f2019-06-13 11:23:57 -0400734 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
735 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
736 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400737
Mike Kleine7007382019-05-21 08:36:32 -0500738 case ByteCodeInstruction::kReturn: {
739 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400740 if (frames.empty()) {
741 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400742 // TODO: This can be smarter, knowing that mask is left-justified
743 I32 m = mask();
744 VValue* src = sp - count + 1;
745 for (int i = 0; i < count; ++i) {
746 for (int j = 0; j < VecWidth; ++j) {
747 if (m[j]) {
748 outReturn[count * j].fSigned = src->fSigned[j];
749 }
750 }
751 ++outReturn;
752 ++src;
753 }
Brian Osman226668a2019-05-14 16:47:30 -0400754 }
755 return;
756 } else {
757 // When we were called, 'stack' was positioned at the old top-of-stack (where
758 // our parameters were placed). So copy our return values to that same spot.
Brian Osman569f12f2019-06-13 11:23:57 -0400759 memmove(stack, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400760
761 // Now move the stack pointer to the end of the just-pushed return values,
762 // and restore everything else.
763 const StackFrame& frame(frames.back());
764 sp = stack + count - 1;
765 stack = frame.fStack;
766 code = frame.fCode;
767 ip = frame.fIP;
768 frames.pop_back();
769 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400770 }
Mike Kleine7007382019-05-21 08:36:32 -0500771 }
772
Brian Osman29e013d2019-05-28 17:16:03 -0400773 case ByteCodeInstruction::kScalarToMatrix: {
774 int cols = READ8();
775 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400776 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400777 for (int c = 0; c < cols; ++c) {
778 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400779 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400780 }
781 }
782 break;
783 }
784
Brian Osman569f12f2019-06-13 11:23:57 -0400785 VECTOR_UNARY_FN_VEC(kSin, sinf)
786 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400787
Brian Osman569f12f2019-06-13 11:23:57 -0400788 case ByteCodeInstruction::kStore4:
789 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
790 case ByteCodeInstruction::kStore3:
791 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
792 case ByteCodeInstruction::kStore2:
793 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
794 case ByteCodeInstruction::kStore :
795 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
796 ++ip;
797 break;
Mike Kleine7007382019-05-21 08:36:32 -0500798
Brian Osman569f12f2019-06-13 11:23:57 -0400799 case ByteCodeInstruction::kStoreGlobal4:
800 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
801 case ByteCodeInstruction::kStoreGlobal3:
802 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
803 case ByteCodeInstruction::kStoreGlobal2:
804 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
805 case ByteCodeInstruction::kStoreGlobal :
806 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
807 ++ip;
808 break;
Mike Kleine7007382019-05-21 08:36:32 -0500809
Brian Osman07c117b2019-05-23 12:51:06 -0700810 case ByteCodeInstruction::kStoreExtended: {
811 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400812 I32 target = POP().fSigned;
813 VValue* src = sp - count + 1;
814 I32 m = mask();
815 for (int i = 0; i < count; ++i) {
816 for (int j = 0; j < VecWidth; ++j) {
817 if (m[j]) {
818 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
819 }
820 }
821 }
Brian Osman07c117b2019-05-23 12:51:06 -0700822 sp -= count;
823 break;
824 }
825 case ByteCodeInstruction::kStoreExtendedGlobal: {
826 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400827 I32 target = POP().fSigned;
828 VValue* src = sp - count + 1;
829 I32 m = mask();
830 for (int i = 0; i < count; ++i) {
831 for (int j = 0; j < VecWidth; ++j) {
832 if (m[j]) {
833 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
834 }
835 }
836 }
Brian Osman07c117b2019-05-23 12:51:06 -0700837 sp -= count;
838 break;
839 }
840
Mike Kleine7007382019-05-21 08:36:32 -0500841 case ByteCodeInstruction::kStoreSwizzle: {
842 int target = READ8();
843 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400844 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400845 stack[target + *(ip + i)] = skvx::if_then_else(
846 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400847 }
Brian Osman1091f022019-05-16 09:42:16 -0400848 ip += count;
849 break;
Mike Kleine7007382019-05-21 08:36:32 -0500850 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400851
Mike Kleine7007382019-05-21 08:36:32 -0500852 case ByteCodeInstruction::kStoreSwizzleGlobal: {
853 int target = READ8();
854 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400855 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400856 globals[target + *(ip + i)] = skvx::if_then_else(
857 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400858 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400859 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400860 break;
Mike Kleine7007382019-05-21 08:36:32 -0500861 }
Brian Osman569f12f2019-06-13 11:23:57 -0400862
Brian Osman07c117b2019-05-23 12:51:06 -0700863 case ByteCodeInstruction::kStoreSwizzleIndirect: {
Brian Osman07c117b2019-05-23 12:51:06 -0700864 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400865 I32 target = POP().fSigned;
866 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700867 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400868 I32 v = POP().fSigned;
869 for (int j = 0; j < VecWidth; ++j) {
870 if (m[j]) {
871 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
872 }
873 }
Brian Osman07c117b2019-05-23 12:51:06 -0700874 }
875 ip += count;
876 break;
877 }
Brian Osman569f12f2019-06-13 11:23:57 -0400878
Brian Osman07c117b2019-05-23 12:51:06 -0700879 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700880 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400881 I32 target = POP().fSigned;
882 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700883 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400884 I32 v = POP().fSigned;
885 for (int j = 0; j < VecWidth; ++j) {
886 if (m[j]) {
887 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
888 }
889 }
Brian Osman07c117b2019-05-23 12:51:06 -0700890 }
891 ip += count;
892 break;
893 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400894
Mike Kleinc1999982019-05-21 13:03:49 -0500895 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400896 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400897
Mike Kleine7007382019-05-21 08:36:32 -0500898 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400899 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400900 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400901 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400902 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400903 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400904 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400905 }
906 break;
Mike Kleine7007382019-05-21 08:36:32 -0500907 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400908
Brian Osman569f12f2019-06-13 11:23:57 -0400909 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400910
Brian Osman569f12f2019-06-13 11:23:57 -0400911 case ByteCodeInstruction::kWriteExternal:
912 case ByteCodeInstruction::kWriteExternal2:
913 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500914 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400915 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500916 int target = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400917 int32_t tmp[4];
918 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400919 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -0400920 for (int i = 0; i < VecWidth; ++i) {
921 if (m[i]) {
922 for (int j = 0; j < count; ++j) {
923 tmp[j] = sp[j + 1].fSigned[i];
924 }
925 byteCode->fExternalValues[target]->write(tmp);
926 }
927 }
928 break;
929 }
930
931 case ByteCodeInstruction::kMaskPush:
932 condPtr[1] = POP().fSigned;
933 maskPtr[1] = maskPtr[0] & condPtr[1];
934 ++condPtr; ++maskPtr;
935 break;
936 case ByteCodeInstruction::kMaskPop:
937 --condPtr; --maskPtr;
938 break;
939 case ByteCodeInstruction::kMaskNegate:
940 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
941 break;
942 case ByteCodeInstruction::kMaskBlend: {
943 int count = READ8();
944 I32 m = condPtr[0];
945 --condPtr; --maskPtr;
946 for (int i = 0; i < count; ++i) {
947 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
948 --sp;
949 }
950 break;
951 }
952 case ByteCodeInstruction::kBranchIfAllFalse: {
953 int target = READ16();
954 if (!skvx::any(mask())) {
955 ip = code + target;
956 }
957 break;
958 }
959
960 case ByteCodeInstruction::kLoopBegin:
961 *(++contPtr) = 0;
962 *(++loopPtr) = ~0;
963 break;
964 case ByteCodeInstruction::kLoopNext:
965 *loopPtr |= *contPtr;
966 *contPtr = 0;
967 break;
968 case ByteCodeInstruction::kLoopMask:
969 *loopPtr &= POP().fSigned;
970 break;
971 case ByteCodeInstruction::kLoopEnd:
972 --contPtr; --loopPtr;
973 break;
974 case ByteCodeInstruction::kLoopBreak:
975 *loopPtr &= ~mask();
976 break;
977 case ByteCodeInstruction::kLoopContinue: {
978 I32 m = mask();
979 *contPtr |= m;
980 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400981 break;
Mike Kleine7007382019-05-21 08:36:32 -0500982 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400983
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400984 default:
Mike Kleine7007382019-05-21 08:36:32 -0500985 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400986 }
Brian Osman569f12f2019-06-13 11:23:57 -0400987 }
988}
989
990void VecRun(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
991 int N, Value uniforms[], int uniformCount) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400992#ifdef TRACE
Brian Osman569f12f2019-06-13 11:23:57 -0400993 disassemble(f);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400994#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400995 VValue smallStack[128];
996
997 SkASSERT(uniformCount == (int)byteCode->fInputSlots.size());
998 VValue smallGlobals[32];
999 VValue* globals = smallGlobals;
1000 SkASSERT((int)SK_ARRAY_COUNT(smallGlobals) >= byteCode->fGlobalCount);
1001 for (uint8_t slot : byteCode->fInputSlots) {
1002 globals[slot].fUnsigned = (uniforms++)->fUnsigned;
1003 }
1004
1005 while (N) {
1006 VValue* stack = smallStack;
1007
1008 int w = std::min(N, VecWidth);
1009 N -= w;
1010
1011 // Transpose args into stack
1012 {
1013 uint32_t* src = (uint32_t*)args;
1014 for (int i = 0; i < w; ++i) {
1015 uint32_t* dst = (uint32_t*)stack + i;
1016 for (int j = f->fParameterCount; j > 0; --j) {
1017 *dst = *src++;
1018 dst += VecWidth;
1019 }
1020 }
1021 }
1022
1023 auto mask = w > gLanes;
1024 innerRun(byteCode, f, stack, outReturn, mask, globals, byteCode->fGlobalCount);
1025
1026 // Transpose out parameters back
1027 {
1028 uint32_t* dst = (uint32_t*)args;
1029 for (int i = 0; i < w; ++i) {
1030 uint32_t* src = (uint32_t*)stack + i;
1031 for (const auto& p : f->fParameters) {
1032 if (p.fIsOutParameter) {
1033 for (int j = p.fSlotCount; j > 0; --j) {
1034 *dst++ = *src;
1035 src += VecWidth;
1036 }
1037 } else {
1038 dst += p.fSlotCount;
1039 src += p.fSlotCount * VecWidth;
1040 }
1041 }
1042 }
1043 }
1044
1045 args += f->fParameterCount * w;
1046 outReturn += f->fReturnCount * w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001047 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001048}
1049
Brian Osman80164412019-06-07 13:00:23 -04001050void Run(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
1051 Value uniforms[], int uniformCount) {
Brian Osman569f12f2019-06-13 11:23:57 -04001052 VecRun(byteCode, f, args, outReturn, 1, uniforms, uniformCount);
Brian Osman80164412019-06-07 13:00:23 -04001053}
1054
1055} // namespace Interpreter
1056} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001057
1058#endif