Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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)
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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);
      }
   }
}
Exemple #11
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_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 );
}
Exemple #12
0
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;
    }
  }
Exemple #13
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 );
}
Exemple #14
0
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;
			}