diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2018-01-04 16:49:29 -0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2018-01-31 05:30:50 -0800 |
commit | b49572d3736bebcf0420178e8b694bb6f1a1a3d8 (patch) | |
tree | edc96fe107e911fe5c1b4ef1ba3c139822bff83b /target/hppa | |
parent | 2330504ceec94e2cfa1138e5b256b5e1b4a1b444 (diff) |
target/hppa: Implement a pause instruction
This is an extension to the base ISA, but we can use this in
the kernel idle loop to reduce the host cpu time consumed.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/hppa')
-rw-r--r-- | target/hppa/translate.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 2f8e87bba9..96cbd29d4d 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2826,9 +2826,45 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, DISAS_NEXT); } +#ifndef CONFIG_USER_ONLY +/* These are QEMU extensions and are nops in the real architecture: + * + * or %r10,%r10,%r10 -- idle loop; wait for interrupt + * or %r31,%r31,%r31 -- death loop; offline cpu + * currently implemented as idle. + */ +static DisasJumpType trans_pause(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + TCGv_i32 tmp; + + /* No need to check for supervisor, as userland can only pause + until the next timer interrupt. */ + nullify_over(ctx); + + /* Advance the instruction queue. */ + copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b); + copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var); + nullify_set(ctx, 0); + + /* Tell the qemu main loop to halt until this cpu has work. */ + tmp = tcg_const_i32(1); + tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) + + offsetof(CPUState, halted)); + tcg_temp_free_i32(tmp); + gen_excp_1(EXCP_HALTED); + + return nullify_end(ctx, DISAS_NORETURN); +} +#endif + static const DisasInsn table_arith_log[] = { { 0x08000240u, 0xfc00ffffu, trans_nop }, /* or x,y,0 */ { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */ +#ifndef CONFIG_USER_ONLY + { 0x094a024au, 0xffffffffu, trans_pause }, /* or r10,r10,r10 */ + { 0x0bff025fu, 0xffffffffu, trans_pause }, /* or r31,r31,r31 */ +#endif { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg }, { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg }, { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg }, |