root / target-microblaze / translate.c @ 8cfd0495
History | View | Annotate | Download (58.5 kB)
1 | 4acb54ba | Edgar E. Iglesias | /*
|
---|---|---|---|
2 | 4acb54ba | Edgar E. Iglesias | * Xilinx MicroBlaze emulation for qemu: main translation routines.
|
3 | 4acb54ba | Edgar E. Iglesias | *
|
4 | 4acb54ba | Edgar E. Iglesias | * Copyright (c) 2009 Edgar E. Iglesias.
|
5 | dadc1064 | Peter A. G. Crosthwaite | * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
|
6 | 4acb54ba | Edgar E. Iglesias | *
|
7 | 4acb54ba | Edgar E. Iglesias | * This library is free software; you can redistribute it and/or
|
8 | 4acb54ba | Edgar E. Iglesias | * modify it under the terms of the GNU Lesser General Public
|
9 | 4acb54ba | Edgar E. Iglesias | * License as published by the Free Software Foundation; either
|
10 | 4acb54ba | Edgar E. Iglesias | * version 2 of the License, or (at your option) any later version.
|
11 | 4acb54ba | Edgar E. Iglesias | *
|
12 | 4acb54ba | Edgar E. Iglesias | * This library is distributed in the hope that it will be useful,
|
13 | 4acb54ba | Edgar E. Iglesias | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 4acb54ba | Edgar E. Iglesias | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | 4acb54ba | Edgar E. Iglesias | * Lesser General Public License for more details.
|
16 | 4acb54ba | Edgar E. Iglesias | *
|
17 | 4acb54ba | Edgar E. Iglesias | * You should have received a copy of the GNU Lesser General Public
|
18 | 8167ee88 | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
19 | 4acb54ba | Edgar E. Iglesias | */
|
20 | 4acb54ba | Edgar E. Iglesias | |
21 | 4acb54ba | Edgar E. Iglesias | #include "cpu.h" |
22 | 76cad711 | Paolo Bonzini | #include "disas/disas.h" |
23 | 4acb54ba | Edgar E. Iglesias | #include "tcg-op.h" |
24 | 4acb54ba | Edgar E. Iglesias | #include "helper.h" |
25 | 4acb54ba | Edgar E. Iglesias | #include "microblaze-decode.h" |
26 | 4acb54ba | Edgar E. Iglesias | |
27 | 4acb54ba | Edgar E. Iglesias | #define GEN_HELPER 1 |
28 | 4acb54ba | Edgar E. Iglesias | #include "helper.h" |
29 | 4acb54ba | Edgar E. Iglesias | |
30 | 4acb54ba | Edgar E. Iglesias | #define SIM_COMPAT 0 |
31 | 4acb54ba | Edgar E. Iglesias | #define DISAS_GNU 1 |
32 | 4acb54ba | Edgar E. Iglesias | #define DISAS_MB 1 |
33 | 4acb54ba | Edgar E. Iglesias | #if DISAS_MB && !SIM_COMPAT
|
34 | 4acb54ba | Edgar E. Iglesias | # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) |
35 | 4acb54ba | Edgar E. Iglesias | #else
|
36 | 4acb54ba | Edgar E. Iglesias | # define LOG_DIS(...) do { } while (0) |
37 | 4acb54ba | Edgar E. Iglesias | #endif
|
38 | 4acb54ba | Edgar E. Iglesias | |
39 | 4acb54ba | Edgar E. Iglesias | #define D(x)
|
40 | 4acb54ba | Edgar E. Iglesias | |
41 | 4acb54ba | Edgar E. Iglesias | #define EXTRACT_FIELD(src, start, end) \
|
42 | 4acb54ba | Edgar E. Iglesias | (((src) >> start) & ((1 << (end - start + 1)) - 1)) |
43 | 4acb54ba | Edgar E. Iglesias | |
44 | 4acb54ba | Edgar E. Iglesias | static TCGv env_debug;
|
45 | 4acb54ba | Edgar E. Iglesias | static TCGv_ptr cpu_env;
|
46 | 4acb54ba | Edgar E. Iglesias | static TCGv cpu_R[32]; |
47 | 4acb54ba | Edgar E. Iglesias | static TCGv cpu_SR[18]; |
48 | 4acb54ba | Edgar E. Iglesias | static TCGv env_imm;
|
49 | 4acb54ba | Edgar E. Iglesias | static TCGv env_btaken;
|
50 | 4acb54ba | Edgar E. Iglesias | static TCGv env_btarget;
|
51 | 4acb54ba | Edgar E. Iglesias | static TCGv env_iflags;
|
52 | 4acb54ba | Edgar E. Iglesias | |
53 | 022c62cb | Paolo Bonzini | #include "exec/gen-icount.h" |
54 | 4acb54ba | Edgar E. Iglesias | |
55 | 4acb54ba | Edgar E. Iglesias | /* This is the state at translation time. */
|
56 | 4acb54ba | Edgar E. Iglesias | typedef struct DisasContext { |
57 | 68cee38a | Andreas Färber | CPUMBState *env; |
58 | a5efa644 | Edgar E. Iglesias | target_ulong pc; |
59 | 4acb54ba | Edgar E. Iglesias | |
60 | 4acb54ba | Edgar E. Iglesias | /* Decoder. */
|
61 | 4acb54ba | Edgar E. Iglesias | int type_b;
|
62 | 4acb54ba | Edgar E. Iglesias | uint32_t ir; |
63 | 4acb54ba | Edgar E. Iglesias | uint8_t opcode; |
64 | 4acb54ba | Edgar E. Iglesias | uint8_t rd, ra, rb; |
65 | 4acb54ba | Edgar E. Iglesias | uint16_t imm; |
66 | 4acb54ba | Edgar E. Iglesias | |
67 | 4acb54ba | Edgar E. Iglesias | unsigned int cpustate_changed; |
68 | 4acb54ba | Edgar E. Iglesias | unsigned int delayed_branch; |
69 | 4acb54ba | Edgar E. Iglesias | unsigned int tb_flags, synced_flags; /* tb dependent flags. */ |
70 | 4acb54ba | Edgar E. Iglesias | unsigned int clear_imm; |
71 | 4acb54ba | Edgar E. Iglesias | int is_jmp;
|
72 | 4acb54ba | Edgar E. Iglesias | |
73 | 844bab60 | Edgar E. Iglesias | #define JMP_NOJMP 0 |
74 | 844bab60 | Edgar E. Iglesias | #define JMP_DIRECT 1 |
75 | 844bab60 | Edgar E. Iglesias | #define JMP_DIRECT_CC 2 |
76 | 844bab60 | Edgar E. Iglesias | #define JMP_INDIRECT 3 |
77 | 4acb54ba | Edgar E. Iglesias | unsigned int jmp; |
78 | 4acb54ba | Edgar E. Iglesias | uint32_t jmp_pc; |
79 | 4acb54ba | Edgar E. Iglesias | |
80 | 4acb54ba | Edgar E. Iglesias | int abort_at_next_insn;
|
81 | 4acb54ba | Edgar E. Iglesias | int nr_nops;
|
82 | 4acb54ba | Edgar E. Iglesias | struct TranslationBlock *tb;
|
83 | 4acb54ba | Edgar E. Iglesias | int singlestep_enabled;
|
84 | 4acb54ba | Edgar E. Iglesias | } DisasContext; |
85 | 4acb54ba | Edgar E. Iglesias | |
86 | 38972938 | Juan Quintela | static const char *regnames[] = |
87 | 4acb54ba | Edgar E. Iglesias | { |
88 | 4acb54ba | Edgar E. Iglesias | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
89 | 4acb54ba | Edgar E. Iglesias | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
90 | 4acb54ba | Edgar E. Iglesias | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
91 | 4acb54ba | Edgar E. Iglesias | "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", |
92 | 4acb54ba | Edgar E. Iglesias | }; |
93 | 4acb54ba | Edgar E. Iglesias | |
94 | 38972938 | Juan Quintela | static const char *special_regnames[] = |
95 | 4acb54ba | Edgar E. Iglesias | { |
96 | 4acb54ba | Edgar E. Iglesias | "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", |
97 | 4acb54ba | Edgar E. Iglesias | "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", |
98 | 4acb54ba | Edgar E. Iglesias | "sr16", "sr17", "sr18" |
99 | 4acb54ba | Edgar E. Iglesias | }; |
100 | 4acb54ba | Edgar E. Iglesias | |
101 | 4acb54ba | Edgar E. Iglesias | /* Sign extend at translation time. */
|
102 | 4acb54ba | Edgar E. Iglesias | static inline int sign_extend(unsigned int val, unsigned int width) |
103 | 4acb54ba | Edgar E. Iglesias | { |
104 | 4acb54ba | Edgar E. Iglesias | int sval;
|
105 | 4acb54ba | Edgar E. Iglesias | |
106 | 4acb54ba | Edgar E. Iglesias | /* LSL. */
|
107 | 4acb54ba | Edgar E. Iglesias | val <<= 31 - width;
|
108 | 4acb54ba | Edgar E. Iglesias | sval = val; |
109 | 4acb54ba | Edgar E. Iglesias | /* ASR. */
|
110 | 4acb54ba | Edgar E. Iglesias | sval >>= 31 - width;
|
111 | 4acb54ba | Edgar E. Iglesias | return sval;
|
112 | 4acb54ba | Edgar E. Iglesias | } |
113 | 4acb54ba | Edgar E. Iglesias | |
114 | 4acb54ba | Edgar E. Iglesias | static inline void t_sync_flags(DisasContext *dc) |
115 | 4acb54ba | Edgar E. Iglesias | { |
116 | 4abf79a4 | Dong Xu Wang | /* Synch the tb dependent flags between translator and runtime. */
|
117 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags != dc->synced_flags) {
|
118 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_iflags, dc->tb_flags); |
119 | 4acb54ba | Edgar E. Iglesias | dc->synced_flags = dc->tb_flags; |
120 | 4acb54ba | Edgar E. Iglesias | } |
121 | 4acb54ba | Edgar E. Iglesias | } |
122 | 4acb54ba | Edgar E. Iglesias | |
123 | 4acb54ba | Edgar E. Iglesias | static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) |
124 | 4acb54ba | Edgar E. Iglesias | { |
125 | 4acb54ba | Edgar E. Iglesias | TCGv_i32 tmp = tcg_const_i32(index); |
126 | 4acb54ba | Edgar E. Iglesias | |
127 | 4acb54ba | Edgar E. Iglesias | t_sync_flags(dc); |
128 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); |
129 | 64254eba | Blue Swirl | gen_helper_raise_exception(cpu_env, tmp); |
130 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free_i32(tmp); |
131 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_UPDATE; |
132 | 4acb54ba | Edgar E. Iglesias | } |
133 | 4acb54ba | Edgar E. Iglesias | |
134 | 4acb54ba | Edgar E. Iglesias | static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) |
135 | 4acb54ba | Edgar E. Iglesias | { |
136 | 4acb54ba | Edgar E. Iglesias | TranslationBlock *tb; |
137 | 4acb54ba | Edgar E. Iglesias | tb = dc->tb; |
138 | 4acb54ba | Edgar E. Iglesias | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
|
139 | 4acb54ba | Edgar E. Iglesias | tcg_gen_goto_tb(n); |
140 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dest); |
141 | 8cfd0495 | Richard Henderson | tcg_gen_exit_tb((uintptr_t)tb + n); |
142 | 4acb54ba | Edgar E. Iglesias | } else {
|
143 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dest); |
144 | 4acb54ba | Edgar E. Iglesias | tcg_gen_exit_tb(0);
|
145 | 4acb54ba | Edgar E. Iglesias | } |
146 | 4acb54ba | Edgar E. Iglesias | } |
147 | 4acb54ba | Edgar E. Iglesias | |
148 | ee8b246f | Edgar E. Iglesias | static void read_carry(DisasContext *dc, TCGv d) |
149 | ee8b246f | Edgar E. Iglesias | { |
150 | ee8b246f | Edgar E. Iglesias | tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
|
151 | ee8b246f | Edgar E. Iglesias | } |
152 | ee8b246f | Edgar E. Iglesias | |
153 | ee8b246f | Edgar E. Iglesias | static void write_carry(DisasContext *dc, TCGv v) |
154 | ee8b246f | Edgar E. Iglesias | { |
155 | ee8b246f | Edgar E. Iglesias | TCGv t0 = tcg_temp_new(); |
156 | ee8b246f | Edgar E. Iglesias | tcg_gen_shli_tl(t0, v, 31);
|
157 | ee8b246f | Edgar E. Iglesias | tcg_gen_sari_tl(t0, t0, 31);
|
158 | ee8b246f | Edgar E. Iglesias | tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC)); |
159 | ee8b246f | Edgar E. Iglesias | tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], |
160 | ee8b246f | Edgar E. Iglesias | ~(MSR_C | MSR_CC)); |
161 | ee8b246f | Edgar E. Iglesias | tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0); |
162 | ee8b246f | Edgar E. Iglesias | tcg_temp_free(t0); |
163 | ee8b246f | Edgar E. Iglesias | } |
164 | ee8b246f | Edgar E. Iglesias | |
165 | 8cc9b43f | Peter A. G. Crosthwaite | static void write_carryi(DisasContext *dc, int carry) |
166 | 8cc9b43f | Peter A. G. Crosthwaite | { |
167 | 8cc9b43f | Peter A. G. Crosthwaite | TCGv t0 = tcg_temp_new(); |
168 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_movi_tl(t0, carry ? 1 : 0); |
169 | 8cc9b43f | Peter A. G. Crosthwaite | write_carry(dc, t0); |
170 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_temp_free(t0); |
171 | 8cc9b43f | Peter A. G. Crosthwaite | } |
172 | 8cc9b43f | Peter A. G. Crosthwaite | |
173 | 61204ce8 | Edgar E. Iglesias | /* True if ALU operand b is a small immediate that may deserve
|
174 | 61204ce8 | Edgar E. Iglesias | faster treatment. */
|
175 | 61204ce8 | Edgar E. Iglesias | static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) |
176 | 61204ce8 | Edgar E. Iglesias | { |
177 | 61204ce8 | Edgar E. Iglesias | /* Immediate insn without the imm prefix ? */
|
178 | 61204ce8 | Edgar E. Iglesias | return dc->type_b && !(dc->tb_flags & IMM_FLAG);
|
179 | 61204ce8 | Edgar E. Iglesias | } |
180 | 61204ce8 | Edgar E. Iglesias | |
181 | 4acb54ba | Edgar E. Iglesias | static inline TCGv *dec_alu_op_b(DisasContext *dc) |
182 | 4acb54ba | Edgar E. Iglesias | { |
183 | 4acb54ba | Edgar E. Iglesias | if (dc->type_b) {
|
184 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags & IMM_FLAG)
|
185 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ori_tl(env_imm, env_imm, dc->imm); |
186 | 4acb54ba | Edgar E. Iglesias | else
|
187 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm)); |
188 | 4acb54ba | Edgar E. Iglesias | return &env_imm;
|
189 | 4acb54ba | Edgar E. Iglesias | } else
|
190 | 4acb54ba | Edgar E. Iglesias | return &cpu_R[dc->rb];
|
191 | 4acb54ba | Edgar E. Iglesias | } |
192 | 4acb54ba | Edgar E. Iglesias | |
193 | 4acb54ba | Edgar E. Iglesias | static void dec_add(DisasContext *dc) |
194 | 4acb54ba | Edgar E. Iglesias | { |
195 | 4acb54ba | Edgar E. Iglesias | unsigned int k, c; |
196 | 40cbf5b7 | Edgar E. Iglesias | TCGv cf; |
197 | 4acb54ba | Edgar E. Iglesias | |
198 | 4acb54ba | Edgar E. Iglesias | k = dc->opcode & 4;
|
199 | 4acb54ba | Edgar E. Iglesias | c = dc->opcode & 2;
|
200 | 4acb54ba | Edgar E. Iglesias | |
201 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("add%s%s%s r%d r%d r%d\n",
|
202 | 4acb54ba | Edgar E. Iglesias | dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "", |
203 | 4acb54ba | Edgar E. Iglesias | dc->rd, dc->ra, dc->rb); |
204 | 4acb54ba | Edgar E. Iglesias | |
205 | 40cbf5b7 | Edgar E. Iglesias | /* Take care of the easy cases first. */
|
206 | 40cbf5b7 | Edgar E. Iglesias | if (k) {
|
207 | 40cbf5b7 | Edgar E. Iglesias | /* k - keep carry, no need to update MSR. */
|
208 | 40cbf5b7 | Edgar E. Iglesias | /* If rd == r0, it's a nop. */
|
209 | 40cbf5b7 | Edgar E. Iglesias | if (dc->rd) {
|
210 | 40cbf5b7 | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
211 | 40cbf5b7 | Edgar E. Iglesias | |
212 | 40cbf5b7 | Edgar E. Iglesias | if (c) {
|
213 | 40cbf5b7 | Edgar E. Iglesias | /* c - Add carry into the result. */
|
214 | 40cbf5b7 | Edgar E. Iglesias | cf = tcg_temp_new(); |
215 | 40cbf5b7 | Edgar E. Iglesias | |
216 | 40cbf5b7 | Edgar E. Iglesias | read_carry(dc, cf); |
217 | 40cbf5b7 | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); |
218 | 40cbf5b7 | Edgar E. Iglesias | tcg_temp_free(cf); |
219 | 40cbf5b7 | Edgar E. Iglesias | } |
220 | 40cbf5b7 | Edgar E. Iglesias | } |
221 | 40cbf5b7 | Edgar E. Iglesias | return;
|
222 | 40cbf5b7 | Edgar E. Iglesias | } |
223 | 40cbf5b7 | Edgar E. Iglesias | |
224 | 40cbf5b7 | Edgar E. Iglesias | /* From now on, we can assume k is zero. So we need to update MSR. */
|
225 | 40cbf5b7 | Edgar E. Iglesias | /* Extract carry. */
|
226 | 40cbf5b7 | Edgar E. Iglesias | cf = tcg_temp_new(); |
227 | 40cbf5b7 | Edgar E. Iglesias | if (c) {
|
228 | 40cbf5b7 | Edgar E. Iglesias | read_carry(dc, cf); |
229 | 40cbf5b7 | Edgar E. Iglesias | } else {
|
230 | 40cbf5b7 | Edgar E. Iglesias | tcg_gen_movi_tl(cf, 0);
|
231 | 40cbf5b7 | Edgar E. Iglesias | } |
232 | 40cbf5b7 | Edgar E. Iglesias | |
233 | 40cbf5b7 | Edgar E. Iglesias | if (dc->rd) {
|
234 | 40cbf5b7 | Edgar E. Iglesias | TCGv ncf = tcg_temp_new(); |
235 | 5d0bb823 | Edgar E. Iglesias | gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); |
236 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
237 | 40cbf5b7 | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); |
238 | 40cbf5b7 | Edgar E. Iglesias | write_carry(dc, ncf); |
239 | 40cbf5b7 | Edgar E. Iglesias | tcg_temp_free(ncf); |
240 | 40cbf5b7 | Edgar E. Iglesias | } else {
|
241 | 5d0bb823 | Edgar E. Iglesias | gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); |
242 | 40cbf5b7 | Edgar E. Iglesias | write_carry(dc, cf); |
243 | 4acb54ba | Edgar E. Iglesias | } |
244 | 40cbf5b7 | Edgar E. Iglesias | tcg_temp_free(cf); |
245 | 4acb54ba | Edgar E. Iglesias | } |
246 | 4acb54ba | Edgar E. Iglesias | |
247 | 4acb54ba | Edgar E. Iglesias | static void dec_sub(DisasContext *dc) |
248 | 4acb54ba | Edgar E. Iglesias | { |
249 | 4acb54ba | Edgar E. Iglesias | unsigned int u, cmp, k, c; |
250 | e0a42ebc | Edgar E. Iglesias | TCGv cf, na; |
251 | 4acb54ba | Edgar E. Iglesias | |
252 | 4acb54ba | Edgar E. Iglesias | u = dc->imm & 2;
|
253 | 4acb54ba | Edgar E. Iglesias | k = dc->opcode & 4;
|
254 | 4acb54ba | Edgar E. Iglesias | c = dc->opcode & 2;
|
255 | 4acb54ba | Edgar E. Iglesias | cmp = (dc->imm & 1) && (!dc->type_b) && k;
|
256 | 4acb54ba | Edgar E. Iglesias | |
257 | 4acb54ba | Edgar E. Iglesias | if (cmp) {
|
258 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir); |
259 | 4acb54ba | Edgar E. Iglesias | if (dc->rd) {
|
260 | 4acb54ba | Edgar E. Iglesias | if (u)
|
261 | 4acb54ba | Edgar E. Iglesias | gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); |
262 | 4acb54ba | Edgar E. Iglesias | else
|
263 | 4acb54ba | Edgar E. Iglesias | gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); |
264 | 4acb54ba | Edgar E. Iglesias | } |
265 | e0a42ebc | Edgar E. Iglesias | return;
|
266 | e0a42ebc | Edgar E. Iglesias | } |
267 | e0a42ebc | Edgar E. Iglesias | |
268 | e0a42ebc | Edgar E. Iglesias | LOG_DIS("sub%s%s r%d, r%d r%d\n",
|
269 | e0a42ebc | Edgar E. Iglesias | k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb); |
270 | e0a42ebc | Edgar E. Iglesias | |
271 | e0a42ebc | Edgar E. Iglesias | /* Take care of the easy cases first. */
|
272 | e0a42ebc | Edgar E. Iglesias | if (k) {
|
273 | e0a42ebc | Edgar E. Iglesias | /* k - keep carry, no need to update MSR. */
|
274 | e0a42ebc | Edgar E. Iglesias | /* If rd == r0, it's a nop. */
|
275 | e0a42ebc | Edgar E. Iglesias | if (dc->rd) {
|
276 | 4acb54ba | Edgar E. Iglesias | tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); |
277 | e0a42ebc | Edgar E. Iglesias | |
278 | e0a42ebc | Edgar E. Iglesias | if (c) {
|
279 | e0a42ebc | Edgar E. Iglesias | /* c - Add carry into the result. */
|
280 | e0a42ebc | Edgar E. Iglesias | cf = tcg_temp_new(); |
281 | e0a42ebc | Edgar E. Iglesias | |
282 | e0a42ebc | Edgar E. Iglesias | read_carry(dc, cf); |
283 | e0a42ebc | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); |
284 | e0a42ebc | Edgar E. Iglesias | tcg_temp_free(cf); |
285 | e0a42ebc | Edgar E. Iglesias | } |
286 | e0a42ebc | Edgar E. Iglesias | } |
287 | e0a42ebc | Edgar E. Iglesias | return;
|
288 | e0a42ebc | Edgar E. Iglesias | } |
289 | e0a42ebc | Edgar E. Iglesias | |
290 | e0a42ebc | Edgar E. Iglesias | /* From now on, we can assume k is zero. So we need to update MSR. */
|
291 | e0a42ebc | Edgar E. Iglesias | /* Extract carry. And complement a into na. */
|
292 | e0a42ebc | Edgar E. Iglesias | cf = tcg_temp_new(); |
293 | e0a42ebc | Edgar E. Iglesias | na = tcg_temp_new(); |
294 | e0a42ebc | Edgar E. Iglesias | if (c) {
|
295 | e0a42ebc | Edgar E. Iglesias | read_carry(dc, cf); |
296 | e0a42ebc | Edgar E. Iglesias | } else {
|
297 | e0a42ebc | Edgar E. Iglesias | tcg_gen_movi_tl(cf, 1);
|
298 | e0a42ebc | Edgar E. Iglesias | } |
299 | e0a42ebc | Edgar E. Iglesias | |
300 | e0a42ebc | Edgar E. Iglesias | /* d = b + ~a + c. carry defaults to 1. */
|
301 | e0a42ebc | Edgar E. Iglesias | tcg_gen_not_tl(na, cpu_R[dc->ra]); |
302 | e0a42ebc | Edgar E. Iglesias | |
303 | e0a42ebc | Edgar E. Iglesias | if (dc->rd) {
|
304 | e0a42ebc | Edgar E. Iglesias | TCGv ncf = tcg_temp_new(); |
305 | 5d0bb823 | Edgar E. Iglesias | gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf); |
306 | e0a42ebc | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc))); |
307 | e0a42ebc | Edgar E. Iglesias | tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); |
308 | e0a42ebc | Edgar E. Iglesias | write_carry(dc, ncf); |
309 | e0a42ebc | Edgar E. Iglesias | tcg_temp_free(ncf); |
310 | e0a42ebc | Edgar E. Iglesias | } else {
|
311 | 5d0bb823 | Edgar E. Iglesias | gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf); |
312 | e0a42ebc | Edgar E. Iglesias | write_carry(dc, cf); |
313 | 4acb54ba | Edgar E. Iglesias | } |
314 | e0a42ebc | Edgar E. Iglesias | tcg_temp_free(cf); |
315 | e0a42ebc | Edgar E. Iglesias | tcg_temp_free(na); |
316 | 4acb54ba | Edgar E. Iglesias | } |
317 | 4acb54ba | Edgar E. Iglesias | |
318 | 4acb54ba | Edgar E. Iglesias | static void dec_pattern(DisasContext *dc) |
319 | 4acb54ba | Edgar E. Iglesias | { |
320 | 4acb54ba | Edgar E. Iglesias | unsigned int mode; |
321 | 4acb54ba | Edgar E. Iglesias | int l1;
|
322 | 4acb54ba | Edgar E. Iglesias | |
323 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
324 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
325 | 1567a005 | Edgar E. Iglesias | && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
|
326 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
327 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
328 | 1567a005 | Edgar E. Iglesias | } |
329 | 1567a005 | Edgar E. Iglesias | |
330 | 4acb54ba | Edgar E. Iglesias | mode = dc->opcode & 3;
|
331 | 4acb54ba | Edgar E. Iglesias | switch (mode) {
|
332 | 4acb54ba | Edgar E. Iglesias | case 0: |
333 | 4acb54ba | Edgar E. Iglesias | /* pcmpbf. */
|
334 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
335 | 4acb54ba | Edgar E. Iglesias | if (dc->rd)
|
336 | 4acb54ba | Edgar E. Iglesias | gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); |
337 | 4acb54ba | Edgar E. Iglesias | break;
|
338 | 4acb54ba | Edgar E. Iglesias | case 2: |
339 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
340 | 4acb54ba | Edgar E. Iglesias | if (dc->rd) {
|
341 | 4acb54ba | Edgar E. Iglesias | TCGv t0 = tcg_temp_local_new(); |
342 | 4acb54ba | Edgar E. Iglesias | l1 = gen_new_label(); |
343 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(t0, 1);
|
344 | 4acb54ba | Edgar E. Iglesias | tcg_gen_brcond_tl(TCG_COND_EQ, |
345 | 4acb54ba | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb], l1); |
346 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(t0, 0);
|
347 | 4acb54ba | Edgar E. Iglesias | gen_set_label(l1); |
348 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], t0); |
349 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
350 | 4acb54ba | Edgar E. Iglesias | } |
351 | 4acb54ba | Edgar E. Iglesias | break;
|
352 | 4acb54ba | Edgar E. Iglesias | case 3: |
353 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
354 | 4acb54ba | Edgar E. Iglesias | l1 = gen_new_label(); |
355 | 4acb54ba | Edgar E. Iglesias | if (dc->rd) {
|
356 | 4acb54ba | Edgar E. Iglesias | TCGv t0 = tcg_temp_local_new(); |
357 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(t0, 1);
|
358 | 4acb54ba | Edgar E. Iglesias | tcg_gen_brcond_tl(TCG_COND_NE, |
359 | 4acb54ba | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb], l1); |
360 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(t0, 0);
|
361 | 4acb54ba | Edgar E. Iglesias | gen_set_label(l1); |
362 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], t0); |
363 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
364 | 4acb54ba | Edgar E. Iglesias | } |
365 | 4acb54ba | Edgar E. Iglesias | break;
|
366 | 4acb54ba | Edgar E. Iglesias | default:
|
367 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, |
368 | 4acb54ba | Edgar E. Iglesias | "unsupported pattern insn opcode=%x\n", dc->opcode);
|
369 | 4acb54ba | Edgar E. Iglesias | break;
|
370 | 4acb54ba | Edgar E. Iglesias | } |
371 | 4acb54ba | Edgar E. Iglesias | } |
372 | 4acb54ba | Edgar E. Iglesias | |
373 | 4acb54ba | Edgar E. Iglesias | static void dec_and(DisasContext *dc) |
374 | 4acb54ba | Edgar E. Iglesias | { |
375 | 4acb54ba | Edgar E. Iglesias | unsigned int not; |
376 | 4acb54ba | Edgar E. Iglesias | |
377 | 4acb54ba | Edgar E. Iglesias | if (!dc->type_b && (dc->imm & (1 << 10))) { |
378 | 4acb54ba | Edgar E. Iglesias | dec_pattern(dc); |
379 | 4acb54ba | Edgar E. Iglesias | return;
|
380 | 4acb54ba | Edgar E. Iglesias | } |
381 | 4acb54ba | Edgar E. Iglesias | |
382 | 4acb54ba | Edgar E. Iglesias | not = dc->opcode & (1 << 1); |
383 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("and%s\n", not ? "n" : ""); |
384 | 4acb54ba | Edgar E. Iglesias | |
385 | 4acb54ba | Edgar E. Iglesias | if (!dc->rd)
|
386 | 4acb54ba | Edgar E. Iglesias | return;
|
387 | 4acb54ba | Edgar E. Iglesias | |
388 | 4acb54ba | Edgar E. Iglesias | if (not) {
|
389 | 4acb54ba | Edgar E. Iglesias | TCGv t = tcg_temp_new(); |
390 | 4acb54ba | Edgar E. Iglesias | tcg_gen_not_tl(t, *(dec_alu_op_b(dc))); |
391 | 4acb54ba | Edgar E. Iglesias | tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t); |
392 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t); |
393 | 4acb54ba | Edgar E. Iglesias | } else
|
394 | 4acb54ba | Edgar E. Iglesias | tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
395 | 4acb54ba | Edgar E. Iglesias | } |
396 | 4acb54ba | Edgar E. Iglesias | |
397 | 4acb54ba | Edgar E. Iglesias | static void dec_or(DisasContext *dc) |
398 | 4acb54ba | Edgar E. Iglesias | { |
399 | 4acb54ba | Edgar E. Iglesias | if (!dc->type_b && (dc->imm & (1 << 10))) { |
400 | 4acb54ba | Edgar E. Iglesias | dec_pattern(dc); |
401 | 4acb54ba | Edgar E. Iglesias | return;
|
402 | 4acb54ba | Edgar E. Iglesias | } |
403 | 4acb54ba | Edgar E. Iglesias | |
404 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
|
405 | 4acb54ba | Edgar E. Iglesias | if (dc->rd)
|
406 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
407 | 4acb54ba | Edgar E. Iglesias | } |
408 | 4acb54ba | Edgar E. Iglesias | |
409 | 4acb54ba | Edgar E. Iglesias | static void dec_xor(DisasContext *dc) |
410 | 4acb54ba | Edgar E. Iglesias | { |
411 | 4acb54ba | Edgar E. Iglesias | if (!dc->type_b && (dc->imm & (1 << 10))) { |
412 | 4acb54ba | Edgar E. Iglesias | dec_pattern(dc); |
413 | 4acb54ba | Edgar E. Iglesias | return;
|
414 | 4acb54ba | Edgar E. Iglesias | } |
415 | 4acb54ba | Edgar E. Iglesias | |
416 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("xor r%d\n", dc->rd);
|
417 | 4acb54ba | Edgar E. Iglesias | if (dc->rd)
|
418 | 4acb54ba | Edgar E. Iglesias | tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
419 | 4acb54ba | Edgar E. Iglesias | } |
420 | 4acb54ba | Edgar E. Iglesias | |
421 | 4acb54ba | Edgar E. Iglesias | static inline void msr_read(DisasContext *dc, TCGv d) |
422 | 4acb54ba | Edgar E. Iglesias | { |
423 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(d, cpu_SR[SR_MSR]); |
424 | 4acb54ba | Edgar E. Iglesias | } |
425 | 4acb54ba | Edgar E. Iglesias | |
426 | 4acb54ba | Edgar E. Iglesias | static inline void msr_write(DisasContext *dc, TCGv v) |
427 | 4acb54ba | Edgar E. Iglesias | { |
428 | 97b833c5 | Edgar E. Iglesias | TCGv t; |
429 | 97b833c5 | Edgar E. Iglesias | |
430 | 97b833c5 | Edgar E. Iglesias | t = tcg_temp_new(); |
431 | 4acb54ba | Edgar E. Iglesias | dc->cpustate_changed = 1;
|
432 | 97b833c5 | Edgar E. Iglesias | /* PVR bit is not writable. */
|
433 | 8a84fc6b | Edgar E. Iglesias | tcg_gen_andi_tl(t, v, ~MSR_PVR); |
434 | 8a84fc6b | Edgar E. Iglesias | tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); |
435 | 97b833c5 | Edgar E. Iglesias | tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v); |
436 | 97b833c5 | Edgar E. Iglesias | tcg_temp_free(t); |
437 | 4acb54ba | Edgar E. Iglesias | } |
438 | 4acb54ba | Edgar E. Iglesias | |
439 | 4acb54ba | Edgar E. Iglesias | static void dec_msr(DisasContext *dc) |
440 | 4acb54ba | Edgar E. Iglesias | { |
441 | 4acb54ba | Edgar E. Iglesias | TCGv t0, t1; |
442 | 4acb54ba | Edgar E. Iglesias | unsigned int sr, to, rn; |
443 | 1567a005 | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
444 | 4acb54ba | Edgar E. Iglesias | |
445 | 4acb54ba | Edgar E. Iglesias | sr = dc->imm & ((1 << 14) - 1); |
446 | 4acb54ba | Edgar E. Iglesias | to = dc->imm & (1 << 14); |
447 | 4acb54ba | Edgar E. Iglesias | dc->type_b = 1;
|
448 | 4acb54ba | Edgar E. Iglesias | if (to)
|
449 | 4acb54ba | Edgar E. Iglesias | dc->cpustate_changed = 1;
|
450 | 4acb54ba | Edgar E. Iglesias | |
451 | 4acb54ba | Edgar E. Iglesias | /* msrclr and msrset. */
|
452 | 4acb54ba | Edgar E. Iglesias | if (!(dc->imm & (1 << 15))) { |
453 | 4acb54ba | Edgar E. Iglesias | unsigned int clr = dc->ir & (1 << 16); |
454 | 4acb54ba | Edgar E. Iglesias | |
455 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", |
456 | 4acb54ba | Edgar E. Iglesias | dc->rd, dc->imm); |
457 | 1567a005 | Edgar E. Iglesias | |
458 | 1567a005 | Edgar E. Iglesias | if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) { |
459 | 1567a005 | Edgar E. Iglesias | /* nop??? */
|
460 | 1567a005 | Edgar E. Iglesias | return;
|
461 | 1567a005 | Edgar E. Iglesias | } |
462 | 1567a005 | Edgar E. Iglesias | |
463 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
464 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) { |
465 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
466 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
467 | 1567a005 | Edgar E. Iglesias | return;
|
468 | 1567a005 | Edgar E. Iglesias | } |
469 | 1567a005 | Edgar E. Iglesias | |
470 | 4acb54ba | Edgar E. Iglesias | if (dc->rd)
|
471 | 4acb54ba | Edgar E. Iglesias | msr_read(dc, cpu_R[dc->rd]); |
472 | 4acb54ba | Edgar E. Iglesias | |
473 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
474 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new(); |
475 | 4acb54ba | Edgar E. Iglesias | msr_read(dc, t0); |
476 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc))); |
477 | 4acb54ba | Edgar E. Iglesias | |
478 | 4acb54ba | Edgar E. Iglesias | if (clr) {
|
479 | 4acb54ba | Edgar E. Iglesias | tcg_gen_not_tl(t1, t1); |
480 | 4acb54ba | Edgar E. Iglesias | tcg_gen_and_tl(t0, t0, t1); |
481 | 4acb54ba | Edgar E. Iglesias | } else
|
482 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(t0, t0, t1); |
483 | 4acb54ba | Edgar E. Iglesias | msr_write(dc, t0); |
484 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
485 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t1); |
486 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
|
487 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_UPDATE; |
488 | 4acb54ba | Edgar E. Iglesias | return;
|
489 | 4acb54ba | Edgar E. Iglesias | } |
490 | 4acb54ba | Edgar E. Iglesias | |
491 | 1567a005 | Edgar E. Iglesias | if (to) {
|
492 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
493 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
494 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
495 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
496 | 1567a005 | Edgar E. Iglesias | return;
|
497 | 1567a005 | Edgar E. Iglesias | } |
498 | 1567a005 | Edgar E. Iglesias | } |
499 | 1567a005 | Edgar E. Iglesias | |
500 | 4acb54ba | Edgar E. Iglesias | #if !defined(CONFIG_USER_ONLY)
|
501 | 4acb54ba | Edgar E. Iglesias | /* Catch read/writes to the mmu block. */
|
502 | 4acb54ba | Edgar E. Iglesias | if ((sr & ~0xff) == 0x1000) { |
503 | 4acb54ba | Edgar E. Iglesias | sr &= 7;
|
504 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); |
505 | 4acb54ba | Edgar E. Iglesias | if (to)
|
506 | 64254eba | Blue Swirl | gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]); |
507 | 4acb54ba | Edgar E. Iglesias | else
|
508 | 64254eba | Blue Swirl | gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr)); |
509 | 4acb54ba | Edgar E. Iglesias | return;
|
510 | 4acb54ba | Edgar E. Iglesias | } |
511 | 4acb54ba | Edgar E. Iglesias | #endif
|
512 | 4acb54ba | Edgar E. Iglesias | |
513 | 4acb54ba | Edgar E. Iglesias | if (to) {
|
514 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); |
515 | 4acb54ba | Edgar E. Iglesias | switch (sr) {
|
516 | 4acb54ba | Edgar E. Iglesias | case 0: |
517 | 4acb54ba | Edgar E. Iglesias | break;
|
518 | 4acb54ba | Edgar E. Iglesias | case 1: |
519 | 4acb54ba | Edgar E. Iglesias | msr_write(dc, cpu_R[dc->ra]); |
520 | 4acb54ba | Edgar E. Iglesias | break;
|
521 | 4acb54ba | Edgar E. Iglesias | case 0x3: |
522 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]); |
523 | 4acb54ba | Edgar E. Iglesias | break;
|
524 | 4acb54ba | Edgar E. Iglesias | case 0x5: |
525 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]); |
526 | 4acb54ba | Edgar E. Iglesias | break;
|
527 | 4acb54ba | Edgar E. Iglesias | case 0x7: |
528 | 97694c57 | Edgar E. Iglesias | tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
|
529 | 4acb54ba | Edgar E. Iglesias | break;
|
530 | 5818dee5 | Edgar E. Iglesias | case 0x800: |
531 | 68cee38a | Andreas Färber | tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr)); |
532 | 5818dee5 | Edgar E. Iglesias | break;
|
533 | 5818dee5 | Edgar E. Iglesias | case 0x802: |
534 | 68cee38a | Andreas Färber | tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr)); |
535 | 5818dee5 | Edgar E. Iglesias | break;
|
536 | 4acb54ba | Edgar E. Iglesias | default:
|
537 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "unknown mts reg %x\n", sr);
|
538 | 4acb54ba | Edgar E. Iglesias | break;
|
539 | 4acb54ba | Edgar E. Iglesias | } |
540 | 4acb54ba | Edgar E. Iglesias | } else {
|
541 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm); |
542 | 4acb54ba | Edgar E. Iglesias | |
543 | 4acb54ba | Edgar E. Iglesias | switch (sr) {
|
544 | 4acb54ba | Edgar E. Iglesias | case 0: |
545 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); |
546 | 4acb54ba | Edgar E. Iglesias | break;
|
547 | 4acb54ba | Edgar E. Iglesias | case 1: |
548 | 4acb54ba | Edgar E. Iglesias | msr_read(dc, cpu_R[dc->rd]); |
549 | 4acb54ba | Edgar E. Iglesias | break;
|
550 | 4acb54ba | Edgar E. Iglesias | case 0x3: |
551 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]); |
552 | 4acb54ba | Edgar E. Iglesias | break;
|
553 | 4acb54ba | Edgar E. Iglesias | case 0x5: |
554 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]); |
555 | 4acb54ba | Edgar E. Iglesias | break;
|
556 | 4acb54ba | Edgar E. Iglesias | case 0x7: |
557 | 97694c57 | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]); |
558 | 4acb54ba | Edgar E. Iglesias | break;
|
559 | 4acb54ba | Edgar E. Iglesias | case 0xb: |
560 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]); |
561 | 4acb54ba | Edgar E. Iglesias | break;
|
562 | 5818dee5 | Edgar E. Iglesias | case 0x800: |
563 | 68cee38a | Andreas Färber | tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr)); |
564 | 5818dee5 | Edgar E. Iglesias | break;
|
565 | 5818dee5 | Edgar E. Iglesias | case 0x802: |
566 | 68cee38a | Andreas Färber | tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr)); |
567 | 5818dee5 | Edgar E. Iglesias | break;
|
568 | 4acb54ba | Edgar E. Iglesias | case 0x2000: |
569 | 4acb54ba | Edgar E. Iglesias | case 0x2001: |
570 | 4acb54ba | Edgar E. Iglesias | case 0x2002: |
571 | 4acb54ba | Edgar E. Iglesias | case 0x2003: |
572 | 4acb54ba | Edgar E. Iglesias | case 0x2004: |
573 | 4acb54ba | Edgar E. Iglesias | case 0x2005: |
574 | 4acb54ba | Edgar E. Iglesias | case 0x2006: |
575 | 4acb54ba | Edgar E. Iglesias | case 0x2007: |
576 | 4acb54ba | Edgar E. Iglesias | case 0x2008: |
577 | 4acb54ba | Edgar E. Iglesias | case 0x2009: |
578 | 4acb54ba | Edgar E. Iglesias | case 0x200a: |
579 | 4acb54ba | Edgar E. Iglesias | case 0x200b: |
580 | 4acb54ba | Edgar E. Iglesias | case 0x200c: |
581 | 4acb54ba | Edgar E. Iglesias | rn = sr & 0xf;
|
582 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ld_tl(cpu_R[dc->rd], |
583 | 68cee38a | Andreas Färber | cpu_env, offsetof(CPUMBState, pvr.regs[rn])); |
584 | 4acb54ba | Edgar E. Iglesias | break;
|
585 | 4acb54ba | Edgar E. Iglesias | default:
|
586 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
|
587 | 4acb54ba | Edgar E. Iglesias | break;
|
588 | 4acb54ba | Edgar E. Iglesias | } |
589 | 4acb54ba | Edgar E. Iglesias | } |
590 | ee7dbcf8 | Edgar E. Iglesias | |
591 | ee7dbcf8 | Edgar E. Iglesias | if (dc->rd == 0) { |
592 | ee7dbcf8 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_R[0], 0); |
593 | ee7dbcf8 | Edgar E. Iglesias | } |
594 | 4acb54ba | Edgar E. Iglesias | } |
595 | 4acb54ba | Edgar E. Iglesias | |
596 | 4acb54ba | Edgar E. Iglesias | /* 64-bit signed mul, lower result in d and upper in d2. */
|
597 | 4acb54ba | Edgar E. Iglesias | static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b) |
598 | 4acb54ba | Edgar E. Iglesias | { |
599 | 4acb54ba | Edgar E. Iglesias | TCGv_i64 t0, t1; |
600 | 4acb54ba | Edgar E. Iglesias | |
601 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new_i64(); |
602 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new_i64(); |
603 | 4acb54ba | Edgar E. Iglesias | |
604 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ext_i32_i64(t0, a); |
605 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ext_i32_i64(t1, b); |
606 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mul_i64(t0, t0, t1); |
607 | 4acb54ba | Edgar E. Iglesias | |
608 | 4acb54ba | Edgar E. Iglesias | tcg_gen_trunc_i64_i32(d, t0); |
609 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_i64(t0, t0, 32);
|
610 | 4acb54ba | Edgar E. Iglesias | tcg_gen_trunc_i64_i32(d2, t0); |
611 | 4acb54ba | Edgar E. Iglesias | |
612 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free_i64(t0); |
613 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free_i64(t1); |
614 | 4acb54ba | Edgar E. Iglesias | } |
615 | 4acb54ba | Edgar E. Iglesias | |
616 | 4acb54ba | Edgar E. Iglesias | /* 64-bit unsigned muls, lower result in d and upper in d2. */
|
617 | 4acb54ba | Edgar E. Iglesias | static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b) |
618 | 4acb54ba | Edgar E. Iglesias | { |
619 | 4acb54ba | Edgar E. Iglesias | TCGv_i64 t0, t1; |
620 | 4acb54ba | Edgar E. Iglesias | |
621 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new_i64(); |
622 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new_i64(); |
623 | 4acb54ba | Edgar E. Iglesias | |
624 | 4acb54ba | Edgar E. Iglesias | tcg_gen_extu_i32_i64(t0, a); |
625 | 4acb54ba | Edgar E. Iglesias | tcg_gen_extu_i32_i64(t1, b); |
626 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mul_i64(t0, t0, t1); |
627 | 4acb54ba | Edgar E. Iglesias | |
628 | 4acb54ba | Edgar E. Iglesias | tcg_gen_trunc_i64_i32(d, t0); |
629 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_i64(t0, t0, 32);
|
630 | 4acb54ba | Edgar E. Iglesias | tcg_gen_trunc_i64_i32(d2, t0); |
631 | 4acb54ba | Edgar E. Iglesias | |
632 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free_i64(t0); |
633 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free_i64(t1); |
634 | 4acb54ba | Edgar E. Iglesias | } |
635 | 4acb54ba | Edgar E. Iglesias | |
636 | 4acb54ba | Edgar E. Iglesias | /* Multiplier unit. */
|
637 | 4acb54ba | Edgar E. Iglesias | static void dec_mul(DisasContext *dc) |
638 | 4acb54ba | Edgar E. Iglesias | { |
639 | 4acb54ba | Edgar E. Iglesias | TCGv d[2];
|
640 | 4acb54ba | Edgar E. Iglesias | unsigned int subcode; |
641 | 4acb54ba | Edgar E. Iglesias | |
642 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
643 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
644 | 1567a005 | Edgar E. Iglesias | && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
|
645 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
646 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
647 | 1567a005 | Edgar E. Iglesias | return;
|
648 | 1567a005 | Edgar E. Iglesias | } |
649 | 1567a005 | Edgar E. Iglesias | |
650 | 4acb54ba | Edgar E. Iglesias | subcode = dc->imm & 3;
|
651 | 4acb54ba | Edgar E. Iglesias | d[0] = tcg_temp_new();
|
652 | 4acb54ba | Edgar E. Iglesias | d[1] = tcg_temp_new();
|
653 | 4acb54ba | Edgar E. Iglesias | |
654 | 4acb54ba | Edgar E. Iglesias | if (dc->type_b) {
|
655 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
|
656 | 4acb54ba | Edgar E. Iglesias | t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
|
657 | 4acb54ba | Edgar E. Iglesias | goto done;
|
658 | 4acb54ba | Edgar E. Iglesias | } |
659 | 4acb54ba | Edgar E. Iglesias | |
660 | 1567a005 | Edgar E. Iglesias | /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
|
661 | 1567a005 | Edgar E. Iglesias | if (subcode >= 1 && subcode <= 3 |
662 | 1567a005 | Edgar E. Iglesias | && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
|
663 | 1567a005 | Edgar E. Iglesias | /* nop??? */
|
664 | 1567a005 | Edgar E. Iglesias | } |
665 | 1567a005 | Edgar E. Iglesias | |
666 | 4acb54ba | Edgar E. Iglesias | switch (subcode) {
|
667 | 4acb54ba | Edgar E. Iglesias | case 0: |
668 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
669 | 4acb54ba | Edgar E. Iglesias | t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
|
670 | 4acb54ba | Edgar E. Iglesias | break;
|
671 | 4acb54ba | Edgar E. Iglesias | case 1: |
672 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
673 | 4acb54ba | Edgar E. Iglesias | t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
|
674 | 4acb54ba | Edgar E. Iglesias | break;
|
675 | 4acb54ba | Edgar E. Iglesias | case 2: |
676 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
677 | 4acb54ba | Edgar E. Iglesias | t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
|
678 | 4acb54ba | Edgar E. Iglesias | break;
|
679 | 4acb54ba | Edgar E. Iglesias | case 3: |
680 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
|
681 | 4acb54ba | Edgar E. Iglesias | t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
|
682 | 4acb54ba | Edgar E. Iglesias | break;
|
683 | 4acb54ba | Edgar E. Iglesias | default:
|
684 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
|
685 | 4acb54ba | Edgar E. Iglesias | break;
|
686 | 4acb54ba | Edgar E. Iglesias | } |
687 | 4acb54ba | Edgar E. Iglesias | done:
|
688 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(d[0]);
|
689 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(d[1]);
|
690 | 4acb54ba | Edgar E. Iglesias | } |
691 | 4acb54ba | Edgar E. Iglesias | |
692 | 4acb54ba | Edgar E. Iglesias | /* Div unit. */
|
693 | 4acb54ba | Edgar E. Iglesias | static void dec_div(DisasContext *dc) |
694 | 4acb54ba | Edgar E. Iglesias | { |
695 | 4acb54ba | Edgar E. Iglesias | unsigned int u; |
696 | 4acb54ba | Edgar E. Iglesias | |
697 | 4acb54ba | Edgar E. Iglesias | u = dc->imm & 2;
|
698 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("div\n");
|
699 | 4acb54ba | Edgar E. Iglesias | |
700 | 97f90cbf | Edgar E. Iglesias | if ((dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) |
701 | 1567a005 | Edgar E. Iglesias | && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
|
702 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
703 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
704 | 1567a005 | Edgar E. Iglesias | } |
705 | 1567a005 | Edgar E. Iglesias | |
706 | 4acb54ba | Edgar E. Iglesias | if (u)
|
707 | 64254eba | Blue Swirl | gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), |
708 | 64254eba | Blue Swirl | cpu_R[dc->ra]); |
709 | 4acb54ba | Edgar E. Iglesias | else
|
710 | 64254eba | Blue Swirl | gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), |
711 | 64254eba | Blue Swirl | cpu_R[dc->ra]); |
712 | 4acb54ba | Edgar E. Iglesias | if (!dc->rd)
|
713 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_R[dc->rd], 0);
|
714 | 4acb54ba | Edgar E. Iglesias | } |
715 | 4acb54ba | Edgar E. Iglesias | |
716 | 4acb54ba | Edgar E. Iglesias | static void dec_barrel(DisasContext *dc) |
717 | 4acb54ba | Edgar E. Iglesias | { |
718 | 4acb54ba | Edgar E. Iglesias | TCGv t0; |
719 | 4acb54ba | Edgar E. Iglesias | unsigned int s, t; |
720 | 4acb54ba | Edgar E. Iglesias | |
721 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
722 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
723 | 1567a005 | Edgar E. Iglesias | && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
|
724 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
725 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
726 | 1567a005 | Edgar E. Iglesias | return;
|
727 | 1567a005 | Edgar E. Iglesias | } |
728 | 1567a005 | Edgar E. Iglesias | |
729 | 4acb54ba | Edgar E. Iglesias | s = dc->imm & (1 << 10); |
730 | 4acb54ba | Edgar E. Iglesias | t = dc->imm & (1 << 9); |
731 | 4acb54ba | Edgar E. Iglesias | |
732 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("bs%s%s r%d r%d r%d\n",
|
733 | 4acb54ba | Edgar E. Iglesias | s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb); |
734 | 4acb54ba | Edgar E. Iglesias | |
735 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
736 | 4acb54ba | Edgar E. Iglesias | |
737 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); |
738 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, t0, 31);
|
739 | 4acb54ba | Edgar E. Iglesias | |
740 | 4acb54ba | Edgar E. Iglesias | if (s)
|
741 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); |
742 | 4acb54ba | Edgar E. Iglesias | else {
|
743 | 4acb54ba | Edgar E. Iglesias | if (t)
|
744 | 4acb54ba | Edgar E. Iglesias | tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); |
745 | 4acb54ba | Edgar E. Iglesias | else
|
746 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); |
747 | 4acb54ba | Edgar E. Iglesias | } |
748 | 4acb54ba | Edgar E. Iglesias | } |
749 | 4acb54ba | Edgar E. Iglesias | |
750 | 4acb54ba | Edgar E. Iglesias | static void dec_bit(DisasContext *dc) |
751 | 4acb54ba | Edgar E. Iglesias | { |
752 | 4acb54ba | Edgar E. Iglesias | TCGv t0, t1; |
753 | 4acb54ba | Edgar E. Iglesias | unsigned int op; |
754 | 1567a005 | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
755 | 4acb54ba | Edgar E. Iglesias | |
756 | ace2e4da | Peter A. G. Crosthwaite | op = dc->ir & ((1 << 9) - 1); |
757 | 4acb54ba | Edgar E. Iglesias | switch (op) {
|
758 | 4acb54ba | Edgar E. Iglesias | case 0x21: |
759 | 4acb54ba | Edgar E. Iglesias | /* src. */
|
760 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
761 | 4acb54ba | Edgar E. Iglesias | |
762 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
|
763 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
|
764 | 4acb54ba | Edgar E. Iglesias | if (dc->rd) {
|
765 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new(); |
766 | 4acb54ba | Edgar E. Iglesias | read_carry(dc, t1); |
767 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shli_tl(t1, t1, 31);
|
768 | 4acb54ba | Edgar E. Iglesias | |
769 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
770 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1); |
771 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t1); |
772 | 4acb54ba | Edgar E. Iglesias | } |
773 | 4acb54ba | Edgar E. Iglesias | |
774 | 4acb54ba | Edgar E. Iglesias | /* Update carry. */
|
775 | 4acb54ba | Edgar E. Iglesias | write_carry(dc, t0); |
776 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
777 | 4acb54ba | Edgar E. Iglesias | break;
|
778 | 4acb54ba | Edgar E. Iglesias | |
779 | 4acb54ba | Edgar E. Iglesias | case 0x1: |
780 | 4acb54ba | Edgar E. Iglesias | case 0x41: |
781 | 4acb54ba | Edgar E. Iglesias | /* srl. */
|
782 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
783 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
|
784 | 4acb54ba | Edgar E. Iglesias | |
785 | 4acb54ba | Edgar E. Iglesias | /* Update carry. */
|
786 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
|
787 | 4acb54ba | Edgar E. Iglesias | write_carry(dc, t0); |
788 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
789 | 4acb54ba | Edgar E. Iglesias | if (dc->rd) {
|
790 | 4acb54ba | Edgar E. Iglesias | if (op == 0x41) |
791 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
792 | 4acb54ba | Edgar E. Iglesias | else
|
793 | 4acb54ba | Edgar E. Iglesias | tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
794 | 4acb54ba | Edgar E. Iglesias | } |
795 | 4acb54ba | Edgar E. Iglesias | break;
|
796 | 4acb54ba | Edgar E. Iglesias | case 0x60: |
797 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
|
798 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); |
799 | 4acb54ba | Edgar E. Iglesias | break;
|
800 | 4acb54ba | Edgar E. Iglesias | case 0x61: |
801 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
|
802 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); |
803 | 4acb54ba | Edgar E. Iglesias | break;
|
804 | 4acb54ba | Edgar E. Iglesias | case 0x64: |
805 | f062a3c7 | Edgar E. Iglesias | case 0x66: |
806 | f062a3c7 | Edgar E. Iglesias | case 0x74: |
807 | f062a3c7 | Edgar E. Iglesias | case 0x76: |
808 | 4acb54ba | Edgar E. Iglesias | /* wdc. */
|
809 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("wdc r%d\n", dc->ra);
|
810 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
811 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
812 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
813 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
814 | 1567a005 | Edgar E. Iglesias | return;
|
815 | 1567a005 | Edgar E. Iglesias | } |
816 | 4acb54ba | Edgar E. Iglesias | break;
|
817 | 4acb54ba | Edgar E. Iglesias | case 0x68: |
818 | 4acb54ba | Edgar E. Iglesias | /* wic. */
|
819 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("wic r%d\n", dc->ra);
|
820 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
821 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
822 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
823 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
824 | 1567a005 | Edgar E. Iglesias | return;
|
825 | 1567a005 | Edgar E. Iglesias | } |
826 | 4acb54ba | Edgar E. Iglesias | break;
|
827 | 48b5e96f | Edgar E. Iglesias | case 0xe0: |
828 | 48b5e96f | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
829 | 48b5e96f | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
830 | 48b5e96f | Edgar E. Iglesias | && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
|
831 | 48b5e96f | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
832 | 48b5e96f | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
833 | 48b5e96f | Edgar E. Iglesias | } |
834 | 48b5e96f | Edgar E. Iglesias | if (dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR) { |
835 | 48b5e96f | Edgar E. Iglesias | gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]); |
836 | 48b5e96f | Edgar E. Iglesias | } |
837 | 48b5e96f | Edgar E. Iglesias | break;
|
838 | ace2e4da | Peter A. G. Crosthwaite | case 0x1e0: |
839 | ace2e4da | Peter A. G. Crosthwaite | /* swapb */
|
840 | ace2e4da | Peter A. G. Crosthwaite | LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
|
841 | ace2e4da | Peter A. G. Crosthwaite | tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]); |
842 | ace2e4da | Peter A. G. Crosthwaite | break;
|
843 | b8c6a5d9 | Peter Crosthwaite | case 0x1e2: |
844 | ace2e4da | Peter A. G. Crosthwaite | /*swaph */
|
845 | ace2e4da | Peter A. G. Crosthwaite | LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
|
846 | ace2e4da | Peter A. G. Crosthwaite | tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
|
847 | ace2e4da | Peter A. G. Crosthwaite | break;
|
848 | 4acb54ba | Edgar E. Iglesias | default:
|
849 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
|
850 | 4acb54ba | Edgar E. Iglesias | dc->pc, op, dc->rd, dc->ra, dc->rb); |
851 | 4acb54ba | Edgar E. Iglesias | break;
|
852 | 4acb54ba | Edgar E. Iglesias | } |
853 | 4acb54ba | Edgar E. Iglesias | } |
854 | 4acb54ba | Edgar E. Iglesias | |
855 | 4acb54ba | Edgar E. Iglesias | static inline void sync_jmpstate(DisasContext *dc) |
856 | 4acb54ba | Edgar E. Iglesias | { |
857 | 844bab60 | Edgar E. Iglesias | if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
|
858 | 844bab60 | Edgar E. Iglesias | if (dc->jmp == JMP_DIRECT) {
|
859 | 844bab60 | Edgar E. Iglesias | tcg_gen_movi_tl(env_btaken, 1);
|
860 | 844bab60 | Edgar E. Iglesias | } |
861 | 23979dc5 | Edgar E. Iglesias | dc->jmp = JMP_INDIRECT; |
862 | 23979dc5 | Edgar E. Iglesias | tcg_gen_movi_tl(env_btarget, dc->jmp_pc); |
863 | 4acb54ba | Edgar E. Iglesias | } |
864 | 4acb54ba | Edgar E. Iglesias | } |
865 | 4acb54ba | Edgar E. Iglesias | |
866 | 4acb54ba | Edgar E. Iglesias | static void dec_imm(DisasContext *dc) |
867 | 4acb54ba | Edgar E. Iglesias | { |
868 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("imm %x\n", dc->imm << 16); |
869 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_imm, (dc->imm << 16));
|
870 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= IMM_FLAG; |
871 | 4acb54ba | Edgar E. Iglesias | dc->clear_imm = 0;
|
872 | 4acb54ba | Edgar E. Iglesias | } |
873 | 4acb54ba | Edgar E. Iglesias | |
874 | 4acb54ba | Edgar E. Iglesias | static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
875 | 4acb54ba | Edgar E. Iglesias | unsigned int size) |
876 | 4acb54ba | Edgar E. Iglesias | { |
877 | 4acb54ba | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
878 | 4acb54ba | Edgar E. Iglesias | |
879 | 4acb54ba | Edgar E. Iglesias | if (size == 1) { |
880 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_ld8u(dst, addr, mem_index); |
881 | 4acb54ba | Edgar E. Iglesias | } else if (size == 2) { |
882 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_ld16u(dst, addr, mem_index); |
883 | 4acb54ba | Edgar E. Iglesias | } else if (size == 4) { |
884 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_ld32u(dst, addr, mem_index); |
885 | 4acb54ba | Edgar E. Iglesias | } else
|
886 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "Incorrect load size %d\n", size);
|
887 | 4acb54ba | Edgar E. Iglesias | } |
888 | 4acb54ba | Edgar E. Iglesias | |
889 | 4acb54ba | Edgar E. Iglesias | static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) |
890 | 4acb54ba | Edgar E. Iglesias | { |
891 | 4acb54ba | Edgar E. Iglesias | unsigned int extimm = dc->tb_flags & IMM_FLAG; |
892 | 5818dee5 | Edgar E. Iglesias | /* Should be set to one if r1 is used by loadstores. */
|
893 | 5818dee5 | Edgar E. Iglesias | int stackprot = 0; |
894 | 5818dee5 | Edgar E. Iglesias | |
895 | 5818dee5 | Edgar E. Iglesias | /* All load/stores use ra. */
|
896 | 5818dee5 | Edgar E. Iglesias | if (dc->ra == 1) { |
897 | 5818dee5 | Edgar E. Iglesias | stackprot = 1;
|
898 | 5818dee5 | Edgar E. Iglesias | } |
899 | 4acb54ba | Edgar E. Iglesias | |
900 | 9ef55357 | Edgar E. Iglesias | /* Treat the common cases first. */
|
901 | 4acb54ba | Edgar E. Iglesias | if (!dc->type_b) {
|
902 | 4b5ef0b5 | Edgar E. Iglesias | /* If any of the regs is r0, return a ptr to the other. */
|
903 | 4b5ef0b5 | Edgar E. Iglesias | if (dc->ra == 0) { |
904 | 4b5ef0b5 | Edgar E. Iglesias | return &cpu_R[dc->rb];
|
905 | 4b5ef0b5 | Edgar E. Iglesias | } else if (dc->rb == 0) { |
906 | 4b5ef0b5 | Edgar E. Iglesias | return &cpu_R[dc->ra];
|
907 | 4b5ef0b5 | Edgar E. Iglesias | } |
908 | 4b5ef0b5 | Edgar E. Iglesias | |
909 | 5818dee5 | Edgar E. Iglesias | if (dc->rb == 1) { |
910 | 5818dee5 | Edgar E. Iglesias | stackprot = 1;
|
911 | 5818dee5 | Edgar E. Iglesias | } |
912 | 5818dee5 | Edgar E. Iglesias | |
913 | 4acb54ba | Edgar E. Iglesias | *t = tcg_temp_new(); |
914 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]); |
915 | 5818dee5 | Edgar E. Iglesias | |
916 | 5818dee5 | Edgar E. Iglesias | if (stackprot) {
|
917 | 64254eba | Blue Swirl | gen_helper_stackprot(cpu_env, *t); |
918 | 5818dee5 | Edgar E. Iglesias | } |
919 | 4acb54ba | Edgar E. Iglesias | return t;
|
920 | 4acb54ba | Edgar E. Iglesias | } |
921 | 4acb54ba | Edgar E. Iglesias | /* Immediate. */
|
922 | 4acb54ba | Edgar E. Iglesias | if (!extimm) {
|
923 | 4acb54ba | Edgar E. Iglesias | if (dc->imm == 0) { |
924 | 4acb54ba | Edgar E. Iglesias | return &cpu_R[dc->ra];
|
925 | 4acb54ba | Edgar E. Iglesias | } |
926 | 4acb54ba | Edgar E. Iglesias | *t = tcg_temp_new(); |
927 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm)); |
928 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(*t, cpu_R[dc->ra], *t); |
929 | 4acb54ba | Edgar E. Iglesias | } else {
|
930 | 4acb54ba | Edgar E. Iglesias | *t = tcg_temp_new(); |
931 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
932 | 4acb54ba | Edgar E. Iglesias | } |
933 | 4acb54ba | Edgar E. Iglesias | |
934 | 5818dee5 | Edgar E. Iglesias | if (stackprot) {
|
935 | 64254eba | Blue Swirl | gen_helper_stackprot(cpu_env, *t); |
936 | 5818dee5 | Edgar E. Iglesias | } |
937 | 4acb54ba | Edgar E. Iglesias | return t;
|
938 | 4acb54ba | Edgar E. Iglesias | } |
939 | 4acb54ba | Edgar E. Iglesias | |
940 | 9f8beb66 | Edgar E. Iglesias | static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size) |
941 | 9f8beb66 | Edgar E. Iglesias | { |
942 | 9f8beb66 | Edgar E. Iglesias | if (size == 4) { |
943 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_bswap32_tl(dst, src); |
944 | 9f8beb66 | Edgar E. Iglesias | } else if (size == 2) { |
945 | 9f8beb66 | Edgar E. Iglesias | TCGv t = tcg_temp_new(); |
946 | 9f8beb66 | Edgar E. Iglesias | |
947 | 9f8beb66 | Edgar E. Iglesias | /* bswap16 assumes the high bits are zero. */
|
948 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_andi_tl(t, src, 0xffff);
|
949 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_bswap16_tl(dst, t); |
950 | 9f8beb66 | Edgar E. Iglesias | tcg_temp_free(t); |
951 | 9f8beb66 | Edgar E. Iglesias | } else {
|
952 | 9f8beb66 | Edgar E. Iglesias | /* Ignore.
|
953 | 9f8beb66 | Edgar E. Iglesias | cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
|
954 | 9f8beb66 | Edgar E. Iglesias | */
|
955 | 9f8beb66 | Edgar E. Iglesias | } |
956 | 9f8beb66 | Edgar E. Iglesias | } |
957 | 9f8beb66 | Edgar E. Iglesias | |
958 | 4acb54ba | Edgar E. Iglesias | static void dec_load(DisasContext *dc) |
959 | 4acb54ba | Edgar E. Iglesias | { |
960 | 4acb54ba | Edgar E. Iglesias | TCGv t, *addr; |
961 | 8cc9b43f | Peter A. G. Crosthwaite | unsigned int size, rev = 0, ex = 0; |
962 | 4acb54ba | Edgar E. Iglesias | |
963 | 4acb54ba | Edgar E. Iglesias | size = 1 << (dc->opcode & 3); |
964 | 9f8beb66 | Edgar E. Iglesias | |
965 | 9f8beb66 | Edgar E. Iglesias | if (!dc->type_b) {
|
966 | 9f8beb66 | Edgar E. Iglesias | rev = (dc->ir >> 9) & 1; |
967 | 8cc9b43f | Peter A. G. Crosthwaite | ex = (dc->ir >> 10) & 1; |
968 | 9f8beb66 | Edgar E. Iglesias | } |
969 | 9f8beb66 | Edgar E. Iglesias | |
970 | 0187688f | Edgar E. Iglesias | if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) |
971 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
|
972 | 0187688f | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
973 | 0187688f | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
974 | 0187688f | Edgar E. Iglesias | return;
|
975 | 0187688f | Edgar E. Iglesias | } |
976 | 4acb54ba | Edgar E. Iglesias | |
977 | 8cc9b43f | Peter A. G. Crosthwaite | LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", |
978 | 8cc9b43f | Peter A. G. Crosthwaite | ex ? "x" : ""); |
979 | 9f8beb66 | Edgar E. Iglesias | |
980 | 4acb54ba | Edgar E. Iglesias | t_sync_flags(dc); |
981 | 4acb54ba | Edgar E. Iglesias | addr = compute_ldst_addr(dc, &t); |
982 | 4acb54ba | Edgar E. Iglesias | |
983 | 9f8beb66 | Edgar E. Iglesias | /*
|
984 | 9f8beb66 | Edgar E. Iglesias | * When doing reverse accesses we need to do two things.
|
985 | 9f8beb66 | Edgar E. Iglesias | *
|
986 | 4ff9786c | Stefan Weil | * 1. Reverse the address wrt endianness.
|
987 | 9f8beb66 | Edgar E. Iglesias | * 2. Byteswap the data lanes on the way back into the CPU core.
|
988 | 9f8beb66 | Edgar E. Iglesias | */
|
989 | 9f8beb66 | Edgar E. Iglesias | if (rev && size != 4) { |
990 | 9f8beb66 | Edgar E. Iglesias | /* Endian reverse the address. t is addr. */
|
991 | 9f8beb66 | Edgar E. Iglesias | switch (size) {
|
992 | 9f8beb66 | Edgar E. Iglesias | case 1: |
993 | 9f8beb66 | Edgar E. Iglesias | { |
994 | 9f8beb66 | Edgar E. Iglesias | /* 00 -> 11
|
995 | 9f8beb66 | Edgar E. Iglesias | 01 -> 10
|
996 | 9f8beb66 | Edgar E. Iglesias | 10 -> 10
|
997 | 9f8beb66 | Edgar E. Iglesias | 11 -> 00 */
|
998 | 9f8beb66 | Edgar E. Iglesias | TCGv low = tcg_temp_new(); |
999 | 9f8beb66 | Edgar E. Iglesias | |
1000 | 9f8beb66 | Edgar E. Iglesias | /* Force addr into the temp. */
|
1001 | 9f8beb66 | Edgar E. Iglesias | if (addr != &t) {
|
1002 | 9f8beb66 | Edgar E. Iglesias | t = tcg_temp_new(); |
1003 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_mov_tl(t, *addr); |
1004 | 9f8beb66 | Edgar E. Iglesias | addr = &t; |
1005 | 9f8beb66 | Edgar E. Iglesias | } |
1006 | 9f8beb66 | Edgar E. Iglesias | |
1007 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_andi_tl(low, t, 3);
|
1008 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_sub_tl(low, tcg_const_tl(3), low);
|
1009 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_andi_tl(t, t, ~3);
|
1010 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_or_tl(t, t, low); |
1011 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_mov_tl(env_imm, t); |
1012 | 9f8beb66 | Edgar E. Iglesias | tcg_temp_free(low); |
1013 | 9f8beb66 | Edgar E. Iglesias | break;
|
1014 | 9f8beb66 | Edgar E. Iglesias | } |
1015 | 9f8beb66 | Edgar E. Iglesias | |
1016 | 9f8beb66 | Edgar E. Iglesias | case 2: |
1017 | 9f8beb66 | Edgar E. Iglesias | /* 00 -> 10
|
1018 | 9f8beb66 | Edgar E. Iglesias | 10 -> 00. */
|
1019 | 9f8beb66 | Edgar E. Iglesias | /* Force addr into the temp. */
|
1020 | 9f8beb66 | Edgar E. Iglesias | if (addr != &t) {
|
1021 | 9f8beb66 | Edgar E. Iglesias | t = tcg_temp_new(); |
1022 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_xori_tl(t, *addr, 2);
|
1023 | 9f8beb66 | Edgar E. Iglesias | addr = &t; |
1024 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1025 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_xori_tl(t, t, 2);
|
1026 | 9f8beb66 | Edgar E. Iglesias | } |
1027 | 9f8beb66 | Edgar E. Iglesias | break;
|
1028 | 9f8beb66 | Edgar E. Iglesias | default:
|
1029 | 9f8beb66 | Edgar E. Iglesias | cpu_abort(dc->env, "Invalid reverse size\n");
|
1030 | 9f8beb66 | Edgar E. Iglesias | break;
|
1031 | 9f8beb66 | Edgar E. Iglesias | } |
1032 | 9f8beb66 | Edgar E. Iglesias | } |
1033 | 9f8beb66 | Edgar E. Iglesias | |
1034 | 8cc9b43f | Peter A. G. Crosthwaite | /* lwx does not throw unaligned access errors, so force alignment */
|
1035 | 8cc9b43f | Peter A. G. Crosthwaite | if (ex) {
|
1036 | 8cc9b43f | Peter A. G. Crosthwaite | /* Force addr into the temp. */
|
1037 | 8cc9b43f | Peter A. G. Crosthwaite | if (addr != &t) {
|
1038 | 8cc9b43f | Peter A. G. Crosthwaite | t = tcg_temp_new(); |
1039 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_mov_tl(t, *addr); |
1040 | 8cc9b43f | Peter A. G. Crosthwaite | addr = &t; |
1041 | 8cc9b43f | Peter A. G. Crosthwaite | } |
1042 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_andi_tl(t, t, ~3);
|
1043 | 8cc9b43f | Peter A. G. Crosthwaite | } |
1044 | 8cc9b43f | Peter A. G. Crosthwaite | |
1045 | 4acb54ba | Edgar E. Iglesias | /* If we get a fault on a dslot, the jmpstate better be in sync. */
|
1046 | 4acb54ba | Edgar E. Iglesias | sync_jmpstate(dc); |
1047 | 968a40f6 | Edgar E. Iglesias | |
1048 | 968a40f6 | Edgar E. Iglesias | /* Verify alignment if needed. */
|
1049 | 968a40f6 | Edgar E. Iglesias | if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { |
1050 | a12f6507 | Edgar E. Iglesias | TCGv v = tcg_temp_new(); |
1051 | a12f6507 | Edgar E. Iglesias | |
1052 | a12f6507 | Edgar E. Iglesias | /*
|
1053 | a12f6507 | Edgar E. Iglesias | * Microblaze gives MMU faults priority over faults due to
|
1054 | a12f6507 | Edgar E. Iglesias | * unaligned addresses. That's why we speculatively do the load
|
1055 | a12f6507 | Edgar E. Iglesias | * into v. If the load succeeds, we verify alignment of the
|
1056 | a12f6507 | Edgar E. Iglesias | * address and if that succeeds we write into the destination reg.
|
1057 | a12f6507 | Edgar E. Iglesias | */
|
1058 | a12f6507 | Edgar E. Iglesias | gen_load(dc, v, *addr, size); |
1059 | a12f6507 | Edgar E. Iglesias | |
1060 | a12f6507 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); |
1061 | 64254eba | Blue Swirl | gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), |
1062 | 3aa80988 | Edgar E. Iglesias | tcg_const_tl(0), tcg_const_tl(size - 1)); |
1063 | 9f8beb66 | Edgar E. Iglesias | if (dc->rd) {
|
1064 | 9f8beb66 | Edgar E. Iglesias | if (rev) {
|
1065 | 9f8beb66 | Edgar E. Iglesias | dec_byteswap(dc, cpu_R[dc->rd], v, size); |
1066 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1067 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_R[dc->rd], v); |
1068 | 9f8beb66 | Edgar E. Iglesias | } |
1069 | 9f8beb66 | Edgar E. Iglesias | } |
1070 | a12f6507 | Edgar E. Iglesias | tcg_temp_free(v); |
1071 | 968a40f6 | Edgar E. Iglesias | } else {
|
1072 | a12f6507 | Edgar E. Iglesias | if (dc->rd) {
|
1073 | a12f6507 | Edgar E. Iglesias | gen_load(dc, cpu_R[dc->rd], *addr, size); |
1074 | 9f8beb66 | Edgar E. Iglesias | if (rev) {
|
1075 | 9f8beb66 | Edgar E. Iglesias | dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size); |
1076 | 9f8beb66 | Edgar E. Iglesias | } |
1077 | a12f6507 | Edgar E. Iglesias | } else {
|
1078 | 9f8beb66 | Edgar E. Iglesias | /* We are loading into r0, no need to reverse. */
|
1079 | a12f6507 | Edgar E. Iglesias | gen_load(dc, env_imm, *addr, size); |
1080 | a12f6507 | Edgar E. Iglesias | } |
1081 | 4acb54ba | Edgar E. Iglesias | } |
1082 | 4acb54ba | Edgar E. Iglesias | |
1083 | 8cc9b43f | Peter A. G. Crosthwaite | if (ex) { /* lwx */ |
1084 | 8cc9b43f | Peter A. G. Crosthwaite | /* no support for for AXI exclusive so always clear C */
|
1085 | 8cc9b43f | Peter A. G. Crosthwaite | write_carryi(dc, 0);
|
1086 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr)); |
1087 | 8cc9b43f | Peter A. G. Crosthwaite | } |
1088 | 8cc9b43f | Peter A. G. Crosthwaite | |
1089 | 4acb54ba | Edgar E. Iglesias | if (addr == &t)
|
1090 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t); |
1091 | 4acb54ba | Edgar E. Iglesias | } |
1092 | 4acb54ba | Edgar E. Iglesias | |
1093 | 4acb54ba | Edgar E. Iglesias | static void gen_store(DisasContext *dc, TCGv addr, TCGv val, |
1094 | 4acb54ba | Edgar E. Iglesias | unsigned int size) |
1095 | 4acb54ba | Edgar E. Iglesias | { |
1096 | 4acb54ba | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
1097 | 4acb54ba | Edgar E. Iglesias | |
1098 | 4acb54ba | Edgar E. Iglesias | if (size == 1) |
1099 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_st8(val, addr, mem_index); |
1100 | 4acb54ba | Edgar E. Iglesias | else if (size == 2) { |
1101 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_st16(val, addr, mem_index); |
1102 | 4acb54ba | Edgar E. Iglesias | } else if (size == 4) { |
1103 | 4acb54ba | Edgar E. Iglesias | tcg_gen_qemu_st32(val, addr, mem_index); |
1104 | 4acb54ba | Edgar E. Iglesias | } else
|
1105 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "Incorrect store size %d\n", size);
|
1106 | 4acb54ba | Edgar E. Iglesias | } |
1107 | 4acb54ba | Edgar E. Iglesias | |
1108 | 4acb54ba | Edgar E. Iglesias | static void dec_store(DisasContext *dc) |
1109 | 4acb54ba | Edgar E. Iglesias | { |
1110 | 083dbf48 | Peter A. G. Crosthwaite | TCGv t, *addr, swx_addr, r_check; |
1111 | 8cc9b43f | Peter A. G. Crosthwaite | int swx_skip = 0; |
1112 | 8cc9b43f | Peter A. G. Crosthwaite | unsigned int size, rev = 0, ex = 0; |
1113 | 4acb54ba | Edgar E. Iglesias | |
1114 | 4acb54ba | Edgar E. Iglesias | size = 1 << (dc->opcode & 3); |
1115 | 9f8beb66 | Edgar E. Iglesias | if (!dc->type_b) {
|
1116 | 9f8beb66 | Edgar E. Iglesias | rev = (dc->ir >> 9) & 1; |
1117 | 8cc9b43f | Peter A. G. Crosthwaite | ex = (dc->ir >> 10) & 1; |
1118 | 9f8beb66 | Edgar E. Iglesias | } |
1119 | 4acb54ba | Edgar E. Iglesias | |
1120 | 0187688f | Edgar E. Iglesias | if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) |
1121 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
|
1122 | 0187688f | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
1123 | 0187688f | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1124 | 0187688f | Edgar E. Iglesias | return;
|
1125 | 0187688f | Edgar E. Iglesias | } |
1126 | 0187688f | Edgar E. Iglesias | |
1127 | 8cc9b43f | Peter A. G. Crosthwaite | LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", |
1128 | 8cc9b43f | Peter A. G. Crosthwaite | ex ? "x" : ""); |
1129 | 4acb54ba | Edgar E. Iglesias | t_sync_flags(dc); |
1130 | 4acb54ba | Edgar E. Iglesias | /* If we get a fault on a dslot, the jmpstate better be in sync. */
|
1131 | 4acb54ba | Edgar E. Iglesias | sync_jmpstate(dc); |
1132 | 4acb54ba | Edgar E. Iglesias | addr = compute_ldst_addr(dc, &t); |
1133 | 968a40f6 | Edgar E. Iglesias | |
1134 | 083dbf48 | Peter A. G. Crosthwaite | r_check = tcg_temp_new(); |
1135 | 083dbf48 | Peter A. G. Crosthwaite | swx_addr = tcg_temp_local_new(); |
1136 | 8cc9b43f | Peter A. G. Crosthwaite | if (ex) { /* swx */ |
1137 | 8cc9b43f | Peter A. G. Crosthwaite | |
1138 | 8cc9b43f | Peter A. G. Crosthwaite | /* Force addr into the swx_addr. */
|
1139 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_mov_tl(swx_addr, *addr); |
1140 | 8cc9b43f | Peter A. G. Crosthwaite | addr = &swx_addr; |
1141 | 8cc9b43f | Peter A. G. Crosthwaite | /* swx does not throw unaligned access errors, so force alignment */
|
1142 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
|
1143 | 8cc9b43f | Peter A. G. Crosthwaite | |
1144 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr)); |
1145 | 8cc9b43f | Peter A. G. Crosthwaite | write_carryi(dc, 1);
|
1146 | 8cc9b43f | Peter A. G. Crosthwaite | swx_skip = gen_new_label(); |
1147 | 8cc9b43f | Peter A. G. Crosthwaite | tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip); |
1148 | 8cc9b43f | Peter A. G. Crosthwaite | write_carryi(dc, 0);
|
1149 | 8cc9b43f | Peter A. G. Crosthwaite | } |
1150 | 8cc9b43f | Peter A. G. Crosthwaite | |
1151 | 9f8beb66 | Edgar E. Iglesias | if (rev && size != 4) { |
1152 | 9f8beb66 | Edgar E. Iglesias | /* Endian reverse the address. t is addr. */
|
1153 | 9f8beb66 | Edgar E. Iglesias | switch (size) {
|
1154 | 9f8beb66 | Edgar E. Iglesias | case 1: |
1155 | 9f8beb66 | Edgar E. Iglesias | { |
1156 | 9f8beb66 | Edgar E. Iglesias | /* 00 -> 11
|
1157 | 9f8beb66 | Edgar E. Iglesias | 01 -> 10
|
1158 | 9f8beb66 | Edgar E. Iglesias | 10 -> 10
|
1159 | 9f8beb66 | Edgar E. Iglesias | 11 -> 00 */
|
1160 | 9f8beb66 | Edgar E. Iglesias | TCGv low = tcg_temp_new(); |
1161 | 9f8beb66 | Edgar E. Iglesias | |
1162 | 9f8beb66 | Edgar E. Iglesias | /* Force addr into the temp. */
|
1163 | 9f8beb66 | Edgar E. Iglesias | if (addr != &t) {
|
1164 | 9f8beb66 | Edgar E. Iglesias | t = tcg_temp_new(); |
1165 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_mov_tl(t, *addr); |
1166 | 9f8beb66 | Edgar E. Iglesias | addr = &t; |
1167 | 9f8beb66 | Edgar E. Iglesias | } |
1168 | 9f8beb66 | Edgar E. Iglesias | |
1169 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_andi_tl(low, t, 3);
|
1170 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_sub_tl(low, tcg_const_tl(3), low);
|
1171 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_andi_tl(t, t, ~3);
|
1172 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_or_tl(t, t, low); |
1173 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_mov_tl(env_imm, t); |
1174 | 9f8beb66 | Edgar E. Iglesias | tcg_temp_free(low); |
1175 | 9f8beb66 | Edgar E. Iglesias | break;
|
1176 | 9f8beb66 | Edgar E. Iglesias | } |
1177 | 9f8beb66 | Edgar E. Iglesias | |
1178 | 9f8beb66 | Edgar E. Iglesias | case 2: |
1179 | 9f8beb66 | Edgar E. Iglesias | /* 00 -> 10
|
1180 | 9f8beb66 | Edgar E. Iglesias | 10 -> 00. */
|
1181 | 9f8beb66 | Edgar E. Iglesias | /* Force addr into the temp. */
|
1182 | 9f8beb66 | Edgar E. Iglesias | if (addr != &t) {
|
1183 | 9f8beb66 | Edgar E. Iglesias | t = tcg_temp_new(); |
1184 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_xori_tl(t, *addr, 2);
|
1185 | 9f8beb66 | Edgar E. Iglesias | addr = &t; |
1186 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1187 | 9f8beb66 | Edgar E. Iglesias | tcg_gen_xori_tl(t, t, 2);
|
1188 | 9f8beb66 | Edgar E. Iglesias | } |
1189 | 9f8beb66 | Edgar E. Iglesias | break;
|
1190 | 9f8beb66 | Edgar E. Iglesias | default:
|
1191 | 9f8beb66 | Edgar E. Iglesias | cpu_abort(dc->env, "Invalid reverse size\n");
|
1192 | 9f8beb66 | Edgar E. Iglesias | break;
|
1193 | 9f8beb66 | Edgar E. Iglesias | } |
1194 | 9f8beb66 | Edgar E. Iglesias | |
1195 | 9f8beb66 | Edgar E. Iglesias | if (size != 1) { |
1196 | 9f8beb66 | Edgar E. Iglesias | TCGv bs_data = tcg_temp_new(); |
1197 | 9f8beb66 | Edgar E. Iglesias | dec_byteswap(dc, bs_data, cpu_R[dc->rd], size); |
1198 | 9f8beb66 | Edgar E. Iglesias | gen_store(dc, *addr, bs_data, size); |
1199 | 9f8beb66 | Edgar E. Iglesias | tcg_temp_free(bs_data); |
1200 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1201 | 9f8beb66 | Edgar E. Iglesias | gen_store(dc, *addr, cpu_R[dc->rd], size); |
1202 | 9f8beb66 | Edgar E. Iglesias | } |
1203 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1204 | 9f8beb66 | Edgar E. Iglesias | if (rev) {
|
1205 | 9f8beb66 | Edgar E. Iglesias | TCGv bs_data = tcg_temp_new(); |
1206 | 9f8beb66 | Edgar E. Iglesias | dec_byteswap(dc, bs_data, cpu_R[dc->rd], size); |
1207 | 9f8beb66 | Edgar E. Iglesias | gen_store(dc, *addr, bs_data, size); |
1208 | 9f8beb66 | Edgar E. Iglesias | tcg_temp_free(bs_data); |
1209 | 9f8beb66 | Edgar E. Iglesias | } else {
|
1210 | 9f8beb66 | Edgar E. Iglesias | gen_store(dc, *addr, cpu_R[dc->rd], size); |
1211 | 9f8beb66 | Edgar E. Iglesias | } |
1212 | 9f8beb66 | Edgar E. Iglesias | } |
1213 | a12f6507 | Edgar E. Iglesias | |
1214 | 968a40f6 | Edgar E. Iglesias | /* Verify alignment if needed. */
|
1215 | 968a40f6 | Edgar E. Iglesias | if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { |
1216 | a12f6507 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); |
1217 | a12f6507 | Edgar E. Iglesias | /* FIXME: if the alignment is wrong, we should restore the value
|
1218 | 4abf79a4 | Dong Xu Wang | * in memory. One possible way to achieve this is to probe
|
1219 | 9f8beb66 | Edgar E. Iglesias | * the MMU prior to the memaccess, thay way we could put
|
1220 | 9f8beb66 | Edgar E. Iglesias | * the alignment checks in between the probe and the mem
|
1221 | 9f8beb66 | Edgar E. Iglesias | * access.
|
1222 | a12f6507 | Edgar E. Iglesias | */
|
1223 | 64254eba | Blue Swirl | gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), |
1224 | 3aa80988 | Edgar E. Iglesias | tcg_const_tl(1), tcg_const_tl(size - 1)); |
1225 | 968a40f6 | Edgar E. Iglesias | } |
1226 | 083dbf48 | Peter A. G. Crosthwaite | |
1227 | 8cc9b43f | Peter A. G. Crosthwaite | if (ex) {
|
1228 | 8cc9b43f | Peter A. G. Crosthwaite | gen_set_label(swx_skip); |
1229 | 8cc9b43f | Peter A. G. Crosthwaite | } |
1230 | 083dbf48 | Peter A. G. Crosthwaite | tcg_temp_free(r_check); |
1231 | 083dbf48 | Peter A. G. Crosthwaite | tcg_temp_free(swx_addr); |
1232 | 968a40f6 | Edgar E. Iglesias | |
1233 | 4acb54ba | Edgar E. Iglesias | if (addr == &t)
|
1234 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t); |
1235 | 4acb54ba | Edgar E. Iglesias | } |
1236 | 4acb54ba | Edgar E. Iglesias | |
1237 | 4acb54ba | Edgar E. Iglesias | static inline void eval_cc(DisasContext *dc, unsigned int cc, |
1238 | 4acb54ba | Edgar E. Iglesias | TCGv d, TCGv a, TCGv b) |
1239 | 4acb54ba | Edgar E. Iglesias | { |
1240 | 4acb54ba | Edgar E. Iglesias | switch (cc) {
|
1241 | 4acb54ba | Edgar E. Iglesias | case CC_EQ:
|
1242 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b); |
1243 | 4acb54ba | Edgar E. Iglesias | break;
|
1244 | 4acb54ba | Edgar E. Iglesias | case CC_NE:
|
1245 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_NE, d, a, b); |
1246 | 4acb54ba | Edgar E. Iglesias | break;
|
1247 | 4acb54ba | Edgar E. Iglesias | case CC_LT:
|
1248 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_LT, d, a, b); |
1249 | 4acb54ba | Edgar E. Iglesias | break;
|
1250 | 4acb54ba | Edgar E. Iglesias | case CC_LE:
|
1251 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_LE, d, a, b); |
1252 | 4acb54ba | Edgar E. Iglesias | break;
|
1253 | 4acb54ba | Edgar E. Iglesias | case CC_GE:
|
1254 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_GE, d, a, b); |
1255 | 4acb54ba | Edgar E. Iglesias | break;
|
1256 | 4acb54ba | Edgar E. Iglesias | case CC_GT:
|
1257 | b2565c69 | Edgar E. Iglesias | tcg_gen_setcond_tl(TCG_COND_GT, d, a, b); |
1258 | 4acb54ba | Edgar E. Iglesias | break;
|
1259 | 4acb54ba | Edgar E. Iglesias | default:
|
1260 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
|
1261 | 4acb54ba | Edgar E. Iglesias | break;
|
1262 | 4acb54ba | Edgar E. Iglesias | } |
1263 | 4acb54ba | Edgar E. Iglesias | } |
1264 | 4acb54ba | Edgar E. Iglesias | |
1265 | 4acb54ba | Edgar E. Iglesias | static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false) |
1266 | 4acb54ba | Edgar E. Iglesias | { |
1267 | 4acb54ba | Edgar E. Iglesias | int l1;
|
1268 | 4acb54ba | Edgar E. Iglesias | |
1269 | 4acb54ba | Edgar E. Iglesias | l1 = gen_new_label(); |
1270 | 4acb54ba | Edgar E. Iglesias | /* Conditional jmp. */
|
1271 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false); |
1272 | 4acb54ba | Edgar E. Iglesias | tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
|
1273 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true); |
1274 | 4acb54ba | Edgar E. Iglesias | gen_set_label(l1); |
1275 | 4acb54ba | Edgar E. Iglesias | } |
1276 | 4acb54ba | Edgar E. Iglesias | |
1277 | 4acb54ba | Edgar E. Iglesias | static void dec_bcc(DisasContext *dc) |
1278 | 4acb54ba | Edgar E. Iglesias | { |
1279 | 4acb54ba | Edgar E. Iglesias | unsigned int cc; |
1280 | 4acb54ba | Edgar E. Iglesias | unsigned int dslot; |
1281 | 4acb54ba | Edgar E. Iglesias | |
1282 | 4acb54ba | Edgar E. Iglesias | cc = EXTRACT_FIELD(dc->ir, 21, 23); |
1283 | 4acb54ba | Edgar E. Iglesias | dslot = dc->ir & (1 << 25); |
1284 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm); |
1285 | 4acb54ba | Edgar E. Iglesias | |
1286 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = 1;
|
1287 | 4acb54ba | Edgar E. Iglesias | if (dslot) {
|
1288 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = 2;
|
1289 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= D_FLAG; |
1290 | 4acb54ba | Edgar E. Iglesias | tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), |
1291 | 68cee38a | Andreas Färber | cpu_env, offsetof(CPUMBState, bimm)); |
1292 | 4acb54ba | Edgar E. Iglesias | } |
1293 | 4acb54ba | Edgar E. Iglesias | |
1294 | 61204ce8 | Edgar E. Iglesias | if (dec_alu_op_b_is_small_imm(dc)) {
|
1295 | 61204ce8 | Edgar E. Iglesias | int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
|
1296 | 61204ce8 | Edgar E. Iglesias | |
1297 | 61204ce8 | Edgar E. Iglesias | tcg_gen_movi_tl(env_btarget, dc->pc + offset); |
1298 | 844bab60 | Edgar E. Iglesias | dc->jmp = JMP_DIRECT_CC; |
1299 | 23979dc5 | Edgar E. Iglesias | dc->jmp_pc = dc->pc + offset; |
1300 | 61204ce8 | Edgar E. Iglesias | } else {
|
1301 | 23979dc5 | Edgar E. Iglesias | dc->jmp = JMP_INDIRECT; |
1302 | 61204ce8 | Edgar E. Iglesias | tcg_gen_movi_tl(env_btarget, dc->pc); |
1303 | 61204ce8 | Edgar E. Iglesias | tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); |
1304 | 61204ce8 | Edgar E. Iglesias | } |
1305 | 61204ce8 | Edgar E. Iglesias | eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
|
1306 | 4acb54ba | Edgar E. Iglesias | } |
1307 | 4acb54ba | Edgar E. Iglesias | |
1308 | 4acb54ba | Edgar E. Iglesias | static void dec_br(DisasContext *dc) |
1309 | 4acb54ba | Edgar E. Iglesias | { |
1310 | 9f6113c7 | Edgar E. Iglesias | unsigned int dslot, link, abs, mbar; |
1311 | ff21f70a | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
1312 | 4acb54ba | Edgar E. Iglesias | |
1313 | 4acb54ba | Edgar E. Iglesias | dslot = dc->ir & (1 << 20); |
1314 | 4acb54ba | Edgar E. Iglesias | abs = dc->ir & (1 << 19); |
1315 | 4acb54ba | Edgar E. Iglesias | link = dc->ir & (1 << 18); |
1316 | 9f6113c7 | Edgar E. Iglesias | |
1317 | 9f6113c7 | Edgar E. Iglesias | /* Memory barrier. */
|
1318 | 9f6113c7 | Edgar E. Iglesias | mbar = (dc->ir >> 16) & 31; |
1319 | 9f6113c7 | Edgar E. Iglesias | if (mbar == 2 && dc->imm == 4) { |
1320 | 5d45de97 | Edgar E. Iglesias | /* mbar IMM & 16 decodes to sleep. */
|
1321 | 5d45de97 | Edgar E. Iglesias | if (dc->rd & 16) { |
1322 | 5d45de97 | Edgar E. Iglesias | TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT); |
1323 | 5d45de97 | Edgar E. Iglesias | TCGv_i32 tmp_1 = tcg_const_i32(1);
|
1324 | 5d45de97 | Edgar E. Iglesias | |
1325 | 5d45de97 | Edgar E. Iglesias | LOG_DIS("sleep\n");
|
1326 | 5d45de97 | Edgar E. Iglesias | |
1327 | 5d45de97 | Edgar E. Iglesias | t_sync_flags(dc); |
1328 | 5d45de97 | Edgar E. Iglesias | tcg_gen_st_i32(tmp_1, cpu_env, |
1329 | 5d45de97 | Edgar E. Iglesias | -offsetof(MicroBlazeCPU, env) |
1330 | 5d45de97 | Edgar E. Iglesias | +offsetof(CPUState, halted)); |
1331 | 5d45de97 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
|
1332 | 5d45de97 | Edgar E. Iglesias | gen_helper_raise_exception(cpu_env, tmp_hlt); |
1333 | 5d45de97 | Edgar E. Iglesias | tcg_temp_free_i32(tmp_hlt); |
1334 | 5d45de97 | Edgar E. Iglesias | tcg_temp_free_i32(tmp_1); |
1335 | 5d45de97 | Edgar E. Iglesias | return;
|
1336 | 5d45de97 | Edgar E. Iglesias | } |
1337 | 9f6113c7 | Edgar E. Iglesias | LOG_DIS("mbar %d\n", dc->rd);
|
1338 | 9f6113c7 | Edgar E. Iglesias | /* Break the TB. */
|
1339 | 9f6113c7 | Edgar E. Iglesias | dc->cpustate_changed = 1;
|
1340 | 9f6113c7 | Edgar E. Iglesias | return;
|
1341 | 9f6113c7 | Edgar E. Iglesias | } |
1342 | 9f6113c7 | Edgar E. Iglesias | |
1343 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("br%s%s%s%s imm=%x\n",
|
1344 | 4acb54ba | Edgar E. Iglesias | abs ? "a" : "", link ? "l" : "", |
1345 | 4acb54ba | Edgar E. Iglesias | dc->type_b ? "i" : "", dslot ? "d" : "", |
1346 | 4acb54ba | Edgar E. Iglesias | dc->imm); |
1347 | 4acb54ba | Edgar E. Iglesias | |
1348 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = 1;
|
1349 | 4acb54ba | Edgar E. Iglesias | if (dslot) {
|
1350 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = 2;
|
1351 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= D_FLAG; |
1352 | 4acb54ba | Edgar E. Iglesias | tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), |
1353 | 68cee38a | Andreas Färber | cpu_env, offsetof(CPUMBState, bimm)); |
1354 | 4acb54ba | Edgar E. Iglesias | } |
1355 | 4acb54ba | Edgar E. Iglesias | if (link && dc->rd)
|
1356 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); |
1357 | 4acb54ba | Edgar E. Iglesias | |
1358 | 4acb54ba | Edgar E. Iglesias | dc->jmp = JMP_INDIRECT; |
1359 | 4acb54ba | Edgar E. Iglesias | if (abs) {
|
1360 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_btaken, 1);
|
1361 | 4acb54ba | Edgar E. Iglesias | tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc))); |
1362 | ff21f70a | Edgar E. Iglesias | if (link && !dslot) {
|
1363 | ff21f70a | Edgar E. Iglesias | if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18)) |
1364 | ff21f70a | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_BREAK); |
1365 | ff21f70a | Edgar E. Iglesias | if (dc->imm == 0) { |
1366 | ff21f70a | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
|
1367 | ff21f70a | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
1368 | ff21f70a | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1369 | ff21f70a | Edgar E. Iglesias | return;
|
1370 | ff21f70a | Edgar E. Iglesias | } |
1371 | ff21f70a | Edgar E. Iglesias | |
1372 | ff21f70a | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_DEBUG); |
1373 | ff21f70a | Edgar E. Iglesias | } |
1374 | ff21f70a | Edgar E. Iglesias | } |
1375 | 4acb54ba | Edgar E. Iglesias | } else {
|
1376 | 61204ce8 | Edgar E. Iglesias | if (dec_alu_op_b_is_small_imm(dc)) {
|
1377 | 61204ce8 | Edgar E. Iglesias | dc->jmp = JMP_DIRECT; |
1378 | 61204ce8 | Edgar E. Iglesias | dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm); |
1379 | 61204ce8 | Edgar E. Iglesias | } else {
|
1380 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_btaken, 1);
|
1381 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_btarget, dc->pc); |
1382 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); |
1383 | 4acb54ba | Edgar E. Iglesias | } |
1384 | 4acb54ba | Edgar E. Iglesias | } |
1385 | 4acb54ba | Edgar E. Iglesias | } |
1386 | 4acb54ba | Edgar E. Iglesias | |
1387 | 4acb54ba | Edgar E. Iglesias | static inline void do_rti(DisasContext *dc) |
1388 | 4acb54ba | Edgar E. Iglesias | { |
1389 | 4acb54ba | Edgar E. Iglesias | TCGv t0, t1; |
1390 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
1391 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new(); |
1392 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
|
1393 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE); |
1394 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); |
1395 | 4acb54ba | Edgar E. Iglesias | |
1396 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); |
1397 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(t1, t1, t0); |
1398 | 4acb54ba | Edgar E. Iglesias | msr_write(dc, t1); |
1399 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t1); |
1400 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
1401 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags &= ~DRTI_FLAG; |
1402 | 4acb54ba | Edgar E. Iglesias | } |
1403 | 4acb54ba | Edgar E. Iglesias | |
1404 | 4acb54ba | Edgar E. Iglesias | static inline void do_rtb(DisasContext *dc) |
1405 | 4acb54ba | Edgar E. Iglesias | { |
1406 | 4acb54ba | Edgar E. Iglesias | TCGv t0, t1; |
1407 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
1408 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new(); |
1409 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP); |
1410 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_tl(t0, t1, 1);
|
1411 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); |
1412 | 4acb54ba | Edgar E. Iglesias | |
1413 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); |
1414 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(t1, t1, t0); |
1415 | 4acb54ba | Edgar E. Iglesias | msr_write(dc, t1); |
1416 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t1); |
1417 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
1418 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags &= ~DRTB_FLAG; |
1419 | 4acb54ba | Edgar E. Iglesias | } |
1420 | 4acb54ba | Edgar E. Iglesias | |
1421 | 4acb54ba | Edgar E. Iglesias | static inline void do_rte(DisasContext *dc) |
1422 | 4acb54ba | Edgar E. Iglesias | { |
1423 | 4acb54ba | Edgar E. Iglesias | TCGv t0, t1; |
1424 | 4acb54ba | Edgar E. Iglesias | t0 = tcg_temp_new(); |
1425 | 4acb54ba | Edgar E. Iglesias | t1 = tcg_temp_new(); |
1426 | 4acb54ba | Edgar E. Iglesias | |
1427 | 4acb54ba | Edgar E. Iglesias | tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE); |
1428 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t1, t1, ~MSR_EIP); |
1429 | 4acb54ba | Edgar E. Iglesias | tcg_gen_shri_tl(t0, t1, 1);
|
1430 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); |
1431 | 4acb54ba | Edgar E. Iglesias | |
1432 | 4acb54ba | Edgar E. Iglesias | tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); |
1433 | 4acb54ba | Edgar E. Iglesias | tcg_gen_or_tl(t1, t1, t0); |
1434 | 4acb54ba | Edgar E. Iglesias | msr_write(dc, t1); |
1435 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t1); |
1436 | 4acb54ba | Edgar E. Iglesias | tcg_temp_free(t0); |
1437 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags &= ~DRTE_FLAG; |
1438 | 4acb54ba | Edgar E. Iglesias | } |
1439 | 4acb54ba | Edgar E. Iglesias | |
1440 | 4acb54ba | Edgar E. Iglesias | static void dec_rts(DisasContext *dc) |
1441 | 4acb54ba | Edgar E. Iglesias | { |
1442 | 4acb54ba | Edgar E. Iglesias | unsigned int b_bit, i_bit, e_bit; |
1443 | 1567a005 | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
1444 | 4acb54ba | Edgar E. Iglesias | |
1445 | 4acb54ba | Edgar E. Iglesias | i_bit = dc->ir & (1 << 21); |
1446 | 4acb54ba | Edgar E. Iglesias | b_bit = dc->ir & (1 << 22); |
1447 | 4acb54ba | Edgar E. Iglesias | e_bit = dc->ir & (1 << 23); |
1448 | 4acb54ba | Edgar E. Iglesias | |
1449 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = 2;
|
1450 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= D_FLAG; |
1451 | 4acb54ba | Edgar E. Iglesias | tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), |
1452 | 68cee38a | Andreas Färber | cpu_env, offsetof(CPUMBState, bimm)); |
1453 | 4acb54ba | Edgar E. Iglesias | |
1454 | 4acb54ba | Edgar E. Iglesias | if (i_bit) {
|
1455 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("rtid ir=%x\n", dc->ir);
|
1456 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1457 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
1458 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
1459 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1460 | 1567a005 | Edgar E. Iglesias | } |
1461 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= DRTI_FLAG; |
1462 | 4acb54ba | Edgar E. Iglesias | } else if (b_bit) { |
1463 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("rtbd ir=%x\n", dc->ir);
|
1464 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1465 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
1466 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
1467 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1468 | 1567a005 | Edgar E. Iglesias | } |
1469 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= DRTB_FLAG; |
1470 | 4acb54ba | Edgar E. Iglesias | } else if (e_bit) { |
1471 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("rted ir=%x\n", dc->ir);
|
1472 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1473 | 1567a005 | Edgar E. Iglesias | && mem_index == MMU_USER_IDX) { |
1474 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
1475 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1476 | 1567a005 | Edgar E. Iglesias | } |
1477 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags |= DRTE_FLAG; |
1478 | 4acb54ba | Edgar E. Iglesias | } else
|
1479 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("rts ir=%x\n", dc->ir);
|
1480 | 4acb54ba | Edgar E. Iglesias | |
1481 | 23979dc5 | Edgar E. Iglesias | dc->jmp = JMP_INDIRECT; |
1482 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(env_btaken, 1);
|
1483 | 4acb54ba | Edgar E. Iglesias | tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc))); |
1484 | 4acb54ba | Edgar E. Iglesias | } |
1485 | 4acb54ba | Edgar E. Iglesias | |
1486 | 97694c57 | Edgar E. Iglesias | static int dec_check_fpuv2(DisasContext *dc) |
1487 | 97694c57 | Edgar E. Iglesias | { |
1488 | 97694c57 | Edgar E. Iglesias | int r;
|
1489 | 97694c57 | Edgar E. Iglesias | |
1490 | 97694c57 | Edgar E. Iglesias | r = dc->env->pvr.regs[2] & PVR2_USE_FPU2_MASK;
|
1491 | 97694c57 | Edgar E. Iglesias | |
1492 | 97694c57 | Edgar E. Iglesias | if (!r && (dc->tb_flags & MSR_EE_FLAG)) {
|
1493 | 97694c57 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU); |
1494 | 97694c57 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1495 | 97694c57 | Edgar E. Iglesias | } |
1496 | 97694c57 | Edgar E. Iglesias | return r;
|
1497 | 97694c57 | Edgar E. Iglesias | } |
1498 | 97694c57 | Edgar E. Iglesias | |
1499 | 1567a005 | Edgar E. Iglesias | static void dec_fpu(DisasContext *dc) |
1500 | 1567a005 | Edgar E. Iglesias | { |
1501 | 97694c57 | Edgar E. Iglesias | unsigned int fpu_insn; |
1502 | 97694c57 | Edgar E. Iglesias | |
1503 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1504 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
1505 | 1567a005 | Edgar E. Iglesias | && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
|
1506 | 97694c57 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
1507 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1508 | 1567a005 | Edgar E. Iglesias | return;
|
1509 | 1567a005 | Edgar E. Iglesias | } |
1510 | 1567a005 | Edgar E. Iglesias | |
1511 | 97694c57 | Edgar E. Iglesias | fpu_insn = (dc->ir >> 7) & 7; |
1512 | 97694c57 | Edgar E. Iglesias | |
1513 | 97694c57 | Edgar E. Iglesias | switch (fpu_insn) {
|
1514 | 97694c57 | Edgar E. Iglesias | case 0: |
1515 | 64254eba | Blue Swirl | gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], |
1516 | 64254eba | Blue Swirl | cpu_R[dc->rb]); |
1517 | 97694c57 | Edgar E. Iglesias | break;
|
1518 | 97694c57 | Edgar E. Iglesias | |
1519 | 97694c57 | Edgar E. Iglesias | case 1: |
1520 | 64254eba | Blue Swirl | gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], |
1521 | 64254eba | Blue Swirl | cpu_R[dc->rb]); |
1522 | 97694c57 | Edgar E. Iglesias | break;
|
1523 | 97694c57 | Edgar E. Iglesias | |
1524 | 97694c57 | Edgar E. Iglesias | case 2: |
1525 | 64254eba | Blue Swirl | gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], |
1526 | 64254eba | Blue Swirl | cpu_R[dc->rb]); |
1527 | 97694c57 | Edgar E. Iglesias | break;
|
1528 | 97694c57 | Edgar E. Iglesias | |
1529 | 97694c57 | Edgar E. Iglesias | case 3: |
1530 | 64254eba | Blue Swirl | gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra], |
1531 | 64254eba | Blue Swirl | cpu_R[dc->rb]); |
1532 | 97694c57 | Edgar E. Iglesias | break;
|
1533 | 97694c57 | Edgar E. Iglesias | |
1534 | 97694c57 | Edgar E. Iglesias | case 4: |
1535 | 97694c57 | Edgar E. Iglesias | switch ((dc->ir >> 4) & 7) { |
1536 | 97694c57 | Edgar E. Iglesias | case 0: |
1537 | 64254eba | Blue Swirl | gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env, |
1538 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1539 | 97694c57 | Edgar E. Iglesias | break;
|
1540 | 97694c57 | Edgar E. Iglesias | case 1: |
1541 | 64254eba | Blue Swirl | gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env, |
1542 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1543 | 97694c57 | Edgar E. Iglesias | break;
|
1544 | 97694c57 | Edgar E. Iglesias | case 2: |
1545 | 64254eba | Blue Swirl | gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env, |
1546 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1547 | 97694c57 | Edgar E. Iglesias | break;
|
1548 | 97694c57 | Edgar E. Iglesias | case 3: |
1549 | 64254eba | Blue Swirl | gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env, |
1550 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1551 | 97694c57 | Edgar E. Iglesias | break;
|
1552 | 97694c57 | Edgar E. Iglesias | case 4: |
1553 | 64254eba | Blue Swirl | gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env, |
1554 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1555 | 97694c57 | Edgar E. Iglesias | break;
|
1556 | 97694c57 | Edgar E. Iglesias | case 5: |
1557 | 64254eba | Blue Swirl | gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env, |
1558 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1559 | 97694c57 | Edgar E. Iglesias | break;
|
1560 | 97694c57 | Edgar E. Iglesias | case 6: |
1561 | 64254eba | Blue Swirl | gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env, |
1562 | 97694c57 | Edgar E. Iglesias | cpu_R[dc->ra], cpu_R[dc->rb]); |
1563 | 97694c57 | Edgar E. Iglesias | break;
|
1564 | 97694c57 | Edgar E. Iglesias | default:
|
1565 | 71547a3b | Blue Swirl | qemu_log_mask(LOG_UNIMP, |
1566 | 71547a3b | Blue Swirl | "unimplemented fcmp fpu_insn=%x pc=%x"
|
1567 | 71547a3b | Blue Swirl | " opc=%x\n",
|
1568 | 71547a3b | Blue Swirl | fpu_insn, dc->pc, dc->opcode); |
1569 | 97694c57 | Edgar E. Iglesias | dc->abort_at_next_insn = 1;
|
1570 | 97694c57 | Edgar E. Iglesias | break;
|
1571 | 97694c57 | Edgar E. Iglesias | } |
1572 | 97694c57 | Edgar E. Iglesias | break;
|
1573 | 97694c57 | Edgar E. Iglesias | |
1574 | 97694c57 | Edgar E. Iglesias | case 5: |
1575 | 97694c57 | Edgar E. Iglesias | if (!dec_check_fpuv2(dc)) {
|
1576 | 97694c57 | Edgar E. Iglesias | return;
|
1577 | 97694c57 | Edgar E. Iglesias | } |
1578 | 64254eba | Blue Swirl | gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); |
1579 | 97694c57 | Edgar E. Iglesias | break;
|
1580 | 97694c57 | Edgar E. Iglesias | |
1581 | 97694c57 | Edgar E. Iglesias | case 6: |
1582 | 97694c57 | Edgar E. Iglesias | if (!dec_check_fpuv2(dc)) {
|
1583 | 97694c57 | Edgar E. Iglesias | return;
|
1584 | 97694c57 | Edgar E. Iglesias | } |
1585 | 64254eba | Blue Swirl | gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); |
1586 | 97694c57 | Edgar E. Iglesias | break;
|
1587 | 97694c57 | Edgar E. Iglesias | |
1588 | 97694c57 | Edgar E. Iglesias | case 7: |
1589 | 97694c57 | Edgar E. Iglesias | if (!dec_check_fpuv2(dc)) {
|
1590 | 97694c57 | Edgar E. Iglesias | return;
|
1591 | 97694c57 | Edgar E. Iglesias | } |
1592 | 64254eba | Blue Swirl | gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]); |
1593 | 97694c57 | Edgar E. Iglesias | break;
|
1594 | 97694c57 | Edgar E. Iglesias | |
1595 | 97694c57 | Edgar E. Iglesias | default:
|
1596 | 71547a3b | Blue Swirl | qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x"
|
1597 | 71547a3b | Blue Swirl | " opc=%x\n",
|
1598 | 71547a3b | Blue Swirl | fpu_insn, dc->pc, dc->opcode); |
1599 | 97694c57 | Edgar E. Iglesias | dc->abort_at_next_insn = 1;
|
1600 | 97694c57 | Edgar E. Iglesias | break;
|
1601 | 97694c57 | Edgar E. Iglesias | } |
1602 | 1567a005 | Edgar E. Iglesias | } |
1603 | 1567a005 | Edgar E. Iglesias | |
1604 | 4acb54ba | Edgar E. Iglesias | static void dec_null(DisasContext *dc) |
1605 | 4acb54ba | Edgar E. Iglesias | { |
1606 | 02b33596 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1607 | 02b33596 | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
|
1608 | 02b33596 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
1609 | 02b33596 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1610 | 02b33596 | Edgar E. Iglesias | return;
|
1611 | 02b33596 | Edgar E. Iglesias | } |
1612 | 4acb54ba | Edgar E. Iglesias | qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
|
1613 | 4acb54ba | Edgar E. Iglesias | dc->abort_at_next_insn = 1;
|
1614 | 4acb54ba | Edgar E. Iglesias | } |
1615 | 4acb54ba | Edgar E. Iglesias | |
1616 | 6d76d23e | Edgar E. Iglesias | /* Insns connected to FSL or AXI stream attached devices. */
|
1617 | 6d76d23e | Edgar E. Iglesias | static void dec_stream(DisasContext *dc) |
1618 | 6d76d23e | Edgar E. Iglesias | { |
1619 | 6d76d23e | Edgar E. Iglesias | int mem_index = cpu_mmu_index(dc->env);
|
1620 | 6d76d23e | Edgar E. Iglesias | TCGv_i32 t_id, t_ctrl; |
1621 | 6d76d23e | Edgar E. Iglesias | int ctrl;
|
1622 | 6d76d23e | Edgar E. Iglesias | |
1623 | 6d76d23e | Edgar E. Iglesias | LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put", |
1624 | 6d76d23e | Edgar E. Iglesias | dc->type_b ? "" : "d", dc->imm); |
1625 | 6d76d23e | Edgar E. Iglesias | |
1626 | 6d76d23e | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
|
1627 | 6d76d23e | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); |
1628 | 6d76d23e | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1629 | 6d76d23e | Edgar E. Iglesias | return;
|
1630 | 6d76d23e | Edgar E. Iglesias | } |
1631 | 6d76d23e | Edgar E. Iglesias | |
1632 | 6d76d23e | Edgar E. Iglesias | t_id = tcg_temp_new(); |
1633 | 6d76d23e | Edgar E. Iglesias | if (dc->type_b) {
|
1634 | 6d76d23e | Edgar E. Iglesias | tcg_gen_movi_tl(t_id, dc->imm & 0xf);
|
1635 | 6d76d23e | Edgar E. Iglesias | ctrl = dc->imm >> 10;
|
1636 | 6d76d23e | Edgar E. Iglesias | } else {
|
1637 | 6d76d23e | Edgar E. Iglesias | tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
|
1638 | 6d76d23e | Edgar E. Iglesias | ctrl = dc->imm >> 5;
|
1639 | 6d76d23e | Edgar E. Iglesias | } |
1640 | 6d76d23e | Edgar E. Iglesias | |
1641 | 6d76d23e | Edgar E. Iglesias | t_ctrl = tcg_const_tl(ctrl); |
1642 | 6d76d23e | Edgar E. Iglesias | |
1643 | 6d76d23e | Edgar E. Iglesias | if (dc->rd == 0) { |
1644 | 6d76d23e | Edgar E. Iglesias | gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]); |
1645 | 6d76d23e | Edgar E. Iglesias | } else {
|
1646 | 6d76d23e | Edgar E. Iglesias | gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl); |
1647 | 6d76d23e | Edgar E. Iglesias | } |
1648 | 6d76d23e | Edgar E. Iglesias | tcg_temp_free(t_id); |
1649 | 6d76d23e | Edgar E. Iglesias | tcg_temp_free(t_ctrl); |
1650 | 6d76d23e | Edgar E. Iglesias | } |
1651 | 6d76d23e | Edgar E. Iglesias | |
1652 | 4acb54ba | Edgar E. Iglesias | static struct decoder_info { |
1653 | 4acb54ba | Edgar E. Iglesias | struct {
|
1654 | 4acb54ba | Edgar E. Iglesias | uint32_t bits; |
1655 | 4acb54ba | Edgar E. Iglesias | uint32_t mask; |
1656 | 4acb54ba | Edgar E. Iglesias | }; |
1657 | 4acb54ba | Edgar E. Iglesias | void (*dec)(DisasContext *dc);
|
1658 | 4acb54ba | Edgar E. Iglesias | } decinfo[] = { |
1659 | 4acb54ba | Edgar E. Iglesias | {DEC_ADD, dec_add}, |
1660 | 4acb54ba | Edgar E. Iglesias | {DEC_SUB, dec_sub}, |
1661 | 4acb54ba | Edgar E. Iglesias | {DEC_AND, dec_and}, |
1662 | 4acb54ba | Edgar E. Iglesias | {DEC_XOR, dec_xor}, |
1663 | 4acb54ba | Edgar E. Iglesias | {DEC_OR, dec_or}, |
1664 | 4acb54ba | Edgar E. Iglesias | {DEC_BIT, dec_bit}, |
1665 | 4acb54ba | Edgar E. Iglesias | {DEC_BARREL, dec_barrel}, |
1666 | 4acb54ba | Edgar E. Iglesias | {DEC_LD, dec_load}, |
1667 | 4acb54ba | Edgar E. Iglesias | {DEC_ST, dec_store}, |
1668 | 4acb54ba | Edgar E. Iglesias | {DEC_IMM, dec_imm}, |
1669 | 4acb54ba | Edgar E. Iglesias | {DEC_BR, dec_br}, |
1670 | 4acb54ba | Edgar E. Iglesias | {DEC_BCC, dec_bcc}, |
1671 | 4acb54ba | Edgar E. Iglesias | {DEC_RTS, dec_rts}, |
1672 | 1567a005 | Edgar E. Iglesias | {DEC_FPU, dec_fpu}, |
1673 | 4acb54ba | Edgar E. Iglesias | {DEC_MUL, dec_mul}, |
1674 | 4acb54ba | Edgar E. Iglesias | {DEC_DIV, dec_div}, |
1675 | 4acb54ba | Edgar E. Iglesias | {DEC_MSR, dec_msr}, |
1676 | 6d76d23e | Edgar E. Iglesias | {DEC_STREAM, dec_stream}, |
1677 | 4acb54ba | Edgar E. Iglesias | {{0, 0}, dec_null} |
1678 | 4acb54ba | Edgar E. Iglesias | }; |
1679 | 4acb54ba | Edgar E. Iglesias | |
1680 | 64254eba | Blue Swirl | static inline void decode(DisasContext *dc, uint32_t ir) |
1681 | 4acb54ba | Edgar E. Iglesias | { |
1682 | 4acb54ba | Edgar E. Iglesias | int i;
|
1683 | 4acb54ba | Edgar E. Iglesias | |
1684 | fdefe51c | Richard Henderson | if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
|
1685 | 4acb54ba | Edgar E. Iglesias | tcg_gen_debug_insn_start(dc->pc); |
1686 | fdefe51c | Richard Henderson | } |
1687 | 4acb54ba | Edgar E. Iglesias | |
1688 | 64254eba | Blue Swirl | dc->ir = ir; |
1689 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("%8.8x\t", dc->ir);
|
1690 | 4acb54ba | Edgar E. Iglesias | |
1691 | 4acb54ba | Edgar E. Iglesias | if (dc->ir)
|
1692 | 4acb54ba | Edgar E. Iglesias | dc->nr_nops = 0;
|
1693 | 4acb54ba | Edgar E. Iglesias | else {
|
1694 | 1567a005 | Edgar E. Iglesias | if ((dc->tb_flags & MSR_EE_FLAG)
|
1695 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
|
1696 | 97f90cbf | Edgar E. Iglesias | && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
|
1697 | 1567a005 | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); |
1698 | 1567a005 | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_HW_EXCP); |
1699 | 1567a005 | Edgar E. Iglesias | return;
|
1700 | 1567a005 | Edgar E. Iglesias | } |
1701 | 1567a005 | Edgar E. Iglesias | |
1702 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("nr_nops=%d\t", dc->nr_nops);
|
1703 | 4acb54ba | Edgar E. Iglesias | dc->nr_nops++; |
1704 | 4acb54ba | Edgar E. Iglesias | if (dc->nr_nops > 4) |
1705 | 4acb54ba | Edgar E. Iglesias | cpu_abort(dc->env, "fetching nop sequence\n");
|
1706 | 4acb54ba | Edgar E. Iglesias | } |
1707 | 4acb54ba | Edgar E. Iglesias | /* bit 2 seems to indicate insn type. */
|
1708 | 4acb54ba | Edgar E. Iglesias | dc->type_b = ir & (1 << 29); |
1709 | 4acb54ba | Edgar E. Iglesias | |
1710 | 4acb54ba | Edgar E. Iglesias | dc->opcode = EXTRACT_FIELD(ir, 26, 31); |
1711 | 4acb54ba | Edgar E. Iglesias | dc->rd = EXTRACT_FIELD(ir, 21, 25); |
1712 | 4acb54ba | Edgar E. Iglesias | dc->ra = EXTRACT_FIELD(ir, 16, 20); |
1713 | 4acb54ba | Edgar E. Iglesias | dc->rb = EXTRACT_FIELD(ir, 11, 15); |
1714 | 4acb54ba | Edgar E. Iglesias | dc->imm = EXTRACT_FIELD(ir, 0, 15); |
1715 | 4acb54ba | Edgar E. Iglesias | |
1716 | 4acb54ba | Edgar E. Iglesias | /* Large switch for all insns. */
|
1717 | 4acb54ba | Edgar E. Iglesias | for (i = 0; i < ARRAY_SIZE(decinfo); i++) { |
1718 | 4acb54ba | Edgar E. Iglesias | if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
|
1719 | 4acb54ba | Edgar E. Iglesias | decinfo[i].dec(dc); |
1720 | 4acb54ba | Edgar E. Iglesias | break;
|
1721 | 4acb54ba | Edgar E. Iglesias | } |
1722 | 4acb54ba | Edgar E. Iglesias | } |
1723 | 4acb54ba | Edgar E. Iglesias | } |
1724 | 4acb54ba | Edgar E. Iglesias | |
1725 | 68cee38a | Andreas Färber | static void check_breakpoint(CPUMBState *env, DisasContext *dc) |
1726 | 4acb54ba | Edgar E. Iglesias | { |
1727 | 4acb54ba | Edgar E. Iglesias | CPUBreakpoint *bp; |
1728 | 4acb54ba | Edgar E. Iglesias | |
1729 | 72cf2d4f | Blue Swirl | if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
|
1730 | 72cf2d4f | Blue Swirl | QTAILQ_FOREACH(bp, &env->breakpoints, entry) { |
1731 | 4acb54ba | Edgar E. Iglesias | if (bp->pc == dc->pc) {
|
1732 | 4acb54ba | Edgar E. Iglesias | t_gen_raise_exception(dc, EXCP_DEBUG); |
1733 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_UPDATE; |
1734 | 4acb54ba | Edgar E. Iglesias | } |
1735 | 4acb54ba | Edgar E. Iglesias | } |
1736 | 4acb54ba | Edgar E. Iglesias | } |
1737 | 4acb54ba | Edgar E. Iglesias | } |
1738 | 4acb54ba | Edgar E. Iglesias | |
1739 | 4acb54ba | Edgar E. Iglesias | /* generate intermediate code for basic block 'tb'. */
|
1740 | fd327f48 | Andreas Färber | static inline void |
1741 | 4a274212 | Andreas Färber | gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, |
1742 | 4a274212 | Andreas Färber | bool search_pc)
|
1743 | 4acb54ba | Edgar E. Iglesias | { |
1744 | ed2803da | Andreas Färber | CPUState *cs = CPU(cpu); |
1745 | 4a274212 | Andreas Färber | CPUMBState *env = &cpu->env; |
1746 | 4acb54ba | Edgar E. Iglesias | uint16_t *gen_opc_end; |
1747 | 4acb54ba | Edgar E. Iglesias | uint32_t pc_start; |
1748 | 4acb54ba | Edgar E. Iglesias | int j, lj;
|
1749 | 4acb54ba | Edgar E. Iglesias | struct DisasContext ctx;
|
1750 | 4acb54ba | Edgar E. Iglesias | struct DisasContext *dc = &ctx;
|
1751 | 4acb54ba | Edgar E. Iglesias | uint32_t next_page_start, org_flags; |
1752 | 4acb54ba | Edgar E. Iglesias | target_ulong npc; |
1753 | 4acb54ba | Edgar E. Iglesias | int num_insns;
|
1754 | 4acb54ba | Edgar E. Iglesias | int max_insns;
|
1755 | 4acb54ba | Edgar E. Iglesias | |
1756 | 4acb54ba | Edgar E. Iglesias | pc_start = tb->pc; |
1757 | 4acb54ba | Edgar E. Iglesias | dc->env = env; |
1758 | 4acb54ba | Edgar E. Iglesias | dc->tb = tb; |
1759 | 4acb54ba | Edgar E. Iglesias | org_flags = dc->synced_flags = dc->tb_flags = tb->flags; |
1760 | 4acb54ba | Edgar E. Iglesias | |
1761 | 92414b31 | Evgeny Voevodin | gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; |
1762 | 4acb54ba | Edgar E. Iglesias | |
1763 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_NEXT; |
1764 | 4acb54ba | Edgar E. Iglesias | dc->jmp = 0;
|
1765 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch = !!(dc->tb_flags & D_FLAG); |
1766 | 23979dc5 | Edgar E. Iglesias | if (dc->delayed_branch) {
|
1767 | 23979dc5 | Edgar E. Iglesias | dc->jmp = JMP_INDIRECT; |
1768 | 23979dc5 | Edgar E. Iglesias | } |
1769 | 4acb54ba | Edgar E. Iglesias | dc->pc = pc_start; |
1770 | ed2803da | Andreas Färber | dc->singlestep_enabled = cs->singlestep_enabled; |
1771 | 4acb54ba | Edgar E. Iglesias | dc->cpustate_changed = 0;
|
1772 | 4acb54ba | Edgar E. Iglesias | dc->abort_at_next_insn = 0;
|
1773 | 4acb54ba | Edgar E. Iglesias | dc->nr_nops = 0;
|
1774 | 4acb54ba | Edgar E. Iglesias | |
1775 | 4acb54ba | Edgar E. Iglesias | if (pc_start & 3) |
1776 | 4acb54ba | Edgar E. Iglesias | cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
|
1777 | 4acb54ba | Edgar E. Iglesias | |
1778 | 4acb54ba | Edgar E. Iglesias | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
1779 | 4acb54ba | Edgar E. Iglesias | #if !SIM_COMPAT
|
1780 | 4acb54ba | Edgar E. Iglesias | qemu_log("--------------\n");
|
1781 | a0762859 | Andreas Färber | log_cpu_state(CPU(cpu), 0);
|
1782 | 4acb54ba | Edgar E. Iglesias | #endif
|
1783 | 4acb54ba | Edgar E. Iglesias | } |
1784 | 4acb54ba | Edgar E. Iglesias | |
1785 | 4acb54ba | Edgar E. Iglesias | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
1786 | 4acb54ba | Edgar E. Iglesias | lj = -1;
|
1787 | 4acb54ba | Edgar E. Iglesias | num_insns = 0;
|
1788 | 4acb54ba | Edgar E. Iglesias | max_insns = tb->cflags & CF_COUNT_MASK; |
1789 | 4acb54ba | Edgar E. Iglesias | if (max_insns == 0) |
1790 | 4acb54ba | Edgar E. Iglesias | max_insns = CF_COUNT_MASK; |
1791 | 4acb54ba | Edgar E. Iglesias | |
1792 | 806f352d | Peter Maydell | gen_tb_start(); |
1793 | 4acb54ba | Edgar E. Iglesias | do
|
1794 | 4acb54ba | Edgar E. Iglesias | { |
1795 | 4acb54ba | Edgar E. Iglesias | #if SIM_COMPAT
|
1796 | 4acb54ba | Edgar E. Iglesias | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
1797 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); |
1798 | 4acb54ba | Edgar E. Iglesias | gen_helper_debug(); |
1799 | 4acb54ba | Edgar E. Iglesias | } |
1800 | 4acb54ba | Edgar E. Iglesias | #endif
|
1801 | 4acb54ba | Edgar E. Iglesias | check_breakpoint(env, dc); |
1802 | 4acb54ba | Edgar E. Iglesias | |
1803 | 4acb54ba | Edgar E. Iglesias | if (search_pc) {
|
1804 | 92414b31 | Evgeny Voevodin | j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; |
1805 | 4acb54ba | Edgar E. Iglesias | if (lj < j) {
|
1806 | 4acb54ba | Edgar E. Iglesias | lj++; |
1807 | 4acb54ba | Edgar E. Iglesias | while (lj < j)
|
1808 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj++] = 0;
|
1809 | 4acb54ba | Edgar E. Iglesias | } |
1810 | 25983cad | Evgeny Voevodin | tcg_ctx.gen_opc_pc[lj] = dc->pc; |
1811 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj] = 1;
|
1812 | c9c99c22 | Evgeny Voevodin | tcg_ctx.gen_opc_icount[lj] = num_insns; |
1813 | 4acb54ba | Edgar E. Iglesias | } |
1814 | 4acb54ba | Edgar E. Iglesias | |
1815 | 4acb54ba | Edgar E. Iglesias | /* Pretty disas. */
|
1816 | 4acb54ba | Edgar E. Iglesias | LOG_DIS("%8.8x:\t", dc->pc);
|
1817 | 4acb54ba | Edgar E. Iglesias | |
1818 | 4acb54ba | Edgar E. Iglesias | if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) |
1819 | 4acb54ba | Edgar E. Iglesias | gen_io_start(); |
1820 | 4acb54ba | Edgar E. Iglesias | |
1821 | 4acb54ba | Edgar E. Iglesias | dc->clear_imm = 1;
|
1822 | 64254eba | Blue Swirl | decode(dc, cpu_ldl_code(env, dc->pc)); |
1823 | 4acb54ba | Edgar E. Iglesias | if (dc->clear_imm)
|
1824 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags &= ~IMM_FLAG; |
1825 | 4acb54ba | Edgar E. Iglesias | dc->pc += 4;
|
1826 | 4acb54ba | Edgar E. Iglesias | num_insns++; |
1827 | 4acb54ba | Edgar E. Iglesias | |
1828 | 4acb54ba | Edgar E. Iglesias | if (dc->delayed_branch) {
|
1829 | 4acb54ba | Edgar E. Iglesias | dc->delayed_branch--; |
1830 | 4acb54ba | Edgar E. Iglesias | if (!dc->delayed_branch) {
|
1831 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags & DRTI_FLAG)
|
1832 | 4acb54ba | Edgar E. Iglesias | do_rti(dc); |
1833 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags & DRTB_FLAG)
|
1834 | 4acb54ba | Edgar E. Iglesias | do_rtb(dc); |
1835 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags & DRTE_FLAG)
|
1836 | 4acb54ba | Edgar E. Iglesias | do_rte(dc); |
1837 | 4acb54ba | Edgar E. Iglesias | /* Clear the delay slot flag. */
|
1838 | 4acb54ba | Edgar E. Iglesias | dc->tb_flags &= ~D_FLAG; |
1839 | 4acb54ba | Edgar E. Iglesias | /* If it is a direct jump, try direct chaining. */
|
1840 | 23979dc5 | Edgar E. Iglesias | if (dc->jmp == JMP_INDIRECT) {
|
1841 | 4acb54ba | Edgar E. Iglesias | eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc)); |
1842 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_JUMP; |
1843 | 23979dc5 | Edgar E. Iglesias | } else if (dc->jmp == JMP_DIRECT) { |
1844 | 844bab60 | Edgar E. Iglesias | t_sync_flags(dc); |
1845 | 844bab60 | Edgar E. Iglesias | gen_goto_tb(dc, 0, dc->jmp_pc);
|
1846 | 844bab60 | Edgar E. Iglesias | dc->is_jmp = DISAS_TB_JUMP; |
1847 | 844bab60 | Edgar E. Iglesias | } else if (dc->jmp == JMP_DIRECT_CC) { |
1848 | 23979dc5 | Edgar E. Iglesias | int l1;
|
1849 | 23979dc5 | Edgar E. Iglesias | |
1850 | 23979dc5 | Edgar E. Iglesias | t_sync_flags(dc); |
1851 | 23979dc5 | Edgar E. Iglesias | l1 = gen_new_label(); |
1852 | 23979dc5 | Edgar E. Iglesias | /* Conditional jmp. */
|
1853 | 23979dc5 | Edgar E. Iglesias | tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
|
1854 | 23979dc5 | Edgar E. Iglesias | gen_goto_tb(dc, 1, dc->pc);
|
1855 | 23979dc5 | Edgar E. Iglesias | gen_set_label(l1); |
1856 | 23979dc5 | Edgar E. Iglesias | gen_goto_tb(dc, 0, dc->jmp_pc);
|
1857 | 23979dc5 | Edgar E. Iglesias | |
1858 | 23979dc5 | Edgar E. Iglesias | dc->is_jmp = DISAS_TB_JUMP; |
1859 | 4acb54ba | Edgar E. Iglesias | } |
1860 | 4acb54ba | Edgar E. Iglesias | break;
|
1861 | 4acb54ba | Edgar E. Iglesias | } |
1862 | 4acb54ba | Edgar E. Iglesias | } |
1863 | ed2803da | Andreas Färber | if (cs->singlestep_enabled) {
|
1864 | 4acb54ba | Edgar E. Iglesias | break;
|
1865 | ed2803da | Andreas Färber | } |
1866 | 4acb54ba | Edgar E. Iglesias | } while (!dc->is_jmp && !dc->cpustate_changed
|
1867 | efd7f486 | Evgeny Voevodin | && tcg_ctx.gen_opc_ptr < gen_opc_end |
1868 | 4acb54ba | Edgar E. Iglesias | && !singlestep |
1869 | 4acb54ba | Edgar E. Iglesias | && (dc->pc < next_page_start) |
1870 | 4acb54ba | Edgar E. Iglesias | && num_insns < max_insns); |
1871 | 4acb54ba | Edgar E. Iglesias | |
1872 | 4acb54ba | Edgar E. Iglesias | npc = dc->pc; |
1873 | 844bab60 | Edgar E. Iglesias | if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
|
1874 | 4acb54ba | Edgar E. Iglesias | if (dc->tb_flags & D_FLAG) {
|
1875 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_UPDATE; |
1876 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], npc); |
1877 | 4acb54ba | Edgar E. Iglesias | sync_jmpstate(dc); |
1878 | 4acb54ba | Edgar E. Iglesias | } else
|
1879 | 4acb54ba | Edgar E. Iglesias | npc = dc->jmp_pc; |
1880 | 4acb54ba | Edgar E. Iglesias | } |
1881 | 4acb54ba | Edgar E. Iglesias | |
1882 | 4acb54ba | Edgar E. Iglesias | if (tb->cflags & CF_LAST_IO)
|
1883 | 4acb54ba | Edgar E. Iglesias | gen_io_end(); |
1884 | 4acb54ba | Edgar E. Iglesias | /* Force an update if the per-tb cpu state has changed. */
|
1885 | 4acb54ba | Edgar E. Iglesias | if (dc->is_jmp == DISAS_NEXT
|
1886 | 4acb54ba | Edgar E. Iglesias | && (dc->cpustate_changed || org_flags != dc->tb_flags)) { |
1887 | 4acb54ba | Edgar E. Iglesias | dc->is_jmp = DISAS_UPDATE; |
1888 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], npc); |
1889 | 4acb54ba | Edgar E. Iglesias | } |
1890 | 4acb54ba | Edgar E. Iglesias | t_sync_flags(dc); |
1891 | 4acb54ba | Edgar E. Iglesias | |
1892 | ed2803da | Andreas Färber | if (unlikely(cs->singlestep_enabled)) {
|
1893 | 6c5f738d | Edgar E. Iglesias | TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); |
1894 | 6c5f738d | Edgar E. Iglesias | |
1895 | 6c5f738d | Edgar E. Iglesias | if (dc->is_jmp != DISAS_JUMP) {
|
1896 | 4acb54ba | Edgar E. Iglesias | tcg_gen_movi_tl(cpu_SR[SR_PC], npc); |
1897 | 6c5f738d | Edgar E. Iglesias | } |
1898 | 64254eba | Blue Swirl | gen_helper_raise_exception(cpu_env, tmp); |
1899 | 6c5f738d | Edgar E. Iglesias | tcg_temp_free_i32(tmp); |
1900 | 4acb54ba | Edgar E. Iglesias | } else {
|
1901 | 4acb54ba | Edgar E. Iglesias | switch(dc->is_jmp) {
|
1902 | 4acb54ba | Edgar E. Iglesias | case DISAS_NEXT:
|
1903 | 4acb54ba | Edgar E. Iglesias | gen_goto_tb(dc, 1, npc);
|
1904 | 4acb54ba | Edgar E. Iglesias | break;
|
1905 | 4acb54ba | Edgar E. Iglesias | default:
|
1906 | 4acb54ba | Edgar E. Iglesias | case DISAS_JUMP:
|
1907 | 4acb54ba | Edgar E. Iglesias | case DISAS_UPDATE:
|
1908 | 4acb54ba | Edgar E. Iglesias | /* indicate that the hash table must be used
|
1909 | 4acb54ba | Edgar E. Iglesias | to find the next TB */
|
1910 | 4acb54ba | Edgar E. Iglesias | tcg_gen_exit_tb(0);
|
1911 | 4acb54ba | Edgar E. Iglesias | break;
|
1912 | 4acb54ba | Edgar E. Iglesias | case DISAS_TB_JUMP:
|
1913 | 4acb54ba | Edgar E. Iglesias | /* nothing more to generate */
|
1914 | 4acb54ba | Edgar E. Iglesias | break;
|
1915 | 4acb54ba | Edgar E. Iglesias | } |
1916 | 4acb54ba | Edgar E. Iglesias | } |
1917 | 806f352d | Peter Maydell | gen_tb_end(tb, num_insns); |
1918 | efd7f486 | Evgeny Voevodin | *tcg_ctx.gen_opc_ptr = INDEX_op_end; |
1919 | 4acb54ba | Edgar E. Iglesias | if (search_pc) {
|
1920 | 92414b31 | Evgeny Voevodin | j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; |
1921 | 4acb54ba | Edgar E. Iglesias | lj++; |
1922 | 4acb54ba | Edgar E. Iglesias | while (lj <= j)
|
1923 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj++] = 0;
|
1924 | 4acb54ba | Edgar E. Iglesias | } else {
|
1925 | 4acb54ba | Edgar E. Iglesias | tb->size = dc->pc - pc_start; |
1926 | 4acb54ba | Edgar E. Iglesias | tb->icount = num_insns; |
1927 | 4acb54ba | Edgar E. Iglesias | } |
1928 | 4acb54ba | Edgar E. Iglesias | |
1929 | 4acb54ba | Edgar E. Iglesias | #ifdef DEBUG_DISAS
|
1930 | 4acb54ba | Edgar E. Iglesias | #if !SIM_COMPAT
|
1931 | 4acb54ba | Edgar E. Iglesias | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
1932 | 4acb54ba | Edgar E. Iglesias | qemu_log("\n");
|
1933 | 4acb54ba | Edgar E. Iglesias | #if DISAS_GNU
|
1934 | f4359b9f | Blue Swirl | log_target_disas(env, pc_start, dc->pc - pc_start, 0);
|
1935 | 4acb54ba | Edgar E. Iglesias | #endif
|
1936 | e6aa0f11 | Stefan Weil | qemu_log("\nisize=%d osize=%td\n",
|
1937 | 92414b31 | Evgeny Voevodin | dc->pc - pc_start, tcg_ctx.gen_opc_ptr - |
1938 | 92414b31 | Evgeny Voevodin | tcg_ctx.gen_opc_buf); |
1939 | 4acb54ba | Edgar E. Iglesias | } |
1940 | 4acb54ba | Edgar E. Iglesias | #endif
|
1941 | 4acb54ba | Edgar E. Iglesias | #endif
|
1942 | 4acb54ba | Edgar E. Iglesias | assert(!dc->abort_at_next_insn); |
1943 | 4acb54ba | Edgar E. Iglesias | } |
1944 | 4acb54ba | Edgar E. Iglesias | |
1945 | 68cee38a | Andreas Färber | void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb) |
1946 | 4acb54ba | Edgar E. Iglesias | { |
1947 | 4a274212 | Andreas Färber | gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false);
|
1948 | 4acb54ba | Edgar E. Iglesias | } |
1949 | 4acb54ba | Edgar E. Iglesias | |
1950 | 68cee38a | Andreas Färber | void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb) |
1951 | 4acb54ba | Edgar E. Iglesias | { |
1952 | 4a274212 | Andreas Färber | gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true);
|
1953 | 4acb54ba | Edgar E. Iglesias | } |
1954 | 4acb54ba | Edgar E. Iglesias | |
1955 | 878096ee | Andreas Färber | void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
1956 | 878096ee | Andreas Färber | int flags)
|
1957 | 4acb54ba | Edgar E. Iglesias | { |
1958 | 878096ee | Andreas Färber | MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); |
1959 | 878096ee | Andreas Färber | CPUMBState *env = &cpu->env; |
1960 | 4acb54ba | Edgar E. Iglesias | int i;
|
1961 | 4acb54ba | Edgar E. Iglesias | |
1962 | 4acb54ba | Edgar E. Iglesias | if (!env || !f)
|
1963 | 4acb54ba | Edgar E. Iglesias | return;
|
1964 | 4acb54ba | Edgar E. Iglesias | |
1965 | 4acb54ba | Edgar E. Iglesias | cpu_fprintf(f, "IN: PC=%x %s\n",
|
1966 | 4acb54ba | Edgar E. Iglesias | env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); |
1967 | 97694c57 | Edgar E. Iglesias | cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n",
|
1968 | 4c24aa0a | Michal Simek | env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], |
1969 | 97694c57 | Edgar E. Iglesias | env->debug, env->imm, env->iflags, env->sregs[SR_FSR]); |
1970 | 17c52a43 | Edgar E. Iglesias | cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
|
1971 | 4acb54ba | Edgar E. Iglesias | env->btaken, env->btarget, |
1972 | 4acb54ba | Edgar E. Iglesias | (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", |
1973 | 17c52a43 | Edgar E. Iglesias | (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", |
1974 | 17c52a43 | Edgar E. Iglesias | (env->sregs[SR_MSR] & MSR_EIP), |
1975 | 17c52a43 | Edgar E. Iglesias | (env->sregs[SR_MSR] & MSR_IE)); |
1976 | 17c52a43 | Edgar E. Iglesias | |
1977 | 4acb54ba | Edgar E. Iglesias | for (i = 0; i < 32; i++) { |
1978 | 4acb54ba | Edgar E. Iglesias | cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
|
1979 | 4acb54ba | Edgar E. Iglesias | if ((i + 1) % 4 == 0) |
1980 | 4acb54ba | Edgar E. Iglesias | cpu_fprintf(f, "\n");
|
1981 | 4acb54ba | Edgar E. Iglesias | } |
1982 | 4acb54ba | Edgar E. Iglesias | cpu_fprintf(f, "\n\n");
|
1983 | 4acb54ba | Edgar E. Iglesias | } |
1984 | 4acb54ba | Edgar E. Iglesias | |
1985 | b33ab1f7 | Andreas Färber | MicroBlazeCPU *cpu_mb_init(const char *cpu_model) |
1986 | 4acb54ba | Edgar E. Iglesias | { |
1987 | b77f98ca | Andreas Färber | MicroBlazeCPU *cpu; |
1988 | 4acb54ba | Edgar E. Iglesias | |
1989 | b77f98ca | Andreas Färber | cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); |
1990 | 4acb54ba | Edgar E. Iglesias | |
1991 | 746b03b2 | Andreas Färber | object_property_set_bool(OBJECT(cpu), true, "realized", NULL); |
1992 | 4acb54ba | Edgar E. Iglesias | |
1993 | cd0c24f9 | Andreas Färber | return cpu;
|
1994 | cd0c24f9 | Andreas Färber | } |
1995 | 4acb54ba | Edgar E. Iglesias | |
1996 | cd0c24f9 | Andreas Färber | void mb_tcg_init(void) |
1997 | cd0c24f9 | Andreas Färber | { |
1998 | cd0c24f9 | Andreas Färber | int i;
|
1999 | 4acb54ba | Edgar E. Iglesias | |
2000 | 4acb54ba | Edgar E. Iglesias | cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
2001 | 4acb54ba | Edgar E. Iglesias | |
2002 | 4acb54ba | Edgar E. Iglesias | env_debug = tcg_global_mem_new(TCG_AREG0, |
2003 | 68cee38a | Andreas Färber | offsetof(CPUMBState, debug), |
2004 | 4acb54ba | Edgar E. Iglesias | "debug0");
|
2005 | 4acb54ba | Edgar E. Iglesias | env_iflags = tcg_global_mem_new(TCG_AREG0, |
2006 | 68cee38a | Andreas Färber | offsetof(CPUMBState, iflags), |
2007 | 4acb54ba | Edgar E. Iglesias | "iflags");
|
2008 | 4acb54ba | Edgar E. Iglesias | env_imm = tcg_global_mem_new(TCG_AREG0, |
2009 | 68cee38a | Andreas Färber | offsetof(CPUMBState, imm), |
2010 | 4acb54ba | Edgar E. Iglesias | "imm");
|
2011 | 4acb54ba | Edgar E. Iglesias | env_btarget = tcg_global_mem_new(TCG_AREG0, |
2012 | 68cee38a | Andreas Färber | offsetof(CPUMBState, btarget), |
2013 | 4acb54ba | Edgar E. Iglesias | "btarget");
|
2014 | 4acb54ba | Edgar E. Iglesias | env_btaken = tcg_global_mem_new(TCG_AREG0, |
2015 | 68cee38a | Andreas Färber | offsetof(CPUMBState, btaken), |
2016 | 4acb54ba | Edgar E. Iglesias | "btaken");
|
2017 | 4acb54ba | Edgar E. Iglesias | for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { |
2018 | 4acb54ba | Edgar E. Iglesias | cpu_R[i] = tcg_global_mem_new(TCG_AREG0, |
2019 | 68cee38a | Andreas Färber | offsetof(CPUMBState, regs[i]), |
2020 | 4acb54ba | Edgar E. Iglesias | regnames[i]); |
2021 | 4acb54ba | Edgar E. Iglesias | } |
2022 | 4acb54ba | Edgar E. Iglesias | for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) { |
2023 | 4acb54ba | Edgar E. Iglesias | cpu_SR[i] = tcg_global_mem_new(TCG_AREG0, |
2024 | 68cee38a | Andreas Färber | offsetof(CPUMBState, sregs[i]), |
2025 | 4acb54ba | Edgar E. Iglesias | special_regnames[i]); |
2026 | 4acb54ba | Edgar E. Iglesias | } |
2027 | 4acb54ba | Edgar E. Iglesias | #define GEN_HELPER 2 |
2028 | 4acb54ba | Edgar E. Iglesias | #include "helper.h" |
2029 | 4acb54ba | Edgar E. Iglesias | } |
2030 | 4acb54ba | Edgar E. Iglesias | |
2031 | 68cee38a | Andreas Färber | void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos) |
2032 | 4acb54ba | Edgar E. Iglesias | { |
2033 | 25983cad | Evgeny Voevodin | env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos]; |
2034 | 4acb54ba | Edgar E. Iglesias | } |