target-arm: Don't halt on WFI unless we don't have any work
authorPeter Maydell <peter.maydell@linaro.org>
Fri, 29 May 2015 10:28:53 +0000 (11:28 +0100)
committerPeter Maydell <peter.maydell@linaro.org>
Fri, 29 May 2015 10:28:53 +0000 (11:28 +0100)
Just NOP the WFI instruction if we have work to do.
This doesn't make much difference currently (though it does avoid
jumping out to the top level loop and immediately restarting),
but the distinction between "halt" and "don't halt" will become
more important when the decision to halt requires us to trap
to a higher exception level instead.

Suggested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
target-arm/op_helper.c
target-arm/translate-a64.c
target-arm/translate.c

index 79e7d1005563b9a7c103e314769d6c307d1eee10..0ea4ed4bae41255869e9290947d931ed0f9ae500 100644 (file)
@@ -252,6 +252,13 @@ void HELPER(wfi)(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
 
+    if (cpu_has_work(cs)) {
+        /* Don't bother to go into our "low power state" if
+         * we would just wake up immediately.
+         */
+        return;
+    }
+
     cs->exception_index = EXCP_HLT;
     cs->halted = 1;
     cpu_loop_exit(cs);
index 8d08ccdf6a040ae6e84f5b6b401bbe27f90c12a9..ffa6cb8e56f274683193881eba66f557d1e38c17 100644 (file)
@@ -11113,6 +11113,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
              */
             gen_a64_set_pc_im(dc->pc);
             gen_helper_wfi(cpu_env);
+            /* The helper doesn't necessarily throw an exception, but we
+             * must go back to the main loop to check for interrupts anyway.
+             */
+            tcg_gen_exit_tb(0);
             break;
         }
     }
index ed2c43d235f51cd211f9b723215204c22c814f45..6493b9a523b1df0a86e93779887c72a692e9fe83 100644 (file)
@@ -11351,6 +11351,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
             break;
         case DISAS_WFI:
             gen_helper_wfi(cpu_env);
+            /* The helper doesn't necessarily throw an exception, but we
+             * must go back to the main loop to check for interrupts anyway.
+             */
+            tcg_gen_exit_tb(0);
             break;
         case DISAS_WFE:
             gen_helper_wfe(cpu_env);