diff options
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/shader/slang/slang_assemble.c | 2479 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_execute_x86.c | 1114 |
2 files changed, 1822 insertions, 1771 deletions
diff --git a/src/mesa/shader/slang/slang_assemble.c b/src/mesa/shader/slang/slang_assemble.c index 36fb2305f68..603fd4f7f87 100644 --- a/src/mesa/shader/slang/slang_assemble.c +++ b/src/mesa/shader/slang/slang_assemble.c @@ -35,13 +35,15 @@ /* slang_assembly */ -static GLboolean slang_assembly_construct (slang_assembly *assem) +static GLboolean +slang_assembly_construct(slang_assembly * assem) { - assem->type = slang_asm_none; - return GL_TRUE; + assem->type = slang_asm_none; + return GL_TRUE; } -static GLvoid slang_assembly_destruct (slang_assembly *assem) +static GLvoid +slang_assembly_destruct(slang_assembly * assem) { } @@ -50,80 +52,89 @@ static GLvoid slang_assembly_destruct (slang_assembly *assem) */ GLvoid -_slang_assembly_file_ctr (slang_assembly_file *self) +_slang_assembly_file_ctr(slang_assembly_file * self) { self->code = NULL; self->count = 0; self->capacity = 0; } -GLvoid slang_assembly_file_destruct (slang_assembly_file *file) +GLvoid +slang_assembly_file_destruct(slang_assembly_file * file) { - GLuint i; + GLuint i; - for (i = 0; i < file->count; i++) - slang_assembly_destruct (&file->code[i]); - slang_alloc_free (file->code); + for (i = 0; i < file->count; i++) + slang_assembly_destruct(&file->code[i]); + slang_alloc_free(file->code); } -static GLboolean push_new (slang_assembly_file *file) +static GLboolean +push_new(slang_assembly_file * file) { - if (file->count == file->capacity) - { - GLuint n; - - if (file->capacity == 0) - n = 256; - else - n = file->capacity * 2; - file->code = (slang_assembly *) slang_alloc_realloc (file->code, - file->capacity * sizeof (slang_assembly), n * sizeof (slang_assembly)); - if (file->code == NULL) - return GL_FALSE; - file->capacity = n; - } - if (!slang_assembly_construct (&file->code[file->count])) - return GL_FALSE; - file->count++; - return GL_TRUE; + if (file->count == file->capacity) { + GLuint n; + + if (file->capacity == 0) + n = 256; + else + n = file->capacity * 2; + file->code = (slang_assembly *) + slang_alloc_realloc(file->code, + file->capacity * sizeof(slang_assembly), + n * sizeof(slang_assembly)); + if (file->code == NULL) + return GL_FALSE; + file->capacity = n; + } + if (!slang_assembly_construct(&file->code[file->count])) + return GL_FALSE; + file->count++; + return GL_TRUE; } -static GLboolean push_gen (slang_assembly_file *file, slang_assembly_type type, GLfloat literal, - GLuint label, GLuint size) +static GLboolean +push_gen(slang_assembly_file * file, slang_assembly_type type, + GLfloat literal, GLuint label, GLuint size) { - slang_assembly *assem; - - if (!push_new (file)) - return GL_FALSE; - assem = &file->code[file->count - 1]; - assem->type = type; - assem->literal = literal; - assem->param[0] = label; - assem->param[1] = size; - return GL_TRUE; + slang_assembly *assem; + + if (!push_new(file)) + return GL_FALSE; + assem = &file->code[file->count - 1]; + assem->type = type; + assem->literal = literal; + assem->param[0] = label; + assem->param[1] = size; + return GL_TRUE; } -GLboolean slang_assembly_file_push (slang_assembly_file *file, slang_assembly_type type) +GLboolean +slang_assembly_file_push(slang_assembly_file * file, slang_assembly_type type) { - return push_gen (file, type, (GLfloat) 0, 0, 0); + return push_gen(file, type, (GLfloat) 0, 0, 0); } -GLboolean slang_assembly_file_push_label (slang_assembly_file *file, slang_assembly_type type, - GLuint label) +GLboolean +slang_assembly_file_push_label(slang_assembly_file * file, + slang_assembly_type type, GLuint label) { - return push_gen (file, type, (GLfloat) 0, label, 0); + return push_gen(file, type, (GLfloat) 0, label, 0); } -GLboolean slang_assembly_file_push_label2 (slang_assembly_file *file, slang_assembly_type type, - GLuint label1, GLuint label2) +GLboolean +slang_assembly_file_push_label2(slang_assembly_file * file, + slang_assembly_type type, GLuint label1, + GLuint label2) { - return push_gen (file, type, (GLfloat) 0, label1, label2); + return push_gen(file, type, (GLfloat) 0, label1, label2); } -GLboolean slang_assembly_file_push_literal (slang_assembly_file *file, slang_assembly_type type, - GLfloat literal) +GLboolean +slang_assembly_file_push_literal(slang_assembly_file * file, + slang_assembly_type type, GLfloat literal) { - return push_gen (file, type, literal, 0, 0); + return push_gen(file, type, literal, 0, 0); } #define PUSH slang_assembly_file_push @@ -133,284 +144,302 @@ GLboolean slang_assembly_file_push_literal (slang_assembly_file *file, slang_ass /* slang_assembly_file_restore_point */ -GLboolean slang_assembly_file_restore_point_save (slang_assembly_file *file, - slang_assembly_file_restore_point *point) +GLboolean +slang_assembly_file_restore_point_save(slang_assembly_file * file, + slang_assembly_file_restore_point * + point) { - point->count = file->count; - return GL_TRUE; + point->count = file->count; + return GL_TRUE; } -GLboolean slang_assembly_file_restore_point_load (slang_assembly_file *file, - slang_assembly_file_restore_point *point) +GLboolean +slang_assembly_file_restore_point_load(slang_assembly_file * file, + slang_assembly_file_restore_point * + point) { - GLuint i; + GLuint i; - for (i = point->count; i < file->count; i++) - slang_assembly_destruct (&file->code[i]); - file->count = point->count; - return GL_TRUE; + for (i = point->count; i < file->count; i++) + slang_assembly_destruct(&file->code[i]); + file->count = point->count; + return GL_TRUE; } /* utility functions */ -static GLboolean sizeof_variable (slang_assemble_ctx *A, slang_type_specifier *spec, - slang_type_qualifier qual, GLuint array_len, GLuint *size) +static GLboolean +sizeof_variable(slang_assemble_ctx * A, slang_type_specifier * spec, + slang_type_qualifier qual, GLuint array_len, GLuint * size) { - slang_storage_aggregate agg; - - /* calculate the size of the variable's aggregate */ - if (!slang_storage_aggregate_construct (&agg)) - return GL_FALSE; - if (!_slang_aggregate_variable (&agg, spec, array_len, A->space.funcs, A->space.structs, - A->space.vars, A->mach, A->file, A->atoms)) - { - slang_storage_aggregate_destruct (&agg); - return GL_FALSE; - } - *size += _slang_sizeof_aggregate (&agg); - slang_storage_aggregate_destruct (&agg); - - /* for reference variables consider the additional address overhead */ - if (qual == slang_qual_out || qual == slang_qual_inout) - *size += 4; - - return GL_TRUE; + slang_storage_aggregate agg; + + /* calculate the size of the variable's aggregate */ + if (!slang_storage_aggregate_construct(&agg)) + return GL_FALSE; + if (!_slang_aggregate_variable + (&agg, spec, array_len, A->space.funcs, A->space.structs, + A->space.vars, A->mach, A->file, A->atoms)) { + slang_storage_aggregate_destruct(&agg); + return GL_FALSE; + } + *size += _slang_sizeof_aggregate(&agg); + slang_storage_aggregate_destruct(&agg); + + /* for reference variables consider the additional address overhead */ + if (qual == slang_qual_out || qual == slang_qual_inout) + *size += 4; + + return GL_TRUE; } -static GLboolean sizeof_variable2 (slang_assemble_ctx *A, slang_variable *var, GLuint *size) +static GLboolean +sizeof_variable2(slang_assemble_ctx * A, slang_variable * var, GLuint * size) { - var->address = *size; - if (var->type.qualifier == slang_qual_out || var->type.qualifier == slang_qual_inout) - var->address += 4; - return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_len, size); + var->address = *size; + if (var->type.qualifier == slang_qual_out + || var->type.qualifier == slang_qual_inout) + var->address += 4; + return sizeof_variable(A, &var->type.specifier, var->type.qualifier, + var->array_len, size); } -static GLboolean sizeof_variables (slang_assemble_ctx *A, slang_variable_scope *vars, GLuint start, - GLuint stop, GLuint *size) +static GLboolean +sizeof_variables(slang_assemble_ctx * A, slang_variable_scope * vars, + GLuint start, GLuint stop, GLuint * size) { - GLuint i; + GLuint i; - for (i = start; i < stop; i++) - if (!sizeof_variable2 (A, &vars->variables[i], size)) - return GL_FALSE; - return GL_TRUE; + for (i = start; i < stop; i++) + if (!sizeof_variable2(A, &vars->variables[i], size)) + return GL_FALSE; + return GL_TRUE; } -static GLboolean collect_locals (slang_assemble_ctx *A, slang_operation *op, GLuint *size) +static GLboolean +collect_locals(slang_assemble_ctx * A, slang_operation * op, GLuint * size) { - GLuint i; - - if (!sizeof_variables (A, op->locals, 0, op->locals->num_variables, size)) - return GL_FALSE; - for (i = 0; i < op->num_children; i++) - if (!collect_locals (A, &op->children[i], size)) - return GL_FALSE; - return GL_TRUE; + GLuint i; + + if (!sizeof_variables(A, op->locals, 0, op->locals->num_variables, size)) + return GL_FALSE; + for (i = 0; i < op->num_children; i++) + if (!collect_locals(A, &op->children[i], size)) + return GL_FALSE; + return GL_TRUE; } /* _slang_locate_function() */ -slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom a_name, - slang_operation *params, GLuint num_params, slang_assembly_name_space *space, - slang_atom_pool *atoms) +slang_function * +_slang_locate_function(slang_function_scope * funcs, slang_atom a_name, + slang_operation * params, GLuint num_params, + slang_assembly_name_space * space, + slang_atom_pool * atoms) { - GLuint i; - - for (i = 0; i < funcs->num_functions; i++) - { - GLuint j; - slang_function *f = &funcs->functions[i]; - - if (a_name != f->header.a_name) - continue; - if (f->param_count != num_params) - continue; - for (j = 0; j < num_params; j++) - { - slang_assembly_typeinfo ti; - - if (!slang_assembly_typeinfo_construct (&ti)) - return NULL; - if (!_slang_typeof_operation_ (¶ms[j], space, &ti, atoms)) - { - slang_assembly_typeinfo_destruct (&ti); - return NULL; - } - if (!slang_type_specifier_equal (&ti.spec, &f->parameters->variables[j].type.specifier)) - { - slang_assembly_typeinfo_destruct (&ti); - break; - } - slang_assembly_typeinfo_destruct (&ti); - - /* "out" and "inout" formal parameter requires the actual parameter to be l-value */ - if (!ti.can_be_referenced && - (f->parameters->variables[j].type.qualifier == slang_qual_out || - f->parameters->variables[j].type.qualifier == slang_qual_inout)) - break; - } - if (j == num_params) - return f; - } - if (funcs->outer_scope != NULL) - return _slang_locate_function (funcs->outer_scope, a_name, params, num_params, space, atoms); - return NULL; + GLuint i; + + for (i = 0; i < funcs->num_functions; i++) { + GLuint j; + slang_function *f = &funcs->functions[i]; + + if (a_name != f->header.a_name) + continue; + if (f->param_count != num_params) + continue; + for (j = 0; j < num_params; j++) { + slang_assembly_typeinfo ti; + + if (!slang_assembly_typeinfo_construct(&ti)) + return NULL; + if (!_slang_typeof_operation_(¶ms[j], space, &ti, atoms)) { + slang_assembly_typeinfo_destruct(&ti); + return NULL; + } + if (!slang_type_specifier_equal + (&ti.spec, &f->parameters->variables[j].type.specifier)) { + slang_assembly_typeinfo_destruct(&ti); + break; + } + slang_assembly_typeinfo_destruct(&ti); + + /* "out" and "inout" formal parameter requires the actual parameter to be l-value */ + if (!ti.can_be_referenced && + (f->parameters->variables[j].type.qualifier == slang_qual_out || + f->parameters->variables[j].type.qualifier == slang_qual_inout)) + break; + } + if (j == num_params) + return f; + } + if (funcs->outer_scope != NULL) + return _slang_locate_function(funcs->outer_scope, a_name, params, + num_params, space, atoms); + return NULL; } /* _slang_assemble_function() */ -GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun) +GLboolean +_slang_assemble_function(slang_assemble_ctx * A, slang_function * fun) { - GLuint param_size, local_size; - GLuint skip, cleanup; - - fun->address = A->file->count; - - if (fun->body == NULL) - { - /* jump to the actual function body - we do not know it, so add the instruction - * to fixup table */ - fun->fixups.table = (GLuint *) slang_alloc_realloc (fun->fixups.table, - fun->fixups.count * sizeof (GLuint), (fun->fixups.count + 1) * sizeof (GLuint)); - if (fun->fixups.table == NULL) - return GL_FALSE; - fun->fixups.table[fun->fixups.count] = fun->address; - fun->fixups.count++; - if (!PUSH (A->file, slang_asm_jump)) - return GL_FALSE; - return GL_TRUE; - } - else - { - GLuint i; - - /* resolve all fixup table entries and delete it */ - for (i = 0; i < fun->fixups.count; i++) - A->file->code[fun->fixups.table[i]].param[0] = fun->address; - slang_fixup_table_free (&fun->fixups); - } - - /* At this point traverse function formal parameters and code to calculate - * total memory size to be allocated on the stack. - * During this process the variables will be assigned local addresses to - * reference them in the code. - * No storage optimizations are performed so exclusive scopes are not detected and shared. */ - - /* calculate return value size */ - param_size = 0; - if (fun->header.type.specifier.type != slang_spec_void) - if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, ¶m_size)) - return GL_FALSE; - A->local.ret_size = param_size; - - /* calculate formal parameter list size */ - if (!sizeof_variables (A, fun->parameters, 0, fun->param_count, ¶m_size)) - return GL_FALSE; - - /* calculate local variables size - take into account the four-byte return address and - * temporaries for various tasks (4 for addr and 16 for swizzle temporaries). - * these include variables from the formal parameter scope and from the code */ - A->local.addr_tmp = param_size + 4; - A->local.swizzle_tmp = param_size + 4 + 4; - local_size = param_size + 4 + 4 + 16; - if (!sizeof_variables (A, fun->parameters, fun->param_count, fun->parameters->num_variables, - &local_size)) - return GL_FALSE; - if (!collect_locals (A, fun->body, &local_size)) - return GL_FALSE; - - /* allocate local variable storage */ - if (!PLAB (A->file, slang_asm_local_alloc, local_size - param_size - 4)) - return GL_FALSE; - - /* mark a new frame for function variable storage */ - if (!PLAB (A->file, slang_asm_enter, local_size)) - return GL_FALSE; - - /* jump directly to the actual code */ - skip = A->file->count; - if (!push_new (A->file)) - return GL_FALSE; - A->file->code[skip].type = slang_asm_jump; - - /* all "return" statements will be directed here */ - A->flow.function_end = A->file->count; - cleanup = A->file->count; - if (!push_new (A->file)) - return GL_FALSE; - A->file->code[cleanup].type = slang_asm_jump; - - /* execute the function body */ - A->file->code[skip].param[0] = A->file->count; - if (!_slang_assemble_operation (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid)) - return GL_FALSE; - - /* this is the end of the function - restore the old function frame */ - A->file->code[cleanup].param[0] = A->file->count; - if (!PUSH (A->file, slang_asm_leave)) - return GL_FALSE; - - /* free local variable storage */ - if (!PLAB (A->file, slang_asm_local_free, local_size - param_size - 4)) - return GL_FALSE; - - /* return from the function */ - if (!PUSH (A->file, slang_asm_return)) - return GL_FALSE; - - return GL_TRUE; + GLuint param_size, local_size; + GLuint skip, cleanup; + + fun->address = A->file->count; + + if (fun->body == NULL) { + /* jump to the actual function body - we do not know it, so add the instruction + * to fixup table */ + fun->fixups.table = (GLuint *) + slang_alloc_realloc(fun->fixups.table, + fun->fixups.count * sizeof(GLuint), + (fun->fixups.count + 1) * sizeof(GLuint)); + if (fun->fixups.table == NULL) + return GL_FALSE; + fun->fixups.table[fun->fixups.count] = fun->address; + fun->fixups.count++; + if (!PUSH(A->file, slang_asm_jump)) + return GL_FALSE; + return GL_TRUE; + } + else { + GLuint i; + + /* resolve all fixup table entries and delete it */ + for (i = 0; i < fun->fixups.count; i++) + A->file->code[fun->fixups.table[i]].param[0] = fun->address; + slang_fixup_table_free(&fun->fixups); + } + + /* At this point traverse function formal parameters and code to calculate + * total memory size to be allocated on the stack. + * During this process the variables will be assigned local addresses to + * reference them in the code. + * No storage optimizations are performed so exclusive scopes are not + * detected and shared. + */ + + /* calculate return value size */ + param_size = 0; + if (fun->header.type.specifier.type != slang_spec_void) + if (!sizeof_variable + (A, &fun->header.type.specifier, slang_qual_none, 0, ¶m_size)) + return GL_FALSE; + A->local.ret_size = param_size; + + /* calculate formal parameter list size */ + if (!sizeof_variables + (A, fun->parameters, 0, fun->param_count, ¶m_size)) + return GL_FALSE; + + /* calculate local variables size - take into account the four-byte + * return address and temporaries for various tasks (4 for addr and + * 16 for swizzle temporaries). these include variables from the + * formal parameter scope and from the code + */ + A->local.addr_tmp = param_size + 4; + A->local.swizzle_tmp = param_size + 4 + 4; + local_size = param_size + 4 + 4 + 16; + if (!sizeof_variables + (A, fun->parameters, fun->param_count, fun->parameters->num_variables, + &local_size)) + return GL_FALSE; + if (!collect_locals(A, fun->body, &local_size)) + return GL_FALSE; + + /* allocate local variable storage */ + if (!PLAB(A->file, slang_asm_local_alloc, local_size - param_size - 4)) + return GL_FALSE; + + /* mark a new frame for function variable storage */ + if (!PLAB(A->file, slang_asm_enter, local_size)) + return GL_FALSE; + + /* jump directly to the actual code */ + skip = A->file->count; + if (!push_new(A->file)) + return GL_FALSE; + A->file->code[skip].type = slang_asm_jump; + + /* all "return" statements will be directed here */ + A->flow.function_end = A->file->count; + cleanup = A->file->count; + if (!push_new(A->file)) + return GL_FALSE; + A->file->code[cleanup].type = slang_asm_jump; + + /* execute the function body */ + A->file->code[skip].param[0] = A->file->count; + if (!_slang_assemble_operation + (A, fun->body, /*slang_ref_freelance */ slang_ref_forbid)) + return GL_FALSE; + + /* this is the end of the function - restore the old function frame */ + A->file->code[cleanup].param[0] = A->file->count; + if (!PUSH(A->file, slang_asm_leave)) + return GL_FALSE; + + /* free local variable storage */ + if (!PLAB(A->file, slang_asm_local_free, local_size - param_size - 4)) + return GL_FALSE; + + /* return from the function */ + if (!PUSH(A->file, slang_asm_return)) + return GL_FALSE; + + return GL_TRUE; } -GLboolean _slang_cleanup_stack (slang_assemble_ctx *A, slang_operation *op) +GLboolean +_slang_cleanup_stack(slang_assemble_ctx * A, slang_operation * op) { - slang_assembly_typeinfo ti; - GLuint size = 0; - - /* get type info of the operation and calculate its size */ - if (!slang_assembly_typeinfo_construct (&ti)) - return GL_FALSE; - if (!_slang_typeof_operation (A, op, &ti)) - { - slang_assembly_typeinfo_destruct (&ti); - return GL_FALSE; - } - if (ti.spec.type != slang_spec_void) { - if (A->ref == slang_ref_force) { - size = 4; - } - else if (!sizeof_variable (A, &ti.spec, slang_qual_none, 0, &size)) - { - slang_assembly_typeinfo_destruct (&ti); - return GL_FALSE; - } - } - slang_assembly_typeinfo_destruct (&ti); - - /* if nonzero, free it from the stack */ - if (size != 0) - { - if (!PLAB (A->file, slang_asm_local_free, size)) - return GL_FALSE; - } - - return GL_TRUE; + slang_assembly_typeinfo ti; + GLuint size = 0; + + /* get type info of the operation and calculate its size */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) { + slang_assembly_typeinfo_destruct(&ti); + return GL_FALSE; + } + if (ti.spec.type != slang_spec_void) { + if (A->ref == slang_ref_force) { + size = 4; + } + else if (!sizeof_variable(A, &ti.spec, slang_qual_none, 0, &size)) { + slang_assembly_typeinfo_destruct(&ti); + return GL_FALSE; + } + } + slang_assembly_typeinfo_destruct(&ti); + + /* if nonzero, free it from the stack */ + if (size != 0) { + if (!PLAB(A->file, slang_asm_local_free, size)) + return GL_FALSE; + } + + return GL_TRUE; } /* _slang_assemble_operation() */ static GLboolean -dereference_basic (slang_assemble_ctx *A, slang_storage_type type, GLuint *size, slang_swizzle *swz, - GLboolean is_swizzled) +dereference_basic(slang_assemble_ctx * A, slang_storage_type type, + GLuint * size, slang_swizzle * swz, GLboolean is_swizzled) { GLuint src_offset; slang_assembly_type ty; - *size -= _slang_sizeof_type (type); + *size -= _slang_sizeof_type(type); - /* If swizzling is taking place, we are forced to use scalar operations, even if we have - * vec4 instructions enabled (this should be actually done with special vec4 shuffle - * instructions). - * Adjust the size and calculate the offset within source variable to read. + /* If swizzling is taking place, we are forced to use scalar + * operations, even if we have vec4 instructions enabled (this + * should be actually done with special vec4 shuffle instructions). + * Adjust the size and calculate the offset within source variable + * to read. */ if (is_swizzled) src_offset = swz->swizzle[*size / 4] * 4; @@ -418,14 +447,14 @@ dereference_basic (slang_assemble_ctx *A, slang_storage_type type, GLuint *size, src_offset = *size; /* dereference data slot of a basic type */ - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_deref)) + if (!PUSH(A->file, slang_asm_addr_deref)) return GL_FALSE; if (src_offset != 0) { - if (!PLAB (A->file, slang_asm_addr_push, src_offset)) + if (!PLAB(A->file, slang_asm_addr_push, src_offset)) return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_add)) + if (!PUSH(A->file, slang_asm_addr_add)) return GL_FALSE; } @@ -449,12 +478,13 @@ dereference_basic (slang_assemble_ctx *A, slang_storage_type type, GLuint *size, ty = slang_asm_none; } - return PUSH (A->file, ty); + return PUSH(A->file, ty); } static GLboolean -dereference_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg, GLuint *size, - slang_swizzle *swz, GLboolean is_swizzled) +dereference_aggregate(slang_assemble_ctx * A, + const slang_storage_aggregate * agg, GLuint * size, + slang_swizzle * swz, GLboolean is_swizzled) { GLuint i; @@ -464,22 +494,27 @@ dereference_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg for (j = arr->length; j > 0; j--) { if (arr->type == slang_stor_aggregate) { - if (!dereference_aggregate (A, arr->aggregate, size, swz, is_swizzled)) + if (!dereference_aggregate + (A, arr->aggregate, size, swz, is_swizzled)) return GL_FALSE; } else { if (is_swizzled && arr->type == slang_stor_vec4) { - if (!dereference_basic (A, slang_stor_float, size, swz, is_swizzled)) + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) return GL_FALSE; - if (!dereference_basic (A, slang_stor_float, size, swz, is_swizzled)) + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) return GL_FALSE; - if (!dereference_basic (A, slang_stor_float, size, swz, is_swizzled)) + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) return GL_FALSE; - if (!dereference_basic (A, slang_stor_float, size, swz, is_swizzled)) + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) return GL_FALSE; } else { - if (!dereference_basic (A, arr->type, size, swz, is_swizzled)) + if (!dereference_basic(A, arr->type, size, swz, is_swizzled)) return GL_FALSE; } } @@ -489,235 +524,240 @@ dereference_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg return GL_TRUE; } -GLboolean _slang_dereference (slang_assemble_ctx *A, slang_operation *op) +GLboolean +_slang_dereference(slang_assemble_ctx * A, slang_operation * op) { - slang_assembly_typeinfo ti; - GLboolean result = GL_FALSE; - slang_storage_aggregate agg; - GLuint size; - - /* get type information of the given operation */ - if (!slang_assembly_typeinfo_construct (&ti)) - return GL_FALSE; - if (!_slang_typeof_operation (A, op, &ti)) - goto end1; - - /* construct aggregate from the type info */ - if (!slang_storage_aggregate_construct (&agg)) - goto end1; - if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs, - A->space.vars, A->mach, A->file, A->atoms)) - goto end; - - /* dereference the resulting aggregate */ - size = _slang_sizeof_aggregate (&agg); - result = dereference_aggregate (A, &agg, &size, &ti.swz, ti.is_swizzled); - -end: - slang_storage_aggregate_destruct (&agg); -end1: - slang_assembly_typeinfo_destruct (&ti); - return result; + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + GLuint size; + + /* get type information of the given operation */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + /* construct aggregate from the type info */ + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable + (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs, + A->space.vars, A->mach, A->file, A->atoms)) + goto end; + + /* dereference the resulting aggregate */ + size = _slang_sizeof_aggregate(&agg); + result = dereference_aggregate(A, &agg, &size, &ti.swz, ti.is_swizzled); + + end: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; } -GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *fun, - slang_operation *params, GLuint param_count, GLboolean assignment) +GLboolean +_slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun, + slang_operation * params, GLuint param_count, + GLboolean assignment) { - GLuint i; - slang_swizzle p_swz[64]; - slang_ref_type p_ref[64]; - - /* TODO: fix this, allocate dynamically */ - if (param_count > 64) - return GL_FALSE; - - /* make room for the return value, if any */ - if (fun->header.type.specifier.type != slang_spec_void) - { - GLuint ret_size = 0; - - if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_local_alloc, ret_size)) - return GL_FALSE; - } - - /* push the actual parameters on the stack */ - for (i = 0; i < param_count; i++) - { - if (fun->parameters->variables[i].type.qualifier == slang_qual_inout || - fun->parameters->variables[i].type.qualifier == slang_qual_out) - { - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - /* TODO: optimize the "out" parameter case */ - if (!_slang_assemble_operation (A, ¶ms[i], slang_ref_force)) - return GL_FALSE; - p_swz[i] = A->swz; - p_ref[i] = A->ref; - if (!PUSH (A->file, slang_asm_addr_copy)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_deref)) - return GL_FALSE; - if (i == 0 && assignment) - { - /* duplicate the resulting address */ - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_deref)) - return GL_FALSE; - } - if (!_slang_dereference (A, ¶ms[i])) - return GL_FALSE; - } - else - { - if (!_slang_assemble_operation (A, ¶ms[i], slang_ref_forbid)) - return GL_FALSE; - p_swz[i] = A->swz; - p_ref[i] = A->ref; - } - } - - /* call the function */ - if (!PLAB (A->file, slang_asm_call, fun->address)) - return GL_FALSE; - - /* pop the parameters from the stack */ - for (i = param_count; i > 0; i--) - { - GLuint j = i - 1; - - A->swz = p_swz[j]; - A->ref = p_ref[j]; - if (fun->parameters->variables[j].type.qualifier == slang_qual_inout || - fun->parameters->variables[j].type.qualifier == slang_qual_out) - { - /* for output parameter copy the contents of the formal parameter - * back to the original actual parameter */ - if (!_slang_assemble_assignment (A, ¶ms[j])) - return GL_FALSE; - /* pop the actual parameter's address */ - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; - } - else - { - /* pop the value of the parameter */ - if (!_slang_cleanup_stack (A, ¶ms[j])) - return GL_FALSE; - } - } - - return GL_TRUE; + GLuint i; + slang_swizzle p_swz[64]; + slang_ref_type p_ref[64]; + + /* TODO: fix this, allocate dynamically */ + if (param_count > 64) + return GL_FALSE; + + /* make room for the return value, if any */ + if (fun->header.type.specifier.type != slang_spec_void) { + GLuint ret_size = 0; + + if (!sizeof_variable + (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_alloc, ret_size)) + return GL_FALSE; + } + + /* push the actual parameters on the stack */ + for (i = 0; i < param_count; i++) { + if (fun->parameters->variables[i].type.qualifier == slang_qual_inout || + fun->parameters->variables[i].type.qualifier == slang_qual_out) { + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + /* TODO: optimize the "out" parameter case */ + if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_force)) + return GL_FALSE; + p_swz[i] = A->swz; + p_ref[i] = A->ref; + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + if (i == 0 && assignment) { + /* duplicate the resulting address */ + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + } + if (!_slang_dereference(A, ¶ms[i])) + return GL_FALSE; + } + else { + if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_forbid)) + return GL_FALSE; + p_swz[i] = A->swz; + p_ref[i] = A->ref; + } + } + + /* call the function */ + if (!PLAB(A->file, slang_asm_call, fun->address)) + return GL_FALSE; + + /* pop the parameters from the stack */ + for (i = param_count; i > 0; i--) { + GLuint j = i - 1; + + A->swz = p_swz[j]; + A->ref = p_ref[j]; + if (fun->parameters->variables[j].type.qualifier == slang_qual_inout || + fun->parameters->variables[j].type.qualifier == slang_qual_out) { + /* for output parameter copy the contents of the formal parameter + * back to the original actual parameter + */ + if (!_slang_assemble_assignment(A, ¶ms[j])) + return GL_FALSE; + /* pop the actual parameter's address */ + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + else { + /* pop the value of the parameter */ + if (!_slang_cleanup_stack(A, ¶ms[j])) + return GL_FALSE; + } + } + + return GL_TRUE; } -GLboolean _slang_assemble_function_call_name (slang_assemble_ctx *A, const char *name, - slang_operation *params, GLuint param_count, GLboolean assignment) +GLboolean +_slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name, + slang_operation * params, + GLuint param_count, GLboolean assignment) { - slang_atom atom; - slang_function *fun; - - atom = slang_atom_pool_atom (A->atoms, name); - if (atom == SLANG_ATOM_NULL) - return GL_FALSE; - fun = _slang_locate_function (A->space.funcs, atom, params, param_count, &A->space, A->atoms); - if (fun == NULL) - return GL_FALSE; - return _slang_assemble_function_call (A, fun, params, param_count, assignment); + slang_atom atom; + slang_function *fun; + + atom = slang_atom_pool_atom(A->atoms, name); + if (atom == SLANG_ATOM_NULL) + return GL_FALSE; + fun = + _slang_locate_function(A->space.funcs, atom, params, param_count, + &A->space, A->atoms); + if (fun == NULL) + return GL_FALSE; + return _slang_assemble_function_call(A, fun, params, param_count, + assignment); } -static GLboolean assemble_function_call_name_dummyint (slang_assemble_ctx *A, const char *name, - slang_operation *params) +static GLboolean +assemble_function_call_name_dummyint(slang_assemble_ctx * A, const char *name, + slang_operation * params) { - slang_operation p[2]; - GLboolean result; - - p[0] = params[0]; - if (!slang_operation_construct (&p[1])) - return GL_FALSE; - p[1].type = slang_oper_literal_int; - result = _slang_assemble_function_call_name (A, name, p, 2, GL_FALSE); - slang_operation_destruct (&p[1]); - return result; + slang_operation p[2]; + GLboolean result; + + p[0] = params[0]; + if (!slang_operation_construct(&p[1])) + return GL_FALSE; + p[1].type = slang_oper_literal_int; + result = _slang_assemble_function_call_name(A, name, p, 2, GL_FALSE); + slang_operation_destruct(&p[1]); + return result; } static const struct { - const char *name; - slang_assembly_type code1, code2; + const char *name; + slang_assembly_type code1, code2; } inst[] = { - /* core */ - { "float_add", slang_asm_float_add, slang_asm_float_copy }, - { "float_multiply", slang_asm_float_multiply, slang_asm_float_copy }, - { "float_divide", slang_asm_float_divide, slang_asm_float_copy }, - { "float_negate", slang_asm_float_negate, slang_asm_float_copy }, - { "float_less", slang_asm_float_less, slang_asm_bool_copy }, - { "float_equal", slang_asm_float_equal_exp,slang_asm_bool_copy }, - { "float_to_int", slang_asm_float_to_int, slang_asm_int_copy }, - { "float_sine", slang_asm_float_sine, slang_asm_float_copy }, - { "float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy }, - { "float_arctan", slang_asm_float_arctan, slang_asm_float_copy }, - { "float_power", slang_asm_float_power, slang_asm_float_copy }, - { "float_log2", slang_asm_float_log2, slang_asm_float_copy }, - { "float_floor", slang_asm_float_floor, slang_asm_float_copy }, - { "float_ceil", slang_asm_float_ceil, slang_asm_float_copy }, - { "float_noise1", slang_asm_float_noise1, slang_asm_float_copy }, - { "float_noise2", slang_asm_float_noise2, slang_asm_float_copy }, - { "float_noise3", slang_asm_float_noise3, slang_asm_float_copy }, - { "float_noise4", slang_asm_float_noise4, slang_asm_float_copy }, - { "int_to_float", slang_asm_int_to_float, slang_asm_float_copy }, - { "vec4_tex1d", slang_asm_vec4_tex1d, slang_asm_none }, - { "vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none }, - { "vec4_tex3d", slang_asm_vec4_tex3d, slang_asm_none }, - { "vec4_texcube", slang_asm_vec4_texcube, slang_asm_none }, - { "vec4_shad1d", slang_asm_vec4_shad1d, slang_asm_none }, - { "vec4_shad2d", slang_asm_vec4_shad2d, slang_asm_none }, - /* GL_MESA_shader_debug */ - { "float_print", slang_asm_float_deref, slang_asm_float_print }, - { "int_print", slang_asm_int_deref, slang_asm_int_print }, - { "bool_print", slang_asm_bool_deref, slang_asm_bool_print }, + /* core */ + {"float_add", slang_asm_float_add, slang_asm_float_copy}, + {"float_multiply", slang_asm_float_multiply, slang_asm_float_copy}, + {"float_divide", slang_asm_float_divide, slang_asm_float_copy}, + {"float_negate", slang_asm_float_negate, slang_asm_float_copy}, + {"float_less", slang_asm_float_less, slang_asm_bool_copy}, + {"float_equal", slang_asm_float_equal_exp, slang_asm_bool_copy}, + {"float_to_int", slang_asm_float_to_int, slang_asm_int_copy}, + {"float_sine", slang_asm_float_sine, slang_asm_float_copy}, + {"float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy}, + {"float_arctan", slang_asm_float_arctan, slang_asm_float_copy}, + {"float_power", slang_asm_float_power, slang_asm_float_copy}, + {"float_log2", slang_asm_float_log2, slang_asm_float_copy}, + {"float_floor", slang_asm_float_floor, slang_asm_float_copy}, + {"float_ceil", slang_asm_float_ceil, slang_asm_float_copy}, + {"float_noise1", slang_asm_float_noise1, slang_asm_float_copy}, + {"float_noise2", slang_asm_float_noise2, slang_asm_float_copy}, + {"float_noise3", slang_asm_float_noise3, slang_asm_float_copy}, + {"float_noise4", slang_asm_float_noise4, slang_asm_float_copy}, + {"int_to_float", slang_asm_int_to_float, slang_asm_float_copy}, + {"vec4_tex1d", slang_asm_vec4_tex1d, slang_asm_none}, + {"vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none}, + {"vec4_tex3d", slang_asm_vec4_tex3d, slang_asm_none}, + {"vec4_texcube", slang_asm_vec4_texcube, slang_asm_none}, + {"vec4_shad1d", slang_asm_vec4_shad1d, slang_asm_none}, + {"vec4_shad2d", slang_asm_vec4_shad2d, slang_asm_none}, + /* GL_MESA_shader_debug */ + {"float_print", slang_asm_float_deref, slang_asm_float_print}, + {"int_print", slang_asm_int_deref, slang_asm_int_print}, + {"bool_print", slang_asm_bool_deref, slang_asm_bool_print}, /* vec4 */ - { "float_to_vec4", slang_asm_float_to_vec4, slang_asm_none }, - { "vec4_add", slang_asm_vec4_add, slang_asm_none }, - { "vec4_subtract", slang_asm_vec4_subtract, slang_asm_none }, - { "vec4_multiply", slang_asm_vec4_multiply, slang_asm_none }, - { "vec4_divide", slang_asm_vec4_divide, slang_asm_none }, - { "vec4_negate", slang_asm_vec4_negate, slang_asm_none }, - { "vec4_dot", slang_asm_vec4_dot, slang_asm_none }, - - { NULL, slang_asm_none, slang_asm_none } + {"float_to_vec4", slang_asm_float_to_vec4, slang_asm_none}, + {"vec4_add", slang_asm_vec4_add, slang_asm_none}, + {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_none}, + {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_none}, + {"vec4_divide", slang_asm_vec4_divide, slang_asm_none}, + {"vec4_negate", slang_asm_vec4_negate, slang_asm_none}, + {"vec4_dot", slang_asm_vec4_dot, slang_asm_none}, + {NULL, slang_asm_none, slang_asm_none} }; -static GLboolean call_asm_instruction (slang_assemble_ctx *A, slang_atom a_name) +static GLboolean +call_asm_instruction(slang_assemble_ctx * A, slang_atom a_name) { - const char *id; - GLuint i; + const char *id; + GLuint i; - id = slang_atom_pool_id (A->atoms, a_name); + id = slang_atom_pool_id(A->atoms, a_name); - for (i = 0; inst[i].name != NULL; i++) - if (slang_string_compare (id, inst[i].name) == 0) - break; - if (inst[i].name == NULL) - return GL_FALSE; + for (i = 0; inst[i].name != NULL; i++) + if (slang_string_compare(id, inst[i].name) == 0) + break; + if (inst[i].name == NULL) + return GL_FALSE; - if (!PLAB2 (A->file, inst[i].code1, 4, 0)) - return GL_FALSE; - if (inst[i].code2 != slang_asm_none) - if (!PLAB2 (A->file, inst[i].code2, 4, 0)) - return GL_FALSE; + if (!PLAB2(A->file, inst[i].code1, 4, 0)) + return GL_FALSE; + if (inst[i].code2 != slang_asm_none) + if (!PLAB2(A->file, inst[i].code2, 4, 0)) + return GL_FALSE; - /* clean-up the stack from the remaining dst address */ - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; + /* clean-up the stack from the remaining dst address */ + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; - return GL_TRUE; + return GL_TRUE; } static GLboolean -equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg, GLuint *index, - GLuint size, GLuint z_label) +equality_aggregate(slang_assemble_ctx * A, + const slang_storage_aggregate * agg, GLuint * index, + GLuint size, GLuint z_label) { GLuint i; @@ -727,22 +767,25 @@ equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg, G for (j = 0; j < arr->length; j++) { if (arr->type == slang_stor_aggregate) { - if (!equality_aggregate (A, arr->aggregate, index, size, z_label)) + if (!equality_aggregate(A, arr->aggregate, index, size, z_label)) return GL_FALSE; } else { #if defined(USE_X86_ASM) || defined(SLANG_X86) if (arr->type == slang_stor_vec4) { - if (!PLAB2 (A->file, slang_asm_vec4_equal_int, size + *index, *index)) + if (!PLAB2 + (A->file, slang_asm_vec4_equal_int, size + *index, *index)) return GL_FALSE; } else #endif - if (!PLAB2 (A->file, slang_asm_float_equal_int, size + *index, *index)) - return GL_FALSE; + if (!PLAB2 + (A->file, slang_asm_float_equal_int, size + *index, + *index)) + return GL_FALSE; - *index += _slang_sizeof_type (arr->type); - if (!PLAB (A->file, slang_asm_jump_if_zero, z_label)) + *index += _slang_sizeof_type(arr->type); + if (!PLAB(A->file, slang_asm_jump_if_zero, z_label)) return GL_FALSE; } } @@ -751,753 +794,755 @@ equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg, G return GL_TRUE; } -static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean equal) +static GLboolean +equality(slang_assemble_ctx * A, slang_operation * op, GLboolean equal) { - slang_assembly_typeinfo ti; - GLboolean result = GL_FALSE; - slang_storage_aggregate agg; - GLuint index, size; - GLuint skip_jump, true_label, true_jump, false_label, false_jump; - - /* get type of operation */ - if (!slang_assembly_typeinfo_construct (&ti)) - return GL_FALSE; - if (!_slang_typeof_operation (A, op, &ti)) - goto end1; - - /* convert it to an aggregate */ - if (!slang_storage_aggregate_construct (&agg)) - goto end1; - if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs, - A->space.vars, A->mach, A->file, A->atoms)) - goto end; - - /* compute the size of the agregate - there are two such aggregates on the stack */ - size = _slang_sizeof_aggregate (&agg); - - /* jump to the actual data-comparison code */ - skip_jump = A->file->count; - if (!PUSH (A->file, slang_asm_jump)) - goto end; - - /* pop off the stack the compared data and push 1 */ - true_label = A->file->count; - if (!PLAB (A->file, slang_asm_local_free, size * 2)) - goto end; - if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 1)) - goto end; - true_jump = A->file->count; - if (!PUSH (A->file, slang_asm_jump)) - goto end; - - false_label = A->file->count; - if (!PLAB (A->file, slang_asm_local_free, size * 2)) - goto end; - if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 0)) - goto end; - false_jump = A->file->count; - if (!PUSH (A->file, slang_asm_jump)) - goto end; - - A->file->code[skip_jump].param[0] = A->file->count; - - /* compare the data on stack, it will eventually jump either to true or false label */ - index = 0; - if (!equality_aggregate (A, &agg, &index, size, equal ? false_label : true_label)) - goto end; - if (!PLAB (A->file, slang_asm_jump, equal ? true_label : false_label)) - goto end; - - A->file->code[true_jump].param[0] = A->file->count; - A->file->code[false_jump].param[0] = A->file->count; - - result = GL_TRUE; -end: - slang_storage_aggregate_destruct (&agg); -end1: - slang_assembly_typeinfo_destruct (&ti); - return result; + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + GLuint index, size; + GLuint skip_jump, true_label, true_jump, false_label, false_jump; + + /* get type of operation */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + /* convert it to an aggregate */ + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable + (&agg, &ti.spec, 0, A->space.funcs, A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end; + + /* compute the size of the agregate - there are two such aggregates on the stack */ + size = _slang_sizeof_aggregate(&agg); + + /* jump to the actual data-comparison code */ + skip_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + /* pop off the stack the compared data and push 1 */ + true_label = A->file->count; + if (!PLAB(A->file, slang_asm_local_free, size * 2)) + goto end; + if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 1)) + goto end; + true_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + false_label = A->file->count; + if (!PLAB(A->file, slang_asm_local_free, size * 2)) + goto end; + if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 0)) + goto end; + false_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + A->file->code[skip_jump].param[0] = A->file->count; + + /* compare the data on stack, it will eventually jump either to true or false label */ + index = 0; + if (!equality_aggregate + (A, &agg, &index, size, equal ? false_label : true_label)) + goto end; + if (!PLAB(A->file, slang_asm_jump, equal ? true_label : false_label)) + goto end; + + A->file->code[true_jump].param[0] = A->file->count; + A->file->code[false_jump].param[0] = A->file->count; + + result = GL_TRUE; + end: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; } -static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinfo *tie, - slang_assembly_typeinfo *tia, slang_operation *op, slang_ref_type ref) +static GLboolean +handle_subscript(slang_assemble_ctx * A, slang_assembly_typeinfo * tie, + slang_assembly_typeinfo * tia, slang_operation * op, + slang_ref_type ref) { - GLuint asize = 0, esize = 0; - - /* get type info of the master expression (matrix, vector or an array */ - if (!_slang_typeof_operation (A, &op->children[0], tia)) - return GL_FALSE; - if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_len, &asize)) - return GL_FALSE; - - /* get type info of the result (matrix column, vector row or array element) */ - if (!_slang_typeof_operation (A, op, tie)) - return GL_FALSE; - if (!sizeof_variable (A, &tie->spec, slang_qual_none, 0, &esize)) - return GL_FALSE; - - /* assemble the master expression */ - if (!_slang_assemble_operation (A, &op->children[0], ref)) - return GL_FALSE; - - /* when indexing an l-value swizzle, push the swizzle_tmp */ - if (ref == slang_ref_force && tia->is_swizzled) - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - return GL_FALSE; - - /* assemble the subscript expression */ - if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) - return GL_FALSE; - - if (ref == slang_ref_force && tia->is_swizzled) - { - GLuint i; - - /* copy the swizzle indexes to the swizzle_tmp */ - for (i = 0; i < tia->swz.num_components; i++) - { - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_addr_push, i * 4)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_add)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_addr_push, tia->swz.swizzle[i])) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_copy)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; - } - - /* offset the pushed swizzle_tmp address and dereference it */ - if (!PUSH (A->file, slang_asm_int_to_addr)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_addr_push, 4)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_multiply)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_add)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_deref)) - return GL_FALSE; - } - else - { - /* convert the integer subscript to a relative address */ - if (!PUSH (A->file, slang_asm_int_to_addr)) - return GL_FALSE; - } - - if (!PLAB (A->file, slang_asm_addr_push, esize)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_multiply)) - return GL_FALSE; - - if (ref == slang_ref_force) - { - /* offset the base address with the relative address */ - if (!PUSH (A->file, slang_asm_addr_add)) - return GL_FALSE; - } - else - { - GLuint i; - - /* move the selected element to the beginning of the master expression */ - for (i = 0; i < esize; i += 4) - if (!PLAB2 (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; - - /* free the rest of the master expression */ - if (!PLAB (A->file, slang_asm_local_free, asize - esize)) - return GL_FALSE; - } - - return GL_TRUE; + GLuint asize = 0, esize = 0; + + /* get type info of the master expression (matrix, vector or an array */ + if (!_slang_typeof_operation(A, &op->children[0], tia)) + return GL_FALSE; + if (!sizeof_variable + (A, &tia->spec, slang_qual_none, tia->array_len, &asize)) + return GL_FALSE; + + /* get type info of the result (matrix column, vector row or array element) */ + if (!_slang_typeof_operation(A, op, tie)) + return GL_FALSE; + if (!sizeof_variable(A, &tie->spec, slang_qual_none, 0, &esize)) + return GL_FALSE; + + /* assemble the master expression */ + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + + /* when indexing an l-value swizzle, push the swizzle_tmp */ + if (ref == slang_ref_force && tia->is_swizzled) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + + /* assemble the subscript expression */ + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + if (ref == slang_ref_force && tia->is_swizzled) { + GLuint i; + + /* copy the swizzle indexes to the swizzle_tmp */ + for (i = 0; i < tia->swz.num_components; i++) { + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, i * 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, tia->swz.swizzle[i])) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + + /* offset the pushed swizzle_tmp address and dereference it */ + if (!PUSH(A->file, slang_asm_int_to_addr)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_multiply)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + } + else { + /* convert the integer subscript to a relative address */ + if (!PUSH(A->file, slang_asm_int_to_addr)) + return GL_FALSE; + } + + if (!PLAB(A->file, slang_asm_addr_push, esize)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_multiply)) + return GL_FALSE; + + if (ref == slang_ref_force) { + /* offset the base address with the relative address */ + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + } + else { + GLuint i; + + /* move the selected element to the beginning of the master expression */ + for (i = 0; i < esize; i += 4) + if (!PLAB2 + (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + + /* free the rest of the master expression */ + if (!PLAB(A->file, slang_asm_local_free, asize - esize)) + return GL_FALSE; + } + + return GL_TRUE; } -static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *tia, - slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref) +static GLboolean +handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia, + slang_assembly_typeinfo * tib, slang_operation * op, + slang_ref_type ref) { - /* get type info of the result (field or swizzle) */ - if (!_slang_typeof_operation (A, op, tia)) - return GL_FALSE; - - /* get type info of the master expression being accessed (struct or vector) */ - if (!_slang_typeof_operation (A, &op->children[0], tib)) - return GL_FALSE; - - /* if swizzling a vector in-place, the swizzle temporary is needed */ - if (ref == slang_ref_forbid && tia->is_swizzled) - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - return GL_FALSE; - - /* assemble the master expression */ - if (!_slang_assemble_operation (A, &op->children[0], ref)) - return GL_FALSE; - - /* assemble the field expression */ - if (tia->is_swizzled) - { - if (ref == slang_ref_force) - { + /* get type info of the result (field or swizzle) */ + if (!_slang_typeof_operation(A, op, tia)) + return GL_FALSE; + + /* get type info of the master expression being accessed (struct or vector) */ + if (!_slang_typeof_operation(A, &op->children[0], tib)) + return GL_FALSE; + + /* if swizzling a vector in-place, the swizzle temporary is needed */ + if (ref == slang_ref_forbid && tia->is_swizzled) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + + /* assemble the master expression */ + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + + /* assemble the field expression */ + if (tia->is_swizzled) { + if (ref == slang_ref_force) { #if 0 - if (tia->swz.num_components == 1) - { - /* simple case - adjust the vector's address to point to the selected component */ - if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4)) - return 0; - if (!PUSH (file, slang_asm_addr_add)) - return 0; - } - else + if (tia->swz.num_components == 1) { + /* simple case - adjust the vector's address to point to + * the selected component + */ + if (!PLAB(file, slang_asm_addr_push, tia->swz.swizzle[0] * 4)) + return 0; + if (!PUSH(file, slang_asm_addr_add)) + return 0; + } + else #endif - { - /* two or more vector components are being referenced - the so-called write mask - * must be passed to the upper operations and applied when assigning value - * to this swizzle */ - A->swz = tia->swz; - } - } - else - { - /* swizzle the vector in-place using the swizzle temporary */ - if (!_slang_assemble_constructor_from_swizzle (A, &tia->swz, &tia->spec, &tib->spec)) - return GL_FALSE; - } - } - else - { - GLuint i, struct_size = 0, field_offset = 0, field_size = 0; + { + /* two or more vector components are being referenced - + * the so-called write mask must be passed to the upper + * operations and applied when assigning value to this swizzle + */ + A->swz = tia->swz; + } + } + else { + /* swizzle the vector in-place using the swizzle temporary */ + if (!_slang_assemble_constructor_from_swizzle + (A, &tia->swz, &tia->spec, &tib->spec)) + return GL_FALSE; + } + } + else { + GLuint i, struct_size = 0, field_offset = 0, field_size = 0; /* * Calculate struct size, field offset and field size. */ - for (i = 0; i < tib->spec._struct->fields->num_variables; i++) - { - slang_variable *field; - slang_storage_aggregate agg; - GLuint size; - - field = &tib->spec._struct->fields->variables[i]; - if (!slang_storage_aggregate_construct (&agg)) - return GL_FALSE; - if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_len, - A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms)) - { - slang_storage_aggregate_destruct (&agg); - return GL_FALSE; - } - size = _slang_sizeof_aggregate (&agg); - slang_storage_aggregate_destruct (&agg); + for (i = 0; i < tib->spec._struct->fields->num_variables; i++) { + slang_variable *field; + slang_storage_aggregate agg; + GLuint size; + + field = &tib->spec._struct->fields->variables[i]; + if (!slang_storage_aggregate_construct(&agg)) + return GL_FALSE; + if (!_slang_aggregate_variable + (&agg, &field->type.specifier, field->array_len, A->space.funcs, + A->space.structs, A->space.vars, A->mach, A->file, A->atoms)) { + slang_storage_aggregate_destruct(&agg); + return GL_FALSE; + } + size = _slang_sizeof_aggregate(&agg); + slang_storage_aggregate_destruct(&agg); if (op->a_id == field->a_name) { field_size = size; field_offset = struct_size; } struct_size += size; - } + } - if (ref == slang_ref_force) - { + if (ref == slang_ref_force) { GLboolean shift; /* - * OPTIMIZATION: If selecting first field, no address shifting is needed. - */ + * OPTIMIZATION: If selecting first field, no address shifting + * is needed. + */ shift = (field_offset != 0); if (shift) { - if (!PLAB (A->file, slang_asm_addr_push, field_offset)) + if (!PLAB(A->file, slang_asm_addr_push, field_offset)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) return GL_FALSE; - if (!PUSH (A->file, slang_asm_addr_add)) - return GL_FALSE; - } - } - else - { + } + } + else { GLboolean relocate, shrink; - GLuint free_b = 0; + GLuint free_b = 0; /* - * OPTIMIZATION: If selecting last field, no relocation is needed. - */ + * OPTIMIZATION: If selecting last field, no relocation is needed. + */ relocate = (field_offset != (struct_size - field_size)); /* - * OPTIMIZATION: If field and struct sizes are equal, no partial free is needed. - */ + * OPTIMIZATION: If field and struct sizes are equal, no partial + * free is needed. + */ shrink = (field_size != struct_size); - if (relocate) - { - GLuint i; + if (relocate) { + GLuint i; - /* - * Move the selected element to the end of the master expression. - * Do it in reverse order to avoid overwriting itself. - */ - if (!PLAB (A->file, slang_asm_addr_push, field_offset)) + /* + * Move the selected element to the end of the master expression. + * Do it in reverse order to avoid overwriting itself. + */ + if (!PLAB(A->file, slang_asm_addr_push, field_offset)) return GL_FALSE; - for (i = field_size; i > 0; i -= 4) - if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i, i)) - return GL_FALSE; - free_b += 4; - } - - if (shrink) - { - /* free the rest of the master expression */ - free_b += struct_size - field_size; - } - - if (free_b) - { - if (!PLAB (A->file, slang_asm_local_free, free_b)) - return GL_FALSE; - } - } - } - - return GL_TRUE; + for (i = field_size; i > 0; i -= 4) + if (!PLAB2 + (A->file, slang_asm_float_move, + struct_size - field_size + i, i)) + return GL_FALSE; + free_b += 4; + } + + if (shrink) { + /* free the rest of the master expression */ + free_b += struct_size - field_size; + } + + if (free_b) { + if (!PLAB(A->file, slang_asm_local_free, free_b)) + return GL_FALSE; + } + } + } + + return GL_TRUE; } -GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref) +GLboolean +_slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op, + slang_ref_type ref) { - /* set default results */ - A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref; - A->swz.num_components = 0; - - switch (op->type) - { - case slang_oper_block_no_new_scope: - case slang_oper_block_new_scope: - { - GLuint i; - - for (i = 0; i < op->num_children; i++) - { - if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/)) - return GL_FALSE; - if (!_slang_cleanup_stack (A, &op->children[i])) - return GL_FALSE; - } - } - break; - case slang_oper_variable_decl: - { - GLuint i; - slang_operation assign; - GLboolean result; - - /* Construct assignment expression placeholder. */ - if (!slang_operation_construct (&assign)) - return GL_FALSE; - assign.type = slang_oper_assign; - assign.children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation)); - if (assign.children == NULL) - { - slang_operation_destruct (&assign); - return GL_FALSE; - } - for (assign.num_children = 0; assign.num_children < 2; assign.num_children++) - if (!slang_operation_construct (&assign.children[assign.num_children])) - { - slang_operation_destruct (&assign); - return GL_FALSE; - } - - result = GL_TRUE; - for (i = 0; i < op->num_children; i++) - { - slang_variable *var; - - var = _slang_locate_variable (op->children[i].locals, op->children[i].a_id, GL_TRUE); - if (var == NULL) - { - result = GL_FALSE; - break; - } - if (var->initializer == NULL) - continue; - - if (!slang_operation_copy (&assign.children[0], &op->children[i]) || - !slang_operation_copy (&assign.children[1], var->initializer) || - !_slang_assemble_assign (A, &assign, "=", slang_ref_forbid) || - !_slang_cleanup_stack (A, &assign)) - { - result = GL_FALSE; - break; - } - } - slang_operation_destruct (&assign); - if (!result) - return GL_FALSE; - } - break; - case slang_oper_asm: - { - GLuint i; - - if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force)) - return GL_FALSE; - for (i = 1; i < op->num_children; i++) - if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid)) - return GL_FALSE; - if (!call_asm_instruction (A, op->a_id)) - return GL_FALSE; - } - break; - case slang_oper_break: - if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end)) - return GL_FALSE; - break; - case slang_oper_continue: - if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start)) - return GL_FALSE; - break; - case slang_oper_discard: - if (!PUSH (A->file, slang_asm_discard)) - return GL_FALSE; - if (!PUSH (A->file, slang_asm_exit)) - return GL_FALSE; - break; - case slang_oper_return: - if (A->local.ret_size != 0) - { - /* push the result's address */ - if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size)) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) - return GL_FALSE; - - A->swz.num_components = 0; - /* assign the operation to the function result (it was reserved on the stack) */ - if (!_slang_assemble_assignment (A, op->children)) - return GL_FALSE; - - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; - } - if (!PLAB (A->file, slang_asm_jump, A->flow.function_end)) - return GL_FALSE; - break; - case slang_oper_expression: - if (ref == slang_ref_force) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[0], ref)) - return GL_FALSE; - break; - case slang_oper_if: - if (!_slang_assemble_if (A, op)) - return GL_FALSE; - break; - case slang_oper_while: - if (!_slang_assemble_while (A, op)) - return GL_FALSE; - break; - case slang_oper_do: - if (!_slang_assemble_do (A, op)) - return GL_FALSE; - break; - case slang_oper_for: - if (!_slang_assemble_for (A, op)) - return GL_FALSE; - break; - case slang_oper_void: - break; - case slang_oper_literal_bool: - if (ref == slang_ref_force) - return GL_FALSE; - if (!PLIT (A->file, slang_asm_bool_push, op->literal)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_literal_int: - if (ref == slang_ref_force) - return GL_FALSE; - if (!PLIT (A->file, slang_asm_int_push, op->literal)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_literal_float: - if (ref == slang_ref_force) - return GL_FALSE; - if (!PLIT (A->file, slang_asm_float_push, op->literal)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_identifier: - { - slang_variable *var; - GLuint size; - - /* find the variable and calculate its size */ - var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE); - if (var == NULL) - return GL_FALSE; - size = 0; - if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size)) - return GL_FALSE; - - /* prepare stack for dereferencing */ - if (ref == slang_ref_forbid) - if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - - /* push the variable's address */ - if (var->global) - { - if (!PLAB (A->file, slang_asm_global_addr, var->address)) - return GL_FALSE; - } - else - { - if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size)) - return GL_FALSE; - } - - /* perform the dereference */ - if (ref == slang_ref_forbid) - { - if (!PUSH (A->file, slang_asm_addr_copy)) - return GL_FALSE; - if (!PLAB (A->file, slang_asm_local_free, 4)) - return GL_FALSE; - if (!_slang_dereference (A, op)) - return GL_FALSE; - } - } - break; - case slang_oper_sequence: - if (ref == slang_ref_force) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/)) - return GL_FALSE; - if (!_slang_cleanup_stack (A, &op->children[0])) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_assign: - if (!_slang_assemble_assign (A, op, "=", ref)) - return GL_FALSE; - break; - case slang_oper_addassign: - if (!_slang_assemble_assign (A, op, "+=", ref)) - return GL_FALSE; - A->ref = ref; - break; - case slang_oper_subassign: - if (!_slang_assemble_assign (A, op, "-=", ref)) - return GL_FALSE; - A->ref = ref; - break; - case slang_oper_mulassign: - if (!_slang_assemble_assign (A, op, "*=", ref)) - return GL_FALSE; - A->ref = ref; - break; - /*case slang_oper_modassign:*/ - /*case slang_oper_lshassign:*/ - /*case slang_oper_rshassign:*/ - /*case slang_oper_orassign:*/ - /*case slang_oper_xorassign:*/ - /*case slang_oper_andassign:*/ - case slang_oper_divassign: - if (!_slang_assemble_assign (A, op, "/=", ref)) - return GL_FALSE; - A->ref = ref; - break; - case slang_oper_select: - if (!_slang_assemble_select (A, op)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_logicalor: - if (!_slang_assemble_logicalor (A, op)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_logicaland: - if (!_slang_assemble_logicaland (A, op)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_logicalxor: - if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - /*case slang_oper_bitor:*/ - /*case slang_oper_bitxor:*/ - /*case slang_oper_bitand:*/ - case slang_oper_less: - if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_greater: - if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_lessequal: - if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_greaterequal: - if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - /*case slang_oper_lshift:*/ - /*case slang_oper_rshift:*/ - case slang_oper_add: - if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_subtract: - if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_multiply: - if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - /*case slang_oper_modulus:*/ - case slang_oper_divide: - if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_equal: - if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) - return GL_FALSE; - if (!equality (A, op->children, GL_TRUE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_notequal: - if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) - return GL_FALSE; - if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) - return GL_FALSE; - if (!equality (A, op->children, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_preincrement: - if (!_slang_assemble_assign (A, op, "++", ref)) - return GL_FALSE; - A->ref = ref; - break; - case slang_oper_predecrement: - if (!_slang_assemble_assign (A, op, "--", ref)) - return GL_FALSE; - A->ref = ref; - break; - case slang_oper_plus: - if (!_slang_dereference (A, op)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_minus: - if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - /*case slang_oper_complement:*/ - case slang_oper_not: - if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_subscript: - { - slang_assembly_typeinfo ti_arr, ti_elem; - - if (!slang_assembly_typeinfo_construct (&ti_arr)) - return GL_FALSE; - if (!slang_assembly_typeinfo_construct (&ti_elem)) - { - slang_assembly_typeinfo_destruct (&ti_arr); - return GL_FALSE; - } - if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref)) - { - slang_assembly_typeinfo_destruct (&ti_arr); - slang_assembly_typeinfo_destruct (&ti_elem); - return GL_FALSE; - } - slang_assembly_typeinfo_destruct (&ti_arr); - slang_assembly_typeinfo_destruct (&ti_elem); - } - break; - case slang_oper_call: - { - slang_function *fun; - - fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children, - &A->space, A->atoms); - if (fun == NULL) - { - if (!_slang_assemble_constructor (A, op)) - return GL_FALSE; - } - else - { - if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE)) - return GL_FALSE; - } - A->ref = slang_ref_forbid; - } - break; - case slang_oper_field: - { - slang_assembly_typeinfo ti_after, ti_before; - - if (!slang_assembly_typeinfo_construct (&ti_after)) - return GL_FALSE; - if (!slang_assembly_typeinfo_construct (&ti_before)) - { - slang_assembly_typeinfo_destruct (&ti_after); - return GL_FALSE; - } - if (!handle_field (A, &ti_after, &ti_before, op, ref)) - { - slang_assembly_typeinfo_destruct (&ti_after); - slang_assembly_typeinfo_destruct (&ti_before); - return GL_FALSE; - } - slang_assembly_typeinfo_destruct (&ti_after); - slang_assembly_typeinfo_destruct (&ti_before); - } - break; - case slang_oper_postincrement: - if (!assemble_function_call_name_dummyint (A, "++", op->children)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - case slang_oper_postdecrement: - if (!assemble_function_call_name_dummyint (A, "--", op->children)) - return GL_FALSE; - A->ref = slang_ref_forbid; - break; - default: - return GL_FALSE; - } - - return GL_TRUE; -} + /* set default results */ + A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ ref; + A->swz.num_components = 0; + + switch (op->type) { + case slang_oper_block_no_new_scope: + case slang_oper_block_new_scope: + { + GLuint i; + + for (i = 0; i < op->num_children; i++) { + if (!_slang_assemble_operation + (A, &op->children[i], + slang_ref_forbid /*slang_ref_freelance */ )) + return GL_FALSE; + if (!_slang_cleanup_stack(A, &op->children[i])) + return GL_FALSE; + } + } + break; + case slang_oper_variable_decl: + { + GLuint i; + slang_operation assign; + GLboolean result; + + /* Construct assignment expression placeholder. */ + if (!slang_operation_construct(&assign)) + return GL_FALSE; + assign.type = slang_oper_assign; + assign.children = + (slang_operation *) slang_alloc_malloc(2 * + sizeof(slang_operation)); + if (assign.children == NULL) { + slang_operation_destruct(&assign); + return GL_FALSE; + } + for (assign.num_children = 0; assign.num_children < 2; + assign.num_children++) + if (!slang_operation_construct + (&assign.children[assign.num_children])) { + slang_operation_destruct(&assign); + return GL_FALSE; + } + + result = GL_TRUE; + for (i = 0; i < op->num_children; i++) { + slang_variable *var; + + var = + _slang_locate_variable(op->children[i].locals, + op->children[i].a_id, GL_TRUE); + if (var == NULL) { + result = GL_FALSE; + break; + } + if (var->initializer == NULL) + continue; + + if (!slang_operation_copy(&assign.children[0], &op->children[i]) + || !slang_operation_copy(&assign.children[1], + var->initializer) + || !_slang_assemble_assign(A, &assign, "=", slang_ref_forbid) + || !_slang_cleanup_stack(A, &assign)) { + result = GL_FALSE; + break; + } + } + slang_operation_destruct(&assign); + if (!result) + return GL_FALSE; + } + break; + case slang_oper_asm: + { + GLuint i; + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force)) + return GL_FALSE; + for (i = 1; i < op->num_children; i++) + if (!_slang_assemble_operation + (A, &op->children[i], slang_ref_forbid)) + return GL_FALSE; + if (!call_asm_instruction(A, op->a_id)) + return GL_FALSE; + } + break; + case slang_oper_break: + if (!PLAB(A->file, slang_asm_jump, A->flow.loop_end)) + return GL_FALSE; + break; + case slang_oper_continue: + if (!PLAB(A->file, slang_asm_jump, A->flow.loop_start)) + return GL_FALSE; + break; + case slang_oper_discard: + if (!PUSH(A->file, slang_asm_discard)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_exit)) + return GL_FALSE; + break; + case slang_oper_return: + if (A->local.ret_size != 0) { + /* push the result's address */ + if (!PLAB2(A->file, slang_asm_local_addr, 0, A->local.ret_size)) + return GL_FALSE; + if (!_slang_assemble_operation + (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + A->swz.num_components = 0; + /* assign the operation to the function result (it was reserved on the stack) */ + if (!_slang_assemble_assignment(A, op->children)) + return GL_FALSE; + + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + if (!PLAB(A->file, slang_asm_jump, A->flow.function_end)) + return GL_FALSE; + break; + case slang_oper_expression: + if (ref == slang_ref_force) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + break; + case slang_oper_if: + if (!_slang_assemble_if(A, op)) + return GL_FALSE; + break; + case slang_oper_while: + if (!_slang_assemble_while(A, op)) + return GL_FALSE; + break; + case slang_oper_do: + if (!_slang_assemble_do(A, op)) + return GL_FALSE; + break; + case slang_oper_for: + if (!_slang_assemble_for(A, op)) + return GL_FALSE; + break; + case slang_oper_void: + break; + case slang_oper_literal_bool: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_bool_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_literal_int: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_int_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_literal_float: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_float_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_identifier: + { + slang_variable *var; + GLuint size; + + /* find the variable and calculate its size */ + var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); + if (var == NULL) + return GL_FALSE; + size = 0; + if (!sizeof_variable + (A, &var->type.specifier, slang_qual_none, var->array_len, + &size)) + return GL_FALSE; + + /* prepare stack for dereferencing */ + if (ref == slang_ref_forbid) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + + /* push the variable's address */ + if (var->global) { + if (!PLAB(A->file, slang_asm_global_addr, var->address)) + return GL_FALSE; + } + else { + if (!PLAB2(A->file, slang_asm_local_addr, var->address, size)) + return GL_FALSE; + } + /* perform the dereference */ + if (ref == slang_ref_forbid) { + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + if (!_slang_dereference(A, op)) + return GL_FALSE; + } + } + break; + case slang_oper_sequence: + if (ref == slang_ref_force) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[0], + slang_ref_forbid /*slang_ref_freelance */ )) + return GL_FALSE; + if (!_slang_cleanup_stack(A, &op->children[0])) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_assign: + if (!_slang_assemble_assign(A, op, "=", ref)) + return GL_FALSE; + break; + case slang_oper_addassign: + if (!_slang_assemble_assign(A, op, "+=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_subassign: + if (!_slang_assemble_assign(A, op, "-=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_mulassign: + if (!_slang_assemble_assign(A, op, "*=", ref)) + return GL_FALSE; + A->ref = ref; + break; + /*case slang_oper_modassign: */ + /*case slang_oper_lshassign: */ + /*case slang_oper_rshassign: */ + /*case slang_oper_orassign: */ + /*case slang_oper_xorassign: */ + /*case slang_oper_andassign: */ + case slang_oper_divassign: + if (!_slang_assemble_assign(A, op, "/=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_select: + if (!_slang_assemble_select(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicalor: + if (!_slang_assemble_logicalor(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicaland: + if (!_slang_assemble_logicaland(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicalxor: + if (!_slang_assemble_function_call_name(A, "^^", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_bitor: */ + /*case slang_oper_bitxor: */ + /*case slang_oper_bitand: */ + case slang_oper_less: + if (!_slang_assemble_function_call_name(A, "<", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_greater: + if (!_slang_assemble_function_call_name(A, ">", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_lessequal: + if (!_slang_assemble_function_call_name(A, "<=", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_greaterequal: + if (!_slang_assemble_function_call_name(A, ">=", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_lshift: */ + /*case slang_oper_rshift: */ + case slang_oper_add: + if (!_slang_assemble_function_call_name(A, "+", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_subtract: + if (!_slang_assemble_function_call_name(A, "-", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_multiply: + if (!_slang_assemble_function_call_name(A, "*", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_modulus: */ + case slang_oper_divide: + if (!_slang_assemble_function_call_name(A, "/", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_equal: + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + if (!equality(A, op->children, GL_TRUE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_notequal: + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + if (!equality(A, op->children, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_preincrement: + if (!_slang_assemble_assign(A, op, "++", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_predecrement: + if (!_slang_assemble_assign(A, op, "--", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_plus: + if (!_slang_dereference(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_minus: + if (!_slang_assemble_function_call_name + (A, "-", op->children, 1, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_complement: */ + case slang_oper_not: + if (!_slang_assemble_function_call_name + (A, "!", op->children, 1, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_subscript: + { + slang_assembly_typeinfo ti_arr, ti_elem; + + if (!slang_assembly_typeinfo_construct(&ti_arr)) + return GL_FALSE; + if (!slang_assembly_typeinfo_construct(&ti_elem)) { + slang_assembly_typeinfo_destruct(&ti_arr); + return GL_FALSE; + } + if (!handle_subscript(A, &ti_elem, &ti_arr, op, ref)) { + slang_assembly_typeinfo_destruct(&ti_arr); + slang_assembly_typeinfo_destruct(&ti_elem); + return GL_FALSE; + } + slang_assembly_typeinfo_destruct(&ti_arr); + slang_assembly_typeinfo_destruct(&ti_elem); + } + break; + case slang_oper_call: + { + slang_function *fun; + + fun = + _slang_locate_function(A->space.funcs, op->a_id, op->children, + op->num_children, &A->space, A->atoms); + if (fun == NULL) { + if (!_slang_assemble_constructor(A, op)) + return GL_FALSE; + } + else { + if (!_slang_assemble_function_call + (A, fun, op->children, op->num_children, GL_FALSE)) + return GL_FALSE; + } + A->ref = slang_ref_forbid; + } + break; + case slang_oper_field: + { + slang_assembly_typeinfo ti_after, ti_before; + + if (!slang_assembly_typeinfo_construct(&ti_after)) + return GL_FALSE; + if (!slang_assembly_typeinfo_construct(&ti_before)) { + slang_assembly_typeinfo_destruct(&ti_after); + return GL_FALSE; + } + if (!handle_field(A, &ti_after, &ti_before, op, ref)) { + slang_assembly_typeinfo_destruct(&ti_after); + slang_assembly_typeinfo_destruct(&ti_before); + return GL_FALSE; + } + slang_assembly_typeinfo_destruct(&ti_after); + slang_assembly_typeinfo_destruct(&ti_before); + } + break; + case slang_oper_postincrement: + if (!assemble_function_call_name_dummyint(A, "++", op->children)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_postdecrement: + if (!assemble_function_call_name_dummyint(A, "--", op->children)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + default: + return GL_FALSE; + } + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_execute_x86.c b/src/mesa/shader/slang/slang_execute_x86.c index 3e21edff6a3..958086ff07c 100644 --- a/src/mesa/shader/slang/slang_execute_x86.c +++ b/src/mesa/shader/slang/slang_execute_x86.c @@ -40,40 +40,42 @@ typedef struct { - GLuint index; - GLubyte *csr; + GLuint index; + GLubyte *csr; } fixup; typedef struct { - struct x86_function f; - struct x86_reg r_eax; - struct x86_reg r_ecx; - struct x86_reg r_edx; + struct x86_function f; + struct x86_reg r_eax; + struct x86_reg r_ecx; + struct x86_reg r_edx; struct x86_reg r_ebx; - struct x86_reg r_esp; - struct x86_reg r_ebp; - struct x86_reg r_st0; - struct x86_reg r_st1; - struct x86_reg r_st2; - struct x86_reg r_st3; + struct x86_reg r_esp; + struct x86_reg r_ebp; + struct x86_reg r_st0; + struct x86_reg r_st1; + struct x86_reg r_st2; + struct x86_reg r_st3; struct x86_reg r_st4; - fixup *fixups; - GLuint fixup_count; - GLubyte **labels; - slang_machine *mach; - GLubyte *l_discard; - GLubyte *l_exit; - GLshort fpucntl; + fixup *fixups; + GLuint fixup_count; + GLubyte **labels; + slang_machine *mach; + GLubyte *l_discard; + GLubyte *l_exit; + GLshort fpucntl; } codegen_ctx; -static GLvoid add_fixup (codegen_ctx *G, GLuint index, GLubyte *csr) +static GLvoid +add_fixup(codegen_ctx * G, GLuint index, GLubyte * csr) { - G->fixups = (fixup *) slang_alloc_realloc (G->fixups, G->fixup_count * sizeof (fixup), - (G->fixup_count + 1) * sizeof (fixup)); - G->fixups[G->fixup_count].index = index; - G->fixups[G->fixup_count].csr = csr; - G->fixup_count++; + G->fixups = + (fixup *) slang_alloc_realloc(G->fixups, G->fixup_count * sizeof(fixup), + (G->fixup_count + 1) * sizeof(fixup)); + G->fixups[G->fixup_count].index = index; + G->fixups[G->fixup_count].csr = csr; + G->fixup_count++; } #ifdef NO_FAST_MATH @@ -88,661 +90,665 @@ static GLvoid add_fixup (codegen_ctx *G, GLuint index, GLubyte *csr) /* * XXX - * These should produce a valid code that computes powers. Unfortunately, it does not. + * These should produce a valid code that computes powers. + * Unfortunately, it does not. */ -static void set_fpu_round_neg_inf (codegen_ctx *G) +static void +set_fpu_round_neg_inf(codegen_ctx * G) { - if (G->fpucntl != RND_NEG_FPU) - { - G->fpucntl = RND_NEG_FPU; - x87_fnclex (&G->f); - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->x86.fpucntl_rnd_neg); - x87_fldcw (&G->f, x86_deref (G->r_eax)); - } + if (G->fpucntl != RND_NEG_FPU) { + G->fpucntl = RND_NEG_FPU; + x87_fnclex(&G->f); + x86_mov_reg_imm(&G->f, G->r_eax, + (GLint) & G->mach->x86.fpucntl_rnd_neg); + x87_fldcw(&G->f, x86_deref(G->r_eax)); + } } -static void emit_x87_ex2 (codegen_ctx *G) +static void +emit_x87_ex2(codegen_ctx * G) { - set_fpu_round_neg_inf (G); - - x87_fld (&G->f, G->r_st0); /* a a */ - x87_fprndint (&G->f); /* int(a) a */ - x87_fld (&G->f, G->r_st0); /* int(a) int(a) a */ - x87_fstp (&G->f, G->r_st3); /* int(a) a int(a)*/ - x87_fsubp (&G->f, G->r_st1);/* frac(a) int(a) */ - x87_f2xm1 (&G->f); /* (2^frac(a))-1 int(a)*/ - x87_fld1 (&G->f); /* 1 (2^frac(a))-1 int(a)*/ - x87_faddp (&G->f, G->r_st1);/* 2^frac(a) int(a) */ - x87_fscale (&G->f); /* 2^a */ + set_fpu_round_neg_inf(G); + + x87_fld(&G->f, G->r_st0); /* a a */ + x87_fprndint(&G->f); /* int(a) a */ + x87_fld(&G->f, G->r_st0); /* int(a) int(a) a */ + x87_fstp(&G->f, G->r_st3); /* int(a) a int(a) */ + x87_fsubp(&G->f, G->r_st1); /* frac(a) int(a) */ + x87_f2xm1(&G->f); /* (2^frac(a))-1 int(a) */ + x87_fld1(&G->f); /* 1 (2^frac(a))-1 int(a) */ + x87_faddp(&G->f, G->r_st1); /* 2^frac(a) int(a) */ + x87_fscale(&G->f); /* 2^a */ } -static void emit_pow (codegen_ctx *G) +static void +emit_pow(codegen_ctx * G) { - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fyl2x (&G->f); - emit_x87_ex2 (G); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fyl2x(&G->f); + emit_x87_ex2(G); } #endif -static GLfloat do_ceilf (GLfloat x) +static GLfloat +do_ceilf(GLfloat x) { - return CEILF (x); + return CEILF(x); } -static GLfloat do_floorf (GLfloat x) +static GLfloat +do_floorf(GLfloat x) { - return FLOORF (x); + return FLOORF(x); } static GLfloat -do_ftoi (GLfloat x) +do_ftoi(GLfloat x) { return (GLfloat) ((GLint) (x)); } -static GLfloat do_powf (GLfloat y, GLfloat x) +static GLfloat +do_powf(GLfloat y, GLfloat x) { - return (GLfloat) _mesa_pow ((GLdouble) x, (GLdouble) y); + return (GLfloat) _mesa_pow((GLdouble) x, (GLdouble) y); } static GLvoid -ensure_infolog_created (slang_info_log **infolog) +ensure_infolog_created(slang_info_log ** infolog) { if (*infolog == NULL) { - *infolog = slang_alloc_malloc (sizeof (slang_info_log)); + *infolog = slang_alloc_malloc(sizeof(slang_info_log)); if (*infolog == NULL) return; - slang_info_log_construct (*infolog); + slang_info_log_construct(*infolog); } } -static GLvoid do_print_float (slang_info_log **infolog, GLfloat x) +static GLvoid +do_print_float(slang_info_log ** infolog, GLfloat x) { - _mesa_printf ("slang print: %f\n", x); - ensure_infolog_created (infolog); - slang_info_log_print (*infolog, "%f", x); + _mesa_printf("slang print: %f\n", x); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%f", x); } -static GLvoid do_print_int (slang_info_log **infolog, GLfloat x) +static GLvoid +do_print_int(slang_info_log ** infolog, GLfloat x) { - _mesa_printf ("slang print: %d\n", (GLint) (x)); - ensure_infolog_created (infolog); - slang_info_log_print (*infolog, "%d", (GLint) (x)); + _mesa_printf("slang print: %d\n", (GLint) (x)); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%d", (GLint) (x)); } -static GLvoid do_print_bool (slang_info_log **infolog, GLfloat x) +static GLvoid +do_print_bool(slang_info_log ** infolog, GLfloat x) { - _mesa_printf ("slang print: %s\n", (GLint) (x) ? "true" : "false"); - ensure_infolog_created (infolog); - slang_info_log_print (*infolog, "%s", (GLint) (x) ? "true" : "false"); + _mesa_printf("slang print: %s\n", (GLint) (x) ? "true" : "false"); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%s", (GLint) (x) ? "true" : "false"); } #define FLOAT_ONE 0x3f800000 #define FLOAT_ZERO 0 -static GLvoid codegen_assem (codegen_ctx *G, slang_assembly *a, slang_info_log **infolog) +static GLvoid +codegen_assem(codegen_ctx * G, slang_assembly * a, slang_info_log ** infolog) { - GLint disp, i; - - switch (a->type) - { - case slang_asm_none: - break; - case slang_asm_float_copy: - case slang_asm_int_copy: - case slang_asm_bool_copy: - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[0])); - x86_pop (&G->f, G->r_ecx); - x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1]), G->r_ecx); - break; - case slang_asm_float_move: - case slang_asm_int_move: - case slang_asm_bool_move: - x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[1])); - x86_add (&G->f, G->r_eax, x86_deref (G->r_esp)); - x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax)); - x86_mov (&G->f, x86_make_disp (G->r_esp, a->param[0]), G->r_eax); - break; - case slang_asm_float_push: - case slang_asm_int_push: - case slang_asm_bool_push: - /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, *((GLint *) &a->literal)); - x86_push (&G->f, G->r_eax); - break; - case slang_asm_float_deref: - case slang_asm_int_deref: - case slang_asm_bool_deref: - case slang_asm_addr_deref: - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); - x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax)); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax); - break; - case slang_asm_float_add: - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_faddp (&G->f, G->r_st1); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_multiply: - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fmulp (&G->f, G->r_st1); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_divide: - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fdivp (&G->f, G->r_st1); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_negate: - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fchs (&G->f); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_less: - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fcomp (&G->f, x86_deref (G->r_esp)); - x87_fnstsw (&G->f, G->r_eax); - /* TODO: use test r8,imm8 */ - x86_mov_reg_imm (&G->f, G->r_ecx, 0x100); - x86_test (&G->f, G->r_eax, G->r_ecx); - { - GLubyte *lab0, *lab1; - - /* TODO: use jcc rel8 */ - lab0 = x86_jcc_forward (&G->f, cc_E); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE); - /* TODO: use jmp rel8 */ - lab1 = x86_jmp_forward (&G->f); - x86_fixup_fwd_jump (&G->f, lab0); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO); - x86_fixup_fwd_jump (&G->f, lab1); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx); - } - break; - case slang_asm_float_equal_exp: - x87_fld (&G->f, x86_make_disp (G->r_esp, 4)); - x87_fcomp (&G->f, x86_deref (G->r_esp)); - x87_fnstsw (&G->f, G->r_eax); - /* TODO: use test r8,imm8 */ - x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000); - x86_test (&G->f, G->r_eax, G->r_ecx); - { - GLubyte *lab0, *lab1; - - /* TODO: use jcc rel8 */ - lab0 = x86_jcc_forward (&G->f, cc_E); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE); - /* TODO: use jmp rel8 */ - lab1 = x86_jmp_forward (&G->f); - x86_fixup_fwd_jump (&G->f, lab0); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO); - x86_fixup_fwd_jump (&G->f, lab1); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx); - } - break; - case slang_asm_float_equal_int: - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -4)); - x87_fld (&G->f, x86_make_disp (G->r_esp, a->param[0] + 4)); - x87_fcomp (&G->f, x86_make_disp (G->r_esp, a->param[1] + 4)); - x87_fnstsw (&G->f, G->r_eax); - /* TODO: use test r8,imm8 */ - x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000); - x86_test (&G->f, G->r_eax, G->r_ecx); - { - GLubyte *lab0, *lab1; - - /* TODO: use jcc rel8 */ - lab0 = x86_jcc_forward (&G->f, cc_E); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE); - /* TODO: use jmp rel8 */ - lab1 = x86_jmp_forward (&G->f); - x86_fixup_fwd_jump (&G->f, lab0); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO); - x86_fixup_fwd_jump (&G->f, lab1); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx); - } - break; - case slang_asm_float_to_int: + GLint disp, i; + + switch (a->type) { + case slang_asm_none: + break; + case slang_asm_float_copy: + case slang_asm_int_copy: + case slang_asm_bool_copy: + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[0])); + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1]), G->r_ecx); + break; + case slang_asm_float_move: + case slang_asm_int_move: + case slang_asm_bool_move: + x86_lea(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[1])); + x86_add(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_eax)); + x86_mov(&G->f, x86_make_disp(G->r_esp, a->param[0]), G->r_eax); + break; + case slang_asm_float_push: + case slang_asm_int_push: + case slang_asm_bool_push: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, *((GLint *) & a->literal)); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_float_deref: + case slang_asm_int_deref: + case slang_asm_bool_deref: + case slang_asm_addr_deref: + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_eax)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_float_add: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_faddp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_multiply: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fmulp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_divide: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fdivp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_negate: + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fchs(&G->f); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_less: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fcomp(&G->f, x86_deref(G->r_esp)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x100); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_equal_exp: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fcomp(&G->f, x86_deref(G->r_esp)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_equal_int: + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -4)); + x87_fld(&G->f, x86_make_disp(G->r_esp, a->param[0] + 4)); + x87_fcomp(&G->f, x86_make_disp(G->r_esp, a->param[1] + 4)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_to_int: /* TODO: use fistp without rounding */ - x86_call (&G->f, (GLubyte *) (do_ftoi)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_sine: - /* TODO: use fsin */ - x86_call (&G->f, (GLubyte *) _mesa_sinf); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_arcsine: - /* TODO: use fpatan (?) */ - x86_call (&G->f, (GLubyte *) _mesa_asinf); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_arctan: - /* TODO: use fpatan */ - x86_call (&G->f, (GLubyte *) _mesa_atanf); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_power: - /* TODO: use emit_pow() */ - x86_call (&G->f, (GLubyte *) do_powf); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_log2: - x87_fld1 (&G->f); - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fyl2x (&G->f); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_floor: - x86_call (&G->f, (GLubyte *) do_floorf); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_ceil: - x86_call (&G->f, (GLubyte *) do_ceilf); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_noise1: - x86_call (&G->f, (GLubyte *) _slang_library_noise1); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_noise2: - x86_call (&G->f, (GLubyte *) _slang_library_noise2); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_noise3: - x86_call (&G->f, (GLubyte *) _slang_library_noise4); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 8)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_float_noise4: - x86_call (&G->f, (GLubyte *) _slang_library_noise4); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12)); - x87_fstp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_int_to_float: - break; - case slang_asm_int_to_addr: - x87_fld (&G->f, x86_deref (G->r_esp)); - x87_fistp (&G->f, x86_deref (G->r_esp)); - break; - case slang_asm_addr_copy: - x86_pop (&G->f, G->r_eax); - x86_mov (&G->f, G->r_ecx, x86_deref (G->r_esp)); - x86_mov (&G->f, x86_deref (G->r_ecx), G->r_eax); - break; - case slang_asm_addr_push: - /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) a->param[0]); - x86_push (&G->f, G->r_eax); - break; - case slang_asm_addr_add: - x86_pop (&G->f, G->r_eax); - x86_add (&G->f, x86_deref (G->r_esp), G->r_eax); - break; - case slang_asm_addr_multiply: - x86_pop (&G->f, G->r_ecx); - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); - x86_mul (&G->f, G->r_ecx); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax); - break; - case slang_asm_vec4_tex1d: - x86_call (&G->f, (GLubyte *) _slang_library_tex1d); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12)); - break; - case slang_asm_vec4_tex2d: - x86_call (&G->f, (GLubyte *) _slang_library_tex2d); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); - break; - case slang_asm_vec4_tex3d: - x86_call (&G->f, (GLubyte *) _slang_library_tex3d); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20)); - break; - case slang_asm_vec4_texcube: - x86_call (&G->f, (GLubyte *) _slang_library_texcube); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20)); - break; - case slang_asm_vec4_shad1d: - x86_call (&G->f, (GLubyte *) _slang_library_shad1d); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20)); - break; - case slang_asm_vec4_shad2d: - x86_call (&G->f, (GLubyte *) _slang_library_shad2d); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20)); - break; - case slang_asm_jump: - add_fixup (G, a->param[0], x86_jmp_forward (&G->f)); - break; - case slang_asm_jump_if_zero: - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x86_xor (&G->f, G->r_eax, G->r_eax); - x86_cmp (&G->f, G->r_eax, x86_make_disp (G->r_esp, -4)); - { - GLubyte *lab0; - - /* TODO: use jcc rel8 */ - lab0 = x86_jcc_forward (&G->f, cc_NE); - add_fixup (G, a->param[0], x86_jmp_forward (&G->f)); - x86_fixup_fwd_jump (&G->f, lab0); - } - break; - case slang_asm_enter: - /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ - assert (a->param[0] != 0); - x86_push (&G->f, G->r_ebp); - x86_lea (&G->f, G->r_ebp, x86_make_disp (G->r_esp, (GLint) a->param[0])); - break; - case slang_asm_leave: - x86_pop (&G->f, G->r_ebp); - break; - case slang_asm_local_alloc: - /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ - assert (a->param[0] != 0); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -(GLint) a->param[0])); - break; - case slang_asm_local_free: - /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ - assert (a->param[0] != 0); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, (GLint) a->param[0])); - break; - case slang_asm_local_addr: - disp = -(GLint) (a->param[0] + a->param[1]) + 4; - if (disp != 0) - { - x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_ebp, disp)); - x86_push (&G->f, G->r_eax); - } - else - x86_push (&G->f, G->r_ebp); - break; - case slang_asm_global_addr: - /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->mem + a->param[0]); - x86_push (&G->f, G->r_eax); - break; - case slang_asm_call: - add_fixup (G, a->param[0], x86_call_forward (&G->f)); - break; - case slang_asm_return: - x86_ret (&G->f); - break; - case slang_asm_discard: - x86_jmp (&G->f, G->l_discard); - break; - case slang_asm_exit: - x86_jmp (&G->f, G->l_exit); - break; - /* GL_MESA_shader_debug */ + x86_call(&G->f, (GLubyte *) (do_ftoi)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_sine: + /* TODO: use fsin */ + x86_call(&G->f, (GLubyte *) _mesa_sinf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_arcsine: + /* TODO: use fpatan (?) */ + x86_call(&G->f, (GLubyte *) _mesa_asinf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_arctan: + /* TODO: use fpatan */ + x86_call(&G->f, (GLubyte *) _mesa_atanf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_power: + /* TODO: use emit_pow() */ + x86_call(&G->f, (GLubyte *) do_powf); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_log2: + x87_fld1(&G->f); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fyl2x(&G->f); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_floor: + x86_call(&G->f, (GLubyte *) do_floorf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_ceil: + x86_call(&G->f, (GLubyte *) do_ceilf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise1: + x86_call(&G->f, (GLubyte *) _slang_library_noise1); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise2: + x86_call(&G->f, (GLubyte *) _slang_library_noise2); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise3: + x86_call(&G->f, (GLubyte *) _slang_library_noise4); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 8)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise4: + x86_call(&G->f, (GLubyte *) _slang_library_noise4); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 12)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_int_to_float: + break; + case slang_asm_int_to_addr: + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fistp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_addr_copy: + x86_pop(&G->f, G->r_eax); + x86_mov(&G->f, G->r_ecx, x86_deref(G->r_esp)); + x86_mov(&G->f, x86_deref(G->r_ecx), G->r_eax); + break; + case slang_asm_addr_push: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) a->param[0]); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_addr_add: + x86_pop(&G->f, G->r_eax); + x86_add(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_addr_multiply: + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mul(&G->f, G->r_ecx); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_vec4_tex1d: + x86_call(&G->f, (GLubyte *) _slang_library_tex1d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 12)); + break; + case slang_asm_vec4_tex2d: + x86_call(&G->f, (GLubyte *) _slang_library_tex2d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + break; + case slang_asm_vec4_tex3d: + x86_call(&G->f, (GLubyte *) _slang_library_tex3d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_texcube: + x86_call(&G->f, (GLubyte *) _slang_library_texcube); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_shad1d: + x86_call(&G->f, (GLubyte *) _slang_library_shad1d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_shad2d: + x86_call(&G->f, (GLubyte *) _slang_library_shad2d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_jump: + add_fixup(G, a->param[0], x86_jmp_forward(&G->f)); + break; + case slang_asm_jump_if_zero: + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_xor(&G->f, G->r_eax, G->r_eax); + x86_cmp(&G->f, G->r_eax, x86_make_disp(G->r_esp, -4)); + { + GLubyte *lab0; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_NE); + add_fixup(G, a->param[0], x86_jmp_forward(&G->f)); + x86_fixup_fwd_jump(&G->f, lab0); + } + break; + case slang_asm_enter: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_push(&G->f, G->r_ebp); + x86_lea(&G->f, G->r_ebp, x86_make_disp(G->r_esp, (GLint) a->param[0])); + break; + case slang_asm_leave: + x86_pop(&G->f, G->r_ebp); + break; + case slang_asm_local_alloc: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -(GLint) a->param[0])); + break; + case slang_asm_local_free: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, (GLint) a->param[0])); + break; + case slang_asm_local_addr: + disp = -(GLint) (a->param[0] + a->param[1]) + 4; + if (disp != 0) { + x86_lea(&G->f, G->r_eax, x86_make_disp(G->r_ebp, disp)); + x86_push(&G->f, G->r_eax); + } + else + x86_push(&G->f, G->r_ebp); + break; + case slang_asm_global_addr: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) & G->mach->mem + a->param[0]); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_call: + add_fixup(G, a->param[0], x86_call_forward(&G->f)); + break; + case slang_asm_return: + x86_ret(&G->f); + break; + case slang_asm_discard: + x86_jmp(&G->f, G->l_discard); + break; + case slang_asm_exit: + x86_jmp(&G->f, G->l_exit); + break; + /* GL_MESA_shader_debug */ case slang_asm_float_print: /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) (infolog)); - x86_push (&G->f, G->r_eax); - x86_call (&G->f, (GLubyte *) (do_print_float)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) (do_print_float)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); break; - case slang_asm_int_print: + case slang_asm_int_print: /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) (infolog)); - x86_push (&G->f, G->r_eax); - x86_call (&G->f, (GLubyte *) do_print_int); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - break; - case slang_asm_bool_print: + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) do_print_int); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + break; + case slang_asm_bool_print: /* TODO: use push imm32 */ - x86_mov_reg_imm (&G->f, G->r_eax, (GLint) (infolog)); - x86_push (&G->f, G->r_eax); - x86_call (&G->f, (GLubyte *) do_print_bool); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - break; - /* vec4 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) do_print_bool); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + break; + /* vec4 */ case slang_asm_float_to_vec4: /* [vec4] | float > [vec4] */ - x87_fld (&G->f, x86_deref (G->r_esp)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4)); - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); - x87_fst (&G->f, x86_make_disp (G->r_eax, 12)); - x87_fst (&G->f, x86_make_disp (G->r_eax, 8)); - x87_fst (&G->f, x86_make_disp (G->r_eax, 4)); - x87_fstp (&G->f, x86_deref (G->r_eax)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 12)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 8)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 4)); + x87_fstp(&G->f, x86_deref(G->r_eax)); break; case slang_asm_vec4_add: /* [vec4] | vec4 > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_esp, i * 4)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_faddp (&G->f, G->r_st4); + x87_faddp(&G->f, G->r_st4); for (i = 0; i < 4; i++) - x87_fstp (&G->f, x86_make_disp (G->r_eax, 12 - i * 4)); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); break; case slang_asm_vec4_subtract: /* [vec4] | vec4 > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_esp, i * 4)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fsubp (&G->f, G->r_st4); + x87_fsubp(&G->f, G->r_st4); for (i = 0; i < 4; i++) - x87_fstp (&G->f, x86_make_disp (G->r_eax, 12 - i * 4)); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); break; case slang_asm_vec4_multiply: /* [vec4] | vec4 > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_esp, i * 4)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fmulp (&G->f, G->r_st4); + x87_fmulp(&G->f, G->r_st4); for (i = 0; i < 4; i++) - x87_fstp (&G->f, x86_make_disp (G->r_eax, 12 - i * 4)); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); break; case slang_asm_vec4_divide: /* [vec4] | vec4 > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_esp, i * 4)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); for (i = 0; i < 4; i++) - x87_fdivp (&G->f, G->r_st4); + x87_fdivp(&G->f, G->r_st4); for (i = 0; i < 4; i++) - x87_fstp (&G->f, x86_make_disp (G->r_eax, 12 - i * 4)); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); break; case slang_asm_vec4_negate: /* [vec4] > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) { - x87_fchs (&G->f); - x87_fstp (&G->f, x86_make_disp (G->r_eax, 12 - i * 4)); + x87_fchs(&G->f); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); } break; case slang_asm_vec4_dot: /* [vec4] | vec4 > [float] */ for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_esp, i * 4)); - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16)); - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); for (i = 0; i < 4; i++) - x87_fld (&G->f, x86_make_disp (G->r_eax, i * 4)); + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); for (i = 0; i < 4; i++) - x87_fmulp (&G->f, G->r_st4); + x87_fmulp(&G->f, G->r_st4); for (i = 0; i < 3; i++) - x87_faddp (&G->f, G->r_st1); - x87_fstp (&G->f, x86_deref (G->r_eax)); + x87_faddp(&G->f, G->r_st1); + x87_fstp(&G->f, x86_deref(G->r_eax)); break; case slang_asm_vec4_copy: /* [vec4] | vec4 > [vec4] */ - x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[0])); - x86_pop (&G->f, G->r_ecx); - x86_pop (&G->f, G->r_edx); - x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1]), G->r_ecx); - x86_pop (&G->f, G->r_ebx); - x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1] + 4), G->r_edx); - x86_pop (&G->f, G->r_ecx); - x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1] + 8), G->r_ebx); - x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1] + 12), G->r_ecx); + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[0])); + x86_pop(&G->f, G->r_ecx); + x86_pop(&G->f, G->r_edx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1]), G->r_ecx); + x86_pop(&G->f, G->r_ebx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 4), G->r_edx); + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 8), G->r_ebx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 12), G->r_ecx); break; case slang_asm_vec4_deref: /* [vec4] > vec4 */ - x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp)); - x86_mov (&G->f, G->r_ecx, x86_make_disp (G->r_eax, 12)); - x86_mov (&G->f, G->r_edx, x86_make_disp (G->r_eax, 8)); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx); - x86_mov (&G->f, G->r_ebx, x86_make_disp (G->r_eax, 4)); - x86_push (&G->f, G->r_edx); - x86_mov (&G->f, G->r_ecx, x86_deref (G->r_eax)); - x86_push (&G->f, G->r_ebx); - x86_push (&G->f, G->r_ecx); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_ecx, x86_make_disp(G->r_eax, 12)); + x86_mov(&G->f, G->r_edx, x86_make_disp(G->r_eax, 8)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + x86_mov(&G->f, G->r_ebx, x86_make_disp(G->r_eax, 4)); + x86_push(&G->f, G->r_edx); + x86_mov(&G->f, G->r_ecx, x86_deref(G->r_eax)); + x86_push(&G->f, G->r_ebx); + x86_push(&G->f, G->r_ecx); break; case slang_asm_vec4_equal_int: - x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -4)); - x86_mov_reg_imm (&G->f, G->r_edx, 0x4000); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -4)); + x86_mov_reg_imm(&G->f, G->r_edx, 0x4000); for (i = 0; i < 4; i++) { - x87_fld (&G->f, x86_make_disp (G->r_esp, a->param[0] + 4 + i * 4)); - x87_fcomp (&G->f, x86_make_disp (G->r_esp, a->param[1] + 4 + i * 4)); - x87_fnstsw (&G->f, G->r_eax); - x86_and (&G->f, G->r_edx, G->r_eax); + x87_fld(&G->f, x86_make_disp(G->r_esp, a->param[0] + 4 + i * 4)); + x87_fcomp(&G->f, x86_make_disp(G->r_esp, a->param[1] + 4 + i * 4)); + x87_fnstsw(&G->f, G->r_eax); + x86_and(&G->f, G->r_edx, G->r_eax); } /* TODO: use test r8,imm8 */ - x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000); - x86_test (&G->f, G->r_edx, G->r_ecx); + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_edx, G->r_ecx); { GLubyte *lab0, *lab1; /* TODO: use jcc rel8 */ - lab0 = x86_jcc_forward (&G->f, cc_E); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE); + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); /* TODO: use jmp rel8 */ - lab1 = x86_jmp_forward (&G->f); - x86_fixup_fwd_jump (&G->f, lab0); - x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO); - x86_fixup_fwd_jump (&G->f, lab1); - x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx); + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); } break; default: - assert (0); + _mesa_problem(NULL, "Unexpected switch case in codegen_assem"); } } -GLboolean _slang_x86_codegen (slang_machine *mach, slang_assembly_file *file, GLuint start) +GLboolean +_slang_x86_codegen(slang_machine * mach, slang_assembly_file * file, + GLuint start) { - codegen_ctx G; - GLubyte *j_body, *j_exit; - GLuint i; + codegen_ctx G; + GLubyte *j_body, *j_exit; + GLuint i; /* Free the old code - if any. */ if (mach->x86.compiled_func != NULL) { - _mesa_exec_free (mach->x86.compiled_func); + _mesa_exec_free(mach->x86.compiled_func); mach->x86.compiled_func = NULL; } - /* - * We need as much as 1M because *all* assembly, including built-in library, is - * being translated to x86. - * The built-in library occupies 450K, so we can be safe for now. - * It is going to change in the future, when we get assembly analysis running. - */ - x86_init_func_size (&G.f, 1048576); - G.r_eax = x86_make_reg (file_REG32, reg_AX); - G.r_ecx = x86_make_reg (file_REG32, reg_CX); - G.r_edx = x86_make_reg (file_REG32, reg_DX); - G.r_ebx = x86_make_reg (file_REG32, reg_BX); - G.r_esp = x86_make_reg (file_REG32, reg_SP); - G.r_ebp = x86_make_reg (file_REG32, reg_BP); - G.r_st0 = x86_make_reg (file_x87, 0); - G.r_st1 = x86_make_reg (file_x87, 1); - G.r_st2 = x86_make_reg (file_x87, 2); - G.r_st3 = x86_make_reg (file_x87, 3); - G.r_st4 = x86_make_reg (file_x87, 4); - G.fixups = NULL; - G.fixup_count = 0; - G.labels = (GLubyte **) slang_alloc_malloc (file->count * sizeof (GLubyte *)); - G.mach = mach; - G.fpucntl = RESTORE_FPU; - - mach->x86.fpucntl_rnd_neg = RND_NEG_FPU; - mach->x86.fpucntl_restore = RESTORE_FPU; - - /* prepare stack and jump to start */ - x86_push (&G.f, G.r_ebp); - x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore); - x86_push (&G.f, G.r_esp); - x86_pop (&G.f, G.r_ecx); - x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx); - j_body = x86_jmp_forward (&G.f); - - /* "discard" instructions jump to this label */ - G.l_discard = x86_get_label (&G.f); - x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->kill); - x86_mov_reg_imm (&G.f, G.r_ecx, 1); - x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx); - G.l_exit = x86_get_label (&G.f); - j_exit = x86_jmp_forward (&G.f); - - for (i = 0; i < file->count; i++) - { - G.labels[i] = x86_get_label (&G.f); - if (i == start) - x86_fixup_fwd_jump (&G.f, j_body); - codegen_assem (&G, &file->code[i], &mach->infolog); - } - - /* - * Restore stack and return. - * This must be handled this way, because "discard" can be invoked from any - * place in the code. - */ - x86_fixup_fwd_jump (&G.f, j_exit); - x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore); - x86_mov (&G.f, G.r_esp, x86_deref (G.r_eax)); - x86_pop (&G.f, G.r_ebp); - if (G.fpucntl != RESTORE_FPU) - { - x87_fnclex (&G.f); - x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->x86.fpucntl_restore); - x87_fldcw (&G.f, x86_deref (G.r_eax)); - } - x86_ret (&G.f); - - /* fixup forward labels */ - for (i = 0; i < G.fixup_count; i++) - { - G.f.csr = G.labels[G.fixups[i].index]; - x86_fixup_fwd_jump (&G.f, G.fixups[i].csr); - } - - slang_alloc_free (G.fixups); - slang_alloc_free (G.labels); - - /* install new code */ - mach->x86.compiled_func = (GLvoid (*) (slang_machine *)) x86_get_func (&G.f); - - return GL_TRUE; + /* + * We need as much as 1M because *all* assembly, including built-in library, is + * being translated to x86. + * The built-in library occupies 450K, so we can be safe for now. + * It is going to change in the future, when we get assembly analysis running. + */ + x86_init_func_size(&G.f, 1048576); + G.r_eax = x86_make_reg(file_REG32, reg_AX); + G.r_ecx = x86_make_reg(file_REG32, reg_CX); + G.r_edx = x86_make_reg(file_REG32, reg_DX); + G.r_ebx = x86_make_reg(file_REG32, reg_BX); + G.r_esp = x86_make_reg(file_REG32, reg_SP); + G.r_ebp = x86_make_reg(file_REG32, reg_BP); + G.r_st0 = x86_make_reg(file_x87, 0); + G.r_st1 = x86_make_reg(file_x87, 1); + G.r_st2 = x86_make_reg(file_x87, 2); + G.r_st3 = x86_make_reg(file_x87, 3); + G.r_st4 = x86_make_reg(file_x87, 4); + G.fixups = NULL; + G.fixup_count = 0; + G.labels = + (GLubyte **) slang_alloc_malloc(file->count * sizeof(GLubyte *)); + G.mach = mach; + G.fpucntl = RESTORE_FPU; + + mach->x86.fpucntl_rnd_neg = RND_NEG_FPU; + mach->x86.fpucntl_restore = RESTORE_FPU; + + /* prepare stack and jump to start */ + x86_push(&G.f, G.r_ebp); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & mach->x86.esp_restore); + x86_push(&G.f, G.r_esp); + x86_pop(&G.f, G.r_ecx); + x86_mov(&G.f, x86_deref(G.r_eax), G.r_ecx); + j_body = x86_jmp_forward(&G.f); + + /* "discard" instructions jump to this label */ + G.l_discard = x86_get_label(&G.f); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & G.mach->kill); + x86_mov_reg_imm(&G.f, G.r_ecx, 1); + x86_mov(&G.f, x86_deref(G.r_eax), G.r_ecx); + G.l_exit = x86_get_label(&G.f); + j_exit = x86_jmp_forward(&G.f); + + for (i = 0; i < file->count; i++) { + G.labels[i] = x86_get_label(&G.f); + if (i == start) + x86_fixup_fwd_jump(&G.f, j_body); + codegen_assem(&G, &file->code[i], &mach->infolog); + } + + /* + * Restore stack and return. + * This must be handled this way, because "discard" can be invoked from any + * place in the code. + */ + x86_fixup_fwd_jump(&G.f, j_exit); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & mach->x86.esp_restore); + x86_mov(&G.f, G.r_esp, x86_deref(G.r_eax)); + x86_pop(&G.f, G.r_ebp); + if (G.fpucntl != RESTORE_FPU) { + x87_fnclex(&G.f); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & G.mach->x86.fpucntl_restore); + x87_fldcw(&G.f, x86_deref(G.r_eax)); + } + x86_ret(&G.f); + + /* fixup forward labels */ + for (i = 0; i < G.fixup_count; i++) { + G.f.csr = G.labels[G.fixups[i].index]; + x86_fixup_fwd_jump(&G.f, G.fixups[i].csr); + } + + slang_alloc_free(G.fixups); + slang_alloc_free(G.labels); + + /* install new code */ + mach->x86.compiled_func = (GLvoid(*)(slang_machine *)) x86_get_func(&G.f); + + return GL_TRUE; } #endif - |