xref: /openbmc/qemu/target/ppc/internal.h (revision ffdd099a782556b9ead26551a6f1d070a595306d)
1  /*
2   *  PowerPC internal definitions for qemu.
3   *
4   * This library is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU Lesser General Public
6   * License as published by the Free Software Foundation; either
7   * version 2.1 of the License, or (at your option) any later version.
8   *
9   * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16   */
17  
18  #ifndef PPC_INTERNAL_H
19  #define PPC_INTERNAL_H
20  
21  #include "exec/breakpoint.h"
22  #include "hw/registerfields.h"
23  #include "exec/page-protection.h"
24  
25  /* PM instructions */
26  typedef enum {
27      PPC_PM_DOZE,
28      PPC_PM_NAP,
29      PPC_PM_SLEEP,
30      PPC_PM_RVWINKLE,
31      PPC_PM_STOP,
32  } powerpc_pm_insn_t;
33  
34  #define FUNC_MASK(name, ret_type, size, max_val)                  \
35  static inline ret_type name(uint##size##_t start,                 \
36                                uint##size##_t end)                 \
37  {                                                                 \
38      ret_type ret, max_bit = size - 1;                             \
39                                                                    \
40      if (likely(start == 0)) {                                     \
41          ret = max_val << (max_bit - end);                         \
42      } else if (likely(end == max_bit)) {                          \
43          ret = max_val >> start;                                   \
44      } else {                                                      \
45          ret = (((uint##size##_t)(-1ULL)) >> (start)) ^            \
46              (((uint##size##_t)(-1ULL) >> (end)) >> 1);            \
47          if (unlikely(start > end)) {                              \
48              return ~ret;                                          \
49          }                                                         \
50      }                                                             \
51                                                                    \
52      return ret;                                                   \
53  }
54  
55  #if defined(TARGET_PPC64)
56  FUNC_MASK(MASK, target_ulong, 64, UINT64_MAX);
57  #else
58  FUNC_MASK(MASK, target_ulong, 32, UINT32_MAX);
59  #endif
60  FUNC_MASK(mask_u32, uint32_t, 32, UINT32_MAX);
61  FUNC_MASK(mask_u64, uint64_t, 64, UINT64_MAX);
62  
63  /*****************************************************************************/
64  /***                           Instruction decoding                        ***/
65  #define EXTRACT_HELPER(name, shift, nb)                                       \
66  static inline uint32_t name(uint32_t opcode)                                  \
67  {                                                                             \
68      return extract32(opcode, shift, nb);                                      \
69  }
70  
71  #define EXTRACT_SHELPER(name, shift, nb)                                      \
72  static inline int32_t name(uint32_t opcode)                                   \
73  {                                                                             \
74      return sextract32(opcode, shift, nb);                                     \
75  }
76  
77  #define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2)                  \
78  static inline uint32_t name(uint32_t opcode)                                  \
79  {                                                                             \
80      return extract32(opcode, shift1, nb1) << nb2 |                            \
81                 extract32(opcode, shift2, nb2);                                \
82  }
83  
84  #define EXTRACT_HELPER_SPLIT_3(name,                                          \
85                                d0_bits, shift_op_d0, shift_d0,                 \
86                                d1_bits, shift_op_d1, shift_d1,                 \
87                                d2_bits, shift_op_d2, shift_d2)                 \
88  static inline int16_t name(uint32_t opcode)                                   \
89  {                                                                             \
90      return                                                                    \
91          (((opcode >> (shift_op_d0)) & ((1 << (d0_bits)) - 1)) << (shift_d0)) | \
92          (((opcode >> (shift_op_d1)) & ((1 << (d1_bits)) - 1)) << (shift_d1)) | \
93          (((opcode >> (shift_op_d2)) & ((1 << (d2_bits)) - 1)) << (shift_d2));  \
94  }
95  
96  
97  /* Opcode part 1 */
98  EXTRACT_HELPER(opc1, 26, 6);
99  /* Opcode part 2 */
100  EXTRACT_HELPER(opc2, 1, 5);
101  /* Opcode part 3 */
102  EXTRACT_HELPER(opc3, 6, 5);
103  /* Opcode part 4 */
104  EXTRACT_HELPER(opc4, 16, 5);
105  /* Update Cr0 flags */
106  EXTRACT_HELPER(Rc, 0, 1);
107  /* Update Cr6 flags (Altivec) */
108  EXTRACT_HELPER(Rc21, 10, 1);
109  /* Destination */
110  EXTRACT_HELPER(rD, 21, 5);
111  /* Source */
112  EXTRACT_HELPER(rS, 21, 5);
113  /* First operand */
114  EXTRACT_HELPER(rA, 16, 5);
115  /* Second operand */
116  EXTRACT_HELPER(rB, 11, 5);
117  /* Third operand */
118  EXTRACT_HELPER(rC, 6, 5);
119  /***                               Get CRn                                 ***/
120  EXTRACT_HELPER(crfD, 23, 3);
121  EXTRACT_HELPER(BF, 23, 3);
122  EXTRACT_HELPER(crfS, 18, 3);
123  EXTRACT_HELPER(crbD, 21, 5);
124  EXTRACT_HELPER(crbA, 16, 5);
125  EXTRACT_HELPER(crbB, 11, 5);
126  /* SPR / TBL */
127  EXTRACT_HELPER(_SPR, 11, 10);
SPR(uint32_t opcode)128  static inline uint32_t SPR(uint32_t opcode)
129  {
130      uint32_t sprn = _SPR(opcode);
131  
132      return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
133  }
134  /***                              Get constants                            ***/
135  /* 16 bits signed immediate value */
136  EXTRACT_SHELPER(SIMM, 0, 16);
137  /* 16 bits unsigned immediate value */
138  EXTRACT_HELPER(UIMM, 0, 16);
139  /* 5 bits signed immediate value */
140  EXTRACT_SHELPER(SIMM5, 16, 5);
141  /* 5 bits signed immediate value */
142  EXTRACT_HELPER(UIMM5, 16, 5);
143  /* 4 bits unsigned immediate value */
144  EXTRACT_HELPER(UIMM4, 16, 4);
145  /* Bit count */
146  EXTRACT_HELPER(NB, 11, 5);
147  /* Shift count */
148  EXTRACT_HELPER(SH, 11, 5);
149  /* lwat/stwat/ldat/lwat */
150  EXTRACT_HELPER(FC, 11, 5);
151  /* Vector shift count */
152  EXTRACT_HELPER(VSH, 6, 4);
153  /* Mask start */
154  EXTRACT_HELPER(MB, 6, 5);
155  /* Mask end */
156  EXTRACT_HELPER(ME, 1, 5);
157  /* Trap operand */
158  EXTRACT_HELPER(TO, 21, 5);
159  
160  EXTRACT_HELPER(CRM, 12, 8);
161  
162  #ifndef CONFIG_USER_ONLY
163  EXTRACT_HELPER(SR, 16, 4);
164  #endif
165  
166  /* mtfsf/mtfsfi */
167  EXTRACT_HELPER(FPBF, 23, 3);
168  EXTRACT_HELPER(FPIMM, 12, 4);
169  EXTRACT_HELPER(FPL, 25, 1);
170  EXTRACT_HELPER(FPFLM, 17, 8);
171  EXTRACT_HELPER(FPW, 16, 1);
172  
173  /* addpcis */
174  EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
175  #if defined(TARGET_PPC64)
176  /* darn */
177  EXTRACT_HELPER(L, 16, 2);
178  #endif
179  /* wait */
180  EXTRACT_HELPER(WC, 21, 2);
181  EXTRACT_HELPER(PL, 16, 2);
182  
183  /***                            Jump target decoding                       ***/
184  /* Immediate address */
LI(uint32_t opcode)185  static inline target_ulong LI(uint32_t opcode)
186  {
187      return (opcode >> 0) & 0x03FFFFFC;
188  }
189  
BD(uint32_t opcode)190  static inline uint32_t BD(uint32_t opcode)
191  {
192      return (opcode >> 0) & 0xFFFC;
193  }
194  
195  EXTRACT_HELPER(BO, 21, 5);
196  EXTRACT_HELPER(BI, 16, 5);
197  /* Absolute/relative address */
198  EXTRACT_HELPER(AA, 1, 1);
199  /* Link */
200  EXTRACT_HELPER(LK, 0, 1);
201  
202  /* DFP Z22-form */
203  EXTRACT_HELPER(DCM, 10, 6)
204  
205  /* DFP Z23-form */
206  EXTRACT_HELPER(RMC, 9, 2)
207  EXTRACT_HELPER(Rrm, 16, 1)
208  
209  EXTRACT_HELPER_SPLIT(DQxT, 3, 1, 21, 5);
210  EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
211  EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
212  EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
213  EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
214  EXTRACT_HELPER_SPLIT(xC, 3, 1,  6, 5);
215  EXTRACT_HELPER(DM, 8, 2);
216  EXTRACT_HELPER(UIM, 16, 2);
217  EXTRACT_HELPER(SHW, 8, 2);
218  EXTRACT_HELPER(SP, 19, 2);
219  EXTRACT_HELPER(IMM8, 11, 8);
220  EXTRACT_HELPER(DCMX, 16, 7);
221  EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6);
222  
223  void helper_compute_fprf_float16(CPUPPCState *env, float16 arg);
224  void helper_compute_fprf_float32(CPUPPCState *env, float32 arg);
225  void helper_compute_fprf_float128(CPUPPCState *env, float128 arg);
226  
227  /* translate.c */
228  
229  int ppc_fixup_cpu(PowerPCCPU *cpu);
230  void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp);
231  void destroy_ppc_opcodes(PowerPCCPU *cpu);
232  
233  /* gdbstub.c */
234  void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
235  const gchar *ppc_gdb_arch_name(CPUState *cs);
236  
237  #ifndef CONFIG_USER_ONLY
238  
239  /* Check if permission bit required for the access_type is set in prot */
check_prot_access_type(int prot,MMUAccessType access_type)240  static inline int check_prot_access_type(int prot, MMUAccessType access_type)
241  {
242      return prot & (1 << access_type);
243  }
244  
245  /* PowerPC MMU emulation */
246  
247  bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
248                        hwaddr *raddrp, int *psizep, int *protp,
249                        int mmu_idx, bool guest_visible);
250  
251  /* Software driven TLB helpers */
252  int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
253                                      int way, int is_code);
254  
255  #endif /* !CONFIG_USER_ONLY */
256  
257  /* Common routines used by software and hardware TLBs emulation */
pte_is_valid(target_ulong pte0)258  static inline int pte_is_valid(target_ulong pte0)
259  {
260      return pte0 & 0x80000000 ? 1 : 0;
261  }
262  
pte_invalidate(target_ulong * pte0)263  static inline void pte_invalidate(target_ulong *pte0)
264  {
265      *pte0 &= ~0x80000000;
266  }
267  
268  #define PTE_PTEM_MASK 0x7FFFFFBF
269  #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
270  
271  #ifdef CONFIG_USER_ONLY
272  void ppc_cpu_record_sigsegv(CPUState *cs, vaddr addr,
273                              MMUAccessType access_type,
274                              bool maperr, uintptr_t ra);
275  #else
276  bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
277                        MMUAccessType access_type, int mmu_idx,
278                        bool probe, uintptr_t retaddr);
279  G_NORETURN void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
280                                              MMUAccessType access_type, int mmu_idx,
281                                              uintptr_t retaddr);
282  void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
283                                     vaddr addr, unsigned size,
284                                     MMUAccessType access_type,
285                                     int mmu_idx, MemTxAttrs attrs,
286                                     MemTxResult response, uintptr_t retaddr);
287  void ppc_cpu_debug_excp_handler(CPUState *cs);
288  bool ppc_cpu_debug_check_breakpoint(CPUState *cs);
289  bool ppc_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
290  #endif
291  
292  FIELD(GER_MSK, XMSK, 0, 4)
293  FIELD(GER_MSK, YMSK, 4, 4)
294  FIELD(GER_MSK, PMSK, 8, 8)
295  
ger_pack_masks(int pmsk,int ymsk,int xmsk)296  static inline int ger_pack_masks(int pmsk, int ymsk, int xmsk)
297  {
298      int msk = 0;
299      msk = FIELD_DP32(msk, GER_MSK, XMSK, xmsk);
300      msk = FIELD_DP32(msk, GER_MSK, YMSK, ymsk);
301      msk = FIELD_DP32(msk, GER_MSK, PMSK, pmsk);
302      return msk;
303  }
304  
305  #endif /* PPC_INTERNAL_H */
306