freedreno/ir3: fix register usage calculations
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_tgsi_action.c
index 8caaf83c79281230ca541ef6f91c2c38016e68ee..9cb42b237b7c632b53b6233273b4158d4753bdd2 100644 (file)
@@ -2,7 +2,7 @@
  * 
  * Copyright 2011-2012 Advanced Micro Devices, Inc.
  * Copyright 2009 VMware, Inc.
- * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007-2008 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -20,7 +20,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -691,39 +691,30 @@ const struct lp_build_tgsi_action scs_action = {
    scs_emit     /* emit */
 };
 
-/* TGSI_OPCODE_SFL */
-
+/* TGSI_OPCODE_SUB */
 static void
-sfl_emit(
+sub_emit(
    const struct lp_build_tgsi_action * action,
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = bld_base->base.zero;
+   emit_data->output[emit_data->chan] =
+      LLVMBuildFSub(bld_base->base.gallivm->builder,
+                    emit_data->args[0],
+                    emit_data->args[1], "");
 }
 
-/* TGSI_OPCODE_STR */
-
+/* TGSI_OPCODE_F2U */
 static void
-str_emit(
+f2u_emit(
    const struct lp_build_tgsi_action * action,
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = bld_base->base.one;
-}
-
-/* TGSI_OPCODE_SUB */
-static void
-sub_emit(
-   const struct lp_build_tgsi_action * action,
-   struct lp_build_tgsi_context * bld_base,
-   struct lp_build_emit_data * emit_data)
-{
-       emit_data->output[emit_data->chan] = LLVMBuildFSub(
-                               bld_base->base.gallivm->builder,
-                               emit_data->args[0],
-                               emit_data->args[1], "");
+   emit_data->output[emit_data->chan] =
+      LLVMBuildFPToUI(bld_base->base.gallivm->builder,
+                      emit_data->args[0],
+                      bld_base->base.int_vec_type, "");
 }
 
 /* TGSI_OPCODE_U2F */
@@ -733,9 +724,10 @@ u2f_emit(
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = LLVMBuildUIToFP(bld_base->base.gallivm->builder,
-                                                       emit_data->args[0],
-                                                       bld_base->base.vec_type, "");
+   emit_data->output[emit_data->chan] =
+      LLVMBuildUIToFP(bld_base->base.gallivm->builder,
+                      emit_data->args[0],
+                      bld_base->base.vec_type, "");
 }
 
 static void
@@ -944,11 +936,10 @@ lp_set_default_actions(struct lp_build_tgsi_context * bld_base)
    bld_base->op_actions[TGSI_OPCODE_MUL].emit = mul_emit;
    bld_base->op_actions[TGSI_OPCODE_DIV].emit = fdiv_emit;
    bld_base->op_actions[TGSI_OPCODE_RCP].emit = rcp_emit;
-   bld_base->op_actions[TGSI_OPCODE_SFL].emit = sfl_emit;
-   bld_base->op_actions[TGSI_OPCODE_STR].emit = str_emit;
    bld_base->op_actions[TGSI_OPCODE_SUB].emit = sub_emit;
 
    bld_base->op_actions[TGSI_OPCODE_UARL].emit = mov_emit;
+   bld_base->op_actions[TGSI_OPCODE_F2U].emit = f2u_emit;
    bld_base->op_actions[TGSI_OPCODE_U2F].emit = u2f_emit;
    bld_base->op_actions[TGSI_OPCODE_UMAD].emit = umad_emit;
    bld_base->op_actions[TGSI_OPCODE_UMUL].emit = umul_emit;
@@ -1066,24 +1057,6 @@ ucmp_emit_cpu(
                       cond, emit_data->args[1], emit_data->args[2]);
 }
 
-
-/* TGSI_OPCODE_CND (CPU Only) */
-static void
-cnd_emit_cpu(
-   const struct lp_build_tgsi_action * action,
-   struct lp_build_tgsi_context * bld_base,
-   struct lp_build_emit_data * emit_data)
-{
-   LLVMValueRef half, tmp;
-   half = lp_build_const_vec(bld_base->base.gallivm, bld_base->base.type, 0.5);
-   tmp = lp_build_cmp(&bld_base->base, PIPE_FUNC_GREATER,
-                      emit_data->args[2], half);
-   emit_data->output[emit_data->chan] = lp_build_select(&bld_base->base,
-                                          tmp,
-                                          emit_data->args[0],
-                                          emit_data->args[1]);
-}
-
 /* TGSI_OPCODE_COS (CPU Only) */
 static void
 cos_emit_cpu(
@@ -1128,18 +1101,6 @@ f2i_emit_cpu(
                                                         emit_data->args[0]);
 }
 
-/* TGSI_OPCODE_F2U (CPU Only) */
-static void
-f2u_emit_cpu(
-   const struct lp_build_tgsi_action * action,
-   struct lp_build_tgsi_context * bld_base,
-   struct lp_build_emit_data * emit_data)
-{
-   /* FIXME: implement and use lp_build_utrunc() */
-   emit_data->output[emit_data->chan] = lp_build_itrunc(&bld_base->base,
-                                                        emit_data->args[0]);
-}
-
 /* TGSI_OPCODE_FSET Helper (CPU Only) */
 static void
 fset_emit_cpu(
@@ -1245,8 +1206,24 @@ idiv_emit_cpu(
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = lp_build_div(&bld_base->int_bld,
-                                   emit_data->args[0], emit_data->args[1]);
+   LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+   LLVMValueRef div_mask = lp_build_cmp(&bld_base->uint_bld,
+                                        PIPE_FUNC_EQUAL, emit_data->args[1],
+                                        bld_base->uint_bld.zero);
+   /* We want to make sure that we never divide/mod by zero to not
+    * generate sigfpe. We don't want to crash just because the
+    * shader is doing something weird. */
+   LLVMValueRef divisor = LLVMBuildOr(builder,
+                                      div_mask,
+                                      emit_data->args[1], "");
+   LLVMValueRef result = lp_build_div(&bld_base->int_bld,
+                                      emit_data->args[0], divisor);
+   LLVMValueRef not_div_mask = LLVMBuildNot(builder,
+                                            div_mask,"");
+   /* idiv by zero doesn't have a guaranteed return value chose 0 for now. */
+   emit_data->output[emit_data->chan] = LLVMBuildAnd(builder,
+                                                     not_div_mask,
+                                                     result, "");
 }
 
 /* TGSI_OPCODE_INEG (CPU Only) */
@@ -1672,15 +1649,15 @@ udiv_emit_cpu(
    LLVMValueRef div_mask = lp_build_cmp(&bld_base->uint_bld,
                                         PIPE_FUNC_EQUAL, emit_data->args[1],
                                         bld_base->uint_bld.zero);
-   /* We want to make sure that we never divide/mod by zero to not 
-    * generate sigfpe. We don't want to crash just because the 
+   /* We want to make sure that we never divide/mod by zero to not
+    * generate sigfpe. We don't want to crash just because the
     * shader is doing something weird. */
    LLVMValueRef divisor = LLVMBuildOr(builder,
                                       div_mask,
                                       emit_data->args[1], "");
    LLVMValueRef result = lp_build_div(&bld_base->uint_bld,
                                       emit_data->args[0], divisor);
-   /* udiv by zero is guaranteed to return 0xffffffff */
+   /* udiv by zero is guaranteed to return 0xffffffff at least with d3d10 */
    emit_data->output[emit_data->chan] = LLVMBuildOr(builder,
                                                     div_mask,
                                                     result, "");
@@ -1826,13 +1803,11 @@ lp_set_default_actions_cpu(
    bld_base->op_actions[TGSI_OPCODE_ARL].emit = arl_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_ARR].emit = arr_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_CEIL].emit = ceil_emit_cpu;
-   bld_base->op_actions[TGSI_OPCODE_CND].emit = cnd_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_COS].emit = cos_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_CMP].emit = cmp_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_DIV].emit = div_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_EX2].emit = ex2_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_F2I].emit = f2i_emit_cpu;
-   bld_base->op_actions[TGSI_OPCODE_F2U].emit = f2u_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_FLR].emit = flr_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_FSEQ].emit = fseq_emit_cpu;
    bld_base->op_actions[TGSI_OPCODE_FSGE].emit = fsge_emit_cpu;