xref: /openbmc/qemu/target/hppa/translate.c (revision 922582ace2df59572a671f5c0c5c6c5c706995e5)
1  /*
2   * HPPA emulation cpu translation for qemu.
3   *
4   * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
5   *
6   * This library is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU Lesser General Public
8   * License as published by the Free Software Foundation; either
9   * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  #include "qemu/osdep.h"
21  #include "cpu.h"
22  #include "qemu/host-utils.h"
23  #include "exec/exec-all.h"
24  #include "exec/page-protection.h"
25  #include "tcg/tcg-op.h"
26  #include "tcg/tcg-op-gvec.h"
27  #include "exec/helper-proto.h"
28  #include "exec/helper-gen.h"
29  #include "exec/translator.h"
30  #include "exec/log.h"
31  
32  #define HELPER_H "helper.h"
33  #include "exec/helper-info.c.inc"
34  #undef  HELPER_H
35  
36  /* Choose to use explicit sizes within this file. */
37  #undef tcg_temp_new
38  
39  typedef struct DisasCond {
40      TCGCond c;
41      TCGv_i64 a0, a1;
42  } DisasCond;
43  
44  typedef struct DisasIAQE {
45      /* IASQ; may be null for no change from TB. */
46      TCGv_i64 space;
47      /* IAOQ base; may be null for relative address. */
48      TCGv_i64 base;
49      /* IAOQ addend; if base is null, relative to cpu_iaoq_f. */
50      int64_t disp;
51  } DisasIAQE;
52  
53  typedef struct DisasDelayException {
54      struct DisasDelayException *next;
55      TCGLabel *lab;
56      uint32_t insn;
57      bool set_iir;
58      int8_t set_n;
59      uint8_t excp;
60      /* Saved state at parent insn. */
61      DisasIAQE iaq_f, iaq_b;
62  } DisasDelayException;
63  
64  typedef struct DisasContext {
65      DisasContextBase base;
66      CPUState *cs;
67  
68      /* IAQ_Front, IAQ_Back. */
69      DisasIAQE iaq_f, iaq_b;
70      /* IAQ_Next, for jumps, otherwise null for simple advance. */
71      DisasIAQE iaq_j, *iaq_n;
72  
73      /* IAOQ_Front at entry to TB. */
74      uint64_t iaoq_first;
75  
76      DisasCond null_cond;
77      TCGLabel *null_lab;
78  
79      DisasDelayException *delay_excp_list;
80      TCGv_i64 zero;
81  
82      uint32_t insn;
83      uint32_t tb_flags;
84      int mmu_idx;
85      int privilege;
86      uint32_t psw_xb;
87      bool psw_n_nonzero;
88      bool psw_b_next;
89      bool is_pa20;
90      bool insn_start_updated;
91  
92  #ifdef CONFIG_USER_ONLY
93      MemOp unalign;
94  #endif
95  } DisasContext;
96  
97  #ifdef CONFIG_USER_ONLY
98  #define UNALIGN(C)       (C)->unalign
99  #define MMU_DISABLED(C)  false
100  #else
101  #define UNALIGN(C)       MO_ALIGN
102  #define MMU_DISABLED(C)  MMU_IDX_MMU_DISABLED((C)->mmu_idx)
103  #endif
104  
105  /* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
expand_sm_imm(DisasContext * ctx,int val)106  static int expand_sm_imm(DisasContext *ctx, int val)
107  {
108      /* Keep unimplemented bits disabled -- see cpu_hppa_put_psw. */
109      if (ctx->is_pa20) {
110          if (val & PSW_SM_W) {
111              val |= PSW_W;
112          }
113          val &= ~(PSW_SM_W | PSW_SM_E | PSW_G);
114      } else {
115          val &= ~(PSW_SM_W | PSW_SM_E | PSW_O);
116      }
117      return val;
118  }
119  
120  /* Inverted space register indicates 0 means sr0 not inferred from base.  */
expand_sr3x(DisasContext * ctx,int val)121  static int expand_sr3x(DisasContext *ctx, int val)
122  {
123      return ~val;
124  }
125  
126  /* Convert the M:A bits within a memory insn to the tri-state value
127     we use for the final M.  */
ma_to_m(DisasContext * ctx,int val)128  static int ma_to_m(DisasContext *ctx, int val)
129  {
130      return val & 2 ? (val & 1 ? -1 : 1) : 0;
131  }
132  
133  /* Convert the sign of the displacement to a pre or post-modify.  */
pos_to_m(DisasContext * ctx,int val)134  static int pos_to_m(DisasContext *ctx, int val)
135  {
136      return val ? 1 : -1;
137  }
138  
neg_to_m(DisasContext * ctx,int val)139  static int neg_to_m(DisasContext *ctx, int val)
140  {
141      return val ? -1 : 1;
142  }
143  
144  /* Used for branch targets and fp memory ops.  */
expand_shl2(DisasContext * ctx,int val)145  static int expand_shl2(DisasContext *ctx, int val)
146  {
147      return val << 2;
148  }
149  
150  /* Used for assemble_21.  */
expand_shl11(DisasContext * ctx,int val)151  static int expand_shl11(DisasContext *ctx, int val)
152  {
153      return val << 11;
154  }
155  
assemble_6(DisasContext * ctx,int val)156  static int assemble_6(DisasContext *ctx, int val)
157  {
158      /*
159       * Officially, 32 * x + 32 - y.
160       * Here, x is already in bit 5, and y is [4:0].
161       * Since -y = ~y + 1, in 5 bits 32 - y => y ^ 31 + 1,
162       * with the overflow from bit 4 summing with x.
163       */
164      return (val ^ 31) + 1;
165  }
166  
167  /* Expander for assemble_16a(s,cat(im10a,0),i). */
expand_11a(DisasContext * ctx,int val)168  static int expand_11a(DisasContext *ctx, int val)
169  {
170      /*
171       * @val is bit 0 and bits [4:15].
172       * Swizzle thing around depending on PSW.W.
173       */
174      int im10a = extract32(val, 1, 10);
175      int s = extract32(val, 11, 2);
176      int i = (-(val & 1) << 13) | (im10a << 3);
177  
178      if (ctx->tb_flags & PSW_W) {
179          i ^= s << 13;
180      }
181      return i;
182  }
183  
184  /* Expander for assemble_16a(s,im11a,i). */
expand_12a(DisasContext * ctx,int val)185  static int expand_12a(DisasContext *ctx, int val)
186  {
187      /*
188       * @val is bit 0 and bits [3:15].
189       * Swizzle thing around depending on PSW.W.
190       */
191      int im11a = extract32(val, 1, 11);
192      int s = extract32(val, 12, 2);
193      int i = (-(val & 1) << 13) | (im11a << 2);
194  
195      if (ctx->tb_flags & PSW_W) {
196          i ^= s << 13;
197      }
198      return i;
199  }
200  
201  /* Expander for assemble_16(s,im14). */
expand_16(DisasContext * ctx,int val)202  static int expand_16(DisasContext *ctx, int val)
203  {
204      /*
205       * @val is bits [0:15], containing both im14 and s.
206       * Swizzle thing around depending on PSW.W.
207       */
208      int s = extract32(val, 14, 2);
209      int i = (-(val & 1) << 13) | extract32(val, 1, 13);
210  
211      if (ctx->tb_flags & PSW_W) {
212          i ^= s << 13;
213      }
214      return i;
215  }
216  
217  /* The sp field is only present with !PSW_W. */
sp0_if_wide(DisasContext * ctx,int sp)218  static int sp0_if_wide(DisasContext *ctx, int sp)
219  {
220      return ctx->tb_flags & PSW_W ? 0 : sp;
221  }
222  
223  /* Translate CMPI doubleword conditions to standard. */
cmpbid_c(DisasContext * ctx,int val)224  static int cmpbid_c(DisasContext *ctx, int val)
225  {
226      return val ? val : 4; /* 0 == "*<<" */
227  }
228  
229  /*
230   * In many places pa1.x did not decode the bit that later became
231   * the pa2.0 D bit.  Suppress D unless the cpu is pa2.0.
232   */
pa20_d(DisasContext * ctx,int val)233  static int pa20_d(DisasContext *ctx, int val)
234  {
235      return ctx->is_pa20 & val;
236  }
237  
238  /* Include the auto-generated decoder.  */
239  #include "decode-insns.c.inc"
240  
241  /* We are not using a goto_tb (for whatever reason), but have updated
242     the iaq (for whatever reason), so don't do it again on exit.  */
243  #define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
244  
245  /* We are exiting the TB, but have neither emitted a goto_tb, nor
246     updated the iaq for the next instruction to be executed.  */
247  #define DISAS_IAQ_N_STALE    DISAS_TARGET_1
248  
249  /* Similarly, but we want to return to the main loop immediately
250     to recognize unmasked interrupts.  */
251  #define DISAS_IAQ_N_STALE_EXIT      DISAS_TARGET_2
252  #define DISAS_EXIT                  DISAS_TARGET_3
253  
254  /* global register indexes */
255  static TCGv_i64 cpu_gr[32];
256  static TCGv_i64 cpu_sr[4];
257  static TCGv_i64 cpu_srH;
258  static TCGv_i64 cpu_iaoq_f;
259  static TCGv_i64 cpu_iaoq_b;
260  static TCGv_i64 cpu_iasq_f;
261  static TCGv_i64 cpu_iasq_b;
262  static TCGv_i64 cpu_sar;
263  static TCGv_i64 cpu_psw_n;
264  static TCGv_i64 cpu_psw_v;
265  static TCGv_i64 cpu_psw_cb;
266  static TCGv_i64 cpu_psw_cb_msb;
267  static TCGv_i32 cpu_psw_xb;
268  
hppa_translate_init(void)269  void hppa_translate_init(void)
270  {
271  #define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
272  
273      typedef struct { TCGv_i64 *var; const char *name; int ofs; } GlobalVar;
274      static const GlobalVar vars[] = {
275          { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) },
276          DEF_VAR(psw_n),
277          DEF_VAR(psw_v),
278          DEF_VAR(psw_cb),
279          DEF_VAR(psw_cb_msb),
280          DEF_VAR(iaoq_f),
281          DEF_VAR(iaoq_b),
282      };
283  
284  #undef DEF_VAR
285  
286      /* Use the symbolic register names that match the disassembler.  */
287      static const char gr_names[32][4] = {
288          "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
289          "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
290          "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
291          "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
292      };
293      /* SR[4-7] are not global registers so that we can index them.  */
294      static const char sr_names[5][4] = {
295          "sr0", "sr1", "sr2", "sr3", "srH"
296      };
297  
298      int i;
299  
300      cpu_gr[0] = NULL;
301      for (i = 1; i < 32; i++) {
302          cpu_gr[i] = tcg_global_mem_new(tcg_env,
303                                         offsetof(CPUHPPAState, gr[i]),
304                                         gr_names[i]);
305      }
306      for (i = 0; i < 4; i++) {
307          cpu_sr[i] = tcg_global_mem_new_i64(tcg_env,
308                                             offsetof(CPUHPPAState, sr[i]),
309                                             sr_names[i]);
310      }
311      cpu_srH = tcg_global_mem_new_i64(tcg_env,
312                                       offsetof(CPUHPPAState, sr[4]),
313                                       sr_names[4]);
314  
315      for (i = 0; i < ARRAY_SIZE(vars); ++i) {
316          const GlobalVar *v = &vars[i];
317          *v->var = tcg_global_mem_new(tcg_env, v->ofs, v->name);
318      }
319  
320      cpu_psw_xb = tcg_global_mem_new_i32(tcg_env,
321                                          offsetof(CPUHPPAState, psw_xb),
322                                          "psw_xb");
323      cpu_iasq_f = tcg_global_mem_new_i64(tcg_env,
324                                          offsetof(CPUHPPAState, iasq_f),
325                                          "iasq_f");
326      cpu_iasq_b = tcg_global_mem_new_i64(tcg_env,
327                                          offsetof(CPUHPPAState, iasq_b),
328                                          "iasq_b");
329  }
330  
set_insn_breg(DisasContext * ctx,int breg)331  static void set_insn_breg(DisasContext *ctx, int breg)
332  {
333      assert(!ctx->insn_start_updated);
334      ctx->insn_start_updated = true;
335      tcg_set_insn_start_param(ctx->base.insn_start, 2, breg);
336  }
337  
cond_make_f(void)338  static DisasCond cond_make_f(void)
339  {
340      return (DisasCond){
341          .c = TCG_COND_NEVER,
342          .a0 = NULL,
343          .a1 = NULL,
344      };
345  }
346  
cond_make_t(void)347  static DisasCond cond_make_t(void)
348  {
349      return (DisasCond){
350          .c = TCG_COND_ALWAYS,
351          .a0 = NULL,
352          .a1 = NULL,
353      };
354  }
355  
cond_make_n(void)356  static DisasCond cond_make_n(void)
357  {
358      return (DisasCond){
359          .c = TCG_COND_NE,
360          .a0 = cpu_psw_n,
361          .a1 = tcg_constant_i64(0)
362      };
363  }
364  
cond_make_tt(TCGCond c,TCGv_i64 a0,TCGv_i64 a1)365  static DisasCond cond_make_tt(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
366  {
367      assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
368      return (DisasCond){ .c = c, .a0 = a0, .a1 = a1 };
369  }
370  
cond_make_ti(TCGCond c,TCGv_i64 a0,uint64_t imm)371  static DisasCond cond_make_ti(TCGCond c, TCGv_i64 a0, uint64_t imm)
372  {
373      return cond_make_tt(c, a0, tcg_constant_i64(imm));
374  }
375  
cond_make_vi(TCGCond c,TCGv_i64 a0,uint64_t imm)376  static DisasCond cond_make_vi(TCGCond c, TCGv_i64 a0, uint64_t imm)
377  {
378      TCGv_i64 tmp = tcg_temp_new_i64();
379      tcg_gen_mov_i64(tmp, a0);
380      return cond_make_ti(c, tmp, imm);
381  }
382  
cond_make_vv(TCGCond c,TCGv_i64 a0,TCGv_i64 a1)383  static DisasCond cond_make_vv(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
384  {
385      TCGv_i64 t0 = tcg_temp_new_i64();
386      TCGv_i64 t1 = tcg_temp_new_i64();
387  
388      tcg_gen_mov_i64(t0, a0);
389      tcg_gen_mov_i64(t1, a1);
390      return cond_make_tt(c, t0, t1);
391  }
392  
load_gpr(DisasContext * ctx,unsigned reg)393  static TCGv_i64 load_gpr(DisasContext *ctx, unsigned reg)
394  {
395      if (reg == 0) {
396          return ctx->zero;
397      } else {
398          return cpu_gr[reg];
399      }
400  }
401  
dest_gpr(DisasContext * ctx,unsigned reg)402  static TCGv_i64 dest_gpr(DisasContext *ctx, unsigned reg)
403  {
404      if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
405          return tcg_temp_new_i64();
406      } else {
407          return cpu_gr[reg];
408      }
409  }
410  
save_or_nullify(DisasContext * ctx,TCGv_i64 dest,TCGv_i64 t)411  static void save_or_nullify(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 t)
412  {
413      if (ctx->null_cond.c != TCG_COND_NEVER) {
414          tcg_gen_movcond_i64(ctx->null_cond.c, dest, ctx->null_cond.a0,
415                              ctx->null_cond.a1, dest, t);
416      } else {
417          tcg_gen_mov_i64(dest, t);
418      }
419  }
420  
save_gpr(DisasContext * ctx,unsigned reg,TCGv_i64 t)421  static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_i64 t)
422  {
423      if (reg != 0) {
424          save_or_nullify(ctx, cpu_gr[reg], t);
425      }
426  }
427  
428  #if HOST_BIG_ENDIAN
429  # define HI_OFS  0
430  # define LO_OFS  4
431  #else
432  # define HI_OFS  4
433  # define LO_OFS  0
434  #endif
435  
load_frw_i32(unsigned rt)436  static TCGv_i32 load_frw_i32(unsigned rt)
437  {
438      TCGv_i32 ret = tcg_temp_new_i32();
439      tcg_gen_ld_i32(ret, tcg_env,
440                     offsetof(CPUHPPAState, fr[rt & 31])
441                     + (rt & 32 ? LO_OFS : HI_OFS));
442      return ret;
443  }
444  
load_frw0_i32(unsigned rt)445  static TCGv_i32 load_frw0_i32(unsigned rt)
446  {
447      if (rt == 0) {
448          TCGv_i32 ret = tcg_temp_new_i32();
449          tcg_gen_movi_i32(ret, 0);
450          return ret;
451      } else {
452          return load_frw_i32(rt);
453      }
454  }
455  
load_frw0_i64(unsigned rt)456  static TCGv_i64 load_frw0_i64(unsigned rt)
457  {
458      TCGv_i64 ret = tcg_temp_new_i64();
459      if (rt == 0) {
460          tcg_gen_movi_i64(ret, 0);
461      } else {
462          tcg_gen_ld32u_i64(ret, tcg_env,
463                            offsetof(CPUHPPAState, fr[rt & 31])
464                            + (rt & 32 ? LO_OFS : HI_OFS));
465      }
466      return ret;
467  }
468  
save_frw_i32(unsigned rt,TCGv_i32 val)469  static void save_frw_i32(unsigned rt, TCGv_i32 val)
470  {
471      tcg_gen_st_i32(val, tcg_env,
472                     offsetof(CPUHPPAState, fr[rt & 31])
473                     + (rt & 32 ? LO_OFS : HI_OFS));
474  }
475  
476  #undef HI_OFS
477  #undef LO_OFS
478  
load_frd(unsigned rt)479  static TCGv_i64 load_frd(unsigned rt)
480  {
481      TCGv_i64 ret = tcg_temp_new_i64();
482      tcg_gen_ld_i64(ret, tcg_env, offsetof(CPUHPPAState, fr[rt]));
483      return ret;
484  }
485  
load_frd0(unsigned rt)486  static TCGv_i64 load_frd0(unsigned rt)
487  {
488      if (rt == 0) {
489          TCGv_i64 ret = tcg_temp_new_i64();
490          tcg_gen_movi_i64(ret, 0);
491          return ret;
492      } else {
493          return load_frd(rt);
494      }
495  }
496  
save_frd(unsigned rt,TCGv_i64 val)497  static void save_frd(unsigned rt, TCGv_i64 val)
498  {
499      tcg_gen_st_i64(val, tcg_env, offsetof(CPUHPPAState, fr[rt]));
500  }
501  
load_spr(DisasContext * ctx,TCGv_i64 dest,unsigned reg)502  static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
503  {
504  #ifdef CONFIG_USER_ONLY
505      tcg_gen_movi_i64(dest, 0);
506  #else
507      if (reg < 4) {
508          tcg_gen_mov_i64(dest, cpu_sr[reg]);
509      } else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
510          tcg_gen_mov_i64(dest, cpu_srH);
511      } else {
512          tcg_gen_ld_i64(dest, tcg_env, offsetof(CPUHPPAState, sr[reg]));
513      }
514  #endif
515  }
516  
517  /*
518   * Write a value to psw_xb, bearing in mind the known value.
519   * To be used just before exiting the TB, so do not update the known value.
520   */
store_psw_xb(DisasContext * ctx,uint32_t xb)521  static void store_psw_xb(DisasContext *ctx, uint32_t xb)
522  {
523      tcg_debug_assert(xb == 0 || xb == PSW_B);
524      if (ctx->psw_xb != xb) {
525          tcg_gen_movi_i32(cpu_psw_xb, xb);
526      }
527  }
528  
529  /* Write a value to psw_xb, and update the known value. */
set_psw_xb(DisasContext * ctx,uint32_t xb)530  static void set_psw_xb(DisasContext *ctx, uint32_t xb)
531  {
532      store_psw_xb(ctx, xb);
533      ctx->psw_xb = xb;
534  }
535  
536  /* Skip over the implementation of an insn that has been nullified.
537     Use this when the insn is too complex for a conditional move.  */
nullify_over(DisasContext * ctx)538  static void nullify_over(DisasContext *ctx)
539  {
540      if (ctx->null_cond.c != TCG_COND_NEVER) {
541          /* The always condition should have been handled in the main loop.  */
542          assert(ctx->null_cond.c != TCG_COND_ALWAYS);
543  
544          ctx->null_lab = gen_new_label();
545  
546          /* If we're using PSW[N], copy it to a temp because... */
547          if (ctx->null_cond.a0 == cpu_psw_n) {
548              ctx->null_cond.a0 = tcg_temp_new_i64();
549              tcg_gen_mov_i64(ctx->null_cond.a0, cpu_psw_n);
550          }
551          /* ... we clear it before branching over the implementation,
552             so that (1) it's clear after nullifying this insn and
553             (2) if this insn nullifies the next, PSW[N] is valid.  */
554          if (ctx->psw_n_nonzero) {
555              ctx->psw_n_nonzero = false;
556              tcg_gen_movi_i64(cpu_psw_n, 0);
557          }
558  
559          tcg_gen_brcond_i64(ctx->null_cond.c, ctx->null_cond.a0,
560                             ctx->null_cond.a1, ctx->null_lab);
561          ctx->null_cond = cond_make_f();
562      }
563  }
564  
565  /* Save the current nullification state to PSW[N].  */
nullify_save(DisasContext * ctx)566  static void nullify_save(DisasContext *ctx)
567  {
568      if (ctx->null_cond.c == TCG_COND_NEVER) {
569          if (ctx->psw_n_nonzero) {
570              tcg_gen_movi_i64(cpu_psw_n, 0);
571          }
572          return;
573      }
574      if (ctx->null_cond.a0 != cpu_psw_n) {
575          tcg_gen_setcond_i64(ctx->null_cond.c, cpu_psw_n,
576                              ctx->null_cond.a0, ctx->null_cond.a1);
577          ctx->psw_n_nonzero = true;
578      }
579      ctx->null_cond = cond_make_f();
580  }
581  
582  /* Set a PSW[N] to X.  The intention is that this is used immediately
583     before a goto_tb/exit_tb, so that there is no fallthru path to other
584     code within the TB.  Therefore we do not update psw_n_nonzero.  */
nullify_set(DisasContext * ctx,bool x)585  static void nullify_set(DisasContext *ctx, bool x)
586  {
587      if (ctx->psw_n_nonzero || x) {
588          tcg_gen_movi_i64(cpu_psw_n, x);
589      }
590  }
591  
592  /* Mark the end of an instruction that may have been nullified.
593     This is the pair to nullify_over.  Always returns true so that
594     it may be tail-called from a translate function.  */
nullify_end(DisasContext * ctx)595  static bool nullify_end(DisasContext *ctx)
596  {
597      TCGLabel *null_lab = ctx->null_lab;
598      DisasJumpType status = ctx->base.is_jmp;
599  
600      /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
601         For UPDATED, we cannot update on the nullified path.  */
602      assert(status != DISAS_IAQ_N_UPDATED);
603      /* Taken branches are handled manually. */
604      assert(!ctx->psw_b_next);
605  
606      if (likely(null_lab == NULL)) {
607          /* The current insn wasn't conditional or handled the condition
608             applied to it without a branch, so the (new) setting of
609             NULL_COND can be applied directly to the next insn.  */
610          return true;
611      }
612      ctx->null_lab = NULL;
613  
614      if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
615          /* The next instruction will be unconditional,
616             and NULL_COND already reflects that.  */
617          gen_set_label(null_lab);
618      } else {
619          /* The insn that we just executed is itself nullifying the next
620             instruction.  Store the condition in the PSW[N] global.
621             We asserted PSW[N] = 0 in nullify_over, so that after the
622             label we have the proper value in place.  */
623          nullify_save(ctx);
624          gen_set_label(null_lab);
625          ctx->null_cond = cond_make_n();
626      }
627      if (status == DISAS_NORETURN) {
628          ctx->base.is_jmp = DISAS_NEXT;
629      }
630      return true;
631  }
632  
iaqe_variable(const DisasIAQE * e)633  static bool iaqe_variable(const DisasIAQE *e)
634  {
635      return e->base || e->space;
636  }
637  
iaqe_incr(const DisasIAQE * e,int64_t disp)638  static DisasIAQE iaqe_incr(const DisasIAQE *e, int64_t disp)
639  {
640      return (DisasIAQE){
641          .space = e->space,
642          .base = e->base,
643          .disp = e->disp + disp,
644      };
645  }
646  
iaqe_branchi(DisasContext * ctx,int64_t disp)647  static DisasIAQE iaqe_branchi(DisasContext *ctx, int64_t disp)
648  {
649      return (DisasIAQE){
650          .space = ctx->iaq_b.space,
651          .disp = ctx->iaq_f.disp + 8 + disp,
652      };
653  }
654  
iaqe_next_absv(DisasContext * ctx,TCGv_i64 var)655  static DisasIAQE iaqe_next_absv(DisasContext *ctx, TCGv_i64 var)
656  {
657      return (DisasIAQE){
658          .space = ctx->iaq_b.space,
659          .base = var,
660      };
661  }
662  
copy_iaoq_entry(DisasContext * ctx,TCGv_i64 dest,const DisasIAQE * src)663  static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
664                              const DisasIAQE *src)
665  {
666      tcg_gen_addi_i64(dest, src->base ? : cpu_iaoq_f, src->disp);
667  }
668  
install_iaq_entries(DisasContext * ctx,const DisasIAQE * f,const DisasIAQE * b)669  static void install_iaq_entries(DisasContext *ctx, const DisasIAQE *f,
670                                  const DisasIAQE *b)
671  {
672      DisasIAQE b_next;
673  
674      if (b == NULL) {
675          b_next = iaqe_incr(f, 4);
676          b = &b_next;
677      }
678  
679      /*
680       * There is an edge case
681       *    bv   r0(rN)
682       *    b,l  disp,r0
683       * for which F will use cpu_iaoq_b (from the indirect branch),
684       * and B will use cpu_iaoq_f (from the direct branch).
685       * In this case we need an extra temporary.
686       */
687      if (f->base != cpu_iaoq_b) {
688          copy_iaoq_entry(ctx, cpu_iaoq_b, b);
689          copy_iaoq_entry(ctx, cpu_iaoq_f, f);
690      } else if (f->base == b->base) {
691          copy_iaoq_entry(ctx, cpu_iaoq_f, f);
692          tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_f, b->disp - f->disp);
693      } else {
694          TCGv_i64 tmp = tcg_temp_new_i64();
695          copy_iaoq_entry(ctx, tmp, b);
696          copy_iaoq_entry(ctx, cpu_iaoq_f, f);
697          tcg_gen_mov_i64(cpu_iaoq_b, tmp);
698      }
699  
700      if (f->space) {
701          tcg_gen_mov_i64(cpu_iasq_f, f->space);
702      }
703      if (b->space || f->space) {
704          tcg_gen_mov_i64(cpu_iasq_b, b->space ? : f->space);
705      }
706  }
707  
install_link(DisasContext * ctx,unsigned link,bool with_sr0)708  static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
709  {
710      tcg_debug_assert(ctx->null_cond.c == TCG_COND_NEVER);
711      if (!link) {
712          return;
713      }
714      DisasIAQE next = iaqe_incr(&ctx->iaq_b, 4);
715      copy_iaoq_entry(ctx, cpu_gr[link], &next);
716  #ifndef CONFIG_USER_ONLY
717      if (with_sr0) {
718          tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
719      }
720  #endif
721  }
722  
gen_excp_1(int exception)723  static void gen_excp_1(int exception)
724  {
725      gen_helper_excp(tcg_env, tcg_constant_i32(exception));
726  }
727  
gen_excp(DisasContext * ctx,int exception)728  static void gen_excp(DisasContext *ctx, int exception)
729  {
730      install_iaq_entries(ctx, &ctx->iaq_f, &ctx->iaq_b);
731      nullify_save(ctx);
732      gen_excp_1(exception);
733      ctx->base.is_jmp = DISAS_NORETURN;
734  }
735  
delay_excp(DisasContext * ctx,uint8_t excp)736  static DisasDelayException *delay_excp(DisasContext *ctx, uint8_t excp)
737  {
738      DisasDelayException *e = tcg_malloc(sizeof(DisasDelayException));
739  
740      memset(e, 0, sizeof(*e));
741      e->next = ctx->delay_excp_list;
742      ctx->delay_excp_list = e;
743  
744      e->lab = gen_new_label();
745      e->insn = ctx->insn;
746      e->set_iir = true;
747      e->set_n = ctx->psw_n_nonzero ? 0 : -1;
748      e->excp = excp;
749      e->iaq_f = ctx->iaq_f;
750      e->iaq_b = ctx->iaq_b;
751  
752      return e;
753  }
754  
gen_excp_iir(DisasContext * ctx,int exc)755  static bool gen_excp_iir(DisasContext *ctx, int exc)
756  {
757      if (ctx->null_cond.c == TCG_COND_NEVER) {
758          tcg_gen_st_i64(tcg_constant_i64(ctx->insn),
759                         tcg_env, offsetof(CPUHPPAState, cr[CR_IIR]));
760          gen_excp(ctx, exc);
761      } else {
762          DisasDelayException *e = delay_excp(ctx, exc);
763          tcg_gen_brcond_i64(tcg_invert_cond(ctx->null_cond.c),
764                             ctx->null_cond.a0, ctx->null_cond.a1, e->lab);
765          ctx->null_cond = cond_make_f();
766      }
767      return true;
768  }
769  
gen_illegal(DisasContext * ctx)770  static bool gen_illegal(DisasContext *ctx)
771  {
772      return gen_excp_iir(ctx, EXCP_ILL);
773  }
774  
775  #ifdef CONFIG_USER_ONLY
776  #define CHECK_MOST_PRIVILEGED(EXCP) \
777      return gen_excp_iir(ctx, EXCP)
778  #else
779  #define CHECK_MOST_PRIVILEGED(EXCP) \
780      do {                                     \
781          if (ctx->privilege != 0) {           \
782              return gen_excp_iir(ctx, EXCP);  \
783          }                                    \
784      } while (0)
785  #endif
786  
use_goto_tb(DisasContext * ctx,const DisasIAQE * f,const DisasIAQE * b)787  static bool use_goto_tb(DisasContext *ctx, const DisasIAQE *f,
788                          const DisasIAQE *b)
789  {
790      return (!iaqe_variable(f) &&
791              (b == NULL || !iaqe_variable(b)) &&
792              translator_use_goto_tb(&ctx->base, ctx->iaoq_first + f->disp));
793  }
794  
795  /* If the next insn is to be nullified, and it's on the same page,
796     and we're not attempting to set a breakpoint on it, then we can
797     totally skip the nullified insn.  This avoids creating and
798     executing a TB that merely branches to the next TB.  */
use_nullify_skip(DisasContext * ctx)799  static bool use_nullify_skip(DisasContext *ctx)
800  {
801      return (!(tb_cflags(ctx->base.tb) & CF_BP_PAGE)
802              && !iaqe_variable(&ctx->iaq_b)
803              && (((ctx->iaoq_first + ctx->iaq_b.disp) ^ ctx->iaoq_first)
804                  & TARGET_PAGE_MASK) == 0);
805  }
806  
gen_goto_tb(DisasContext * ctx,int which,const DisasIAQE * f,const DisasIAQE * b)807  static void gen_goto_tb(DisasContext *ctx, int which,
808                          const DisasIAQE *f, const DisasIAQE *b)
809  {
810      install_iaq_entries(ctx, f, b);
811      if (use_goto_tb(ctx, f, b)) {
812          tcg_gen_goto_tb(which);
813          tcg_gen_exit_tb(ctx->base.tb, which);
814      } else {
815          tcg_gen_lookup_and_goto_ptr();
816      }
817  }
818  
cond_need_sv(int c)819  static bool cond_need_sv(int c)
820  {
821      return c == 2 || c == 3 || c == 6;
822  }
823  
cond_need_cb(int c)824  static bool cond_need_cb(int c)
825  {
826      return c == 4 || c == 5;
827  }
828  
829  /*
830   * Compute conditional for arithmetic.  See Page 5-3, Table 5-1, of
831   * the Parisc 1.1 Architecture Reference Manual for details.
832   */
833  
do_cond(DisasContext * ctx,unsigned cf,bool d,TCGv_i64 res,TCGv_i64 uv,TCGv_i64 sv)834  static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
835                           TCGv_i64 res, TCGv_i64 uv, TCGv_i64 sv)
836  {
837      TCGCond sign_cond, zero_cond;
838      uint64_t sign_imm, zero_imm;
839      DisasCond cond;
840      TCGv_i64 tmp;
841  
842      if (d) {
843          /* 64-bit condition. */
844          sign_imm = 0;
845          sign_cond = TCG_COND_LT;
846          zero_imm = 0;
847          zero_cond = TCG_COND_EQ;
848      } else {
849          /* 32-bit condition. */
850          sign_imm = 1ull << 31;
851          sign_cond = TCG_COND_TSTNE;
852          zero_imm = UINT32_MAX;
853          zero_cond = TCG_COND_TSTEQ;
854      }
855  
856      switch (cf >> 1) {
857      case 0: /* Never / TR    (0 / 1) */
858          cond = cond_make_f();
859          break;
860      case 1: /* = / <>        (Z / !Z) */
861          cond = cond_make_vi(zero_cond, res, zero_imm);
862          break;
863      case 2: /* < / >=        (N ^ V / !(N ^ V) */
864          tmp = tcg_temp_new_i64();
865          tcg_gen_xor_i64(tmp, res, sv);
866          cond = cond_make_ti(sign_cond, tmp, sign_imm);
867          break;
868      case 3: /* <= / >        (N ^ V) | Z / !((N ^ V) | Z) */
869          /*
870           * Simplify:
871           *   (N ^ V) | Z
872           *   ((res < 0) ^ (sv < 0)) | !res
873           *   ((res ^ sv) < 0) | !res
874           *   ((res ^ sv) < 0 ? 1 : !res)
875           *   !((res ^ sv) < 0 ? 0 : res)
876           */
877          tmp = tcg_temp_new_i64();
878          tcg_gen_xor_i64(tmp, res, sv);
879          tcg_gen_movcond_i64(sign_cond, tmp,
880                              tmp, tcg_constant_i64(sign_imm),
881                              ctx->zero, res);
882          cond = cond_make_ti(zero_cond, tmp, zero_imm);
883          break;
884      case 4: /* NUV / UV      (!UV / UV) */
885          cond = cond_make_vi(TCG_COND_EQ, uv, 0);
886          break;
887      case 5: /* ZNV / VNZ     (!UV | Z / UV & !Z) */
888          tmp = tcg_temp_new_i64();
889          tcg_gen_movcond_i64(TCG_COND_EQ, tmp, uv, ctx->zero, ctx->zero, res);
890          cond = cond_make_ti(zero_cond, tmp, zero_imm);
891          break;
892      case 6: /* SV / NSV      (V / !V) */
893          cond = cond_make_vi(sign_cond, sv, sign_imm);
894          break;
895      case 7: /* OD / EV */
896          cond = cond_make_vi(TCG_COND_TSTNE, res, 1);
897          break;
898      default:
899          g_assert_not_reached();
900      }
901      if (cf & 1) {
902          cond.c = tcg_invert_cond(cond.c);
903      }
904  
905      return cond;
906  }
907  
908  /* Similar, but for the special case of subtraction without borrow, we
909     can use the inputs directly.  This can allow other computation to be
910     deleted as unused.  */
911  
do_sub_cond(DisasContext * ctx,unsigned cf,bool d,TCGv_i64 res,TCGv_i64 in1,TCGv_i64 in2,TCGv_i64 sv)912  static DisasCond do_sub_cond(DisasContext *ctx, unsigned cf, bool d,
913                               TCGv_i64 res, TCGv_i64 in1,
914                               TCGv_i64 in2, TCGv_i64 sv)
915  {
916      TCGCond tc;
917      bool ext_uns;
918  
919      switch (cf >> 1) {
920      case 1: /* = / <> */
921          tc = TCG_COND_EQ;
922          ext_uns = true;
923          break;
924      case 2: /* < / >= */
925          tc = TCG_COND_LT;
926          ext_uns = false;
927          break;
928      case 3: /* <= / > */
929          tc = TCG_COND_LE;
930          ext_uns = false;
931          break;
932      case 4: /* << / >>= */
933          tc = TCG_COND_LTU;
934          ext_uns = true;
935          break;
936      case 5: /* <<= / >> */
937          tc = TCG_COND_LEU;
938          ext_uns = true;
939          break;
940      default:
941          return do_cond(ctx, cf, d, res, NULL, sv);
942      }
943  
944      if (cf & 1) {
945          tc = tcg_invert_cond(tc);
946      }
947      if (!d) {
948          TCGv_i64 t1 = tcg_temp_new_i64();
949          TCGv_i64 t2 = tcg_temp_new_i64();
950  
951          if (ext_uns) {
952              tcg_gen_ext32u_i64(t1, in1);
953              tcg_gen_ext32u_i64(t2, in2);
954          } else {
955              tcg_gen_ext32s_i64(t1, in1);
956              tcg_gen_ext32s_i64(t2, in2);
957          }
958          return cond_make_tt(tc, t1, t2);
959      }
960      return cond_make_vv(tc, in1, in2);
961  }
962  
963  /*
964   * Similar, but for logicals, where the carry and overflow bits are not
965   * computed, and use of them is undefined.
966   *
967   * Undefined or not, hardware does not trap.  It seems reasonable to
968   * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's
969   * how cases c={2,3} are treated.
970   */
971  
do_log_cond(DisasContext * ctx,unsigned cf,bool d,TCGv_i64 res)972  static DisasCond do_log_cond(DisasContext *ctx, unsigned cf, bool d,
973                               TCGv_i64 res)
974  {
975      TCGCond tc;
976      uint64_t imm;
977  
978      switch (cf >> 1) {
979      case 0:  /* never / always */
980      case 4:  /* undef, C */
981      case 5:  /* undef, C & !Z */
982      case 6:  /* undef, V */
983          return cf & 1 ? cond_make_t() : cond_make_f();
984      case 1:  /* == / <> */
985          tc = d ? TCG_COND_EQ : TCG_COND_TSTEQ;
986          imm = d ? 0 : UINT32_MAX;
987          break;
988      case 2:  /* < / >= */
989          tc = d ? TCG_COND_LT : TCG_COND_TSTNE;
990          imm = d ? 0 : 1ull << 31;
991          break;
992      case 3:  /* <= / > */
993          tc = cf & 1 ? TCG_COND_GT : TCG_COND_LE;
994          if (!d) {
995              TCGv_i64 tmp = tcg_temp_new_i64();
996              tcg_gen_ext32s_i64(tmp, res);
997              return cond_make_ti(tc, tmp, 0);
998          }
999          return cond_make_vi(tc, res, 0);
1000      case 7: /* OD / EV */
1001          tc = TCG_COND_TSTNE;
1002          imm = 1;
1003          break;
1004      default:
1005          g_assert_not_reached();
1006      }
1007      if (cf & 1) {
1008          tc = tcg_invert_cond(tc);
1009      }
1010      return cond_make_vi(tc, res, imm);
1011  }
1012  
1013  /* Similar, but for shift/extract/deposit conditions.  */
1014  
do_sed_cond(DisasContext * ctx,unsigned orig,bool d,TCGv_i64 res)1015  static DisasCond do_sed_cond(DisasContext *ctx, unsigned orig, bool d,
1016                               TCGv_i64 res)
1017  {
1018      unsigned c, f;
1019  
1020      /* Convert the compressed condition codes to standard.
1021         0-2 are the same as logicals (nv,<,<=), while 3 is OD.
1022         4-7 are the reverse of 0-3.  */
1023      c = orig & 3;
1024      if (c == 3) {
1025          c = 7;
1026      }
1027      f = (orig & 4) / 4;
1028  
1029      return do_log_cond(ctx, c * 2 + f, d, res);
1030  }
1031  
1032  /* Similar, but for unit zero conditions.  */
do_unit_zero_cond(unsigned cf,bool d,TCGv_i64 res)1033  static DisasCond do_unit_zero_cond(unsigned cf, bool d, TCGv_i64 res)
1034  {
1035      TCGv_i64 tmp;
1036      uint64_t d_repl = d ? 0x0000000100000001ull : 1;
1037      uint64_t ones = 0, sgns = 0;
1038  
1039      switch (cf >> 1) {
1040      case 1: /* SBW / NBW */
1041          if (d) {
1042              ones = d_repl;
1043              sgns = d_repl << 31;
1044          }
1045          break;
1046      case 2: /* SBZ / NBZ */
1047          ones = d_repl * 0x01010101u;
1048          sgns = ones << 7;
1049          break;
1050      case 3: /* SHZ / NHZ */
1051          ones = d_repl * 0x00010001u;
1052          sgns = ones << 15;
1053          break;
1054      }
1055      if (ones == 0) {
1056          /* Undefined, or 0/1 (never/always). */
1057          return cf & 1 ? cond_make_t() : cond_make_f();
1058      }
1059  
1060      /*
1061       * See hasless(v,1) from
1062       * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
1063       */
1064      tmp = tcg_temp_new_i64();
1065      tcg_gen_subi_i64(tmp, res, ones);
1066      tcg_gen_andc_i64(tmp, tmp, res);
1067  
1068      return cond_make_ti(cf & 1 ? TCG_COND_TSTEQ : TCG_COND_TSTNE, tmp, sgns);
1069  }
1070  
get_carry(DisasContext * ctx,bool d,TCGv_i64 cb,TCGv_i64 cb_msb)1071  static TCGv_i64 get_carry(DisasContext *ctx, bool d,
1072                            TCGv_i64 cb, TCGv_i64 cb_msb)
1073  {
1074      if (!d) {
1075          TCGv_i64 t = tcg_temp_new_i64();
1076          tcg_gen_extract_i64(t, cb, 32, 1);
1077          return t;
1078      }
1079      return cb_msb;
1080  }
1081  
get_psw_carry(DisasContext * ctx,bool d)1082  static TCGv_i64 get_psw_carry(DisasContext *ctx, bool d)
1083  {
1084      return get_carry(ctx, d, cpu_psw_cb, cpu_psw_cb_msb);
1085  }
1086  
1087  /* Compute signed overflow for addition.  */
do_add_sv(DisasContext * ctx,TCGv_i64 res,TCGv_i64 in1,TCGv_i64 in2,TCGv_i64 orig_in1,int shift,bool d)1088  static TCGv_i64 do_add_sv(DisasContext *ctx, TCGv_i64 res,
1089                            TCGv_i64 in1, TCGv_i64 in2,
1090                            TCGv_i64 orig_in1, int shift, bool d)
1091  {
1092      TCGv_i64 sv = tcg_temp_new_i64();
1093      TCGv_i64 tmp = tcg_temp_new_i64();
1094  
1095      tcg_gen_xor_i64(sv, res, in1);
1096      tcg_gen_xor_i64(tmp, in1, in2);
1097      tcg_gen_andc_i64(sv, sv, tmp);
1098  
1099      switch (shift) {
1100      case 0:
1101          break;
1102      case 1:
1103          /* Shift left by one and compare the sign. */
1104          tcg_gen_add_i64(tmp, orig_in1, orig_in1);
1105          tcg_gen_xor_i64(tmp, tmp, orig_in1);
1106          /* Incorporate into the overflow. */
1107          tcg_gen_or_i64(sv, sv, tmp);
1108          break;
1109      default:
1110          {
1111              int sign_bit = d ? 63 : 31;
1112  
1113              /* Compare the sign against all lower bits. */
1114              tcg_gen_sextract_i64(tmp, orig_in1, sign_bit, 1);
1115              tcg_gen_xor_i64(tmp, tmp, orig_in1);
1116              /*
1117               * If one of the bits shifting into or through the sign
1118               * differs, then we have overflow.
1119               */
1120              tcg_gen_extract_i64(tmp, tmp, sign_bit - shift, shift);
1121              tcg_gen_movcond_i64(TCG_COND_NE, sv, tmp, ctx->zero,
1122                                  tcg_constant_i64(-1), sv);
1123          }
1124      }
1125      return sv;
1126  }
1127  
1128  /* Compute unsigned overflow for addition.  */
do_add_uv(DisasContext * ctx,TCGv_i64 cb,TCGv_i64 cb_msb,TCGv_i64 in1,int shift,bool d)1129  static TCGv_i64 do_add_uv(DisasContext *ctx, TCGv_i64 cb, TCGv_i64 cb_msb,
1130                            TCGv_i64 in1, int shift, bool d)
1131  {
1132      if (shift == 0) {
1133          return get_carry(ctx, d, cb, cb_msb);
1134      } else {
1135          TCGv_i64 tmp = tcg_temp_new_i64();
1136          tcg_gen_extract_i64(tmp, in1, (d ? 63 : 31) - shift, shift);
1137          tcg_gen_or_i64(tmp, tmp, get_carry(ctx, d, cb, cb_msb));
1138          return tmp;
1139      }
1140  }
1141  
1142  /* Compute signed overflow for subtraction.  */
do_sub_sv(DisasContext * ctx,TCGv_i64 res,TCGv_i64 in1,TCGv_i64 in2)1143  static TCGv_i64 do_sub_sv(DisasContext *ctx, TCGv_i64 res,
1144                            TCGv_i64 in1, TCGv_i64 in2)
1145  {
1146      TCGv_i64 sv = tcg_temp_new_i64();
1147      TCGv_i64 tmp = tcg_temp_new_i64();
1148  
1149      tcg_gen_xor_i64(sv, res, in1);
1150      tcg_gen_xor_i64(tmp, in1, in2);
1151      tcg_gen_and_i64(sv, sv, tmp);
1152  
1153      return sv;
1154  }
1155  
gen_tc(DisasContext * ctx,DisasCond * cond)1156  static void gen_tc(DisasContext *ctx, DisasCond *cond)
1157  {
1158      DisasDelayException *e;
1159  
1160      switch (cond->c) {
1161      case TCG_COND_NEVER:
1162          break;
1163      case TCG_COND_ALWAYS:
1164          gen_excp_iir(ctx, EXCP_COND);
1165          break;
1166      default:
1167          e = delay_excp(ctx, EXCP_COND);
1168          tcg_gen_brcond_i64(cond->c, cond->a0, cond->a1, e->lab);
1169          /* In the non-trap path, the condition is known false. */
1170          *cond = cond_make_f();
1171          break;
1172      }
1173  }
1174  
gen_tsv(DisasContext * ctx,TCGv_i64 * sv,bool d)1175  static void gen_tsv(DisasContext *ctx, TCGv_i64 *sv, bool d)
1176  {
1177      DisasCond cond = do_cond(ctx, /* SV */ 12, d, NULL, NULL, *sv);
1178      DisasDelayException *e = delay_excp(ctx, EXCP_OVERFLOW);
1179  
1180      tcg_gen_brcond_i64(cond.c, cond.a0, cond.a1, e->lab);
1181  
1182      /* In the non-trap path, V is known zero. */
1183      *sv = tcg_constant_i64(0);
1184  }
1185  
do_add(DisasContext * ctx,unsigned rt,TCGv_i64 orig_in1,TCGv_i64 in2,unsigned shift,bool is_l,bool is_tsv,bool is_tc,bool is_c,unsigned cf,bool d)1186  static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
1187                     TCGv_i64 in2, unsigned shift, bool is_l,
1188                     bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
1189  {
1190      TCGv_i64 dest, cb, cb_msb, in1, uv, sv, tmp;
1191      unsigned c = cf >> 1;
1192      DisasCond cond;
1193  
1194      dest = tcg_temp_new_i64();
1195      cb = NULL;
1196      cb_msb = NULL;
1197  
1198      in1 = orig_in1;
1199      if (shift) {
1200          tmp = tcg_temp_new_i64();
1201          tcg_gen_shli_i64(tmp, in1, shift);
1202          in1 = tmp;
1203      }
1204  
1205      if (!is_l || cond_need_cb(c)) {
1206          cb_msb = tcg_temp_new_i64();
1207          cb = tcg_temp_new_i64();
1208  
1209          tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero, in2, ctx->zero);
1210          if (is_c) {
1211              tcg_gen_add2_i64(dest, cb_msb, dest, cb_msb,
1212                               get_psw_carry(ctx, d), ctx->zero);
1213          }
1214          tcg_gen_xor_i64(cb, in1, in2);
1215          tcg_gen_xor_i64(cb, cb, dest);
1216      } else {
1217          tcg_gen_add_i64(dest, in1, in2);
1218          if (is_c) {
1219              tcg_gen_add_i64(dest, dest, get_psw_carry(ctx, d));
1220          }
1221      }
1222  
1223      /* Compute signed overflow if required.  */
1224      sv = NULL;
1225      if (is_tsv || cond_need_sv(c)) {
1226          sv = do_add_sv(ctx, dest, in1, in2, orig_in1, shift, d);
1227          if (is_tsv) {
1228              gen_tsv(ctx, &sv, d);
1229          }
1230      }
1231  
1232      /* Compute unsigned overflow if required.  */
1233      uv = NULL;
1234      if (cond_need_cb(c)) {
1235          uv = do_add_uv(ctx, cb, cb_msb, orig_in1, shift, d);
1236      }
1237  
1238      /* Emit any conditional trap before any writeback.  */
1239      cond = do_cond(ctx, cf, d, dest, uv, sv);
1240      if (is_tc) {
1241          gen_tc(ctx, &cond);
1242      }
1243  
1244      /* Write back the result.  */
1245      if (!is_l) {
1246          save_or_nullify(ctx, cpu_psw_cb, cb);
1247          save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1248      }
1249      save_gpr(ctx, rt, dest);
1250  
1251      /* Install the new nullification.  */
1252      ctx->null_cond = cond;
1253  }
1254  
do_add_reg(DisasContext * ctx,arg_rrr_cf_d_sh * a,bool is_l,bool is_tsv,bool is_tc,bool is_c)1255  static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_d_sh *a,
1256                         bool is_l, bool is_tsv, bool is_tc, bool is_c)
1257  {
1258      TCGv_i64 tcg_r1, tcg_r2;
1259  
1260      if (unlikely(is_tc && a->cf == 1)) {
1261          /* Unconditional trap on condition. */
1262          return gen_excp_iir(ctx, EXCP_COND);
1263      }
1264      if (a->cf) {
1265          nullify_over(ctx);
1266      }
1267      tcg_r1 = load_gpr(ctx, a->r1);
1268      tcg_r2 = load_gpr(ctx, a->r2);
1269      do_add(ctx, a->t, tcg_r1, tcg_r2, a->sh, is_l,
1270             is_tsv, is_tc, is_c, a->cf, a->d);
1271      return nullify_end(ctx);
1272  }
1273  
do_add_imm(DisasContext * ctx,arg_rri_cf * a,bool is_tsv,bool is_tc)1274  static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
1275                         bool is_tsv, bool is_tc)
1276  {
1277      TCGv_i64 tcg_im, tcg_r2;
1278  
1279      if (unlikely(is_tc && a->cf == 1)) {
1280          /* Unconditional trap on condition. */
1281          return gen_excp_iir(ctx, EXCP_COND);
1282      }
1283      if (a->cf) {
1284          nullify_over(ctx);
1285      }
1286      tcg_im = tcg_constant_i64(a->i);
1287      tcg_r2 = load_gpr(ctx, a->r);
1288      /* All ADDI conditions are 32-bit. */
1289      do_add(ctx, a->t, tcg_im, tcg_r2, 0, 0, is_tsv, is_tc, 0, a->cf, false);
1290      return nullify_end(ctx);
1291  }
1292  
do_sub(DisasContext * ctx,unsigned rt,TCGv_i64 in1,TCGv_i64 in2,bool is_tsv,bool is_b,bool is_tc,unsigned cf,bool d)1293  static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1294                     TCGv_i64 in2, bool is_tsv, bool is_b,
1295                     bool is_tc, unsigned cf, bool d)
1296  {
1297      TCGv_i64 dest, sv, cb, cb_msb;
1298      unsigned c = cf >> 1;
1299      DisasCond cond;
1300  
1301      dest = tcg_temp_new_i64();
1302      cb = tcg_temp_new_i64();
1303      cb_msb = tcg_temp_new_i64();
1304  
1305      if (is_b) {
1306          /* DEST,C = IN1 + ~IN2 + C.  */
1307          tcg_gen_not_i64(cb, in2);
1308          tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero,
1309                           get_psw_carry(ctx, d), ctx->zero);
1310          tcg_gen_add2_i64(dest, cb_msb, dest, cb_msb, cb, ctx->zero);
1311          tcg_gen_xor_i64(cb, cb, in1);
1312          tcg_gen_xor_i64(cb, cb, dest);
1313      } else {
1314          /*
1315           * DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
1316           * operations by seeding the high word with 1 and subtracting.
1317           */
1318          TCGv_i64 one = tcg_constant_i64(1);
1319          tcg_gen_sub2_i64(dest, cb_msb, in1, one, in2, ctx->zero);
1320          tcg_gen_eqv_i64(cb, in1, in2);
1321          tcg_gen_xor_i64(cb, cb, dest);
1322      }
1323  
1324      /* Compute signed overflow if required.  */
1325      sv = NULL;
1326      if (is_tsv || cond_need_sv(c)) {
1327          sv = do_sub_sv(ctx, dest, in1, in2);
1328          if (is_tsv) {
1329              gen_tsv(ctx, &sv, d);
1330          }
1331      }
1332  
1333      /* Compute the condition.  We cannot use the special case for borrow.  */
1334      if (!is_b) {
1335          cond = do_sub_cond(ctx, cf, d, dest, in1, in2, sv);
1336      } else {
1337          cond = do_cond(ctx, cf, d, dest, get_carry(ctx, d, cb, cb_msb), sv);
1338      }
1339  
1340      /* Emit any conditional trap before any writeback.  */
1341      if (is_tc) {
1342          gen_tc(ctx, &cond);
1343      }
1344  
1345      /* Write back the result.  */
1346      save_or_nullify(ctx, cpu_psw_cb, cb);
1347      save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1348      save_gpr(ctx, rt, dest);
1349  
1350      /* Install the new nullification.  */
1351      ctx->null_cond = cond;
1352  }
1353  
do_sub_reg(DisasContext * ctx,arg_rrr_cf_d * a,bool is_tsv,bool is_b,bool is_tc)1354  static bool do_sub_reg(DisasContext *ctx, arg_rrr_cf_d *a,
1355                         bool is_tsv, bool is_b, bool is_tc)
1356  {
1357      TCGv_i64 tcg_r1, tcg_r2;
1358  
1359      if (a->cf) {
1360          nullify_over(ctx);
1361      }
1362      tcg_r1 = load_gpr(ctx, a->r1);
1363      tcg_r2 = load_gpr(ctx, a->r2);
1364      do_sub(ctx, a->t, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, a->cf, a->d);
1365      return nullify_end(ctx);
1366  }
1367  
do_sub_imm(DisasContext * ctx,arg_rri_cf * a,bool is_tsv)1368  static bool do_sub_imm(DisasContext *ctx, arg_rri_cf *a, bool is_tsv)
1369  {
1370      TCGv_i64 tcg_im, tcg_r2;
1371  
1372      if (a->cf) {
1373          nullify_over(ctx);
1374      }
1375      tcg_im = tcg_constant_i64(a->i);
1376      tcg_r2 = load_gpr(ctx, a->r);
1377      /* All SUBI conditions are 32-bit. */
1378      do_sub(ctx, a->t, tcg_im, tcg_r2, is_tsv, 0, 0, a->cf, false);
1379      return nullify_end(ctx);
1380  }
1381  
do_cmpclr(DisasContext * ctx,unsigned rt,TCGv_i64 in1,TCGv_i64 in2,unsigned cf,bool d)1382  static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1383                        TCGv_i64 in2, unsigned cf, bool d)
1384  {
1385      TCGv_i64 dest, sv;
1386      DisasCond cond;
1387  
1388      dest = tcg_temp_new_i64();
1389      tcg_gen_sub_i64(dest, in1, in2);
1390  
1391      /* Compute signed overflow if required.  */
1392      sv = NULL;
1393      if (cond_need_sv(cf >> 1)) {
1394          sv = do_sub_sv(ctx, dest, in1, in2);
1395      }
1396  
1397      /* Form the condition for the compare.  */
1398      cond = do_sub_cond(ctx, cf, d, dest, in1, in2, sv);
1399  
1400      /* Clear.  */
1401      tcg_gen_movi_i64(dest, 0);
1402      save_gpr(ctx, rt, dest);
1403  
1404      /* Install the new nullification.  */
1405      ctx->null_cond = cond;
1406  }
1407  
do_log(DisasContext * ctx,unsigned rt,TCGv_i64 in1,TCGv_i64 in2,unsigned cf,bool d,void (* fn)(TCGv_i64,TCGv_i64,TCGv_i64))1408  static void do_log(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1409                     TCGv_i64 in2, unsigned cf, bool d,
1410                     void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
1411  {
1412      TCGv_i64 dest = dest_gpr(ctx, rt);
1413  
1414      /* Perform the operation, and writeback.  */
1415      fn(dest, in1, in2);
1416      save_gpr(ctx, rt, dest);
1417  
1418      /* Install the new nullification.  */
1419      ctx->null_cond = do_log_cond(ctx, cf, d, dest);
1420  }
1421  
do_log_reg(DisasContext * ctx,arg_rrr_cf_d * a,void (* fn)(TCGv_i64,TCGv_i64,TCGv_i64))1422  static bool do_log_reg(DisasContext *ctx, arg_rrr_cf_d *a,
1423                         void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
1424  {
1425      TCGv_i64 tcg_r1, tcg_r2;
1426  
1427      if (a->cf) {
1428          nullify_over(ctx);
1429      }
1430      tcg_r1 = load_gpr(ctx, a->r1);
1431      tcg_r2 = load_gpr(ctx, a->r2);
1432      do_log(ctx, a->t, tcg_r1, tcg_r2, a->cf, a->d, fn);
1433      return nullify_end(ctx);
1434  }
1435  
do_unit_addsub(DisasContext * ctx,unsigned rt,TCGv_i64 in1,TCGv_i64 in2,unsigned cf,bool d,bool is_tc,bool is_add)1436  static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1437                             TCGv_i64 in2, unsigned cf, bool d,
1438                             bool is_tc, bool is_add)
1439  {
1440      TCGv_i64 dest = tcg_temp_new_i64();
1441      uint64_t test_cb = 0;
1442      DisasCond cond;
1443  
1444      /* Select which carry-out bits to test. */
1445      switch (cf >> 1) {
1446      case 4: /* NDC / SDC -- 4-bit carries */
1447          test_cb = dup_const(MO_8, 0x88);
1448          break;
1449      case 5: /* NWC / SWC -- 32-bit carries */
1450          if (d) {
1451              test_cb = dup_const(MO_32, INT32_MIN);
1452          } else {
1453              cf &= 1; /* undefined -- map to never/always */
1454          }
1455          break;
1456      case 6: /* NBC / SBC -- 8-bit carries */
1457          test_cb = dup_const(MO_8, INT8_MIN);
1458          break;
1459      case 7: /* NHC / SHC -- 16-bit carries */
1460          test_cb = dup_const(MO_16, INT16_MIN);
1461          break;
1462      }
1463      if (!d) {
1464          test_cb = (uint32_t)test_cb;
1465      }
1466  
1467      if (!test_cb) {
1468          /* No need to compute carries if we don't need to test them. */
1469          if (is_add) {
1470              tcg_gen_add_i64(dest, in1, in2);
1471          } else {
1472              tcg_gen_sub_i64(dest, in1, in2);
1473          }
1474          cond = do_unit_zero_cond(cf, d, dest);
1475      } else {
1476          TCGv_i64 cb = tcg_temp_new_i64();
1477  
1478          if (d) {
1479              TCGv_i64 cb_msb = tcg_temp_new_i64();
1480              if (is_add) {
1481                  tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero, in2, ctx->zero);
1482                  tcg_gen_xor_i64(cb, in1, in2);
1483              } else {
1484                  /* See do_sub, !is_b. */
1485                  TCGv_i64 one = tcg_constant_i64(1);
1486                  tcg_gen_sub2_i64(dest, cb_msb, in1, one, in2, ctx->zero);
1487                  tcg_gen_eqv_i64(cb, in1, in2);
1488              }
1489              tcg_gen_xor_i64(cb, cb, dest);
1490              tcg_gen_extract2_i64(cb, cb, cb_msb, 1);
1491          } else {
1492              if (is_add) {
1493                  tcg_gen_add_i64(dest, in1, in2);
1494                  tcg_gen_xor_i64(cb, in1, in2);
1495              } else {
1496                  tcg_gen_sub_i64(dest, in1, in2);
1497                  tcg_gen_eqv_i64(cb, in1, in2);
1498              }
1499              tcg_gen_xor_i64(cb, cb, dest);
1500              tcg_gen_shri_i64(cb, cb, 1);
1501          }
1502  
1503          cond = cond_make_ti(cf & 1 ? TCG_COND_TSTEQ : TCG_COND_TSTNE,
1504                              cb, test_cb);
1505      }
1506  
1507      if (is_tc) {
1508          gen_tc(ctx, &cond);
1509      }
1510      save_gpr(ctx, rt, dest);
1511  
1512      ctx->null_cond = cond;
1513  }
1514  
1515  #ifndef CONFIG_USER_ONLY
1516  /* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
1517     from the top 2 bits of the base register.  There are a few system
1518     instructions that have a 3-bit space specifier, for which SR0 is
1519     not special.  To handle this, pass ~SP.  */
space_select(DisasContext * ctx,int sp,TCGv_i64 base)1520  static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_i64 base)
1521  {
1522      TCGv_ptr ptr;
1523      TCGv_i64 tmp;
1524      TCGv_i64 spc;
1525  
1526      if (sp != 0) {
1527          if (sp < 0) {
1528              sp = ~sp;
1529          }
1530          spc = tcg_temp_new_i64();
1531          load_spr(ctx, spc, sp);
1532          return spc;
1533      }
1534      if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1535          return cpu_srH;
1536      }
1537  
1538      ptr = tcg_temp_new_ptr();
1539      tmp = tcg_temp_new_i64();
1540      spc = tcg_temp_new_i64();
1541  
1542      /* Extract top 2 bits of the address, shift left 3 for uint64_t index. */
1543      tcg_gen_shri_i64(tmp, base, (ctx->tb_flags & PSW_W ? 64 : 32) - 5);
1544      tcg_gen_andi_i64(tmp, tmp, 030);
1545      tcg_gen_trunc_i64_ptr(ptr, tmp);
1546  
1547      tcg_gen_add_ptr(ptr, ptr, tcg_env);
1548      tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
1549  
1550      return spc;
1551  }
1552  #endif
1553  
form_gva(DisasContext * ctx,TCGv_i64 * pgva,TCGv_i64 * pofs,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,bool is_phys)1554  static void form_gva(DisasContext *ctx, TCGv_i64 *pgva, TCGv_i64 *pofs,
1555                       unsigned rb, unsigned rx, int scale, int64_t disp,
1556                       unsigned sp, int modify, bool is_phys)
1557  {
1558      TCGv_i64 base = load_gpr(ctx, rb);
1559      TCGv_i64 ofs;
1560      TCGv_i64 addr;
1561  
1562      set_insn_breg(ctx, rb);
1563  
1564      /* Note that RX is mutually exclusive with DISP.  */
1565      if (rx) {
1566          ofs = tcg_temp_new_i64();
1567          tcg_gen_shli_i64(ofs, cpu_gr[rx], scale);
1568          tcg_gen_add_i64(ofs, ofs, base);
1569      } else if (disp || modify) {
1570          ofs = tcg_temp_new_i64();
1571          tcg_gen_addi_i64(ofs, base, disp);
1572      } else {
1573          ofs = base;
1574      }
1575  
1576      *pofs = ofs;
1577      *pgva = addr = tcg_temp_new_i64();
1578      tcg_gen_andi_i64(addr, modify <= 0 ? ofs : base,
1579                       gva_offset_mask(ctx->tb_flags));
1580  #ifndef CONFIG_USER_ONLY
1581      if (!is_phys) {
1582          tcg_gen_or_i64(addr, addr, space_select(ctx, sp, base));
1583      }
1584  #endif
1585  }
1586  
1587  /* Emit a memory load.  The modify parameter should be
1588   * < 0 for pre-modify,
1589   * > 0 for post-modify,
1590   * = 0 for no base register update.
1591   */
do_load_32(DisasContext * ctx,TCGv_i32 dest,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,MemOp mop)1592  static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1593                         unsigned rx, int scale, int64_t disp,
1594                         unsigned sp, int modify, MemOp mop)
1595  {
1596      TCGv_i64 ofs;
1597      TCGv_i64 addr;
1598  
1599      /* Caller uses nullify_over/nullify_end.  */
1600      assert(ctx->null_cond.c == TCG_COND_NEVER);
1601  
1602      form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1603               MMU_DISABLED(ctx));
1604      tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1605      if (modify) {
1606          save_gpr(ctx, rb, ofs);
1607      }
1608  }
1609  
do_load_64(DisasContext * ctx,TCGv_i64 dest,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,MemOp mop)1610  static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1611                         unsigned rx, int scale, int64_t disp,
1612                         unsigned sp, int modify, MemOp mop)
1613  {
1614      TCGv_i64 ofs;
1615      TCGv_i64 addr;
1616  
1617      /* Caller uses nullify_over/nullify_end.  */
1618      assert(ctx->null_cond.c == TCG_COND_NEVER);
1619  
1620      form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1621               MMU_DISABLED(ctx));
1622      tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1623      if (modify) {
1624          save_gpr(ctx, rb, ofs);
1625      }
1626  }
1627  
do_store_32(DisasContext * ctx,TCGv_i32 src,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,MemOp mop)1628  static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1629                          unsigned rx, int scale, int64_t disp,
1630                          unsigned sp, int modify, MemOp mop)
1631  {
1632      TCGv_i64 ofs;
1633      TCGv_i64 addr;
1634  
1635      /* Caller uses nullify_over/nullify_end.  */
1636      assert(ctx->null_cond.c == TCG_COND_NEVER);
1637  
1638      form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1639               MMU_DISABLED(ctx));
1640      tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1641      if (modify) {
1642          save_gpr(ctx, rb, ofs);
1643      }
1644  }
1645  
do_store_64(DisasContext * ctx,TCGv_i64 src,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,MemOp mop)1646  static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1647                          unsigned rx, int scale, int64_t disp,
1648                          unsigned sp, int modify, MemOp mop)
1649  {
1650      TCGv_i64 ofs;
1651      TCGv_i64 addr;
1652  
1653      /* Caller uses nullify_over/nullify_end.  */
1654      assert(ctx->null_cond.c == TCG_COND_NEVER);
1655  
1656      form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1657               MMU_DISABLED(ctx));
1658      tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1659      if (modify) {
1660          save_gpr(ctx, rb, ofs);
1661      }
1662  }
1663  
do_load(DisasContext * ctx,unsigned rt,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify,MemOp mop)1664  static bool do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1665                      unsigned rx, int scale, int64_t disp,
1666                      unsigned sp, int modify, MemOp mop)
1667  {
1668      TCGv_i64 dest;
1669  
1670      nullify_over(ctx);
1671  
1672      if (modify == 0) {
1673          /* No base register update.  */
1674          dest = dest_gpr(ctx, rt);
1675      } else {
1676          /* Make sure if RT == RB, we see the result of the load.  */
1677          dest = tcg_temp_new_i64();
1678      }
1679      do_load_64(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
1680      save_gpr(ctx, rt, dest);
1681  
1682      return nullify_end(ctx);
1683  }
1684  
do_floadw(DisasContext * ctx,unsigned rt,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify)1685  static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1686                        unsigned rx, int scale, int64_t disp,
1687                        unsigned sp, int modify)
1688  {
1689      TCGv_i32 tmp;
1690  
1691      nullify_over(ctx);
1692  
1693      tmp = tcg_temp_new_i32();
1694      do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1695      save_frw_i32(rt, tmp);
1696  
1697      if (rt == 0) {
1698          gen_helper_loaded_fr0(tcg_env);
1699      }
1700  
1701      return nullify_end(ctx);
1702  }
1703  
trans_fldw(DisasContext * ctx,arg_ldst * a)1704  static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
1705  {
1706      return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1707                       a->disp, a->sp, a->m);
1708  }
1709  
do_floadd(DisasContext * ctx,unsigned rt,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify)1710  static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1711                        unsigned rx, int scale, int64_t disp,
1712                        unsigned sp, int modify)
1713  {
1714      TCGv_i64 tmp;
1715  
1716      nullify_over(ctx);
1717  
1718      tmp = tcg_temp_new_i64();
1719      do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
1720      save_frd(rt, tmp);
1721  
1722      if (rt == 0) {
1723          gen_helper_loaded_fr0(tcg_env);
1724      }
1725  
1726      return nullify_end(ctx);
1727  }
1728  
trans_fldd(DisasContext * ctx,arg_ldst * a)1729  static bool trans_fldd(DisasContext *ctx, arg_ldst *a)
1730  {
1731      return do_floadd(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1732                       a->disp, a->sp, a->m);
1733  }
1734  
do_store(DisasContext * ctx,unsigned rt,unsigned rb,int64_t disp,unsigned sp,int modify,MemOp mop)1735  static bool do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1736                       int64_t disp, unsigned sp,
1737                       int modify, MemOp mop)
1738  {
1739      nullify_over(ctx);
1740      do_store_64(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
1741      return nullify_end(ctx);
1742  }
1743  
do_fstorew(DisasContext * ctx,unsigned rt,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify)1744  static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1745                         unsigned rx, int scale, int64_t disp,
1746                         unsigned sp, int modify)
1747  {
1748      TCGv_i32 tmp;
1749  
1750      nullify_over(ctx);
1751  
1752      tmp = load_frw_i32(rt);
1753      do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1754  
1755      return nullify_end(ctx);
1756  }
1757  
trans_fstw(DisasContext * ctx,arg_ldst * a)1758  static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
1759  {
1760      return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1761                        a->disp, a->sp, a->m);
1762  }
1763  
do_fstored(DisasContext * ctx,unsigned rt,unsigned rb,unsigned rx,int scale,int64_t disp,unsigned sp,int modify)1764  static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1765                         unsigned rx, int scale, int64_t disp,
1766                         unsigned sp, int modify)
1767  {
1768      TCGv_i64 tmp;
1769  
1770      nullify_over(ctx);
1771  
1772      tmp = load_frd(rt);
1773      do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
1774  
1775      return nullify_end(ctx);
1776  }
1777  
trans_fstd(DisasContext * ctx,arg_ldst * a)1778  static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
1779  {
1780      return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1781                        a->disp, a->sp, a->m);
1782  }
1783  
do_fop_wew(DisasContext * ctx,unsigned rt,unsigned ra,void (* func)(TCGv_i32,TCGv_env,TCGv_i32))1784  static bool do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1785                         void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1786  {
1787      TCGv_i32 tmp;
1788  
1789      nullify_over(ctx);
1790      tmp = load_frw0_i32(ra);
1791  
1792      func(tmp, tcg_env, tmp);
1793  
1794      save_frw_i32(rt, tmp);
1795      return nullify_end(ctx);
1796  }
1797  
do_fop_wed(DisasContext * ctx,unsigned rt,unsigned ra,void (* func)(TCGv_i32,TCGv_env,TCGv_i64))1798  static bool do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1799                         void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1800  {
1801      TCGv_i32 dst;
1802      TCGv_i64 src;
1803  
1804      nullify_over(ctx);
1805      src = load_frd(ra);
1806      dst = tcg_temp_new_i32();
1807  
1808      func(dst, tcg_env, src);
1809  
1810      save_frw_i32(rt, dst);
1811      return nullify_end(ctx);
1812  }
1813  
do_fop_ded(DisasContext * ctx,unsigned rt,unsigned ra,void (* func)(TCGv_i64,TCGv_env,TCGv_i64))1814  static bool do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1815                         void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1816  {
1817      TCGv_i64 tmp;
1818  
1819      nullify_over(ctx);
1820      tmp = load_frd0(ra);
1821  
1822      func(tmp, tcg_env, tmp);
1823  
1824      save_frd(rt, tmp);
1825      return nullify_end(ctx);
1826  }
1827  
do_fop_dew(DisasContext * ctx,unsigned rt,unsigned ra,void (* func)(TCGv_i64,TCGv_env,TCGv_i32))1828  static bool do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1829                         void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1830  {
1831      TCGv_i32 src;
1832      TCGv_i64 dst;
1833  
1834      nullify_over(ctx);
1835      src = load_frw0_i32(ra);
1836      dst = tcg_temp_new_i64();
1837  
1838      func(dst, tcg_env, src);
1839  
1840      save_frd(rt, dst);
1841      return nullify_end(ctx);
1842  }
1843  
do_fop_weww(DisasContext * ctx,unsigned rt,unsigned ra,unsigned rb,void (* func)(TCGv_i32,TCGv_env,TCGv_i32,TCGv_i32))1844  static bool do_fop_weww(DisasContext *ctx, unsigned rt,
1845                          unsigned ra, unsigned rb,
1846                          void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
1847  {
1848      TCGv_i32 a, b;
1849  
1850      nullify_over(ctx);
1851      a = load_frw0_i32(ra);
1852      b = load_frw0_i32(rb);
1853  
1854      func(a, tcg_env, a, b);
1855  
1856      save_frw_i32(rt, a);
1857      return nullify_end(ctx);
1858  }
1859  
do_fop_dedd(DisasContext * ctx,unsigned rt,unsigned ra,unsigned rb,void (* func)(TCGv_i64,TCGv_env,TCGv_i64,TCGv_i64))1860  static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
1861                          unsigned ra, unsigned rb,
1862                          void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1863  {
1864      TCGv_i64 a, b;
1865  
1866      nullify_over(ctx);
1867      a = load_frd0(ra);
1868      b = load_frd0(rb);
1869  
1870      func(a, tcg_env, a, b);
1871  
1872      save_frd(rt, a);
1873      return nullify_end(ctx);
1874  }
1875  
1876  /* Emit an unconditional branch to a direct target, which may or may not
1877     have already had nullification handled.  */
do_dbranch(DisasContext * ctx,int64_t disp,unsigned link,bool is_n)1878  static bool do_dbranch(DisasContext *ctx, int64_t disp,
1879                         unsigned link, bool is_n)
1880  {
1881      ctx->iaq_j = iaqe_branchi(ctx, disp);
1882  
1883      if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1884          install_link(ctx, link, false);
1885          if (is_n) {
1886              if (use_nullify_skip(ctx)) {
1887                  nullify_set(ctx, 0);
1888                  store_psw_xb(ctx, 0);
1889                  gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
1890                  ctx->base.is_jmp = DISAS_NORETURN;
1891                  return true;
1892              }
1893              ctx->null_cond.c = TCG_COND_ALWAYS;
1894          }
1895          ctx->iaq_n = &ctx->iaq_j;
1896          ctx->psw_b_next = true;
1897      } else {
1898          nullify_over(ctx);
1899  
1900          install_link(ctx, link, false);
1901          if (is_n && use_nullify_skip(ctx)) {
1902              nullify_set(ctx, 0);
1903              store_psw_xb(ctx, 0);
1904              gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
1905          } else {
1906              nullify_set(ctx, is_n);
1907              store_psw_xb(ctx, PSW_B);
1908              gen_goto_tb(ctx, 0, &ctx->iaq_b, &ctx->iaq_j);
1909          }
1910          nullify_end(ctx);
1911  
1912          nullify_set(ctx, 0);
1913          store_psw_xb(ctx, 0);
1914          gen_goto_tb(ctx, 1, &ctx->iaq_b, NULL);
1915          ctx->base.is_jmp = DISAS_NORETURN;
1916      }
1917      return true;
1918  }
1919  
1920  /* Emit a conditional branch to a direct target.  If the branch itself
1921     is nullified, we should have already used nullify_over.  */
do_cbranch(DisasContext * ctx,int64_t disp,bool is_n,DisasCond * cond)1922  static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
1923                         DisasCond *cond)
1924  {
1925      DisasIAQE next;
1926      TCGLabel *taken = NULL;
1927      TCGCond c = cond->c;
1928      bool n;
1929  
1930      assert(ctx->null_cond.c == TCG_COND_NEVER);
1931  
1932      /* Handle TRUE and NEVER as direct branches.  */
1933      if (c == TCG_COND_ALWAYS) {
1934          return do_dbranch(ctx, disp, 0, is_n && disp >= 0);
1935      }
1936  
1937      taken = gen_new_label();
1938      tcg_gen_brcond_i64(c, cond->a0, cond->a1, taken);
1939  
1940      /* Not taken: Condition not satisfied; nullify on backward branches. */
1941      n = is_n && disp < 0;
1942      if (n && use_nullify_skip(ctx)) {
1943          nullify_set(ctx, 0);
1944          store_psw_xb(ctx, 0);
1945          next = iaqe_incr(&ctx->iaq_b, 4);
1946          gen_goto_tb(ctx, 0, &next, NULL);
1947      } else {
1948          if (!n && ctx->null_lab) {
1949              gen_set_label(ctx->null_lab);
1950              ctx->null_lab = NULL;
1951          }
1952          nullify_set(ctx, n);
1953          store_psw_xb(ctx, 0);
1954          gen_goto_tb(ctx, 0, &ctx->iaq_b, NULL);
1955      }
1956  
1957      gen_set_label(taken);
1958  
1959      /* Taken: Condition satisfied; nullify on forward branches.  */
1960      n = is_n && disp >= 0;
1961  
1962      next = iaqe_branchi(ctx, disp);
1963      if (n && use_nullify_skip(ctx)) {
1964          nullify_set(ctx, 0);
1965          store_psw_xb(ctx, 0);
1966          gen_goto_tb(ctx, 1, &next, NULL);
1967      } else {
1968          nullify_set(ctx, n);
1969          store_psw_xb(ctx, PSW_B);
1970          gen_goto_tb(ctx, 1, &ctx->iaq_b, &next);
1971      }
1972  
1973      /* Not taken: the branch itself was nullified.  */
1974      if (ctx->null_lab) {
1975          gen_set_label(ctx->null_lab);
1976          ctx->null_lab = NULL;
1977          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
1978      } else {
1979          ctx->base.is_jmp = DISAS_NORETURN;
1980      }
1981      return true;
1982  }
1983  
1984  /*
1985   * Emit an unconditional branch to an indirect target, in ctx->iaq_j.
1986   * This handles nullification of the branch itself.
1987   */
do_ibranch(DisasContext * ctx,unsigned link,bool with_sr0,bool is_n)1988  static bool do_ibranch(DisasContext *ctx, unsigned link,
1989                         bool with_sr0, bool is_n)
1990  {
1991      if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1992          install_link(ctx, link, with_sr0);
1993          if (is_n) {
1994              if (use_nullify_skip(ctx)) {
1995                  install_iaq_entries(ctx, &ctx->iaq_j, NULL);
1996                  nullify_set(ctx, 0);
1997                  ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
1998                  return true;
1999              }
2000              ctx->null_cond.c = TCG_COND_ALWAYS;
2001          }
2002          ctx->iaq_n = &ctx->iaq_j;
2003          ctx->psw_b_next = true;
2004          return true;
2005      }
2006  
2007      nullify_over(ctx);
2008  
2009      install_link(ctx, link, with_sr0);
2010      if (is_n && use_nullify_skip(ctx)) {
2011          install_iaq_entries(ctx, &ctx->iaq_j, NULL);
2012          nullify_set(ctx, 0);
2013          store_psw_xb(ctx, 0);
2014      } else {
2015          install_iaq_entries(ctx, &ctx->iaq_b, &ctx->iaq_j);
2016          nullify_set(ctx, is_n);
2017          store_psw_xb(ctx, PSW_B);
2018      }
2019  
2020      tcg_gen_lookup_and_goto_ptr();
2021      ctx->base.is_jmp = DISAS_NORETURN;
2022      return nullify_end(ctx);
2023  }
2024  
2025  /* Implement
2026   *    if (IAOQ_Front{30..31} < GR[b]{30..31})
2027   *      IAOQ_Next{30..31} ← GR[b]{30..31};
2028   *    else
2029   *      IAOQ_Next{30..31} ← IAOQ_Front{30..31};
2030   * which keeps the privilege level from being increased.
2031   */
do_ibranch_priv(DisasContext * ctx,TCGv_i64 offset)2032  static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
2033  {
2034      TCGv_i64 dest = tcg_temp_new_i64();
2035      switch (ctx->privilege) {
2036      case 0:
2037          /* Privilege 0 is maximum and is allowed to decrease.  */
2038          tcg_gen_mov_i64(dest, offset);
2039          break;
2040      case 3:
2041          /* Privilege 3 is minimum and is never allowed to increase.  */
2042          tcg_gen_ori_i64(dest, offset, 3);
2043          break;
2044      default:
2045          tcg_gen_andi_i64(dest, offset, -4);
2046          tcg_gen_ori_i64(dest, dest, ctx->privilege);
2047          tcg_gen_umax_i64(dest, dest, offset);
2048          break;
2049      }
2050      return dest;
2051  }
2052  
2053  #ifdef CONFIG_USER_ONLY
2054  /* On Linux, page zero is normally marked execute only + gateway.
2055     Therefore normal read or write is supposed to fail, but specific
2056     offsets have kernel code mapped to raise permissions to implement
2057     system calls.  Handling this via an explicit check here, rather
2058     in than the "be disp(sr2,r0)" instruction that probably sent us
2059     here, is the easiest way to handle the branch delay slot on the
2060     aforementioned BE.  */
do_page_zero(DisasContext * ctx)2061  static void do_page_zero(DisasContext *ctx)
2062  {
2063      assert(ctx->iaq_f.disp == 0);
2064  
2065      /* If by some means we get here with PSW[N]=1, that implies that
2066         the B,GATE instruction would be skipped, and we'd fault on the
2067         next insn within the privileged page.  */
2068      switch (ctx->null_cond.c) {
2069      case TCG_COND_NEVER:
2070          break;
2071      case TCG_COND_ALWAYS:
2072          tcg_gen_movi_i64(cpu_psw_n, 0);
2073          goto do_sigill;
2074      default:
2075          /* Since this is always the first (and only) insn within the
2076             TB, we should know the state of PSW[N] from TB->FLAGS.  */
2077          g_assert_not_reached();
2078      }
2079  
2080      /* If PSW[B] is set, the B,GATE insn would trap. */
2081      if (ctx->psw_xb & PSW_B) {
2082          goto do_sigill;
2083      }
2084  
2085      switch (ctx->base.pc_first) {
2086      case 0x00: /* Null pointer call */
2087          gen_excp_1(EXCP_IMP);
2088          ctx->base.is_jmp = DISAS_NORETURN;
2089          break;
2090  
2091      case 0xb0: /* LWS */
2092          gen_excp_1(EXCP_SYSCALL_LWS);
2093          ctx->base.is_jmp = DISAS_NORETURN;
2094          break;
2095  
2096      case 0xe0: /* SET_THREAD_POINTER */
2097          {
2098              DisasIAQE next = { .base = tcg_temp_new_i64() };
2099  
2100              tcg_gen_st_i64(cpu_gr[26], tcg_env,
2101                             offsetof(CPUHPPAState, cr[27]));
2102              tcg_gen_ori_i64(next.base, cpu_gr[31], PRIV_USER);
2103              install_iaq_entries(ctx, &next, NULL);
2104              ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
2105          }
2106          break;
2107  
2108      case 0x100: /* SYSCALL */
2109          gen_excp_1(EXCP_SYSCALL);
2110          ctx->base.is_jmp = DISAS_NORETURN;
2111          break;
2112  
2113      default:
2114      do_sigill:
2115          gen_excp_1(EXCP_ILL);
2116          ctx->base.is_jmp = DISAS_NORETURN;
2117          break;
2118      }
2119  }
2120  #endif
2121  
trans_nop(DisasContext * ctx,arg_nop * a)2122  static bool trans_nop(DisasContext *ctx, arg_nop *a)
2123  {
2124      ctx->null_cond = cond_make_f();
2125      return true;
2126  }
2127  
trans_break(DisasContext * ctx,arg_break * a)2128  static bool trans_break(DisasContext *ctx, arg_break *a)
2129  {
2130      return gen_excp_iir(ctx, EXCP_BREAK);
2131  }
2132  
trans_sync(DisasContext * ctx,arg_sync * a)2133  static bool trans_sync(DisasContext *ctx, arg_sync *a)
2134  {
2135      /* No point in nullifying the memory barrier.  */
2136      tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
2137  
2138      ctx->null_cond = cond_make_f();
2139      return true;
2140  }
2141  
trans_mfia(DisasContext * ctx,arg_mfia * a)2142  static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
2143  {
2144      TCGv_i64 dest = dest_gpr(ctx, a->t);
2145  
2146      copy_iaoq_entry(ctx, dest, &ctx->iaq_f);
2147      tcg_gen_andi_i64(dest, dest, -4);
2148  
2149      save_gpr(ctx, a->t, dest);
2150      ctx->null_cond = cond_make_f();
2151      return true;
2152  }
2153  
trans_mfsp(DisasContext * ctx,arg_mfsp * a)2154  static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
2155  {
2156      unsigned rt = a->t;
2157      unsigned rs = a->sp;
2158      TCGv_i64 t0 = tcg_temp_new_i64();
2159  
2160      load_spr(ctx, t0, rs);
2161      tcg_gen_shri_i64(t0, t0, 32);
2162  
2163      save_gpr(ctx, rt, t0);
2164  
2165      ctx->null_cond = cond_make_f();
2166      return true;
2167  }
2168  
trans_mfctl(DisasContext * ctx,arg_mfctl * a)2169  static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
2170  {
2171      unsigned rt = a->t;
2172      unsigned ctl = a->r;
2173      TCGv_i64 tmp;
2174  
2175      switch (ctl) {
2176      case CR_SAR:
2177          if (a->e == 0) {
2178              /* MFSAR without ,W masks low 5 bits.  */
2179              tmp = dest_gpr(ctx, rt);
2180              tcg_gen_andi_i64(tmp, cpu_sar, 31);
2181              save_gpr(ctx, rt, tmp);
2182              goto done;
2183          }
2184          save_gpr(ctx, rt, cpu_sar);
2185          goto done;
2186      case CR_IT: /* Interval Timer */
2187          /* FIXME: Respect PSW_S bit.  */
2188          nullify_over(ctx);
2189          tmp = dest_gpr(ctx, rt);
2190          if (translator_io_start(&ctx->base)) {
2191              ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2192          }
2193          gen_helper_read_interval_timer(tmp);
2194          save_gpr(ctx, rt, tmp);
2195          return nullify_end(ctx);
2196      case 26:
2197      case 27:
2198          break;
2199      default:
2200          /* All other control registers are privileged.  */
2201          CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2202          break;
2203      }
2204  
2205      tmp = tcg_temp_new_i64();
2206      tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2207      save_gpr(ctx, rt, tmp);
2208  
2209   done:
2210      ctx->null_cond = cond_make_f();
2211      return true;
2212  }
2213  
trans_mtsp(DisasContext * ctx,arg_mtsp * a)2214  static bool trans_mtsp(DisasContext *ctx, arg_mtsp *a)
2215  {
2216      unsigned rr = a->r;
2217      unsigned rs = a->sp;
2218      TCGv_i64 tmp;
2219  
2220      if (rs >= 5) {
2221          CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2222      }
2223      nullify_over(ctx);
2224  
2225      tmp = tcg_temp_new_i64();
2226      tcg_gen_shli_i64(tmp, load_gpr(ctx, rr), 32);
2227  
2228      if (rs >= 4) {
2229          tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUHPPAState, sr[rs]));
2230          ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2231      } else {
2232          tcg_gen_mov_i64(cpu_sr[rs], tmp);
2233      }
2234  
2235      return nullify_end(ctx);
2236  }
2237  
trans_mtctl(DisasContext * ctx,arg_mtctl * a)2238  static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
2239  {
2240      unsigned ctl = a->t;
2241      TCGv_i64 reg;
2242      TCGv_i64 tmp;
2243  
2244      if (ctl == CR_SAR) {
2245          reg = load_gpr(ctx, a->r);
2246          tmp = tcg_temp_new_i64();
2247          tcg_gen_andi_i64(tmp, reg, ctx->is_pa20 ? 63 : 31);
2248          save_or_nullify(ctx, cpu_sar, tmp);
2249  
2250          ctx->null_cond = cond_make_f();
2251          return true;
2252      }
2253  
2254      /* All other control registers are privileged or read-only.  */
2255      CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2256  
2257  #ifndef CONFIG_USER_ONLY
2258      nullify_over(ctx);
2259  
2260      if (ctx->is_pa20) {
2261          reg = load_gpr(ctx, a->r);
2262      } else {
2263          reg = tcg_temp_new_i64();
2264          tcg_gen_ext32u_i64(reg, load_gpr(ctx, a->r));
2265      }
2266  
2267      switch (ctl) {
2268      case CR_IT:
2269          if (translator_io_start(&ctx->base)) {
2270              ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2271          }
2272          gen_helper_write_interval_timer(tcg_env, reg);
2273          break;
2274      case CR_EIRR:
2275          /* Helper modifies interrupt lines and is therefore IO. */
2276          translator_io_start(&ctx->base);
2277          gen_helper_write_eirr(tcg_env, reg);
2278          /* Exit to re-evaluate interrupts in the main loop. */
2279          ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2280          break;
2281  
2282      case CR_IIASQ:
2283      case CR_IIAOQ:
2284          /* FIXME: Respect PSW_Q bit */
2285          /* The write advances the queue and stores to the back element.  */
2286          tmp = tcg_temp_new_i64();
2287          tcg_gen_ld_i64(tmp, tcg_env,
2288                         offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2289          tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2290          tcg_gen_st_i64(reg, tcg_env,
2291                         offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2292          break;
2293  
2294      case CR_PID1:
2295      case CR_PID2:
2296      case CR_PID3:
2297      case CR_PID4:
2298          tcg_gen_st_i64(reg, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2299  #ifndef CONFIG_USER_ONLY
2300          gen_helper_change_prot_id(tcg_env);
2301  #endif
2302          break;
2303  
2304      case CR_EIEM:
2305          /* Exit to re-evaluate interrupts in the main loop. */
2306          ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2307          /* FALLTHRU */
2308      default:
2309          tcg_gen_st_i64(reg, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2310          break;
2311      }
2312      return nullify_end(ctx);
2313  #endif
2314  }
2315  
trans_mtsarcm(DisasContext * ctx,arg_mtsarcm * a)2316  static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
2317  {
2318      TCGv_i64 tmp = tcg_temp_new_i64();
2319  
2320      tcg_gen_not_i64(tmp, load_gpr(ctx, a->r));
2321      tcg_gen_andi_i64(tmp, tmp, ctx->is_pa20 ? 63 : 31);
2322      save_or_nullify(ctx, cpu_sar, tmp);
2323  
2324      ctx->null_cond = cond_make_f();
2325      return true;
2326  }
2327  
trans_ldsid(DisasContext * ctx,arg_ldsid * a)2328  static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
2329  {
2330      TCGv_i64 dest = dest_gpr(ctx, a->t);
2331  
2332  #ifdef CONFIG_USER_ONLY
2333      /* We don't implement space registers in user mode. */
2334      tcg_gen_movi_i64(dest, 0);
2335  #else
2336      tcg_gen_mov_i64(dest, space_select(ctx, a->sp, load_gpr(ctx, a->b)));
2337      tcg_gen_shri_i64(dest, dest, 32);
2338  #endif
2339      save_gpr(ctx, a->t, dest);
2340  
2341      ctx->null_cond = cond_make_f();
2342      return true;
2343  }
2344  
trans_rsm(DisasContext * ctx,arg_rsm * a)2345  static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
2346  {
2347  #ifdef CONFIG_USER_ONLY
2348      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2349  #else
2350      TCGv_i64 tmp;
2351  
2352      /* HP-UX 11i and HP ODE use rsm for read-access to PSW */
2353      if (a->i) {
2354          CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2355      }
2356  
2357      nullify_over(ctx);
2358  
2359      tmp = tcg_temp_new_i64();
2360      tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, psw));
2361      tcg_gen_andi_i64(tmp, tmp, ~a->i);
2362      gen_helper_swap_system_mask(tmp, tcg_env, tmp);
2363      save_gpr(ctx, a->t, tmp);
2364  
2365      /* Exit the TB to recognize new interrupts, e.g. PSW_M.  */
2366      ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2367      return nullify_end(ctx);
2368  #endif
2369  }
2370  
trans_ssm(DisasContext * ctx,arg_ssm * a)2371  static bool trans_ssm(DisasContext *ctx, arg_ssm *a)
2372  {
2373      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2374  #ifndef CONFIG_USER_ONLY
2375      TCGv_i64 tmp;
2376  
2377      nullify_over(ctx);
2378  
2379      tmp = tcg_temp_new_i64();
2380      tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, psw));
2381      tcg_gen_ori_i64(tmp, tmp, a->i);
2382      gen_helper_swap_system_mask(tmp, tcg_env, tmp);
2383      save_gpr(ctx, a->t, tmp);
2384  
2385      /* Exit the TB to recognize new interrupts, e.g. PSW_I.  */
2386      ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2387      return nullify_end(ctx);
2388  #endif
2389  }
2390  
trans_mtsm(DisasContext * ctx,arg_mtsm * a)2391  static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a)
2392  {
2393      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2394  #ifndef CONFIG_USER_ONLY
2395      TCGv_i64 tmp, reg;
2396      nullify_over(ctx);
2397  
2398      reg = load_gpr(ctx, a->r);
2399      tmp = tcg_temp_new_i64();
2400      gen_helper_swap_system_mask(tmp, tcg_env, reg);
2401  
2402      /* Exit the TB to recognize new interrupts.  */
2403      ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2404      return nullify_end(ctx);
2405  #endif
2406  }
2407  
do_rfi(DisasContext * ctx,bool rfi_r)2408  static bool do_rfi(DisasContext *ctx, bool rfi_r)
2409  {
2410      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2411  #ifndef CONFIG_USER_ONLY
2412      nullify_over(ctx);
2413  
2414      if (rfi_r) {
2415          gen_helper_rfi_r(tcg_env);
2416      } else {
2417          gen_helper_rfi(tcg_env);
2418      }
2419      /* Exit the TB to recognize new interrupts.  */
2420      tcg_gen_exit_tb(NULL, 0);
2421      ctx->base.is_jmp = DISAS_NORETURN;
2422  
2423      return nullify_end(ctx);
2424  #endif
2425  }
2426  
trans_rfi(DisasContext * ctx,arg_rfi * a)2427  static bool trans_rfi(DisasContext *ctx, arg_rfi *a)
2428  {
2429      return do_rfi(ctx, false);
2430  }
2431  
trans_rfi_r(DisasContext * ctx,arg_rfi_r * a)2432  static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a)
2433  {
2434      return do_rfi(ctx, true);
2435  }
2436  
trans_halt(DisasContext * ctx,arg_halt * a)2437  static bool trans_halt(DisasContext *ctx, arg_halt *a)
2438  {
2439      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2440  #ifndef CONFIG_USER_ONLY
2441      set_psw_xb(ctx, 0);
2442      nullify_over(ctx);
2443      gen_helper_halt(tcg_env);
2444      ctx->base.is_jmp = DISAS_NORETURN;
2445      return nullify_end(ctx);
2446  #endif
2447  }
2448  
trans_reset(DisasContext * ctx,arg_reset * a)2449  static bool trans_reset(DisasContext *ctx, arg_reset *a)
2450  {
2451      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2452  #ifndef CONFIG_USER_ONLY
2453      set_psw_xb(ctx, 0);
2454      nullify_over(ctx);
2455      gen_helper_reset(tcg_env);
2456      ctx->base.is_jmp = DISAS_NORETURN;
2457      return nullify_end(ctx);
2458  #endif
2459  }
2460  
do_getshadowregs(DisasContext * ctx)2461  static bool do_getshadowregs(DisasContext *ctx)
2462  {
2463      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2464      nullify_over(ctx);
2465      tcg_gen_ld_i64(cpu_gr[1], tcg_env, offsetof(CPUHPPAState, shadow[0]));
2466      tcg_gen_ld_i64(cpu_gr[8], tcg_env, offsetof(CPUHPPAState, shadow[1]));
2467      tcg_gen_ld_i64(cpu_gr[9], tcg_env, offsetof(CPUHPPAState, shadow[2]));
2468      tcg_gen_ld_i64(cpu_gr[16], tcg_env, offsetof(CPUHPPAState, shadow[3]));
2469      tcg_gen_ld_i64(cpu_gr[17], tcg_env, offsetof(CPUHPPAState, shadow[4]));
2470      tcg_gen_ld_i64(cpu_gr[24], tcg_env, offsetof(CPUHPPAState, shadow[5]));
2471      tcg_gen_ld_i64(cpu_gr[25], tcg_env, offsetof(CPUHPPAState, shadow[6]));
2472      return nullify_end(ctx);
2473  }
2474  
do_putshadowregs(DisasContext * ctx)2475  static bool do_putshadowregs(DisasContext *ctx)
2476  {
2477      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2478      nullify_over(ctx);
2479      tcg_gen_st_i64(cpu_gr[1], tcg_env, offsetof(CPUHPPAState, shadow[0]));
2480      tcg_gen_st_i64(cpu_gr[8], tcg_env, offsetof(CPUHPPAState, shadow[1]));
2481      tcg_gen_st_i64(cpu_gr[9], tcg_env, offsetof(CPUHPPAState, shadow[2]));
2482      tcg_gen_st_i64(cpu_gr[16], tcg_env, offsetof(CPUHPPAState, shadow[3]));
2483      tcg_gen_st_i64(cpu_gr[17], tcg_env, offsetof(CPUHPPAState, shadow[4]));
2484      tcg_gen_st_i64(cpu_gr[24], tcg_env, offsetof(CPUHPPAState, shadow[5]));
2485      tcg_gen_st_i64(cpu_gr[25], tcg_env, offsetof(CPUHPPAState, shadow[6]));
2486      return nullify_end(ctx);
2487  }
2488  
trans_getshadowregs(DisasContext * ctx,arg_getshadowregs * a)2489  static bool trans_getshadowregs(DisasContext *ctx, arg_getshadowregs *a)
2490  {
2491      return do_getshadowregs(ctx);
2492  }
2493  
trans_nop_addrx(DisasContext * ctx,arg_ldst * a)2494  static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
2495  {
2496      if (a->m) {
2497          TCGv_i64 dest = dest_gpr(ctx, a->b);
2498          TCGv_i64 src1 = load_gpr(ctx, a->b);
2499          TCGv_i64 src2 = load_gpr(ctx, a->x);
2500  
2501          /* The only thing we need to do is the base register modification.  */
2502          tcg_gen_add_i64(dest, src1, src2);
2503          save_gpr(ctx, a->b, dest);
2504      }
2505      ctx->null_cond = cond_make_f();
2506      return true;
2507  }
2508  
trans_fic(DisasContext * ctx,arg_ldst * a)2509  static bool trans_fic(DisasContext *ctx, arg_ldst *a)
2510  {
2511      /* End TB for flush instruction cache, so we pick up new insns. */
2512      ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2513      return trans_nop_addrx(ctx, a);
2514  }
2515  
trans_probe(DisasContext * ctx,arg_probe * a)2516  static bool trans_probe(DisasContext *ctx, arg_probe *a)
2517  {
2518      TCGv_i64 dest, ofs;
2519      TCGv_i32 level, want;
2520      TCGv_i64 addr;
2521  
2522      nullify_over(ctx);
2523  
2524      dest = dest_gpr(ctx, a->t);
2525      form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2526  
2527      if (a->imm) {
2528          level = tcg_constant_i32(a->ri & 3);
2529      } else {
2530          level = tcg_temp_new_i32();
2531          tcg_gen_extrl_i64_i32(level, load_gpr(ctx, a->ri));
2532          tcg_gen_andi_i32(level, level, 3);
2533      }
2534      want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ);
2535  
2536      gen_helper_probe(dest, tcg_env, addr, level, want);
2537  
2538      save_gpr(ctx, a->t, dest);
2539      return nullify_end(ctx);
2540  }
2541  
trans_ixtlbx(DisasContext * ctx,arg_ixtlbx * a)2542  static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
2543  {
2544      if (ctx->is_pa20) {
2545          return false;
2546      }
2547      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2548  #ifndef CONFIG_USER_ONLY
2549      TCGv_i64 addr;
2550      TCGv_i64 ofs, reg;
2551  
2552      nullify_over(ctx);
2553  
2554      form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2555      reg = load_gpr(ctx, a->r);
2556      if (a->addr) {
2557          gen_helper_itlba_pa11(tcg_env, addr, reg);
2558      } else {
2559          gen_helper_itlbp_pa11(tcg_env, addr, reg);
2560      }
2561  
2562      /* Exit TB for TLB change if mmu is enabled.  */
2563      if (ctx->tb_flags & PSW_C) {
2564          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2565      }
2566      return nullify_end(ctx);
2567  #endif
2568  }
2569  
do_pxtlb(DisasContext * ctx,arg_ldst * a,bool local)2570  static bool do_pxtlb(DisasContext *ctx, arg_ldst *a, bool local)
2571  {
2572      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2573  #ifndef CONFIG_USER_ONLY
2574      TCGv_i64 addr;
2575      TCGv_i64 ofs;
2576  
2577      nullify_over(ctx);
2578  
2579      form_gva(ctx, &addr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2580  
2581      /*
2582       * Page align now, rather than later, so that we can add in the
2583       * page_size field from pa2.0 from the low 4 bits of GR[b].
2584       */
2585      tcg_gen_andi_i64(addr, addr, TARGET_PAGE_MASK);
2586      if (ctx->is_pa20) {
2587          tcg_gen_deposit_i64(addr, addr, load_gpr(ctx, a->b), 0, 4);
2588      }
2589  
2590      if (local) {
2591          gen_helper_ptlb_l(tcg_env, addr);
2592      } else {
2593          gen_helper_ptlb(tcg_env, addr);
2594      }
2595  
2596      if (a->m) {
2597          save_gpr(ctx, a->b, ofs);
2598      }
2599  
2600      /* Exit TB for TLB change if mmu is enabled.  */
2601      if (ctx->tb_flags & PSW_C) {
2602          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2603      }
2604      return nullify_end(ctx);
2605  #endif
2606  }
2607  
trans_pxtlb(DisasContext * ctx,arg_ldst * a)2608  static bool trans_pxtlb(DisasContext *ctx, arg_ldst *a)
2609  {
2610      return do_pxtlb(ctx, a, false);
2611  }
2612  
trans_pxtlb_l(DisasContext * ctx,arg_ldst * a)2613  static bool trans_pxtlb_l(DisasContext *ctx, arg_ldst *a)
2614  {
2615      return ctx->is_pa20 && do_pxtlb(ctx, a, true);
2616  }
2617  
trans_pxtlbe(DisasContext * ctx,arg_ldst * a)2618  static bool trans_pxtlbe(DisasContext *ctx, arg_ldst *a)
2619  {
2620      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2621  #ifndef CONFIG_USER_ONLY
2622      nullify_over(ctx);
2623  
2624      trans_nop_addrx(ctx, a);
2625      gen_helper_ptlbe(tcg_env);
2626  
2627      /* Exit TB for TLB change if mmu is enabled.  */
2628      if (ctx->tb_flags & PSW_C) {
2629          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2630      }
2631      return nullify_end(ctx);
2632  #endif
2633  }
2634  
2635  /*
2636   * Implement the pcxl and pcxl2 Fast TLB Insert instructions.
2637   * See
2638   *     https://parisc.wiki.kernel.org/images-parisc/a/a9/Pcxl2_ers.pdf
2639   *     page 13-9 (195/206)
2640   */
trans_ixtlbxf(DisasContext * ctx,arg_ixtlbxf * a)2641  static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
2642  {
2643      if (ctx->is_pa20) {
2644          return false;
2645      }
2646      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2647  #ifndef CONFIG_USER_ONLY
2648      TCGv_i64 addr, atl, stl;
2649      TCGv_i64 reg;
2650  
2651      nullify_over(ctx);
2652  
2653      /*
2654       * FIXME:
2655       *  if (not (pcxl or pcxl2))
2656       *    return gen_illegal(ctx);
2657       */
2658  
2659      atl = tcg_temp_new_i64();
2660      stl = tcg_temp_new_i64();
2661      addr = tcg_temp_new_i64();
2662  
2663      tcg_gen_ld32u_i64(stl, tcg_env,
2664                        a->data ? offsetof(CPUHPPAState, cr[CR_ISR])
2665                        : offsetof(CPUHPPAState, cr[CR_IIASQ]));
2666      tcg_gen_ld32u_i64(atl, tcg_env,
2667                        a->data ? offsetof(CPUHPPAState, cr[CR_IOR])
2668                        : offsetof(CPUHPPAState, cr[CR_IIAOQ]));
2669      tcg_gen_shli_i64(stl, stl, 32);
2670      tcg_gen_or_i64(addr, atl, stl);
2671  
2672      reg = load_gpr(ctx, a->r);
2673      if (a->addr) {
2674          gen_helper_itlba_pa11(tcg_env, addr, reg);
2675      } else {
2676          gen_helper_itlbp_pa11(tcg_env, addr, reg);
2677      }
2678  
2679      /* Exit TB for TLB change if mmu is enabled.  */
2680      if (ctx->tb_flags & PSW_C) {
2681          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2682      }
2683      return nullify_end(ctx);
2684  #endif
2685  }
2686  
trans_ixtlbt(DisasContext * ctx,arg_ixtlbt * a)2687  static bool trans_ixtlbt(DisasContext *ctx, arg_ixtlbt *a)
2688  {
2689      if (!ctx->is_pa20) {
2690          return false;
2691      }
2692      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2693  #ifndef CONFIG_USER_ONLY
2694      nullify_over(ctx);
2695      {
2696          TCGv_i64 src1 = load_gpr(ctx, a->r1);
2697          TCGv_i64 src2 = load_gpr(ctx, a->r2);
2698  
2699          if (a->data) {
2700              gen_helper_idtlbt_pa20(tcg_env, src1, src2);
2701          } else {
2702              gen_helper_iitlbt_pa20(tcg_env, src1, src2);
2703          }
2704      }
2705      /* Exit TB for TLB change if mmu is enabled.  */
2706      if (ctx->tb_flags & PSW_C) {
2707          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2708      }
2709      return nullify_end(ctx);
2710  #endif
2711  }
2712  
trans_lpa(DisasContext * ctx,arg_ldst * a)2713  static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
2714  {
2715      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2716  #ifndef CONFIG_USER_ONLY
2717      TCGv_i64 vaddr;
2718      TCGv_i64 ofs, paddr;
2719  
2720      nullify_over(ctx);
2721  
2722      form_gva(ctx, &vaddr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2723  
2724      paddr = tcg_temp_new_i64();
2725      gen_helper_lpa(paddr, tcg_env, vaddr);
2726  
2727      /* Note that physical address result overrides base modification.  */
2728      if (a->m) {
2729          save_gpr(ctx, a->b, ofs);
2730      }
2731      save_gpr(ctx, a->t, paddr);
2732  
2733      return nullify_end(ctx);
2734  #endif
2735  }
2736  
trans_lci(DisasContext * ctx,arg_lci * a)2737  static bool trans_lci(DisasContext *ctx, arg_lci *a)
2738  {
2739      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2740  
2741      /* The Coherence Index is an implementation-defined function of the
2742         physical address.  Two addresses with the same CI have a coherent
2743         view of the cache.  Our implementation is to return 0 for all,
2744         since the entire address space is coherent.  */
2745      save_gpr(ctx, a->t, ctx->zero);
2746  
2747      ctx->null_cond = cond_make_f();
2748      return true;
2749  }
2750  
trans_add(DisasContext * ctx,arg_rrr_cf_d_sh * a)2751  static bool trans_add(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2752  {
2753      return do_add_reg(ctx, a, false, false, false, false);
2754  }
2755  
trans_add_l(DisasContext * ctx,arg_rrr_cf_d_sh * a)2756  static bool trans_add_l(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2757  {
2758      return do_add_reg(ctx, a, true, false, false, false);
2759  }
2760  
trans_add_tsv(DisasContext * ctx,arg_rrr_cf_d_sh * a)2761  static bool trans_add_tsv(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2762  {
2763      return do_add_reg(ctx, a, false, true, false, false);
2764  }
2765  
trans_add_c(DisasContext * ctx,arg_rrr_cf_d_sh * a)2766  static bool trans_add_c(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2767  {
2768      return do_add_reg(ctx, a, false, false, false, true);
2769  }
2770  
trans_add_c_tsv(DisasContext * ctx,arg_rrr_cf_d_sh * a)2771  static bool trans_add_c_tsv(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2772  {
2773      return do_add_reg(ctx, a, false, true, false, true);
2774  }
2775  
trans_sub(DisasContext * ctx,arg_rrr_cf_d * a)2776  static bool trans_sub(DisasContext *ctx, arg_rrr_cf_d *a)
2777  {
2778      return do_sub_reg(ctx, a, false, false, false);
2779  }
2780  
trans_sub_tsv(DisasContext * ctx,arg_rrr_cf_d * a)2781  static bool trans_sub_tsv(DisasContext *ctx, arg_rrr_cf_d *a)
2782  {
2783      return do_sub_reg(ctx, a, true, false, false);
2784  }
2785  
trans_sub_tc(DisasContext * ctx,arg_rrr_cf_d * a)2786  static bool trans_sub_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2787  {
2788      return do_sub_reg(ctx, a, false, false, true);
2789  }
2790  
trans_sub_tsv_tc(DisasContext * ctx,arg_rrr_cf_d * a)2791  static bool trans_sub_tsv_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2792  {
2793      return do_sub_reg(ctx, a, true, false, true);
2794  }
2795  
trans_sub_b(DisasContext * ctx,arg_rrr_cf_d * a)2796  static bool trans_sub_b(DisasContext *ctx, arg_rrr_cf_d *a)
2797  {
2798      return do_sub_reg(ctx, a, false, true, false);
2799  }
2800  
trans_sub_b_tsv(DisasContext * ctx,arg_rrr_cf_d * a)2801  static bool trans_sub_b_tsv(DisasContext *ctx, arg_rrr_cf_d *a)
2802  {
2803      return do_sub_reg(ctx, a, true, true, false);
2804  }
2805  
trans_andcm(DisasContext * ctx,arg_rrr_cf_d * a)2806  static bool trans_andcm(DisasContext *ctx, arg_rrr_cf_d *a)
2807  {
2808      return do_log_reg(ctx, a, tcg_gen_andc_i64);
2809  }
2810  
trans_and(DisasContext * ctx,arg_rrr_cf_d * a)2811  static bool trans_and(DisasContext *ctx, arg_rrr_cf_d *a)
2812  {
2813      return do_log_reg(ctx, a, tcg_gen_and_i64);
2814  }
2815  
trans_or(DisasContext * ctx,arg_rrr_cf_d * a)2816  static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
2817  {
2818      if (a->cf == 0) {
2819          unsigned r2 = a->r2;
2820          unsigned r1 = a->r1;
2821          unsigned rt = a->t;
2822  
2823          if (rt == 0) { /* NOP */
2824              ctx->null_cond = cond_make_f();
2825              return true;
2826          }
2827          if (r2 == 0) { /* COPY */
2828              if (r1 == 0) {
2829                  TCGv_i64 dest = dest_gpr(ctx, rt);
2830                  tcg_gen_movi_i64(dest, 0);
2831                  save_gpr(ctx, rt, dest);
2832              } else {
2833                  save_gpr(ctx, rt, cpu_gr[r1]);
2834              }
2835              ctx->null_cond = cond_make_f();
2836              return true;
2837          }
2838  #ifndef CONFIG_USER_ONLY
2839          /* These are QEMU extensions and are nops in the real architecture:
2840           *
2841           * or %r10,%r10,%r10 -- idle loop; wait for interrupt
2842           * or %r31,%r31,%r31 -- death loop; offline cpu
2843           *                      currently implemented as idle.
2844           */
2845          if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
2846              /* No need to check for supervisor, as userland can only pause
2847                 until the next timer interrupt.  */
2848  
2849              set_psw_xb(ctx, 0);
2850  
2851              nullify_over(ctx);
2852  
2853              /* Advance the instruction queue.  */
2854              install_iaq_entries(ctx, &ctx->iaq_b, NULL);
2855              nullify_set(ctx, 0);
2856  
2857              /* Tell the qemu main loop to halt until this cpu has work.  */
2858              tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
2859                             offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2860              gen_excp_1(EXCP_HALTED);
2861              ctx->base.is_jmp = DISAS_NORETURN;
2862  
2863              return nullify_end(ctx);
2864          }
2865  #endif
2866      }
2867      return do_log_reg(ctx, a, tcg_gen_or_i64);
2868  }
2869  
trans_xor(DisasContext * ctx,arg_rrr_cf_d * a)2870  static bool trans_xor(DisasContext *ctx, arg_rrr_cf_d *a)
2871  {
2872      return do_log_reg(ctx, a, tcg_gen_xor_i64);
2873  }
2874  
trans_cmpclr(DisasContext * ctx,arg_rrr_cf_d * a)2875  static bool trans_cmpclr(DisasContext *ctx, arg_rrr_cf_d *a)
2876  {
2877      TCGv_i64 tcg_r1, tcg_r2;
2878  
2879      if (a->cf) {
2880          nullify_over(ctx);
2881      }
2882      tcg_r1 = load_gpr(ctx, a->r1);
2883      tcg_r2 = load_gpr(ctx, a->r2);
2884      do_cmpclr(ctx, a->t, tcg_r1, tcg_r2, a->cf, a->d);
2885      return nullify_end(ctx);
2886  }
2887  
trans_uxor(DisasContext * ctx,arg_rrr_cf_d * a)2888  static bool trans_uxor(DisasContext *ctx, arg_rrr_cf_d *a)
2889  {
2890      TCGv_i64 tcg_r1, tcg_r2, dest;
2891  
2892      if (a->cf) {
2893          nullify_over(ctx);
2894      }
2895  
2896      tcg_r1 = load_gpr(ctx, a->r1);
2897      tcg_r2 = load_gpr(ctx, a->r2);
2898      dest = dest_gpr(ctx, a->t);
2899  
2900      tcg_gen_xor_i64(dest, tcg_r1, tcg_r2);
2901      save_gpr(ctx, a->t, dest);
2902  
2903      ctx->null_cond = do_unit_zero_cond(a->cf, a->d, dest);
2904      return nullify_end(ctx);
2905  }
2906  
do_uaddcm(DisasContext * ctx,arg_rrr_cf_d * a,bool is_tc)2907  static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf_d *a, bool is_tc)
2908  {
2909      TCGv_i64 tcg_r1, tcg_r2, tmp;
2910  
2911      if (a->cf == 0) {
2912          tcg_r2 = load_gpr(ctx, a->r2);
2913          tmp = dest_gpr(ctx, a->t);
2914  
2915          if (a->r1 == 0) {
2916              /* UADDCM r0,src,dst is the common idiom for dst = ~src. */
2917              tcg_gen_not_i64(tmp, tcg_r2);
2918          } else {
2919              /*
2920               * Recall that r1 - r2 == r1 + ~r2 + 1.
2921               * Thus r1 + ~r2 == r1 - r2 - 1,
2922               * which does not require an extra temporary.
2923               */
2924              tcg_r1 = load_gpr(ctx, a->r1);
2925              tcg_gen_sub_i64(tmp, tcg_r1, tcg_r2);
2926              tcg_gen_subi_i64(tmp, tmp, 1);
2927          }
2928          save_gpr(ctx, a->t, tmp);
2929          ctx->null_cond = cond_make_f();
2930          return true;
2931      }
2932  
2933      nullify_over(ctx);
2934      tcg_r1 = load_gpr(ctx, a->r1);
2935      tcg_r2 = load_gpr(ctx, a->r2);
2936      tmp = tcg_temp_new_i64();
2937      tcg_gen_not_i64(tmp, tcg_r2);
2938      do_unit_addsub(ctx, a->t, tcg_r1, tmp, a->cf, a->d, is_tc, true);
2939      return nullify_end(ctx);
2940  }
2941  
trans_uaddcm(DisasContext * ctx,arg_rrr_cf_d * a)2942  static bool trans_uaddcm(DisasContext *ctx, arg_rrr_cf_d *a)
2943  {
2944      return do_uaddcm(ctx, a, false);
2945  }
2946  
trans_uaddcm_tc(DisasContext * ctx,arg_rrr_cf_d * a)2947  static bool trans_uaddcm_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2948  {
2949      return do_uaddcm(ctx, a, true);
2950  }
2951  
do_dcor(DisasContext * ctx,arg_rr_cf_d * a,bool is_i)2952  static bool do_dcor(DisasContext *ctx, arg_rr_cf_d *a, bool is_i)
2953  {
2954      TCGv_i64 tmp;
2955  
2956      nullify_over(ctx);
2957  
2958      tmp = tcg_temp_new_i64();
2959      tcg_gen_extract2_i64(tmp, cpu_psw_cb, cpu_psw_cb_msb, 4);
2960      if (!is_i) {
2961          tcg_gen_not_i64(tmp, tmp);
2962      }
2963      tcg_gen_andi_i64(tmp, tmp, (uint64_t)0x1111111111111111ull);
2964      tcg_gen_muli_i64(tmp, tmp, 6);
2965      do_unit_addsub(ctx, a->t, load_gpr(ctx, a->r), tmp,
2966                     a->cf, a->d, false, is_i);
2967      return nullify_end(ctx);
2968  }
2969  
trans_dcor(DisasContext * ctx,arg_rr_cf_d * a)2970  static bool trans_dcor(DisasContext *ctx, arg_rr_cf_d *a)
2971  {
2972      return do_dcor(ctx, a, false);
2973  }
2974  
trans_dcor_i(DisasContext * ctx,arg_rr_cf_d * a)2975  static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf_d *a)
2976  {
2977      return do_dcor(ctx, a, true);
2978  }
2979  
trans_ds(DisasContext * ctx,arg_rrr_cf * a)2980  static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
2981  {
2982      TCGv_i64 dest, add1, add2, addc, in1, in2;
2983  
2984      nullify_over(ctx);
2985  
2986      in1 = load_gpr(ctx, a->r1);
2987      in2 = load_gpr(ctx, a->r2);
2988  
2989      add1 = tcg_temp_new_i64();
2990      add2 = tcg_temp_new_i64();
2991      addc = tcg_temp_new_i64();
2992      dest = tcg_temp_new_i64();
2993  
2994      /* Form R1 << 1 | PSW[CB]{8}.  */
2995      tcg_gen_add_i64(add1, in1, in1);
2996      tcg_gen_add_i64(add1, add1, get_psw_carry(ctx, false));
2997  
2998      /*
2999       * Add or subtract R2, depending on PSW[V].  Proper computation of
3000       * carry requires that we subtract via + ~R2 + 1, as described in
3001       * the manual.  By extracting and masking V, we can produce the
3002       * proper inputs to the addition without movcond.
3003       */
3004      tcg_gen_sextract_i64(addc, cpu_psw_v, 31, 1);
3005      tcg_gen_xor_i64(add2, in2, addc);
3006      tcg_gen_andi_i64(addc, addc, 1);
3007  
3008      tcg_gen_add2_i64(dest, cpu_psw_cb_msb, add1, ctx->zero, add2, ctx->zero);
3009      tcg_gen_add2_i64(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb,
3010                       addc, ctx->zero);
3011  
3012      /* Write back the result register.  */
3013      save_gpr(ctx, a->t, dest);
3014  
3015      /* Write back PSW[CB].  */
3016      tcg_gen_xor_i64(cpu_psw_cb, add1, add2);
3017      tcg_gen_xor_i64(cpu_psw_cb, cpu_psw_cb, dest);
3018  
3019      /*
3020       * Write back PSW[V] for the division step.
3021       * Shift cb{8} from where it lives in bit 32 to bit 31,
3022       * so that it overlaps r2{32} in bit 31.
3023       */
3024      tcg_gen_shri_i64(cpu_psw_v, cpu_psw_cb, 1);
3025      tcg_gen_xor_i64(cpu_psw_v, cpu_psw_v, in2);
3026  
3027      /* Install the new nullification.  */
3028      if (a->cf) {
3029          TCGv_i64 sv = NULL, uv = NULL;
3030          if (cond_need_sv(a->cf >> 1)) {
3031              sv = do_add_sv(ctx, dest, add1, add2, in1, 1, false);
3032          } else if (cond_need_cb(a->cf >> 1)) {
3033              uv = do_add_uv(ctx, cpu_psw_cb, NULL, in1, 1, false);
3034          }
3035          ctx->null_cond = do_cond(ctx, a->cf, false, dest, uv, sv);
3036      }
3037  
3038      return nullify_end(ctx);
3039  }
3040  
trans_addi(DisasContext * ctx,arg_rri_cf * a)3041  static bool trans_addi(DisasContext *ctx, arg_rri_cf *a)
3042  {
3043      return do_add_imm(ctx, a, false, false);
3044  }
3045  
trans_addi_tsv(DisasContext * ctx,arg_rri_cf * a)3046  static bool trans_addi_tsv(DisasContext *ctx, arg_rri_cf *a)
3047  {
3048      return do_add_imm(ctx, a, true, false);
3049  }
3050  
trans_addi_tc(DisasContext * ctx,arg_rri_cf * a)3051  static bool trans_addi_tc(DisasContext *ctx, arg_rri_cf *a)
3052  {
3053      return do_add_imm(ctx, a, false, true);
3054  }
3055  
trans_addi_tc_tsv(DisasContext * ctx,arg_rri_cf * a)3056  static bool trans_addi_tc_tsv(DisasContext *ctx, arg_rri_cf *a)
3057  {
3058      return do_add_imm(ctx, a, true, true);
3059  }
3060  
trans_subi(DisasContext * ctx,arg_rri_cf * a)3061  static bool trans_subi(DisasContext *ctx, arg_rri_cf *a)
3062  {
3063      return do_sub_imm(ctx, a, false);
3064  }
3065  
trans_subi_tsv(DisasContext * ctx,arg_rri_cf * a)3066  static bool trans_subi_tsv(DisasContext *ctx, arg_rri_cf *a)
3067  {
3068      return do_sub_imm(ctx, a, true);
3069  }
3070  
trans_cmpiclr(DisasContext * ctx,arg_rri_cf_d * a)3071  static bool trans_cmpiclr(DisasContext *ctx, arg_rri_cf_d *a)
3072  {
3073      TCGv_i64 tcg_im, tcg_r2;
3074  
3075      if (a->cf) {
3076          nullify_over(ctx);
3077      }
3078  
3079      tcg_im = tcg_constant_i64(a->i);
3080      tcg_r2 = load_gpr(ctx, a->r);
3081      do_cmpclr(ctx, a->t, tcg_im, tcg_r2, a->cf, a->d);
3082  
3083      return nullify_end(ctx);
3084  }
3085  
do_multimedia(DisasContext * ctx,arg_rrr * a,void (* fn)(TCGv_i64,TCGv_i64,TCGv_i64))3086  static bool do_multimedia(DisasContext *ctx, arg_rrr *a,
3087                            void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
3088  {
3089      TCGv_i64 r1, r2, dest;
3090  
3091      if (!ctx->is_pa20) {
3092          return false;
3093      }
3094  
3095      nullify_over(ctx);
3096  
3097      r1 = load_gpr(ctx, a->r1);
3098      r2 = load_gpr(ctx, a->r2);
3099      dest = dest_gpr(ctx, a->t);
3100  
3101      fn(dest, r1, r2);
3102      save_gpr(ctx, a->t, dest);
3103  
3104      return nullify_end(ctx);
3105  }
3106  
do_multimedia_sh(DisasContext * ctx,arg_rri * a,void (* fn)(TCGv_i64,TCGv_i64,int64_t))3107  static bool do_multimedia_sh(DisasContext *ctx, arg_rri *a,
3108                               void (*fn)(TCGv_i64, TCGv_i64, int64_t))
3109  {
3110      TCGv_i64 r, dest;
3111  
3112      if (!ctx->is_pa20) {
3113          return false;
3114      }
3115  
3116      nullify_over(ctx);
3117  
3118      r = load_gpr(ctx, a->r);
3119      dest = dest_gpr(ctx, a->t);
3120  
3121      fn(dest, r, a->i);
3122      save_gpr(ctx, a->t, dest);
3123  
3124      return nullify_end(ctx);
3125  }
3126  
do_multimedia_shadd(DisasContext * ctx,arg_rrr_sh * a,void (* fn)(TCGv_i64,TCGv_i64,TCGv_i64,TCGv_i32))3127  static bool do_multimedia_shadd(DisasContext *ctx, arg_rrr_sh *a,
3128                                  void (*fn)(TCGv_i64, TCGv_i64,
3129                                             TCGv_i64, TCGv_i32))
3130  {
3131      TCGv_i64 r1, r2, dest;
3132  
3133      if (!ctx->is_pa20) {
3134          return false;
3135      }
3136  
3137      nullify_over(ctx);
3138  
3139      r1 = load_gpr(ctx, a->r1);
3140      r2 = load_gpr(ctx, a->r2);
3141      dest = dest_gpr(ctx, a->t);
3142  
3143      fn(dest, r1, r2, tcg_constant_i32(a->sh));
3144      save_gpr(ctx, a->t, dest);
3145  
3146      return nullify_end(ctx);
3147  }
3148  
trans_hadd(DisasContext * ctx,arg_rrr * a)3149  static bool trans_hadd(DisasContext *ctx, arg_rrr *a)
3150  {
3151      return do_multimedia(ctx, a, tcg_gen_vec_add16_i64);
3152  }
3153  
trans_hadd_ss(DisasContext * ctx,arg_rrr * a)3154  static bool trans_hadd_ss(DisasContext *ctx, arg_rrr *a)
3155  {
3156      return do_multimedia(ctx, a, gen_helper_hadd_ss);
3157  }
3158  
trans_hadd_us(DisasContext * ctx,arg_rrr * a)3159  static bool trans_hadd_us(DisasContext *ctx, arg_rrr *a)
3160  {
3161      return do_multimedia(ctx, a, gen_helper_hadd_us);
3162  }
3163  
trans_havg(DisasContext * ctx,arg_rrr * a)3164  static bool trans_havg(DisasContext *ctx, arg_rrr *a)
3165  {
3166      return do_multimedia(ctx, a, gen_helper_havg);
3167  }
3168  
trans_hshl(DisasContext * ctx,arg_rri * a)3169  static bool trans_hshl(DisasContext *ctx, arg_rri *a)
3170  {
3171      return do_multimedia_sh(ctx, a, tcg_gen_vec_shl16i_i64);
3172  }
3173  
trans_hshr_s(DisasContext * ctx,arg_rri * a)3174  static bool trans_hshr_s(DisasContext *ctx, arg_rri *a)
3175  {
3176      return do_multimedia_sh(ctx, a, tcg_gen_vec_sar16i_i64);
3177  }
3178  
trans_hshr_u(DisasContext * ctx,arg_rri * a)3179  static bool trans_hshr_u(DisasContext *ctx, arg_rri *a)
3180  {
3181      return do_multimedia_sh(ctx, a, tcg_gen_vec_shr16i_i64);
3182  }
3183  
trans_hshladd(DisasContext * ctx,arg_rrr_sh * a)3184  static bool trans_hshladd(DisasContext *ctx, arg_rrr_sh *a)
3185  {
3186      return do_multimedia_shadd(ctx, a, gen_helper_hshladd);
3187  }
3188  
trans_hshradd(DisasContext * ctx,arg_rrr_sh * a)3189  static bool trans_hshradd(DisasContext *ctx, arg_rrr_sh *a)
3190  {
3191      return do_multimedia_shadd(ctx, a, gen_helper_hshradd);
3192  }
3193  
trans_hsub(DisasContext * ctx,arg_rrr * a)3194  static bool trans_hsub(DisasContext *ctx, arg_rrr *a)
3195  {
3196      return do_multimedia(ctx, a, tcg_gen_vec_sub16_i64);
3197  }
3198  
trans_hsub_ss(DisasContext * ctx,arg_rrr * a)3199  static bool trans_hsub_ss(DisasContext *ctx, arg_rrr *a)
3200  {
3201      return do_multimedia(ctx, a, gen_helper_hsub_ss);
3202  }
3203  
trans_hsub_us(DisasContext * ctx,arg_rrr * a)3204  static bool trans_hsub_us(DisasContext *ctx, arg_rrr *a)
3205  {
3206      return do_multimedia(ctx, a, gen_helper_hsub_us);
3207  }
3208  
gen_mixh_l(TCGv_i64 dst,TCGv_i64 r1,TCGv_i64 r2)3209  static void gen_mixh_l(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3210  {
3211      uint64_t mask = 0xffff0000ffff0000ull;
3212      TCGv_i64 tmp = tcg_temp_new_i64();
3213  
3214      tcg_gen_andi_i64(tmp, r2, mask);
3215      tcg_gen_andi_i64(dst, r1, mask);
3216      tcg_gen_shri_i64(tmp, tmp, 16);
3217      tcg_gen_or_i64(dst, dst, tmp);
3218  }
3219  
trans_mixh_l(DisasContext * ctx,arg_rrr * a)3220  static bool trans_mixh_l(DisasContext *ctx, arg_rrr *a)
3221  {
3222      return do_multimedia(ctx, a, gen_mixh_l);
3223  }
3224  
gen_mixh_r(TCGv_i64 dst,TCGv_i64 r1,TCGv_i64 r2)3225  static void gen_mixh_r(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3226  {
3227      uint64_t mask = 0x0000ffff0000ffffull;
3228      TCGv_i64 tmp = tcg_temp_new_i64();
3229  
3230      tcg_gen_andi_i64(tmp, r1, mask);
3231      tcg_gen_andi_i64(dst, r2, mask);
3232      tcg_gen_shli_i64(tmp, tmp, 16);
3233      tcg_gen_or_i64(dst, dst, tmp);
3234  }
3235  
trans_mixh_r(DisasContext * ctx,arg_rrr * a)3236  static bool trans_mixh_r(DisasContext *ctx, arg_rrr *a)
3237  {
3238      return do_multimedia(ctx, a, gen_mixh_r);
3239  }
3240  
gen_mixw_l(TCGv_i64 dst,TCGv_i64 r1,TCGv_i64 r2)3241  static void gen_mixw_l(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3242  {
3243      TCGv_i64 tmp = tcg_temp_new_i64();
3244  
3245      tcg_gen_shri_i64(tmp, r2, 32);
3246      tcg_gen_deposit_i64(dst, r1, tmp, 0, 32);
3247  }
3248  
trans_mixw_l(DisasContext * ctx,arg_rrr * a)3249  static bool trans_mixw_l(DisasContext *ctx, arg_rrr *a)
3250  {
3251      return do_multimedia(ctx, a, gen_mixw_l);
3252  }
3253  
gen_mixw_r(TCGv_i64 dst,TCGv_i64 r1,TCGv_i64 r2)3254  static void gen_mixw_r(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3255  {
3256      tcg_gen_deposit_i64(dst, r2, r1, 32, 32);
3257  }
3258  
trans_mixw_r(DisasContext * ctx,arg_rrr * a)3259  static bool trans_mixw_r(DisasContext *ctx, arg_rrr *a)
3260  {
3261      return do_multimedia(ctx, a, gen_mixw_r);
3262  }
3263  
trans_permh(DisasContext * ctx,arg_permh * a)3264  static bool trans_permh(DisasContext *ctx, arg_permh *a)
3265  {
3266      TCGv_i64 r, t0, t1, t2, t3;
3267  
3268      if (!ctx->is_pa20) {
3269          return false;
3270      }
3271  
3272      nullify_over(ctx);
3273  
3274      r = load_gpr(ctx, a->r1);
3275      t0 = tcg_temp_new_i64();
3276      t1 = tcg_temp_new_i64();
3277      t2 = tcg_temp_new_i64();
3278      t3 = tcg_temp_new_i64();
3279  
3280      tcg_gen_extract_i64(t0, r, (3 - a->c0) * 16, 16);
3281      tcg_gen_extract_i64(t1, r, (3 - a->c1) * 16, 16);
3282      tcg_gen_extract_i64(t2, r, (3 - a->c2) * 16, 16);
3283      tcg_gen_extract_i64(t3, r, (3 - a->c3) * 16, 16);
3284  
3285      tcg_gen_deposit_i64(t0, t1, t0, 16, 48);
3286      tcg_gen_deposit_i64(t2, t3, t2, 16, 48);
3287      tcg_gen_deposit_i64(t0, t2, t0, 32, 32);
3288  
3289      save_gpr(ctx, a->t, t0);
3290      return nullify_end(ctx);
3291  }
3292  
trans_ld(DisasContext * ctx,arg_ldst * a)3293  static bool trans_ld(DisasContext *ctx, arg_ldst *a)
3294  {
3295      if (ctx->is_pa20) {
3296         /*
3297          * With pa20, LDB, LDH, LDW, LDD to %g0 are prefetches.
3298          * Any base modification still occurs.
3299          */
3300          if (a->t == 0) {
3301              return trans_nop_addrx(ctx, a);
3302          }
3303      } else if (a->size > MO_32) {
3304          return gen_illegal(ctx);
3305      }
3306      return do_load(ctx, a->t, a->b, a->x, a->scale ? a->size : 0,
3307                     a->disp, a->sp, a->m, a->size | MO_TE);
3308  }
3309  
trans_st(DisasContext * ctx,arg_ldst * a)3310  static bool trans_st(DisasContext *ctx, arg_ldst *a)
3311  {
3312      assert(a->x == 0 && a->scale == 0);
3313      if (!ctx->is_pa20 && a->size > MO_32) {
3314          return gen_illegal(ctx);
3315      }
3316      return do_store(ctx, a->t, a->b, a->disp, a->sp, a->m, a->size | MO_TE);
3317  }
3318  
trans_ldc(DisasContext * ctx,arg_ldst * a)3319  static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
3320  {
3321      MemOp mop = MO_TE | MO_ALIGN | a->size;
3322      TCGv_i64 dest, ofs;
3323      TCGv_i64 addr;
3324  
3325      if (!ctx->is_pa20 && a->size > MO_32) {
3326          return gen_illegal(ctx);
3327      }
3328  
3329      nullify_over(ctx);
3330  
3331      if (a->m) {
3332          /* Base register modification.  Make sure if RT == RB,
3333             we see the result of the load.  */
3334          dest = tcg_temp_new_i64();
3335      } else {
3336          dest = dest_gpr(ctx, a->t);
3337      }
3338  
3339      form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? 3 : 0,
3340               a->disp, a->sp, a->m, MMU_DISABLED(ctx));
3341  
3342      /*
3343       * For hppa1.1, LDCW is undefined unless aligned mod 16.
3344       * However actual hardware succeeds with aligned mod 4.
3345       * Detect this case and log a GUEST_ERROR.
3346       *
3347       * TODO: HPPA64 relaxes the over-alignment requirement
3348       * with the ,co completer.
3349       */
3350      gen_helper_ldc_check(addr);
3351  
3352      tcg_gen_atomic_xchg_i64(dest, addr, ctx->zero, ctx->mmu_idx, mop);
3353  
3354      if (a->m) {
3355          save_gpr(ctx, a->b, ofs);
3356      }
3357      save_gpr(ctx, a->t, dest);
3358  
3359      return nullify_end(ctx);
3360  }
3361  
trans_stby(DisasContext * ctx,arg_stby * a)3362  static bool trans_stby(DisasContext *ctx, arg_stby *a)
3363  {
3364      TCGv_i64 ofs, val;
3365      TCGv_i64 addr;
3366  
3367      nullify_over(ctx);
3368  
3369      form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
3370               MMU_DISABLED(ctx));
3371      val = load_gpr(ctx, a->r);
3372      if (a->a) {
3373          if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3374              gen_helper_stby_e_parallel(tcg_env, addr, val);
3375          } else {
3376              gen_helper_stby_e(tcg_env, addr, val);
3377          }
3378      } else {
3379          if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3380              gen_helper_stby_b_parallel(tcg_env, addr, val);
3381          } else {
3382              gen_helper_stby_b(tcg_env, addr, val);
3383          }
3384      }
3385      if (a->m) {
3386          tcg_gen_andi_i64(ofs, ofs, ~3);
3387          save_gpr(ctx, a->b, ofs);
3388      }
3389  
3390      return nullify_end(ctx);
3391  }
3392  
trans_stdby(DisasContext * ctx,arg_stby * a)3393  static bool trans_stdby(DisasContext *ctx, arg_stby *a)
3394  {
3395      TCGv_i64 ofs, val;
3396      TCGv_i64 addr;
3397  
3398      if (!ctx->is_pa20) {
3399          return false;
3400      }
3401      nullify_over(ctx);
3402  
3403      form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
3404               MMU_DISABLED(ctx));
3405      val = load_gpr(ctx, a->r);
3406      if (a->a) {
3407          if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3408              gen_helper_stdby_e_parallel(tcg_env, addr, val);
3409          } else {
3410              gen_helper_stdby_e(tcg_env, addr, val);
3411          }
3412      } else {
3413          if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3414              gen_helper_stdby_b_parallel(tcg_env, addr, val);
3415          } else {
3416              gen_helper_stdby_b(tcg_env, addr, val);
3417          }
3418      }
3419      if (a->m) {
3420          tcg_gen_andi_i64(ofs, ofs, ~7);
3421          save_gpr(ctx, a->b, ofs);
3422      }
3423  
3424      return nullify_end(ctx);
3425  }
3426  
trans_lda(DisasContext * ctx,arg_ldst * a)3427  static bool trans_lda(DisasContext *ctx, arg_ldst *a)
3428  {
3429      int hold_mmu_idx = ctx->mmu_idx;
3430  
3431      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3432      ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
3433      trans_ld(ctx, a);
3434      ctx->mmu_idx = hold_mmu_idx;
3435      return true;
3436  }
3437  
trans_sta(DisasContext * ctx,arg_ldst * a)3438  static bool trans_sta(DisasContext *ctx, arg_ldst *a)
3439  {
3440      int hold_mmu_idx = ctx->mmu_idx;
3441  
3442      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3443      ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
3444      trans_st(ctx, a);
3445      ctx->mmu_idx = hold_mmu_idx;
3446      return true;
3447  }
3448  
trans_ldil(DisasContext * ctx,arg_ldil * a)3449  static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
3450  {
3451      TCGv_i64 tcg_rt = dest_gpr(ctx, a->t);
3452  
3453      tcg_gen_movi_i64(tcg_rt, a->i);
3454      save_gpr(ctx, a->t, tcg_rt);
3455      ctx->null_cond = cond_make_f();
3456      return true;
3457  }
3458  
trans_addil(DisasContext * ctx,arg_addil * a)3459  static bool trans_addil(DisasContext *ctx, arg_addil *a)
3460  {
3461      TCGv_i64 tcg_rt = load_gpr(ctx, a->r);
3462      TCGv_i64 tcg_r1 = dest_gpr(ctx, 1);
3463  
3464      tcg_gen_addi_i64(tcg_r1, tcg_rt, a->i);
3465      save_gpr(ctx, 1, tcg_r1);
3466      ctx->null_cond = cond_make_f();
3467      return true;
3468  }
3469  
trans_ldo(DisasContext * ctx,arg_ldo * a)3470  static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
3471  {
3472      TCGv_i64 tcg_rt = dest_gpr(ctx, a->t);
3473  
3474      /* Special case rb == 0, for the LDI pseudo-op.
3475         The COPY pseudo-op is handled for free within tcg_gen_addi_i64.  */
3476      if (a->b == 0) {
3477          tcg_gen_movi_i64(tcg_rt, a->i);
3478      } else {
3479          tcg_gen_addi_i64(tcg_rt, cpu_gr[a->b], a->i);
3480      }
3481      save_gpr(ctx, a->t, tcg_rt);
3482      ctx->null_cond = cond_make_f();
3483      return true;
3484  }
3485  
do_cmpb(DisasContext * ctx,unsigned r,TCGv_i64 in1,unsigned c,unsigned f,bool d,unsigned n,int disp)3486  static bool do_cmpb(DisasContext *ctx, unsigned r, TCGv_i64 in1,
3487                      unsigned c, unsigned f, bool d, unsigned n, int disp)
3488  {
3489      TCGv_i64 dest, in2, sv;
3490      DisasCond cond;
3491  
3492      in2 = load_gpr(ctx, r);
3493      dest = tcg_temp_new_i64();
3494  
3495      tcg_gen_sub_i64(dest, in1, in2);
3496  
3497      sv = NULL;
3498      if (cond_need_sv(c)) {
3499          sv = do_sub_sv(ctx, dest, in1, in2);
3500      }
3501  
3502      cond = do_sub_cond(ctx, c * 2 + f, d, dest, in1, in2, sv);
3503      return do_cbranch(ctx, disp, n, &cond);
3504  }
3505  
trans_cmpb(DisasContext * ctx,arg_cmpb * a)3506  static bool trans_cmpb(DisasContext *ctx, arg_cmpb *a)
3507  {
3508      if (!ctx->is_pa20 && a->d) {
3509          return false;
3510      }
3511      nullify_over(ctx);
3512      return do_cmpb(ctx, a->r2, load_gpr(ctx, a->r1),
3513                     a->c, a->f, a->d, a->n, a->disp);
3514  }
3515  
trans_cmpbi(DisasContext * ctx,arg_cmpbi * a)3516  static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
3517  {
3518      if (!ctx->is_pa20 && a->d) {
3519          return false;
3520      }
3521      nullify_over(ctx);
3522      return do_cmpb(ctx, a->r, tcg_constant_i64(a->i),
3523                     a->c, a->f, a->d, a->n, a->disp);
3524  }
3525  
do_addb(DisasContext * ctx,unsigned r,TCGv_i64 in1,unsigned c,unsigned f,unsigned n,int disp)3526  static bool do_addb(DisasContext *ctx, unsigned r, TCGv_i64 in1,
3527                      unsigned c, unsigned f, unsigned n, int disp)
3528  {
3529      TCGv_i64 dest, in2, sv, cb_cond;
3530      DisasCond cond;
3531      bool d = false;
3532  
3533      /*
3534       * For hppa64, the ADDB conditions change with PSW.W,
3535       * dropping ZNV, SV, OD in favor of double-word EQ, LT, LE.
3536       */
3537      if (ctx->tb_flags & PSW_W) {
3538          d = c >= 5;
3539          if (d) {
3540              c &= 3;
3541          }
3542      }
3543  
3544      in2 = load_gpr(ctx, r);
3545      dest = tcg_temp_new_i64();
3546      sv = NULL;
3547      cb_cond = NULL;
3548  
3549      if (cond_need_cb(c)) {
3550          TCGv_i64 cb = tcg_temp_new_i64();
3551          TCGv_i64 cb_msb = tcg_temp_new_i64();
3552  
3553          tcg_gen_movi_i64(cb_msb, 0);
3554          tcg_gen_add2_i64(dest, cb_msb, in1, cb_msb, in2, cb_msb);
3555          tcg_gen_xor_i64(cb, in1, in2);
3556          tcg_gen_xor_i64(cb, cb, dest);
3557          cb_cond = get_carry(ctx, d, cb, cb_msb);
3558      } else {
3559          tcg_gen_add_i64(dest, in1, in2);
3560      }
3561      if (cond_need_sv(c)) {
3562          sv = do_add_sv(ctx, dest, in1, in2, in1, 0, d);
3563      }
3564  
3565      cond = do_cond(ctx, c * 2 + f, d, dest, cb_cond, sv);
3566      save_gpr(ctx, r, dest);
3567      return do_cbranch(ctx, disp, n, &cond);
3568  }
3569  
trans_addb(DisasContext * ctx,arg_addb * a)3570  static bool trans_addb(DisasContext *ctx, arg_addb *a)
3571  {
3572      nullify_over(ctx);
3573      return do_addb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3574  }
3575  
trans_addbi(DisasContext * ctx,arg_addbi * a)3576  static bool trans_addbi(DisasContext *ctx, arg_addbi *a)
3577  {
3578      nullify_over(ctx);
3579      return do_addb(ctx, a->r, tcg_constant_i64(a->i), a->c, a->f, a->n, a->disp);
3580  }
3581  
trans_bb_sar(DisasContext * ctx,arg_bb_sar * a)3582  static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
3583  {
3584      TCGv_i64 tmp, tcg_r;
3585      DisasCond cond;
3586  
3587      nullify_over(ctx);
3588  
3589      tmp = tcg_temp_new_i64();
3590      tcg_r = load_gpr(ctx, a->r);
3591      if (a->d) {
3592          tcg_gen_shl_i64(tmp, tcg_r, cpu_sar);
3593      } else {
3594          /* Force shift into [32,63] */
3595          tcg_gen_ori_i64(tmp, cpu_sar, 32);
3596          tcg_gen_shl_i64(tmp, tcg_r, tmp);
3597      }
3598  
3599      cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0);
3600      return do_cbranch(ctx, a->disp, a->n, &cond);
3601  }
3602  
trans_bb_imm(DisasContext * ctx,arg_bb_imm * a)3603  static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
3604  {
3605      DisasCond cond;
3606      int p = a->p | (a->d ? 0 : 32);
3607  
3608      nullify_over(ctx);
3609      cond = cond_make_vi(a->c ? TCG_COND_TSTEQ : TCG_COND_TSTNE,
3610                          load_gpr(ctx, a->r), 1ull << (63 - p));
3611      return do_cbranch(ctx, a->disp, a->n, &cond);
3612  }
3613  
trans_movb(DisasContext * ctx,arg_movb * a)3614  static bool trans_movb(DisasContext *ctx, arg_movb *a)
3615  {
3616      TCGv_i64 dest;
3617      DisasCond cond;
3618  
3619      nullify_over(ctx);
3620  
3621      dest = dest_gpr(ctx, a->r2);
3622      if (a->r1 == 0) {
3623          tcg_gen_movi_i64(dest, 0);
3624      } else {
3625          tcg_gen_mov_i64(dest, cpu_gr[a->r1]);
3626      }
3627  
3628      /* All MOVB conditions are 32-bit. */
3629      cond = do_sed_cond(ctx, a->c, false, dest);
3630      return do_cbranch(ctx, a->disp, a->n, &cond);
3631  }
3632  
trans_movbi(DisasContext * ctx,arg_movbi * a)3633  static bool trans_movbi(DisasContext *ctx, arg_movbi *a)
3634  {
3635      TCGv_i64 dest;
3636      DisasCond cond;
3637  
3638      nullify_over(ctx);
3639  
3640      dest = dest_gpr(ctx, a->r);
3641      tcg_gen_movi_i64(dest, a->i);
3642  
3643      /* All MOVBI conditions are 32-bit. */
3644      cond = do_sed_cond(ctx, a->c, false, dest);
3645      return do_cbranch(ctx, a->disp, a->n, &cond);
3646  }
3647  
trans_shrp_sar(DisasContext * ctx,arg_shrp_sar * a)3648  static bool trans_shrp_sar(DisasContext *ctx, arg_shrp_sar *a)
3649  {
3650      TCGv_i64 dest, src2;
3651  
3652      if (!ctx->is_pa20 && a->d) {
3653          return false;
3654      }
3655      if (a->c) {
3656          nullify_over(ctx);
3657      }
3658  
3659      dest = dest_gpr(ctx, a->t);
3660      src2 = load_gpr(ctx, a->r2);
3661      if (a->r1 == 0) {
3662          if (a->d) {
3663              tcg_gen_shr_i64(dest, src2, cpu_sar);
3664          } else {
3665              TCGv_i64 tmp = tcg_temp_new_i64();
3666  
3667              tcg_gen_ext32u_i64(dest, src2);
3668              tcg_gen_andi_i64(tmp, cpu_sar, 31);
3669              tcg_gen_shr_i64(dest, dest, tmp);
3670          }
3671      } else if (a->r1 == a->r2) {
3672          if (a->d) {
3673              tcg_gen_rotr_i64(dest, src2, cpu_sar);
3674          } else {
3675              TCGv_i32 t32 = tcg_temp_new_i32();
3676              TCGv_i32 s32 = tcg_temp_new_i32();
3677  
3678              tcg_gen_extrl_i64_i32(t32, src2);
3679              tcg_gen_extrl_i64_i32(s32, cpu_sar);
3680              tcg_gen_andi_i32(s32, s32, 31);
3681              tcg_gen_rotr_i32(t32, t32, s32);
3682              tcg_gen_extu_i32_i64(dest, t32);
3683          }
3684      } else {
3685          TCGv_i64 src1 = load_gpr(ctx, a->r1);
3686  
3687          if (a->d) {
3688              TCGv_i64 t = tcg_temp_new_i64();
3689              TCGv_i64 n = tcg_temp_new_i64();
3690  
3691              tcg_gen_xori_i64(n, cpu_sar, 63);
3692              tcg_gen_shl_i64(t, src1, n);
3693              tcg_gen_shli_i64(t, t, 1);
3694              tcg_gen_shr_i64(dest, src2, cpu_sar);
3695              tcg_gen_or_i64(dest, dest, t);
3696          } else {
3697              TCGv_i64 t = tcg_temp_new_i64();
3698              TCGv_i64 s = tcg_temp_new_i64();
3699  
3700              tcg_gen_concat32_i64(t, src2, src1);
3701              tcg_gen_andi_i64(s, cpu_sar, 31);
3702              tcg_gen_shr_i64(dest, t, s);
3703          }
3704      }
3705      save_gpr(ctx, a->t, dest);
3706  
3707      /* Install the new nullification.  */
3708      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3709      return nullify_end(ctx);
3710  }
3711  
trans_shrp_imm(DisasContext * ctx,arg_shrp_imm * a)3712  static bool trans_shrp_imm(DisasContext *ctx, arg_shrp_imm *a)
3713  {
3714      unsigned width, sa;
3715      TCGv_i64 dest, t2;
3716  
3717      if (!ctx->is_pa20 && a->d) {
3718          return false;
3719      }
3720      if (a->c) {
3721          nullify_over(ctx);
3722      }
3723  
3724      width = a->d ? 64 : 32;
3725      sa = width - 1 - a->cpos;
3726  
3727      dest = dest_gpr(ctx, a->t);
3728      t2 = load_gpr(ctx, a->r2);
3729      if (a->r1 == 0) {
3730          tcg_gen_extract_i64(dest, t2, sa, width - sa);
3731      } else if (width == TARGET_LONG_BITS) {
3732          tcg_gen_extract2_i64(dest, t2, cpu_gr[a->r1], sa);
3733      } else {
3734          assert(!a->d);
3735          if (a->r1 == a->r2) {
3736              TCGv_i32 t32 = tcg_temp_new_i32();
3737              tcg_gen_extrl_i64_i32(t32, t2);
3738              tcg_gen_rotri_i32(t32, t32, sa);
3739              tcg_gen_extu_i32_i64(dest, t32);
3740          } else {
3741              tcg_gen_concat32_i64(dest, t2, cpu_gr[a->r1]);
3742              tcg_gen_extract_i64(dest, dest, sa, 32);
3743          }
3744      }
3745      save_gpr(ctx, a->t, dest);
3746  
3747      /* Install the new nullification.  */
3748      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3749      return nullify_end(ctx);
3750  }
3751  
trans_extr_sar(DisasContext * ctx,arg_extr_sar * a)3752  static bool trans_extr_sar(DisasContext *ctx, arg_extr_sar *a)
3753  {
3754      unsigned widthm1 = a->d ? 63 : 31;
3755      TCGv_i64 dest, src, tmp;
3756  
3757      if (!ctx->is_pa20 && a->d) {
3758          return false;
3759      }
3760      if (a->c) {
3761          nullify_over(ctx);
3762      }
3763  
3764      dest = dest_gpr(ctx, a->t);
3765      src = load_gpr(ctx, a->r);
3766      tmp = tcg_temp_new_i64();
3767  
3768      /* Recall that SAR is using big-endian bit numbering.  */
3769      tcg_gen_andi_i64(tmp, cpu_sar, widthm1);
3770      tcg_gen_xori_i64(tmp, tmp, widthm1);
3771  
3772      if (a->se) {
3773          if (!a->d) {
3774              tcg_gen_ext32s_i64(dest, src);
3775              src = dest;
3776          }
3777          tcg_gen_sar_i64(dest, src, tmp);
3778          tcg_gen_sextract_i64(dest, dest, 0, a->len);
3779      } else {
3780          if (!a->d) {
3781              tcg_gen_ext32u_i64(dest, src);
3782              src = dest;
3783          }
3784          tcg_gen_shr_i64(dest, src, tmp);
3785          tcg_gen_extract_i64(dest, dest, 0, a->len);
3786      }
3787      save_gpr(ctx, a->t, dest);
3788  
3789      /* Install the new nullification.  */
3790      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3791      return nullify_end(ctx);
3792  }
3793  
trans_extr_imm(DisasContext * ctx,arg_extr_imm * a)3794  static bool trans_extr_imm(DisasContext *ctx, arg_extr_imm *a)
3795  {
3796      unsigned len, cpos, width;
3797      TCGv_i64 dest, src;
3798  
3799      if (!ctx->is_pa20 && a->d) {
3800          return false;
3801      }
3802      if (a->c) {
3803          nullify_over(ctx);
3804      }
3805  
3806      len = a->len;
3807      width = a->d ? 64 : 32;
3808      cpos = width - 1 - a->pos;
3809      if (cpos + len > width) {
3810          len = width - cpos;
3811      }
3812  
3813      dest = dest_gpr(ctx, a->t);
3814      src = load_gpr(ctx, a->r);
3815      if (a->se) {
3816          tcg_gen_sextract_i64(dest, src, cpos, len);
3817      } else {
3818          tcg_gen_extract_i64(dest, src, cpos, len);
3819      }
3820      save_gpr(ctx, a->t, dest);
3821  
3822      /* Install the new nullification.  */
3823      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3824      return nullify_end(ctx);
3825  }
3826  
trans_depi_imm(DisasContext * ctx,arg_depi_imm * a)3827  static bool trans_depi_imm(DisasContext *ctx, arg_depi_imm *a)
3828  {
3829      unsigned len, width;
3830      uint64_t mask0, mask1;
3831      TCGv_i64 dest;
3832  
3833      if (!ctx->is_pa20 && a->d) {
3834          return false;
3835      }
3836      if (a->c) {
3837          nullify_over(ctx);
3838      }
3839  
3840      len = a->len;
3841      width = a->d ? 64 : 32;
3842      if (a->cpos + len > width) {
3843          len = width - a->cpos;
3844      }
3845  
3846      dest = dest_gpr(ctx, a->t);
3847      mask0 = deposit64(0, a->cpos, len, a->i);
3848      mask1 = deposit64(-1, a->cpos, len, a->i);
3849  
3850      if (a->nz) {
3851          TCGv_i64 src = load_gpr(ctx, a->t);
3852          tcg_gen_andi_i64(dest, src, mask1);
3853          tcg_gen_ori_i64(dest, dest, mask0);
3854      } else {
3855          tcg_gen_movi_i64(dest, mask0);
3856      }
3857      save_gpr(ctx, a->t, dest);
3858  
3859      /* Install the new nullification.  */
3860      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3861      return nullify_end(ctx);
3862  }
3863  
trans_dep_imm(DisasContext * ctx,arg_dep_imm * a)3864  static bool trans_dep_imm(DisasContext *ctx, arg_dep_imm *a)
3865  {
3866      unsigned rs = a->nz ? a->t : 0;
3867      unsigned len, width;
3868      TCGv_i64 dest, val;
3869  
3870      if (!ctx->is_pa20 && a->d) {
3871          return false;
3872      }
3873      if (a->c) {
3874          nullify_over(ctx);
3875      }
3876  
3877      len = a->len;
3878      width = a->d ? 64 : 32;
3879      if (a->cpos + len > width) {
3880          len = width - a->cpos;
3881      }
3882  
3883      dest = dest_gpr(ctx, a->t);
3884      val = load_gpr(ctx, a->r);
3885      if (rs == 0) {
3886          tcg_gen_deposit_z_i64(dest, val, a->cpos, len);
3887      } else {
3888          tcg_gen_deposit_i64(dest, cpu_gr[rs], val, a->cpos, len);
3889      }
3890      save_gpr(ctx, a->t, dest);
3891  
3892      /* Install the new nullification.  */
3893      ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3894      return nullify_end(ctx);
3895  }
3896  
do_dep_sar(DisasContext * ctx,unsigned rt,unsigned c,bool d,bool nz,unsigned len,TCGv_i64 val)3897  static bool do_dep_sar(DisasContext *ctx, unsigned rt, unsigned c,
3898                         bool d, bool nz, unsigned len, TCGv_i64 val)
3899  {
3900      unsigned rs = nz ? rt : 0;
3901      unsigned widthm1 = d ? 63 : 31;
3902      TCGv_i64 mask, tmp, shift, dest;
3903      uint64_t msb = 1ULL << (len - 1);
3904  
3905      dest = dest_gpr(ctx, rt);
3906      shift = tcg_temp_new_i64();
3907      tmp = tcg_temp_new_i64();
3908  
3909      /* Convert big-endian bit numbering in SAR to left-shift.  */
3910      tcg_gen_andi_i64(shift, cpu_sar, widthm1);
3911      tcg_gen_xori_i64(shift, shift, widthm1);
3912  
3913      mask = tcg_temp_new_i64();
3914      tcg_gen_movi_i64(mask, msb + (msb - 1));
3915      tcg_gen_and_i64(tmp, val, mask);
3916      if (rs) {
3917          tcg_gen_shl_i64(mask, mask, shift);
3918          tcg_gen_shl_i64(tmp, tmp, shift);
3919          tcg_gen_andc_i64(dest, cpu_gr[rs], mask);
3920          tcg_gen_or_i64(dest, dest, tmp);
3921      } else {
3922          tcg_gen_shl_i64(dest, tmp, shift);
3923      }
3924      save_gpr(ctx, rt, dest);
3925  
3926      /* Install the new nullification.  */
3927      ctx->null_cond = do_sed_cond(ctx, c, d, dest);
3928      return nullify_end(ctx);
3929  }
3930  
trans_dep_sar(DisasContext * ctx,arg_dep_sar * a)3931  static bool trans_dep_sar(DisasContext *ctx, arg_dep_sar *a)
3932  {
3933      if (!ctx->is_pa20 && a->d) {
3934          return false;
3935      }
3936      if (a->c) {
3937          nullify_over(ctx);
3938      }
3939      return do_dep_sar(ctx, a->t, a->c, a->d, a->nz, a->len,
3940                        load_gpr(ctx, a->r));
3941  }
3942  
trans_depi_sar(DisasContext * ctx,arg_depi_sar * a)3943  static bool trans_depi_sar(DisasContext *ctx, arg_depi_sar *a)
3944  {
3945      if (!ctx->is_pa20 && a->d) {
3946          return false;
3947      }
3948      if (a->c) {
3949          nullify_over(ctx);
3950      }
3951      return do_dep_sar(ctx, a->t, a->c, a->d, a->nz, a->len,
3952                        tcg_constant_i64(a->i));
3953  }
3954  
trans_be(DisasContext * ctx,arg_be * a)3955  static bool trans_be(DisasContext *ctx, arg_be *a)
3956  {
3957  #ifndef CONFIG_USER_ONLY
3958      ctx->iaq_j.space = tcg_temp_new_i64();
3959      load_spr(ctx, ctx->iaq_j.space, a->sp);
3960  #endif
3961  
3962      ctx->iaq_j.base = tcg_temp_new_i64();
3963      ctx->iaq_j.disp = 0;
3964  
3965      tcg_gen_addi_i64(ctx->iaq_j.base, load_gpr(ctx, a->b), a->disp);
3966      ctx->iaq_j.base = do_ibranch_priv(ctx, ctx->iaq_j.base);
3967  
3968      return do_ibranch(ctx, a->l, true, a->n);
3969  }
3970  
trans_bl(DisasContext * ctx,arg_bl * a)3971  static bool trans_bl(DisasContext *ctx, arg_bl *a)
3972  {
3973      return do_dbranch(ctx, a->disp, a->l, a->n);
3974  }
3975  
trans_b_gate(DisasContext * ctx,arg_b_gate * a)3976  static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
3977  {
3978      int64_t disp = a->disp;
3979      bool indirect = false;
3980  
3981      /* Trap if PSW[B] is set. */
3982      if (ctx->psw_xb & PSW_B) {
3983          return gen_illegal(ctx);
3984      }
3985  
3986      nullify_over(ctx);
3987  
3988  #ifndef CONFIG_USER_ONLY
3989      if (ctx->privilege == 0) {
3990          /* Privilege cannot decrease. */
3991      } else if (!(ctx->tb_flags & PSW_C)) {
3992          /* With paging disabled, priv becomes 0. */
3993          disp -= ctx->privilege;
3994      } else {
3995          /* Adjust the dest offset for the privilege change from the PTE. */
3996          TCGv_i64 off = tcg_temp_new_i64();
3997  
3998          copy_iaoq_entry(ctx, off, &ctx->iaq_f);
3999          gen_helper_b_gate_priv(off, tcg_env, off);
4000  
4001          ctx->iaq_j.base = off;
4002          ctx->iaq_j.disp = disp + 8;
4003          indirect = true;
4004      }
4005  #endif
4006  
4007      if (a->l) {
4008          TCGv_i64 tmp = dest_gpr(ctx, a->l);
4009          if (ctx->privilege < 3) {
4010              tcg_gen_andi_i64(tmp, tmp, -4);
4011          }
4012          tcg_gen_ori_i64(tmp, tmp, ctx->privilege);
4013          save_gpr(ctx, a->l, tmp);
4014      }
4015  
4016      if (indirect) {
4017          return do_ibranch(ctx, 0, false, a->n);
4018      }
4019      return do_dbranch(ctx, disp, 0, a->n);
4020  }
4021  
trans_blr(DisasContext * ctx,arg_blr * a)4022  static bool trans_blr(DisasContext *ctx, arg_blr *a)
4023  {
4024      if (a->x) {
4025          DisasIAQE next = iaqe_incr(&ctx->iaq_f, 8);
4026          TCGv_i64 t0 = tcg_temp_new_i64();
4027          TCGv_i64 t1 = tcg_temp_new_i64();
4028  
4029          /* The computation here never changes privilege level.  */
4030          copy_iaoq_entry(ctx, t0, &next);
4031          tcg_gen_shli_i64(t1, load_gpr(ctx, a->x), 3);
4032          tcg_gen_add_i64(t0, t0, t1);
4033  
4034          ctx->iaq_j = iaqe_next_absv(ctx, t0);
4035          return do_ibranch(ctx, a->l, false, a->n);
4036      } else {
4037          /* BLR R0,RX is a good way to load PC+8 into RX.  */
4038          return do_dbranch(ctx, 0, a->l, a->n);
4039      }
4040  }
4041  
trans_bv(DisasContext * ctx,arg_bv * a)4042  static bool trans_bv(DisasContext *ctx, arg_bv *a)
4043  {
4044      TCGv_i64 dest;
4045  
4046      if (a->x == 0) {
4047          dest = load_gpr(ctx, a->b);
4048      } else {
4049          dest = tcg_temp_new_i64();
4050          tcg_gen_shli_i64(dest, load_gpr(ctx, a->x), 3);
4051          tcg_gen_add_i64(dest, dest, load_gpr(ctx, a->b));
4052      }
4053      dest = do_ibranch_priv(ctx, dest);
4054      ctx->iaq_j = iaqe_next_absv(ctx, dest);
4055  
4056      return do_ibranch(ctx, 0, false, a->n);
4057  }
4058  
trans_bve(DisasContext * ctx,arg_bve * a)4059  static bool trans_bve(DisasContext *ctx, arg_bve *a)
4060  {
4061      TCGv_i64 b = load_gpr(ctx, a->b);
4062  
4063  #ifndef CONFIG_USER_ONLY
4064      ctx->iaq_j.space = space_select(ctx, 0, b);
4065  #endif
4066      ctx->iaq_j.base = do_ibranch_priv(ctx, b);
4067      ctx->iaq_j.disp = 0;
4068  
4069      return do_ibranch(ctx, a->l, false, a->n);
4070  }
4071  
trans_nopbts(DisasContext * ctx,arg_nopbts * a)4072  static bool trans_nopbts(DisasContext *ctx, arg_nopbts *a)
4073  {
4074      /* All branch target stack instructions implement as nop. */
4075      return ctx->is_pa20;
4076  }
4077  
4078  /*
4079   * Float class 0
4080   */
4081  
gen_fcpy_f(TCGv_i32 dst,TCGv_env unused,TCGv_i32 src)4082  static void gen_fcpy_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4083  {
4084      tcg_gen_mov_i32(dst, src);
4085  }
4086  
trans_fid_f(DisasContext * ctx,arg_fid_f * a)4087  static bool trans_fid_f(DisasContext *ctx, arg_fid_f *a)
4088  {
4089      uint64_t ret;
4090  
4091      if (ctx->is_pa20) {
4092          ret = 0x13080000000000ULL; /* PA8700 (PCX-W2) */
4093      } else {
4094          ret = 0x0f080000000000ULL; /* PA7300LC (PCX-L2) */
4095      }
4096  
4097      nullify_over(ctx);
4098      save_frd(0, tcg_constant_i64(ret));
4099      return nullify_end(ctx);
4100  }
4101  
trans_fcpy_f(DisasContext * ctx,arg_fclass01 * a)4102  static bool trans_fcpy_f(DisasContext *ctx, arg_fclass01 *a)
4103  {
4104      return do_fop_wew(ctx, a->t, a->r, gen_fcpy_f);
4105  }
4106  
gen_fcpy_d(TCGv_i64 dst,TCGv_env unused,TCGv_i64 src)4107  static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4108  {
4109      tcg_gen_mov_i64(dst, src);
4110  }
4111  
trans_fcpy_d(DisasContext * ctx,arg_fclass01 * a)4112  static bool trans_fcpy_d(DisasContext *ctx, arg_fclass01 *a)
4113  {
4114      return do_fop_ded(ctx, a->t, a->r, gen_fcpy_d);
4115  }
4116  
gen_fabs_f(TCGv_i32 dst,TCGv_env unused,TCGv_i32 src)4117  static void gen_fabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4118  {
4119      tcg_gen_andi_i32(dst, src, INT32_MAX);
4120  }
4121  
trans_fabs_f(DisasContext * ctx,arg_fclass01 * a)4122  static bool trans_fabs_f(DisasContext *ctx, arg_fclass01 *a)
4123  {
4124      return do_fop_wew(ctx, a->t, a->r, gen_fabs_f);
4125  }
4126  
gen_fabs_d(TCGv_i64 dst,TCGv_env unused,TCGv_i64 src)4127  static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4128  {
4129      tcg_gen_andi_i64(dst, src, INT64_MAX);
4130  }
4131  
trans_fabs_d(DisasContext * ctx,arg_fclass01 * a)4132  static bool trans_fabs_d(DisasContext *ctx, arg_fclass01 *a)
4133  {
4134      return do_fop_ded(ctx, a->t, a->r, gen_fabs_d);
4135  }
4136  
trans_fsqrt_f(DisasContext * ctx,arg_fclass01 * a)4137  static bool trans_fsqrt_f(DisasContext *ctx, arg_fclass01 *a)
4138  {
4139      return do_fop_wew(ctx, a->t, a->r, gen_helper_fsqrt_s);
4140  }
4141  
trans_fsqrt_d(DisasContext * ctx,arg_fclass01 * a)4142  static bool trans_fsqrt_d(DisasContext *ctx, arg_fclass01 *a)
4143  {
4144      return do_fop_ded(ctx, a->t, a->r, gen_helper_fsqrt_d);
4145  }
4146  
trans_frnd_f(DisasContext * ctx,arg_fclass01 * a)4147  static bool trans_frnd_f(DisasContext *ctx, arg_fclass01 *a)
4148  {
4149      return do_fop_wew(ctx, a->t, a->r, gen_helper_frnd_s);
4150  }
4151  
trans_frnd_d(DisasContext * ctx,arg_fclass01 * a)4152  static bool trans_frnd_d(DisasContext *ctx, arg_fclass01 *a)
4153  {
4154      return do_fop_ded(ctx, a->t, a->r, gen_helper_frnd_d);
4155  }
4156  
gen_fneg_f(TCGv_i32 dst,TCGv_env unused,TCGv_i32 src)4157  static void gen_fneg_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4158  {
4159      tcg_gen_xori_i32(dst, src, INT32_MIN);
4160  }
4161  
trans_fneg_f(DisasContext * ctx,arg_fclass01 * a)4162  static bool trans_fneg_f(DisasContext *ctx, arg_fclass01 *a)
4163  {
4164      return do_fop_wew(ctx, a->t, a->r, gen_fneg_f);
4165  }
4166  
gen_fneg_d(TCGv_i64 dst,TCGv_env unused,TCGv_i64 src)4167  static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4168  {
4169      tcg_gen_xori_i64(dst, src, INT64_MIN);
4170  }
4171  
trans_fneg_d(DisasContext * ctx,arg_fclass01 * a)4172  static bool trans_fneg_d(DisasContext *ctx, arg_fclass01 *a)
4173  {
4174      return do_fop_ded(ctx, a->t, a->r, gen_fneg_d);
4175  }
4176  
gen_fnegabs_f(TCGv_i32 dst,TCGv_env unused,TCGv_i32 src)4177  static void gen_fnegabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4178  {
4179      tcg_gen_ori_i32(dst, src, INT32_MIN);
4180  }
4181  
trans_fnegabs_f(DisasContext * ctx,arg_fclass01 * a)4182  static bool trans_fnegabs_f(DisasContext *ctx, arg_fclass01 *a)
4183  {
4184      return do_fop_wew(ctx, a->t, a->r, gen_fnegabs_f);
4185  }
4186  
gen_fnegabs_d(TCGv_i64 dst,TCGv_env unused,TCGv_i64 src)4187  static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4188  {
4189      tcg_gen_ori_i64(dst, src, INT64_MIN);
4190  }
4191  
trans_fnegabs_d(DisasContext * ctx,arg_fclass01 * a)4192  static bool trans_fnegabs_d(DisasContext *ctx, arg_fclass01 *a)
4193  {
4194      return do_fop_ded(ctx, a->t, a->r, gen_fnegabs_d);
4195  }
4196  
4197  /*
4198   * Float class 1
4199   */
4200  
trans_fcnv_d_f(DisasContext * ctx,arg_fclass01 * a)4201  static bool trans_fcnv_d_f(DisasContext *ctx, arg_fclass01 *a)
4202  {
4203      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_s);
4204  }
4205  
trans_fcnv_f_d(DisasContext * ctx,arg_fclass01 * a)4206  static bool trans_fcnv_f_d(DisasContext *ctx, arg_fclass01 *a)
4207  {
4208      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_d);
4209  }
4210  
trans_fcnv_w_f(DisasContext * ctx,arg_fclass01 * a)4211  static bool trans_fcnv_w_f(DisasContext *ctx, arg_fclass01 *a)
4212  {
4213      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_w_s);
4214  }
4215  
trans_fcnv_q_f(DisasContext * ctx,arg_fclass01 * a)4216  static bool trans_fcnv_q_f(DisasContext *ctx, arg_fclass01 *a)
4217  {
4218      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_dw_s);
4219  }
4220  
trans_fcnv_w_d(DisasContext * ctx,arg_fclass01 * a)4221  static bool trans_fcnv_w_d(DisasContext *ctx, arg_fclass01 *a)
4222  {
4223      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_w_d);
4224  }
4225  
trans_fcnv_q_d(DisasContext * ctx,arg_fclass01 * a)4226  static bool trans_fcnv_q_d(DisasContext *ctx, arg_fclass01 *a)
4227  {
4228      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_dw_d);
4229  }
4230  
trans_fcnv_f_w(DisasContext * ctx,arg_fclass01 * a)4231  static bool trans_fcnv_f_w(DisasContext *ctx, arg_fclass01 *a)
4232  {
4233      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_w);
4234  }
4235  
trans_fcnv_d_w(DisasContext * ctx,arg_fclass01 * a)4236  static bool trans_fcnv_d_w(DisasContext *ctx, arg_fclass01 *a)
4237  {
4238      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_w);
4239  }
4240  
trans_fcnv_f_q(DisasContext * ctx,arg_fclass01 * a)4241  static bool trans_fcnv_f_q(DisasContext *ctx, arg_fclass01 *a)
4242  {
4243      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_dw);
4244  }
4245  
trans_fcnv_d_q(DisasContext * ctx,arg_fclass01 * a)4246  static bool trans_fcnv_d_q(DisasContext *ctx, arg_fclass01 *a)
4247  {
4248      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_dw);
4249  }
4250  
trans_fcnv_t_f_w(DisasContext * ctx,arg_fclass01 * a)4251  static bool trans_fcnv_t_f_w(DisasContext *ctx, arg_fclass01 *a)
4252  {
4253      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_w);
4254  }
4255  
trans_fcnv_t_d_w(DisasContext * ctx,arg_fclass01 * a)4256  static bool trans_fcnv_t_d_w(DisasContext *ctx, arg_fclass01 *a)
4257  {
4258      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_w);
4259  }
4260  
trans_fcnv_t_f_q(DisasContext * ctx,arg_fclass01 * a)4261  static bool trans_fcnv_t_f_q(DisasContext *ctx, arg_fclass01 *a)
4262  {
4263      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_dw);
4264  }
4265  
trans_fcnv_t_d_q(DisasContext * ctx,arg_fclass01 * a)4266  static bool trans_fcnv_t_d_q(DisasContext *ctx, arg_fclass01 *a)
4267  {
4268      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_dw);
4269  }
4270  
trans_fcnv_uw_f(DisasContext * ctx,arg_fclass01 * a)4271  static bool trans_fcnv_uw_f(DisasContext *ctx, arg_fclass01 *a)
4272  {
4273      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_uw_s);
4274  }
4275  
trans_fcnv_uq_f(DisasContext * ctx,arg_fclass01 * a)4276  static bool trans_fcnv_uq_f(DisasContext *ctx, arg_fclass01 *a)
4277  {
4278      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_udw_s);
4279  }
4280  
trans_fcnv_uw_d(DisasContext * ctx,arg_fclass01 * a)4281  static bool trans_fcnv_uw_d(DisasContext *ctx, arg_fclass01 *a)
4282  {
4283      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_uw_d);
4284  }
4285  
trans_fcnv_uq_d(DisasContext * ctx,arg_fclass01 * a)4286  static bool trans_fcnv_uq_d(DisasContext *ctx, arg_fclass01 *a)
4287  {
4288      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_udw_d);
4289  }
4290  
trans_fcnv_f_uw(DisasContext * ctx,arg_fclass01 * a)4291  static bool trans_fcnv_f_uw(DisasContext *ctx, arg_fclass01 *a)
4292  {
4293      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_uw);
4294  }
4295  
trans_fcnv_d_uw(DisasContext * ctx,arg_fclass01 * a)4296  static bool trans_fcnv_d_uw(DisasContext *ctx, arg_fclass01 *a)
4297  {
4298      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_uw);
4299  }
4300  
trans_fcnv_f_uq(DisasContext * ctx,arg_fclass01 * a)4301  static bool trans_fcnv_f_uq(DisasContext *ctx, arg_fclass01 *a)
4302  {
4303      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_udw);
4304  }
4305  
trans_fcnv_d_uq(DisasContext * ctx,arg_fclass01 * a)4306  static bool trans_fcnv_d_uq(DisasContext *ctx, arg_fclass01 *a)
4307  {
4308      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_udw);
4309  }
4310  
trans_fcnv_t_f_uw(DisasContext * ctx,arg_fclass01 * a)4311  static bool trans_fcnv_t_f_uw(DisasContext *ctx, arg_fclass01 *a)
4312  {
4313      return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_uw);
4314  }
4315  
trans_fcnv_t_d_uw(DisasContext * ctx,arg_fclass01 * a)4316  static bool trans_fcnv_t_d_uw(DisasContext *ctx, arg_fclass01 *a)
4317  {
4318      return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_uw);
4319  }
4320  
trans_fcnv_t_f_uq(DisasContext * ctx,arg_fclass01 * a)4321  static bool trans_fcnv_t_f_uq(DisasContext *ctx, arg_fclass01 *a)
4322  {
4323      return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_udw);
4324  }
4325  
trans_fcnv_t_d_uq(DisasContext * ctx,arg_fclass01 * a)4326  static bool trans_fcnv_t_d_uq(DisasContext *ctx, arg_fclass01 *a)
4327  {
4328      return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_udw);
4329  }
4330  
4331  /*
4332   * Float class 2
4333   */
4334  
trans_fcmp_f(DisasContext * ctx,arg_fclass2 * a)4335  static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
4336  {
4337      TCGv_i32 ta, tb, tc, ty;
4338  
4339      nullify_over(ctx);
4340  
4341      ta = load_frw0_i32(a->r1);
4342      tb = load_frw0_i32(a->r2);
4343      ty = tcg_constant_i32(a->y);
4344      tc = tcg_constant_i32(a->c);
4345  
4346      gen_helper_fcmp_s(tcg_env, ta, tb, ty, tc);
4347  
4348      return nullify_end(ctx);
4349  }
4350  
trans_fcmp_d(DisasContext * ctx,arg_fclass2 * a)4351  static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
4352  {
4353      TCGv_i64 ta, tb;
4354      TCGv_i32 tc, ty;
4355  
4356      nullify_over(ctx);
4357  
4358      ta = load_frd0(a->r1);
4359      tb = load_frd0(a->r2);
4360      ty = tcg_constant_i32(a->y);
4361      tc = tcg_constant_i32(a->c);
4362  
4363      gen_helper_fcmp_d(tcg_env, ta, tb, ty, tc);
4364  
4365      return nullify_end(ctx);
4366  }
4367  
trans_ftest(DisasContext * ctx,arg_ftest * a)4368  static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
4369  {
4370      TCGCond tc = TCG_COND_TSTNE;
4371      uint32_t mask;
4372      TCGv_i64 t;
4373  
4374      nullify_over(ctx);
4375  
4376      t = tcg_temp_new_i64();
4377      tcg_gen_ld32u_i64(t, tcg_env, offsetof(CPUHPPAState, fr0_shadow));
4378  
4379      if (a->y == 1) {
4380          switch (a->c) {
4381          case 0: /* simple */
4382              mask = R_FPSR_C_MASK;
4383              break;
4384          case 2: /* rej */
4385              tc = TCG_COND_TSTEQ;
4386              /* fallthru */
4387          case 1: /* acc */
4388              mask = R_FPSR_C_MASK | R_FPSR_CQ_MASK;
4389              break;
4390          case 6: /* rej8 */
4391              tc = TCG_COND_TSTEQ;
4392              /* fallthru */
4393          case 5: /* acc8 */
4394              mask = R_FPSR_C_MASK | R_FPSR_CQ0_6_MASK;
4395              break;
4396          case 9: /* acc6 */
4397              mask = R_FPSR_C_MASK | R_FPSR_CQ0_4_MASK;
4398              break;
4399          case 13: /* acc4 */
4400              mask = R_FPSR_C_MASK | R_FPSR_CQ0_2_MASK;
4401              break;
4402          case 17: /* acc2 */
4403              mask = R_FPSR_C_MASK | R_FPSR_CQ0_MASK;
4404              break;
4405          default:
4406              gen_illegal(ctx);
4407              return true;
4408          }
4409      } else {
4410          unsigned cbit = (a->y ^ 1) - 1;
4411          mask = R_FPSR_CA0_MASK >> cbit;
4412      }
4413  
4414      ctx->null_cond = cond_make_ti(tc, t, mask);
4415      return nullify_end(ctx);
4416  }
4417  
4418  /*
4419   * Float class 2
4420   */
4421  
trans_fadd_f(DisasContext * ctx,arg_fclass3 * a)4422  static bool trans_fadd_f(DisasContext *ctx, arg_fclass3 *a)
4423  {
4424      return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fadd_s);
4425  }
4426  
trans_fadd_d(DisasContext * ctx,arg_fclass3 * a)4427  static bool trans_fadd_d(DisasContext *ctx, arg_fclass3 *a)
4428  {
4429      return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fadd_d);
4430  }
4431  
trans_fsub_f(DisasContext * ctx,arg_fclass3 * a)4432  static bool trans_fsub_f(DisasContext *ctx, arg_fclass3 *a)
4433  {
4434      return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fsub_s);
4435  }
4436  
trans_fsub_d(DisasContext * ctx,arg_fclass3 * a)4437  static bool trans_fsub_d(DisasContext *ctx, arg_fclass3 *a)
4438  {
4439      return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fsub_d);
4440  }
4441  
trans_fmpy_f(DisasContext * ctx,arg_fclass3 * a)4442  static bool trans_fmpy_f(DisasContext *ctx, arg_fclass3 *a)
4443  {
4444      return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_s);
4445  }
4446  
trans_fmpy_d(DisasContext * ctx,arg_fclass3 * a)4447  static bool trans_fmpy_d(DisasContext *ctx, arg_fclass3 *a)
4448  {
4449      return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_d);
4450  }
4451  
trans_fdiv_f(DisasContext * ctx,arg_fclass3 * a)4452  static bool trans_fdiv_f(DisasContext *ctx, arg_fclass3 *a)
4453  {
4454      return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_s);
4455  }
4456  
trans_fdiv_d(DisasContext * ctx,arg_fclass3 * a)4457  static bool trans_fdiv_d(DisasContext *ctx, arg_fclass3 *a)
4458  {
4459      return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_d);
4460  }
4461  
trans_xmpyu(DisasContext * ctx,arg_xmpyu * a)4462  static bool trans_xmpyu(DisasContext *ctx, arg_xmpyu *a)
4463  {
4464      TCGv_i64 x, y;
4465  
4466      nullify_over(ctx);
4467  
4468      x = load_frw0_i64(a->r1);
4469      y = load_frw0_i64(a->r2);
4470      tcg_gen_mul_i64(x, x, y);
4471      save_frd(a->t, x);
4472  
4473      return nullify_end(ctx);
4474  }
4475  
4476  /* Convert the fmpyadd single-precision register encodings to standard.  */
fmpyadd_s_reg(unsigned r)4477  static inline int fmpyadd_s_reg(unsigned r)
4478  {
4479      return (r & 16) * 2 + 16 + (r & 15);
4480  }
4481  
do_fmpyadd_s(DisasContext * ctx,arg_mpyadd * a,bool is_sub)4482  static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4483  {
4484      int tm = fmpyadd_s_reg(a->tm);
4485      int ra = fmpyadd_s_reg(a->ra);
4486      int ta = fmpyadd_s_reg(a->ta);
4487      int rm2 = fmpyadd_s_reg(a->rm2);
4488      int rm1 = fmpyadd_s_reg(a->rm1);
4489  
4490      nullify_over(ctx);
4491  
4492      do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
4493      do_fop_weww(ctx, ta, ta, ra,
4494                  is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
4495  
4496      return nullify_end(ctx);
4497  }
4498  
trans_fmpyadd_f(DisasContext * ctx,arg_mpyadd * a)4499  static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
4500  {
4501      return do_fmpyadd_s(ctx, a, false);
4502  }
4503  
trans_fmpysub_f(DisasContext * ctx,arg_mpyadd * a)4504  static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
4505  {
4506      return do_fmpyadd_s(ctx, a, true);
4507  }
4508  
do_fmpyadd_d(DisasContext * ctx,arg_mpyadd * a,bool is_sub)4509  static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4510  {
4511      nullify_over(ctx);
4512  
4513      do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
4514      do_fop_dedd(ctx, a->ta, a->ta, a->ra,
4515                  is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
4516  
4517      return nullify_end(ctx);
4518  }
4519  
trans_fmpyadd_d(DisasContext * ctx,arg_mpyadd * a)4520  static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
4521  {
4522      return do_fmpyadd_d(ctx, a, false);
4523  }
4524  
trans_fmpysub_d(DisasContext * ctx,arg_mpyadd * a)4525  static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
4526  {
4527      return do_fmpyadd_d(ctx, a, true);
4528  }
4529  
trans_fmpyfadd_f(DisasContext * ctx,arg_fmpyfadd_f * a)4530  static bool trans_fmpyfadd_f(DisasContext *ctx, arg_fmpyfadd_f *a)
4531  {
4532      TCGv_i32 x, y, z;
4533  
4534      nullify_over(ctx);
4535      x = load_frw0_i32(a->rm1);
4536      y = load_frw0_i32(a->rm2);
4537      z = load_frw0_i32(a->ra3);
4538  
4539      if (a->neg) {
4540          gen_helper_fmpynfadd_s(x, tcg_env, x, y, z);
4541      } else {
4542          gen_helper_fmpyfadd_s(x, tcg_env, x, y, z);
4543      }
4544  
4545      save_frw_i32(a->t, x);
4546      return nullify_end(ctx);
4547  }
4548  
trans_fmpyfadd_d(DisasContext * ctx,arg_fmpyfadd_d * a)4549  static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
4550  {
4551      TCGv_i64 x, y, z;
4552  
4553      nullify_over(ctx);
4554      x = load_frd0(a->rm1);
4555      y = load_frd0(a->rm2);
4556      z = load_frd0(a->ra3);
4557  
4558      if (a->neg) {
4559          gen_helper_fmpynfadd_d(x, tcg_env, x, y, z);
4560      } else {
4561          gen_helper_fmpyfadd_d(x, tcg_env, x, y, z);
4562      }
4563  
4564      save_frd(a->t, x);
4565      return nullify_end(ctx);
4566  }
4567  
4568  /* Emulate PDC BTLB, called by SeaBIOS-hppa */
trans_diag_btlb(DisasContext * ctx,arg_diag_btlb * a)4569  static bool trans_diag_btlb(DisasContext *ctx, arg_diag_btlb *a)
4570  {
4571      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4572  #ifndef CONFIG_USER_ONLY
4573      nullify_over(ctx);
4574      gen_helper_diag_btlb(tcg_env);
4575      return nullify_end(ctx);
4576  #endif
4577  }
4578  
4579  /* Print char in %r26 to first serial console, used by SeaBIOS-hppa */
trans_diag_cout(DisasContext * ctx,arg_diag_cout * a)4580  static bool trans_diag_cout(DisasContext *ctx, arg_diag_cout *a)
4581  {
4582      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4583  #ifndef CONFIG_USER_ONLY
4584      nullify_over(ctx);
4585      gen_helper_diag_console_output(tcg_env);
4586      return nullify_end(ctx);
4587  #endif
4588  }
4589  
trans_diag_getshadowregs_pa1(DisasContext * ctx,arg_empty * a)4590  static bool trans_diag_getshadowregs_pa1(DisasContext *ctx, arg_empty *a)
4591  {
4592      return !ctx->is_pa20 && do_getshadowregs(ctx);
4593  }
4594  
trans_diag_getshadowregs_pa2(DisasContext * ctx,arg_empty * a)4595  static bool trans_diag_getshadowregs_pa2(DisasContext *ctx, arg_empty *a)
4596  {
4597      return ctx->is_pa20 && do_getshadowregs(ctx);
4598  }
4599  
trans_diag_putshadowregs_pa1(DisasContext * ctx,arg_empty * a)4600  static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a)
4601  {
4602      return !ctx->is_pa20 && do_putshadowregs(ctx);
4603  }
4604  
trans_diag_putshadowregs_pa2(DisasContext * ctx,arg_empty * a)4605  static bool trans_diag_putshadowregs_pa2(DisasContext *ctx, arg_empty *a)
4606  {
4607      return ctx->is_pa20 && do_putshadowregs(ctx);
4608  }
4609  
trans_diag_unimp(DisasContext * ctx,arg_diag_unimp * a)4610  static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a)
4611  {
4612      CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4613      qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
4614      return true;
4615  }
4616  
hppa_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cs)4617  static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4618  {
4619      DisasContext *ctx = container_of(dcbase, DisasContext, base);
4620      uint64_t cs_base;
4621      int bound;
4622  
4623      ctx->cs = cs;
4624      ctx->tb_flags = ctx->base.tb->flags;
4625      ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
4626      ctx->psw_xb = ctx->tb_flags & (PSW_X | PSW_B);
4627  
4628  #ifdef CONFIG_USER_ONLY
4629      ctx->privilege = PRIV_USER;
4630      ctx->mmu_idx = MMU_USER_IDX;
4631      ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
4632  #else
4633      ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
4634      ctx->mmu_idx = (ctx->tb_flags & PSW_D
4635                      ? PRIV_P_TO_MMU_IDX(ctx->privilege, ctx->tb_flags & PSW_P)
4636                      : ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
4637  #endif
4638  
4639      cs_base = ctx->base.tb->cs_base;
4640      ctx->iaoq_first = ctx->base.pc_first + ctx->privilege;
4641  
4642      if (unlikely(cs_base & CS_BASE_DIFFSPACE)) {
4643          ctx->iaq_b.space = cpu_iasq_b;
4644          ctx->iaq_b.base = cpu_iaoq_b;
4645      } else if (unlikely(cs_base & CS_BASE_DIFFPAGE)) {
4646          ctx->iaq_b.base = cpu_iaoq_b;
4647      } else {
4648          uint64_t iaoq_f_pgofs = ctx->iaoq_first & ~TARGET_PAGE_MASK;
4649          uint64_t iaoq_b_pgofs = cs_base & ~TARGET_PAGE_MASK;
4650          ctx->iaq_b.disp = iaoq_b_pgofs - iaoq_f_pgofs;
4651      }
4652  
4653      ctx->zero = tcg_constant_i64(0);
4654  
4655      /* Bound the number of instructions by those left on the page.  */
4656      bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
4657      ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
4658  }
4659  
hppa_tr_tb_start(DisasContextBase * dcbase,CPUState * cs)4660  static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
4661  {
4662      DisasContext *ctx = container_of(dcbase, DisasContext, base);
4663  
4664      /* Seed the nullification status from PSW[N], as saved in TB->FLAGS.  */
4665      ctx->null_cond = cond_make_f();
4666      ctx->psw_n_nonzero = false;
4667      if (ctx->tb_flags & PSW_N) {
4668          ctx->null_cond.c = TCG_COND_ALWAYS;
4669          ctx->psw_n_nonzero = true;
4670      }
4671      ctx->null_lab = NULL;
4672  }
4673  
hppa_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)4674  static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
4675  {
4676      DisasContext *ctx = container_of(dcbase, DisasContext, base);
4677      uint64_t iaoq_f, iaoq_b;
4678      int64_t diff;
4679  
4680      tcg_debug_assert(!iaqe_variable(&ctx->iaq_f));
4681  
4682      iaoq_f = ctx->iaoq_first + ctx->iaq_f.disp;
4683      if (iaqe_variable(&ctx->iaq_b)) {
4684          diff = INT32_MIN;
4685      } else {
4686          iaoq_b = ctx->iaoq_first + ctx->iaq_b.disp;
4687          diff = iaoq_b - iaoq_f;
4688          /* Direct branches can only produce a 24-bit displacement. */
4689          tcg_debug_assert(diff == (int32_t)diff);
4690          tcg_debug_assert(diff != INT32_MIN);
4691      }
4692  
4693      tcg_gen_insn_start(iaoq_f & ~TARGET_PAGE_MASK, diff, 0);
4694      ctx->insn_start_updated = false;
4695  }
4696  
hppa_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)4697  static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
4698  {
4699      DisasContext *ctx = container_of(dcbase, DisasContext, base);
4700      CPUHPPAState *env = cpu_env(cs);
4701      DisasJumpType ret;
4702  
4703      /* Execute one insn.  */
4704  #ifdef CONFIG_USER_ONLY
4705      if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
4706          do_page_zero(ctx);
4707          ret = ctx->base.is_jmp;
4708          assert(ret != DISAS_NEXT);
4709      } else
4710  #endif
4711      {
4712          /* Always fetch the insn, even if nullified, so that we check
4713             the page permissions for execute.  */
4714          uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next);
4715  
4716          /*
4717           * Set up the IA queue for the next insn.
4718           * This will be overwritten by a branch.
4719           */
4720          ctx->iaq_n = NULL;
4721          memset(&ctx->iaq_j, 0, sizeof(ctx->iaq_j));
4722          ctx->psw_b_next = false;
4723  
4724          if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
4725              ctx->null_cond.c = TCG_COND_NEVER;
4726              ret = DISAS_NEXT;
4727          } else {
4728              ctx->insn = insn;
4729              if (!decode(ctx, insn)) {
4730                  gen_illegal(ctx);
4731              }
4732              ret = ctx->base.is_jmp;
4733              assert(ctx->null_lab == NULL);
4734          }
4735  
4736          if (ret != DISAS_NORETURN) {
4737              set_psw_xb(ctx, ctx->psw_b_next ? PSW_B : 0);
4738          }
4739      }
4740  
4741      /* If the TranslationBlock must end, do so. */
4742      ctx->base.pc_next += 4;
4743      if (ret != DISAS_NEXT) {
4744          return;
4745      }
4746      /* Note this also detects a priority change. */
4747      if (iaqe_variable(&ctx->iaq_b)
4748          || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
4749          ctx->base.is_jmp = DISAS_IAQ_N_STALE;
4750          return;
4751      }
4752  
4753      /*
4754       * Advance the insn queue.
4755       * The only exit now is DISAS_TOO_MANY from the translator loop.
4756       */
4757      ctx->iaq_f.disp = ctx->iaq_b.disp;
4758      if (!ctx->iaq_n) {
4759          ctx->iaq_b.disp += 4;
4760          return;
4761      }
4762      /*
4763       * If IAQ_Next is variable in any way, we need to copy into the
4764       * IAQ_Back globals, in case the next insn raises an exception.
4765       */
4766      if (ctx->iaq_n->base) {
4767          copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaq_n);
4768          ctx->iaq_b.base = cpu_iaoq_b;
4769          ctx->iaq_b.disp = 0;
4770      } else {
4771          ctx->iaq_b.disp = ctx->iaq_n->disp;
4772      }
4773      if (ctx->iaq_n->space) {
4774          tcg_gen_mov_i64(cpu_iasq_b, ctx->iaq_n->space);
4775          ctx->iaq_b.space = cpu_iasq_b;
4776      }
4777  }
4778  
hppa_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)4779  static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
4780  {
4781      DisasContext *ctx = container_of(dcbase, DisasContext, base);
4782      DisasJumpType is_jmp = ctx->base.is_jmp;
4783      /* Assume the insn queue has not been advanced. */
4784      DisasIAQE *f = &ctx->iaq_b;
4785      DisasIAQE *b = ctx->iaq_n;
4786  
4787      switch (is_jmp) {
4788      case DISAS_NORETURN:
4789          break;
4790      case DISAS_TOO_MANY:
4791          /* The insn queue has not been advanced. */
4792          f = &ctx->iaq_f;
4793          b = &ctx->iaq_b;
4794          /* FALLTHRU */
4795      case DISAS_IAQ_N_STALE:
4796          if (use_goto_tb(ctx, f, b)
4797              && (ctx->null_cond.c == TCG_COND_NEVER
4798                  || ctx->null_cond.c == TCG_COND_ALWAYS)) {
4799              nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
4800              gen_goto_tb(ctx, 0, f, b);
4801              break;
4802          }
4803          /* FALLTHRU */
4804      case DISAS_IAQ_N_STALE_EXIT:
4805          install_iaq_entries(ctx, f, b);
4806          nullify_save(ctx);
4807          if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
4808              tcg_gen_exit_tb(NULL, 0);
4809              break;
4810          }
4811          /* FALLTHRU */
4812      case DISAS_IAQ_N_UPDATED:
4813          tcg_gen_lookup_and_goto_ptr();
4814          break;
4815      case DISAS_EXIT:
4816          tcg_gen_exit_tb(NULL, 0);
4817          break;
4818      default:
4819          g_assert_not_reached();
4820      }
4821  
4822      for (DisasDelayException *e = ctx->delay_excp_list; e ; e = e->next) {
4823          gen_set_label(e->lab);
4824          if (e->set_n >= 0) {
4825              tcg_gen_movi_i64(cpu_psw_n, e->set_n);
4826          }
4827          if (e->set_iir) {
4828              tcg_gen_st_i64(tcg_constant_i64(e->insn), tcg_env,
4829                             offsetof(CPUHPPAState, cr[CR_IIR]));
4830          }
4831          install_iaq_entries(ctx, &e->iaq_f, &e->iaq_b);
4832          gen_excp_1(e->excp);
4833      }
4834  }
4835  
4836  #ifdef CONFIG_USER_ONLY
hppa_tr_disas_log(const DisasContextBase * dcbase,CPUState * cs,FILE * logfile)4837  static bool hppa_tr_disas_log(const DisasContextBase *dcbase,
4838                                CPUState *cs, FILE *logfile)
4839  {
4840      target_ulong pc = dcbase->pc_first;
4841  
4842      switch (pc) {
4843      case 0x00:
4844          fprintf(logfile, "IN:\n0x00000000:  (null)\n");
4845          return true;
4846      case 0xb0:
4847          fprintf(logfile, "IN:\n0x000000b0:  light-weight-syscall\n");
4848          return true;
4849      case 0xe0:
4850          fprintf(logfile, "IN:\n0x000000e0:  set-thread-pointer-syscall\n");
4851          return true;
4852      case 0x100:
4853          fprintf(logfile, "IN:\n0x00000100:  syscall\n");
4854          return true;
4855      }
4856      return false;
4857  }
4858  #endif
4859  
4860  static const TranslatorOps hppa_tr_ops = {
4861      .init_disas_context = hppa_tr_init_disas_context,
4862      .tb_start           = hppa_tr_tb_start,
4863      .insn_start         = hppa_tr_insn_start,
4864      .translate_insn     = hppa_tr_translate_insn,
4865      .tb_stop            = hppa_tr_tb_stop,
4866  #ifdef CONFIG_USER_ONLY
4867      .disas_log          = hppa_tr_disas_log,
4868  #endif
4869  };
4870  
gen_intermediate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)4871  void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
4872                             vaddr pc, void *host_pc)
4873  {
4874      DisasContext ctx = { };
4875      translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
4876  }
4877