Commit | Line | Data |
---|---|---|
97b58163 MD |
1 | /* |
2 | * lttng-filter-specialize.c | |
3 | * | |
4 | * LTTng UST filter code specializer. | |
5 | * | |
6 | * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
7 | * | |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; only | |
11 | * version 2.1 of the License. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
23 | #include "lttng-filter.h" | |
24 | ||
25 | int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode) | |
26 | { | |
27 | void *pc, *next_pc, *start_pc; | |
28 | int ret = -EINVAL; | |
0305960f MD |
29 | struct vstack _stack; |
30 | struct vstack *stack = &_stack; | |
97b58163 | 31 | |
0305960f | 32 | vstack_init(stack); |
97b58163 MD |
33 | |
34 | start_pc = &bytecode->data[0]; | |
35 | for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; | |
36 | pc = next_pc) { | |
37 | switch (*(filter_opcode_t *) pc) { | |
38 | case FILTER_OP_UNKNOWN: | |
39 | default: | |
40 | ERR("unknown bytecode op %u\n", | |
41 | (unsigned int) *(filter_opcode_t *) pc); | |
42 | ret = -EINVAL; | |
43 | goto end; | |
44 | ||
45 | case FILTER_OP_RETURN: | |
46 | ret = 0; | |
47 | goto end; | |
48 | ||
49 | /* binary */ | |
50 | case FILTER_OP_MUL: | |
51 | case FILTER_OP_DIV: | |
52 | case FILTER_OP_MOD: | |
53 | case FILTER_OP_PLUS: | |
54 | case FILTER_OP_MINUS: | |
55 | case FILTER_OP_RSHIFT: | |
56 | case FILTER_OP_LSHIFT: | |
57 | case FILTER_OP_BIN_AND: | |
58 | case FILTER_OP_BIN_OR: | |
59 | case FILTER_OP_BIN_XOR: | |
60 | ERR("unsupported bytecode op %u\n", | |
61 | (unsigned int) *(filter_opcode_t *) pc); | |
62 | ret = -EINVAL; | |
63 | goto end; | |
64 | ||
65 | case FILTER_OP_EQ: | |
66 | { | |
67 | struct binary_op *insn = (struct binary_op *) pc; | |
68 | ||
0305960f | 69 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
70 | default: |
71 | ERR("unknown register type\n"); | |
72 | ret = -EINVAL; | |
73 | goto end; | |
74 | ||
75 | case REG_STRING: | |
53569322 MD |
76 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
77 | break; | |
97b58163 MD |
78 | insn->op = FILTER_OP_EQ_STRING; |
79 | break; | |
80 | case REG_S64: | |
53569322 MD |
81 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
82 | break; | |
0305960f | 83 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
84 | insn->op = FILTER_OP_EQ_S64; |
85 | else | |
dbea82ec | 86 | insn->op = FILTER_OP_EQ_DOUBLE_S64; |
97b58163 MD |
87 | break; |
88 | case REG_DOUBLE: | |
53569322 MD |
89 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
90 | break; | |
dbea82ec MD |
91 | if (vstack_bx(stack)->type == REG_S64) |
92 | insn->op = FILTER_OP_EQ_S64_DOUBLE; | |
93 | else | |
94 | insn->op = FILTER_OP_EQ_DOUBLE; | |
97b58163 | 95 | break; |
53569322 MD |
96 | case REG_UNKNOWN: |
97 | break; /* Dynamic typing. */ | |
97b58163 | 98 | } |
0305960f MD |
99 | /* Pop 2, push 1 */ |
100 | if (vstack_pop(stack)) { | |
101 | ret = -EINVAL; | |
102 | goto end; | |
103 | } | |
104 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
105 | next_pc += sizeof(struct binary_op); |
106 | break; | |
107 | } | |
108 | ||
109 | case FILTER_OP_NE: | |
110 | { | |
111 | struct binary_op *insn = (struct binary_op *) pc; | |
112 | ||
0305960f | 113 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
114 | default: |
115 | ERR("unknown register type\n"); | |
116 | ret = -EINVAL; | |
117 | goto end; | |
118 | ||
119 | case REG_STRING: | |
53569322 MD |
120 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
121 | break; | |
97b58163 MD |
122 | insn->op = FILTER_OP_NE_STRING; |
123 | break; | |
124 | case REG_S64: | |
53569322 MD |
125 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
126 | break; | |
0305960f | 127 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
128 | insn->op = FILTER_OP_NE_S64; |
129 | else | |
dbea82ec | 130 | insn->op = FILTER_OP_NE_DOUBLE_S64; |
97b58163 MD |
131 | break; |
132 | case REG_DOUBLE: | |
53569322 MD |
133 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
134 | break; | |
dbea82ec MD |
135 | if (vstack_bx(stack)->type == REG_S64) |
136 | insn->op = FILTER_OP_NE_S64_DOUBLE; | |
137 | else | |
138 | insn->op = FILTER_OP_NE_DOUBLE; | |
97b58163 | 139 | break; |
53569322 MD |
140 | case REG_UNKNOWN: |
141 | break; /* Dynamic typing. */ | |
97b58163 | 142 | } |
0305960f MD |
143 | /* Pop 2, push 1 */ |
144 | if (vstack_pop(stack)) { | |
145 | ret = -EINVAL; | |
146 | goto end; | |
147 | } | |
148 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
149 | next_pc += sizeof(struct binary_op); |
150 | break; | |
151 | } | |
152 | ||
153 | case FILTER_OP_GT: | |
154 | { | |
155 | struct binary_op *insn = (struct binary_op *) pc; | |
156 | ||
0305960f | 157 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
158 | default: |
159 | ERR("unknown register type\n"); | |
160 | ret = -EINVAL; | |
161 | goto end; | |
162 | ||
163 | case REG_STRING: | |
53569322 MD |
164 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
165 | break; | |
97b58163 MD |
166 | insn->op = FILTER_OP_GT_STRING; |
167 | break; | |
168 | case REG_S64: | |
53569322 MD |
169 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
170 | break; | |
0305960f | 171 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
172 | insn->op = FILTER_OP_GT_S64; |
173 | else | |
dbea82ec | 174 | insn->op = FILTER_OP_GT_DOUBLE_S64; |
97b58163 MD |
175 | break; |
176 | case REG_DOUBLE: | |
53569322 MD |
177 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
178 | break; | |
dbea82ec MD |
179 | if (vstack_bx(stack)->type == REG_S64) |
180 | insn->op = FILTER_OP_GT_S64_DOUBLE; | |
181 | else | |
182 | insn->op = FILTER_OP_GT_DOUBLE; | |
97b58163 | 183 | break; |
53569322 MD |
184 | case REG_UNKNOWN: |
185 | break; /* Dynamic typing. */ | |
97b58163 | 186 | } |
0305960f MD |
187 | /* Pop 2, push 1 */ |
188 | if (vstack_pop(stack)) { | |
189 | ret = -EINVAL; | |
190 | goto end; | |
191 | } | |
192 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
193 | next_pc += sizeof(struct binary_op); |
194 | break; | |
195 | } | |
196 | ||
197 | case FILTER_OP_LT: | |
198 | { | |
199 | struct binary_op *insn = (struct binary_op *) pc; | |
200 | ||
0305960f | 201 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
202 | default: |
203 | ERR("unknown register type\n"); | |
204 | ret = -EINVAL; | |
205 | goto end; | |
206 | ||
207 | case REG_STRING: | |
53569322 MD |
208 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
209 | break; | |
97b58163 MD |
210 | insn->op = FILTER_OP_LT_STRING; |
211 | break; | |
212 | case REG_S64: | |
53569322 MD |
213 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
214 | break; | |
0305960f | 215 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
216 | insn->op = FILTER_OP_LT_S64; |
217 | else | |
dbea82ec | 218 | insn->op = FILTER_OP_LT_DOUBLE_S64; |
97b58163 MD |
219 | break; |
220 | case REG_DOUBLE: | |
53569322 MD |
221 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
222 | break; | |
dbea82ec MD |
223 | if (vstack_bx(stack)->type == REG_S64) |
224 | insn->op = FILTER_OP_LT_S64_DOUBLE; | |
225 | else | |
226 | insn->op = FILTER_OP_LT_DOUBLE; | |
97b58163 | 227 | break; |
53569322 MD |
228 | case REG_UNKNOWN: |
229 | break; /* Dynamic typing. */ | |
97b58163 | 230 | } |
0305960f MD |
231 | /* Pop 2, push 1 */ |
232 | if (vstack_pop(stack)) { | |
233 | ret = -EINVAL; | |
234 | goto end; | |
235 | } | |
236 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
237 | next_pc += sizeof(struct binary_op); |
238 | break; | |
239 | } | |
240 | ||
241 | case FILTER_OP_GE: | |
242 | { | |
243 | struct binary_op *insn = (struct binary_op *) pc; | |
244 | ||
0305960f | 245 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
246 | default: |
247 | ERR("unknown register type\n"); | |
248 | ret = -EINVAL; | |
249 | goto end; | |
250 | ||
251 | case REG_STRING: | |
53569322 MD |
252 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
253 | break; | |
97b58163 MD |
254 | insn->op = FILTER_OP_GE_STRING; |
255 | break; | |
256 | case REG_S64: | |
53569322 MD |
257 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
258 | break; | |
0305960f | 259 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
260 | insn->op = FILTER_OP_GE_S64; |
261 | else | |
dbea82ec | 262 | insn->op = FILTER_OP_GE_DOUBLE_S64; |
97b58163 MD |
263 | break; |
264 | case REG_DOUBLE: | |
53569322 MD |
265 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
266 | break; | |
dbea82ec MD |
267 | if (vstack_bx(stack)->type == REG_S64) |
268 | insn->op = FILTER_OP_GE_S64_DOUBLE; | |
269 | else | |
270 | insn->op = FILTER_OP_GE_DOUBLE; | |
97b58163 | 271 | break; |
53569322 MD |
272 | case REG_UNKNOWN: |
273 | break; /* Dynamic typing. */ | |
97b58163 | 274 | } |
0305960f MD |
275 | /* Pop 2, push 1 */ |
276 | if (vstack_pop(stack)) { | |
277 | ret = -EINVAL; | |
278 | goto end; | |
279 | } | |
280 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
281 | next_pc += sizeof(struct binary_op); |
282 | break; | |
283 | } | |
284 | case FILTER_OP_LE: | |
285 | { | |
286 | struct binary_op *insn = (struct binary_op *) pc; | |
287 | ||
0305960f | 288 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
289 | default: |
290 | ERR("unknown register type\n"); | |
291 | ret = -EINVAL; | |
292 | goto end; | |
293 | ||
294 | case REG_STRING: | |
53569322 MD |
295 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
296 | break; | |
97b58163 MD |
297 | insn->op = FILTER_OP_LE_STRING; |
298 | break; | |
299 | case REG_S64: | |
53569322 MD |
300 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
301 | break; | |
0305960f | 302 | if (vstack_bx(stack)->type == REG_S64) |
97b58163 MD |
303 | insn->op = FILTER_OP_LE_S64; |
304 | else | |
dbea82ec | 305 | insn->op = FILTER_OP_LE_DOUBLE_S64; |
97b58163 MD |
306 | break; |
307 | case REG_DOUBLE: | |
53569322 MD |
308 | if (vstack_bx(stack)->type == REG_UNKNOWN) |
309 | break; | |
dbea82ec MD |
310 | if (vstack_bx(stack)->type == REG_S64) |
311 | insn->op = FILTER_OP_LE_S64_DOUBLE; | |
312 | else | |
313 | insn->op = FILTER_OP_LE_DOUBLE; | |
97b58163 | 314 | break; |
53569322 MD |
315 | case REG_UNKNOWN: |
316 | break; /* Dynamic typing. */ | |
97b58163 | 317 | } |
0305960f | 318 | vstack_ax(stack)->type = REG_S64; |
97b58163 MD |
319 | next_pc += sizeof(struct binary_op); |
320 | break; | |
321 | } | |
322 | ||
323 | case FILTER_OP_EQ_STRING: | |
324 | case FILTER_OP_NE_STRING: | |
325 | case FILTER_OP_GT_STRING: | |
326 | case FILTER_OP_LT_STRING: | |
327 | case FILTER_OP_GE_STRING: | |
328 | case FILTER_OP_LE_STRING: | |
329 | case FILTER_OP_EQ_S64: | |
330 | case FILTER_OP_NE_S64: | |
331 | case FILTER_OP_GT_S64: | |
332 | case FILTER_OP_LT_S64: | |
333 | case FILTER_OP_GE_S64: | |
334 | case FILTER_OP_LE_S64: | |
335 | case FILTER_OP_EQ_DOUBLE: | |
336 | case FILTER_OP_NE_DOUBLE: | |
337 | case FILTER_OP_GT_DOUBLE: | |
338 | case FILTER_OP_LT_DOUBLE: | |
339 | case FILTER_OP_GE_DOUBLE: | |
340 | case FILTER_OP_LE_DOUBLE: | |
dbea82ec MD |
341 | case FILTER_OP_EQ_DOUBLE_S64: |
342 | case FILTER_OP_NE_DOUBLE_S64: | |
343 | case FILTER_OP_GT_DOUBLE_S64: | |
344 | case FILTER_OP_LT_DOUBLE_S64: | |
345 | case FILTER_OP_GE_DOUBLE_S64: | |
346 | case FILTER_OP_LE_DOUBLE_S64: | |
347 | case FILTER_OP_EQ_S64_DOUBLE: | |
348 | case FILTER_OP_NE_S64_DOUBLE: | |
349 | case FILTER_OP_GT_S64_DOUBLE: | |
350 | case FILTER_OP_LT_S64_DOUBLE: | |
351 | case FILTER_OP_GE_S64_DOUBLE: | |
352 | case FILTER_OP_LE_S64_DOUBLE: | |
97b58163 | 353 | { |
0305960f MD |
354 | /* Pop 2, push 1 */ |
355 | if (vstack_pop(stack)) { | |
356 | ret = -EINVAL; | |
357 | goto end; | |
358 | } | |
359 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
360 | next_pc += sizeof(struct binary_op); |
361 | break; | |
362 | } | |
363 | ||
364 | /* unary */ | |
365 | case FILTER_OP_UNARY_PLUS: | |
366 | { | |
367 | struct unary_op *insn = (struct unary_op *) pc; | |
368 | ||
0305960f | 369 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
370 | default: |
371 | ERR("unknown register type\n"); | |
372 | ret = -EINVAL; | |
373 | goto end; | |
374 | ||
375 | case REG_S64: | |
376 | insn->op = FILTER_OP_UNARY_PLUS_S64; | |
377 | break; | |
378 | case REG_DOUBLE: | |
379 | insn->op = FILTER_OP_UNARY_PLUS_DOUBLE; | |
380 | break; | |
53569322 MD |
381 | case REG_UNKNOWN: /* Dynamic typing. */ |
382 | break; | |
97b58163 | 383 | } |
0305960f | 384 | /* Pop 1, push 1 */ |
97b58163 MD |
385 | next_pc += sizeof(struct unary_op); |
386 | break; | |
387 | } | |
388 | ||
389 | case FILTER_OP_UNARY_MINUS: | |
390 | { | |
391 | struct unary_op *insn = (struct unary_op *) pc; | |
392 | ||
0305960f | 393 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
394 | default: |
395 | ERR("unknown register type\n"); | |
396 | ret = -EINVAL; | |
397 | goto end; | |
398 | ||
399 | case REG_S64: | |
400 | insn->op = FILTER_OP_UNARY_MINUS_S64; | |
401 | break; | |
402 | case REG_DOUBLE: | |
403 | insn->op = FILTER_OP_UNARY_MINUS_DOUBLE; | |
404 | break; | |
53569322 MD |
405 | case REG_UNKNOWN: /* Dynamic typing. */ |
406 | break; | |
97b58163 | 407 | } |
0305960f | 408 | /* Pop 1, push 1 */ |
97b58163 MD |
409 | next_pc += sizeof(struct unary_op); |
410 | break; | |
411 | } | |
412 | ||
413 | case FILTER_OP_UNARY_NOT: | |
414 | { | |
415 | struct unary_op *insn = (struct unary_op *) pc; | |
416 | ||
0305960f | 417 | switch(vstack_ax(stack)->type) { |
97b58163 MD |
418 | default: |
419 | ERR("unknown register type\n"); | |
420 | ret = -EINVAL; | |
421 | goto end; | |
422 | ||
423 | case REG_S64: | |
424 | insn->op = FILTER_OP_UNARY_NOT_S64; | |
425 | break; | |
426 | case REG_DOUBLE: | |
427 | insn->op = FILTER_OP_UNARY_NOT_DOUBLE; | |
428 | break; | |
53569322 MD |
429 | case REG_UNKNOWN: /* Dynamic typing. */ |
430 | break; | |
97b58163 | 431 | } |
0305960f | 432 | /* Pop 1, push 1 */ |
97b58163 MD |
433 | next_pc += sizeof(struct unary_op); |
434 | break; | |
435 | } | |
436 | ||
437 | case FILTER_OP_UNARY_PLUS_S64: | |
438 | case FILTER_OP_UNARY_MINUS_S64: | |
439 | case FILTER_OP_UNARY_NOT_S64: | |
440 | case FILTER_OP_UNARY_PLUS_DOUBLE: | |
441 | case FILTER_OP_UNARY_MINUS_DOUBLE: | |
442 | case FILTER_OP_UNARY_NOT_DOUBLE: | |
443 | { | |
0305960f | 444 | /* Pop 1, push 1 */ |
97b58163 MD |
445 | next_pc += sizeof(struct unary_op); |
446 | break; | |
447 | } | |
448 | ||
449 | /* logical */ | |
450 | case FILTER_OP_AND: | |
451 | case FILTER_OP_OR: | |
452 | { | |
b9f4cd79 MD |
453 | /* Continue to next instruction */ |
454 | /* Pop 1 when jump not taken */ | |
455 | if (vstack_pop(stack)) { | |
456 | ret = -EINVAL; | |
457 | goto end; | |
458 | } | |
97b58163 MD |
459 | next_pc += sizeof(struct logical_op); |
460 | break; | |
461 | } | |
462 | ||
77aa5901 | 463 | /* load field ref */ |
97b58163 MD |
464 | case FILTER_OP_LOAD_FIELD_REF: |
465 | { | |
466 | ERR("Unknown field ref type\n"); | |
467 | ret = -EINVAL; | |
468 | goto end; | |
469 | } | |
77aa5901 MD |
470 | /* get context ref */ |
471 | case FILTER_OP_GET_CONTEXT_REF: | |
472 | { | |
53569322 MD |
473 | if (vstack_push(stack)) { |
474 | ret = -EINVAL; | |
475 | goto end; | |
476 | } | |
477 | vstack_ax(stack)->type = REG_UNKNOWN; | |
478 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); | |
479 | break; | |
77aa5901 | 480 | } |
97b58163 MD |
481 | case FILTER_OP_LOAD_FIELD_REF_STRING: |
482 | case FILTER_OP_LOAD_FIELD_REF_SEQUENCE: | |
77aa5901 | 483 | case FILTER_OP_GET_CONTEXT_REF_STRING: |
97b58163 | 484 | { |
0305960f MD |
485 | if (vstack_push(stack)) { |
486 | ret = -EINVAL; | |
487 | goto end; | |
488 | } | |
489 | vstack_ax(stack)->type = REG_STRING; | |
97b58163 MD |
490 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); |
491 | break; | |
492 | } | |
493 | case FILTER_OP_LOAD_FIELD_REF_S64: | |
77aa5901 | 494 | case FILTER_OP_GET_CONTEXT_REF_S64: |
97b58163 | 495 | { |
0305960f MD |
496 | if (vstack_push(stack)) { |
497 | ret = -EINVAL; | |
498 | goto end; | |
499 | } | |
500 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
501 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); |
502 | break; | |
503 | } | |
504 | case FILTER_OP_LOAD_FIELD_REF_DOUBLE: | |
77aa5901 | 505 | case FILTER_OP_GET_CONTEXT_REF_DOUBLE: |
97b58163 | 506 | { |
0305960f MD |
507 | if (vstack_push(stack)) { |
508 | ret = -EINVAL; | |
509 | goto end; | |
510 | } | |
511 | vstack_ax(stack)->type = REG_DOUBLE; | |
97b58163 MD |
512 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); |
513 | break; | |
514 | } | |
515 | ||
77aa5901 | 516 | /* load from immediate operand */ |
97b58163 MD |
517 | case FILTER_OP_LOAD_STRING: |
518 | { | |
519 | struct load_op *insn = (struct load_op *) pc; | |
520 | ||
0305960f MD |
521 | if (vstack_push(stack)) { |
522 | ret = -EINVAL; | |
523 | goto end; | |
524 | } | |
525 | vstack_ax(stack)->type = REG_STRING; | |
97b58163 MD |
526 | next_pc += sizeof(struct load_op) + strlen(insn->data) + 1; |
527 | break; | |
528 | } | |
529 | ||
530 | case FILTER_OP_LOAD_S64: | |
531 | { | |
0305960f MD |
532 | if (vstack_push(stack)) { |
533 | ret = -EINVAL; | |
534 | goto end; | |
535 | } | |
536 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
537 | next_pc += sizeof(struct load_op) |
538 | + sizeof(struct literal_numeric); | |
539 | break; | |
540 | } | |
541 | ||
542 | case FILTER_OP_LOAD_DOUBLE: | |
543 | { | |
0305960f MD |
544 | if (vstack_push(stack)) { |
545 | ret = -EINVAL; | |
546 | goto end; | |
547 | } | |
548 | vstack_ax(stack)->type = REG_DOUBLE; | |
97b58163 MD |
549 | next_pc += sizeof(struct load_op) |
550 | + sizeof(struct literal_double); | |
551 | break; | |
552 | } | |
553 | ||
554 | /* cast */ | |
555 | case FILTER_OP_CAST_TO_S64: | |
556 | { | |
557 | struct cast_op *insn = (struct cast_op *) pc; | |
558 | ||
0305960f | 559 | switch (vstack_ax(stack)->type) { |
97b58163 MD |
560 | default: |
561 | ERR("unknown register type\n"); | |
562 | ret = -EINVAL; | |
563 | goto end; | |
564 | ||
565 | case REG_STRING: | |
566 | ERR("Cast op can only be applied to numeric or floating point registers\n"); | |
567 | ret = -EINVAL; | |
568 | goto end; | |
569 | case REG_S64: | |
570 | insn->op = FILTER_OP_CAST_NOP; | |
571 | break; | |
572 | case REG_DOUBLE: | |
573 | insn->op = FILTER_OP_CAST_DOUBLE_TO_S64; | |
574 | break; | |
53569322 MD |
575 | case REG_UNKNOWN: |
576 | break; | |
97b58163 | 577 | } |
0305960f MD |
578 | /* Pop 1, push 1 */ |
579 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
580 | next_pc += sizeof(struct cast_op); |
581 | break; | |
582 | } | |
583 | case FILTER_OP_CAST_DOUBLE_TO_S64: | |
584 | { | |
0305960f MD |
585 | /* Pop 1, push 1 */ |
586 | vstack_ax(stack)->type = REG_S64; | |
97b58163 MD |
587 | next_pc += sizeof(struct cast_op); |
588 | break; | |
589 | } | |
590 | case FILTER_OP_CAST_NOP: | |
591 | { | |
592 | next_pc += sizeof(struct cast_op); | |
593 | break; | |
594 | } | |
595 | ||
97b58163 MD |
596 | } |
597 | } | |
598 | end: | |
599 | return ret; | |
600 | } |