target/ppc: Move sleep & friends to decodetree
Convert the following instructions to decode tree specification: doze nap sleep rvwinkle stop The functionality was tested by comparing the qemu -D log -d op,in_asm output as well as single stepping gdb to confirm behavior was not changed for ISA3.x (stop) as well as ISA206 (doze, nap, sleep, rvwinkle). Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com> Signed-off-by: Chinmay Rath <rathc@linux.ibm.com> Tested-by: Aniket Sahu <asahu1x@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260827133010.278889-19-rathc@linux.ibm.com Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Ojaswin Mujoo committed
Aug 27, 2026 at 18:59 UTC
453b78afa9b0c5a09bf3e1618a1c33bb9cf482b4
3 files changed
+108
-85
target/ppc/insn32.decode
+8
@@ -913,6 +913,14 @@ VPERMR 000100 ..... ..... ..... ..... 111011 @VA
913
914
VSEL 000100 ..... ..... ..... ..... 101010 @VA
915
916
+## Power Management Instructions
917
+
918
+DOZE 010011 ----- ----- ----- 0110010010 -
919
+NAP 010011 ----- ----- ----- 0110110010 -
920
+SLEEP 010011 ----- ----- ----- 0111010010 -
921
+RVWINKLE 010011 ----- ----- ----- 0111110010 -
922
+STOP 010011 ----- ----- ----- 0101110010 -
923
+
924
## Vector Integer Shift Instruction
925
926
VSLB 000100 ..... ..... ..... 00100000100 @VX
target/ppc/translate.c
-85
@@ -2728,86 +2728,6 @@ static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
2728
#endif
2729
2730
#if defined(TARGET_PPC64)
2731
-static void gen_doze(DisasContext *ctx)
2732
-{
2733
-#if defined(CONFIG_USER_ONLY)
2734
- GEN_PRIV(ctx);
2735
-#else
2736
- TCGv_i32 t;
2737
-
2738
- CHK_HV(ctx);
2739
- translator_io_start(&ctx->base);
2740
- t = tcg_constant_i32(PPC_PM_DOZE);
2741
- gen_helper_pminsn(tcg_env, t);
2742
- /* Stop translation, as the CPU is supposed to sleep from now */
2743
- gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2744
-#endif /* defined(CONFIG_USER_ONLY) */
2745
-}
2746
-
2747
-static void gen_nap(DisasContext *ctx)
2748
-{
2749
-#if defined(CONFIG_USER_ONLY)
2750
- GEN_PRIV(ctx);
2751
-#else
2752
- TCGv_i32 t;
2753
-
2754
- CHK_HV(ctx);
2755
- translator_io_start(&ctx->base);
2756
- t = tcg_constant_i32(PPC_PM_NAP);
2757
- gen_helper_pminsn(tcg_env, t);
2758
- /* Stop translation, as the CPU is supposed to sleep from now */
2759
- gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2760
-#endif /* defined(CONFIG_USER_ONLY) */
2761
-}
2762
-
2763
-static void gen_stop(DisasContext *ctx)
2764
-{
2765
-#if defined(CONFIG_USER_ONLY)
2766
- GEN_PRIV(ctx);
2767
-#else
2768
- TCGv_i32 t;
2769
-
2770
- CHK_HV(ctx);
2771
- translator_io_start(&ctx->base);
2772
- t = tcg_constant_i32(PPC_PM_STOP);
2773
- gen_helper_pminsn(tcg_env, t);
2774
- /* Stop translation, as the CPU is supposed to sleep from now */
2775
- gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2776
-#endif /* defined(CONFIG_USER_ONLY) */
2777
-}
2778
-
2779
-static void gen_sleep(DisasContext *ctx)
2780
-{
2781
-#if defined(CONFIG_USER_ONLY)
2782
- GEN_PRIV(ctx);
2783
-#else
2784
- TCGv_i32 t;
2785
-
2786
- CHK_HV(ctx);
2787
- translator_io_start(&ctx->base);
2788
- t = tcg_constant_i32(PPC_PM_SLEEP);
2789
- gen_helper_pminsn(tcg_env, t);
2790
- /* Stop translation, as the CPU is supposed to sleep from now */
2791
- gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2792
-#endif /* defined(CONFIG_USER_ONLY) */
2793
-}
2794
-
2795
-static void gen_rvwinkle(DisasContext *ctx)
2796
-{
2797
-#if defined(CONFIG_USER_ONLY)
2798
- GEN_PRIV(ctx);
2799
-#else
2800
- TCGv_i32 t;
2801
-
2802
- CHK_HV(ctx);
2803
- translator_io_start(&ctx->base);
2804
- t = tcg_constant_i32(PPC_PM_RVWINKLE);
2805
- gen_helper_pminsn(tcg_env, t);
2806
- /* Stop translation, as the CPU is supposed to sleep from now */
2807
- gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2808
-#endif /* defined(CONFIG_USER_ONLY) */
2809
-}
2810
-
2731
static inline TCGv gen_write_bhrb(TCGv_ptr base, TCGv offset, TCGv mask, TCGv value)
2732
{
2733
TCGv_ptr tmp = tcg_temp_new_ptr();
@@ -5104,11 +5024,6 @@ GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
5024
GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
5025
GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300),
5026
#endif
5107
-GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
5108
-GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
5109
-GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
5110
-GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
5111
-GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
5027
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
5028
#endif
5029
/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
target/ppc/translate/processor-ctrl-impl.c.inc
+100
@@ -103,3 +103,103 @@ static bool trans_MSGSYNC(DisasContext *ctx, arg_MSGSYNC *a)
103
/* interpreted as no-op */
104
return true;
105
}
106
+
107
+static bool do_doze(DisasContext *ctx, arg_DOZE *a)
108
+{
109
+ REQUIRE_64BIT(ctx);
110
+
111
+#if defined(CONFIG_USER_ONLY)
112
+ gen_priv_opc(ctx);
113
+#else
114
+ TCGv_i32 t;
115
+
116
+ REQUIRE_HV(ctx);
117
+ translator_io_start(&ctx->base);
118
+ t = tcg_constant_i32(PPC_PM_DOZE);
119
+ gen_helper_pminsn(tcg_env, t);
120
+ /* Stop translation, as the CPU is supposed to sleep from now */
121
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
122
+#endif /* defined(CONFIG_USER_ONLY) */
123
+ return true;
124
+}
125
+TRANS_FLAGS2(PM_ISA206, DOZE, do_doze);
126
+
127
+static bool do_nap(DisasContext *ctx, arg_NAP *a)
128
+{
129
+ REQUIRE_64BIT(ctx);
130
+
131
+#if defined(CONFIG_USER_ONLY)
132
+ gen_priv_opc(ctx);
133
+#else
134
+ TCGv_i32 t;
135
+
136
+ REQUIRE_HV(ctx);
137
+ translator_io_start(&ctx->base);
138
+ t = tcg_constant_i32(PPC_PM_NAP);
139
+ gen_helper_pminsn(tcg_env, t);
140
+ /* Stop translation, as the CPU is supposed to sleep from now */
141
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
142
+#endif /* defined(CONFIG_USER_ONLY) */
143
+ return true;
144
+}
145
+TRANS_FLAGS2(PM_ISA206, NAP, do_nap);
146
+
147
+static bool do_sleep(DisasContext *ctx, arg_SLEEP *a)
148
+{
149
+ REQUIRE_64BIT(ctx);
150
+
151
+#if defined(CONFIG_USER_ONLY)
152
+ gen_priv_opc(ctx);
153
+#else
154
+ TCGv_i32 t;
155
+
156
+ REQUIRE_HV(ctx);
157
+ translator_io_start(&ctx->base);
158
+ t = tcg_constant_i32(PPC_PM_SLEEP);
159
+ gen_helper_pminsn(tcg_env, t);
160
+ /* Stop translation, as the CPU is supposed to sleep from now */
161
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
162
+#endif /* defined(CONFIG_USER_ONLY) */
163
+ return true;
164
+}
165
+TRANS_FLAGS2(PM_ISA206, SLEEP, do_sleep);
166
+
167
+static bool do_rvwinkle(DisasContext *ctx, arg_RVWINKLE *a)
168
+{
169
+ REQUIRE_64BIT(ctx);
170
+
171
+#if defined(CONFIG_USER_ONLY)
172
+ gen_priv_opc(ctx);
173
+#else
174
+ TCGv_i32 t;
175
+
176
+ REQUIRE_HV(ctx);
177
+ translator_io_start(&ctx->base);
178
+ t = tcg_constant_i32(PPC_PM_RVWINKLE);
179
+ gen_helper_pminsn(tcg_env, t);
180
+ /* Stop translation, as the CPU is supposed to sleep from now */
181
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
182
+#endif /* defined(CONFIG_USER_ONLY) */
183
+ return true;
184
+}
185
+TRANS_FLAGS2(PM_ISA206, RVWINKLE, do_rvwinkle);
186
+
187
+static bool do_stop(DisasContext *ctx, arg_STOP *a)
188
+{
189
+ REQUIRE_64BIT(ctx);
190
+
191
+#if defined(CONFIG_USER_ONLY)
192
+ gen_priv_opc(ctx);
193
+#else
194
+ TCGv_i32 t;
195
+
196
+ REQUIRE_HV(ctx);
197
+ translator_io_start(&ctx->base);
198
+ t = tcg_constant_i32(PPC_PM_STOP);
199
+ gen_helper_pminsn(tcg_env, t);
200
+ /* Stop translation, as the CPU is supposed to sleep from now */
201
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
202
+#endif /* defined(CONFIG_USER_ONLY) */
203
+ return true;
204
+}
205
+TRANS_FLAGS2(ISA300, STOP, do_stop);