xref: /qemu/target/arm/tcg/translate-a32.h (revision 81ae37dbb4a5c5b8eb54bc7f5e6c69097eacb9d2)
15ce389f2SPeter Maydell /*
25ce389f2SPeter Maydell  *  AArch32 translation, common definitions.
35ce389f2SPeter Maydell  *
45ce389f2SPeter Maydell  * Copyright (c) 2021 Linaro, Ltd.
55ce389f2SPeter Maydell  *
65ce389f2SPeter Maydell  * This library is free software; you can redistribute it and/or
75ce389f2SPeter Maydell  * modify it under the terms of the GNU Lesser General Public
85ce389f2SPeter Maydell  * License as published by the Free Software Foundation; either
95ce389f2SPeter Maydell  * version 2.1 of the License, or (at your option) any later version.
105ce389f2SPeter Maydell  *
115ce389f2SPeter Maydell  * This library is distributed in the hope that it will be useful,
125ce389f2SPeter Maydell  * but WITHOUT ANY WARRANTY; without even the implied warranty of
135ce389f2SPeter Maydell  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145ce389f2SPeter Maydell  * Lesser General Public License for more details.
155ce389f2SPeter Maydell  *
165ce389f2SPeter Maydell  * You should have received a copy of the GNU Lesser General Public
175ce389f2SPeter Maydell  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
185ce389f2SPeter Maydell  */
195ce389f2SPeter Maydell 
2052581c71SMarkus Armbruster #ifndef TARGET_ARM_TRANSLATE_A32_H
2152581c71SMarkus Armbruster #define TARGET_ARM_TRANSLATE_A32_H
225ce389f2SPeter Maydell 
239a5071abSPeter Maydell /* Prototypes for autogenerated disassembler functions */
249a5071abSPeter Maydell bool disas_m_nocp(DisasContext *dc, uint32_t insn);
256390eed4SPeter Maydell bool disas_mve(DisasContext *dc, uint32_t insn);
2645fbd5a9SPeter Maydell bool disas_vfp(DisasContext *s, uint32_t insn);
2745fbd5a9SPeter Maydell bool disas_vfp_uncond(DisasContext *s, uint32_t insn);
284800b852SPeter Maydell bool disas_neon_dp(DisasContext *s, uint32_t insn);
294800b852SPeter Maydell bool disas_neon_ls(DisasContext *s, uint32_t insn);
304800b852SPeter Maydell bool disas_neon_shared(DisasContext *s, uint32_t insn);
319a5071abSPeter Maydell 
325ce389f2SPeter Maydell void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
335ce389f2SPeter Maydell void arm_gen_condlabel(DisasContext *s);
345ce389f2SPeter Maydell bool vfp_access_check(DisasContext *s);
3588137f78SPeter Maydell bool vfp_access_check_m(DisasContext *s, bool skip_context_update);
365ce389f2SPeter Maydell void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
375ce389f2SPeter Maydell void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
385ce389f2SPeter Maydell void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
395ce389f2SPeter Maydell void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
404a800a73SPeter Maydell TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs);
414a800a73SPeter Maydell void gen_set_cpsr(TCGv_i32 var, uint32_t mask);
424a800a73SPeter Maydell void gen_set_condexec(DisasContext *s);
43c44c8b8bSRichard Henderson void gen_update_pc(DisasContext *s, target_long diff);
444a800a73SPeter Maydell void gen_lookup_tb(DisasContext *s);
454a800a73SPeter Maydell long vfp_reg_offset(bool dp, unsigned reg);
464a800a73SPeter Maydell long neon_full_reg_offset(unsigned reg);
47b5c8a457SPeter Maydell long neon_element_offset(int reg, int element, MemOp memop);
48b5c8a457SPeter Maydell void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
495138bd01SPeter Maydell void clear_eci_state(DisasContext *s);
504f57ef95SPeter Maydell bool mve_eci_check(DisasContext *s);
510f31e37cSPeter Maydell void mve_update_eci(DisasContext *s);
524f57ef95SPeter Maydell void mve_update_and_store_eci(DisasContext *s);
531241f148SPeter Maydell bool mve_skip_vmov(DisasContext *s, int vn, int index, int size);
545ce389f2SPeter Maydell 
load_cpu_offset(int offset)555ce389f2SPeter Maydell static inline TCGv_i32 load_cpu_offset(int offset)
565ce389f2SPeter Maydell {
575ce389f2SPeter Maydell     TCGv_i32 tmp = tcg_temp_new_i32();
58ad75a51eSRichard Henderson     tcg_gen_ld_i32(tmp, tcg_env, offset);
595ce389f2SPeter Maydell     return tmp;
605ce389f2SPeter Maydell }
615ce389f2SPeter Maydell 
622b67d0ffSPeter Maydell /* Load from a 32-bit field to a TCGv_i32 */
632b67d0ffSPeter Maydell #define load_cpu_field(name)                                            \
642b67d0ffSPeter Maydell     ({                                                                  \
652b67d0ffSPeter Maydell         QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 4);        \
662b67d0ffSPeter Maydell         load_cpu_offset(offsetof(CPUARMState, name));                   \
672b67d0ffSPeter Maydell     })
685ce389f2SPeter Maydell 
697f3a3d3dSPeter Maydell /* Load from the low half of a 64-bit field to a TCGv_i32 */
707f3a3d3dSPeter Maydell #define load_cpu_field_low32(name)                                      \
717f3a3d3dSPeter Maydell     ({                                                                  \
727f3a3d3dSPeter Maydell         QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 8);        \
737f3a3d3dSPeter Maydell         load_cpu_offset(offsetoflow32(CPUARMState, name));              \
747f3a3d3dSPeter Maydell     })
757f3a3d3dSPeter Maydell 
764f4c2a4bSRichard Henderson void store_cpu_offset(TCGv_i32 var, int offset, int size);
775ce389f2SPeter Maydell 
782b67d0ffSPeter Maydell #define store_cpu_field(val, name)                                      \
792b67d0ffSPeter Maydell     ({                                                                  \
802b67d0ffSPeter Maydell         QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 4          \
812b67d0ffSPeter Maydell                           && sizeof_field(CPUARMState, name) != 1);     \
822b67d0ffSPeter Maydell         store_cpu_offset(val, offsetof(CPUARMState, name),              \
832b67d0ffSPeter Maydell                          sizeof_field(CPUARMState, name));              \
842b67d0ffSPeter Maydell     })
855ce389f2SPeter Maydell 
86*81ae37dbSPeter Maydell /* Store to the low half of a 64-bit field from a TCGv_i32 */
87*81ae37dbSPeter Maydell #define store_cpu_field_low32(val, name)                                \
88*81ae37dbSPeter Maydell     ({                                                                  \
89*81ae37dbSPeter Maydell         QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, name) != 8);        \
90*81ae37dbSPeter Maydell         store_cpu_offset(val, offsetoflow32(CPUARMState, name), 4);     \
91*81ae37dbSPeter Maydell     })
92*81ae37dbSPeter Maydell 
93daf7a181SPhilippe Mathieu-Daudé #define store_cpu_field_constant(val, name) \
944f4c2a4bSRichard Henderson     store_cpu_field(tcg_constant_i32(val), name)
95daf7a181SPhilippe Mathieu-Daudé 
965ce389f2SPeter Maydell /* Create a new temporary and set it to the value of a CPU register.  */
load_reg(DisasContext * s,int reg)975ce389f2SPeter Maydell static inline TCGv_i32 load_reg(DisasContext *s, int reg)
985ce389f2SPeter Maydell {
995ce389f2SPeter Maydell     TCGv_i32 tmp = tcg_temp_new_i32();
1005ce389f2SPeter Maydell     load_reg_var(s, tmp, reg);
1015ce389f2SPeter Maydell     return tmp;
1025ce389f2SPeter Maydell }
1035ce389f2SPeter Maydell 
1044a800a73SPeter Maydell void store_reg(DisasContext *s, int reg, TCGv_i32 var);
1054a800a73SPeter Maydell 
10673d2f5d2SPeter Maydell void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
10773d2f5d2SPeter Maydell                               TCGv_i32 a32, int index, MemOp opc);
10873d2f5d2SPeter Maydell void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
10973d2f5d2SPeter Maydell                               TCGv_i32 a32, int index, MemOp opc);
11073d2f5d2SPeter Maydell void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
11173d2f5d2SPeter Maydell                               TCGv_i32 a32, int index, MemOp opc);
11273d2f5d2SPeter Maydell void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
11373d2f5d2SPeter Maydell                               TCGv_i32 a32, int index, MemOp opc);
11473d2f5d2SPeter Maydell void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
11573d2f5d2SPeter Maydell                      int index, MemOp opc);
11673d2f5d2SPeter Maydell void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
11773d2f5d2SPeter Maydell                      int index, MemOp opc);
11873d2f5d2SPeter Maydell void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
11973d2f5d2SPeter Maydell                      int index, MemOp opc);
12073d2f5d2SPeter Maydell void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
12173d2f5d2SPeter Maydell                      int index, MemOp opc);
12273d2f5d2SPeter Maydell 
12373d2f5d2SPeter Maydell #define DO_GEN_LD(SUFF, OPC)                                            \
12473d2f5d2SPeter Maydell     static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
12573d2f5d2SPeter Maydell                                          TCGv_i32 a32, int index)       \
12673d2f5d2SPeter Maydell     {                                                                   \
12773d2f5d2SPeter Maydell         gen_aa32_ld_i32(s, val, a32, index, OPC);                       \
12873d2f5d2SPeter Maydell     }
12973d2f5d2SPeter Maydell 
13073d2f5d2SPeter Maydell #define DO_GEN_ST(SUFF, OPC)                                            \
13173d2f5d2SPeter Maydell     static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
13273d2f5d2SPeter Maydell                                          TCGv_i32 a32, int index)       \
13373d2f5d2SPeter Maydell     {                                                                   \
13473d2f5d2SPeter Maydell         gen_aa32_st_i32(s, val, a32, index, OPC);                       \
13573d2f5d2SPeter Maydell     }
13673d2f5d2SPeter Maydell 
gen_aa32_ld64(DisasContext * s,TCGv_i64 val,TCGv_i32 a32,int index)13773d2f5d2SPeter Maydell static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
13873d2f5d2SPeter Maydell                                  TCGv_i32 a32, int index)
13973d2f5d2SPeter Maydell {
140fc313c64SFrédéric Pétrot     gen_aa32_ld_i64(s, val, a32, index, MO_UQ);
14173d2f5d2SPeter Maydell }
14273d2f5d2SPeter Maydell 
gen_aa32_st64(DisasContext * s,TCGv_i64 val,TCGv_i32 a32,int index)14373d2f5d2SPeter Maydell static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
14473d2f5d2SPeter Maydell                                  TCGv_i32 a32, int index)
14573d2f5d2SPeter Maydell {
146fc313c64SFrédéric Pétrot     gen_aa32_st_i64(s, val, a32, index, MO_UQ);
14773d2f5d2SPeter Maydell }
14873d2f5d2SPeter Maydell 
14973d2f5d2SPeter Maydell DO_GEN_LD(8u, MO_UB)
15073d2f5d2SPeter Maydell DO_GEN_LD(16u, MO_UW)
15173d2f5d2SPeter Maydell DO_GEN_LD(32u, MO_UL)
15273d2f5d2SPeter Maydell DO_GEN_ST(8, MO_UB)
15373d2f5d2SPeter Maydell DO_GEN_ST(16, MO_UW)
15473d2f5d2SPeter Maydell DO_GEN_ST(32, MO_UL)
15573d2f5d2SPeter Maydell 
15673d2f5d2SPeter Maydell #undef DO_GEN_LD
15773d2f5d2SPeter Maydell #undef DO_GEN_ST
15873d2f5d2SPeter Maydell 
1594a800a73SPeter Maydell #if defined(CONFIG_USER_ONLY)
1604a800a73SPeter Maydell #define IS_USER(s) 1
1614a800a73SPeter Maydell #else
1624a800a73SPeter Maydell #define IS_USER(s) (s->user)
1634a800a73SPeter Maydell #endif
1644a800a73SPeter Maydell 
1654a800a73SPeter Maydell /* Set NZCV flags from the high 4 bits of var.  */
1664a800a73SPeter Maydell #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
1674a800a73SPeter Maydell 
168b5c8a457SPeter Maydell /* Swap low and high halfwords.  */
gen_swap_half(TCGv_i32 dest,TCGv_i32 var)169b5c8a457SPeter Maydell static inline void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
170b5c8a457SPeter Maydell {
171b5c8a457SPeter Maydell     tcg_gen_rotri_i32(dest, var, 16);
172b5c8a457SPeter Maydell }
173b5c8a457SPeter Maydell 
1745ce389f2SPeter Maydell #endif
175