summaryrefslogtreecommitdiffstats
path: root/llvm/include/llvm-state.h
blob: e573073b065a46dd336c621aef9a43478e262a69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
 *  (C) 2010 by Computer System Laboratory, IIS, Academia Sinica, Taiwan.
 *      See COPYRIGHT in top-level directory.
 *
 *   This file implements the basic optimization schemes including indirect
 *   branch target cache (IBTC), indirect branch chain (IB chain), and trace
 *   profiling and prediction routines.
 */

#ifndef __LLVM_STATE_H
#define __LLVM_STATE_H

#define COPY_STATE(_dst, _src, _e) do { _dst->_e = _src->_e; } while(0)

/*
 * The following data structure and routine are used to save/restore the states
 * of CPUArchState. Only the states that could affect decoding the guest binary by
 * the TCG front-end are saved/restored. Such states are saved when translating
 * the block at the first time because the states could change later and are
 * restored to the saved values when the block is decoded again during the
 * trace formation.
 */
#if defined(TARGET_I386) || defined(TARGET_X86_64)
typedef struct i386_env {
    int singlestep_enabled;
    uint32_t hflags;
    target_ulong eflags;
} cpustate;
#elif defined(TARGET_ARM)
typedef struct arm_env {
    int singlestep_enabled;
    uint32_t pstate;
    uint32_t aarch64;
    struct {
        uint32_t c15_cpar;
        uint64_t scr_el3;
    } cp15;
    uint32_t uncached_cpsr;
    uint64_t features;
} cpustate;
#elif defined(TARGET_PPC) || defined(TARGET_PPC64)
typedef struct ppc_env {
    int singlestep_enabled;
    target_ulong msr;
    int mmu_idx;
    uint32_t flags;
    uint64_t insns_flags;
    uint64_t insns_flags2;
    target_ulong hflags;
} cpustate;
#elif defined(TARGET_SH4)
typedef struct sh4_env {
    int singlestep_enabled;
    uint32_t sr;	/* status register */
    uint32_t fpscr;	/* floating point status/control register */
    uint32_t features;
} cpustate;
#elif defined(TARGET_M68K)
typedef struct m68k_env {
    int singlestep_enabled;
    uint32_t sr;	/* status register */
    uint32_t fpcr;	/* floating point status/control register */
} cpustate;
#elif defined(TARGET_MIPS)
typedef struct mips_env {
    int singlestep_enabled;
    target_ulong btarget;
} cpustate;
#else
typedef struct dummy_env {
    int dummy;
} cpustate;
#endif

static inline void tcg_save_state(CPUArchState *env, TranslationBlock *tb)
{
#if defined(TARGET_I386) || defined(TARGET_X86_64)
    CPUState *cpu = ENV_GET_CPU(env);
    struct i386_env *s = new struct i386_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, hflags);
    COPY_STATE(s, env, eflags);
#elif defined(TARGET_ARM)
    CPUState *cpu = ENV_GET_CPU(env);
    struct arm_env *s = new struct arm_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, cp15.c15_cpar);
    COPY_STATE(s, env, cp15.scr_el3);
    COPY_STATE(s, env, uncached_cpsr);
    COPY_STATE(s, env, features);
    COPY_STATE(s, env, pstate);
    COPY_STATE(s, env, aarch64);
#elif defined(TARGET_PPC) || defined(TARGET_PPC64)
    CPUState *cpu = ENV_GET_CPU(env);
    struct ppc_env *s = new struct ppc_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, msr);
    COPY_STATE(s, env, mmu_idx);
    COPY_STATE(s, env, flags);
    COPY_STATE(s, env, insns_flags);
    COPY_STATE(s, env, insns_flags2);
    COPY_STATE(s, env, hflags);
#elif defined(TARGET_SH4)
    CPUState *cpu = ENV_GET_CPU(env);
    struct sh4_env *s = new struct sh4_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, sr);
    COPY_STATE(s, env, fpscr);
    COPY_STATE(s, env, features);
#elif defined(TARGET_M68K)
    CPUState *cpu = ENV_GET_CPU(env);
    struct m68k_env *s = new struct m68k_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, sr);
    COPY_STATE(s, env, fpcr);
#elif defined(TARGET_MIPS)
    CPUState *cpu = ENV_GET_CPU(env);
    struct mips_env *s = new struct mips_env;
    COPY_STATE(s, cpu, singlestep_enabled);
    COPY_STATE(s, env, btarget);
#else
    void *s = nullptr;
#endif

    tb->state = (void *)s;
}

/*
 * tcg_restore_state()
 *  Reset states to those when the block is first translated.
 */
static inline void tcg_copy_state(CPUArchState *env, TranslationBlock *tb)
{
#if defined(TARGET_I386) || defined(TARGET_X86_64)
    CPUState *cpu = ENV_GET_CPU(env);
    struct i386_env *i386e = (struct i386_env *)tb->state;
    COPY_STATE(cpu, i386e, singlestep_enabled);
    COPY_STATE(env, i386e, hflags);
    COPY_STATE(env, i386e, eflags);
#elif defined(TARGET_ARM)
    CPUState *cpu = ENV_GET_CPU(env);
    struct arm_env *arme = (struct arm_env *)tb->state;
    COPY_STATE(cpu, arme, singlestep_enabled);
    COPY_STATE(env, arme, cp15.c15_cpar);
    COPY_STATE(env, arme, cp15.scr_el3);
    COPY_STATE(env, arme, uncached_cpsr);
    COPY_STATE(env, arme, features);
    COPY_STATE(env, arme, pstate);
    COPY_STATE(env, arme, aarch64);
#elif defined(TARGET_PPC) || defined(TARGET_PPC64)
    CPUState *cpu = ENV_GET_CPU(env);
    struct ppc_env *ppce = (struct ppc_env *)tb->state;
    COPY_STATE(cpu, ppce, singlestep_enabled);
    COPY_STATE(env, ppce, msr);
    COPY_STATE(env, ppce, mmu_idx);
    COPY_STATE(env, ppce, flags);
    COPY_STATE(env, ppce, insns_flags);
    COPY_STATE(env, ppce, insns_flags2);
    COPY_STATE(env, ppce, hflags);
#elif defined(TARGET_SH4)
    CPUState *cpu = ENV_GET_CPU(env);
    struct sh4_env *sh4e = (struct sh4_env *)tb->state;
    COPY_STATE(cpu, sh4e, singlestep_enabled);
    COPY_STATE(env, sh4e, sr);
    COPY_STATE(env, sh4e, fpscr);
    COPY_STATE(env, sh4e, features);
#elif defined(TARGET_M68K)
    CPUState *cpu = ENV_GET_CPU(env);
    struct m68k_env *m68ke = (struct m68k_env *)tb->state;
    COPY_STATE(cpu, m68ke, singlestep_enabled);
    COPY_STATE(env, m68ke, sr);
    COPY_STATE(env, m68ke, fpcr);
#elif defined(TARGET_MIPS)
    CPUState *cpu = ENV_GET_CPU(env);
    struct mips_env *mipse = (struct mips_env *)tb->state;
    COPY_STATE(cpu, mipse, singlestep_enabled);
    COPY_STATE(env, mipse, btarget);
#endif
}

static inline void delete_state(TranslationBlock *tb)
{
    delete (cpustate *)tb->state;
    tb->state = nullptr;
}

#undef COPY_STATE
#endif  /* __LLVM_STATE_H */


/*
 * vim: ts=8 sts=4 sw=4 expandtab
 */

OpenPOWER on IntegriCloud