static struct ureg calculate_light_attenuation( struct tnl_program *p, GLuint i, struct ureg VPpli, struct ureg dist ) { struct ureg attenuation = register_param3(p, STATE_LIGHT, i, STATE_ATTENUATION); struct ureg att = undef; /* Calculate spot attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180) { struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL, STATE_LIGHT_SPOT_DIR_NORMALIZED, i); struct ureg spot = get_temp(p); struct ureg slt = get_temp(p); att = get_temp(p); emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm); emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot); emit_op1(p, OPCODE_ABS, spot, 0, spot); emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W)); emit_op2(p, OPCODE_MUL, att, 0, slt, spot); release_temp(p, spot); release_temp(p, slt); } /* Calculate distance attenuation(See formula (2.4) at glspec 2.1 page 62): * * Skip the calucation when _dist_ is undefined(light_eyepos3_is_zero) */ if (p->state->unit[i].light_attenuated && !is_undef(dist)) { if (is_undef(att)) att = get_temp(p); /* 1/d,d,d,1/d */ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist); /* 1,d,d*d,1/d */ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y)); /* 1/dist-atten */ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist); if (!p->state->unit[i].light_spotcutoff_is_180) { /* dist-atten */ emit_op1(p, OPCODE_RCP, dist, 0, dist); /* spot-atten * dist-atten */ emit_op2(p, OPCODE_MUL, att, 0, dist, att); } else { /* dist-atten */ emit_op1(p, OPCODE_RCP, att, 0, dist); } } return att; }
static struct ureg get_identity_param( struct tnl_program *p ) { if (is_undef(p->identity)) p->identity = register_const4f(p, 0,0,0,1); return p->identity; }
static struct ureg get_eye_normal( struct tnl_program *p ) { if (is_undef(p->eye_normal)) { struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL ); struct ureg mvinv[3]; register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2, STATE_MATRIX_INVTRANS, mvinv ); p->eye_normal = reserve_temp(p); /* Transform to eye space: */ emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal ); /* Normalize/Rescale: */ if (p->state->normalize) { emit_normalize_vec3( p, p->eye_normal, p->eye_normal ); } else if (p->state->rescale_normals) { struct ureg rescale = register_param2(p, STATE_INTERNAL, STATE_NORMAL_SCALE); emit_op2( p, OPCODE_MUL, p->eye_normal, 0, p->eye_normal, swizzle1(rescale, X)); } } return p->eye_normal; }
static struct ureg get_transformed_normal( struct tnl_program *p ) { if (is_undef(p->transformed_normal) && !p->state->need_eye_coords && !p->state->normalize && !(p->state->need_eye_coords == p->state->rescale_normals)) { p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL ); } else if (is_undef(p->transformed_normal)) { struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL ); struct ureg mvinv[3]; struct ureg transformed_normal = reserve_temp(p); if (p->state->need_eye_coords) { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2, STATE_MATRIX_INVTRANS, mvinv ); /* Transform to eye space: */ emit_matrix_transform_vec3( p, transformed_normal, mvinv, normal ); normal = transformed_normal; } /* Normalize/Rescale: */ if (p->state->normalize) { emit_normalize_vec3( p, transformed_normal, normal ); normal = transformed_normal; } else if (p->state->need_eye_coords == p->state->rescale_normals) { /* This is already adjusted for eye/non-eye rendering: */ struct ureg rescale = register_param2(p, STATE_INTERNAL, STATE_NORMAL_SCALE); emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal, rescale ); normal = transformed_normal; } assert(normal.file == PROGRAM_TEMPORARY); p->transformed_normal = normal; } return p->transformed_normal; }
static struct ureg get_eye_position_normalized( struct tnl_program *p ) { if (is_undef(p->eye_position_normalized)) { struct ureg eye = get_eye_position(p); p->eye_position_normalized = reserve_temp(p); emit_normalize_vec3(p, p->eye_position_normalized, eye); } return p->eye_position_normalized; }
static struct ureg get_eye_position_z( struct tnl_program *p ) { if (!is_undef(p->eye_position)) return swizzle1(p->eye_position, Z); if (is_undef(p->eye_position_z)) { struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg modelview[4]; p->eye_position_z = reserve_temp(p); register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 0, modelview ); emit_op2(p, OPCODE_DP4, p->eye_position_z, 0, pos, modelview[2]); } return p->eye_position_z; }
static struct ureg get_eye_z( struct tnl_program *p ) { if (!is_undef(p->eye_position)) { return swizzle1(p->eye_position, Z); } else if (!is_undef(p->eye_z)) { struct ureg pos = register_input( p, BRW_ATTRIB_POS ); struct ureg modelview2; p->eye_z = reserve_temp(p); register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 2, 1, STATE_MATRIX, &modelview2 ); emit_matrix_transform_vec4(p, p->eye_position, modelview, pos); emit_op2(p, OPCODE_DP4, p->eye_z, WRITEMASK_Z, pos, modelview2); } return swizzle1(p->eye_z, Z) }
static struct ureg get_eye_position( struct tnl_program *p ) { if (is_undef(p->eye_position)) { struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg modelview[4]; p->eye_position = reserve_temp(p); if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 0, modelview ); emit_matrix_transform_vec4(p, p->eye_position, modelview, pos); } else { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, STATE_MATRIX_TRANSPOSE, modelview ); emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos); } } return p->eye_position; }
int yr_execute_code( YR_RULES* rules, YR_SCAN_CONTEXT* context, int timeout, time_t start_time) { int64_t mem[MEM_SIZE]; int64_t args[MAX_FUNCTION_ARGS]; int32_t sp = 0; uint8_t* ip = rules->code_start; STACK_ITEM *stack; STACK_ITEM r1; STACK_ITEM r2; STACK_ITEM r3; #ifdef PROFILING_ENABLED YR_RULE* current_rule = NULL; #endif YR_RULE* rule; YR_MATCH* match; YR_OBJECT_FUNCTION* function; char* identifier; char* args_fmt; int i; int found; int count; int result = ERROR_SUCCESS; int stop = FALSE; int cycle = 0; int tidx = context->tidx; #ifdef PROFILING_ENABLED clock_t start = clock(); #endif stack = (STACK_ITEM *) yr_malloc(STACK_SIZE * sizeof(STACK_ITEM)); if (stack == NULL) return ERROR_INSUFICIENT_MEMORY; while(!stop) { switch(*ip) { case OP_HALT: assert(sp == 0); // When HALT is reached the stack should be empty. stop = TRUE; break; case OP_PUSH: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); push(r1); break; case OP_POP: pop(r1); break; case OP_CLEAR_M: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1.i] = 0; break; case OP_ADD_M: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); if (!is_undef(r2)) mem[r1.i] += r2.i; break; case OP_INCR_M: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1.i]++; break; case OP_PUSH_M: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); r1.i = mem[r1.i]; push(r1); break; case OP_POP_M: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); mem[r1.i] = r2.i; break; case OP_SWAPUNDEF: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); if (is_undef(r2)) { r1.i = mem[r1.i]; push(r1); } else { push(r2); } break; case OP_JNUNDEF: pop(r1); push(r1); ip = jmp_if(!is_undef(r1), ip); break; case OP_JLE: pop(r2); pop(r1); push(r1); push(r2); ip = jmp_if(r1.i <= r2.i, ip); break; case OP_JTRUE: pop(r1); push(r1); ip = jmp_if(!is_undef(r1) && r1.i, ip); break; case OP_JFALSE: pop(r1); push(r1); ip = jmp_if(is_undef(r1) || !r1.i, ip); break; case OP_AND: pop(r2); pop(r1); if (is_undef(r1) || is_undef(r2)) r1.i = 0; else r1.i = r1.i && r2.i; push(r1); break; case OP_OR: pop(r2); pop(r1); if (is_undef(r1)) { push(r2); } else if (is_undef(r2)) { push(r1); } else { r1.i = r1.i || r2.i; push(r1); } break; case OP_NOT: pop(r1); if (is_undef(r1)) r1.i = UNDEFINED; else r1.i= !r1.i; push(r1); break; case OP_MOD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i != 0) r1.i = r1.i % r2.i; else r1.i = UNDEFINED; push(r1); break; case OP_SHR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i >> r2.i; push(r1); break; case OP_SHL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i << r2.i; push(r1); break; case OP_BITWISE_NOT: pop(r1); ensure_defined(r1); r1.i = ~r1.i; push(r1); break; case OP_BITWISE_AND: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i & r2.i; push(r1); break; case OP_BITWISE_OR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i | r2.i; push(r1); break; case OP_BITWISE_XOR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i ^ r2.i; push(r1); break; case OP_PUSH_RULE: rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); r1.i = rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0; push(r1); break; case OP_INIT_RULE: #ifdef PROFILING_ENABLED current_rule = *(YR_RULE**)(ip + 1); #endif ip += sizeof(uint64_t); break; case OP_MATCH_RULE: pop(r1); rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); if (!is_undef(r1) && r1.i) rule->t_flags[tidx] |= RULE_TFLAGS_MATCH; #ifdef PROFILING_ENABLED rule->clock_ticks += clock() - start; start = clock(); #endif break; case OP_OBJ_LOAD: identifier = *(char**)(ip + 1); ip += sizeof(uint64_t); r1.o = (YR_OBJECT*) yr_hash_table_lookup( context->objects_table, identifier, NULL); assert(r1.o != NULL); push(r1); break; case OP_OBJ_FIELD: identifier = *(char**)(ip + 1); ip += sizeof(uint64_t); pop(r1); ensure_defined(r1); r1.o = yr_object_lookup_field(r1.o, identifier); assert(r1.o != NULL); push(r1); break; case OP_OBJ_VALUE: pop(r1); ensure_defined(r1); switch(r1.o->type) { case OBJECT_TYPE_INTEGER: r1.i = ((YR_OBJECT_INTEGER*) r1.o)->value; break; case OBJECT_TYPE_FLOAT: if (isnan(((YR_OBJECT_DOUBLE*) r1.o)->value)) r1.i = UNDEFINED; else r1.d = ((YR_OBJECT_DOUBLE*) r1.o)->value; break; case OBJECT_TYPE_STRING: if (((YR_OBJECT_STRING*) r1.o)->value == NULL) r1.i = UNDEFINED; else r1.p = ((YR_OBJECT_STRING*) r1.o)->value; break; default: assert(FALSE); } push(r1); break; case OP_INDEX_ARRAY: pop(r1); // index pop(r2); // array ensure_defined(r1); assert(r2.o->type == OBJECT_TYPE_ARRAY); r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i); if (r1.o == NULL) r1.i = UNDEFINED; push(r1); break; case OP_LOOKUP_DICT: pop(r1); // key pop(r2); // dictionary ensure_defined(r1); assert(r2.o->type == OBJECT_TYPE_DICTIONARY); r1.o = yr_object_dict_get_item( r2.o, 0, r1.ss->c_string); if (r1.o == NULL) r1.i = UNDEFINED; push(r1); break; case OP_CALL: args_fmt = *(char**)(ip + 1); ip += sizeof(uint64_t); i = (int) strlen(args_fmt); count = 0; // pop arguments from stack and copy them to args array while (i > 0) { pop(r1); if (is_undef(r1)) // count the number of undefined args count++; args[i - 1] = r1.i; i--; } pop(r2); ensure_defined(r2); if (count > 0) { // if there are undefined args, result for function call // is undefined as well. r1.i = UNDEFINED; push(r1); break; } function = (YR_OBJECT_FUNCTION*) r2.o; result = ERROR_INTERNAL_FATAL_ERROR; for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++) { if (function->prototypes[i].arguments_fmt == NULL) break; if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0) { result = function->prototypes[i].code( (void*) args, context, function); break; } } assert(i < MAX_OVERLOADED_FUNCTIONS); if (result == ERROR_SUCCESS) { r1.o = function->return_obj; push(r1); } else { stop = TRUE; } break; case OP_FOUND: pop(r1); r1.i = r1.s->matches[tidx].tail != NULL ? 1 : 0; push(r1); break; case OP_FOUND_AT: pop(r2); pop(r1); if (is_undef(r1)) { r1.i = 0; push(r1); break; } match = r2.s->matches[tidx].head; r3.i = FALSE; while (match != NULL) { if (r1.i == match->base + match->offset) { r3.i = TRUE; break; } if (r1.i < match->base + match->offset) break; match = match->next; } push(r3); break; case OP_FOUND_IN: pop(r3); pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); match = r3.s->matches[tidx].head; r3.i = FALSE; while (match != NULL && !r3.i) { if (match->base + match->offset >= r1.i && match->base + match->offset <= r2.i) { r3.i = TRUE; } if (match->base + match->offset > r2.i) break; match = match->next; } push(r3); break; case OP_COUNT: pop(r1); r1.i = r1.s->matches[tidx].count; push(r1); break; case OP_OFFSET: pop(r2); pop(r1); ensure_defined(r1); match = r2.s->matches[tidx].head; i = 1; r3.i = UNDEFINED; while (match != NULL && r3.i == UNDEFINED) { if (r1.i == i) r3.i = match->base + match->offset; i++; match = match->next; } push(r3); break; case OP_LENGTH: pop(r2); pop(r1); ensure_defined(r1); match = r2.s->matches[tidx].head; i = 1; r3.i = UNDEFINED; while (match != NULL && r3.i == UNDEFINED) { if (r1.i == i) r3.i = match->length; i++; match = match->next; } push(r3); break; case OP_OF: found = 0; count = 0; pop(r1); while (!is_undef(r1)) { if (r1.s->matches[tidx].tail != NULL) found++; count++; pop(r1); } pop(r2); if (is_undef(r2)) r1.i = found >= count ? 1 : 0; else r1.i = found >= r2.i ? 1 : 0; push(r1); break; case OP_FILESIZE: r1.i = context->file_size; push(r1); break; case OP_ENTRYPOINT: r1.i = context->entry_point; push(r1); break; case OP_INT8: pop(r1); r1.i = read_int8_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_INT16: pop(r1); r1.i = read_int16_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_INT32: pop(r1); r1.i = read_int32_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT8: pop(r1); r1.i = read_uint8_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT16: pop(r1); r1.i = read_uint16_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT32: pop(r1); r1.i = read_uint32_t_little_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_INT8BE: pop(r1); r1.i = read_int8_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_INT16BE: pop(r1); r1.i = read_int16_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_INT32BE: pop(r1); r1.i = read_int32_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT8BE: pop(r1); r1.i = read_uint8_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT16BE: pop(r1); r1.i = read_uint16_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_UINT32BE: pop(r1); r1.i = read_uint32_t_big_endian(context->mem_block, (size_t) r1.i); push(r1); break; case OP_CONTAINS: pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); r1.i = memmem(r1.ss->c_string, r1.ss->length, r2.ss->c_string, r2.ss->length) != NULL; push(r1); break; case OP_IMPORT: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); FAIL_ON_ERROR(yr_modules_load( (char*) r1.p, context)); break; case OP_MATCHES: pop(r2); pop(r1); if (r1.ss->length == 0) { r1.i = FALSE; push(r1); break; } r1.i = yr_re_exec( (uint8_t*) r2.p, (uint8_t*) r1.ss->c_string, r1.ss->length, RE_FLAGS_SCAN, NULL, NULL) >= 0; push(r1); break; case OP_INT_TO_DBL: r1.i = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); r2 = stack[sp - r1.i]; if (is_undef(r2)) stack[sp - r1.i].i = UNDEFINED; else stack[sp - r1.i].d = r2.i; break; case OP_STR_TO_BOOL: pop(r1); ensure_defined(r1); r1.i = r1.ss->length > 0; push(r1); break; case OP_INT_EQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i == r2.i; push(r1); break; case OP_INT_NEQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i != r2.i; push(r1); break; case OP_INT_LT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i < r2.i; push(r1); break; case OP_INT_GT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i > r2.i; push(r1); break; case OP_INT_LE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i <= r2.i; push(r1); break; case OP_INT_GE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i >= r2.i; push(r1); break; case OP_INT_ADD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i + r2.i; push(r1); break; case OP_INT_SUB: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i - r2.i; push(r1); break; case OP_INT_MUL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i * r2.i; push(r1); break; case OP_INT_DIV: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i != 0) r1.i = r1.i / r2.i; else r1.i = UNDEFINED; push(r1); break; case OP_INT_MINUS: pop(r1); ensure_defined(r1); r1.i = -r1.i; push(r1); break; case OP_DBL_LT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d < r2.d; push(r1); break; case OP_DBL_GT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d > r2.d; push(r1); break; case OP_DBL_LE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d <= r2.d; push(r1); break; case OP_DBL_GE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d >= r2.d; push(r1); break; case OP_DBL_EQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d == r2.d; push(r1); break; case OP_DBL_NEQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d != r2.d; push(r1); break; case OP_DBL_ADD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d + r2.d; push(r1); break; case OP_DBL_SUB: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d - r2.d; push(r1); break; case OP_DBL_MUL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d * r2.d; push(r1); break; case OP_DBL_DIV: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d / r2.d; push(r1); break; case OP_DBL_MINUS: pop(r1); ensure_defined(r1); r1.d = -r1.d; push(r1); break; case OP_STR_EQ: case OP_STR_NEQ: case OP_STR_LT: case OP_STR_LE: case OP_STR_GT: case OP_STR_GE: pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); switch(*ip) { case OP_STR_EQ: r1.i = (sized_string_cmp(r1.ss, r2.ss) == 0); break; case OP_STR_NEQ: r1.i = (sized_string_cmp(r1.ss, r2.ss) != 0); break; case OP_STR_LT: r1.i = (sized_string_cmp(r1.ss, r2.ss) < 0); break; case OP_STR_LE: r1.i = (sized_string_cmp(r1.ss, r2.ss) <= 0); break; case OP_STR_GT: r1.i = (sized_string_cmp(r1.ss, r2.ss) > 0); break; case OP_STR_GE: r1.i = (sized_string_cmp(r1.ss, r2.ss) >= 0); break; } push(r1); break; default: // Unknown instruction, this shouldn't happen. assert(FALSE); } if (timeout > 0) // timeout == 0 means no timeout { // Check for timeout every 10 instruction cycles. if (++cycle == 10) { if (difftime(time(NULL), start_time) > timeout) { #ifdef PROFILING_ENABLED assert(current_rule != NULL); current_rule->clock_ticks += clock() - start; #endif result = ERROR_SCAN_TIMEOUT; stop = TRUE; } cycle = 0; } } ip++; } yr_free(stack); return result; }
static void build_texture_transform( struct tnl_program *p ) { GLuint i, j; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i))) continue; if (p->state->unit[i].texgen_enabled || p->state->unit[i].texmat_enabled) { GLuint texmat_enabled = p->state->unit[i].texmat_enabled; struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out_texgen = undef; if (p->state->unit[i].texgen_enabled) { GLuint copy_mask = 0; GLuint sphere_mask = 0; GLuint reflect_mask = 0; GLuint normal_mask = 0; GLuint modes[4]; if (texmat_enabled) out_texgen = get_temp(p); else out_texgen = out; modes[0] = p->state->unit[i].texgen_mode0; modes[1] = p->state->unit[i].texgen_mode1; modes[2] = p->state->unit[i].texgen_mode2; modes[3] = p->state->unit[i].texgen_mode3; for (j = 0; j < 4; j++) { switch (modes[j]) { case TXG_OBJ_LINEAR: { struct ureg obj = register_input(p, VERT_ATTRIB_POS); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane ); break; } case TXG_EYE_LINEAR: { struct ureg eye = get_eye_position(p); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane ); break; } case TXG_SPHERE_MAP: sphere_mask |= WRITEMASK_X << j; break; case TXG_REFLECTION_MAP: reflect_mask |= WRITEMASK_X << j; break; case TXG_NORMAL_MAP: normal_mask |= WRITEMASK_X << j; break; case TXG_NONE: copy_mask |= WRITEMASK_X << j; } } if (sphere_mask) { build_sphere_texgen(p, out_texgen, sphere_mask); } if (reflect_mask) { build_reflect_texgen(p, out_texgen, reflect_mask); } if (normal_mask) { struct ureg normal = get_transformed_normal(p); emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal ); } if (copy_mask) { struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i); emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in ); } } if (texmat_enabled) { struct ureg texmat[4]; struct ureg in = (!is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); } else { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, STATE_MATRIX_TRANSPOSE, texmat ); emit_transpose_matrix_transform_vec4( p, out, texmat, in ); } } release_temps(p); } else { emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); } } }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_transformed_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; /* * NOTE: * dots.x = dot(normal, VPpli) * dots.y = dot(normal, halfAngle) * dots.z = back.shininess * dots.w = front.shininess */ for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { if (!p->state->material_shininess_is_zero) { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); } _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { if (!p->state->material_shininess_is_zero) { /* Note that we negate the back-face specular exponent here. * The negation will be un-done later in the back-face code below. */ struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, negate(swizzle1(shininess,X))); release_temp(p, shininess); } _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); } if (separate) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); } if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } if (twoside && separate) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION_NORMALIZED, i); if (!p->state->material_shininess_is_zero) { if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_INTERNAL, STATE_LIGHT_HALF_VECTOR, i); } } } else { struct ureg Ppli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION, i); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); /* Calculate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (!p->state->material_shininess_is_zero) { half = get_temp(p); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); } release_temp(p, dist); } /* Calculate dot products: */ if (p->state->material_shininess_is_zero) { emit_op2(p, OPCODE_DP3, dots, 0, normal, VPpli); } else { emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); } /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_COL0 ); res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _col0; res1 = register_output( p, VERT_RESULT_COL0 ); } } else { mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; } if (!is_undef(att)) { /* light is attenuated by distance */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); } else if (!p->state->material_shininess_is_zero) { /* there's a non-zero specular term */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } else { /* no attenutation, no specular */ emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_BFC0 ); res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _bfc0; res1 = register_output( p, VERT_RESULT_BFC0 ); } } else { res0 = _bfc0; res1 = _bfc1; mask0 = 0; mask1 = 0; } /* For the back face we need to negate the X and Y component * dot products. dots.Z has the negated back-face specular * exponent. We swizzle that into the W position. This * negation makes the back-face specular term positive again. */ dots = negate(swizzle(dots,X,Y,W,Z)); if (!is_undef(att)) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); } else if (!p->state->material_shininess_is_zero) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/ } else { emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); /* restore dots to its original state for subsequent lights * by negating and swizzling again. */ dots = negate(swizzle(dots,X,Y,W,Z)); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
int yr_execute_code( YR_SCAN_CONTEXT* context) { int64_t mem[MEM_SIZE]; int32_t sp = 0; const uint8_t* ip = context->rules->code_start; YR_VALUE args[YR_MAX_FUNCTION_ARGS]; YR_VALUE *stack; YR_VALUE r1; YR_VALUE r2; YR_VALUE r3; uint64_t elapsed_time; #ifdef PROFILING_ENABLED uint64_t start_time; YR_RULE* current_rule = NULL; #endif YR_INIT_RULE_ARGS init_rule_args; YR_RULE* rule; YR_MATCH* match; YR_OBJECT_FUNCTION* function; YR_OBJECT** obj_ptr; YR_ARENA* obj_arena; char* identifier; char* args_fmt; int i; int found; int count; int result = ERROR_SUCCESS; int cycle = 0; int tidx = context->tidx; int stack_size; bool stop = false; uint8_t opcode; yr_get_configuration(YR_CONFIG_STACK_SIZE, (void*) &stack_size); stack = (YR_VALUE*) yr_malloc(stack_size * sizeof(YR_VALUE)); if (stack == NULL) return ERROR_INSUFFICIENT_MEMORY; FAIL_ON_ERROR_WITH_CLEANUP( yr_arena_create(1024, 0, &obj_arena), yr_free(stack)); #ifdef PROFILING_ENABLED start_time = yr_stopwatch_elapsed_us(&context->stopwatch); #endif #if PARANOID_EXEC memset(mem, 0, MEM_SIZE * sizeof(mem[0])); #endif while(!stop) { opcode = *ip; ip++; switch(opcode) { case OP_NOP: break; case OP_HALT: assert(sp == 0); // When HALT is reached the stack should be empty. stop = true; break; case OP_PUSH: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); push(r1); break; case OP_POP: pop(r1); break; case OP_CLEAR_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif mem[r1.i] = 0; break; case OP_ADD_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif pop(r2); if (!is_undef(r2)) mem[r1.i] += r2.i; break; case OP_INCR_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif mem[r1.i]++; break; case OP_PUSH_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif r1.i = mem[r1.i]; push(r1); break; case OP_POP_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif pop(r2); mem[r1.i] = r2.i; break; case OP_SET_M: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif pop(r2); push(r2); if (!is_undef(r2)) mem[r1.i] = r2.i; break; case OP_SWAPUNDEF: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC ensure_within_mem(r1.i); #endif pop(r2); if (is_undef(r2)) { r1.i = mem[r1.i]; push(r1); } else { push(r2); } break; case OP_JNUNDEF: pop(r1); push(r1); ip = jmp_if(!is_undef(r1), ip); break; case OP_JLE_P: pop(r2); pop(r1); ip = jmp_if(r1.i <= r2.i, ip); break; case OP_JTRUE: pop(r1); push(r1); ip = jmp_if(!is_undef(r1) && r1.i, ip); break; case OP_JFALSE: pop(r1); push(r1); ip = jmp_if(is_undef(r1) || !r1.i, ip); break; case OP_JFALSE_P: pop(r1); ip = jmp_if(is_undef(r1) || !r1.i, ip); break; case OP_AND: pop(r2); pop(r1); if (is_undef(r1) || is_undef(r2)) r1.i = 0; else r1.i = r1.i && r2.i; push(r1); break; case OP_OR: pop(r2); pop(r1); if (is_undef(r1)) { push(r2); } else if (is_undef(r2)) { push(r1); } else { r1.i = r1.i || r2.i; push(r1); } break; case OP_NOT: pop(r1); if (is_undef(r1)) r1.i = UNDEFINED; else r1.i = !r1.i; push(r1); break; case OP_MOD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i != 0) r1.i = r1.i % r2.i; else r1.i = UNDEFINED; push(r1); break; case OP_SHR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i < 0) r1.i = UNDEFINED; else if (r2.i < 64) r1.i = r1.i >> r2.i; else r1.i = 0; push(r1); break; case OP_SHL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i < 0) r1.i = UNDEFINED; else if (r2.i < 64) r1.i = r1.i << r2.i; else r1.i = 0; push(r1); break; case OP_BITWISE_NOT: pop(r1); ensure_defined(r1); r1.i = ~r1.i; push(r1); break; case OP_BITWISE_AND: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i & r2.i; push(r1); break; case OP_BITWISE_OR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i | r2.i; push(r1); break; case OP_BITWISE_XOR: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i ^ r2.i; push(r1); break; case OP_PUSH_RULE: rule = *(YR_RULE**)(ip); ip += sizeof(uint64_t); if (RULE_IS_DISABLED(rule)) r1.i = UNDEFINED; else r1.i = rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0; push(r1); break; case OP_INIT_RULE: memcpy(&init_rule_args, ip, sizeof(init_rule_args)); #ifdef PROFILING_ENABLED current_rule = init_rule_args.rule; #endif if (RULE_IS_DISABLED(init_rule_args.rule)) ip = init_rule_args.jmp_addr; else ip += sizeof(init_rule_args); break; case OP_MATCH_RULE: pop(r1); rule = *(YR_RULE**)(ip); ip += sizeof(uint64_t); if (!is_undef(r1) && r1.i) rule->t_flags[tidx] |= RULE_TFLAGS_MATCH; else if (RULE_IS_GLOBAL(rule)) rule->ns->t_flags[tidx] |= NAMESPACE_TFLAGS_UNSATISFIED_GLOBAL; #ifdef PROFILING_ENABLED elapsed_time = yr_stopwatch_elapsed_us(&context->stopwatch); rule->time_cost_per_thread[tidx] += (elapsed_time - start_time); start_time = elapsed_time; #endif assert(sp == 0); // at this point the stack should be empty. break; case OP_OBJ_LOAD: identifier = *(char**)(ip); ip += sizeof(uint64_t); r1.o = (YR_OBJECT*) yr_hash_table_lookup( context->objects_table, identifier, NULL); assert(r1.o != NULL); push(r1); break; case OP_OBJ_FIELD: identifier = *(char**)(ip); ip += sizeof(uint64_t); pop(r1); ensure_defined(r1); r1.o = yr_object_lookup_field(r1.o, identifier); assert(r1.o != NULL); push(r1); break; case OP_OBJ_VALUE: pop(r1); ensure_defined(r1); #if PARANOID_EXEC check_object_canary(r1.o); #endif switch(r1.o->type) { case OBJECT_TYPE_INTEGER: r1.i = r1.o->value.i; break; case OBJECT_TYPE_FLOAT: if (isnan(r1.o->value.d)) r1.i = UNDEFINED; else r1.d = r1.o->value.d; break; case OBJECT_TYPE_STRING: if (r1.o->value.ss == NULL) r1.i = UNDEFINED; else r1.ss = r1.o->value.ss; break; default: assert(false); } push(r1); break; case OP_INDEX_ARRAY: pop(r1); // index pop(r2); // array ensure_defined(r1); ensure_defined(r2); assert(r2.o->type == OBJECT_TYPE_ARRAY); #if PARANOID_EXEC check_object_canary(r2.o); #endif r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i); if (r1.o == NULL) r1.i = UNDEFINED; push(r1); break; case OP_LOOKUP_DICT: pop(r1); // key pop(r2); // dictionary ensure_defined(r1); ensure_defined(r2); assert(r2.o->type == OBJECT_TYPE_DICTIONARY); #if PARANOID_EXEC check_object_canary(r2.o); #endif r1.o = yr_object_dict_get_item( r2.o, 0, r1.ss->c_string); if (r1.o == NULL) r1.i = UNDEFINED; push(r1); break; case OP_CALL: args_fmt = *(char**)(ip); ip += sizeof(uint64_t); i = (int) strlen(args_fmt); count = 0; #if PARANOID_EXEC if (i > YR_MAX_FUNCTION_ARGS) { stop = true; result = ERROR_INTERNAL_FATAL_ERROR; break; } #endif // pop arguments from stack and copy them to args array while (i > 0) { pop(r1); if (is_undef(r1)) // count the number of undefined args count++; args[i - 1] = r1; i--; } pop(r2); ensure_defined(r2); #if PARANOID_EXEC check_object_canary(r2.o); #endif if (count > 0) { // if there are undefined args, result for function call // is undefined as well. r1.i = UNDEFINED; push(r1); break; } function = object_as_function(r2.o); result = ERROR_INTERNAL_FATAL_ERROR; for (i = 0; i < YR_MAX_OVERLOADED_FUNCTIONS; i++) { if (function->prototypes[i].arguments_fmt == NULL) break; if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0) { result = function->prototypes[i].code(args, context, function); break; } } // if i == YR_MAX_OVERLOADED_FUNCTIONS at this point no matching // prototype was found, but this shouldn't happen. assert(i < YR_MAX_OVERLOADED_FUNCTIONS); // make a copy of the returned object and push the copy into the stack // function->return_obj can't be pushed because it can change in // subsequent calls to the same function. if (result == ERROR_SUCCESS) result = yr_object_copy(function->return_obj, &r1.o); // a pointer to the copied object is stored in a arena in order to // free the object before exiting yr_execute_code if (result == ERROR_SUCCESS) result = yr_arena_write_data(obj_arena, &r1.o, sizeof(r1.o), NULL); stop = (result != ERROR_SUCCESS); push(r1); break; case OP_FOUND: pop(r1); r1.i = r1.s->matches[tidx].tail != NULL ? 1 : 0; push(r1); break; case OP_FOUND_AT: pop(r2); pop(r1); if (is_undef(r1)) { r1.i = 0; push(r1); break; } match = r2.s->matches[tidx].head; r3.i = false; while (match != NULL) { if (r1.i == match->base + match->offset) { r3.i = true; break; } if (r1.i < match->base + match->offset) break; match = match->next; } push(r3); break; case OP_FOUND_IN: pop(r3); pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); match = r3.s->matches[tidx].head; r3.i = false; while (match != NULL && !r3.i) { if (match->base + match->offset >= r1.i && match->base + match->offset <= r2.i) { r3.i = true; } if (match->base + match->offset > r2.i) break; match = match->next; } push(r3); break; case OP_COUNT: pop(r1); #if PARANOID_EXEC // Make sure that the string pointer is within the rules arena. if (yr_arena_page_for_address(context->rules->arena, r1.p) == NULL) return ERROR_INTERNAL_FATAL_ERROR; #endif r1.i = r1.s->matches[tidx].count; push(r1); break; case OP_OFFSET: pop(r2); pop(r1); ensure_defined(r1); match = r2.s->matches[tidx].head; i = 1; r3.i = UNDEFINED; while (match != NULL && r3.i == UNDEFINED) { if (r1.i == i) r3.i = match->base + match->offset; i++; match = match->next; } push(r3); break; case OP_LENGTH: pop(r2); pop(r1); ensure_defined(r1); match = r2.s->matches[tidx].head; i = 1; r3.i = UNDEFINED; while (match != NULL && r3.i == UNDEFINED) { if (r1.i == i) r3.i = match->match_length; i++; match = match->next; } push(r3); break; case OP_OF: found = 0; count = 0; pop(r1); while (!is_undef(r1)) { if (r1.s->matches[tidx].tail != NULL) found++; count++; pop(r1); } pop(r2); if (is_undef(r2)) r1.i = found >= count ? 1 : 0; else r1.i = found >= r2.i ? 1 : 0; push(r1); break; case OP_FILESIZE: r1.i = context->file_size; push(r1); break; case OP_ENTRYPOINT: r1.i = context->entry_point; push(r1); break; case OP_INT8: pop(r1); r1.i = read_int8_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_INT16: pop(r1); r1.i = read_int16_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_INT32: pop(r1); r1.i = read_int32_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT8: pop(r1); r1.i = read_uint8_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT16: pop(r1); r1.i = read_uint16_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT32: pop(r1); r1.i = read_uint32_t_little_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_INT8BE: pop(r1); r1.i = read_int8_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_INT16BE: pop(r1); r1.i = read_int16_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_INT32BE: pop(r1); r1.i = read_int32_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT8BE: pop(r1); r1.i = read_uint8_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT16BE: pop(r1); r1.i = read_uint16_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_UINT32BE: pop(r1); r1.i = read_uint32_t_big_endian(context->iterator, (size_t) r1.i); push(r1); break; case OP_CONTAINS: pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); r1.i = memmem(r1.ss->c_string, r1.ss->length, r2.ss->c_string, r2.ss->length) != NULL; push(r1); break; case OP_IMPORT: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); result = yr_modules_load((char*) r1.p, context); if (result != ERROR_SUCCESS) stop = true; break; case OP_MATCHES: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r1.ss->length == 0) { r1.i = false; push(r1); break; } result = yr_re_exec( context, (uint8_t*) r2.re->code, (uint8_t*) r1.ss->c_string, r1.ss->length, 0, r2.re->flags | RE_FLAGS_SCAN, NULL, NULL, &found); if (result != ERROR_SUCCESS) stop = true; r1.i = found >= 0; push(r1); break; case OP_INT_TO_DBL: r1.i = *(uint64_t*)(ip); ip += sizeof(uint64_t); #if PARANOID_EXEC if (r1.i > sp || sp - r1.i >= stack_size) { stop = true; result = ERROR_INTERNAL_FATAL_ERROR; break; } #endif r2 = stack[sp - r1.i]; if (is_undef(r2)) stack[sp - r1.i].i = UNDEFINED; else stack[sp - r1.i].d = (double) r2.i; break; case OP_STR_TO_BOOL: pop(r1); ensure_defined(r1); r1.i = r1.ss->length > 0; push(r1); break; case OP_INT_EQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i == r2.i; push(r1); break; case OP_INT_NEQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i != r2.i; push(r1); break; case OP_INT_LT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i < r2.i; push(r1); break; case OP_INT_GT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i > r2.i; push(r1); break; case OP_INT_LE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i <= r2.i; push(r1); break; case OP_INT_GE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i >= r2.i; push(r1); break; case OP_INT_ADD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i + r2.i; push(r1); break; case OP_INT_SUB: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i - r2.i; push(r1); break; case OP_INT_MUL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.i * r2.i; push(r1); break; case OP_INT_DIV: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); if (r2.i != 0) r1.i = r1.i / r2.i; else r1.i = UNDEFINED; push(r1); break; case OP_INT_MINUS: pop(r1); ensure_defined(r1); r1.i = -r1.i; push(r1); break; case OP_DBL_LT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d < r2.d; push(r1); break; case OP_DBL_GT: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d > r2.d; push(r1); break; case OP_DBL_LE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d <= r2.d; push(r1); break; case OP_DBL_GE: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = r1.d >= r2.d; push(r1); break; case OP_DBL_EQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = fabs(r1.d - r2.d) < DBL_EPSILON; push(r1); break; case OP_DBL_NEQ: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.i = fabs(r1.d - r2.d) >= DBL_EPSILON; push(r1); break; case OP_DBL_ADD: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d + r2.d; push(r1); break; case OP_DBL_SUB: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d - r2.d; push(r1); break; case OP_DBL_MUL: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d * r2.d; push(r1); break; case OP_DBL_DIV: pop(r2); pop(r1); ensure_defined(r2); ensure_defined(r1); r1.d = r1.d / r2.d; push(r1); break; case OP_DBL_MINUS: pop(r1); ensure_defined(r1); r1.d = -r1.d; push(r1); break; case OP_STR_EQ: case OP_STR_NEQ: case OP_STR_LT: case OP_STR_LE: case OP_STR_GT: case OP_STR_GE: pop(r2); pop(r1); ensure_defined(r1); ensure_defined(r2); switch(opcode) { case OP_STR_EQ: r1.i = (sized_string_cmp(r1.ss, r2.ss) == 0); break; case OP_STR_NEQ: r1.i = (sized_string_cmp(r1.ss, r2.ss) != 0); break; case OP_STR_LT: r1.i = (sized_string_cmp(r1.ss, r2.ss) < 0); break; case OP_STR_LE: r1.i = (sized_string_cmp(r1.ss, r2.ss) <= 0); break; case OP_STR_GT: r1.i = (sized_string_cmp(r1.ss, r2.ss) > 0); break; case OP_STR_GE: r1.i = (sized_string_cmp(r1.ss, r2.ss) >= 0); break; } push(r1); break; default: // Unknown instruction, this shouldn't happen. assert(false); } // Check for timeout every 10 instruction cycles. If timeout == 0 it means // no timeout at all. if (context->timeout > 0L && ++cycle == 10) { elapsed_time = yr_stopwatch_elapsed_us(&context->stopwatch); if (elapsed_time > context->timeout) { #ifdef PROFILING_ENABLED assert(current_rule != NULL); current_rule->time_cost_per_thread[tidx] += elapsed_time - start_time; #endif result = ERROR_SCAN_TIMEOUT; stop = true; } cycle = 0; } }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_eye_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, ureg_negate(swizzle1(shininess,X))); release_temp(p, shininess); _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ /* KW: changed to do this always - v1.17 "Fix lighting alpha result"? */ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } } if (separate && (p->state->fragprog_inputs_read & FRAG_BIT_COL1)) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); if (twoside) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_LIGHT, i, STATE_POSITION_NORMALIZED); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR); } } else { struct ureg Ppli = register_param3(p, STATE_LIGHT, i, STATE_POSITION); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); half = get_temp(p); /* Calulate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); release_temp(p, dist); } /* Calculate dot products: */ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, dots); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_COL0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_COL0 ); } } emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, ureg_negate(swizzle(dots,X,Y,W,Z))); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _bfc0; res1 = _bfc1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_BFC0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_BFC0 ); } } emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
int eval(PSTATE *ps, OpCodes *opcodes, ScopeChain *scope, Value *currentScope, /* scope chain */ Value *_this, Value *vret) { int context_id = ps->_context_id++; OpCode *ip = &opcodes->codes[0]; OpCode *end = &opcodes->codes[opcodes->code_len]; TryList *trylist = NULL; if (currentScope->vt != VT_OBJECT) { bug("Eval: current scope is not a object\n"); } while(ip < end) { #ifdef DEBUG int i; printf("STACK%d: ", sp); for (i = 0; i < sp; ++i) { printf("%s ", vprint(&stack[i])); } printf("\tthis: %s ", vprint(_this)); TryList *tlt = trylist; for (i = 0; tlt; tlt = tlt->next) i++; printf("TL: %d, excpt: %s\n", i, vprint(&ps->last_exception)); code_decode(ip, ip - opcodes->codes); #endif switch(ip->op) { case OP_NOP: case OP_LASTOP: break; case OP_PUSHNUM: value_make_number(stack[sp], (*((double *)ip->data))); sp++; break; case OP_PUSHSTR: value_make_string(stack[sp], unistrdup(ip->data)); sp++; break; case OP_PUSHVAR: { FastVar *n = ip->data; Value *v = NULL; if (n->context_id == context_id) { v = n->var.lval; } else { unichar *varname = n->var.varname; v = value_object_lookup(currentScope, (ObjKey *)varname, NULL); if (!v) v = scope_chain_object_lookup(scope, (ObjKey *)varname); if (!v) { /* add to global scope */ Value *global_scope = scope->chains_cnt > 0 ? scope->chains[0]:currentScope; Value key; value_make_string(key, varname); /* varname is not dupped, do not erase*/ Value val; value_make_undef(val); v = value_object_key_assign(global_scope, &key, &val, OM_DONTEMU); /* key assign dup key and insert into object, so release ourself */ } n->context_id = context_id; n->var.lval = v; } stack[sp].vt = VT_VARIABLE; stack[sp].d.lval = v; sp++; break; } case OP_PUSHUND: value_make_undef(stack[sp]); sp++; break; case OP_PUSHBOO: value_make_bool(stack[sp], (int)ip->data); sp++; break; case OP_PUSHFUN: { FuncObj *fo = funcobj_new((Func *)ip->data); fo->scope = scope_chain_dup_next(scope, currentScope); Object *obj = object_new(); obj->ot = OT_FUNCTION; obj->d.fobj = fo; obj->__proto__ = Function_prototype; Value *fun_prototype = value_object_utils_new_object(); fun_prototype->d.obj->__proto__ = Object_prototype; value_make_object(stack[sp], obj); value_object_utils_insert(&stack[sp], PROTOTYPE.unistr, fun_prototype, 0, 1, 0); /* todo: make own prototype and prototype.constructor */ sp++; break; } case OP_PUSHREG: { Object *obj = object_new(); obj->ot = OT_REGEXP; obj->d.robj = (regex_t *)ip->data; obj->__proto__ = RegExp_prototype; value_make_object(stack[sp], obj); sp++; break; } case OP_PUSHARG: value_copy(stack[sp], *currentScope); sp++; break; case OP_PUSHTHS: value_copy(stack[sp], *_this); sp++; break; case OP_PUSHTOP: value_copy(stack[sp], TOP); sp++; break; case OP_UNREF: topeval1(); break; case OP_PUSHTOP2: value_copy(stack[sp], TOQ); value_copy(stack[sp+1], TOP); sp += 2; break; case OP_CHTHIS: { int t = sp - 2; if (ip->data) { value_erase(obj_this[t]); value_copy(obj_this[t], TOQ); if (obj_this[t].vt == VT_VARIABLE) { Value *v = obj_this[t].d.lval; value_copy(obj_this[t], *v); } value_toobject(&obj_this[t]); } break; } case OP_LOCAL: { ObjKey *strkey = objkey_new((const unichar *)ip->data, OM_DONTEMU); value_object_insert(currentScope, strkey, value_new()); /* make all FastVar to be relocated */ context_id = ps->_context_id++; break; } case OP_POP: pop_n(ip->data); break; case OP_NEG: topeval1(); value_tonumber(&TOP); TOP.d.num = -(TOP.d.num); break; case OP_POS: topeval1(); value_tonumber(&TOP); break; case OP_NOT: { int val = 0; topeval1(); val = value_istrue(&TOP); value_erase(TOP); value_make_bool(TOP, !val); break; } case OP_BNOT: { topeval1(); value_toint32(&TOP); TOP.d.num = (double)(~((int)TOP.d.num)); break; } case OP_ADD: { topeval2(); value_toprimitive(&TOP); value_toprimitive(&TOQ); if (TOP.vt == VT_STRING || TOQ.vt == VT_STRING) { value_tostring(&TOP); value_tostring(&TOQ); unichar *v = unistrcat(TOQ.d.str, TOP.d.str); value_erase(TOQ); value_make_string(TOQ, v); } else { value_tonumber(&TOP); value_tonumber(&TOQ); double n = TOP.d.num + TOQ.d.num; value_erase(TOQ); value_make_number(TOQ, n); } pop(); break; } case OP_SUB: /* god, the notes in ecma is so long, pray to run correctly */ common_math_opr(-); break; case OP_MUL: common_math_opr(*); break; case OP_DIV: common_math_opr(/); break; case OP_MOD: { topeval2(); if (!is_number(&TOP)) value_tonumber(&TOP); if (!is_number(&TOQ)) value_tonumber(&TOQ); TOQ.d.num = fmod(TOQ.d.num, TOP.d.num); pop(); break; } case OP_LESS: topeval2(); logic_less(TOQ, TOP, TOQ); pop(); break; case OP_GREATER: topeval2(); logic_less(TOP, TOQ, TOQ); pop(); break; case OP_LESSEQU: topeval2(); logic_less(TOP, TOQ, TOQ); TOQ.d.val = !TOQ.d.val; pop(); break; case OP_GREATEREQU: topeval2(); logic_less(TOQ, TOP, TOQ); TOQ.d.val = !TOQ.d.val; pop(); break; case OP_EQUAL: case OP_NOTEQUAL: { /* awful, equal opration */ int r = 0; topeval2(); if (TOP.vt != TOQ.vt) { value_toprimitive(&TOP); value_toprimitive(&TOQ); } if (TOP.vt != TOQ.vt) { if ((is_undef(&TOP) || is_null(&TOP)) && (is_undef(&TOQ) || is_null(&TOQ))) { r = 1; } else { value_tonumber(&TOP); value_tonumber(&TOQ); r = (TOP.d.num == TOQ.d.num); } } else { switch (TOP.vt) { case VT_NUMBER: r = (TOP.d.num == TOQ.d.num); break; case VT_BOOL: r = (TOP.d.val == TOQ.d.val); break; case VT_STRING: r = (unistrcmp(TOQ.d.str, TOP.d.str) == 0); break; case VT_OBJECT: /* todo: refer to objects joined to each other */ r = (TOP.d.obj == TOQ.d.obj); break; case VT_UNDEF: case VT_NULL: r = 1; break; default: bug("Unexpected value type\n"); } } r = (ip->op == OP_EQUAL ? r : !r); value_erase(TOQ); value_make_bool(TOQ, r); pop(); break; } case OP_STRICTEQU: case OP_STRICTNEQ: { int r = 0; topeval2(); if (TOP.vt == TOQ.vt) { switch (TOP.vt) { case VT_NUMBER: r = (TOP.d.num == TOQ.d.num); break; case VT_BOOL: r = (TOP.d.val == TOQ.d.val); break; case VT_STRING: r = (unistrcmp(TOQ.d.str, TOP.d.str) == 0); break; case VT_OBJECT: /* todo: refer to objects joined to each other */ r = (TOP.d.obj == TOQ.d.obj); break; case VT_UNDEF: case VT_NULL: r = 1; break; default: bug("Unexpected value type\n"); } } r = (ip->op == OP_STRICTEQU ? r : !r); value_erase(TOQ); value_make_bool(TOQ, r); pop(); break; } case OP_BAND: common_bitwise_opr(&); break; case OP_BOR: common_bitwise_opr(|); break; case OP_BXOR: common_bitwise_opr(^); break; case OP_SHF: { topeval2(); value_toint32(&TOQ); value_toint32(&TOP); int t1 = (int)TOQ.d.num; int t2 = ((unsigned int)TOP.d.num) & 0x1f; if (ip->data) { /* thift right */ if ((int)ip->data == 2) { /* unsigned shift */ unsigned int t3 = (unsigned int)t1; t3 >>= t2; value_make_number(TOQ, t3); } else { t1 >>= t2; value_make_number(TOQ, t1); } } else { t1 <<= t2; value_make_number(TOQ, t1); } pop(); break; }