xref: /openbmc/qemu/target/openrisc/translate.c (revision 2b01688380103acc2a9cd197b964d643fceba2a9)
1  /*
2   * OpenRISC translation
3   *
4   * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5   *                         Feng Gao <gf91597@gmail.com>
6   *
7   * This library is free software; you can redistribute it and/or
8   * modify it under the terms of the GNU Lesser General Public
9   * License as published by the Free Software Foundation; either
10   * version 2.1 of the License, or (at your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19   */
20  
21  #include "qemu/osdep.h"
22  #include "cpu.h"
23  #include "exec/exec-all.h"
24  #include "tcg/tcg-op.h"
25  #include "qemu/log.h"
26  #include "qemu/bitops.h"
27  #include "qemu/qemu-print.h"
28  #include "exec/translator.h"
29  
30  #include "exec/helper-proto.h"
31  #include "exec/helper-gen.h"
32  
33  #include "exec/log.h"
34  
35  #define HELPER_H "helper.h"
36  #include "exec/helper-info.c.inc"
37  #undef  HELPER_H
38  
39  
40  /* is_jmp field values */
41  #define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
42  #define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
43  
44  typedef struct DisasContext {
45      DisasContextBase base;
46      uint32_t mem_idx;
47      uint32_t tb_flags;
48      uint32_t delayed_branch;
49      uint32_t cpucfgr;
50      uint32_t avr;
51  
52      /* If not -1, jmp_pc contains this value and so is a direct jump.  */
53      target_ulong jmp_pc_imm;
54  
55      /* The temporary corresponding to register 0 for this compilation.  */
56      TCGv R0;
57      /* The constant zero. */
58      TCGv zero;
59  } DisasContext;
60  
is_user(DisasContext * dc)61  static inline bool is_user(DisasContext *dc)
62  {
63  #ifdef CONFIG_USER_ONLY
64      return true;
65  #else
66      return !(dc->tb_flags & TB_FLAGS_SM);
67  #endif
68  }
69  
70  /* Include the auto-generated decoder.  */
71  #include "decode-insns.c.inc"
72  
73  static TCGv cpu_sr;
74  static TCGv cpu_regs[32];
75  static TCGv cpu_pc;
76  static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
77  static TCGv cpu_ppc;
78  static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
79  static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
80  static TCGv cpu_sr_ov;          /* signed overflow */
81  static TCGv cpu_lock_addr;
82  static TCGv cpu_lock_value;
83  static TCGv_i32 fpcsr;
84  static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
85  static TCGv_i32 cpu_dflag;
86  
openrisc_translate_init(void)87  void openrisc_translate_init(void)
88  {
89      static const char * const regnames[] = {
90          "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
91          "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
92          "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
93          "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
94      };
95      int i;
96  
97      cpu_sr = tcg_global_mem_new(tcg_env,
98                                  offsetof(CPUOpenRISCState, sr), "sr");
99      cpu_dflag = tcg_global_mem_new_i32(tcg_env,
100                                         offsetof(CPUOpenRISCState, dflag),
101                                         "dflag");
102      cpu_pc = tcg_global_mem_new(tcg_env,
103                                  offsetof(CPUOpenRISCState, pc), "pc");
104      cpu_ppc = tcg_global_mem_new(tcg_env,
105                                   offsetof(CPUOpenRISCState, ppc), "ppc");
106      jmp_pc = tcg_global_mem_new(tcg_env,
107                                  offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
108      cpu_sr_f = tcg_global_mem_new(tcg_env,
109                                    offsetof(CPUOpenRISCState, sr_f), "sr_f");
110      cpu_sr_cy = tcg_global_mem_new(tcg_env,
111                                     offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
112      cpu_sr_ov = tcg_global_mem_new(tcg_env,
113                                     offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
114      cpu_lock_addr = tcg_global_mem_new(tcg_env,
115                                         offsetof(CPUOpenRISCState, lock_addr),
116                                         "lock_addr");
117      cpu_lock_value = tcg_global_mem_new(tcg_env,
118                                          offsetof(CPUOpenRISCState, lock_value),
119                                          "lock_value");
120      fpcsr = tcg_global_mem_new_i32(tcg_env,
121                                     offsetof(CPUOpenRISCState, fpcsr),
122                                     "fpcsr");
123      cpu_mac = tcg_global_mem_new_i64(tcg_env,
124                                       offsetof(CPUOpenRISCState, mac),
125                                       "mac");
126      for (i = 0; i < 32; i++) {
127          cpu_regs[i] = tcg_global_mem_new(tcg_env,
128                                           offsetof(CPUOpenRISCState,
129                                                    shadow_gpr[0][i]),
130                                           regnames[i]);
131      }
132  }
133  
gen_exception(DisasContext * dc,unsigned int excp)134  static void gen_exception(DisasContext *dc, unsigned int excp)
135  {
136      gen_helper_exception(tcg_env, tcg_constant_i32(excp));
137  }
138  
gen_illegal_exception(DisasContext * dc)139  static void gen_illegal_exception(DisasContext *dc)
140  {
141      tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
142      gen_exception(dc, EXCP_ILLEGAL);
143      dc->base.is_jmp = DISAS_NORETURN;
144  }
145  
check_v1_3(DisasContext * dc)146  static bool check_v1_3(DisasContext *dc)
147  {
148      return dc->avr >= 0x01030000;
149  }
150  
check_of32s(DisasContext * dc)151  static bool check_of32s(DisasContext *dc)
152  {
153      return dc->cpucfgr & CPUCFGR_OF32S;
154  }
155  
check_of64a32s(DisasContext * dc)156  static bool check_of64a32s(DisasContext *dc)
157  {
158      return dc->cpucfgr & CPUCFGR_OF64A32S;
159  }
160  
cpu_R(DisasContext * dc,int reg)161  static TCGv cpu_R(DisasContext *dc, int reg)
162  {
163      if (reg == 0) {
164          return dc->R0;
165      } else {
166          return cpu_regs[reg];
167      }
168  }
169  
170  /*
171   * We're about to write to REG.  On the off-chance that the user is
172   * writing to R0, re-instate the architectural register.
173   */
check_r0_write(DisasContext * dc,int reg)174  static void check_r0_write(DisasContext *dc, int reg)
175  {
176      if (unlikely(reg == 0)) {
177          dc->R0 = cpu_regs[0];
178      }
179  }
180  
gen_ove_cy(DisasContext * dc)181  static void gen_ove_cy(DisasContext *dc)
182  {
183      if (dc->tb_flags & SR_OVE) {
184          gen_helper_ove_cy(tcg_env);
185      }
186  }
187  
gen_ove_ov(DisasContext * dc)188  static void gen_ove_ov(DisasContext *dc)
189  {
190      if (dc->tb_flags & SR_OVE) {
191          gen_helper_ove_ov(tcg_env);
192      }
193  }
194  
gen_ove_cyov(DisasContext * dc)195  static void gen_ove_cyov(DisasContext *dc)
196  {
197      if (dc->tb_flags & SR_OVE) {
198          gen_helper_ove_cyov(tcg_env);
199      }
200  }
201  
gen_add(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)202  static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
203  {
204      TCGv t0 = tcg_temp_new();
205      TCGv res = tcg_temp_new();
206  
207      tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero);
208      tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
209      tcg_gen_xor_tl(t0, res, srcb);
210      tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
211  
212      tcg_gen_mov_tl(dest, res);
213  
214      gen_ove_cyov(dc);
215  }
216  
gen_addc(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)217  static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
218  {
219      TCGv t0 = tcg_temp_new();
220      TCGv res = tcg_temp_new();
221  
222      tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero);
223      tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero);
224      tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
225      tcg_gen_xor_tl(t0, res, srcb);
226      tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
227  
228      tcg_gen_mov_tl(dest, res);
229  
230      gen_ove_cyov(dc);
231  }
232  
gen_sub(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)233  static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
234  {
235      TCGv res = tcg_temp_new();
236  
237      tcg_gen_sub_tl(res, srca, srcb);
238      tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
239      tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
240      tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
241      tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
242  
243      tcg_gen_mov_tl(dest, res);
244  
245      gen_ove_cyov(dc);
246  }
247  
gen_mul(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)248  static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
249  {
250      TCGv t0 = tcg_temp_new();
251  
252      tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
253      tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
254      tcg_gen_negsetcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
255  
256      gen_ove_ov(dc);
257  }
258  
gen_mulu(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)259  static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
260  {
261      tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
262      tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
263  
264      gen_ove_cy(dc);
265  }
266  
gen_div(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)267  static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
268  {
269      TCGv t0 = tcg_temp_new();
270  
271      tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
272      /* The result of divide-by-zero is undefined.
273         Suppress the host-side exception by dividing by 1. */
274      tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
275      tcg_gen_div_tl(dest, srca, t0);
276  
277      tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
278      gen_ove_ov(dc);
279  }
280  
gen_divu(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)281  static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
282  {
283      TCGv t0 = tcg_temp_new();
284  
285      tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
286      /* The result of divide-by-zero is undefined.
287         Suppress the host-side exception by dividing by 1. */
288      tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
289      tcg_gen_divu_tl(dest, srca, t0);
290  
291      gen_ove_cy(dc);
292  }
293  
gen_muld(DisasContext * dc,TCGv srca,TCGv srcb)294  static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
295  {
296      TCGv_i64 t1 = tcg_temp_new_i64();
297      TCGv_i64 t2 = tcg_temp_new_i64();
298  
299      tcg_gen_ext_tl_i64(t1, srca);
300      tcg_gen_ext_tl_i64(t2, srcb);
301      if (TARGET_LONG_BITS == 32) {
302          tcg_gen_mul_i64(cpu_mac, t1, t2);
303          tcg_gen_movi_tl(cpu_sr_ov, 0);
304      } else {
305          TCGv_i64 high = tcg_temp_new_i64();
306  
307          tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
308          tcg_gen_sari_i64(t1, cpu_mac, 63);
309          tcg_gen_negsetcond_i64(TCG_COND_NE, t1, t1, high);
310          tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
311  
312          gen_ove_ov(dc);
313      }
314  }
315  
gen_muldu(DisasContext * dc,TCGv srca,TCGv srcb)316  static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
317  {
318      TCGv_i64 t1 = tcg_temp_new_i64();
319      TCGv_i64 t2 = tcg_temp_new_i64();
320  
321      tcg_gen_extu_tl_i64(t1, srca);
322      tcg_gen_extu_tl_i64(t2, srcb);
323      if (TARGET_LONG_BITS == 32) {
324          tcg_gen_mul_i64(cpu_mac, t1, t2);
325          tcg_gen_movi_tl(cpu_sr_cy, 0);
326      } else {
327          TCGv_i64 high = tcg_temp_new_i64();
328  
329          tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
330          tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
331          tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
332  
333          gen_ove_cy(dc);
334      }
335  }
336  
gen_mac(DisasContext * dc,TCGv srca,TCGv srcb)337  static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
338  {
339      TCGv_i64 t1 = tcg_temp_new_i64();
340      TCGv_i64 t2 = tcg_temp_new_i64();
341  
342      tcg_gen_ext_tl_i64(t1, srca);
343      tcg_gen_ext_tl_i64(t2, srcb);
344      tcg_gen_mul_i64(t1, t1, t2);
345  
346      /* Note that overflow is only computed during addition stage.  */
347      tcg_gen_xor_i64(t2, cpu_mac, t1);
348      tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
349      tcg_gen_xor_i64(t1, t1, cpu_mac);
350      tcg_gen_andc_i64(t1, t1, t2);
351  
352  #if TARGET_LONG_BITS == 32
353      tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
354  #else
355      tcg_gen_mov_i64(cpu_sr_ov, t1);
356  #endif
357  
358      gen_ove_ov(dc);
359  }
360  
gen_macu(DisasContext * dc,TCGv srca,TCGv srcb)361  static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
362  {
363      TCGv_i64 t1 = tcg_temp_new_i64();
364      TCGv_i64 t2 = tcg_temp_new_i64();
365  
366      tcg_gen_extu_tl_i64(t1, srca);
367      tcg_gen_extu_tl_i64(t2, srcb);
368      tcg_gen_mul_i64(t1, t1, t2);
369  
370      /* Note that overflow is only computed during addition stage.  */
371      tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
372      tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
373      tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
374  
375      gen_ove_cy(dc);
376  }
377  
gen_msb(DisasContext * dc,TCGv srca,TCGv srcb)378  static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
379  {
380      TCGv_i64 t1 = tcg_temp_new_i64();
381      TCGv_i64 t2 = tcg_temp_new_i64();
382  
383      tcg_gen_ext_tl_i64(t1, srca);
384      tcg_gen_ext_tl_i64(t2, srcb);
385      tcg_gen_mul_i64(t1, t1, t2);
386  
387      /* Note that overflow is only computed during subtraction stage.  */
388      tcg_gen_xor_i64(t2, cpu_mac, t1);
389      tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
390      tcg_gen_xor_i64(t1, t1, cpu_mac);
391      tcg_gen_and_i64(t1, t1, t2);
392  
393  #if TARGET_LONG_BITS == 32
394      tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
395  #else
396      tcg_gen_mov_i64(cpu_sr_ov, t1);
397  #endif
398  
399      gen_ove_ov(dc);
400  }
401  
gen_msbu(DisasContext * dc,TCGv srca,TCGv srcb)402  static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
403  {
404      TCGv_i64 t1 = tcg_temp_new_i64();
405      TCGv_i64 t2 = tcg_temp_new_i64();
406  
407      tcg_gen_extu_tl_i64(t1, srca);
408      tcg_gen_extu_tl_i64(t2, srcb);
409      tcg_gen_mul_i64(t1, t1, t2);
410  
411      /* Note that overflow is only computed during subtraction stage.  */
412      tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
413      tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
414      tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
415  
416      gen_ove_cy(dc);
417  }
418  
trans_l_add(DisasContext * dc,arg_dab * a)419  static bool trans_l_add(DisasContext *dc, arg_dab *a)
420  {
421      check_r0_write(dc, a->d);
422      gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
423      return true;
424  }
425  
trans_l_addc(DisasContext * dc,arg_dab * a)426  static bool trans_l_addc(DisasContext *dc, arg_dab *a)
427  {
428      check_r0_write(dc, a->d);
429      gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
430      return true;
431  }
432  
trans_l_sub(DisasContext * dc,arg_dab * a)433  static bool trans_l_sub(DisasContext *dc, arg_dab *a)
434  {
435      check_r0_write(dc, a->d);
436      gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
437      return true;
438  }
439  
trans_l_and(DisasContext * dc,arg_dab * a)440  static bool trans_l_and(DisasContext *dc, arg_dab *a)
441  {
442      check_r0_write(dc, a->d);
443      tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
444      return true;
445  }
446  
trans_l_or(DisasContext * dc,arg_dab * a)447  static bool trans_l_or(DisasContext *dc, arg_dab *a)
448  {
449      check_r0_write(dc, a->d);
450      tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
451      return true;
452  }
453  
trans_l_xor(DisasContext * dc,arg_dab * a)454  static bool trans_l_xor(DisasContext *dc, arg_dab *a)
455  {
456      check_r0_write(dc, a->d);
457      tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
458      return true;
459  }
460  
trans_l_sll(DisasContext * dc,arg_dab * a)461  static bool trans_l_sll(DisasContext *dc, arg_dab *a)
462  {
463      check_r0_write(dc, a->d);
464      tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
465      return true;
466  }
467  
trans_l_srl(DisasContext * dc,arg_dab * a)468  static bool trans_l_srl(DisasContext *dc, arg_dab *a)
469  {
470      check_r0_write(dc, a->d);
471      tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
472      return true;
473  }
474  
trans_l_sra(DisasContext * dc,arg_dab * a)475  static bool trans_l_sra(DisasContext *dc, arg_dab *a)
476  {
477      check_r0_write(dc, a->d);
478      tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
479      return true;
480  }
481  
trans_l_ror(DisasContext * dc,arg_dab * a)482  static bool trans_l_ror(DisasContext *dc, arg_dab *a)
483  {
484      check_r0_write(dc, a->d);
485      tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
486      return true;
487  }
488  
trans_l_exths(DisasContext * dc,arg_da * a)489  static bool trans_l_exths(DisasContext *dc, arg_da *a)
490  {
491      check_r0_write(dc, a->d);
492      tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
493      return true;
494  }
495  
trans_l_extbs(DisasContext * dc,arg_da * a)496  static bool trans_l_extbs(DisasContext *dc, arg_da *a)
497  {
498      check_r0_write(dc, a->d);
499      tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
500      return true;
501  }
502  
trans_l_exthz(DisasContext * dc,arg_da * a)503  static bool trans_l_exthz(DisasContext *dc, arg_da *a)
504  {
505      check_r0_write(dc, a->d);
506      tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
507      return true;
508  }
509  
trans_l_extbz(DisasContext * dc,arg_da * a)510  static bool trans_l_extbz(DisasContext *dc, arg_da *a)
511  {
512      check_r0_write(dc, a->d);
513      tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
514      return true;
515  }
516  
trans_l_cmov(DisasContext * dc,arg_dab * a)517  static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
518  {
519      check_r0_write(dc, a->d);
520      tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero,
521                         cpu_R(dc, a->a), cpu_R(dc, a->b));
522      return true;
523  }
524  
trans_l_ff1(DisasContext * dc,arg_da * a)525  static bool trans_l_ff1(DisasContext *dc, arg_da *a)
526  {
527      check_r0_write(dc, a->d);
528      tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
529      tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
530      return true;
531  }
532  
trans_l_fl1(DisasContext * dc,arg_da * a)533  static bool trans_l_fl1(DisasContext *dc, arg_da *a)
534  {
535      check_r0_write(dc, a->d);
536      tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
537      tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
538      return true;
539  }
540  
trans_l_mul(DisasContext * dc,arg_dab * a)541  static bool trans_l_mul(DisasContext *dc, arg_dab *a)
542  {
543      check_r0_write(dc, a->d);
544      gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
545      return true;
546  }
547  
trans_l_mulu(DisasContext * dc,arg_dab * a)548  static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
549  {
550      check_r0_write(dc, a->d);
551      gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
552      return true;
553  }
554  
trans_l_div(DisasContext * dc,arg_dab * a)555  static bool trans_l_div(DisasContext *dc, arg_dab *a)
556  {
557      check_r0_write(dc, a->d);
558      gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
559      return true;
560  }
561  
trans_l_divu(DisasContext * dc,arg_dab * a)562  static bool trans_l_divu(DisasContext *dc, arg_dab *a)
563  {
564      check_r0_write(dc, a->d);
565      gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
566      return true;
567  }
568  
trans_l_muld(DisasContext * dc,arg_ab * a)569  static bool trans_l_muld(DisasContext *dc, arg_ab *a)
570  {
571      gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
572      return true;
573  }
574  
trans_l_muldu(DisasContext * dc,arg_ab * a)575  static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
576  {
577      gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
578      return true;
579  }
580  
trans_l_j(DisasContext * dc,arg_l_j * a)581  static bool trans_l_j(DisasContext *dc, arg_l_j *a)
582  {
583      target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
584  
585      tcg_gen_movi_tl(jmp_pc, tmp_pc);
586      dc->jmp_pc_imm = tmp_pc;
587      dc->delayed_branch = 2;
588      return true;
589  }
590  
trans_l_jal(DisasContext * dc,arg_l_jal * a)591  static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
592  {
593      target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
594      target_ulong ret_pc = dc->base.pc_next + 8;
595  
596      tcg_gen_movi_tl(cpu_regs[9], ret_pc);
597      /* Optimize jal being used to load the PC for PIC.  */
598      if (tmp_pc != ret_pc) {
599          tcg_gen_movi_tl(jmp_pc, tmp_pc);
600          dc->jmp_pc_imm = tmp_pc;
601          dc->delayed_branch = 2;
602      }
603      return true;
604  }
605  
do_bf(DisasContext * dc,arg_l_bf * a,TCGCond cond)606  static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
607  {
608      target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
609      TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8);
610      TCGv t_true = tcg_constant_tl(tmp_pc);
611  
612      tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next);
613      dc->delayed_branch = 2;
614  }
615  
trans_l_bf(DisasContext * dc,arg_l_bf * a)616  static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
617  {
618      do_bf(dc, a, TCG_COND_NE);
619      return true;
620  }
621  
trans_l_bnf(DisasContext * dc,arg_l_bf * a)622  static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
623  {
624      do_bf(dc, a, TCG_COND_EQ);
625      return true;
626  }
627  
trans_l_jr(DisasContext * dc,arg_l_jr * a)628  static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
629  {
630      tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
631      dc->delayed_branch = 2;
632      return true;
633  }
634  
trans_l_jalr(DisasContext * dc,arg_l_jalr * a)635  static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
636  {
637      tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
638      tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
639      dc->delayed_branch = 2;
640      return true;
641  }
642  
trans_l_lwa(DisasContext * dc,arg_load * a)643  static bool trans_l_lwa(DisasContext *dc, arg_load *a)
644  {
645      TCGv ea;
646  
647      check_r0_write(dc, a->d);
648      ea = tcg_temp_new();
649      tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
650      tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
651      tcg_gen_mov_tl(cpu_lock_addr, ea);
652      tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
653      return true;
654  }
655  
do_load(DisasContext * dc,arg_load * a,MemOp mop)656  static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
657  {
658      TCGv ea;
659  
660      check_r0_write(dc, a->d);
661      ea = tcg_temp_new();
662      tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
663      tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
664  }
665  
trans_l_lwz(DisasContext * dc,arg_load * a)666  static bool trans_l_lwz(DisasContext *dc, arg_load *a)
667  {
668      do_load(dc, a, MO_TEUL);
669      return true;
670  }
671  
trans_l_lws(DisasContext * dc,arg_load * a)672  static bool trans_l_lws(DisasContext *dc, arg_load *a)
673  {
674      do_load(dc, a, MO_TESL);
675      return true;
676  }
677  
trans_l_lbz(DisasContext * dc,arg_load * a)678  static bool trans_l_lbz(DisasContext *dc, arg_load *a)
679  {
680      do_load(dc, a, MO_UB);
681      return true;
682  }
683  
trans_l_lbs(DisasContext * dc,arg_load * a)684  static bool trans_l_lbs(DisasContext *dc, arg_load *a)
685  {
686      do_load(dc, a, MO_SB);
687      return true;
688  }
689  
trans_l_lhz(DisasContext * dc,arg_load * a)690  static bool trans_l_lhz(DisasContext *dc, arg_load *a)
691  {
692      do_load(dc, a, MO_TEUW);
693      return true;
694  }
695  
trans_l_lhs(DisasContext * dc,arg_load * a)696  static bool trans_l_lhs(DisasContext *dc, arg_load *a)
697  {
698      do_load(dc, a, MO_TESW);
699      return true;
700  }
701  
trans_l_swa(DisasContext * dc,arg_store * a)702  static bool trans_l_swa(DisasContext *dc, arg_store *a)
703  {
704      TCGv ea, val;
705      TCGLabel *lab_fail, *lab_done;
706  
707      ea = tcg_temp_new();
708      tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
709  
710      lab_fail = gen_new_label();
711      lab_done = gen_new_label();
712      tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
713  
714      val = tcg_temp_new();
715      tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
716                                cpu_R(dc, a->b), dc->mem_idx, MO_TEUL);
717      tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
718  
719      tcg_gen_br(lab_done);
720  
721      gen_set_label(lab_fail);
722      tcg_gen_movi_tl(cpu_sr_f, 0);
723  
724      gen_set_label(lab_done);
725      tcg_gen_movi_tl(cpu_lock_addr, -1);
726      return true;
727  }
728  
do_store(DisasContext * dc,arg_store * a,MemOp mop)729  static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
730  {
731      TCGv t0 = tcg_temp_new();
732      tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
733      tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
734  }
735  
trans_l_sw(DisasContext * dc,arg_store * a)736  static bool trans_l_sw(DisasContext *dc, arg_store *a)
737  {
738      do_store(dc, a, MO_TEUL);
739      return true;
740  }
741  
trans_l_sb(DisasContext * dc,arg_store * a)742  static bool trans_l_sb(DisasContext *dc, arg_store *a)
743  {
744      do_store(dc, a, MO_UB);
745      return true;
746  }
747  
trans_l_sh(DisasContext * dc,arg_store * a)748  static bool trans_l_sh(DisasContext *dc, arg_store *a)
749  {
750      do_store(dc, a, MO_TEUW);
751      return true;
752  }
753  
trans_l_nop(DisasContext * dc,arg_l_nop * a)754  static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
755  {
756      return true;
757  }
758  
trans_l_adrp(DisasContext * dc,arg_l_adrp * a)759  static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a)
760  {
761      if (!check_v1_3(dc)) {
762          return false;
763      }
764      check_r0_write(dc, a->d);
765  
766      tcg_gen_movi_i32(cpu_R(dc, a->d),
767                       (dc->base.pc_next & TARGET_PAGE_MASK) +
768                       ((target_long)a->i << TARGET_PAGE_BITS));
769      return true;
770  }
771  
trans_l_addi(DisasContext * dc,arg_rri * a)772  static bool trans_l_addi(DisasContext *dc, arg_rri *a)
773  {
774      check_r0_write(dc, a->d);
775      gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
776      return true;
777  }
778  
trans_l_addic(DisasContext * dc,arg_rri * a)779  static bool trans_l_addic(DisasContext *dc, arg_rri *a)
780  {
781      check_r0_write(dc, a->d);
782      gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
783      return true;
784  }
785  
trans_l_muli(DisasContext * dc,arg_rri * a)786  static bool trans_l_muli(DisasContext *dc, arg_rri *a)
787  {
788      check_r0_write(dc, a->d);
789      gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
790      return true;
791  }
792  
trans_l_maci(DisasContext * dc,arg_l_maci * a)793  static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
794  {
795      gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i));
796      return true;
797  }
798  
trans_l_andi(DisasContext * dc,arg_rrk * a)799  static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
800  {
801      check_r0_write(dc, a->d);
802      tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
803      return true;
804  }
805  
trans_l_ori(DisasContext * dc,arg_rrk * a)806  static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
807  {
808      check_r0_write(dc, a->d);
809      tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
810      return true;
811  }
812  
trans_l_xori(DisasContext * dc,arg_rri * a)813  static bool trans_l_xori(DisasContext *dc, arg_rri *a)
814  {
815      check_r0_write(dc, a->d);
816      tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
817      return true;
818  }
819  
trans_l_mfspr(DisasContext * dc,arg_l_mfspr * a)820  static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
821  {
822      TCGv spr = tcg_temp_new();
823  
824      check_r0_write(dc, a->d);
825  
826      if (translator_io_start(&dc->base)) {
827          if (dc->delayed_branch) {
828              tcg_gen_mov_tl(cpu_pc, jmp_pc);
829              tcg_gen_discard_tl(jmp_pc);
830          } else {
831              tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
832          }
833          dc->base.is_jmp = DISAS_EXIT;
834      }
835  
836      tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
837      gen_helper_mfspr(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d), spr);
838      return true;
839  }
840  
trans_l_mtspr(DisasContext * dc,arg_l_mtspr * a)841  static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
842  {
843      TCGv spr = tcg_temp_new();
844  
845      translator_io_start(&dc->base);
846  
847      /*
848       * For SR, we will need to exit the TB to recognize the new
849       * exception state.  For NPC, in theory this counts as a branch
850       * (although the SPR only exists for use by an ICE).  Save all
851       * of the cpu state first, allowing it to be overwritten.
852       */
853      if (dc->delayed_branch) {
854          tcg_gen_mov_tl(cpu_pc, jmp_pc);
855          tcg_gen_discard_tl(jmp_pc);
856      } else {
857          tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
858      }
859      dc->base.is_jmp = DISAS_EXIT;
860  
861      tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
862      gen_helper_mtspr(tcg_env, spr, cpu_R(dc, a->b));
863      return true;
864  }
865  
trans_l_mac(DisasContext * dc,arg_ab * a)866  static bool trans_l_mac(DisasContext *dc, arg_ab *a)
867  {
868      gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
869      return true;
870  }
871  
trans_l_msb(DisasContext * dc,arg_ab * a)872  static bool trans_l_msb(DisasContext *dc, arg_ab *a)
873  {
874      gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
875      return true;
876  }
877  
trans_l_macu(DisasContext * dc,arg_ab * a)878  static bool trans_l_macu(DisasContext *dc, arg_ab *a)
879  {
880      gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
881      return true;
882  }
883  
trans_l_msbu(DisasContext * dc,arg_ab * a)884  static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
885  {
886      gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
887      return true;
888  }
889  
trans_l_slli(DisasContext * dc,arg_dal * a)890  static bool trans_l_slli(DisasContext *dc, arg_dal *a)
891  {
892      check_r0_write(dc, a->d);
893      tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
894                      a->l & (TARGET_LONG_BITS - 1));
895      return true;
896  }
897  
trans_l_srli(DisasContext * dc,arg_dal * a)898  static bool trans_l_srli(DisasContext *dc, arg_dal *a)
899  {
900      check_r0_write(dc, a->d);
901      tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
902                      a->l & (TARGET_LONG_BITS - 1));
903      return true;
904  }
905  
trans_l_srai(DisasContext * dc,arg_dal * a)906  static bool trans_l_srai(DisasContext *dc, arg_dal *a)
907  {
908      check_r0_write(dc, a->d);
909      tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
910                      a->l & (TARGET_LONG_BITS - 1));
911      return true;
912  }
913  
trans_l_rori(DisasContext * dc,arg_dal * a)914  static bool trans_l_rori(DisasContext *dc, arg_dal *a)
915  {
916      check_r0_write(dc, a->d);
917      tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
918                       a->l & (TARGET_LONG_BITS - 1));
919      return true;
920  }
921  
trans_l_movhi(DisasContext * dc,arg_l_movhi * a)922  static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
923  {
924      check_r0_write(dc, a->d);
925      tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
926      return true;
927  }
928  
trans_l_macrc(DisasContext * dc,arg_l_macrc * a)929  static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
930  {
931      check_r0_write(dc, a->d);
932      tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
933      tcg_gen_movi_i64(cpu_mac, 0);
934      return true;
935  }
936  
trans_l_sfeq(DisasContext * dc,arg_ab * a)937  static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
938  {
939      tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
940                         cpu_R(dc, a->a), cpu_R(dc, a->b));
941      return true;
942  }
943  
trans_l_sfne(DisasContext * dc,arg_ab * a)944  static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
945  {
946      tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
947                         cpu_R(dc, a->a), cpu_R(dc, a->b));
948      return true;
949  }
950  
trans_l_sfgtu(DisasContext * dc,arg_ab * a)951  static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
952  {
953      tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
954                         cpu_R(dc, a->a), cpu_R(dc, a->b));
955      return true;
956  }
957  
trans_l_sfgeu(DisasContext * dc,arg_ab * a)958  static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
959  {
960      tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
961                         cpu_R(dc, a->a), cpu_R(dc, a->b));
962      return true;
963  }
964  
trans_l_sfltu(DisasContext * dc,arg_ab * a)965  static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
966  {
967      tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
968                         cpu_R(dc, a->a), cpu_R(dc, a->b));
969      return true;
970  }
971  
trans_l_sfleu(DisasContext * dc,arg_ab * a)972  static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
973  {
974      tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
975                         cpu_R(dc, a->a), cpu_R(dc, a->b));
976      return true;
977  }
978  
trans_l_sfgts(DisasContext * dc,arg_ab * a)979  static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
980  {
981      tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
982                         cpu_R(dc, a->a), cpu_R(dc, a->b));
983      return true;
984  }
985  
trans_l_sfges(DisasContext * dc,arg_ab * a)986  static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
987  {
988      tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
989                         cpu_R(dc, a->a), cpu_R(dc, a->b));
990      return true;
991  }
992  
trans_l_sflts(DisasContext * dc,arg_ab * a)993  static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
994  {
995      tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
996                         cpu_R(dc, a->a), cpu_R(dc, a->b));
997      return true;
998  }
999  
trans_l_sfles(DisasContext * dc,arg_ab * a)1000  static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1001  {
1002      tcg_gen_setcond_tl(TCG_COND_LE,
1003                         cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1004      return true;
1005  }
1006  
trans_l_sfeqi(DisasContext * dc,arg_ai * a)1007  static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1008  {
1009      tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1010      return true;
1011  }
1012  
trans_l_sfnei(DisasContext * dc,arg_ai * a)1013  static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1014  {
1015      tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1016      return true;
1017  }
1018  
trans_l_sfgtui(DisasContext * dc,arg_ai * a)1019  static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1020  {
1021      tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1022      return true;
1023  }
1024  
trans_l_sfgeui(DisasContext * dc,arg_ai * a)1025  static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1026  {
1027      tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1028      return true;
1029  }
1030  
trans_l_sfltui(DisasContext * dc,arg_ai * a)1031  static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1032  {
1033      tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1034      return true;
1035  }
1036  
trans_l_sfleui(DisasContext * dc,arg_ai * a)1037  static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1038  {
1039      tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1040      return true;
1041  }
1042  
trans_l_sfgtsi(DisasContext * dc,arg_ai * a)1043  static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1044  {
1045      tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1046      return true;
1047  }
1048  
trans_l_sfgesi(DisasContext * dc,arg_ai * a)1049  static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1050  {
1051      tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1052      return true;
1053  }
1054  
trans_l_sfltsi(DisasContext * dc,arg_ai * a)1055  static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1056  {
1057      tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1058      return true;
1059  }
1060  
trans_l_sflesi(DisasContext * dc,arg_ai * a)1061  static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1062  {
1063      tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1064      return true;
1065  }
1066  
trans_l_sys(DisasContext * dc,arg_l_sys * a)1067  static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1068  {
1069      tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1070      gen_exception(dc, EXCP_SYSCALL);
1071      dc->base.is_jmp = DISAS_NORETURN;
1072      return true;
1073  }
1074  
trans_l_trap(DisasContext * dc,arg_l_trap * a)1075  static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
1076  {
1077      tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1078      gen_exception(dc, EXCP_TRAP);
1079      dc->base.is_jmp = DISAS_NORETURN;
1080      return true;
1081  }
1082  
trans_l_msync(DisasContext * dc,arg_l_msync * a)1083  static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
1084  {
1085      tcg_gen_mb(TCG_MO_ALL);
1086      return true;
1087  }
1088  
trans_l_psync(DisasContext * dc,arg_l_psync * a)1089  static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
1090  {
1091      return true;
1092  }
1093  
trans_l_csync(DisasContext * dc,arg_l_csync * a)1094  static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
1095  {
1096      return true;
1097  }
1098  
trans_l_rfe(DisasContext * dc,arg_l_rfe * a)1099  static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
1100  {
1101      if (is_user(dc)) {
1102          gen_illegal_exception(dc);
1103      } else {
1104          gen_helper_rfe(tcg_env);
1105          dc->base.is_jmp = DISAS_EXIT;
1106      }
1107      return true;
1108  }
1109  
do_fp2(DisasContext * dc,arg_da * a,void (* fn)(TCGv,TCGv_env,TCGv))1110  static bool do_fp2(DisasContext *dc, arg_da *a,
1111                     void (*fn)(TCGv, TCGv_env, TCGv))
1112  {
1113      if (!check_of32s(dc)) {
1114          return false;
1115      }
1116      check_r0_write(dc, a->d);
1117      fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a));
1118      gen_helper_update_fpcsr(tcg_env);
1119      return true;
1120  }
1121  
do_fp3(DisasContext * dc,arg_dab * a,void (* fn)(TCGv,TCGv_env,TCGv,TCGv))1122  static bool do_fp3(DisasContext *dc, arg_dab *a,
1123                     void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
1124  {
1125      if (!check_of32s(dc)) {
1126          return false;
1127      }
1128      check_r0_write(dc, a->d);
1129      fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
1130      gen_helper_update_fpcsr(tcg_env);
1131      return true;
1132  }
1133  
do_fpcmp(DisasContext * dc,arg_ab * a,void (* fn)(TCGv,TCGv_env,TCGv,TCGv),bool inv,bool swap)1134  static bool do_fpcmp(DisasContext *dc, arg_ab *a,
1135                       void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
1136                       bool inv, bool swap)
1137  {
1138      if (!check_of32s(dc)) {
1139          return false;
1140      }
1141      if (swap) {
1142          fn(cpu_sr_f, tcg_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
1143      } else {
1144          fn(cpu_sr_f, tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
1145      }
1146      if (inv) {
1147          tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
1148      }
1149      gen_helper_update_fpcsr(tcg_env);
1150      return true;
1151  }
1152  
trans_lf_add_s(DisasContext * dc,arg_dab * a)1153  static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
1154  {
1155      return do_fp3(dc, a, gen_helper_float_add_s);
1156  }
1157  
trans_lf_sub_s(DisasContext * dc,arg_dab * a)1158  static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
1159  {
1160      return do_fp3(dc, a, gen_helper_float_sub_s);
1161  }
1162  
trans_lf_mul_s(DisasContext * dc,arg_dab * a)1163  static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
1164  {
1165      return do_fp3(dc, a, gen_helper_float_mul_s);
1166  }
1167  
trans_lf_div_s(DisasContext * dc,arg_dab * a)1168  static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
1169  {
1170      return do_fp3(dc, a, gen_helper_float_div_s);
1171  }
1172  
trans_lf_rem_s(DisasContext * dc,arg_dab * a)1173  static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
1174  {
1175      return do_fp3(dc, a, gen_helper_float_rem_s);
1176      return true;
1177  }
1178  
trans_lf_itof_s(DisasContext * dc,arg_da * a)1179  static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
1180  {
1181      return do_fp2(dc, a, gen_helper_itofs);
1182  }
1183  
trans_lf_ftoi_s(DisasContext * dc,arg_da * a)1184  static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
1185  {
1186      return do_fp2(dc, a, gen_helper_ftois);
1187  }
1188  
trans_lf_madd_s(DisasContext * dc,arg_dab * a)1189  static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
1190  {
1191      if (!check_of32s(dc)) {
1192          return false;
1193      }
1194      check_r0_write(dc, a->d);
1195      gen_helper_float_madd_s(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d),
1196                              cpu_R(dc, a->a), cpu_R(dc, a->b));
1197      gen_helper_update_fpcsr(tcg_env);
1198      return true;
1199  }
1200  
trans_lf_sfeq_s(DisasContext * dc,arg_ab * a)1201  static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
1202  {
1203      return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
1204  }
1205  
trans_lf_sfne_s(DisasContext * dc,arg_ab * a)1206  static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
1207  {
1208      return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
1209  }
1210  
trans_lf_sfgt_s(DisasContext * dc,arg_ab * a)1211  static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
1212  {
1213      return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
1214  }
1215  
trans_lf_sfge_s(DisasContext * dc,arg_ab * a)1216  static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
1217  {
1218      return do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
1219  }
1220  
trans_lf_sflt_s(DisasContext * dc,arg_ab * a)1221  static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
1222  {
1223      return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
1224  }
1225  
trans_lf_sfle_s(DisasContext * dc,arg_ab * a)1226  static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
1227  {
1228      return do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1229  }
1230  
trans_lf_sfueq_s(DisasContext * dc,arg_ab * a)1231  static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a)
1232  {
1233      if (!check_v1_3(dc)) {
1234          return false;
1235      }
1236      return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false);
1237  }
1238  
trans_lf_sfult_s(DisasContext * dc,arg_ab * a)1239  static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a)
1240  {
1241      if (!check_v1_3(dc)) {
1242          return false;
1243      }
1244      return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false);
1245  }
1246  
trans_lf_sfugt_s(DisasContext * dc,arg_ab * a)1247  static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a)
1248  {
1249      if (!check_v1_3(dc)) {
1250          return false;
1251      }
1252      return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true);
1253  }
1254  
trans_lf_sfule_s(DisasContext * dc,arg_ab * a)1255  static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a)
1256  {
1257      if (!check_v1_3(dc)) {
1258          return false;
1259      }
1260      return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false);
1261  }
1262  
trans_lf_sfuge_s(DisasContext * dc,arg_ab * a)1263  static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a)
1264  {
1265      if (!check_v1_3(dc)) {
1266          return false;
1267      }
1268      return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true);
1269  }
1270  
trans_lf_sfun_s(DisasContext * dc,arg_ab * a)1271  static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a)
1272  {
1273      if (!check_v1_3(dc)) {
1274          return false;
1275      }
1276      return do_fpcmp(dc, a, gen_helper_float_un_s, false, false);
1277  }
1278  
check_pair(DisasContext * dc,int r,int p)1279  static bool check_pair(DisasContext *dc, int r, int p)
1280  {
1281      return r + 1 + p < 32;
1282  }
1283  
load_pair(DisasContext * dc,TCGv_i64 t,int r,int p)1284  static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
1285  {
1286      tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r));
1287  }
1288  
save_pair(DisasContext * dc,TCGv_i64 t,int r,int p)1289  static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
1290  {
1291      tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t);
1292  }
1293  
do_dp3(DisasContext * dc,arg_dab_pair * a,void (* fn)(TCGv_i64,TCGv_env,TCGv_i64,TCGv_i64))1294  static bool do_dp3(DisasContext *dc, arg_dab_pair *a,
1295                     void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1296  {
1297      TCGv_i64 t0, t1;
1298  
1299      if (!check_of64a32s(dc) ||
1300          !check_pair(dc, a->a, a->ap) ||
1301          !check_pair(dc, a->b, a->bp) ||
1302          !check_pair(dc, a->d, a->dp)) {
1303          return false;
1304      }
1305      check_r0_write(dc, a->d);
1306  
1307      t0 = tcg_temp_new_i64();
1308      t1 = tcg_temp_new_i64();
1309      load_pair(dc, t0, a->a, a->ap);
1310      load_pair(dc, t1, a->b, a->bp);
1311      fn(t0, tcg_env, t0, t1);
1312      save_pair(dc, t0, a->d, a->dp);
1313  
1314      gen_helper_update_fpcsr(tcg_env);
1315      return true;
1316  }
1317  
do_dp2(DisasContext * dc,arg_da_pair * a,void (* fn)(TCGv_i64,TCGv_env,TCGv_i64))1318  static bool do_dp2(DisasContext *dc, arg_da_pair *a,
1319                     void (*fn)(TCGv_i64, TCGv_env, TCGv_i64))
1320  {
1321      TCGv_i64 t0;
1322  
1323      if (!check_of64a32s(dc) ||
1324          !check_pair(dc, a->a, a->ap) ||
1325          !check_pair(dc, a->d, a->dp)) {
1326          return false;
1327      }
1328      check_r0_write(dc, a->d);
1329  
1330      t0 = tcg_temp_new_i64();
1331      load_pair(dc, t0, a->a, a->ap);
1332      fn(t0, tcg_env, t0);
1333      save_pair(dc, t0, a->d, a->dp);
1334  
1335      gen_helper_update_fpcsr(tcg_env);
1336      return true;
1337  }
1338  
do_dpcmp(DisasContext * dc,arg_ab_pair * a,void (* fn)(TCGv,TCGv_env,TCGv_i64,TCGv_i64),bool inv,bool swap)1339  static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a,
1340                       void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64),
1341                       bool inv, bool swap)
1342  {
1343      TCGv_i64 t0, t1;
1344  
1345      if (!check_of64a32s(dc) ||
1346          !check_pair(dc, a->a, a->ap) ||
1347          !check_pair(dc, a->b, a->bp)) {
1348          return false;
1349      }
1350  
1351      t0 = tcg_temp_new_i64();
1352      t1 = tcg_temp_new_i64();
1353      load_pair(dc, t0, a->a, a->ap);
1354      load_pair(dc, t1, a->b, a->bp);
1355      if (swap) {
1356          fn(cpu_sr_f, tcg_env, t1, t0);
1357      } else {
1358          fn(cpu_sr_f, tcg_env, t0, t1);
1359      }
1360  
1361      if (inv) {
1362          tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
1363      }
1364      gen_helper_update_fpcsr(tcg_env);
1365      return true;
1366  }
1367  
trans_lf_add_d(DisasContext * dc,arg_dab_pair * a)1368  static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a)
1369  {
1370      return do_dp3(dc, a, gen_helper_float_add_d);
1371  }
1372  
trans_lf_sub_d(DisasContext * dc,arg_dab_pair * a)1373  static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a)
1374  {
1375      return do_dp3(dc, a, gen_helper_float_sub_d);
1376  }
1377  
trans_lf_mul_d(DisasContext * dc,arg_dab_pair * a)1378  static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a)
1379  {
1380      return do_dp3(dc, a, gen_helper_float_mul_d);
1381  }
1382  
trans_lf_div_d(DisasContext * dc,arg_dab_pair * a)1383  static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a)
1384  {
1385      return do_dp3(dc, a, gen_helper_float_div_d);
1386  }
1387  
trans_lf_rem_d(DisasContext * dc,arg_dab_pair * a)1388  static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a)
1389  {
1390      return do_dp3(dc, a, gen_helper_float_rem_d);
1391  }
1392  
trans_lf_itof_d(DisasContext * dc,arg_da_pair * a)1393  static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a)
1394  {
1395      return do_dp2(dc, a, gen_helper_itofd);
1396  }
1397  
trans_lf_ftoi_d(DisasContext * dc,arg_da_pair * a)1398  static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a)
1399  {
1400      return do_dp2(dc, a, gen_helper_ftoid);
1401  }
1402  
trans_lf_stod_d(DisasContext * dc,arg_lf_stod_d * a)1403  static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a)
1404  {
1405      TCGv_i64 t0;
1406  
1407      if (!check_of64a32s(dc) ||
1408          !check_pair(dc, a->d, a->dp)) {
1409          return false;
1410      }
1411      check_r0_write(dc, a->d);
1412  
1413      t0 = tcg_temp_new_i64();
1414      gen_helper_stod(t0, tcg_env, cpu_R(dc, a->a));
1415      save_pair(dc, t0, a->d, a->dp);
1416  
1417      gen_helper_update_fpcsr(tcg_env);
1418      return true;
1419  }
1420  
trans_lf_dtos_d(DisasContext * dc,arg_lf_dtos_d * a)1421  static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a)
1422  {
1423      TCGv_i64 t0;
1424  
1425      if (!check_of64a32s(dc) ||
1426          !check_pair(dc, a->a, a->ap)) {
1427          return false;
1428      }
1429      check_r0_write(dc, a->d);
1430  
1431      t0 = tcg_temp_new_i64();
1432      load_pair(dc, t0, a->a, a->ap);
1433      gen_helper_dtos(cpu_R(dc, a->d), tcg_env, t0);
1434  
1435      gen_helper_update_fpcsr(tcg_env);
1436      return true;
1437  }
1438  
trans_lf_madd_d(DisasContext * dc,arg_dab_pair * a)1439  static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a)
1440  {
1441      TCGv_i64 t0, t1, t2;
1442  
1443      if (!check_of64a32s(dc) ||
1444          !check_pair(dc, a->a, a->ap) ||
1445          !check_pair(dc, a->b, a->bp) ||
1446          !check_pair(dc, a->d, a->dp)) {
1447          return false;
1448      }
1449      check_r0_write(dc, a->d);
1450  
1451      t0 = tcg_temp_new_i64();
1452      t1 = tcg_temp_new_i64();
1453      t2 = tcg_temp_new_i64();
1454      load_pair(dc, t0, a->d, a->dp);
1455      load_pair(dc, t1, a->a, a->ap);
1456      load_pair(dc, t2, a->b, a->bp);
1457      gen_helper_float_madd_d(t0, tcg_env, t0, t1, t2);
1458      save_pair(dc, t0, a->d, a->dp);
1459  
1460      gen_helper_update_fpcsr(tcg_env);
1461      return true;
1462  }
1463  
trans_lf_sfeq_d(DisasContext * dc,arg_ab_pair * a)1464  static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a)
1465  {
1466      return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false);
1467  }
1468  
trans_lf_sfne_d(DisasContext * dc,arg_ab_pair * a)1469  static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a)
1470  {
1471      return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false);
1472  }
1473  
trans_lf_sfgt_d(DisasContext * dc,arg_ab_pair * a)1474  static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a)
1475  {
1476      return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true);
1477  }
1478  
trans_lf_sfge_d(DisasContext * dc,arg_ab_pair * a)1479  static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a)
1480  {
1481      return do_dpcmp(dc, a, gen_helper_float_le_d, false, true);
1482  }
1483  
trans_lf_sflt_d(DisasContext * dc,arg_ab_pair * a)1484  static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a)
1485  {
1486      return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false);
1487  }
1488  
trans_lf_sfle_d(DisasContext * dc,arg_ab_pair * a)1489  static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a)
1490  {
1491      return do_dpcmp(dc, a, gen_helper_float_le_d, false, false);
1492  }
1493  
trans_lf_sfueq_d(DisasContext * dc,arg_ab_pair * a)1494  static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a)
1495  {
1496      return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false);
1497  }
1498  
trans_lf_sfule_d(DisasContext * dc,arg_ab_pair * a)1499  static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a)
1500  {
1501      return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false);
1502  }
1503  
trans_lf_sfuge_d(DisasContext * dc,arg_ab_pair * a)1504  static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a)
1505  {
1506      return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true);
1507  }
1508  
trans_lf_sfult_d(DisasContext * dc,arg_ab_pair * a)1509  static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a)
1510  {
1511      return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false);
1512  }
1513  
trans_lf_sfugt_d(DisasContext * dc,arg_ab_pair * a)1514  static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a)
1515  {
1516      return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true);
1517  }
1518  
trans_lf_sfun_d(DisasContext * dc,arg_ab_pair * a)1519  static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a)
1520  {
1521      return do_dpcmp(dc, a, gen_helper_float_un_d, false, false);
1522  }
1523  
openrisc_tr_init_disas_context(DisasContextBase * dcb,CPUState * cs)1524  static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1525  {
1526      DisasContext *dc = container_of(dcb, DisasContext, base);
1527      CPUOpenRISCState *env = cpu_env(cs);
1528      int bound;
1529  
1530      dc->mem_idx = cpu_mmu_index(cs, false);
1531      dc->tb_flags = dc->base.tb->flags;
1532      dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1533      dc->cpucfgr = env->cpucfgr;
1534      dc->avr = env->avr;
1535      dc->jmp_pc_imm = -1;
1536  
1537      bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1538      dc->base.max_insns = MIN(dc->base.max_insns, bound);
1539  }
1540  
openrisc_tr_tb_start(DisasContextBase * db,CPUState * cs)1541  static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1542  {
1543      DisasContext *dc = container_of(db, DisasContext, base);
1544  
1545      /* Allow the TCG optimizer to see that R0 == 0,
1546         when it's true, which is the common case.  */
1547      dc->zero = tcg_constant_tl(0);
1548      if (dc->tb_flags & TB_FLAGS_R0_0) {
1549          dc->R0 = dc->zero;
1550      } else {
1551          dc->R0 = cpu_regs[0];
1552      }
1553  }
1554  
openrisc_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)1555  static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1556  {
1557      DisasContext *dc = container_of(dcbase, DisasContext, base);
1558  
1559      tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1560                         | (dc->base.num_insns > 1 ? 2 : 0));
1561  }
1562  
openrisc_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)1563  static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1564  {
1565      DisasContext *dc = container_of(dcbase, DisasContext, base);
1566      uint32_t insn = translator_ldl(cpu_env(cs), &dc->base, dc->base.pc_next);
1567  
1568      if (!decode(dc, insn)) {
1569          gen_illegal_exception(dc);
1570      }
1571      dc->base.pc_next += 4;
1572  
1573      /* When exiting the delay slot normally, exit via jmp_pc.
1574       * For DISAS_NORETURN, we have raised an exception and already exited.
1575       * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
1576       * in the manual saying this is illegal, but it surely it should.
1577       * At least or1ksim overrides pcnext and ignores the branch.
1578       */
1579      if (dc->delayed_branch
1580          && --dc->delayed_branch == 0
1581          && dc->base.is_jmp == DISAS_NEXT) {
1582          dc->base.is_jmp = DISAS_JUMP;
1583      }
1584  }
1585  
openrisc_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)1586  static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1587  {
1588      DisasContext *dc = container_of(dcbase, DisasContext, base);
1589      target_ulong jmp_dest;
1590  
1591      /* If we have already exited the TB, nothing following has effect.  */
1592      if (dc->base.is_jmp == DISAS_NORETURN) {
1593          return;
1594      }
1595  
1596      /* Adjust the delayed branch state for the next TB.  */
1597      if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1598          tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1599      }
1600  
1601      /* For DISAS_TOO_MANY, jump to the next insn.  */
1602      jmp_dest = dc->base.pc_next;
1603      tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
1604  
1605      switch (dc->base.is_jmp) {
1606      case DISAS_JUMP:
1607          jmp_dest = dc->jmp_pc_imm;
1608          if (jmp_dest == -1) {
1609              /* The jump destination is indirect/computed; use jmp_pc.  */
1610              tcg_gen_mov_tl(cpu_pc, jmp_pc);
1611              tcg_gen_discard_tl(jmp_pc);
1612              tcg_gen_lookup_and_goto_ptr();
1613              break;
1614          }
1615          /* The jump destination is direct; use jmp_pc_imm.
1616             However, we will have stored into jmp_pc as well;
1617             we know now that it wasn't needed.  */
1618          tcg_gen_discard_tl(jmp_pc);
1619          /* fallthru */
1620  
1621      case DISAS_TOO_MANY:
1622          if (translator_use_goto_tb(&dc->base, jmp_dest)) {
1623              tcg_gen_goto_tb(0);
1624              tcg_gen_movi_tl(cpu_pc, jmp_dest);
1625              tcg_gen_exit_tb(dc->base.tb, 0);
1626              break;
1627          }
1628          tcg_gen_movi_tl(cpu_pc, jmp_dest);
1629          tcg_gen_lookup_and_goto_ptr();
1630          break;
1631  
1632      case DISAS_EXIT:
1633          tcg_gen_exit_tb(NULL, 0);
1634          break;
1635      default:
1636          g_assert_not_reached();
1637      }
1638  }
1639  
1640  static const TranslatorOps openrisc_tr_ops = {
1641      .init_disas_context = openrisc_tr_init_disas_context,
1642      .tb_start           = openrisc_tr_tb_start,
1643      .insn_start         = openrisc_tr_insn_start,
1644      .translate_insn     = openrisc_tr_translate_insn,
1645      .tb_stop            = openrisc_tr_tb_stop,
1646  };
1647  
gen_intermediate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)1648  void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
1649                             vaddr pc, void *host_pc)
1650  {
1651      DisasContext ctx;
1652  
1653      translator_loop(cs, tb, max_insns, pc, host_pc,
1654                      &openrisc_tr_ops, &ctx.base);
1655  }
1656  
openrisc_cpu_dump_state(CPUState * cs,FILE * f,int flags)1657  void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1658  {
1659      CPUOpenRISCState *env = cpu_env(cs);
1660      int i;
1661  
1662      qemu_fprintf(f, "PC=%08x\n", env->pc);
1663      for (i = 0; i < 32; ++i) {
1664          qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1665                       (i % 4) == 3 ? '\n' : ' ');
1666      }
1667  }
1668