root / target-cris / translate.c @ 7fd2592d
History | View | Annotate | Download (93.6 kB)
1 | 8170028d | ths | /*
|
---|---|---|---|
2 | 8170028d | ths | * CRIS emulation for qemu: main translation routines.
|
3 | 8170028d | ths | *
|
4 | 05ba7d5f | edgar_igl | * Copyright (c) 2008 AXIS Communications AB
|
5 | 8170028d | ths | * Written by Edgar E. Iglesias.
|
6 | 8170028d | ths | *
|
7 | 8170028d | ths | * This library is free software; you can redistribute it and/or
|
8 | 8170028d | ths | * modify it under the terms of the GNU Lesser General Public
|
9 | 8170028d | ths | * License as published by the Free Software Foundation; either
|
10 | 8170028d | ths | * version 2 of the License, or (at your option) any later version.
|
11 | 8170028d | ths | *
|
12 | 8170028d | ths | * This library is distributed in the hope that it will be useful,
|
13 | 8170028d | ths | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 8170028d | ths | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | 8170028d | ths | * Lesser General Public License for more details.
|
16 | 8170028d | ths | *
|
17 | 8170028d | ths | * 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 | 8170028d | ths | */
|
20 | 8170028d | ths | |
21 | b41f7df0 | edgar_igl | /*
|
22 | b41f7df0 | edgar_igl | * FIXME:
|
23 | cf1d97f0 | edgar_igl | * The condition code translation is in need of attention.
|
24 | b41f7df0 | edgar_igl | */
|
25 | b41f7df0 | edgar_igl | |
26 | 8170028d | ths | #include "cpu.h" |
27 | 76cad711 | Paolo Bonzini | #include "disas/disas.h" |
28 | 57fec1fe | bellard | #include "tcg-op.h" |
29 | 05ba7d5f | edgar_igl | #include "helper.h" |
30 | 52819664 | edgar_igl | #include "mmu.h" |
31 | 8170028d | ths | #include "crisv32-decode.h" |
32 | 8170028d | ths | |
33 | a7812ae4 | pbrook | #define GEN_HELPER 1 |
34 | a7812ae4 | pbrook | #include "helper.h" |
35 | a7812ae4 | pbrook | |
36 | 8170028d | ths | #define DISAS_CRIS 0 |
37 | 8170028d | ths | #if DISAS_CRIS
|
38 | 93fcfe39 | aliguori | # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) |
39 | 8170028d | ths | #else
|
40 | d12d51d5 | aliguori | # define LOG_DIS(...) do { } while (0) |
41 | 8170028d | ths | #endif
|
42 | 8170028d | ths | |
43 | b41f7df0 | edgar_igl | #define D(x)
|
44 | 8170028d | ths | #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
|
45 | 8170028d | ths | #define BUG_ON(x) ({if (x) BUG();}) |
46 | 8170028d | ths | |
47 | 4f400ab5 | edgar_igl | #define DISAS_SWI 5 |
48 | 4f400ab5 | edgar_igl | |
49 | 8170028d | ths | /* Used by the decoder. */
|
50 | 8170028d | ths | #define EXTRACT_FIELD(src, start, end) \
|
51 | 8170028d | ths | (((src) >> start) & ((1 << (end - start + 1)) - 1)) |
52 | 8170028d | ths | |
53 | 8170028d | ths | #define CC_MASK_NZ 0xc |
54 | 8170028d | ths | #define CC_MASK_NZV 0xe |
55 | 8170028d | ths | #define CC_MASK_NZVC 0xf |
56 | 8170028d | ths | #define CC_MASK_RNZV 0x10e |
57 | 8170028d | ths | |
58 | a7812ae4 | pbrook | static TCGv_ptr cpu_env;
|
59 | 9b32fbf8 | edgar_igl | static TCGv cpu_R[16]; |
60 | 9b32fbf8 | edgar_igl | static TCGv cpu_PR[16]; |
61 | 9b32fbf8 | edgar_igl | static TCGv cc_x;
|
62 | 9b32fbf8 | edgar_igl | static TCGv cc_src;
|
63 | 9b32fbf8 | edgar_igl | static TCGv cc_dest;
|
64 | 9b32fbf8 | edgar_igl | static TCGv cc_result;
|
65 | 9b32fbf8 | edgar_igl | static TCGv cc_op;
|
66 | 9b32fbf8 | edgar_igl | static TCGv cc_size;
|
67 | 9b32fbf8 | edgar_igl | static TCGv cc_mask;
|
68 | 9b32fbf8 | edgar_igl | |
69 | 9b32fbf8 | edgar_igl | static TCGv env_btaken;
|
70 | 9b32fbf8 | edgar_igl | static TCGv env_btarget;
|
71 | 9b32fbf8 | edgar_igl | static TCGv env_pc;
|
72 | b41f7df0 | edgar_igl | |
73 | 022c62cb | Paolo Bonzini | #include "exec/gen-icount.h" |
74 | 2e70f6ef | pbrook | |
75 | 8170028d | ths | /* This is the state at translation time. */
|
76 | 8170028d | ths | typedef struct DisasContext { |
77 | 7b5eff4d | Evgeny Voevodin | CPUCRISState *env; |
78 | 7b5eff4d | Evgeny Voevodin | target_ulong pc, ppc; |
79 | 8170028d | ths | |
80 | 7b5eff4d | Evgeny Voevodin | /* Decoder. */
|
81 | cf7e0c80 | Aurelien Jarno | unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc); |
82 | 7b5eff4d | Evgeny Voevodin | uint32_t ir; |
83 | 7b5eff4d | Evgeny Voevodin | uint32_t opcode; |
84 | 7b5eff4d | Evgeny Voevodin | unsigned int op1; |
85 | 7b5eff4d | Evgeny Voevodin | unsigned int op2; |
86 | 7b5eff4d | Evgeny Voevodin | unsigned int zsize, zzsize; |
87 | 7b5eff4d | Evgeny Voevodin | unsigned int mode; |
88 | 7b5eff4d | Evgeny Voevodin | unsigned int postinc; |
89 | 7b5eff4d | Evgeny Voevodin | |
90 | 7b5eff4d | Evgeny Voevodin | unsigned int size; |
91 | 7b5eff4d | Evgeny Voevodin | unsigned int src; |
92 | 7b5eff4d | Evgeny Voevodin | unsigned int dst; |
93 | 7b5eff4d | Evgeny Voevodin | unsigned int cond; |
94 | 7b5eff4d | Evgeny Voevodin | |
95 | 7b5eff4d | Evgeny Voevodin | int update_cc;
|
96 | 7b5eff4d | Evgeny Voevodin | int cc_op;
|
97 | 7b5eff4d | Evgeny Voevodin | int cc_size;
|
98 | 7b5eff4d | Evgeny Voevodin | uint32_t cc_mask; |
99 | 7b5eff4d | Evgeny Voevodin | |
100 | 7b5eff4d | Evgeny Voevodin | int cc_size_uptodate; /* -1 invalid or last written value. */ |
101 | 7b5eff4d | Evgeny Voevodin | |
102 | 7b5eff4d | Evgeny Voevodin | int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate. */ |
103 | 7b5eff4d | Evgeny Voevodin | int flags_uptodate; /* Wether or not $ccs is uptodate. */ |
104 | 7b5eff4d | Evgeny Voevodin | int flagx_known; /* Wether or not flags_x has the x flag known at |
105 | 7b5eff4d | Evgeny Voevodin | translation time. */
|
106 | 7b5eff4d | Evgeny Voevodin | int flags_x;
|
107 | 7b5eff4d | Evgeny Voevodin | |
108 | 7b5eff4d | Evgeny Voevodin | int clear_x; /* Clear x after this insn? */ |
109 | 7b5eff4d | Evgeny Voevodin | int clear_prefix; /* Clear prefix after this insn? */ |
110 | 7b5eff4d | Evgeny Voevodin | int clear_locked_irq; /* Clear the irq lockout. */ |
111 | 7b5eff4d | Evgeny Voevodin | int cpustate_changed;
|
112 | 7b5eff4d | Evgeny Voevodin | unsigned int tb_flags; /* tb dependent flags. */ |
113 | 7b5eff4d | Evgeny Voevodin | int is_jmp;
|
114 | 8170028d | ths | |
115 | 5cabc5cc | Edgar E. Iglesias | #define JMP_NOJMP 0 |
116 | 5cabc5cc | Edgar E. Iglesias | #define JMP_DIRECT 1 |
117 | 5cabc5cc | Edgar E. Iglesias | #define JMP_DIRECT_CC 2 |
118 | 5cabc5cc | Edgar E. Iglesias | #define JMP_INDIRECT 3 |
119 | 7b5eff4d | Evgeny Voevodin | int jmp; /* 0=nojmp, 1=direct, 2=indirect. */ |
120 | 7b5eff4d | Evgeny Voevodin | uint32_t jmp_pc; |
121 | 2a44f7f1 | edgar_igl | |
122 | 7b5eff4d | Evgeny Voevodin | int delayed_branch;
|
123 | 8170028d | ths | |
124 | 7b5eff4d | Evgeny Voevodin | struct TranslationBlock *tb;
|
125 | 7b5eff4d | Evgeny Voevodin | int singlestep_enabled;
|
126 | 8170028d | ths | } DisasContext; |
127 | 8170028d | ths | |
128 | 7ccfb2eb | blueswir1 | static void gen_BUG(DisasContext *dc, const char *file, int line) |
129 | 8170028d | ths | { |
130 | 7b5eff4d | Evgeny Voevodin | printf("BUG: pc=%x %s %d\n", dc->pc, file, line);
|
131 | 7b5eff4d | Evgeny Voevodin | qemu_log("BUG: pc=%x %s %d\n", dc->pc, file, line);
|
132 | 7b5eff4d | Evgeny Voevodin | cpu_abort(dc->env, "%s:%d\n", file, line);
|
133 | 8170028d | ths | } |
134 | 8170028d | ths | |
135 | 9b32fbf8 | edgar_igl | static const char *regnames[] = |
136 | a825e703 | edgar_igl | { |
137 | 7b5eff4d | Evgeny Voevodin | "$r0", "$r1", "$r2", "$r3", |
138 | 7b5eff4d | Evgeny Voevodin | "$r4", "$r5", "$r6", "$r7", |
139 | 7b5eff4d | Evgeny Voevodin | "$r8", "$r9", "$r10", "$r11", |
140 | 7b5eff4d | Evgeny Voevodin | "$r12", "$r13", "$sp", "$acr", |
141 | a825e703 | edgar_igl | }; |
142 | 9b32fbf8 | edgar_igl | static const char *pregnames[] = |
143 | a825e703 | edgar_igl | { |
144 | 7b5eff4d | Evgeny Voevodin | "$bz", "$vr", "$pid", "$srs", |
145 | 7b5eff4d | Evgeny Voevodin | "$wz", "$exs", "$eda", "$mof", |
146 | 7b5eff4d | Evgeny Voevodin | "$dz", "$ebp", "$erp", "$srp", |
147 | 7b5eff4d | Evgeny Voevodin | "$nrp", "$ccs", "$usp", "$spc", |
148 | a825e703 | edgar_igl | }; |
149 | a825e703 | edgar_igl | |
150 | 05ba7d5f | edgar_igl | /* We need this table to handle preg-moves with implicit width. */
|
151 | 9b32fbf8 | edgar_igl | static int preg_sizes[] = { |
152 | 7b5eff4d | Evgeny Voevodin | 1, /* bz. */ |
153 | 7b5eff4d | Evgeny Voevodin | 1, /* vr. */ |
154 | 7b5eff4d | Evgeny Voevodin | 4, /* pid. */ |
155 | 7b5eff4d | Evgeny Voevodin | 1, /* srs. */ |
156 | 7b5eff4d | Evgeny Voevodin | 2, /* wz. */ |
157 | 7b5eff4d | Evgeny Voevodin | 4, 4, 4, |
158 | 7b5eff4d | Evgeny Voevodin | 4, 4, 4, 4, |
159 | 7b5eff4d | Evgeny Voevodin | 4, 4, 4, 4, |
160 | 05ba7d5f | edgar_igl | }; |
161 | 05ba7d5f | edgar_igl | |
162 | 05ba7d5f | edgar_igl | #define t_gen_mov_TN_env(tn, member) \
|
163 | a1170bfd | Andreas Färber | _t_gen_mov_TN_env((tn), offsetof(CPUCRISState, member)) |
164 | 05ba7d5f | edgar_igl | #define t_gen_mov_env_TN(member, tn) \
|
165 | a1170bfd | Andreas Färber | _t_gen_mov_env_TN(offsetof(CPUCRISState, member), (tn)) |
166 | 05ba7d5f | edgar_igl | |
167 | b41f7df0 | edgar_igl | static inline void t_gen_mov_TN_reg(TCGv tn, int r) |
168 | b41f7df0 | edgar_igl | { |
169 | 7b5eff4d | Evgeny Voevodin | if (r < 0 || r > 15) { |
170 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong register read $r%d\n", r);
|
171 | 7b5eff4d | Evgeny Voevodin | } |
172 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(tn, cpu_R[r]); |
173 | b41f7df0 | edgar_igl | } |
174 | b41f7df0 | edgar_igl | static inline void t_gen_mov_reg_TN(int r, TCGv tn) |
175 | b41f7df0 | edgar_igl | { |
176 | 7b5eff4d | Evgeny Voevodin | if (r < 0 || r > 15) { |
177 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong register write $r%d\n", r);
|
178 | 7b5eff4d | Evgeny Voevodin | } |
179 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cpu_R[r], tn); |
180 | b41f7df0 | edgar_igl | } |
181 | 05ba7d5f | edgar_igl | |
182 | 05ba7d5f | edgar_igl | static inline void _t_gen_mov_TN_env(TCGv tn, int offset) |
183 | 05ba7d5f | edgar_igl | { |
184 | 7b5eff4d | Evgeny Voevodin | if (offset > sizeof(CPUCRISState)) { |
185 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong load from env from off=%d\n", offset);
|
186 | 7b5eff4d | Evgeny Voevodin | } |
187 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ld_tl(tn, cpu_env, offset); |
188 | 05ba7d5f | edgar_igl | } |
189 | 05ba7d5f | edgar_igl | static inline void _t_gen_mov_env_TN(int offset, TCGv tn) |
190 | 05ba7d5f | edgar_igl | { |
191 | 7b5eff4d | Evgeny Voevodin | if (offset > sizeof(CPUCRISState)) { |
192 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong store to env at off=%d\n", offset);
|
193 | 7b5eff4d | Evgeny Voevodin | } |
194 | 7b5eff4d | Evgeny Voevodin | tcg_gen_st_tl(tn, cpu_env, offset); |
195 | 05ba7d5f | edgar_igl | } |
196 | 05ba7d5f | edgar_igl | |
197 | 05ba7d5f | edgar_igl | static inline void t_gen_mov_TN_preg(TCGv tn, int r) |
198 | 05ba7d5f | edgar_igl | { |
199 | 7b5eff4d | Evgeny Voevodin | if (r < 0 || r > 15) { |
200 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong register read $p%d\n", r);
|
201 | 7b5eff4d | Evgeny Voevodin | } |
202 | 7b5eff4d | Evgeny Voevodin | if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
|
203 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(tn, tcg_const_tl(0));
|
204 | 7b5eff4d | Evgeny Voevodin | } else if (r == PR_VR) { |
205 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(tn, tcg_const_tl(32));
|
206 | 7b5eff4d | Evgeny Voevodin | } else {
|
207 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(tn, cpu_PR[r]); |
208 | 7b5eff4d | Evgeny Voevodin | } |
209 | 05ba7d5f | edgar_igl | } |
210 | cf1d97f0 | edgar_igl | static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) |
211 | 05ba7d5f | edgar_igl | { |
212 | 7b5eff4d | Evgeny Voevodin | if (r < 0 || r > 15) { |
213 | 7b5eff4d | Evgeny Voevodin | fprintf(stderr, "wrong register write $p%d\n", r);
|
214 | 7b5eff4d | Evgeny Voevodin | } |
215 | 7b5eff4d | Evgeny Voevodin | if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
|
216 | 7b5eff4d | Evgeny Voevodin | return;
|
217 | 7b5eff4d | Evgeny Voevodin | } else if (r == PR_SRS) { |
218 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cpu_PR[r], tn, 3);
|
219 | 7b5eff4d | Evgeny Voevodin | } else {
|
220 | 7b5eff4d | Evgeny Voevodin | if (r == PR_PID) {
|
221 | 7b5eff4d | Evgeny Voevodin | gen_helper_tlb_flush_pid(cpu_env, tn); |
222 | 7b5eff4d | Evgeny Voevodin | } |
223 | 7b5eff4d | Evgeny Voevodin | if (dc->tb_flags & S_FLAG && r == PR_SPC) {
|
224 | 7b5eff4d | Evgeny Voevodin | gen_helper_spc_write(cpu_env, tn); |
225 | 7b5eff4d | Evgeny Voevodin | } else if (r == PR_CCS) { |
226 | 7b5eff4d | Evgeny Voevodin | dc->cpustate_changed = 1;
|
227 | 7b5eff4d | Evgeny Voevodin | } |
228 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cpu_PR[r], tn); |
229 | 7b5eff4d | Evgeny Voevodin | } |
230 | 05ba7d5f | edgar_igl | } |
231 | 05ba7d5f | edgar_igl | |
232 | 1884533c | Edgar E. Iglesias | /* Sign extend at translation time. */
|
233 | 1884533c | Edgar E. Iglesias | static int sign_extend(unsigned int val, unsigned int width) |
234 | 1884533c | Edgar E. Iglesias | { |
235 | 7b5eff4d | Evgeny Voevodin | int sval;
|
236 | 1884533c | Edgar E. Iglesias | |
237 | 7b5eff4d | Evgeny Voevodin | /* LSL. */
|
238 | 7b5eff4d | Evgeny Voevodin | val <<= 31 - width;
|
239 | 7b5eff4d | Evgeny Voevodin | sval = val; |
240 | 7b5eff4d | Evgeny Voevodin | /* ASR. */
|
241 | 7b5eff4d | Evgeny Voevodin | sval >>= 31 - width;
|
242 | 7b5eff4d | Evgeny Voevodin | return sval;
|
243 | 1884533c | Edgar E. Iglesias | } |
244 | 1884533c | Edgar E. Iglesias | |
245 | cf7e0c80 | Aurelien Jarno | static int cris_fetch(CPUCRISState *env, DisasContext *dc, uint32_t addr, |
246 | 7b5eff4d | Evgeny Voevodin | unsigned int size, unsigned int sign) |
247 | 7b5eff4d | Evgeny Voevodin | { |
248 | 7b5eff4d | Evgeny Voevodin | int r;
|
249 | 7b5eff4d | Evgeny Voevodin | |
250 | 7b5eff4d | Evgeny Voevodin | switch (size) {
|
251 | 7b5eff4d | Evgeny Voevodin | case 4: |
252 | 7b5eff4d | Evgeny Voevodin | { |
253 | 7b5eff4d | Evgeny Voevodin | r = cpu_ldl_code(env, addr); |
254 | 7b5eff4d | Evgeny Voevodin | break;
|
255 | 7b5eff4d | Evgeny Voevodin | } |
256 | 7b5eff4d | Evgeny Voevodin | case 2: |
257 | 7b5eff4d | Evgeny Voevodin | { |
258 | 7b5eff4d | Evgeny Voevodin | if (sign) {
|
259 | 7b5eff4d | Evgeny Voevodin | r = cpu_ldsw_code(env, addr); |
260 | 7b5eff4d | Evgeny Voevodin | } else {
|
261 | 7b5eff4d | Evgeny Voevodin | r = cpu_lduw_code(env, addr); |
262 | 7b5eff4d | Evgeny Voevodin | } |
263 | 7b5eff4d | Evgeny Voevodin | break;
|
264 | 7b5eff4d | Evgeny Voevodin | } |
265 | 7b5eff4d | Evgeny Voevodin | case 1: |
266 | 7b5eff4d | Evgeny Voevodin | { |
267 | 7b5eff4d | Evgeny Voevodin | if (sign) {
|
268 | 7b5eff4d | Evgeny Voevodin | r = cpu_ldsb_code(env, addr); |
269 | 7b5eff4d | Evgeny Voevodin | } else {
|
270 | 7b5eff4d | Evgeny Voevodin | r = cpu_ldub_code(env, addr); |
271 | 7b5eff4d | Evgeny Voevodin | } |
272 | 7b5eff4d | Evgeny Voevodin | break;
|
273 | 7b5eff4d | Evgeny Voevodin | } |
274 | 7b5eff4d | Evgeny Voevodin | default:
|
275 | 7b5eff4d | Evgeny Voevodin | cpu_abort(dc->env, "Invalid fetch size %d\n", size);
|
276 | 7b5eff4d | Evgeny Voevodin | break;
|
277 | 7b5eff4d | Evgeny Voevodin | } |
278 | 7b5eff4d | Evgeny Voevodin | return r;
|
279 | 7de141cb | Edgar E. Iglesias | } |
280 | 7de141cb | Edgar E. Iglesias | |
281 | 40e9eddd | Edgar E. Iglesias | static void cris_lock_irq(DisasContext *dc) |
282 | 40e9eddd | Edgar E. Iglesias | { |
283 | 7b5eff4d | Evgeny Voevodin | dc->clear_locked_irq = 0;
|
284 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
|
285 | 40e9eddd | Edgar E. Iglesias | } |
286 | 40e9eddd | Edgar E. Iglesias | |
287 | dceaf394 | edgar_igl | static inline void t_gen_raise_exception(uint32_t index) |
288 | 05ba7d5f | edgar_igl | { |
289 | a7812ae4 | pbrook | TCGv_i32 tmp = tcg_const_i32(index); |
290 | febc9920 | Aurelien Jarno | gen_helper_raise_exception(cpu_env, tmp); |
291 | a7812ae4 | pbrook | tcg_temp_free_i32(tmp); |
292 | 05ba7d5f | edgar_igl | } |
293 | 05ba7d5f | edgar_igl | |
294 | 05ba7d5f | edgar_igl | static void t_gen_lsl(TCGv d, TCGv a, TCGv b) |
295 | 05ba7d5f | edgar_igl | { |
296 | 7b5eff4d | Evgeny Voevodin | TCGv t0, t_31; |
297 | 05ba7d5f | edgar_igl | |
298 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
299 | 7b5eff4d | Evgeny Voevodin | t_31 = tcg_const_tl(31);
|
300 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shl_tl(d, a, b); |
301 | 7dcfb089 | edgar_igl | |
302 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(t0, t_31, b); |
303 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sar_tl(t0, t0, t_31); |
304 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(t0, t0, d); |
305 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(d, d, t0); |
306 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
307 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t_31); |
308 | 05ba7d5f | edgar_igl | } |
309 | 05ba7d5f | edgar_igl | |
310 | 05ba7d5f | edgar_igl | static void t_gen_lsr(TCGv d, TCGv a, TCGv b) |
311 | 05ba7d5f | edgar_igl | { |
312 | 7b5eff4d | Evgeny Voevodin | TCGv t0, t_31; |
313 | 05ba7d5f | edgar_igl | |
314 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
315 | 7b5eff4d | Evgeny Voevodin | t_31 = tcg_temp_new(); |
316 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shr_tl(d, a, b); |
317 | 7dcfb089 | edgar_igl | |
318 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(t_31, 31);
|
319 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(t0, t_31, b); |
320 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sar_tl(t0, t0, t_31); |
321 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(t0, t0, d); |
322 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(d, d, t0); |
323 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
324 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t_31); |
325 | 05ba7d5f | edgar_igl | } |
326 | 05ba7d5f | edgar_igl | |
327 | 05ba7d5f | edgar_igl | static void t_gen_asr(TCGv d, TCGv a, TCGv b) |
328 | 05ba7d5f | edgar_igl | { |
329 | 7b5eff4d | Evgeny Voevodin | TCGv t0, t_31; |
330 | 05ba7d5f | edgar_igl | |
331 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
332 | 7b5eff4d | Evgeny Voevodin | t_31 = tcg_temp_new(); |
333 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sar_tl(d, a, b); |
334 | 7dcfb089 | edgar_igl | |
335 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(t_31, 31);
|
336 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(t0, t_31, b); |
337 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sar_tl(t0, t0, t_31); |
338 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(d, d, t0); |
339 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
340 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t_31); |
341 | 05ba7d5f | edgar_igl | } |
342 | 05ba7d5f | edgar_igl | |
343 | 30abcfc7 | edgar_igl | static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b) |
344 | aae6b32a | edgar_igl | { |
345 | 7b5eff4d | Evgeny Voevodin | int l1;
|
346 | aae6b32a | edgar_igl | |
347 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
348 | aae6b32a | edgar_igl | |
349 | 7b5eff4d | Evgeny Voevodin | /*
|
350 | 7b5eff4d | Evgeny Voevodin | * d <<= 1
|
351 | 7b5eff4d | Evgeny Voevodin | * if (d >= s)
|
352 | 7b5eff4d | Evgeny Voevodin | * d -= s;
|
353 | 7b5eff4d | Evgeny Voevodin | */
|
354 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(d, a, 1);
|
355 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1); |
356 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(d, d, b); |
357 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
358 | aae6b32a | edgar_igl | } |
359 | aae6b32a | edgar_igl | |
360 | 40e9eddd | Edgar E. Iglesias | static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs) |
361 | 40e9eddd | Edgar E. Iglesias | { |
362 | 7b5eff4d | Evgeny Voevodin | TCGv t; |
363 | 40e9eddd | Edgar E. Iglesias | |
364 | 7b5eff4d | Evgeny Voevodin | /*
|
365 | 7b5eff4d | Evgeny Voevodin | * d <<= 1
|
366 | 7b5eff4d | Evgeny Voevodin | * if (n)
|
367 | 7b5eff4d | Evgeny Voevodin | * d += s;
|
368 | 7b5eff4d | Evgeny Voevodin | */
|
369 | 7b5eff4d | Evgeny Voevodin | t = tcg_temp_new(); |
370 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(d, a, 1);
|
371 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(t, ccs, 31 - 3); |
372 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sari_tl(t, t, 31);
|
373 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(t, t, b); |
374 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(d, d, t); |
375 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t); |
376 | 40e9eddd | Edgar E. Iglesias | } |
377 | 40e9eddd | Edgar E. Iglesias | |
378 | 3157a0a9 | edgar_igl | /* Extended arithmetics on CRIS. */
|
379 | 3157a0a9 | edgar_igl | static inline void t_gen_add_flag(TCGv d, int flag) |
380 | 3157a0a9 | edgar_igl | { |
381 | 7b5eff4d | Evgeny Voevodin | TCGv c; |
382 | 3157a0a9 | edgar_igl | |
383 | 7b5eff4d | Evgeny Voevodin | c = tcg_temp_new(); |
384 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(c, PR_CCS); |
385 | 7b5eff4d | Evgeny Voevodin | /* Propagate carry into d. */
|
386 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(c, c, 1 << flag);
|
387 | 7b5eff4d | Evgeny Voevodin | if (flag) {
|
388 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(c, c, flag); |
389 | 7b5eff4d | Evgeny Voevodin | } |
390 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(d, d, c); |
391 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(c); |
392 | 3157a0a9 | edgar_igl | } |
393 | 3157a0a9 | edgar_igl | |
394 | 30abcfc7 | edgar_igl | static inline void t_gen_addx_carry(DisasContext *dc, TCGv d) |
395 | 3157a0a9 | edgar_igl | { |
396 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known) {
|
397 | 7b5eff4d | Evgeny Voevodin | if (dc->flags_x) {
|
398 | 7b5eff4d | Evgeny Voevodin | TCGv c; |
399 | 30abcfc7 | edgar_igl | |
400 | 7b5eff4d | Evgeny Voevodin | c = tcg_temp_new(); |
401 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(c, PR_CCS); |
402 | 7b5eff4d | Evgeny Voevodin | /* C flag is already at bit 0. */
|
403 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(c, c, C_FLAG); |
404 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(d, d, c); |
405 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(c); |
406 | 7b5eff4d | Evgeny Voevodin | } |
407 | 7b5eff4d | Evgeny Voevodin | } else {
|
408 | 7b5eff4d | Evgeny Voevodin | TCGv x, c; |
409 | 7b5eff4d | Evgeny Voevodin | |
410 | 7b5eff4d | Evgeny Voevodin | x = tcg_temp_new(); |
411 | 7b5eff4d | Evgeny Voevodin | c = tcg_temp_new(); |
412 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(x, PR_CCS); |
413 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(c, x); |
414 | 7b5eff4d | Evgeny Voevodin | |
415 | 7b5eff4d | Evgeny Voevodin | /* Propagate carry into d if X is set. Branch free. */
|
416 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(c, c, C_FLAG); |
417 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(x, x, X_FLAG); |
418 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(x, x, 4);
|
419 | 7b5eff4d | Evgeny Voevodin | |
420 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(x, x, c); |
421 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(d, d, x); |
422 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(x); |
423 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(c); |
424 | 7b5eff4d | Evgeny Voevodin | } |
425 | 3157a0a9 | edgar_igl | } |
426 | 3157a0a9 | edgar_igl | |
427 | a39f8f3a | edgar_igl | static inline void t_gen_subx_carry(DisasContext *dc, TCGv d) |
428 | 3157a0a9 | edgar_igl | { |
429 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known) {
|
430 | 7b5eff4d | Evgeny Voevodin | if (dc->flags_x) {
|
431 | 7b5eff4d | Evgeny Voevodin | TCGv c; |
432 | 30abcfc7 | edgar_igl | |
433 | 7b5eff4d | Evgeny Voevodin | c = tcg_temp_new(); |
434 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(c, PR_CCS); |
435 | 7b5eff4d | Evgeny Voevodin | /* C flag is already at bit 0. */
|
436 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(c, c, C_FLAG); |
437 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(d, d, c); |
438 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(c); |
439 | 7b5eff4d | Evgeny Voevodin | } |
440 | 7b5eff4d | Evgeny Voevodin | } else {
|
441 | 7b5eff4d | Evgeny Voevodin | TCGv x, c; |
442 | 7b5eff4d | Evgeny Voevodin | |
443 | 7b5eff4d | Evgeny Voevodin | x = tcg_temp_new(); |
444 | 7b5eff4d | Evgeny Voevodin | c = tcg_temp_new(); |
445 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(x, PR_CCS); |
446 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(c, x); |
447 | 7b5eff4d | Evgeny Voevodin | |
448 | 7b5eff4d | Evgeny Voevodin | /* Propagate carry into d if X is set. Branch free. */
|
449 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(c, c, C_FLAG); |
450 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(x, x, X_FLAG); |
451 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(x, x, 4);
|
452 | 7b5eff4d | Evgeny Voevodin | |
453 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(x, x, c); |
454 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(d, d, x); |
455 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(x); |
456 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(c); |
457 | 7b5eff4d | Evgeny Voevodin | } |
458 | 3157a0a9 | edgar_igl | } |
459 | 3157a0a9 | edgar_igl | |
460 | 3157a0a9 | edgar_igl | /* Swap the two bytes within each half word of the s operand.
|
461 | 3157a0a9 | edgar_igl | T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff) */
|
462 | 3157a0a9 | edgar_igl | static inline void t_gen_swapb(TCGv d, TCGv s) |
463 | 3157a0a9 | edgar_igl | { |
464 | 7b5eff4d | Evgeny Voevodin | TCGv t, org_s; |
465 | 3157a0a9 | edgar_igl | |
466 | 7b5eff4d | Evgeny Voevodin | t = tcg_temp_new(); |
467 | 7b5eff4d | Evgeny Voevodin | org_s = tcg_temp_new(); |
468 | 3157a0a9 | edgar_igl | |
469 | 7b5eff4d | Evgeny Voevodin | /* d and s may refer to the same object. */
|
470 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(org_s, s); |
471 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(t, org_s, 8);
|
472 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(d, t, 0xff00ff00);
|
473 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(t, org_s, 8);
|
474 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t, t, 0x00ff00ff);
|
475 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(d, d, t); |
476 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t); |
477 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(org_s); |
478 | 3157a0a9 | edgar_igl | } |
479 | 3157a0a9 | edgar_igl | |
480 | 3157a0a9 | edgar_igl | /* Swap the halfwords of the s operand. */
|
481 | 3157a0a9 | edgar_igl | static inline void t_gen_swapw(TCGv d, TCGv s) |
482 | 3157a0a9 | edgar_igl | { |
483 | 7b5eff4d | Evgeny Voevodin | TCGv t; |
484 | 7b5eff4d | Evgeny Voevodin | /* d and s refer the same object. */
|
485 | 7b5eff4d | Evgeny Voevodin | t = tcg_temp_new(); |
486 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(t, s); |
487 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(d, t, 16);
|
488 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(t, t, 16);
|
489 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(d, d, t); |
490 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t); |
491 | 3157a0a9 | edgar_igl | } |
492 | 3157a0a9 | edgar_igl | |
493 | 3157a0a9 | edgar_igl | /* Reverse the within each byte.
|
494 | 3157a0a9 | edgar_igl | T0 = (((T0 << 7) & 0x80808080) |
|
495 | 3157a0a9 | edgar_igl | ((T0 << 5) & 0x40404040) |
|
496 | 3157a0a9 | edgar_igl | ((T0 << 3) & 0x20202020) |
|
497 | 3157a0a9 | edgar_igl | ((T0 << 1) & 0x10101010) |
|
498 | 3157a0a9 | edgar_igl | ((T0 >> 1) & 0x08080808) |
|
499 | 3157a0a9 | edgar_igl | ((T0 >> 3) & 0x04040404) |
|
500 | 3157a0a9 | edgar_igl | ((T0 >> 5) & 0x02020202) |
|
501 | 3157a0a9 | edgar_igl | ((T0 >> 7) & 0x01010101));
|
502 | 3157a0a9 | edgar_igl | */
|
503 | 3157a0a9 | edgar_igl | static inline void t_gen_swapr(TCGv d, TCGv s) |
504 | 3157a0a9 | edgar_igl | { |
505 | 7b5eff4d | Evgeny Voevodin | struct {
|
506 | 7b5eff4d | Evgeny Voevodin | int shift; /* LSL when positive, LSR when negative. */ |
507 | 7b5eff4d | Evgeny Voevodin | uint32_t mask; |
508 | 7b5eff4d | Evgeny Voevodin | } bitrev[] = { |
509 | 7b5eff4d | Evgeny Voevodin | {7, 0x80808080}, |
510 | 7b5eff4d | Evgeny Voevodin | {5, 0x40404040}, |
511 | 7b5eff4d | Evgeny Voevodin | {3, 0x20202020}, |
512 | 7b5eff4d | Evgeny Voevodin | {1, 0x10101010}, |
513 | 7b5eff4d | Evgeny Voevodin | {-1, 0x08080808}, |
514 | 7b5eff4d | Evgeny Voevodin | {-3, 0x04040404}, |
515 | 7b5eff4d | Evgeny Voevodin | {-5, 0x02020202}, |
516 | 7b5eff4d | Evgeny Voevodin | {-7, 0x01010101} |
517 | 7b5eff4d | Evgeny Voevodin | }; |
518 | 7b5eff4d | Evgeny Voevodin | int i;
|
519 | 7b5eff4d | Evgeny Voevodin | TCGv t, org_s; |
520 | 7b5eff4d | Evgeny Voevodin | |
521 | 7b5eff4d | Evgeny Voevodin | /* d and s refer the same object. */
|
522 | 7b5eff4d | Evgeny Voevodin | t = tcg_temp_new(); |
523 | 7b5eff4d | Evgeny Voevodin | org_s = tcg_temp_new(); |
524 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(org_s, s); |
525 | 7b5eff4d | Evgeny Voevodin | |
526 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(t, org_s, bitrev[0].shift);
|
527 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(d, t, bitrev[0].mask);
|
528 | 7b5eff4d | Evgeny Voevodin | for (i = 1; i < ARRAY_SIZE(bitrev); i++) { |
529 | 7b5eff4d | Evgeny Voevodin | if (bitrev[i].shift >= 0) { |
530 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(t, org_s, bitrev[i].shift); |
531 | 7b5eff4d | Evgeny Voevodin | } else {
|
532 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(t, org_s, -bitrev[i].shift); |
533 | 7b5eff4d | Evgeny Voevodin | } |
534 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t, t, bitrev[i].mask); |
535 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(d, d, t); |
536 | 7b5eff4d | Evgeny Voevodin | } |
537 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t); |
538 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(org_s); |
539 | 3157a0a9 | edgar_igl | } |
540 | 3157a0a9 | edgar_igl | |
541 | cf1d97f0 | edgar_igl | static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false) |
542 | 17ac9754 | edgar_igl | { |
543 | 7b5eff4d | Evgeny Voevodin | int l1;
|
544 | 17ac9754 | edgar_igl | |
545 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
546 | 17ac9754 | edgar_igl | |
547 | 7b5eff4d | Evgeny Voevodin | /* Conditional jmp. */
|
548 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(env_pc, pc_false); |
549 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
|
550 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(env_pc, pc_true); |
551 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
552 | 17ac9754 | edgar_igl | } |
553 | 17ac9754 | edgar_igl | |
554 | 8170028d | ths | static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) |
555 | 8170028d | ths | { |
556 | 7b5eff4d | Evgeny Voevodin | TranslationBlock *tb; |
557 | 7b5eff4d | Evgeny Voevodin | tb = dc->tb; |
558 | 7b5eff4d | Evgeny Voevodin | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
|
559 | 7b5eff4d | Evgeny Voevodin | tcg_gen_goto_tb(n); |
560 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dest); |
561 | 4b4a72e5 | Stefan Weil | tcg_gen_exit_tb((tcg_target_long)tb + n); |
562 | 7b5eff4d | Evgeny Voevodin | } else {
|
563 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dest); |
564 | 7b5eff4d | Evgeny Voevodin | tcg_gen_exit_tb(0);
|
565 | 7b5eff4d | Evgeny Voevodin | } |
566 | 8170028d | ths | } |
567 | 8170028d | ths | |
568 | 05ba7d5f | edgar_igl | static inline void cris_clear_x_flag(DisasContext *dc) |
569 | 05ba7d5f | edgar_igl | { |
570 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known && dc->flags_x) {
|
571 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 0;
|
572 | 7b5eff4d | Evgeny Voevodin | } |
573 | 2a44f7f1 | edgar_igl | |
574 | 7b5eff4d | Evgeny Voevodin | dc->flagx_known = 1;
|
575 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = 0;
|
576 | 05ba7d5f | edgar_igl | } |
577 | 05ba7d5f | edgar_igl | |
578 | 30abcfc7 | edgar_igl | static void cris_flush_cc_state(DisasContext *dc) |
579 | 8170028d | ths | { |
580 | 7b5eff4d | Evgeny Voevodin | if (dc->cc_size_uptodate != dc->cc_size) {
|
581 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc_size, dc->cc_size); |
582 | 7b5eff4d | Evgeny Voevodin | dc->cc_size_uptodate = dc->cc_size; |
583 | 7b5eff4d | Evgeny Voevodin | } |
584 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc_op, dc->cc_op); |
585 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc_mask, dc->cc_mask); |
586 | 30abcfc7 | edgar_igl | } |
587 | 30abcfc7 | edgar_igl | |
588 | 30abcfc7 | edgar_igl | static void cris_evaluate_flags(DisasContext *dc) |
589 | 30abcfc7 | edgar_igl | { |
590 | 7b5eff4d | Evgeny Voevodin | if (dc->flags_uptodate) {
|
591 | 7b5eff4d | Evgeny Voevodin | return;
|
592 | 7b5eff4d | Evgeny Voevodin | } |
593 | 7b5eff4d | Evgeny Voevodin | |
594 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
595 | 7b5eff4d | Evgeny Voevodin | |
596 | 7b5eff4d | Evgeny Voevodin | switch (dc->cc_op) {
|
597 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MCP:
|
598 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], cpu_env, |
599 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc_src, |
600 | 7b5eff4d | Evgeny Voevodin | cc_dest, cc_result); |
601 | 7b5eff4d | Evgeny Voevodin | break;
|
602 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULS:
|
603 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], cpu_env, |
604 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc_result, |
605 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_MOF]); |
606 | 7b5eff4d | Evgeny Voevodin | break;
|
607 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULU:
|
608 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], cpu_env, |
609 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc_result, |
610 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_MOF]); |
611 | 7b5eff4d | Evgeny Voevodin | break;
|
612 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MOVE:
|
613 | 7b5eff4d | Evgeny Voevodin | case CC_OP_AND:
|
614 | 7b5eff4d | Evgeny Voevodin | case CC_OP_OR:
|
615 | 7b5eff4d | Evgeny Voevodin | case CC_OP_XOR:
|
616 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ASR:
|
617 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSR:
|
618 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSL:
|
619 | 7b5eff4d | Evgeny Voevodin | switch (dc->cc_size) {
|
620 | 7b5eff4d | Evgeny Voevodin | case 4: |
621 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS], |
622 | 7b5eff4d | Evgeny Voevodin | cpu_env, cpu_PR[PR_CCS], cc_result); |
623 | 7b5eff4d | Evgeny Voevodin | break;
|
624 | 7b5eff4d | Evgeny Voevodin | case 2: |
625 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS], |
626 | 7b5eff4d | Evgeny Voevodin | cpu_env, cpu_PR[PR_CCS], cc_result); |
627 | 7b5eff4d | Evgeny Voevodin | break;
|
628 | 7b5eff4d | Evgeny Voevodin | default:
|
629 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags(cpu_env); |
630 | 7b5eff4d | Evgeny Voevodin | break;
|
631 | 7b5eff4d | Evgeny Voevodin | } |
632 | 7b5eff4d | Evgeny Voevodin | break;
|
633 | 7b5eff4d | Evgeny Voevodin | case CC_OP_FLAGS:
|
634 | 7b5eff4d | Evgeny Voevodin | /* live. */
|
635 | 7b5eff4d | Evgeny Voevodin | break;
|
636 | 7b5eff4d | Evgeny Voevodin | case CC_OP_SUB:
|
637 | 7b5eff4d | Evgeny Voevodin | case CC_OP_CMP:
|
638 | 7b5eff4d | Evgeny Voevodin | if (dc->cc_size == 4) { |
639 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], cpu_env, |
640 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc_src, cc_dest, cc_result); |
641 | 7b5eff4d | Evgeny Voevodin | } else {
|
642 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags(cpu_env); |
643 | 7b5eff4d | Evgeny Voevodin | } |
644 | 7b5eff4d | Evgeny Voevodin | |
645 | 7b5eff4d | Evgeny Voevodin | break;
|
646 | 7b5eff4d | Evgeny Voevodin | default:
|
647 | 7b5eff4d | Evgeny Voevodin | switch (dc->cc_size) {
|
648 | 7b5eff4d | Evgeny Voevodin | case 4: |
649 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], cpu_env, |
650 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc_src, cc_dest, cc_result); |
651 | 7b5eff4d | Evgeny Voevodin | break;
|
652 | 7b5eff4d | Evgeny Voevodin | default:
|
653 | 7b5eff4d | Evgeny Voevodin | gen_helper_evaluate_flags(cpu_env); |
654 | 7b5eff4d | Evgeny Voevodin | break;
|
655 | 6231868b | edgar_igl | } |
656 | 7b5eff4d | Evgeny Voevodin | break;
|
657 | 7b5eff4d | Evgeny Voevodin | } |
658 | 7b5eff4d | Evgeny Voevodin | |
659 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known) {
|
660 | 7b5eff4d | Evgeny Voevodin | if (dc->flags_x) {
|
661 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], X_FLAG); |
662 | 7b5eff4d | Evgeny Voevodin | } else if (dc->cc_op == CC_OP_FLAGS) { |
663 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG); |
664 | 7b5eff4d | Evgeny Voevodin | } |
665 | 7b5eff4d | Evgeny Voevodin | } |
666 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
667 | 8170028d | ths | } |
668 | 8170028d | ths | |
669 | 8170028d | ths | static void cris_cc_mask(DisasContext *dc, unsigned int mask) |
670 | 8170028d | ths | { |
671 | 7b5eff4d | Evgeny Voevodin | uint32_t ovl; |
672 | 8170028d | ths | |
673 | 7b5eff4d | Evgeny Voevodin | if (!mask) {
|
674 | 7b5eff4d | Evgeny Voevodin | dc->update_cc = 0;
|
675 | 7b5eff4d | Evgeny Voevodin | return;
|
676 | 7b5eff4d | Evgeny Voevodin | } |
677 | 2a44f7f1 | edgar_igl | |
678 | 7b5eff4d | Evgeny Voevodin | /* Check if we need to evaluate the condition codes due to
|
679 | 7b5eff4d | Evgeny Voevodin | CC overlaying. */
|
680 | 7b5eff4d | Evgeny Voevodin | ovl = (dc->cc_mask ^ mask) & ~mask; |
681 | 7b5eff4d | Evgeny Voevodin | if (ovl) {
|
682 | 7b5eff4d | Evgeny Voevodin | /* TODO: optimize this case. It trigs all the time. */
|
683 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
684 | 7b5eff4d | Evgeny Voevodin | } |
685 | 7b5eff4d | Evgeny Voevodin | dc->cc_mask = mask; |
686 | 7b5eff4d | Evgeny Voevodin | dc->update_cc = 1;
|
687 | 8170028d | ths | } |
688 | 8170028d | ths | |
689 | b41f7df0 | edgar_igl | static void cris_update_cc_op(DisasContext *dc, int op, int size) |
690 | 8170028d | ths | { |
691 | 7b5eff4d | Evgeny Voevodin | dc->cc_op = op; |
692 | 7b5eff4d | Evgeny Voevodin | dc->cc_size = size; |
693 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 0;
|
694 | 8170028d | ths | } |
695 | 8170028d | ths | |
696 | 30abcfc7 | edgar_igl | static inline void cris_update_cc_x(DisasContext *dc) |
697 | 30abcfc7 | edgar_igl | { |
698 | 7b5eff4d | Evgeny Voevodin | /* Save the x flag state at the time of the cc snapshot. */
|
699 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known) {
|
700 | 7b5eff4d | Evgeny Voevodin | if (dc->cc_x_uptodate == (2 | dc->flags_x)) { |
701 | 7b5eff4d | Evgeny Voevodin | return;
|
702 | 7b5eff4d | Evgeny Voevodin | } |
703 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc_x, dc->flags_x); |
704 | 7b5eff4d | Evgeny Voevodin | dc->cc_x_uptodate = 2 | dc->flags_x;
|
705 | 7b5eff4d | Evgeny Voevodin | } else {
|
706 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG); |
707 | 7b5eff4d | Evgeny Voevodin | dc->cc_x_uptodate = 1;
|
708 | 7b5eff4d | Evgeny Voevodin | } |
709 | 30abcfc7 | edgar_igl | } |
710 | 30abcfc7 | edgar_igl | |
711 | 30abcfc7 | edgar_igl | /* Update cc prior to executing ALU op. Needs source operands untouched. */
|
712 | 30abcfc7 | edgar_igl | static void cris_pre_alu_update_cc(DisasContext *dc, int op, |
713 | 7b5eff4d | Evgeny Voevodin | TCGv dst, TCGv src, int size)
|
714 | 7b5eff4d | Evgeny Voevodin | { |
715 | 7b5eff4d | Evgeny Voevodin | if (dc->update_cc) {
|
716 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, op, size); |
717 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cc_src, src); |
718 | 7b5eff4d | Evgeny Voevodin | |
719 | 7b5eff4d | Evgeny Voevodin | if (op != CC_OP_MOVE
|
720 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_AND |
721 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_OR |
722 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_XOR |
723 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_ASR |
724 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_LSR |
725 | 7b5eff4d | Evgeny Voevodin | && op != CC_OP_LSL) { |
726 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cc_dest, dst); |
727 | 7b5eff4d | Evgeny Voevodin | } |
728 | 30abcfc7 | edgar_igl | |
729 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_x(dc); |
730 | 7b5eff4d | Evgeny Voevodin | } |
731 | 30abcfc7 | edgar_igl | } |
732 | 3157a0a9 | edgar_igl | |
733 | 30abcfc7 | edgar_igl | /* Update cc after executing ALU op. needs the result. */
|
734 | 30abcfc7 | edgar_igl | static inline void cris_update_result(DisasContext *dc, TCGv res) |
735 | 30abcfc7 | edgar_igl | { |
736 | 7b5eff4d | Evgeny Voevodin | if (dc->update_cc) {
|
737 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cc_result, res); |
738 | 7b5eff4d | Evgeny Voevodin | } |
739 | 30abcfc7 | edgar_igl | } |
740 | 8170028d | ths | |
741 | 30abcfc7 | edgar_igl | /* Returns one if the write back stage should execute. */
|
742 | 30abcfc7 | edgar_igl | static void cris_alu_op_exec(DisasContext *dc, int op, |
743 | 7b5eff4d | Evgeny Voevodin | TCGv dst, TCGv a, TCGv b, int size)
|
744 | 7b5eff4d | Evgeny Voevodin | { |
745 | 7b5eff4d | Evgeny Voevodin | /* Emit the ALU insns. */
|
746 | 7b5eff4d | Evgeny Voevodin | switch (op) {
|
747 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ADD:
|
748 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(dst, a, b); |
749 | 7b5eff4d | Evgeny Voevodin | /* Extended arithmetics. */
|
750 | 7b5eff4d | Evgeny Voevodin | t_gen_addx_carry(dc, dst); |
751 | 7b5eff4d | Evgeny Voevodin | break;
|
752 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ADDC:
|
753 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(dst, a, b); |
754 | 7b5eff4d | Evgeny Voevodin | t_gen_add_flag(dst, 0); /* C_FLAG. */ |
755 | 7b5eff4d | Evgeny Voevodin | break;
|
756 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MCP:
|
757 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(dst, a, b); |
758 | 7b5eff4d | Evgeny Voevodin | t_gen_add_flag(dst, 8); /* R_FLAG. */ |
759 | 7b5eff4d | Evgeny Voevodin | break;
|
760 | 7b5eff4d | Evgeny Voevodin | case CC_OP_SUB:
|
761 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(dst, a, b); |
762 | 7b5eff4d | Evgeny Voevodin | /* Extended arithmetics. */
|
763 | 7b5eff4d | Evgeny Voevodin | t_gen_subx_carry(dc, dst); |
764 | 7b5eff4d | Evgeny Voevodin | break;
|
765 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MOVE:
|
766 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(dst, b); |
767 | 7b5eff4d | Evgeny Voevodin | break;
|
768 | 7b5eff4d | Evgeny Voevodin | case CC_OP_OR:
|
769 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(dst, a, b); |
770 | 7b5eff4d | Evgeny Voevodin | break;
|
771 | 7b5eff4d | Evgeny Voevodin | case CC_OP_AND:
|
772 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(dst, a, b); |
773 | 7b5eff4d | Evgeny Voevodin | break;
|
774 | 7b5eff4d | Evgeny Voevodin | case CC_OP_XOR:
|
775 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(dst, a, b); |
776 | 7b5eff4d | Evgeny Voevodin | break;
|
777 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSL:
|
778 | 7b5eff4d | Evgeny Voevodin | t_gen_lsl(dst, a, b); |
779 | 7b5eff4d | Evgeny Voevodin | break;
|
780 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSR:
|
781 | 7b5eff4d | Evgeny Voevodin | t_gen_lsr(dst, a, b); |
782 | 7b5eff4d | Evgeny Voevodin | break;
|
783 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ASR:
|
784 | 7b5eff4d | Evgeny Voevodin | t_gen_asr(dst, a, b); |
785 | 7b5eff4d | Evgeny Voevodin | break;
|
786 | 7b5eff4d | Evgeny Voevodin | case CC_OP_NEG:
|
787 | 7b5eff4d | Evgeny Voevodin | tcg_gen_neg_tl(dst, b); |
788 | 7b5eff4d | Evgeny Voevodin | /* Extended arithmetics. */
|
789 | 7b5eff4d | Evgeny Voevodin | t_gen_subx_carry(dc, dst); |
790 | 7b5eff4d | Evgeny Voevodin | break;
|
791 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LZ:
|
792 | 7b5eff4d | Evgeny Voevodin | gen_helper_lz(dst, b); |
793 | 7b5eff4d | Evgeny Voevodin | break;
|
794 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULS:
|
795 | bf45f971 | Richard Henderson | tcg_gen_muls2_tl(dst, cpu_PR[PR_MOF], a, b); |
796 | 7b5eff4d | Evgeny Voevodin | break;
|
797 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULU:
|
798 | bf45f971 | Richard Henderson | tcg_gen_mulu2_tl(dst, cpu_PR[PR_MOF], a, b); |
799 | 7b5eff4d | Evgeny Voevodin | break;
|
800 | 7b5eff4d | Evgeny Voevodin | case CC_OP_DSTEP:
|
801 | 7b5eff4d | Evgeny Voevodin | t_gen_cris_dstep(dst, a, b); |
802 | 7b5eff4d | Evgeny Voevodin | break;
|
803 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MSTEP:
|
804 | 7b5eff4d | Evgeny Voevodin | t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]); |
805 | 7b5eff4d | Evgeny Voevodin | break;
|
806 | 7b5eff4d | Evgeny Voevodin | case CC_OP_BOUND:
|
807 | 7b5eff4d | Evgeny Voevodin | { |
808 | 7b5eff4d | Evgeny Voevodin | int l1;
|
809 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
810 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(dst, a); |
811 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1); |
812 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(dst, b); |
813 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
814 | 7b5eff4d | Evgeny Voevodin | } |
815 | 7b5eff4d | Evgeny Voevodin | break;
|
816 | 7b5eff4d | Evgeny Voevodin | case CC_OP_CMP:
|
817 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(dst, a, b); |
818 | 7b5eff4d | Evgeny Voevodin | /* Extended arithmetics. */
|
819 | 7b5eff4d | Evgeny Voevodin | t_gen_subx_carry(dc, dst); |
820 | 7b5eff4d | Evgeny Voevodin | break;
|
821 | 7b5eff4d | Evgeny Voevodin | default:
|
822 | 7b5eff4d | Evgeny Voevodin | qemu_log("illegal ALU op.\n");
|
823 | 7b5eff4d | Evgeny Voevodin | BUG(); |
824 | 7b5eff4d | Evgeny Voevodin | break;
|
825 | 7b5eff4d | Evgeny Voevodin | } |
826 | 7b5eff4d | Evgeny Voevodin | |
827 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
828 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(dst, dst, 0xff);
|
829 | 7b5eff4d | Evgeny Voevodin | } else if (size == 2) { |
830 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(dst, dst, 0xffff);
|
831 | 7b5eff4d | Evgeny Voevodin | } |
832 | 30abcfc7 | edgar_igl | } |
833 | 30abcfc7 | edgar_igl | |
834 | 30abcfc7 | edgar_igl | static void cris_alu(DisasContext *dc, int op, |
835 | 7b5eff4d | Evgeny Voevodin | TCGv d, TCGv op_a, TCGv op_b, int size)
|
836 | 30abcfc7 | edgar_igl | { |
837 | 7b5eff4d | Evgeny Voevodin | TCGv tmp; |
838 | 7b5eff4d | Evgeny Voevodin | int writeback;
|
839 | 30abcfc7 | edgar_igl | |
840 | 7b5eff4d | Evgeny Voevodin | writeback = 1;
|
841 | 31c18d87 | edgar_igl | |
842 | 7b5eff4d | Evgeny Voevodin | if (op == CC_OP_CMP) {
|
843 | 7b5eff4d | Evgeny Voevodin | tmp = tcg_temp_new(); |
844 | 7b5eff4d | Evgeny Voevodin | writeback = 0;
|
845 | 7b5eff4d | Evgeny Voevodin | } else if (size == 4) { |
846 | 7b5eff4d | Evgeny Voevodin | tmp = d; |
847 | 7b5eff4d | Evgeny Voevodin | writeback = 0;
|
848 | 7b5eff4d | Evgeny Voevodin | } else {
|
849 | 7b5eff4d | Evgeny Voevodin | tmp = tcg_temp_new(); |
850 | 7b5eff4d | Evgeny Voevodin | } |
851 | 44696296 | edgar_igl | |
852 | 30abcfc7 | edgar_igl | |
853 | 7b5eff4d | Evgeny Voevodin | cris_pre_alu_update_cc(dc, op, op_a, op_b, size); |
854 | 7b5eff4d | Evgeny Voevodin | cris_alu_op_exec(dc, op, tmp, op_a, op_b, size); |
855 | 7b5eff4d | Evgeny Voevodin | cris_update_result(dc, tmp); |
856 | 05ba7d5f | edgar_igl | |
857 | 7b5eff4d | Evgeny Voevodin | /* Writeback. */
|
858 | 7b5eff4d | Evgeny Voevodin | if (writeback) {
|
859 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
860 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(d, d, ~0xff);
|
861 | 7b5eff4d | Evgeny Voevodin | } else {
|
862 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(d, d, ~0xffff);
|
863 | 7b5eff4d | Evgeny Voevodin | } |
864 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(d, d, tmp); |
865 | 7b5eff4d | Evgeny Voevodin | } |
866 | 7b5eff4d | Evgeny Voevodin | if (!TCGV_EQUAL(tmp, d)) {
|
867 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(tmp); |
868 | 7b5eff4d | Evgeny Voevodin | } |
869 | 8170028d | ths | } |
870 | 8170028d | ths | |
871 | 8170028d | ths | static int arith_cc(DisasContext *dc) |
872 | 8170028d | ths | { |
873 | 7b5eff4d | Evgeny Voevodin | if (dc->update_cc) {
|
874 | 7b5eff4d | Evgeny Voevodin | switch (dc->cc_op) {
|
875 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ADDC: return 1; |
876 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ADD: return 1; |
877 | 7b5eff4d | Evgeny Voevodin | case CC_OP_SUB: return 1; |
878 | 7b5eff4d | Evgeny Voevodin | case CC_OP_DSTEP: return 1; |
879 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSL: return 1; |
880 | 7b5eff4d | Evgeny Voevodin | case CC_OP_LSR: return 1; |
881 | 7b5eff4d | Evgeny Voevodin | case CC_OP_ASR: return 1; |
882 | 7b5eff4d | Evgeny Voevodin | case CC_OP_CMP: return 1; |
883 | 7b5eff4d | Evgeny Voevodin | case CC_OP_NEG: return 1; |
884 | 7b5eff4d | Evgeny Voevodin | case CC_OP_OR: return 1; |
885 | 7b5eff4d | Evgeny Voevodin | case CC_OP_AND: return 1; |
886 | 7b5eff4d | Evgeny Voevodin | case CC_OP_XOR: return 1; |
887 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULU: return 1; |
888 | 7b5eff4d | Evgeny Voevodin | case CC_OP_MULS: return 1; |
889 | 7b5eff4d | Evgeny Voevodin | default:
|
890 | 7b5eff4d | Evgeny Voevodin | return 0; |
891 | 7b5eff4d | Evgeny Voevodin | } |
892 | 7b5eff4d | Evgeny Voevodin | } |
893 | 7b5eff4d | Evgeny Voevodin | return 0; |
894 | 8170028d | ths | } |
895 | 8170028d | ths | |
896 | c5631f48 | edgar_igl | static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond) |
897 | 8170028d | ths | { |
898 | 7b5eff4d | Evgeny Voevodin | int arith_opt, move_opt;
|
899 | 7b5eff4d | Evgeny Voevodin | |
900 | 7b5eff4d | Evgeny Voevodin | /* TODO: optimize more condition codes. */
|
901 | 7b5eff4d | Evgeny Voevodin | |
902 | 7b5eff4d | Evgeny Voevodin | /*
|
903 | 7b5eff4d | Evgeny Voevodin | * If the flags are live, we've gotta look into the bits of CCS.
|
904 | 7b5eff4d | Evgeny Voevodin | * Otherwise, if we just did an arithmetic operation we try to
|
905 | 7b5eff4d | Evgeny Voevodin | * evaluate the condition code faster.
|
906 | 7b5eff4d | Evgeny Voevodin | *
|
907 | 7b5eff4d | Evgeny Voevodin | * When this function is done, T0 should be non-zero if the condition
|
908 | 7b5eff4d | Evgeny Voevodin | * code is true.
|
909 | 7b5eff4d | Evgeny Voevodin | */
|
910 | 7b5eff4d | Evgeny Voevodin | arith_opt = arith_cc(dc) && !dc->flags_uptodate; |
911 | 7b5eff4d | Evgeny Voevodin | move_opt = (dc->cc_op == CC_OP_MOVE); |
912 | 7b5eff4d | Evgeny Voevodin | switch (cond) {
|
913 | 7b5eff4d | Evgeny Voevodin | case CC_EQ:
|
914 | 7b5eff4d | Evgeny Voevodin | if ((arith_opt || move_opt)
|
915 | 7b5eff4d | Evgeny Voevodin | && dc->cc_x_uptodate != (2 | X_FLAG)) {
|
916 | 7b5eff4d | Evgeny Voevodin | tcg_gen_setcond_tl(TCG_COND_EQ, cc, |
917 | 7b5eff4d | Evgeny Voevodin | cc_result, tcg_const_tl(0));
|
918 | 7b5eff4d | Evgeny Voevodin | } else {
|
919 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
920 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, |
921 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], Z_FLAG); |
922 | 7b5eff4d | Evgeny Voevodin | } |
923 | 7b5eff4d | Evgeny Voevodin | break;
|
924 | 7b5eff4d | Evgeny Voevodin | case CC_NE:
|
925 | 7b5eff4d | Evgeny Voevodin | if ((arith_opt || move_opt)
|
926 | 7b5eff4d | Evgeny Voevodin | && dc->cc_x_uptodate != (2 | X_FLAG)) {
|
927 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cc, cc_result); |
928 | 7b5eff4d | Evgeny Voevodin | } else {
|
929 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
930 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
931 | 7b5eff4d | Evgeny Voevodin | Z_FLAG); |
932 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, Z_FLAG); |
933 | 7b5eff4d | Evgeny Voevodin | } |
934 | 7b5eff4d | Evgeny Voevodin | break;
|
935 | 7b5eff4d | Evgeny Voevodin | case CC_CS:
|
936 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
937 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG); |
938 | 7b5eff4d | Evgeny Voevodin | break;
|
939 | 7b5eff4d | Evgeny Voevodin | case CC_CC:
|
940 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
941 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG); |
942 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, C_FLAG); |
943 | 7b5eff4d | Evgeny Voevodin | break;
|
944 | 7b5eff4d | Evgeny Voevodin | case CC_VS:
|
945 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
946 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG); |
947 | 7b5eff4d | Evgeny Voevodin | break;
|
948 | 7b5eff4d | Evgeny Voevodin | case CC_VC:
|
949 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
950 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
951 | 7b5eff4d | Evgeny Voevodin | V_FLAG); |
952 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, V_FLAG); |
953 | 7b5eff4d | Evgeny Voevodin | break;
|
954 | 7b5eff4d | Evgeny Voevodin | case CC_PL:
|
955 | 7b5eff4d | Evgeny Voevodin | if (arith_opt || move_opt) {
|
956 | 7b5eff4d | Evgeny Voevodin | int bits = 31; |
957 | 7b5eff4d | Evgeny Voevodin | |
958 | 7b5eff4d | Evgeny Voevodin | if (dc->cc_size == 1) { |
959 | 7b5eff4d | Evgeny Voevodin | bits = 7;
|
960 | 7b5eff4d | Evgeny Voevodin | } else if (dc->cc_size == 2) { |
961 | 7b5eff4d | Evgeny Voevodin | bits = 15;
|
962 | 7b5eff4d | Evgeny Voevodin | } |
963 | 7b5eff4d | Evgeny Voevodin | |
964 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(cc, cc_result, bits); |
965 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cc, 1);
|
966 | 7b5eff4d | Evgeny Voevodin | } else {
|
967 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
968 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
969 | 7b5eff4d | Evgeny Voevodin | N_FLAG); |
970 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, N_FLAG); |
971 | 7b5eff4d | Evgeny Voevodin | } |
972 | 7b5eff4d | Evgeny Voevodin | break;
|
973 | 7b5eff4d | Evgeny Voevodin | case CC_MI:
|
974 | 7b5eff4d | Evgeny Voevodin | if (arith_opt || move_opt) {
|
975 | 7b5eff4d | Evgeny Voevodin | int bits = 31; |
976 | 7b5eff4d | Evgeny Voevodin | |
977 | 7b5eff4d | Evgeny Voevodin | if (dc->cc_size == 1) { |
978 | 7b5eff4d | Evgeny Voevodin | bits = 7;
|
979 | 7b5eff4d | Evgeny Voevodin | } else if (dc->cc_size == 2) { |
980 | 7b5eff4d | Evgeny Voevodin | bits = 15;
|
981 | 7b5eff4d | Evgeny Voevodin | } |
982 | 7b5eff4d | Evgeny Voevodin | |
983 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(cc, cc_result, bits); |
984 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, 1);
|
985 | 7b5eff4d | Evgeny Voevodin | } else {
|
986 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
987 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], |
988 | 7b5eff4d | Evgeny Voevodin | N_FLAG); |
989 | 7b5eff4d | Evgeny Voevodin | } |
990 | 7b5eff4d | Evgeny Voevodin | break;
|
991 | 7b5eff4d | Evgeny Voevodin | case CC_LS:
|
992 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
993 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], |
994 | 7b5eff4d | Evgeny Voevodin | C_FLAG | Z_FLAG); |
995 | 7b5eff4d | Evgeny Voevodin | break;
|
996 | 7b5eff4d | Evgeny Voevodin | case CC_HI:
|
997 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
998 | 7b5eff4d | Evgeny Voevodin | { |
999 | 7b5eff4d | Evgeny Voevodin | TCGv tmp; |
1000 | 7b5eff4d | Evgeny Voevodin | |
1001 | 7b5eff4d | Evgeny Voevodin | tmp = tcg_temp_new(); |
1002 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS], |
1003 | 7b5eff4d | Evgeny Voevodin | C_FLAG | Z_FLAG); |
1004 | 7b5eff4d | Evgeny Voevodin | /* Overlay the C flag on top of the Z. */
|
1005 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(cc, tmp, 2);
|
1006 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(cc, tmp, cc); |
1007 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, Z_FLAG); |
1008 | 7b5eff4d | Evgeny Voevodin | |
1009 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(tmp); |
1010 | 7b5eff4d | Evgeny Voevodin | } |
1011 | 7b5eff4d | Evgeny Voevodin | break;
|
1012 | 7b5eff4d | Evgeny Voevodin | case CC_GE:
|
1013 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1014 | 7b5eff4d | Evgeny Voevodin | /* Overlay the V flag on top of the N. */
|
1015 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
|
1016 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(cc, |
1017 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc); |
1018 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, N_FLAG); |
1019 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(cc, cc, N_FLAG); |
1020 | 7b5eff4d | Evgeny Voevodin | break;
|
1021 | 7b5eff4d | Evgeny Voevodin | case CC_LT:
|
1022 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1023 | 7b5eff4d | Evgeny Voevodin | /* Overlay the V flag on top of the N. */
|
1024 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
|
1025 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(cc, |
1026 | 7b5eff4d | Evgeny Voevodin | cpu_PR[PR_CCS], cc); |
1027 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, N_FLAG); |
1028 | 7b5eff4d | Evgeny Voevodin | break;
|
1029 | 7b5eff4d | Evgeny Voevodin | case CC_GT:
|
1030 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1031 | 7b5eff4d | Evgeny Voevodin | { |
1032 | 7b5eff4d | Evgeny Voevodin | TCGv n, z; |
1033 | 7b5eff4d | Evgeny Voevodin | |
1034 | 7b5eff4d | Evgeny Voevodin | n = tcg_temp_new(); |
1035 | 7b5eff4d | Evgeny Voevodin | z = tcg_temp_new(); |
1036 | 7b5eff4d | Evgeny Voevodin | |
1037 | 7b5eff4d | Evgeny Voevodin | /* To avoid a shift we overlay everything on
|
1038 | 7b5eff4d | Evgeny Voevodin | the V flag. */
|
1039 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
|
1040 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
|
1041 | 7b5eff4d | Evgeny Voevodin | /* invert Z. */
|
1042 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(z, z, 2);
|
1043 | 7b5eff4d | Evgeny Voevodin | |
1044 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); |
1045 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xori_tl(n, n, 2);
|
1046 | 7b5eff4d | Evgeny Voevodin | tcg_gen_and_tl(cc, z, n); |
1047 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, 2);
|
1048 | 7b5eff4d | Evgeny Voevodin | |
1049 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(n); |
1050 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(z); |
1051 | 7b5eff4d | Evgeny Voevodin | } |
1052 | 7b5eff4d | Evgeny Voevodin | break;
|
1053 | 7b5eff4d | Evgeny Voevodin | case CC_LE:
|
1054 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1055 | 7b5eff4d | Evgeny Voevodin | { |
1056 | 7b5eff4d | Evgeny Voevodin | TCGv n, z; |
1057 | 7b5eff4d | Evgeny Voevodin | |
1058 | 7b5eff4d | Evgeny Voevodin | n = tcg_temp_new(); |
1059 | 7b5eff4d | Evgeny Voevodin | z = tcg_temp_new(); |
1060 | 7b5eff4d | Evgeny Voevodin | |
1061 | 7b5eff4d | Evgeny Voevodin | /* To avoid a shift we overlay everything on
|
1062 | 7b5eff4d | Evgeny Voevodin | the V flag. */
|
1063 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
|
1064 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
|
1065 | 7b5eff4d | Evgeny Voevodin | |
1066 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); |
1067 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(cc, z, n); |
1068 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cc, 2);
|
1069 | 7b5eff4d | Evgeny Voevodin | |
1070 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(n); |
1071 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(z); |
1072 | 7b5eff4d | Evgeny Voevodin | } |
1073 | 7b5eff4d | Evgeny Voevodin | break;
|
1074 | 7b5eff4d | Evgeny Voevodin | case CC_P:
|
1075 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1076 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG); |
1077 | 7b5eff4d | Evgeny Voevodin | break;
|
1078 | 7b5eff4d | Evgeny Voevodin | case CC_A:
|
1079 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc, 1);
|
1080 | 7b5eff4d | Evgeny Voevodin | break;
|
1081 | 7b5eff4d | Evgeny Voevodin | default:
|
1082 | 7b5eff4d | Evgeny Voevodin | BUG(); |
1083 | 7b5eff4d | Evgeny Voevodin | break;
|
1084 | 7b5eff4d | Evgeny Voevodin | }; |
1085 | 8170028d | ths | } |
1086 | 8170028d | ths | |
1087 | 2a44f7f1 | edgar_igl | static void cris_store_direct_jmp(DisasContext *dc) |
1088 | 2a44f7f1 | edgar_igl | { |
1089 | 7b5eff4d | Evgeny Voevodin | /* Store the direct jmp state into the cpu-state. */
|
1090 | 7b5eff4d | Evgeny Voevodin | if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
|
1091 | 7b5eff4d | Evgeny Voevodin | if (dc->jmp == JMP_DIRECT) {
|
1092 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_btaken, 1);
|
1093 | 7b5eff4d | Evgeny Voevodin | } |
1094 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_btarget, dc->jmp_pc); |
1095 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_INDIRECT; |
1096 | 7b5eff4d | Evgeny Voevodin | } |
1097 | 2a44f7f1 | edgar_igl | } |
1098 | 2a44f7f1 | edgar_igl | |
1099 | 2a44f7f1 | edgar_igl | static void cris_prepare_cc_branch (DisasContext *dc, |
1100 | 7b5eff4d | Evgeny Voevodin | int offset, int cond) |
1101 | 8170028d | ths | { |
1102 | 7b5eff4d | Evgeny Voevodin | /* This helps us re-schedule the micro-code to insns in delay-slots
|
1103 | 7b5eff4d | Evgeny Voevodin | before the actual jump. */
|
1104 | 7b5eff4d | Evgeny Voevodin | dc->delayed_branch = 2;
|
1105 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_DIRECT_CC; |
1106 | 7b5eff4d | Evgeny Voevodin | dc->jmp_pc = dc->pc + offset; |
1107 | 2a44f7f1 | edgar_igl | |
1108 | 7b5eff4d | Evgeny Voevodin | gen_tst_cc(dc, env_btaken, cond); |
1109 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_btarget, dc->jmp_pc); |
1110 | 8170028d | ths | } |
1111 | 8170028d | ths | |
1112 | b41f7df0 | edgar_igl | |
1113 | 2a44f7f1 | edgar_igl | /* jumps, when the dest is in a live reg for example. Direct should be set
|
1114 | 2a44f7f1 | edgar_igl | when the dest addr is constant to allow tb chaining. */
|
1115 | 2a44f7f1 | edgar_igl | static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type) |
1116 | 8170028d | ths | { |
1117 | 7b5eff4d | Evgeny Voevodin | /* This helps us re-schedule the micro-code to insns in delay-slots
|
1118 | 7b5eff4d | Evgeny Voevodin | before the actual jump. */
|
1119 | 7b5eff4d | Evgeny Voevodin | dc->delayed_branch = 2;
|
1120 | 7b5eff4d | Evgeny Voevodin | dc->jmp = type; |
1121 | 7b5eff4d | Evgeny Voevodin | if (type == JMP_INDIRECT) {
|
1122 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_btaken, 1);
|
1123 | 7b5eff4d | Evgeny Voevodin | } |
1124 | 8170028d | ths | } |
1125 | 8170028d | ths | |
1126 | a7812ae4 | pbrook | static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr) |
1127 | a7812ae4 | pbrook | { |
1128 | 7b5eff4d | Evgeny Voevodin | int mem_index = cpu_mmu_index(dc->env);
|
1129 | a7812ae4 | pbrook | |
1130 | 7b5eff4d | Evgeny Voevodin | /* If we get a fault on a delayslot we must keep the jmp state in
|
1131 | 7b5eff4d | Evgeny Voevodin | the cpu-state to be able to re-execute the jmp. */
|
1132 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 1) { |
1133 | 7b5eff4d | Evgeny Voevodin | cris_store_direct_jmp(dc); |
1134 | 7b5eff4d | Evgeny Voevodin | } |
1135 | a7812ae4 | pbrook | |
1136 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld64(dst, addr, mem_index); |
1137 | a7812ae4 | pbrook | } |
1138 | a7812ae4 | pbrook | |
1139 | 9b32fbf8 | edgar_igl | static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
1140 | 7b5eff4d | Evgeny Voevodin | unsigned int size, int sign) |
1141 | 7b5eff4d | Evgeny Voevodin | { |
1142 | 7b5eff4d | Evgeny Voevodin | int mem_index = cpu_mmu_index(dc->env);
|
1143 | 7b5eff4d | Evgeny Voevodin | |
1144 | 7b5eff4d | Evgeny Voevodin | /* If we get a fault on a delayslot we must keep the jmp state in
|
1145 | 7b5eff4d | Evgeny Voevodin | the cpu-state to be able to re-execute the jmp. */
|
1146 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 1) { |
1147 | 7b5eff4d | Evgeny Voevodin | cris_store_direct_jmp(dc); |
1148 | 7b5eff4d | Evgeny Voevodin | } |
1149 | 7b5eff4d | Evgeny Voevodin | |
1150 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
1151 | 7b5eff4d | Evgeny Voevodin | if (sign) {
|
1152 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld8s(dst, addr, mem_index); |
1153 | 7b5eff4d | Evgeny Voevodin | } else {
|
1154 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld8u(dst, addr, mem_index); |
1155 | 7b5eff4d | Evgeny Voevodin | } |
1156 | 7b5eff4d | Evgeny Voevodin | } else if (size == 2) { |
1157 | 7b5eff4d | Evgeny Voevodin | if (sign) {
|
1158 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld16s(dst, addr, mem_index); |
1159 | 7b5eff4d | Evgeny Voevodin | } else {
|
1160 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld16u(dst, addr, mem_index); |
1161 | 7b5eff4d | Evgeny Voevodin | } |
1162 | 7b5eff4d | Evgeny Voevodin | } else if (size == 4) { |
1163 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_ld32u(dst, addr, mem_index); |
1164 | 7b5eff4d | Evgeny Voevodin | } else {
|
1165 | 7b5eff4d | Evgeny Voevodin | abort(); |
1166 | 7b5eff4d | Evgeny Voevodin | } |
1167 | 8170028d | ths | } |
1168 | 8170028d | ths | |
1169 | 9b32fbf8 | edgar_igl | static void gen_store (DisasContext *dc, TCGv addr, TCGv val, |
1170 | 7b5eff4d | Evgeny Voevodin | unsigned int size) |
1171 | 8170028d | ths | { |
1172 | 7b5eff4d | Evgeny Voevodin | int mem_index = cpu_mmu_index(dc->env);
|
1173 | b41f7df0 | edgar_igl | |
1174 | 7b5eff4d | Evgeny Voevodin | /* If we get a fault on a delayslot we must keep the jmp state in
|
1175 | 7b5eff4d | Evgeny Voevodin | the cpu-state to be able to re-execute the jmp. */
|
1176 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 1) { |
1177 | 7b5eff4d | Evgeny Voevodin | cris_store_direct_jmp(dc); |
1178 | 7b5eff4d | Evgeny Voevodin | } |
1179 | 2a44f7f1 | edgar_igl | |
1180 | 2a44f7f1 | edgar_igl | |
1181 | 7b5eff4d | Evgeny Voevodin | /* Conditional writes. We only support the kind were X and P are known
|
1182 | 7b5eff4d | Evgeny Voevodin | at translation time. */
|
1183 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
|
1184 | 7b5eff4d | Evgeny Voevodin | dc->postinc = 0;
|
1185 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1186 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG); |
1187 | 7b5eff4d | Evgeny Voevodin | return;
|
1188 | 7b5eff4d | Evgeny Voevodin | } |
1189 | 2a44f7f1 | edgar_igl | |
1190 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
1191 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_st8(val, addr, mem_index); |
1192 | 7b5eff4d | Evgeny Voevodin | } else if (size == 2) { |
1193 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_st16(val, addr, mem_index); |
1194 | 7b5eff4d | Evgeny Voevodin | } else {
|
1195 | 7b5eff4d | Evgeny Voevodin | tcg_gen_qemu_st32(val, addr, mem_index); |
1196 | 7b5eff4d | Evgeny Voevodin | } |
1197 | 2a44f7f1 | edgar_igl | |
1198 | 7b5eff4d | Evgeny Voevodin | if (dc->flagx_known && dc->flags_x) {
|
1199 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1200 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG); |
1201 | 7b5eff4d | Evgeny Voevodin | } |
1202 | 8170028d | ths | } |
1203 | 8170028d | ths | |
1204 | 05ba7d5f | edgar_igl | static inline void t_gen_sext(TCGv d, TCGv s, int size) |
1205 | 8170028d | ths | { |
1206 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
1207 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ext8s_i32(d, s); |
1208 | 7b5eff4d | Evgeny Voevodin | } else if (size == 2) { |
1209 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ext16s_i32(d, s); |
1210 | 7b5eff4d | Evgeny Voevodin | } else if (!TCGV_EQUAL(d, s)) { |
1211 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(d, s); |
1212 | 7b5eff4d | Evgeny Voevodin | } |
1213 | 8170028d | ths | } |
1214 | 8170028d | ths | |
1215 | 05ba7d5f | edgar_igl | static inline void t_gen_zext(TCGv d, TCGv s, int size) |
1216 | 8170028d | ths | { |
1217 | 7b5eff4d | Evgeny Voevodin | if (size == 1) { |
1218 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ext8u_i32(d, s); |
1219 | 7b5eff4d | Evgeny Voevodin | } else if (size == 2) { |
1220 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ext16u_i32(d, s); |
1221 | 7b5eff4d | Evgeny Voevodin | } else if (!TCGV_EQUAL(d, s)) { |
1222 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(d, s); |
1223 | 7b5eff4d | Evgeny Voevodin | } |
1224 | 8170028d | ths | } |
1225 | 8170028d | ths | |
1226 | 8170028d | ths | #if DISAS_CRIS
|
1227 | 8170028d | ths | static char memsize_char(int size) |
1228 | 8170028d | ths | { |
1229 | 7b5eff4d | Evgeny Voevodin | switch (size) {
|
1230 | 7b5eff4d | Evgeny Voevodin | case 1: return 'b'; break; |
1231 | 7b5eff4d | Evgeny Voevodin | case 2: return 'w'; break; |
1232 | 7b5eff4d | Evgeny Voevodin | case 4: return 'd'; break; |
1233 | 7b5eff4d | Evgeny Voevodin | default:
|
1234 | 7b5eff4d | Evgeny Voevodin | return 'x'; |
1235 | 7b5eff4d | Evgeny Voevodin | break;
|
1236 | 7b5eff4d | Evgeny Voevodin | } |
1237 | 8170028d | ths | } |
1238 | 8170028d | ths | #endif
|
1239 | 8170028d | ths | |
1240 | 30abcfc7 | edgar_igl | static inline unsigned int memsize_z(DisasContext *dc) |
1241 | 8170028d | ths | { |
1242 | 7b5eff4d | Evgeny Voevodin | return dc->zsize + 1; |
1243 | 8170028d | ths | } |
1244 | 8170028d | ths | |
1245 | 30abcfc7 | edgar_igl | static inline unsigned int memsize_zz(DisasContext *dc) |
1246 | 8170028d | ths | { |
1247 | 7b5eff4d | Evgeny Voevodin | switch (dc->zzsize) {
|
1248 | 7b5eff4d | Evgeny Voevodin | case 0: return 1; |
1249 | 7b5eff4d | Evgeny Voevodin | case 1: return 2; |
1250 | 7b5eff4d | Evgeny Voevodin | default:
|
1251 | 7b5eff4d | Evgeny Voevodin | return 4; |
1252 | 7b5eff4d | Evgeny Voevodin | } |
1253 | 8170028d | ths | } |
1254 | 8170028d | ths | |
1255 | c7d05695 | edgar_igl | static inline void do_postinc (DisasContext *dc, int size) |
1256 | 8170028d | ths | { |
1257 | 7b5eff4d | Evgeny Voevodin | if (dc->postinc) {
|
1258 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size); |
1259 | 7b5eff4d | Evgeny Voevodin | } |
1260 | 8170028d | ths | } |
1261 | 8170028d | ths | |
1262 | 30abcfc7 | edgar_igl | static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd, |
1263 | 7b5eff4d | Evgeny Voevodin | int size, int s_ext, TCGv dst) |
1264 | 8170028d | ths | { |
1265 | 7b5eff4d | Evgeny Voevodin | if (s_ext) {
|
1266 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(dst, cpu_R[rs], size); |
1267 | 7b5eff4d | Evgeny Voevodin | } else {
|
1268 | 7b5eff4d | Evgeny Voevodin | t_gen_zext(dst, cpu_R[rs], size); |
1269 | 7b5eff4d | Evgeny Voevodin | } |
1270 | 8170028d | ths | } |
1271 | 8170028d | ths | |
1272 | 8170028d | ths | /* Prepare T0 and T1 for a register alu operation.
|
1273 | 8170028d | ths | s_ext decides if the operand1 should be sign-extended or zero-extended when
|
1274 | 8170028d | ths | needed. */
|
1275 | 8170028d | ths | static void dec_prep_alu_r(DisasContext *dc, int rs, int rd, |
1276 | 7b5eff4d | Evgeny Voevodin | int size, int s_ext, TCGv dst, TCGv src) |
1277 | 8170028d | ths | { |
1278 | 7b5eff4d | Evgeny Voevodin | dec_prep_move_r(dc, rs, rd, size, s_ext, src); |
1279 | 8170028d | ths | |
1280 | 7b5eff4d | Evgeny Voevodin | if (s_ext) {
|
1281 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(dst, cpu_R[rd], size); |
1282 | 7b5eff4d | Evgeny Voevodin | } else {
|
1283 | 7b5eff4d | Evgeny Voevodin | t_gen_zext(dst, cpu_R[rd], size); |
1284 | 7b5eff4d | Evgeny Voevodin | } |
1285 | 8170028d | ths | } |
1286 | 8170028d | ths | |
1287 | cf7e0c80 | Aurelien Jarno | static int dec_prep_move_m(CPUCRISState *env, DisasContext *dc, |
1288 | cf7e0c80 | Aurelien Jarno | int s_ext, int memsize, TCGv dst) |
1289 | 8170028d | ths | { |
1290 | 7b5eff4d | Evgeny Voevodin | unsigned int rs; |
1291 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
1292 | 7b5eff4d | Evgeny Voevodin | int is_imm;
|
1293 | 7b5eff4d | Evgeny Voevodin | int insn_len = 2; |
1294 | 7b5eff4d | Evgeny Voevodin | |
1295 | 7b5eff4d | Evgeny Voevodin | rs = dc->op1; |
1296 | 7b5eff4d | Evgeny Voevodin | is_imm = rs == 15 && dc->postinc;
|
1297 | 7b5eff4d | Evgeny Voevodin | |
1298 | 7b5eff4d | Evgeny Voevodin | /* Load [$rs] onto T1. */
|
1299 | 7b5eff4d | Evgeny Voevodin | if (is_imm) {
|
1300 | 7b5eff4d | Evgeny Voevodin | insn_len = 2 + memsize;
|
1301 | 7b5eff4d | Evgeny Voevodin | if (memsize == 1) { |
1302 | 7b5eff4d | Evgeny Voevodin | insn_len++; |
1303 | 7b5eff4d | Evgeny Voevodin | } |
1304 | 7b5eff4d | Evgeny Voevodin | |
1305 | 7b5eff4d | Evgeny Voevodin | imm = cris_fetch(env, dc, dc->pc + 2, memsize, s_ext);
|
1306 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(dst, imm); |
1307 | 7b5eff4d | Evgeny Voevodin | dc->postinc = 0;
|
1308 | 7b5eff4d | Evgeny Voevodin | } else {
|
1309 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
1310 | 7b5eff4d | Evgeny Voevodin | gen_load(dc, dst, cpu_R[rs], memsize, 0);
|
1311 | 7b5eff4d | Evgeny Voevodin | if (s_ext) {
|
1312 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(dst, dst, memsize); |
1313 | 7b5eff4d | Evgeny Voevodin | } else {
|
1314 | 7b5eff4d | Evgeny Voevodin | t_gen_zext(dst, dst, memsize); |
1315 | 7b5eff4d | Evgeny Voevodin | } |
1316 | 7b5eff4d | Evgeny Voevodin | } |
1317 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
1318 | cf1d97f0 | edgar_igl | } |
1319 | cf1d97f0 | edgar_igl | |
1320 | cf1d97f0 | edgar_igl | /* Prepare T0 and T1 for a memory + alu operation.
|
1321 | cf1d97f0 | edgar_igl | s_ext decides if the operand1 should be sign-extended or zero-extended when
|
1322 | cf1d97f0 | edgar_igl | needed. */
|
1323 | cf7e0c80 | Aurelien Jarno | static int dec_prep_alu_m(CPUCRISState *env, DisasContext *dc, |
1324 | cf7e0c80 | Aurelien Jarno | int s_ext, int memsize, TCGv dst, TCGv src) |
1325 | cf1d97f0 | edgar_igl | { |
1326 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
1327 | cf1d97f0 | edgar_igl | |
1328 | 7b5eff4d | Evgeny Voevodin | insn_len = dec_prep_move_m(env, dc, s_ext, memsize, src); |
1329 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(dst, cpu_R[dc->op2]); |
1330 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
1331 | 8170028d | ths | } |
1332 | 8170028d | ths | |
1333 | 8170028d | ths | #if DISAS_CRIS
|
1334 | 8170028d | ths | static const char *cc_name(int cc) |
1335 | 8170028d | ths | { |
1336 | 7b5eff4d | Evgeny Voevodin | static const char *cc_names[16] = { |
1337 | 7b5eff4d | Evgeny Voevodin | "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", |
1338 | 7b5eff4d | Evgeny Voevodin | "ls", "hi", "ge", "lt", "gt", "le", "a", "p" |
1339 | 7b5eff4d | Evgeny Voevodin | }; |
1340 | 7b5eff4d | Evgeny Voevodin | assert(cc < 16);
|
1341 | 7b5eff4d | Evgeny Voevodin | return cc_names[cc];
|
1342 | 8170028d | ths | } |
1343 | 8170028d | ths | #endif
|
1344 | 8170028d | ths | |
1345 | b41f7df0 | edgar_igl | /* Start of insn decoders. */
|
1346 | b41f7df0 | edgar_igl | |
1347 | cf7e0c80 | Aurelien Jarno | static int dec_bccq(CPUCRISState *env, DisasContext *dc) |
1348 | 8170028d | ths | { |
1349 | 7b5eff4d | Evgeny Voevodin | int32_t offset; |
1350 | 7b5eff4d | Evgeny Voevodin | int sign;
|
1351 | 7b5eff4d | Evgeny Voevodin | uint32_t cond = dc->op2; |
1352 | 8170028d | ths | |
1353 | 7b5eff4d | Evgeny Voevodin | offset = EXTRACT_FIELD(dc->ir, 1, 7); |
1354 | 7b5eff4d | Evgeny Voevodin | sign = EXTRACT_FIELD(dc->ir, 0, 0); |
1355 | 8170028d | ths | |
1356 | 7b5eff4d | Evgeny Voevodin | offset *= 2;
|
1357 | 7b5eff4d | Evgeny Voevodin | offset |= sign << 8;
|
1358 | 7b5eff4d | Evgeny Voevodin | offset = sign_extend(offset, 8);
|
1359 | 8170028d | ths | |
1360 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
|
1361 | 2a44f7f1 | edgar_igl | |
1362 | 7b5eff4d | Evgeny Voevodin | /* op2 holds the condition-code. */
|
1363 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
1364 | 7b5eff4d | Evgeny Voevodin | cris_prepare_cc_branch(dc, offset, cond); |
1365 | 7b5eff4d | Evgeny Voevodin | return 2; |
1366 | 8170028d | ths | } |
1367 | cf7e0c80 | Aurelien Jarno | static int dec_addoq(CPUCRISState *env, DisasContext *dc) |
1368 | 8170028d | ths | { |
1369 | 7b5eff4d | Evgeny Voevodin | int32_t imm; |
1370 | 8170028d | ths | |
1371 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7); |
1372 | 7b5eff4d | Evgeny Voevodin | imm = sign_extend(dc->op1, 7);
|
1373 | 8170028d | ths | |
1374 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
|
1375 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
1376 | 7b5eff4d | Evgeny Voevodin | /* Fetch register operand, */
|
1377 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm); |
1378 | fb48f71b | edgar_igl | |
1379 | 7b5eff4d | Evgeny Voevodin | return 2; |
1380 | 8170028d | ths | } |
1381 | cf7e0c80 | Aurelien Jarno | static int dec_addq(CPUCRISState *env, DisasContext *dc) |
1382 | 8170028d | ths | { |
1383 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
|
1384 | 8170028d | ths | |
1385 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1386 | 8170028d | ths | |
1387 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1388 | 30abcfc7 | edgar_igl | |
1389 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, |
1390 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
|
1391 | 7b5eff4d | Evgeny Voevodin | return 2; |
1392 | 8170028d | ths | } |
1393 | cf7e0c80 | Aurelien Jarno | static int dec_moveq(CPUCRISState *env, DisasContext *dc) |
1394 | 8170028d | ths | { |
1395 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
1396 | 8170028d | ths | |
1397 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1398 | 7b5eff4d | Evgeny Voevodin | imm = sign_extend(dc->op1, 5);
|
1399 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
|
1400 | 8170028d | ths | |
1401 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[dc->op2], imm); |
1402 | 7b5eff4d | Evgeny Voevodin | return 2; |
1403 | 8170028d | ths | } |
1404 | cf7e0c80 | Aurelien Jarno | static int dec_subq(CPUCRISState *env, DisasContext *dc) |
1405 | 8170028d | ths | { |
1406 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1407 | 8170028d | ths | |
1408 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
|
1409 | 8170028d | ths | |
1410 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1411 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, |
1412 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
|
1413 | 7b5eff4d | Evgeny Voevodin | return 2; |
1414 | 8170028d | ths | } |
1415 | cf7e0c80 | Aurelien Jarno | static int dec_cmpq(CPUCRISState *env, DisasContext *dc) |
1416 | 8170028d | ths | { |
1417 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
1418 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1419 | 7b5eff4d | Evgeny Voevodin | imm = sign_extend(dc->op1, 5);
|
1420 | 8170028d | ths | |
1421 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
|
1422 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1423 | 30abcfc7 | edgar_igl | |
1424 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, |
1425 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
|
1426 | 7b5eff4d | Evgeny Voevodin | return 2; |
1427 | 8170028d | ths | } |
1428 | cf7e0c80 | Aurelien Jarno | static int dec_andq(CPUCRISState *env, DisasContext *dc) |
1429 | 8170028d | ths | { |
1430 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
1431 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1432 | 7b5eff4d | Evgeny Voevodin | imm = sign_extend(dc->op1, 5);
|
1433 | 8170028d | ths | |
1434 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
|
1435 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1436 | 30abcfc7 | edgar_igl | |
1437 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_AND, |
1438 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
|
1439 | 7b5eff4d | Evgeny Voevodin | return 2; |
1440 | 8170028d | ths | } |
1441 | cf7e0c80 | Aurelien Jarno | static int dec_orq(CPUCRISState *env, DisasContext *dc) |
1442 | 8170028d | ths | { |
1443 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
1444 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
1445 | 7b5eff4d | Evgeny Voevodin | imm = sign_extend(dc->op1, 5);
|
1446 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
|
1447 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1448 | 30abcfc7 | edgar_igl | |
1449 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_OR, |
1450 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
|
1451 | 7b5eff4d | Evgeny Voevodin | return 2; |
1452 | 8170028d | ths | } |
1453 | cf7e0c80 | Aurelien Jarno | static int dec_btstq(CPUCRISState *env, DisasContext *dc) |
1454 | 8170028d | ths | { |
1455 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
1456 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
|
1457 | 17ac9754 | edgar_igl | |
1458 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1459 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1460 | febc9920 | Aurelien Jarno | gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2], |
1461 | 7b5eff4d | Evgeny Voevodin | tcg_const_tl(dc->op1), cpu_PR[PR_CCS]); |
1462 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1463 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1464 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
1465 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
1466 | 7b5eff4d | Evgeny Voevodin | return 2; |
1467 | 8170028d | ths | } |
1468 | cf7e0c80 | Aurelien Jarno | static int dec_asrq(CPUCRISState *env, DisasContext *dc) |
1469 | 8170028d | ths | { |
1470 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
1471 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
|
1472 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1473 | 30abcfc7 | edgar_igl | |
1474 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
1475 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1476 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], |
1477 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1478 | 7b5eff4d | Evgeny Voevodin | return 2; |
1479 | 8170028d | ths | } |
1480 | cf7e0c80 | Aurelien Jarno | static int dec_lslq(CPUCRISState *env, DisasContext *dc) |
1481 | 8170028d | ths | { |
1482 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
1483 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
|
1484 | 8170028d | ths | |
1485 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1486 | 30abcfc7 | edgar_igl | |
1487 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
1488 | 2a44f7f1 | edgar_igl | |
1489 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1490 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], |
1491 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1492 | 7b5eff4d | Evgeny Voevodin | return 2; |
1493 | 8170028d | ths | } |
1494 | cf7e0c80 | Aurelien Jarno | static int dec_lsrq(CPUCRISState *env, DisasContext *dc) |
1495 | 8170028d | ths | { |
1496 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
1497 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
|
1498 | 8170028d | ths | |
1499 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1500 | 30abcfc7 | edgar_igl | |
1501 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
1502 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1503 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], |
1504 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1505 | 7b5eff4d | Evgeny Voevodin | return 2; |
1506 | 8170028d | ths | } |
1507 | 8170028d | ths | |
1508 | cf7e0c80 | Aurelien Jarno | static int dec_move_r(CPUCRISState *env, DisasContext *dc) |
1509 | 8170028d | ths | { |
1510 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1511 | 7b5eff4d | Evgeny Voevodin | |
1512 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move.%c $r%u, $r%u\n",
|
1513 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1514 | 7b5eff4d | Evgeny Voevodin | |
1515 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1516 | 7b5eff4d | Evgeny Voevodin | if (size == 4) { |
1517 | 7b5eff4d | Evgeny Voevodin | dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
|
1518 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1519 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_MOVE, 4);
|
1520 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_x(dc); |
1521 | 7b5eff4d | Evgeny Voevodin | cris_update_result(dc, cpu_R[dc->op2]); |
1522 | 7b5eff4d | Evgeny Voevodin | } else {
|
1523 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1524 | 7b5eff4d | Evgeny Voevodin | |
1525 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1526 | 7b5eff4d | Evgeny Voevodin | dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
|
1527 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1528 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], |
1529 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], t0, size); |
1530 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1531 | 7b5eff4d | Evgeny Voevodin | } |
1532 | 7b5eff4d | Evgeny Voevodin | return 2; |
1533 | 8170028d | ths | } |
1534 | 8170028d | ths | |
1535 | cf7e0c80 | Aurelien Jarno | static int dec_scc_r(CPUCRISState *env, DisasContext *dc) |
1536 | 8170028d | ths | { |
1537 | 7b5eff4d | Evgeny Voevodin | int cond = dc->op2;
|
1538 | 8170028d | ths | |
1539 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("s%s $r%u\n",
|
1540 | 7b5eff4d | Evgeny Voevodin | cc_name(cond), dc->op1); |
1541 | 8170028d | ths | |
1542 | 7b5eff4d | Evgeny Voevodin | if (cond != CC_A) {
|
1543 | 7b5eff4d | Evgeny Voevodin | int l1;
|
1544 | dceaf394 | edgar_igl | |
1545 | 7b5eff4d | Evgeny Voevodin | gen_tst_cc(dc, cpu_R[dc->op1], cond); |
1546 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
1547 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
|
1548 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[dc->op1], 1);
|
1549 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
1550 | 7b5eff4d | Evgeny Voevodin | } else {
|
1551 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[dc->op1], 1);
|
1552 | 7b5eff4d | Evgeny Voevodin | } |
1553 | 8170028d | ths | |
1554 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
1555 | 7b5eff4d | Evgeny Voevodin | return 2; |
1556 | 8170028d | ths | } |
1557 | 8170028d | ths | |
1558 | fb48f71b | edgar_igl | static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t) |
1559 | fb48f71b | edgar_igl | { |
1560 | 7b5eff4d | Evgeny Voevodin | if (size == 4) { |
1561 | 7b5eff4d | Evgeny Voevodin | t[0] = cpu_R[dc->op2];
|
1562 | 7b5eff4d | Evgeny Voevodin | t[1] = cpu_R[dc->op1];
|
1563 | 7b5eff4d | Evgeny Voevodin | } else {
|
1564 | 7b5eff4d | Evgeny Voevodin | t[0] = tcg_temp_new();
|
1565 | 7b5eff4d | Evgeny Voevodin | t[1] = tcg_temp_new();
|
1566 | 7b5eff4d | Evgeny Voevodin | } |
1567 | fb48f71b | edgar_igl | } |
1568 | fb48f71b | edgar_igl | |
1569 | fb48f71b | edgar_igl | static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t) |
1570 | fb48f71b | edgar_igl | { |
1571 | 7b5eff4d | Evgeny Voevodin | if (size != 4) { |
1572 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[0]);
|
1573 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[1]);
|
1574 | 7b5eff4d | Evgeny Voevodin | } |
1575 | fb48f71b | edgar_igl | } |
1576 | fb48f71b | edgar_igl | |
1577 | cf7e0c80 | Aurelien Jarno | static int dec_and_r(CPUCRISState *env, DisasContext *dc) |
1578 | 8170028d | ths | { |
1579 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1580 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1581 | 8170028d | ths | |
1582 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("and.%c $r%u, $r%u\n",
|
1583 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1584 | fb48f71b | edgar_igl | |
1585 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1586 | 30abcfc7 | edgar_igl | |
1587 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1588 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1589 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size); |
1590 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1591 | 7b5eff4d | Evgeny Voevodin | return 2; |
1592 | 8170028d | ths | } |
1593 | 8170028d | ths | |
1594 | cf7e0c80 | Aurelien Jarno | static int dec_lz_r(CPUCRISState *env, DisasContext *dc) |
1595 | 8170028d | ths | { |
1596 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1597 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lz $r%u, $r%u\n",
|
1598 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1599 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1600 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1601 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0); |
1602 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
1603 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1604 | 7b5eff4d | Evgeny Voevodin | return 2; |
1605 | 8170028d | ths | } |
1606 | 8170028d | ths | |
1607 | cf7e0c80 | Aurelien Jarno | static int dec_lsl_r(CPUCRISState *env, DisasContext *dc) |
1608 | 8170028d | ths | { |
1609 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1610 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1611 | 8170028d | ths | |
1612 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lsl.%c $r%u, $r%u\n",
|
1613 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1614 | 30abcfc7 | edgar_igl | |
1615 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1616 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1617 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1618 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[1], t[1], 63); |
1619 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size); |
1620 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1621 | 7b5eff4d | Evgeny Voevodin | return 2; |
1622 | 8170028d | ths | } |
1623 | 8170028d | ths | |
1624 | cf7e0c80 | Aurelien Jarno | static int dec_lsr_r(CPUCRISState *env, DisasContext *dc) |
1625 | 8170028d | ths | { |
1626 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1627 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1628 | 8170028d | ths | |
1629 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lsr.%c $r%u, $r%u\n",
|
1630 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1631 | 30abcfc7 | edgar_igl | |
1632 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1633 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1634 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1635 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[1], t[1], 63); |
1636 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size); |
1637 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1638 | 7b5eff4d | Evgeny Voevodin | return 2; |
1639 | 8170028d | ths | } |
1640 | 8170028d | ths | |
1641 | cf7e0c80 | Aurelien Jarno | static int dec_asr_r(CPUCRISState *env, DisasContext *dc) |
1642 | 8170028d | ths | { |
1643 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1644 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1645 | 8170028d | ths | |
1646 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("asr.%c $r%u, $r%u\n",
|
1647 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1648 | 30abcfc7 | edgar_igl | |
1649 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1650 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1651 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]); |
1652 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[1], t[1], 63); |
1653 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size); |
1654 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1655 | 7b5eff4d | Evgeny Voevodin | return 2; |
1656 | 8170028d | ths | } |
1657 | 8170028d | ths | |
1658 | cf7e0c80 | Aurelien Jarno | static int dec_muls_r(CPUCRISState *env, DisasContext *dc) |
1659 | 8170028d | ths | { |
1660 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1661 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1662 | 8170028d | ths | |
1663 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("muls.%c $r%u, $r%u\n",
|
1664 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1665 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZV); |
1666 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1667 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]); |
1668 | 30abcfc7 | edgar_igl | |
1669 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4); |
1670 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1671 | 7b5eff4d | Evgeny Voevodin | return 2; |
1672 | 8170028d | ths | } |
1673 | 8170028d | ths | |
1674 | cf7e0c80 | Aurelien Jarno | static int dec_mulu_r(CPUCRISState *env, DisasContext *dc) |
1675 | 8170028d | ths | { |
1676 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1677 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1678 | 8170028d | ths | |
1679 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("mulu.%c $r%u, $r%u\n",
|
1680 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1681 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZV); |
1682 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1683 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1684 | 30abcfc7 | edgar_igl | |
1685 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4); |
1686 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1687 | 7b5eff4d | Evgeny Voevodin | return 2; |
1688 | 8170028d | ths | } |
1689 | 8170028d | ths | |
1690 | 8170028d | ths | |
1691 | cf7e0c80 | Aurelien Jarno | static int dec_dstep_r(CPUCRISState *env, DisasContext *dc) |
1692 | 8170028d | ths | { |
1693 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
|
1694 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1695 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_DSTEP, |
1696 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
|
1697 | 7b5eff4d | Evgeny Voevodin | return 2; |
1698 | 8170028d | ths | } |
1699 | 8170028d | ths | |
1700 | cf7e0c80 | Aurelien Jarno | static int dec_xor_r(CPUCRISState *env, DisasContext *dc) |
1701 | 8170028d | ths | { |
1702 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1703 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1704 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("xor.%c $r%u, $r%u\n",
|
1705 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1706 | 7b5eff4d | Evgeny Voevodin | BUG_ON(size != 4); /* xor is dword. */ |
1707 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1708 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1709 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1710 | 30abcfc7 | edgar_igl | |
1711 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4); |
1712 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1713 | 7b5eff4d | Evgeny Voevodin | return 2; |
1714 | 8170028d | ths | } |
1715 | 8170028d | ths | |
1716 | cf7e0c80 | Aurelien Jarno | static int dec_bound_r(CPUCRISState *env, DisasContext *dc) |
1717 | 8170028d | ths | { |
1718 | 7b5eff4d | Evgeny Voevodin | TCGv l0; |
1719 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1720 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("bound.%c $r%u, $r%u\n",
|
1721 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1722 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1723 | 7b5eff4d | Evgeny Voevodin | l0 = tcg_temp_local_new(); |
1724 | 7b5eff4d | Evgeny Voevodin | dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
|
1725 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
|
1726 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(l0); |
1727 | 7b5eff4d | Evgeny Voevodin | return 2; |
1728 | 8170028d | ths | } |
1729 | 8170028d | ths | |
1730 | cf7e0c80 | Aurelien Jarno | static int dec_cmp_r(CPUCRISState *env, DisasContext *dc) |
1731 | 8170028d | ths | { |
1732 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1733 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1734 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("cmp.%c $r%u, $r%u\n",
|
1735 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1736 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1737 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1738 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1739 | 30abcfc7 | edgar_igl | |
1740 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size); |
1741 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1742 | 7b5eff4d | Evgeny Voevodin | return 2; |
1743 | 8170028d | ths | } |
1744 | 8170028d | ths | |
1745 | cf7e0c80 | Aurelien Jarno | static int dec_abs_r(CPUCRISState *env, DisasContext *dc) |
1746 | 8170028d | ths | { |
1747 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1748 | 3157a0a9 | edgar_igl | |
1749 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("abs $r%u, $r%u\n",
|
1750 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1751 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1752 | 3157a0a9 | edgar_igl | |
1753 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1754 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
|
1755 | 7b5eff4d | Evgeny Voevodin | tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0); |
1756 | 7b5eff4d | Evgeny Voevodin | tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0); |
1757 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1758 | 7dcfb089 | edgar_igl | |
1759 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1760 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1761 | 7b5eff4d | Evgeny Voevodin | return 2; |
1762 | 8170028d | ths | } |
1763 | 8170028d | ths | |
1764 | cf7e0c80 | Aurelien Jarno | static int dec_add_r(CPUCRISState *env, DisasContext *dc) |
1765 | 8170028d | ths | { |
1766 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1767 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1768 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("add.%c $r%u, $r%u\n",
|
1769 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1770 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1771 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1772 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1773 | 30abcfc7 | edgar_igl | |
1774 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size); |
1775 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1776 | 7b5eff4d | Evgeny Voevodin | return 2; |
1777 | 8170028d | ths | } |
1778 | 8170028d | ths | |
1779 | cf7e0c80 | Aurelien Jarno | static int dec_addc_r(CPUCRISState *env, DisasContext *dc) |
1780 | 8170028d | ths | { |
1781 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addc $r%u, $r%u\n",
|
1782 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1783 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1784 | 7b5eff4d | Evgeny Voevodin | /* Set for this insn. */
|
1785 | 7b5eff4d | Evgeny Voevodin | dc->flagx_known = 1;
|
1786 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = X_FLAG; |
1787 | a8cf66bb | edgar_igl | |
1788 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1789 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADDC, |
1790 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
|
1791 | 7b5eff4d | Evgeny Voevodin | return 2; |
1792 | 8170028d | ths | } |
1793 | 8170028d | ths | |
1794 | cf7e0c80 | Aurelien Jarno | static int dec_mcp_r(CPUCRISState *env, DisasContext *dc) |
1795 | 8170028d | ths | { |
1796 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("mcp $p%u, $r%u\n",
|
1797 | 7b5eff4d | Evgeny Voevodin | dc->op2, dc->op1); |
1798 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1799 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_RNZV); |
1800 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MCP, |
1801 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
|
1802 | 7b5eff4d | Evgeny Voevodin | return 2; |
1803 | 8170028d | ths | } |
1804 | 8170028d | ths | |
1805 | 8170028d | ths | #if DISAS_CRIS
|
1806 | 8170028d | ths | static char * swapmode_name(int mode, char *modename) { |
1807 | 7b5eff4d | Evgeny Voevodin | int i = 0; |
1808 | 7b5eff4d | Evgeny Voevodin | if (mode & 8) { |
1809 | 7b5eff4d | Evgeny Voevodin | modename[i++] = 'n';
|
1810 | 7b5eff4d | Evgeny Voevodin | } |
1811 | 7b5eff4d | Evgeny Voevodin | if (mode & 4) { |
1812 | 7b5eff4d | Evgeny Voevodin | modename[i++] = 'w';
|
1813 | 7b5eff4d | Evgeny Voevodin | } |
1814 | 7b5eff4d | Evgeny Voevodin | if (mode & 2) { |
1815 | 7b5eff4d | Evgeny Voevodin | modename[i++] = 'b';
|
1816 | 7b5eff4d | Evgeny Voevodin | } |
1817 | 7b5eff4d | Evgeny Voevodin | if (mode & 1) { |
1818 | 7b5eff4d | Evgeny Voevodin | modename[i++] = 'r';
|
1819 | 7b5eff4d | Evgeny Voevodin | } |
1820 | 7b5eff4d | Evgeny Voevodin | modename[i++] = 0;
|
1821 | 7b5eff4d | Evgeny Voevodin | return modename;
|
1822 | 8170028d | ths | } |
1823 | 8170028d | ths | #endif
|
1824 | 8170028d | ths | |
1825 | cf7e0c80 | Aurelien Jarno | static int dec_swap_r(CPUCRISState *env, DisasContext *dc) |
1826 | 8170028d | ths | { |
1827 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1828 | cf1d97f0 | edgar_igl | #if DISAS_CRIS
|
1829 | 7b5eff4d | Evgeny Voevodin | char modename[4]; |
1830 | cf1d97f0 | edgar_igl | #endif
|
1831 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("swap%s $r%u\n",
|
1832 | 7b5eff4d | Evgeny Voevodin | swapmode_name(dc->op2, modename), dc->op1); |
1833 | 7b5eff4d | Evgeny Voevodin | |
1834 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1835 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1836 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_reg(t0, dc->op1); |
1837 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 & 8) { |
1838 | 7b5eff4d | Evgeny Voevodin | tcg_gen_not_tl(t0, t0); |
1839 | 7b5eff4d | Evgeny Voevodin | } |
1840 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 & 4) { |
1841 | 7b5eff4d | Evgeny Voevodin | t_gen_swapw(t0, t0); |
1842 | 7b5eff4d | Evgeny Voevodin | } |
1843 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 & 2) { |
1844 | 7b5eff4d | Evgeny Voevodin | t_gen_swapb(t0, t0); |
1845 | 7b5eff4d | Evgeny Voevodin | } |
1846 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 & 1) { |
1847 | 7b5eff4d | Evgeny Voevodin | t_gen_swapr(t0, t0); |
1848 | 7b5eff4d | Evgeny Voevodin | } |
1849 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
|
1850 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1851 | 7b5eff4d | Evgeny Voevodin | return 2; |
1852 | 8170028d | ths | } |
1853 | 8170028d | ths | |
1854 | cf7e0c80 | Aurelien Jarno | static int dec_or_r(CPUCRISState *env, DisasContext *dc) |
1855 | 8170028d | ths | { |
1856 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1857 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1858 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("or.%c $r%u, $r%u\n",
|
1859 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1860 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1861 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1862 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1863 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size); |
1864 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1865 | 7b5eff4d | Evgeny Voevodin | return 2; |
1866 | 8170028d | ths | } |
1867 | 8170028d | ths | |
1868 | cf7e0c80 | Aurelien Jarno | static int dec_addi_r(CPUCRISState *env, DisasContext *dc) |
1869 | 8170028d | ths | { |
1870 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1871 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addi.%c $r%u, $r%u\n",
|
1872 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize_zz(dc)), dc->op2, dc->op1); |
1873 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
1874 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1875 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize)); |
1876 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0); |
1877 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1878 | 7b5eff4d | Evgeny Voevodin | return 2; |
1879 | 8170028d | ths | } |
1880 | 8170028d | ths | |
1881 | cf7e0c80 | Aurelien Jarno | static int dec_addi_acr(CPUCRISState *env, DisasContext *dc) |
1882 | 8170028d | ths | { |
1883 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1884 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
|
1885 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize_zz(dc)), dc->op2, dc->op1); |
1886 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
1887 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1888 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize)); |
1889 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0); |
1890 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1891 | 7b5eff4d | Evgeny Voevodin | return 2; |
1892 | 8170028d | ths | } |
1893 | 8170028d | ths | |
1894 | cf7e0c80 | Aurelien Jarno | static int dec_neg_r(CPUCRISState *env, DisasContext *dc) |
1895 | 8170028d | ths | { |
1896 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1897 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1898 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("neg.%c $r%u, $r%u\n",
|
1899 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1900 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1901 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1902 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1903 | 30abcfc7 | edgar_igl | |
1904 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size); |
1905 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1906 | 7b5eff4d | Evgeny Voevodin | return 2; |
1907 | 8170028d | ths | } |
1908 | 8170028d | ths | |
1909 | cf7e0c80 | Aurelien Jarno | static int dec_btst_r(CPUCRISState *env, DisasContext *dc) |
1910 | 8170028d | ths | { |
1911 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("btst $r%u, $r%u\n",
|
1912 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1913 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1914 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
1915 | febc9920 | Aurelien Jarno | gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->op2], |
1916 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op1], cpu_PR[PR_CCS]); |
1917 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], |
1918 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
1919 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
1920 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
1921 | 7b5eff4d | Evgeny Voevodin | return 2; |
1922 | 8170028d | ths | } |
1923 | 8170028d | ths | |
1924 | cf7e0c80 | Aurelien Jarno | static int dec_sub_r(CPUCRISState *env, DisasContext *dc) |
1925 | 8170028d | ths | { |
1926 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
1927 | 7b5eff4d | Evgeny Voevodin | int size = memsize_zz(dc);
|
1928 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("sub.%c $r%u, $r%u\n",
|
1929 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), dc->op1, dc->op2); |
1930 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1931 | 7b5eff4d | Evgeny Voevodin | cris_alu_alloc_temps(dc, size, t); |
1932 | 7b5eff4d | Evgeny Voevodin | dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
1933 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size); |
1934 | 7b5eff4d | Evgeny Voevodin | cris_alu_free_temps(dc, size, t); |
1935 | 7b5eff4d | Evgeny Voevodin | return 2; |
1936 | 8170028d | ths | } |
1937 | 8170028d | ths | |
1938 | 8170028d | ths | /* Zero extension. From size to dword. */
|
1939 | cf7e0c80 | Aurelien Jarno | static int dec_movu_r(CPUCRISState *env, DisasContext *dc) |
1940 | 8170028d | ths | { |
1941 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1942 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
1943 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movu.%c $r%u, $r%u\n",
|
1944 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
1945 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1946 | 8170028d | ths | |
1947 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1948 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1949 | 7b5eff4d | Evgeny Voevodin | dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
|
1950 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
1951 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1952 | 7b5eff4d | Evgeny Voevodin | return 2; |
1953 | 8170028d | ths | } |
1954 | 8170028d | ths | |
1955 | 8170028d | ths | /* Sign extension. From size to dword. */
|
1956 | cf7e0c80 | Aurelien Jarno | static int dec_movs_r(CPUCRISState *env, DisasContext *dc) |
1957 | 8170028d | ths | { |
1958 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1959 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
1960 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movs.%c $r%u, $r%u\n",
|
1961 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
1962 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1963 | 8170028d | ths | |
1964 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
1965 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1966 | 7b5eff4d | Evgeny Voevodin | /* Size can only be qi or hi. */
|
1967 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(t0, cpu_R[dc->op1], size); |
1968 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
1969 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
|
1970 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1971 | 7b5eff4d | Evgeny Voevodin | return 2; |
1972 | 8170028d | ths | } |
1973 | 8170028d | ths | |
1974 | 8170028d | ths | /* zero extension. From size to dword. */
|
1975 | cf7e0c80 | Aurelien Jarno | static int dec_addu_r(CPUCRISState *env, DisasContext *dc) |
1976 | 8170028d | ths | { |
1977 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1978 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
1979 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addu.%c $r%u, $r%u\n",
|
1980 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
1981 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
1982 | 8170028d | ths | |
1983 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
1984 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
1985 | 7b5eff4d | Evgeny Voevodin | /* Size can only be qi or hi. */
|
1986 | 7b5eff4d | Evgeny Voevodin | t_gen_zext(t0, cpu_R[dc->op1], size); |
1987 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
1988 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
1989 | 7b5eff4d | Evgeny Voevodin | return 2; |
1990 | 8170028d | ths | } |
1991 | 05ba7d5f | edgar_igl | |
1992 | 8170028d | ths | /* Sign extension. From size to dword. */
|
1993 | cf7e0c80 | Aurelien Jarno | static int dec_adds_r(CPUCRISState *env, DisasContext *dc) |
1994 | 8170028d | ths | { |
1995 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
1996 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
1997 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("adds.%c $r%u, $r%u\n",
|
1998 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
1999 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
2000 | 8170028d | ths | |
2001 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2002 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2003 | 7b5eff4d | Evgeny Voevodin | /* Size can only be qi or hi. */
|
2004 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(t0, cpu_R[dc->op1], size); |
2005 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, |
2006 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
2007 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2008 | 7b5eff4d | Evgeny Voevodin | return 2; |
2009 | 8170028d | ths | } |
2010 | 8170028d | ths | |
2011 | 8170028d | ths | /* Zero extension. From size to dword. */
|
2012 | cf7e0c80 | Aurelien Jarno | static int dec_subu_r(CPUCRISState *env, DisasContext *dc) |
2013 | 8170028d | ths | { |
2014 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
2015 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
2016 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("subu.%c $r%u, $r%u\n",
|
2017 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
2018 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
2019 | 8170028d | ths | |
2020 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2021 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2022 | 7b5eff4d | Evgeny Voevodin | /* Size can only be qi or hi. */
|
2023 | 7b5eff4d | Evgeny Voevodin | t_gen_zext(t0, cpu_R[dc->op1], size); |
2024 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, |
2025 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
2026 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2027 | 7b5eff4d | Evgeny Voevodin | return 2; |
2028 | 8170028d | ths | } |
2029 | 8170028d | ths | |
2030 | 8170028d | ths | /* Sign extension. From size to dword. */
|
2031 | cf7e0c80 | Aurelien Jarno | static int dec_subs_r(CPUCRISState *env, DisasContext *dc) |
2032 | 8170028d | ths | { |
2033 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
2034 | 7b5eff4d | Evgeny Voevodin | int size = memsize_z(dc);
|
2035 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("subs.%c $r%u, $r%u\n",
|
2036 | 7b5eff4d | Evgeny Voevodin | memsize_char(size), |
2037 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->op2); |
2038 | 8170028d | ths | |
2039 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2040 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2041 | 7b5eff4d | Evgeny Voevodin | /* Size can only be qi or hi. */
|
2042 | 7b5eff4d | Evgeny Voevodin | t_gen_sext(t0, cpu_R[dc->op1], size); |
2043 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, |
2044 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
|
2045 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2046 | 7b5eff4d | Evgeny Voevodin | return 2; |
2047 | 8170028d | ths | } |
2048 | 8170028d | ths | |
2049 | cf7e0c80 | Aurelien Jarno | static int dec_setclrf(CPUCRISState *env, DisasContext *dc) |
2050 | 8170028d | ths | { |
2051 | 7b5eff4d | Evgeny Voevodin | uint32_t flags; |
2052 | 7b5eff4d | Evgeny Voevodin | int set = (~dc->opcode >> 2) & 1; |
2053 | 7b5eff4d | Evgeny Voevodin | |
2054 | 7b5eff4d | Evgeny Voevodin | |
2055 | 7b5eff4d | Evgeny Voevodin | flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) |
2056 | 7b5eff4d | Evgeny Voevodin | | EXTRACT_FIELD(dc->ir, 0, 3); |
2057 | 7b5eff4d | Evgeny Voevodin | if (set && flags == 0) { |
2058 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("nop\n");
|
2059 | 7b5eff4d | Evgeny Voevodin | return 2; |
2060 | 7b5eff4d | Evgeny Voevodin | } else if (!set && (flags & 0x20)) { |
2061 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("di\n");
|
2062 | 7b5eff4d | Evgeny Voevodin | } else {
|
2063 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("%sf %x\n", set ? "set" : "clr", flags); |
2064 | 7b5eff4d | Evgeny Voevodin | } |
2065 | 7b5eff4d | Evgeny Voevodin | |
2066 | 7b5eff4d | Evgeny Voevodin | /* User space is not allowed to touch these. Silently ignore. */
|
2067 | 7b5eff4d | Evgeny Voevodin | if (dc->tb_flags & U_FLAG) {
|
2068 | 7b5eff4d | Evgeny Voevodin | flags &= ~(S_FLAG | I_FLAG | U_FLAG); |
2069 | 7b5eff4d | Evgeny Voevodin | } |
2070 | 7b5eff4d | Evgeny Voevodin | |
2071 | 7b5eff4d | Evgeny Voevodin | if (flags & X_FLAG) {
|
2072 | 7b5eff4d | Evgeny Voevodin | dc->flagx_known = 1;
|
2073 | 7b5eff4d | Evgeny Voevodin | if (set) {
|
2074 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = X_FLAG; |
2075 | 7b5eff4d | Evgeny Voevodin | } else {
|
2076 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = 0;
|
2077 | 7b5eff4d | Evgeny Voevodin | } |
2078 | 7b5eff4d | Evgeny Voevodin | } |
2079 | 7b5eff4d | Evgeny Voevodin | |
2080 | 7b5eff4d | Evgeny Voevodin | /* Break the TB if any of the SPI flag changes. */
|
2081 | 7b5eff4d | Evgeny Voevodin | if (flags & (P_FLAG | S_FLAG)) {
|
2082 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
2083 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
2084 | 7b5eff4d | Evgeny Voevodin | dc->cpustate_changed = 1;
|
2085 | 7b5eff4d | Evgeny Voevodin | } |
2086 | 7b5eff4d | Evgeny Voevodin | |
2087 | 7b5eff4d | Evgeny Voevodin | /* For the I flag, only act on posedge. */
|
2088 | 7b5eff4d | Evgeny Voevodin | if ((flags & I_FLAG)) {
|
2089 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
2090 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
2091 | 7b5eff4d | Evgeny Voevodin | dc->cpustate_changed = 1;
|
2092 | 7b5eff4d | Evgeny Voevodin | } |
2093 | 7b5eff4d | Evgeny Voevodin | |
2094 | 7b5eff4d | Evgeny Voevodin | |
2095 | 7b5eff4d | Evgeny Voevodin | /* Simply decode the flags. */
|
2096 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2097 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
2098 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_x(dc); |
2099 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cc_op, dc->cc_op); |
2100 | 7b5eff4d | Evgeny Voevodin | |
2101 | 7b5eff4d | Evgeny Voevodin | if (set) {
|
2102 | 7b5eff4d | Evgeny Voevodin | if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
|
2103 | 7b5eff4d | Evgeny Voevodin | /* Enter user mode. */
|
2104 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(ksp, cpu_R[R_SP]); |
2105 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]); |
2106 | 7b5eff4d | Evgeny Voevodin | dc->cpustate_changed = 1;
|
2107 | 7b5eff4d | Evgeny Voevodin | } |
2108 | 7b5eff4d | Evgeny Voevodin | tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); |
2109 | 7b5eff4d | Evgeny Voevodin | } else {
|
2110 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags); |
2111 | 7b5eff4d | Evgeny Voevodin | } |
2112 | 7b5eff4d | Evgeny Voevodin | |
2113 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
2114 | 7b5eff4d | Evgeny Voevodin | dc->clear_x = 0;
|
2115 | 7b5eff4d | Evgeny Voevodin | return 2; |
2116 | 8170028d | ths | } |
2117 | 8170028d | ths | |
2118 | cf7e0c80 | Aurelien Jarno | static int dec_move_rs(CPUCRISState *env, DisasContext *dc) |
2119 | 8170028d | ths | { |
2120 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
|
2121 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2122 | febc9920 | Aurelien Jarno | gen_helper_movl_sreg_reg(cpu_env, tcg_const_tl(dc->op2), |
2123 | febc9920 | Aurelien Jarno | tcg_const_tl(dc->op1)); |
2124 | 7b5eff4d | Evgeny Voevodin | return 2; |
2125 | 8170028d | ths | } |
2126 | cf7e0c80 | Aurelien Jarno | static int dec_move_sr(CPUCRISState *env, DisasContext *dc) |
2127 | 8170028d | ths | { |
2128 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
|
2129 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2130 | febc9920 | Aurelien Jarno | gen_helper_movl_reg_sreg(cpu_env, tcg_const_tl(dc->op1), |
2131 | febc9920 | Aurelien Jarno | tcg_const_tl(dc->op2)); |
2132 | 7b5eff4d | Evgeny Voevodin | return 2; |
2133 | 8170028d | ths | } |
2134 | dceaf394 | edgar_igl | |
2135 | cf7e0c80 | Aurelien Jarno | static int dec_move_rp(CPUCRISState *env, DisasContext *dc) |
2136 | 8170028d | ths | { |
2137 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2138 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
|
2139 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2140 | 7b5eff4d | Evgeny Voevodin | |
2141 | 7b5eff4d | Evgeny Voevodin | t[0] = tcg_temp_new();
|
2142 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2143 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2144 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_reg(t[0], dc->op1);
|
2145 | 7b5eff4d | Evgeny Voevodin | if (dc->tb_flags & U_FLAG) {
|
2146 | 7b5eff4d | Evgeny Voevodin | t[1] = tcg_temp_new();
|
2147 | 7b5eff4d | Evgeny Voevodin | /* User space is not allowed to touch all flags. */
|
2148 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[0], t[0], 0x39f); |
2149 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f); |
2150 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(t[0], t[1], t[0]); |
2151 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[1]);
|
2152 | 7b5eff4d | Evgeny Voevodin | } |
2153 | 7b5eff4d | Evgeny Voevodin | } else {
|
2154 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_reg(t[0], dc->op1);
|
2155 | 7b5eff4d | Evgeny Voevodin | } |
2156 | 7b5eff4d | Evgeny Voevodin | |
2157 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, t[0]);
|
2158 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2159 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
2160 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
2161 | 7b5eff4d | Evgeny Voevodin | } |
2162 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[0]);
|
2163 | 7b5eff4d | Evgeny Voevodin | return 2; |
2164 | 8170028d | ths | } |
2165 | cf7e0c80 | Aurelien Jarno | static int dec_move_pr(CPUCRISState *env, DisasContext *dc) |
2166 | 8170028d | ths | { |
2167 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
2168 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
|
2169 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2170 | 2a44f7f1 | edgar_igl | |
2171 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2172 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2173 | 7b5eff4d | Evgeny Voevodin | } |
2174 | 2a44f7f1 | edgar_igl | |
2175 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_DZ) {
|
2176 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[dc->op1], 0);
|
2177 | 7b5eff4d | Evgeny Voevodin | } else {
|
2178 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2179 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(t0, dc->op2); |
2180 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
2181 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op1], cpu_R[dc->op1], t0, |
2182 | 7b5eff4d | Evgeny Voevodin | preg_sizes[dc->op2]); |
2183 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2184 | 7b5eff4d | Evgeny Voevodin | } |
2185 | 7b5eff4d | Evgeny Voevodin | return 2; |
2186 | 8170028d | ths | } |
2187 | 8170028d | ths | |
2188 | cf7e0c80 | Aurelien Jarno | static int dec_move_mr(CPUCRISState *env, DisasContext *dc) |
2189 | 8170028d | ths | { |
2190 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2191 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2192 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move.%c [$r%u%s, $r%u\n",
|
2193 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2194 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2195 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2196 | 7b5eff4d | Evgeny Voevodin | |
2197 | 7b5eff4d | Evgeny Voevodin | if (memsize == 4) { |
2198 | 7b5eff4d | Evgeny Voevodin | insn_len = dec_prep_move_m(env, dc, 0, 4, cpu_R[dc->op2]); |
2199 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2200 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_MOVE, 4);
|
2201 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_x(dc); |
2202 | 7b5eff4d | Evgeny Voevodin | cris_update_result(dc, cpu_R[dc->op2]); |
2203 | 7b5eff4d | Evgeny Voevodin | } else {
|
2204 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
2205 | 7b5eff4d | Evgeny Voevodin | |
2206 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2207 | 7b5eff4d | Evgeny Voevodin | insn_len = dec_prep_move_m(env, dc, 0, memsize, t0);
|
2208 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2209 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
2210 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize); |
2211 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2212 | 7b5eff4d | Evgeny Voevodin | } |
2213 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2214 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2215 | 8170028d | ths | } |
2216 | 8170028d | ths | |
2217 | 31c18d87 | edgar_igl | static inline void cris_alu_m_alloc_temps(TCGv *t) |
2218 | 31c18d87 | edgar_igl | { |
2219 | 7b5eff4d | Evgeny Voevodin | t[0] = tcg_temp_new();
|
2220 | 7b5eff4d | Evgeny Voevodin | t[1] = tcg_temp_new();
|
2221 | 31c18d87 | edgar_igl | } |
2222 | 31c18d87 | edgar_igl | |
2223 | 31c18d87 | edgar_igl | static inline void cris_alu_m_free_temps(TCGv *t) |
2224 | 31c18d87 | edgar_igl | { |
2225 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[0]);
|
2226 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t[1]);
|
2227 | 31c18d87 | edgar_igl | } |
2228 | 31c18d87 | edgar_igl | |
2229 | cf7e0c80 | Aurelien Jarno | static int dec_movs_m(CPUCRISState *env, DisasContext *dc) |
2230 | 8170028d | ths | { |
2231 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2232 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2233 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2234 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movs.%c [$r%u%s, $r%u\n",
|
2235 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2236 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2237 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2238 | 8170028d | ths | |
2239 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2240 | 7b5eff4d | Evgeny Voevodin | /* sign extend. */
|
2241 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); |
2242 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2243 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, |
2244 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2245 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2246 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2247 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2248 | 8170028d | ths | } |
2249 | 8170028d | ths | |
2250 | cf7e0c80 | Aurelien Jarno | static int dec_addu_m(CPUCRISState *env, DisasContext *dc) |
2251 | 8170028d | ths | { |
2252 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2253 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2254 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2255 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addu.%c [$r%u%s, $r%u\n",
|
2256 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2257 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2258 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2259 | 8170028d | ths | |
2260 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2261 | 7b5eff4d | Evgeny Voevodin | /* sign extend. */
|
2262 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2263 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2264 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, |
2265 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2266 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2267 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2268 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2269 | 8170028d | ths | } |
2270 | 8170028d | ths | |
2271 | cf7e0c80 | Aurelien Jarno | static int dec_adds_m(CPUCRISState *env, DisasContext *dc) |
2272 | 8170028d | ths | { |
2273 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2274 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2275 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2276 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("adds.%c [$r%u%s, $r%u\n",
|
2277 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2278 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2279 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2280 | 8170028d | ths | |
2281 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2282 | 7b5eff4d | Evgeny Voevodin | /* sign extend. */
|
2283 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); |
2284 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2285 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2286 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2287 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2288 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2289 | 8170028d | ths | } |
2290 | 8170028d | ths | |
2291 | cf7e0c80 | Aurelien Jarno | static int dec_subu_m(CPUCRISState *env, DisasContext *dc) |
2292 | 8170028d | ths | { |
2293 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2294 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2295 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2296 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("subu.%c [$r%u%s, $r%u\n",
|
2297 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2298 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2299 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2300 | 8170028d | ths | |
2301 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2302 | 7b5eff4d | Evgeny Voevodin | /* sign extend. */
|
2303 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2304 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2305 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2306 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2307 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2308 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2309 | 8170028d | ths | } |
2310 | 8170028d | ths | |
2311 | cf7e0c80 | Aurelien Jarno | static int dec_subs_m(CPUCRISState *env, DisasContext *dc) |
2312 | 8170028d | ths | { |
2313 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2314 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2315 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2316 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("subs.%c [$r%u%s, $r%u\n",
|
2317 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2318 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2319 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2320 | 8170028d | ths | |
2321 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2322 | 7b5eff4d | Evgeny Voevodin | /* sign extend. */
|
2323 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); |
2324 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2325 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2326 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2327 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2328 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2329 | 8170028d | ths | } |
2330 | 8170028d | ths | |
2331 | cf7e0c80 | Aurelien Jarno | static int dec_movu_m(CPUCRISState *env, DisasContext *dc) |
2332 | 8170028d | ths | { |
2333 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2334 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2335 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2336 | 8170028d | ths | |
2337 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movu.%c [$r%u%s, $r%u\n",
|
2338 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2339 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2340 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2341 | 8170028d | ths | |
2342 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2343 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2344 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2345 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2346 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2347 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2348 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2349 | 8170028d | ths | } |
2350 | 8170028d | ths | |
2351 | cf7e0c80 | Aurelien Jarno | static int dec_cmpu_m(CPUCRISState *env, DisasContext *dc) |
2352 | 8170028d | ths | { |
2353 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2354 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2355 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2356 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
|
2357 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2358 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2359 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2360 | 8170028d | ths | |
2361 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2362 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2363 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2364 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
2365 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2366 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2367 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2368 | 8170028d | ths | } |
2369 | 8170028d | ths | |
2370 | cf7e0c80 | Aurelien Jarno | static int dec_cmps_m(CPUCRISState *env, DisasContext *dc) |
2371 | 8170028d | ths | { |
2372 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2373 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_z(dc);
|
2374 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2375 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
|
2376 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2377 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2378 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2379 | 8170028d | ths | |
2380 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2381 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); |
2382 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2383 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, |
2384 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t[1],
|
2385 | 7b5eff4d | Evgeny Voevodin | memsize_zz(dc)); |
2386 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2387 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2388 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2389 | 8170028d | ths | } |
2390 | 8170028d | ths | |
2391 | cf7e0c80 | Aurelien Jarno | static int dec_cmp_m(CPUCRISState *env, DisasContext *dc) |
2392 | 8170028d | ths | { |
2393 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2394 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2395 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2396 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
|
2397 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2398 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2399 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2400 | 8170028d | ths | |
2401 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2402 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2403 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2404 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, |
2405 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], cpu_R[dc->op2], t[1],
|
2406 | 7b5eff4d | Evgeny Voevodin | memsize_zz(dc)); |
2407 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2408 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2409 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2410 | 8170028d | ths | } |
2411 | 8170028d | ths | |
2412 | cf7e0c80 | Aurelien Jarno | static int dec_test_m(CPUCRISState *env, DisasContext *dc) |
2413 | 8170028d | ths | { |
2414 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2415 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2416 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2417 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("test.%c [$r%u%s] op2=%x\n",
|
2418 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2419 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2420 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2421 | 8170028d | ths | |
2422 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2423 | dceaf394 | edgar_igl | |
2424 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2425 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2426 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2427 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
|
2428 | b41f7df0 | edgar_igl | |
2429 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_CMP, |
2430 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc)); |
2431 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2432 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2433 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2434 | 8170028d | ths | } |
2435 | 8170028d | ths | |
2436 | cf7e0c80 | Aurelien Jarno | static int dec_and_m(CPUCRISState *env, DisasContext *dc) |
2437 | 8170028d | ths | { |
2438 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2439 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2440 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2441 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("and.%c [$r%u%s, $r%u\n",
|
2442 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2443 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2444 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2445 | 8170028d | ths | |
2446 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2447 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2448 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2449 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
2450 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2451 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2452 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2453 | 8170028d | ths | } |
2454 | 8170028d | ths | |
2455 | cf7e0c80 | Aurelien Jarno | static int dec_add_m(CPUCRISState *env, DisasContext *dc) |
2456 | 8170028d | ths | { |
2457 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2458 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2459 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2460 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("add.%c [$r%u%s, $r%u\n",
|
2461 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2462 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2463 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2464 | 8170028d | ths | |
2465 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2466 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2467 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2468 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, |
2469 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
2470 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2471 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2472 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2473 | 8170028d | ths | } |
2474 | 8170028d | ths | |
2475 | cf7e0c80 | Aurelien Jarno | static int dec_addo_m(CPUCRISState *env, DisasContext *dc) |
2476 | 8170028d | ths | { |
2477 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2478 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2479 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2480 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("add.%c [$r%u%s, $r%u\n",
|
2481 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2482 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2483 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2484 | 8170028d | ths | |
2485 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2486 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]); |
2487 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2488 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4); |
2489 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2490 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2491 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2492 | 8170028d | ths | } |
2493 | 8170028d | ths | |
2494 | cf7e0c80 | Aurelien Jarno | static int dec_bound_m(CPUCRISState *env, DisasContext *dc) |
2495 | 8170028d | ths | { |
2496 | 7b5eff4d | Evgeny Voevodin | TCGv l[2];
|
2497 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2498 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2499 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("bound.%c [$r%u%s, $r%u\n",
|
2500 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2501 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2502 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2503 | 8170028d | ths | |
2504 | 7b5eff4d | Evgeny Voevodin | l[0] = tcg_temp_local_new();
|
2505 | 7b5eff4d | Evgeny Voevodin | l[1] = tcg_temp_local_new();
|
2506 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, l[0], l[1]); |
2507 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2508 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4); |
2509 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2510 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(l[0]);
|
2511 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(l[1]);
|
2512 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2513 | 8170028d | ths | } |
2514 | 8170028d | ths | |
2515 | cf7e0c80 | Aurelien Jarno | static int dec_addc_mr(CPUCRISState *env, DisasContext *dc) |
2516 | 8170028d | ths | { |
2517 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2518 | 7b5eff4d | Evgeny Voevodin | int insn_len = 2; |
2519 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("addc [$r%u%s, $r%u\n",
|
2520 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2521 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2522 | 8170028d | ths | |
2523 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2524 | a8cf66bb | edgar_igl | |
2525 | 7b5eff4d | Evgeny Voevodin | /* Set for this insn. */
|
2526 | 7b5eff4d | Evgeny Voevodin | dc->flagx_known = 1;
|
2527 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = X_FLAG; |
2528 | a8cf66bb | edgar_igl | |
2529 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2530 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, 4, t[0], t[1]); |
2531 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2532 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4); |
2533 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, 4);
|
2534 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2535 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2536 | 8170028d | ths | } |
2537 | 8170028d | ths | |
2538 | cf7e0c80 | Aurelien Jarno | static int dec_sub_m(CPUCRISState *env, DisasContext *dc) |
2539 | 8170028d | ths | { |
2540 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2541 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2542 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2543 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
|
2544 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2545 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2546 | 7b5eff4d | Evgeny Voevodin | dc->op2, dc->ir, dc->zzsize); |
2547 | 8170028d | ths | |
2548 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2549 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2550 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZVC); |
2551 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize); |
2552 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2553 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2554 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2555 | 8170028d | ths | } |
2556 | 8170028d | ths | |
2557 | cf7e0c80 | Aurelien Jarno | static int dec_or_m(CPUCRISState *env, DisasContext *dc) |
2558 | 8170028d | ths | { |
2559 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2560 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2561 | 7b5eff4d | Evgeny Voevodin | int insn_len;
|
2562 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
|
2563 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2564 | 7b5eff4d | Evgeny Voevodin | dc->op1, dc->postinc ? "+]" : "]", |
2565 | 7b5eff4d | Evgeny Voevodin | dc->op2, dc->pc); |
2566 | 8170028d | ths | |
2567 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2568 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2569 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, CC_MASK_NZ); |
2570 | 7b5eff4d | Evgeny Voevodin | cris_alu(dc, CC_OP_OR, |
2571 | 7b5eff4d | Evgeny Voevodin | cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
2572 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2573 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2574 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2575 | 8170028d | ths | } |
2576 | 8170028d | ths | |
2577 | cf7e0c80 | Aurelien Jarno | static int dec_move_mp(CPUCRISState *env, DisasContext *dc) |
2578 | 8170028d | ths | { |
2579 | 7b5eff4d | Evgeny Voevodin | TCGv t[2];
|
2580 | 7b5eff4d | Evgeny Voevodin | int memsize = memsize_zz(dc);
|
2581 | 7b5eff4d | Evgeny Voevodin | int insn_len = 2; |
2582 | 8170028d | ths | |
2583 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move.%c [$r%u%s, $p%u\n",
|
2584 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2585 | 7b5eff4d | Evgeny Voevodin | dc->op1, |
2586 | 7b5eff4d | Evgeny Voevodin | dc->postinc ? "+]" : "]", |
2587 | 7b5eff4d | Evgeny Voevodin | dc->op2); |
2588 | 8170028d | ths | |
2589 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_alloc_temps(t); |
2590 | cf7e0c80 | Aurelien Jarno | insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]); |
2591 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2592 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2593 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2594 | 7b5eff4d | Evgeny Voevodin | if (dc->tb_flags & U_FLAG) {
|
2595 | 7b5eff4d | Evgeny Voevodin | /* User space is not allowed to touch all flags. */
|
2596 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[1], t[1], 0x39f); |
2597 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f); |
2598 | 7b5eff4d | Evgeny Voevodin | tcg_gen_or_tl(t[1], t[0], t[1]); |
2599 | 7b5eff4d | Evgeny Voevodin | } |
2600 | 7b5eff4d | Evgeny Voevodin | } |
2601 | b41f7df0 | edgar_igl | |
2602 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, t[1]);
|
2603 | 8170028d | ths | |
2604 | 7b5eff4d | Evgeny Voevodin | do_postinc(dc, memsize); |
2605 | 7b5eff4d | Evgeny Voevodin | cris_alu_m_free_temps(t); |
2606 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
2607 | 8170028d | ths | } |
2608 | 8170028d | ths | |
2609 | cf7e0c80 | Aurelien Jarno | static int dec_move_pm(CPUCRISState *env, DisasContext *dc) |
2610 | 8170028d | ths | { |
2611 | 7b5eff4d | Evgeny Voevodin | TCGv t0; |
2612 | 7b5eff4d | Evgeny Voevodin | int memsize;
|
2613 | 8170028d | ths | |
2614 | 7b5eff4d | Evgeny Voevodin | memsize = preg_sizes[dc->op2]; |
2615 | 8170028d | ths | |
2616 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move.%c $p%u, [$r%u%s\n",
|
2617 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), |
2618 | 7b5eff4d | Evgeny Voevodin | dc->op2, dc->op1, dc->postinc ? "+]" : "]"); |
2619 | 8170028d | ths | |
2620 | 7b5eff4d | Evgeny Voevodin | /* prepare store. Address in T0, value in T1. */
|
2621 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2622 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2623 | 7b5eff4d | Evgeny Voevodin | } |
2624 | 7b5eff4d | Evgeny Voevodin | t0 = tcg_temp_new(); |
2625 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(t0, dc->op2); |
2626 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
2627 | 7b5eff4d | Evgeny Voevodin | gen_store(dc, cpu_R[dc->op1], t0, memsize); |
2628 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(t0); |
2629 | 7b5eff4d | Evgeny Voevodin | |
2630 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2631 | 7b5eff4d | Evgeny Voevodin | if (dc->postinc) {
|
2632 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); |
2633 | 7b5eff4d | Evgeny Voevodin | } |
2634 | 7b5eff4d | Evgeny Voevodin | return 2; |
2635 | 8170028d | ths | } |
2636 | 8170028d | ths | |
2637 | cf7e0c80 | Aurelien Jarno | static int dec_movem_mr(CPUCRISState *env, DisasContext *dc) |
2638 | 8170028d | ths | { |
2639 | 7b5eff4d | Evgeny Voevodin | TCGv_i64 tmp[16];
|
2640 | 7b5eff4d | Evgeny Voevodin | TCGv tmp32; |
2641 | 7b5eff4d | Evgeny Voevodin | TCGv addr; |
2642 | 7b5eff4d | Evgeny Voevodin | int i;
|
2643 | 7b5eff4d | Evgeny Voevodin | int nr = dc->op2 + 1; |
2644 | 7b5eff4d | Evgeny Voevodin | |
2645 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
|
2646 | 7b5eff4d | Evgeny Voevodin | dc->postinc ? "+]" : "]", dc->op2); |
2647 | 7b5eff4d | Evgeny Voevodin | |
2648 | 7b5eff4d | Evgeny Voevodin | addr = tcg_temp_new(); |
2649 | 7b5eff4d | Evgeny Voevodin | /* There are probably better ways of doing this. */
|
2650 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
2651 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < (nr >> 1); i++) { |
2652 | 7b5eff4d | Evgeny Voevodin | tmp[i] = tcg_temp_new_i64(); |
2653 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
|
2654 | 7b5eff4d | Evgeny Voevodin | gen_load64(dc, tmp[i], addr); |
2655 | 7b5eff4d | Evgeny Voevodin | } |
2656 | 7b5eff4d | Evgeny Voevodin | if (nr & 1) { |
2657 | 7b5eff4d | Evgeny Voevodin | tmp32 = tcg_temp_new_i32(); |
2658 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
|
2659 | 7b5eff4d | Evgeny Voevodin | gen_load(dc, tmp32, addr, 4, 0); |
2660 | 7b5eff4d | Evgeny Voevodin | } else {
|
2661 | 7b5eff4d | Evgeny Voevodin | TCGV_UNUSED(tmp32); |
2662 | 7b5eff4d | Evgeny Voevodin | } |
2663 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(addr); |
2664 | 7b5eff4d | Evgeny Voevodin | |
2665 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < (nr >> 1); i++) { |
2666 | 7b5eff4d | Evgeny Voevodin | tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
|
2667 | 7b5eff4d | Evgeny Voevodin | tcg_gen_shri_i64(tmp[i], tmp[i], 32);
|
2668 | 7b5eff4d | Evgeny Voevodin | tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]); |
2669 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free_i64(tmp[i]); |
2670 | 7b5eff4d | Evgeny Voevodin | } |
2671 | 7b5eff4d | Evgeny Voevodin | if (nr & 1) { |
2672 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cpu_R[dc->op2], tmp32); |
2673 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(tmp32); |
2674 | 7b5eff4d | Evgeny Voevodin | } |
2675 | 7b5eff4d | Evgeny Voevodin | |
2676 | 7b5eff4d | Evgeny Voevodin | /* writeback the updated pointer value. */
|
2677 | 7b5eff4d | Evgeny Voevodin | if (dc->postinc) {
|
2678 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
|
2679 | 7b5eff4d | Evgeny Voevodin | } |
2680 | 7b5eff4d | Evgeny Voevodin | |
2681 | 7b5eff4d | Evgeny Voevodin | /* gen_load might want to evaluate the previous insns flags. */
|
2682 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2683 | 7b5eff4d | Evgeny Voevodin | return 2; |
2684 | 8170028d | ths | } |
2685 | 8170028d | ths | |
2686 | cf7e0c80 | Aurelien Jarno | static int dec_movem_rm(CPUCRISState *env, DisasContext *dc) |
2687 | 8170028d | ths | { |
2688 | 7b5eff4d | Evgeny Voevodin | TCGv tmp; |
2689 | 7b5eff4d | Evgeny Voevodin | TCGv addr; |
2690 | 7b5eff4d | Evgeny Voevodin | int i;
|
2691 | 7b5eff4d | Evgeny Voevodin | |
2692 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
|
2693 | 7b5eff4d | Evgeny Voevodin | dc->postinc ? "+]" : "]"); |
2694 | 7b5eff4d | Evgeny Voevodin | |
2695 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
2696 | 7b5eff4d | Evgeny Voevodin | |
2697 | 7b5eff4d | Evgeny Voevodin | tmp = tcg_temp_new(); |
2698 | 7b5eff4d | Evgeny Voevodin | addr = tcg_temp_new(); |
2699 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(tmp, 4);
|
2700 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(addr, cpu_R[dc->op1]); |
2701 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i <= dc->op2; i++) { |
2702 | 7b5eff4d | Evgeny Voevodin | /* Displace addr. */
|
2703 | 7b5eff4d | Evgeny Voevodin | /* Perform the store. */
|
2704 | 7b5eff4d | Evgeny Voevodin | gen_store(dc, addr, cpu_R[i], 4);
|
2705 | 7b5eff4d | Evgeny Voevodin | tcg_gen_add_tl(addr, addr, tmp); |
2706 | 7b5eff4d | Evgeny Voevodin | } |
2707 | 7b5eff4d | Evgeny Voevodin | if (dc->postinc) {
|
2708 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(cpu_R[dc->op1], addr); |
2709 | 7b5eff4d | Evgeny Voevodin | } |
2710 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2711 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(tmp); |
2712 | 7b5eff4d | Evgeny Voevodin | tcg_temp_free(addr); |
2713 | 7b5eff4d | Evgeny Voevodin | return 2; |
2714 | 8170028d | ths | } |
2715 | 8170028d | ths | |
2716 | cf7e0c80 | Aurelien Jarno | static int dec_move_rm(CPUCRISState *env, DisasContext *dc) |
2717 | 8170028d | ths | { |
2718 | 7b5eff4d | Evgeny Voevodin | int memsize;
|
2719 | 8170028d | ths | |
2720 | 7b5eff4d | Evgeny Voevodin | memsize = memsize_zz(dc); |
2721 | 8170028d | ths | |
2722 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("move.%c $r%u, [$r%u]\n",
|
2723 | 7b5eff4d | Evgeny Voevodin | memsize_char(memsize), dc->op2, dc->op1); |
2724 | 8170028d | ths | |
2725 | 7b5eff4d | Evgeny Voevodin | /* prepare store. */
|
2726 | 7b5eff4d | Evgeny Voevodin | cris_flush_cc_state(dc); |
2727 | 7b5eff4d | Evgeny Voevodin | gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize); |
2728 | 17ac9754 | edgar_igl | |
2729 | 7b5eff4d | Evgeny Voevodin | if (dc->postinc) {
|
2730 | 7b5eff4d | Evgeny Voevodin | tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); |
2731 | 7b5eff4d | Evgeny Voevodin | } |
2732 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2733 | 7b5eff4d | Evgeny Voevodin | return 2; |
2734 | 8170028d | ths | } |
2735 | 8170028d | ths | |
2736 | cf7e0c80 | Aurelien Jarno | static int dec_lapcq(CPUCRISState *env, DisasContext *dc) |
2737 | 8170028d | ths | { |
2738 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lapcq %x, $r%u\n",
|
2739 | 7b5eff4d | Evgeny Voevodin | dc->pc + dc->op1*2, dc->op2);
|
2740 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2741 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
|
2742 | 7b5eff4d | Evgeny Voevodin | return 2; |
2743 | 8170028d | ths | } |
2744 | 8170028d | ths | |
2745 | cf7e0c80 | Aurelien Jarno | static int dec_lapc_im(CPUCRISState *env, DisasContext *dc) |
2746 | 8170028d | ths | { |
2747 | 7b5eff4d | Evgeny Voevodin | unsigned int rd; |
2748 | 7b5eff4d | Evgeny Voevodin | int32_t imm; |
2749 | 7b5eff4d | Evgeny Voevodin | int32_t pc; |
2750 | 8170028d | ths | |
2751 | 7b5eff4d | Evgeny Voevodin | rd = dc->op2; |
2752 | 8170028d | ths | |
2753 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2754 | 7b5eff4d | Evgeny Voevodin | imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); |
2755 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
|
2756 | b41f7df0 | edgar_igl | |
2757 | 7b5eff4d | Evgeny Voevodin | pc = dc->pc; |
2758 | 7b5eff4d | Evgeny Voevodin | pc += imm; |
2759 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_R[rd], pc); |
2760 | 7b5eff4d | Evgeny Voevodin | return 6; |
2761 | 8170028d | ths | } |
2762 | 8170028d | ths | |
2763 | 8170028d | ths | /* Jump to special reg. */
|
2764 | cf7e0c80 | Aurelien Jarno | static int dec_jump_p(CPUCRISState *env, DisasContext *dc) |
2765 | 8170028d | ths | { |
2766 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("jump $p%u\n", dc->op2);
|
2767 | b41f7df0 | edgar_igl | |
2768 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == PR_CCS) {
|
2769 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2770 | 7b5eff4d | Evgeny Voevodin | } |
2771 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_TN_preg(env_btarget, dc->op2); |
2772 | 7b5eff4d | Evgeny Voevodin | /* rete will often have low bit set to indicate delayslot. */
|
2773 | 7b5eff4d | Evgeny Voevodin | tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
|
2774 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2775 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_INDIRECT); |
2776 | 7b5eff4d | Evgeny Voevodin | return 2; |
2777 | 8170028d | ths | } |
2778 | 8170028d | ths | |
2779 | 8170028d | ths | /* Jump and save. */
|
2780 | cf7e0c80 | Aurelien Jarno | static int dec_jas_r(CPUCRISState *env, DisasContext *dc) |
2781 | 8170028d | ths | { |
2782 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
|
2783 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2784 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2785 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); |
2786 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 > 15) { |
2787 | 7b5eff4d | Evgeny Voevodin | abort(); |
2788 | 7b5eff4d | Evgeny Voevodin | } |
2789 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
|
2790 | b41f7df0 | edgar_igl | |
2791 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_INDIRECT); |
2792 | 7b5eff4d | Evgeny Voevodin | return 2; |
2793 | 8170028d | ths | } |
2794 | 8170028d | ths | |
2795 | cf7e0c80 | Aurelien Jarno | static int dec_jas_im(CPUCRISState *env, DisasContext *dc) |
2796 | 8170028d | ths | { |
2797 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
2798 | 8170028d | ths | |
2799 | 7b5eff4d | Evgeny Voevodin | imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); |
2800 | 8170028d | ths | |
2801 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("jas 0x%x\n", imm);
|
2802 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2803 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2804 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
|
2805 | 2a44f7f1 | edgar_igl | |
2806 | 7b5eff4d | Evgeny Voevodin | dc->jmp_pc = imm; |
2807 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_DIRECT); |
2808 | 7b5eff4d | Evgeny Voevodin | return 6; |
2809 | 8170028d | ths | } |
2810 | 8170028d | ths | |
2811 | cf7e0c80 | Aurelien Jarno | static int dec_jasc_im(CPUCRISState *env, DisasContext *dc) |
2812 | 8170028d | ths | { |
2813 | 7b5eff4d | Evgeny Voevodin | uint32_t imm; |
2814 | 8170028d | ths | |
2815 | 7b5eff4d | Evgeny Voevodin | imm = cris_fetch(env, dc, dc->pc + 2, 4, 0); |
2816 | 8170028d | ths | |
2817 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("jasc 0x%x\n", imm);
|
2818 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2819 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2820 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4)); |
2821 | 2a44f7f1 | edgar_igl | |
2822 | 7b5eff4d | Evgeny Voevodin | dc->jmp_pc = imm; |
2823 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_DIRECT); |
2824 | 7b5eff4d | Evgeny Voevodin | return 6; |
2825 | 8170028d | ths | } |
2826 | 8170028d | ths | |
2827 | cf7e0c80 | Aurelien Jarno | static int dec_jasc_r(CPUCRISState *env, DisasContext *dc) |
2828 | 8170028d | ths | { |
2829 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
|
2830 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2831 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2832 | 7b5eff4d | Evgeny Voevodin | tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); |
2833 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4)); |
2834 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_INDIRECT); |
2835 | 7b5eff4d | Evgeny Voevodin | return 2; |
2836 | 8170028d | ths | } |
2837 | 8170028d | ths | |
2838 | cf7e0c80 | Aurelien Jarno | static int dec_bcc_im(CPUCRISState *env, DisasContext *dc) |
2839 | 8170028d | ths | { |
2840 | 7b5eff4d | Evgeny Voevodin | int32_t offset; |
2841 | 7b5eff4d | Evgeny Voevodin | uint32_t cond = dc->op2; |
2842 | 8170028d | ths | |
2843 | 7b5eff4d | Evgeny Voevodin | offset = cris_fetch(env, dc, dc->pc + 2, 2, 1); |
2844 | 8170028d | ths | |
2845 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("b%s %d pc=%x dst=%x\n",
|
2846 | 7b5eff4d | Evgeny Voevodin | cc_name(cond), offset, |
2847 | 7b5eff4d | Evgeny Voevodin | dc->pc, dc->pc + offset); |
2848 | 8170028d | ths | |
2849 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2850 | 7b5eff4d | Evgeny Voevodin | /* op2 holds the condition-code. */
|
2851 | 7b5eff4d | Evgeny Voevodin | cris_prepare_cc_branch(dc, offset, cond); |
2852 | 7b5eff4d | Evgeny Voevodin | return 4; |
2853 | 8170028d | ths | } |
2854 | 8170028d | ths | |
2855 | cf7e0c80 | Aurelien Jarno | static int dec_bas_im(CPUCRISState *env, DisasContext *dc) |
2856 | 8170028d | ths | { |
2857 | 7b5eff4d | Evgeny Voevodin | int32_t simm; |
2858 | 8170028d | ths | |
2859 | 7b5eff4d | Evgeny Voevodin | simm = cris_fetch(env, dc, dc->pc + 2, 4, 0); |
2860 | 8170028d | ths | |
2861 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
|
2862 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2863 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2864 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
|
2865 | 8170028d | ths | |
2866 | 7b5eff4d | Evgeny Voevodin | dc->jmp_pc = dc->pc + simm; |
2867 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_DIRECT); |
2868 | 7b5eff4d | Evgeny Voevodin | return 6; |
2869 | 8170028d | ths | } |
2870 | 8170028d | ths | |
2871 | cf7e0c80 | Aurelien Jarno | static int dec_basc_im(CPUCRISState *env, DisasContext *dc) |
2872 | 8170028d | ths | { |
2873 | 7b5eff4d | Evgeny Voevodin | int32_t simm; |
2874 | 7b5eff4d | Evgeny Voevodin | simm = cris_fetch(env, dc, dc->pc + 2, 4, 0); |
2875 | 8170028d | ths | |
2876 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
|
2877 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2878 | 7b5eff4d | Evgeny Voevodin | /* Store the return address in Pd. */
|
2879 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
|
2880 | 2a44f7f1 | edgar_igl | |
2881 | 7b5eff4d | Evgeny Voevodin | dc->jmp_pc = dc->pc + simm; |
2882 | 7b5eff4d | Evgeny Voevodin | cris_prepare_jmp(dc, JMP_DIRECT); |
2883 | 7b5eff4d | Evgeny Voevodin | return 6; |
2884 | 8170028d | ths | } |
2885 | 8170028d | ths | |
2886 | cf7e0c80 | Aurelien Jarno | static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc) |
2887 | 8170028d | ths | { |
2888 | 7b5eff4d | Evgeny Voevodin | cris_cc_mask(dc, 0);
|
2889 | 7b5eff4d | Evgeny Voevodin | |
2890 | 7b5eff4d | Evgeny Voevodin | if (dc->op2 == 15) { |
2891 | 259186a7 | Andreas Färber | tcg_gen_st_i32(tcg_const_i32(1), cpu_env,
|
2892 | 259186a7 | Andreas Färber | -offsetof(CRISCPU, env) + offsetof(CPUState, halted)); |
2893 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
2894 | 7b5eff4d | Evgeny Voevodin | t_gen_raise_exception(EXCP_HLT); |
2895 | 7b5eff4d | Evgeny Voevodin | return 2; |
2896 | 7b5eff4d | Evgeny Voevodin | } |
2897 | 7b5eff4d | Evgeny Voevodin | |
2898 | 7b5eff4d | Evgeny Voevodin | switch (dc->op2 & 7) { |
2899 | 7b5eff4d | Evgeny Voevodin | case 2: |
2900 | 7b5eff4d | Evgeny Voevodin | /* rfe. */
|
2901 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("rfe\n");
|
2902 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2903 | 7b5eff4d | Evgeny Voevodin | gen_helper_rfe(cpu_env); |
2904 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
2905 | 7b5eff4d | Evgeny Voevodin | break;
|
2906 | 7b5eff4d | Evgeny Voevodin | case 5: |
2907 | 7b5eff4d | Evgeny Voevodin | /* rfn. */
|
2908 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("rfn\n");
|
2909 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2910 | 7b5eff4d | Evgeny Voevodin | gen_helper_rfn(cpu_env); |
2911 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
2912 | 7b5eff4d | Evgeny Voevodin | break;
|
2913 | 7b5eff4d | Evgeny Voevodin | case 6: |
2914 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("break %d\n", dc->op1);
|
2915 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
2916 | 7b5eff4d | Evgeny Voevodin | /* break. */
|
2917 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
2918 | 7b5eff4d | Evgeny Voevodin | |
2919 | 7b5eff4d | Evgeny Voevodin | /* Breaks start at 16 in the exception vector. */
|
2920 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(trap_vector, |
2921 | 7b5eff4d | Evgeny Voevodin | tcg_const_tl(dc->op1 + 16));
|
2922 | 7b5eff4d | Evgeny Voevodin | t_gen_raise_exception(EXCP_BREAK); |
2923 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
2924 | 7b5eff4d | Evgeny Voevodin | break;
|
2925 | 7b5eff4d | Evgeny Voevodin | default:
|
2926 | 7b5eff4d | Evgeny Voevodin | printf("op2=%x\n", dc->op2);
|
2927 | 7b5eff4d | Evgeny Voevodin | BUG(); |
2928 | 7b5eff4d | Evgeny Voevodin | break;
|
2929 | 7b5eff4d | Evgeny Voevodin | |
2930 | 7b5eff4d | Evgeny Voevodin | } |
2931 | 7b5eff4d | Evgeny Voevodin | return 2; |
2932 | 8170028d | ths | } |
2933 | 8170028d | ths | |
2934 | cf7e0c80 | Aurelien Jarno | static int dec_ftag_fidx_d_m(CPUCRISState *env, DisasContext *dc) |
2935 | 5d4a534d | edgar_igl | { |
2936 | 7b5eff4d | Evgeny Voevodin | return 2; |
2937 | 5d4a534d | edgar_igl | } |
2938 | 5d4a534d | edgar_igl | |
2939 | cf7e0c80 | Aurelien Jarno | static int dec_ftag_fidx_i_m(CPUCRISState *env, DisasContext *dc) |
2940 | 5d4a534d | edgar_igl | { |
2941 | 7b5eff4d | Evgeny Voevodin | return 2; |
2942 | 5d4a534d | edgar_igl | } |
2943 | 5d4a534d | edgar_igl | |
2944 | cf7e0c80 | Aurelien Jarno | static int dec_null(CPUCRISState *env, DisasContext *dc) |
2945 | 8170028d | ths | { |
2946 | 7b5eff4d | Evgeny Voevodin | printf("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
|
2947 | 7b5eff4d | Evgeny Voevodin | dc->pc, dc->opcode, dc->op1, dc->op2); |
2948 | 7b5eff4d | Evgeny Voevodin | fflush(NULL);
|
2949 | 7b5eff4d | Evgeny Voevodin | BUG(); |
2950 | 7b5eff4d | Evgeny Voevodin | return 2; |
2951 | 8170028d | ths | } |
2952 | 8170028d | ths | |
2953 | 9b32fbf8 | edgar_igl | static struct decoder_info { |
2954 | 7b5eff4d | Evgeny Voevodin | struct {
|
2955 | 7b5eff4d | Evgeny Voevodin | uint32_t bits; |
2956 | 7b5eff4d | Evgeny Voevodin | uint32_t mask; |
2957 | 7b5eff4d | Evgeny Voevodin | }; |
2958 | 7b5eff4d | Evgeny Voevodin | int (*dec)(CPUCRISState *env, DisasContext *dc);
|
2959 | 8170028d | ths | } decinfo[] = { |
2960 | 7b5eff4d | Evgeny Voevodin | /* Order matters here. */
|
2961 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVEQ, dec_moveq}, |
2962 | 7b5eff4d | Evgeny Voevodin | {DEC_BTSTQ, dec_btstq}, |
2963 | 7b5eff4d | Evgeny Voevodin | {DEC_CMPQ, dec_cmpq}, |
2964 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDOQ, dec_addoq}, |
2965 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDQ, dec_addq}, |
2966 | 7b5eff4d | Evgeny Voevodin | {DEC_SUBQ, dec_subq}, |
2967 | 7b5eff4d | Evgeny Voevodin | {DEC_ANDQ, dec_andq}, |
2968 | 7b5eff4d | Evgeny Voevodin | {DEC_ORQ, dec_orq}, |
2969 | 7b5eff4d | Evgeny Voevodin | {DEC_ASRQ, dec_asrq}, |
2970 | 7b5eff4d | Evgeny Voevodin | {DEC_LSLQ, dec_lslq}, |
2971 | 7b5eff4d | Evgeny Voevodin | {DEC_LSRQ, dec_lsrq}, |
2972 | 7b5eff4d | Evgeny Voevodin | {DEC_BCCQ, dec_bccq}, |
2973 | 7b5eff4d | Evgeny Voevodin | |
2974 | 7b5eff4d | Evgeny Voevodin | {DEC_BCC_IM, dec_bcc_im}, |
2975 | 7b5eff4d | Evgeny Voevodin | {DEC_JAS_IM, dec_jas_im}, |
2976 | 7b5eff4d | Evgeny Voevodin | {DEC_JAS_R, dec_jas_r}, |
2977 | 7b5eff4d | Evgeny Voevodin | {DEC_JASC_IM, dec_jasc_im}, |
2978 | 7b5eff4d | Evgeny Voevodin | {DEC_JASC_R, dec_jasc_r}, |
2979 | 7b5eff4d | Evgeny Voevodin | {DEC_BAS_IM, dec_bas_im}, |
2980 | 7b5eff4d | Evgeny Voevodin | {DEC_BASC_IM, dec_basc_im}, |
2981 | 7b5eff4d | Evgeny Voevodin | {DEC_JUMP_P, dec_jump_p}, |
2982 | 7b5eff4d | Evgeny Voevodin | {DEC_LAPC_IM, dec_lapc_im}, |
2983 | 7b5eff4d | Evgeny Voevodin | {DEC_LAPCQ, dec_lapcq}, |
2984 | 7b5eff4d | Evgeny Voevodin | |
2985 | 7b5eff4d | Evgeny Voevodin | {DEC_RFE_ETC, dec_rfe_etc}, |
2986 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDC_MR, dec_addc_mr}, |
2987 | 7b5eff4d | Evgeny Voevodin | |
2988 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_MP, dec_move_mp}, |
2989 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_PM, dec_move_pm}, |
2990 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVEM_MR, dec_movem_mr}, |
2991 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVEM_RM, dec_movem_rm}, |
2992 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_PR, dec_move_pr}, |
2993 | 7b5eff4d | Evgeny Voevodin | {DEC_SCC_R, dec_scc_r}, |
2994 | 7b5eff4d | Evgeny Voevodin | {DEC_SETF, dec_setclrf}, |
2995 | 7b5eff4d | Evgeny Voevodin | {DEC_CLEARF, dec_setclrf}, |
2996 | 7b5eff4d | Evgeny Voevodin | |
2997 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_SR, dec_move_sr}, |
2998 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_RP, dec_move_rp}, |
2999 | 7b5eff4d | Evgeny Voevodin | {DEC_SWAP_R, dec_swap_r}, |
3000 | 7b5eff4d | Evgeny Voevodin | {DEC_ABS_R, dec_abs_r}, |
3001 | 7b5eff4d | Evgeny Voevodin | {DEC_LZ_R, dec_lz_r}, |
3002 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_RS, dec_move_rs}, |
3003 | 7b5eff4d | Evgeny Voevodin | {DEC_BTST_R, dec_btst_r}, |
3004 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDC_R, dec_addc_r}, |
3005 | 7b5eff4d | Evgeny Voevodin | |
3006 | 7b5eff4d | Evgeny Voevodin | {DEC_DSTEP_R, dec_dstep_r}, |
3007 | 7b5eff4d | Evgeny Voevodin | {DEC_XOR_R, dec_xor_r}, |
3008 | 7b5eff4d | Evgeny Voevodin | {DEC_MCP_R, dec_mcp_r}, |
3009 | 7b5eff4d | Evgeny Voevodin | {DEC_CMP_R, dec_cmp_r}, |
3010 | 7b5eff4d | Evgeny Voevodin | |
3011 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDI_R, dec_addi_r}, |
3012 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDI_ACR, dec_addi_acr}, |
3013 | 7b5eff4d | Evgeny Voevodin | |
3014 | 7b5eff4d | Evgeny Voevodin | {DEC_ADD_R, dec_add_r}, |
3015 | 7b5eff4d | Evgeny Voevodin | {DEC_SUB_R, dec_sub_r}, |
3016 | 7b5eff4d | Evgeny Voevodin | |
3017 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDU_R, dec_addu_r}, |
3018 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDS_R, dec_adds_r}, |
3019 | 7b5eff4d | Evgeny Voevodin | {DEC_SUBU_R, dec_subu_r}, |
3020 | 7b5eff4d | Evgeny Voevodin | {DEC_SUBS_R, dec_subs_r}, |
3021 | 7b5eff4d | Evgeny Voevodin | {DEC_LSL_R, dec_lsl_r}, |
3022 | 7b5eff4d | Evgeny Voevodin | |
3023 | 7b5eff4d | Evgeny Voevodin | {DEC_AND_R, dec_and_r}, |
3024 | 7b5eff4d | Evgeny Voevodin | {DEC_OR_R, dec_or_r}, |
3025 | 7b5eff4d | Evgeny Voevodin | {DEC_BOUND_R, dec_bound_r}, |
3026 | 7b5eff4d | Evgeny Voevodin | {DEC_ASR_R, dec_asr_r}, |
3027 | 7b5eff4d | Evgeny Voevodin | {DEC_LSR_R, dec_lsr_r}, |
3028 | 7b5eff4d | Evgeny Voevodin | |
3029 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVU_R, dec_movu_r}, |
3030 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVS_R, dec_movs_r}, |
3031 | 7b5eff4d | Evgeny Voevodin | {DEC_NEG_R, dec_neg_r}, |
3032 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_R, dec_move_r}, |
3033 | 7b5eff4d | Evgeny Voevodin | |
3034 | 7b5eff4d | Evgeny Voevodin | {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m}, |
3035 | 7b5eff4d | Evgeny Voevodin | {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m}, |
3036 | 7b5eff4d | Evgeny Voevodin | |
3037 | 7b5eff4d | Evgeny Voevodin | {DEC_MULS_R, dec_muls_r}, |
3038 | 7b5eff4d | Evgeny Voevodin | {DEC_MULU_R, dec_mulu_r}, |
3039 | 7b5eff4d | Evgeny Voevodin | |
3040 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDU_M, dec_addu_m}, |
3041 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDS_M, dec_adds_m}, |
3042 | 7b5eff4d | Evgeny Voevodin | {DEC_SUBU_M, dec_subu_m}, |
3043 | 7b5eff4d | Evgeny Voevodin | {DEC_SUBS_M, dec_subs_m}, |
3044 | 7b5eff4d | Evgeny Voevodin | |
3045 | 7b5eff4d | Evgeny Voevodin | {DEC_CMPU_M, dec_cmpu_m}, |
3046 | 7b5eff4d | Evgeny Voevodin | {DEC_CMPS_M, dec_cmps_m}, |
3047 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVU_M, dec_movu_m}, |
3048 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVS_M, dec_movs_m}, |
3049 | 7b5eff4d | Evgeny Voevodin | |
3050 | 7b5eff4d | Evgeny Voevodin | {DEC_CMP_M, dec_cmp_m}, |
3051 | 7b5eff4d | Evgeny Voevodin | {DEC_ADDO_M, dec_addo_m}, |
3052 | 7b5eff4d | Evgeny Voevodin | {DEC_BOUND_M, dec_bound_m}, |
3053 | 7b5eff4d | Evgeny Voevodin | {DEC_ADD_M, dec_add_m}, |
3054 | 7b5eff4d | Evgeny Voevodin | {DEC_SUB_M, dec_sub_m}, |
3055 | 7b5eff4d | Evgeny Voevodin | {DEC_AND_M, dec_and_m}, |
3056 | 7b5eff4d | Evgeny Voevodin | {DEC_OR_M, dec_or_m}, |
3057 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_RM, dec_move_rm}, |
3058 | 7b5eff4d | Evgeny Voevodin | {DEC_TEST_M, dec_test_m}, |
3059 | 7b5eff4d | Evgeny Voevodin | {DEC_MOVE_MR, dec_move_mr}, |
3060 | 7b5eff4d | Evgeny Voevodin | |
3061 | 7b5eff4d | Evgeny Voevodin | {{0, 0}, dec_null} |
3062 | 8170028d | ths | }; |
3063 | 8170028d | ths | |
3064 | cf7e0c80 | Aurelien Jarno | static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) |
3065 | 8170028d | ths | { |
3066 | 7b5eff4d | Evgeny Voevodin | int insn_len = 2; |
3067 | 7b5eff4d | Evgeny Voevodin | int i;
|
3068 | 8170028d | ths | |
3069 | 7b5eff4d | Evgeny Voevodin | if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
|
3070 | 7b5eff4d | Evgeny Voevodin | tcg_gen_debug_insn_start(dc->pc); |
3071 | fdefe51c | Richard Henderson | } |
3072 | 28de16da | edgar_igl | |
3073 | 7b5eff4d | Evgeny Voevodin | /* Load a halfword onto the instruction register. */
|
3074 | cf7e0c80 | Aurelien Jarno | dc->ir = cris_fetch(env, dc, dc->pc, 2, 0); |
3075 | 8170028d | ths | |
3076 | 7b5eff4d | Evgeny Voevodin | /* Now decode it. */
|
3077 | 7b5eff4d | Evgeny Voevodin | dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11); |
3078 | 7b5eff4d | Evgeny Voevodin | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3); |
3079 | 7b5eff4d | Evgeny Voevodin | dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15); |
3080 | 7b5eff4d | Evgeny Voevodin | dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4); |
3081 | 7b5eff4d | Evgeny Voevodin | dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5); |
3082 | 7b5eff4d | Evgeny Voevodin | dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10); |
3083 | 7b5eff4d | Evgeny Voevodin | |
3084 | 7b5eff4d | Evgeny Voevodin | /* Large switch for all insns. */
|
3085 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < ARRAY_SIZE(decinfo); i++) { |
3086 | 7b5eff4d | Evgeny Voevodin | if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
|
3087 | 7b5eff4d | Evgeny Voevodin | insn_len = decinfo[i].dec(env, dc); |
3088 | 7b5eff4d | Evgeny Voevodin | break;
|
3089 | 7b5eff4d | Evgeny Voevodin | } |
3090 | 7b5eff4d | Evgeny Voevodin | } |
3091 | 8170028d | ths | |
3092 | dd20fcd0 | edgar_igl | #if !defined(CONFIG_USER_ONLY)
|
3093 | 7b5eff4d | Evgeny Voevodin | /* Single-stepping ? */
|
3094 | 7b5eff4d | Evgeny Voevodin | if (dc->tb_flags & S_FLAG) {
|
3095 | 7b5eff4d | Evgeny Voevodin | int l1;
|
3096 | 7b5eff4d | Evgeny Voevodin | |
3097 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
3098 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1); |
3099 | 7b5eff4d | Evgeny Voevodin | /* We treat SPC as a break with an odd trap vector. */
|
3100 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
3101 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
|
3102 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc + insn_len); |
3103 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len); |
3104 | 7b5eff4d | Evgeny Voevodin | t_gen_raise_exception(EXCP_BREAK); |
3105 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
3106 | 7b5eff4d | Evgeny Voevodin | } |
3107 | a1aebcb8 | edgar_igl | #endif
|
3108 | 7b5eff4d | Evgeny Voevodin | return insn_len;
|
3109 | 8170028d | ths | } |
3110 | 8170028d | ths | |
3111 | a1170bfd | Andreas Färber | static void check_breakpoint(CPUCRISState *env, DisasContext *dc) |
3112 | 8170028d | ths | { |
3113 | 7b5eff4d | Evgeny Voevodin | CPUBreakpoint *bp; |
3114 | a1d1bb31 | aliguori | |
3115 | 7b5eff4d | Evgeny Voevodin | if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
|
3116 | 7b5eff4d | Evgeny Voevodin | QTAILQ_FOREACH(bp, &env->breakpoints, entry) { |
3117 | 7b5eff4d | Evgeny Voevodin | if (bp->pc == dc->pc) {
|
3118 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
3119 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, dc->pc); |
3120 | 7b5eff4d | Evgeny Voevodin | t_gen_raise_exception(EXCP_DEBUG); |
3121 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
3122 | 7b5eff4d | Evgeny Voevodin | } |
3123 | 7b5eff4d | Evgeny Voevodin | } |
3124 | 7b5eff4d | Evgeny Voevodin | } |
3125 | 8170028d | ths | } |
3126 | 8170028d | ths | |
3127 | 40e9eddd | Edgar E. Iglesias | #include "translate_v10.c" |
3128 | cf1d97f0 | edgar_igl | |
3129 | cf1d97f0 | edgar_igl | /*
|
3130 | cf1d97f0 | edgar_igl | * Delay slots on QEMU/CRIS.
|
3131 | cf1d97f0 | edgar_igl | *
|
3132 | cf1d97f0 | edgar_igl | * If an exception hits on a delayslot, the core will let ERP (the Exception
|
3133 | cf1d97f0 | edgar_igl | * Return Pointer) point to the branch (the previous) insn and set the lsb to
|
3134 | cf1d97f0 | edgar_igl | * to give SW a hint that the exception actually hit on the dslot.
|
3135 | cf1d97f0 | edgar_igl | *
|
3136 | cf1d97f0 | edgar_igl | * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
|
3137 | cf1d97f0 | edgar_igl | * the core and any jmp to an odd addresses will mask off that lsb. It is
|
3138 | cf1d97f0 | edgar_igl | * simply there to let sw know there was an exception on a dslot.
|
3139 | cf1d97f0 | edgar_igl | *
|
3140 | cf1d97f0 | edgar_igl | * When the software returns from an exception, the branch will re-execute.
|
3141 | cf1d97f0 | edgar_igl | * On QEMU care needs to be taken when a branch+delayslot sequence is broken
|
3142 | cf1d97f0 | edgar_igl | * and the branch and delayslot dont share pages.
|
3143 | cf1d97f0 | edgar_igl | *
|
3144 | cf1d97f0 | edgar_igl | * The TB contaning the branch insn will set up env->btarget and evaluate
|
3145 | cf1d97f0 | edgar_igl | * env->btaken. When the translation loop exits we will note that the branch
|
3146 | cf1d97f0 | edgar_igl | * sequence is broken and let env->dslot be the size of the branch insn (those
|
3147 | cf1d97f0 | edgar_igl | * vary in length).
|
3148 | cf1d97f0 | edgar_igl | *
|
3149 | cf1d97f0 | edgar_igl | * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
|
3150 | cf1d97f0 | edgar_igl | * set). It will also expect to have env->dslot setup with the size of the
|
3151 | cf1d97f0 | edgar_igl | * delay slot so that env->pc - env->dslot point to the branch insn. This TB
|
3152 | cf1d97f0 | edgar_igl | * will execute the dslot and take the branch, either to btarget or just one
|
3153 | cf1d97f0 | edgar_igl | * insn ahead.
|
3154 | cf1d97f0 | edgar_igl | *
|
3155 | cf1d97f0 | edgar_igl | * When exceptions occur, we check for env->dslot in do_interrupt to detect
|
3156 | cf1d97f0 | edgar_igl | * broken branch sequences and setup $erp accordingly (i.e let it point to the
|
3157 | cf1d97f0 | edgar_igl | * branch and set lsb). Then env->dslot gets cleared so that the exception
|
3158 | cf1d97f0 | edgar_igl | * handler can enter. When returning from exceptions (jump $erp) the lsb gets
|
3159 | cf1d97f0 | edgar_igl | * masked off and we will reexecute the branch insn.
|
3160 | cf1d97f0 | edgar_igl | *
|
3161 | cf1d97f0 | edgar_igl | */
|
3162 | cf1d97f0 | edgar_igl | |
3163 | 8170028d | ths | /* generate intermediate code for basic block 'tb'. */
|
3164 | 6f47ec50 | Andreas Färber | static inline void |
3165 | 7fd2592d | Andreas Färber | gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, |
3166 | 7fd2592d | Andreas Färber | bool search_pc)
|
3167 | 8170028d | ths | { |
3168 | 7fd2592d | Andreas Färber | CPUCRISState *env = &cpu->env; |
3169 | 7b5eff4d | Evgeny Voevodin | uint16_t *gen_opc_end; |
3170 | 7b5eff4d | Evgeny Voevodin | uint32_t pc_start; |
3171 | 7b5eff4d | Evgeny Voevodin | unsigned int insn_len; |
3172 | 7b5eff4d | Evgeny Voevodin | int j, lj;
|
3173 | 7b5eff4d | Evgeny Voevodin | struct DisasContext ctx;
|
3174 | 7b5eff4d | Evgeny Voevodin | struct DisasContext *dc = &ctx;
|
3175 | 7b5eff4d | Evgeny Voevodin | uint32_t next_page_start; |
3176 | 7b5eff4d | Evgeny Voevodin | target_ulong npc; |
3177 | 7b5eff4d | Evgeny Voevodin | int num_insns;
|
3178 | 7b5eff4d | Evgeny Voevodin | int max_insns;
|
3179 | 7b5eff4d | Evgeny Voevodin | |
3180 | 7b5eff4d | Evgeny Voevodin | if (env->pregs[PR_VR] == 32) { |
3181 | 7b5eff4d | Evgeny Voevodin | dc->decoder = crisv32_decoder; |
3182 | 7b5eff4d | Evgeny Voevodin | dc->clear_locked_irq = 0;
|
3183 | 7b5eff4d | Evgeny Voevodin | } else {
|
3184 | 7b5eff4d | Evgeny Voevodin | dc->decoder = crisv10_decoder; |
3185 | 7b5eff4d | Evgeny Voevodin | dc->clear_locked_irq = 1;
|
3186 | 7b5eff4d | Evgeny Voevodin | } |
3187 | 7b5eff4d | Evgeny Voevodin | |
3188 | 7b5eff4d | Evgeny Voevodin | /* Odd PC indicates that branch is rexecuting due to exception in the
|
3189 | 7b5eff4d | Evgeny Voevodin | * delayslot, like in real hw.
|
3190 | 7b5eff4d | Evgeny Voevodin | */
|
3191 | 7b5eff4d | Evgeny Voevodin | pc_start = tb->pc & ~1;
|
3192 | 7b5eff4d | Evgeny Voevodin | dc->env = env; |
3193 | 7b5eff4d | Evgeny Voevodin | dc->tb = tb; |
3194 | 7b5eff4d | Evgeny Voevodin | |
3195 | 92414b31 | Evgeny Voevodin | gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; |
3196 | 7b5eff4d | Evgeny Voevodin | |
3197 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_NEXT; |
3198 | 7b5eff4d | Evgeny Voevodin | dc->ppc = pc_start; |
3199 | 7b5eff4d | Evgeny Voevodin | dc->pc = pc_start; |
3200 | 7b5eff4d | Evgeny Voevodin | dc->singlestep_enabled = env->singlestep_enabled; |
3201 | 7b5eff4d | Evgeny Voevodin | dc->flags_uptodate = 1;
|
3202 | 7b5eff4d | Evgeny Voevodin | dc->flagx_known = 1;
|
3203 | 7b5eff4d | Evgeny Voevodin | dc->flags_x = tb->flags & X_FLAG; |
3204 | 7b5eff4d | Evgeny Voevodin | dc->cc_x_uptodate = 0;
|
3205 | 7b5eff4d | Evgeny Voevodin | dc->cc_mask = 0;
|
3206 | 7b5eff4d | Evgeny Voevodin | dc->update_cc = 0;
|
3207 | 7b5eff4d | Evgeny Voevodin | dc->clear_prefix = 0;
|
3208 | 7b5eff4d | Evgeny Voevodin | |
3209 | 7b5eff4d | Evgeny Voevodin | cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
3210 | 7b5eff4d | Evgeny Voevodin | dc->cc_size_uptodate = -1;
|
3211 | 7b5eff4d | Evgeny Voevodin | |
3212 | 7b5eff4d | Evgeny Voevodin | /* Decode TB flags. */
|
3213 | 7b5eff4d | Evgeny Voevodin | dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \ |
3214 | 7b5eff4d | Evgeny Voevodin | | X_FLAG | PFIX_FLAG); |
3215 | 7b5eff4d | Evgeny Voevodin | dc->delayed_branch = !!(tb->flags & 7);
|
3216 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch) {
|
3217 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_INDIRECT; |
3218 | 7b5eff4d | Evgeny Voevodin | } else {
|
3219 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_NOJMP; |
3220 | 7b5eff4d | Evgeny Voevodin | } |
3221 | 7b5eff4d | Evgeny Voevodin | |
3222 | 7b5eff4d | Evgeny Voevodin | dc->cpustate_changed = 0;
|
3223 | 7b5eff4d | Evgeny Voevodin | |
3224 | 7b5eff4d | Evgeny Voevodin | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
3225 | 7b5eff4d | Evgeny Voevodin | qemu_log( |
3226 | 7b5eff4d | Evgeny Voevodin | "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n" |
3227 | 7b5eff4d | Evgeny Voevodin | "pid=%x usp=%x\n"
|
3228 | 7b5eff4d | Evgeny Voevodin | "%x.%x.%x.%x\n"
|
3229 | 7b5eff4d | Evgeny Voevodin | "%x.%x.%x.%x\n"
|
3230 | 7b5eff4d | Evgeny Voevodin | "%x.%x.%x.%x\n"
|
3231 | 7b5eff4d | Evgeny Voevodin | "%x.%x.%x.%x\n",
|
3232 | 7b5eff4d | Evgeny Voevodin | search_pc, dc->pc, dc->ppc, |
3233 | 7b5eff4d | Evgeny Voevodin | (uint64_t)tb->flags, |
3234 | 7b5eff4d | Evgeny Voevodin | env->btarget, (unsigned)tb->flags & 7, |
3235 | 7b5eff4d | Evgeny Voevodin | env->pregs[PR_CCS], |
3236 | 7b5eff4d | Evgeny Voevodin | env->pregs[PR_PID], env->pregs[PR_USP], |
3237 | 7b5eff4d | Evgeny Voevodin | env->regs[0], env->regs[1], env->regs[2], env->regs[3], |
3238 | 7b5eff4d | Evgeny Voevodin | env->regs[4], env->regs[5], env->regs[6], env->regs[7], |
3239 | 7b5eff4d | Evgeny Voevodin | env->regs[8], env->regs[9], |
3240 | 7b5eff4d | Evgeny Voevodin | env->regs[10], env->regs[11], |
3241 | 7b5eff4d | Evgeny Voevodin | env->regs[12], env->regs[13], |
3242 | 7b5eff4d | Evgeny Voevodin | env->regs[14], env->regs[15]); |
3243 | 7b5eff4d | Evgeny Voevodin | qemu_log("--------------\n");
|
3244 | 7b5eff4d | Evgeny Voevodin | qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
3245 | 7b5eff4d | Evgeny Voevodin | } |
3246 | 7b5eff4d | Evgeny Voevodin | |
3247 | 7b5eff4d | Evgeny Voevodin | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
3248 | 7b5eff4d | Evgeny Voevodin | lj = -1;
|
3249 | 7b5eff4d | Evgeny Voevodin | num_insns = 0;
|
3250 | 7b5eff4d | Evgeny Voevodin | max_insns = tb->cflags & CF_COUNT_MASK; |
3251 | 7b5eff4d | Evgeny Voevodin | if (max_insns == 0) { |
3252 | 7b5eff4d | Evgeny Voevodin | max_insns = CF_COUNT_MASK; |
3253 | 7b5eff4d | Evgeny Voevodin | } |
3254 | 7b5eff4d | Evgeny Voevodin | |
3255 | 806f352d | Peter Maydell | gen_tb_start(); |
3256 | 7b5eff4d | Evgeny Voevodin | do {
|
3257 | 7b5eff4d | Evgeny Voevodin | check_breakpoint(env, dc); |
3258 | 7b5eff4d | Evgeny Voevodin | |
3259 | 7b5eff4d | Evgeny Voevodin | if (search_pc) {
|
3260 | 92414b31 | Evgeny Voevodin | j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; |
3261 | 7b5eff4d | Evgeny Voevodin | if (lj < j) {
|
3262 | 7b5eff4d | Evgeny Voevodin | lj++; |
3263 | 7b5eff4d | Evgeny Voevodin | while (lj < j) {
|
3264 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj++] = 0;
|
3265 | 7b5eff4d | Evgeny Voevodin | } |
3266 | 7b5eff4d | Evgeny Voevodin | } |
3267 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 1) { |
3268 | 25983cad | Evgeny Voevodin | tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1;
|
3269 | 7b5eff4d | Evgeny Voevodin | } else {
|
3270 | 25983cad | Evgeny Voevodin | tcg_ctx.gen_opc_pc[lj] = dc->pc; |
3271 | 7b5eff4d | Evgeny Voevodin | } |
3272 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj] = 1;
|
3273 | c9c99c22 | Evgeny Voevodin | tcg_ctx.gen_opc_icount[lj] = num_insns; |
3274 | 7b5eff4d | Evgeny Voevodin | } |
3275 | 7b5eff4d | Evgeny Voevodin | |
3276 | 7b5eff4d | Evgeny Voevodin | /* Pretty disas. */
|
3277 | 7b5eff4d | Evgeny Voevodin | LOG_DIS("%8.8x:\t", dc->pc);
|
3278 | 7b5eff4d | Evgeny Voevodin | |
3279 | 7b5eff4d | Evgeny Voevodin | if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { |
3280 | 7b5eff4d | Evgeny Voevodin | gen_io_start(); |
3281 | 7b5eff4d | Evgeny Voevodin | } |
3282 | 7b5eff4d | Evgeny Voevodin | dc->clear_x = 1;
|
3283 | 7b5eff4d | Evgeny Voevodin | |
3284 | 7b5eff4d | Evgeny Voevodin | insn_len = dc->decoder(env, dc); |
3285 | 7b5eff4d | Evgeny Voevodin | dc->ppc = dc->pc; |
3286 | 7b5eff4d | Evgeny Voevodin | dc->pc += insn_len; |
3287 | 7b5eff4d | Evgeny Voevodin | if (dc->clear_x) {
|
3288 | 7b5eff4d | Evgeny Voevodin | cris_clear_x_flag(dc); |
3289 | 7b5eff4d | Evgeny Voevodin | } |
3290 | 7b5eff4d | Evgeny Voevodin | |
3291 | 7b5eff4d | Evgeny Voevodin | num_insns++; |
3292 | 7b5eff4d | Evgeny Voevodin | /* Check for delayed branches here. If we do it before
|
3293 | 7b5eff4d | Evgeny Voevodin | actually generating any host code, the simulator will just
|
3294 | 7b5eff4d | Evgeny Voevodin | loop doing nothing for on this program location. */
|
3295 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch) {
|
3296 | 7b5eff4d | Evgeny Voevodin | dc->delayed_branch--; |
3297 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 0) { |
3298 | 7b5eff4d | Evgeny Voevodin | if (tb->flags & 7) { |
3299 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(dslot, tcg_const_tl(0));
|
3300 | 7b5eff4d | Evgeny Voevodin | } |
3301 | 7b5eff4d | Evgeny Voevodin | if (dc->cpustate_changed || !dc->flagx_known
|
3302 | 7b5eff4d | Evgeny Voevodin | || (dc->flags_x != (tb->flags & X_FLAG))) { |
3303 | 7b5eff4d | Evgeny Voevodin | cris_store_direct_jmp(dc); |
3304 | 7b5eff4d | Evgeny Voevodin | } |
3305 | 7b5eff4d | Evgeny Voevodin | |
3306 | 7b5eff4d | Evgeny Voevodin | if (dc->clear_locked_irq) {
|
3307 | 7b5eff4d | Evgeny Voevodin | dc->clear_locked_irq = 0;
|
3308 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
|
3309 | 7b5eff4d | Evgeny Voevodin | } |
3310 | 7b5eff4d | Evgeny Voevodin | |
3311 | 7b5eff4d | Evgeny Voevodin | if (dc->jmp == JMP_DIRECT_CC) {
|
3312 | 7b5eff4d | Evgeny Voevodin | int l1;
|
3313 | 7b5eff4d | Evgeny Voevodin | |
3314 | 7b5eff4d | Evgeny Voevodin | l1 = gen_new_label(); |
3315 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
3316 | 7b5eff4d | Evgeny Voevodin | |
3317 | 7b5eff4d | Evgeny Voevodin | /* Conditional jmp. */
|
3318 | 7b5eff4d | Evgeny Voevodin | tcg_gen_brcondi_tl(TCG_COND_EQ, |
3319 | 7b5eff4d | Evgeny Voevodin | env_btaken, 0, l1);
|
3320 | 7b5eff4d | Evgeny Voevodin | gen_goto_tb(dc, 1, dc->jmp_pc);
|
3321 | 7b5eff4d | Evgeny Voevodin | gen_set_label(l1); |
3322 | 7b5eff4d | Evgeny Voevodin | gen_goto_tb(dc, 0, dc->pc);
|
3323 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_TB_JUMP; |
3324 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_NOJMP; |
3325 | 7b5eff4d | Evgeny Voevodin | } else if (dc->jmp == JMP_DIRECT) { |
3326 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
3327 | 7b5eff4d | Evgeny Voevodin | gen_goto_tb(dc, 0, dc->jmp_pc);
|
3328 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_TB_JUMP; |
3329 | 7b5eff4d | Evgeny Voevodin | dc->jmp = JMP_NOJMP; |
3330 | 7b5eff4d | Evgeny Voevodin | } else {
|
3331 | 7b5eff4d | Evgeny Voevodin | t_gen_cc_jmp(env_btarget, tcg_const_tl(dc->pc)); |
3332 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_JUMP; |
3333 | 7b5eff4d | Evgeny Voevodin | } |
3334 | 7b5eff4d | Evgeny Voevodin | break;
|
3335 | 7b5eff4d | Evgeny Voevodin | } |
3336 | 7b5eff4d | Evgeny Voevodin | } |
3337 | 7b5eff4d | Evgeny Voevodin | |
3338 | 7b5eff4d | Evgeny Voevodin | /* If we are rexecuting a branch due to exceptions on
|
3339 | 7b5eff4d | Evgeny Voevodin | delay slots dont break. */
|
3340 | 7b5eff4d | Evgeny Voevodin | if (!(tb->pc & 1) && env->singlestep_enabled) { |
3341 | 7b5eff4d | Evgeny Voevodin | break;
|
3342 | 7b5eff4d | Evgeny Voevodin | } |
3343 | 7b5eff4d | Evgeny Voevodin | } while (!dc->is_jmp && !dc->cpustate_changed
|
3344 | efd7f486 | Evgeny Voevodin | && tcg_ctx.gen_opc_ptr < gen_opc_end |
3345 | 7b5eff4d | Evgeny Voevodin | && !singlestep |
3346 | 7b5eff4d | Evgeny Voevodin | && (dc->pc < next_page_start) |
3347 | 7b5eff4d | Evgeny Voevodin | && num_insns < max_insns); |
3348 | 7b5eff4d | Evgeny Voevodin | |
3349 | 7b5eff4d | Evgeny Voevodin | if (dc->clear_locked_irq) {
|
3350 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
|
3351 | 7b5eff4d | Evgeny Voevodin | } |
3352 | 7b5eff4d | Evgeny Voevodin | |
3353 | 7b5eff4d | Evgeny Voevodin | npc = dc->pc; |
3354 | 2a44f7f1 | edgar_igl | |
3355 | 2e70f6ef | pbrook | if (tb->cflags & CF_LAST_IO)
|
3356 | 2e70f6ef | pbrook | gen_io_end(); |
3357 | 7b5eff4d | Evgeny Voevodin | /* Force an update if the per-tb cpu state has changed. */
|
3358 | 7b5eff4d | Evgeny Voevodin | if (dc->is_jmp == DISAS_NEXT
|
3359 | 7b5eff4d | Evgeny Voevodin | && (dc->cpustate_changed || !dc->flagx_known |
3360 | 7b5eff4d | Evgeny Voevodin | || (dc->flags_x != (tb->flags & X_FLAG)))) { |
3361 | 7b5eff4d | Evgeny Voevodin | dc->is_jmp = DISAS_UPDATE; |
3362 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, npc); |
3363 | 7b5eff4d | Evgeny Voevodin | } |
3364 | 7b5eff4d | Evgeny Voevodin | /* Broken branch+delayslot sequence. */
|
3365 | 7b5eff4d | Evgeny Voevodin | if (dc->delayed_branch == 1) { |
3366 | 7b5eff4d | Evgeny Voevodin | /* Set env->dslot to the size of the branch insn. */
|
3367 | 7b5eff4d | Evgeny Voevodin | t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc)); |
3368 | 7b5eff4d | Evgeny Voevodin | cris_store_direct_jmp(dc); |
3369 | 7b5eff4d | Evgeny Voevodin | } |
3370 | 7b5eff4d | Evgeny Voevodin | |
3371 | 7b5eff4d | Evgeny Voevodin | cris_evaluate_flags(dc); |
3372 | 7b5eff4d | Evgeny Voevodin | |
3373 | 7b5eff4d | Evgeny Voevodin | if (unlikely(env->singlestep_enabled)) {
|
3374 | 7b5eff4d | Evgeny Voevodin | if (dc->is_jmp == DISAS_NEXT) {
|
3375 | 7b5eff4d | Evgeny Voevodin | tcg_gen_movi_tl(env_pc, npc); |
3376 | 7b5eff4d | Evgeny Voevodin | } |
3377 | 7b5eff4d | Evgeny Voevodin | t_gen_raise_exception(EXCP_DEBUG); |
3378 | 7b5eff4d | Evgeny Voevodin | } else {
|
3379 | 7b5eff4d | Evgeny Voevodin | switch (dc->is_jmp) {
|
3380 | 7b5eff4d | Evgeny Voevodin | case DISAS_NEXT:
|
3381 | 7b5eff4d | Evgeny Voevodin | gen_goto_tb(dc, 1, npc);
|
3382 | 7b5eff4d | Evgeny Voevodin | break;
|
3383 | 7b5eff4d | Evgeny Voevodin | default:
|
3384 | 7b5eff4d | Evgeny Voevodin | case DISAS_JUMP:
|
3385 | 7b5eff4d | Evgeny Voevodin | case DISAS_UPDATE:
|
3386 | 7b5eff4d | Evgeny Voevodin | /* indicate that the hash table must be used
|
3387 | 7b5eff4d | Evgeny Voevodin | to find the next TB */
|
3388 | 7b5eff4d | Evgeny Voevodin | tcg_gen_exit_tb(0);
|
3389 | 7b5eff4d | Evgeny Voevodin | break;
|
3390 | 7b5eff4d | Evgeny Voevodin | case DISAS_SWI:
|
3391 | 7b5eff4d | Evgeny Voevodin | case DISAS_TB_JUMP:
|
3392 | 7b5eff4d | Evgeny Voevodin | /* nothing more to generate */
|
3393 | 7b5eff4d | Evgeny Voevodin | break;
|
3394 | 7b5eff4d | Evgeny Voevodin | } |
3395 | 7b5eff4d | Evgeny Voevodin | } |
3396 | 806f352d | Peter Maydell | gen_tb_end(tb, num_insns); |
3397 | efd7f486 | Evgeny Voevodin | *tcg_ctx.gen_opc_ptr = INDEX_op_end; |
3398 | 7b5eff4d | Evgeny Voevodin | if (search_pc) {
|
3399 | 92414b31 | Evgeny Voevodin | j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; |
3400 | 7b5eff4d | Evgeny Voevodin | lj++; |
3401 | 7b5eff4d | Evgeny Voevodin | while (lj <= j) {
|
3402 | ab1103de | Evgeny Voevodin | tcg_ctx.gen_opc_instr_start[lj++] = 0;
|
3403 | 7b5eff4d | Evgeny Voevodin | } |
3404 | 7b5eff4d | Evgeny Voevodin | } else {
|
3405 | 7b5eff4d | Evgeny Voevodin | tb->size = dc->pc - pc_start; |
3406 | 7b5eff4d | Evgeny Voevodin | tb->icount = num_insns; |
3407 | 7b5eff4d | Evgeny Voevodin | } |
3408 | 8170028d | ths | |
3409 | 8170028d | ths | #ifdef DEBUG_DISAS
|
3410 | a1aebcb8 | edgar_igl | #if !DISAS_CRIS
|
3411 | 7b5eff4d | Evgeny Voevodin | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
3412 | 7b5eff4d | Evgeny Voevodin | log_target_disas(env, pc_start, dc->pc - pc_start, |
3413 | 40e9eddd | Edgar E. Iglesias | dc->env->pregs[PR_VR]); |
3414 | 7b5eff4d | Evgeny Voevodin | qemu_log("\nisize=%d osize=%td\n",
|
3415 | 92414b31 | Evgeny Voevodin | dc->pc - pc_start, tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf); |
3416 | 7b5eff4d | Evgeny Voevodin | } |
3417 | 8170028d | ths | #endif
|
3418 | a1aebcb8 | edgar_igl | #endif
|
3419 | 8170028d | ths | } |
3420 | 8170028d | ths | |
3421 | a1170bfd | Andreas Färber | void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb) |
3422 | 8170028d | ths | { |
3423 | 7fd2592d | Andreas Färber | gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false);
|
3424 | 8170028d | ths | } |
3425 | 8170028d | ths | |
3426 | a1170bfd | Andreas Färber | void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb) |
3427 | 8170028d | ths | { |
3428 | 7fd2592d | Andreas Färber | gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true);
|
3429 | 8170028d | ths | } |
3430 | 8170028d | ths | |
3431 | 878096ee | Andreas Färber | void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
3432 | 878096ee | Andreas Färber | int flags)
|
3433 | 8170028d | ths | { |
3434 | 878096ee | Andreas Färber | CRISCPU *cpu = CRIS_CPU(cs); |
3435 | 878096ee | Andreas Färber | CPUCRISState *env = &cpu->env; |
3436 | 7b5eff4d | Evgeny Voevodin | int i;
|
3437 | 7b5eff4d | Evgeny Voevodin | uint32_t srs; |
3438 | 7b5eff4d | Evgeny Voevodin | |
3439 | 7b5eff4d | Evgeny Voevodin | if (!env || !f) {
|
3440 | 7b5eff4d | Evgeny Voevodin | return;
|
3441 | 7b5eff4d | Evgeny Voevodin | } |
3442 | 7b5eff4d | Evgeny Voevodin | |
3443 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
|
3444 | 7b5eff4d | Evgeny Voevodin | "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
|
3445 | 7b5eff4d | Evgeny Voevodin | env->pc, env->pregs[PR_CCS], env->btaken, env->btarget, |
3446 | 7b5eff4d | Evgeny Voevodin | env->cc_op, |
3447 | 7b5eff4d | Evgeny Voevodin | env->cc_src, env->cc_dest, env->cc_result, env->cc_mask); |
3448 | 7b5eff4d | Evgeny Voevodin | |
3449 | 7b5eff4d | Evgeny Voevodin | |
3450 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < 16; i++) { |
3451 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "%s=%8.8x ", regnames[i], env->regs[i]);
|
3452 | 7b5eff4d | Evgeny Voevodin | if ((i + 1) % 4 == 0) { |
3453 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\n");
|
3454 | 7b5eff4d | Evgeny Voevodin | } |
3455 | 7b5eff4d | Evgeny Voevodin | } |
3456 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\nspecial regs:\n");
|
3457 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < 16; i++) { |
3458 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
|
3459 | 7b5eff4d | Evgeny Voevodin | if ((i + 1) % 4 == 0) { |
3460 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\n");
|
3461 | 7b5eff4d | Evgeny Voevodin | } |
3462 | 7b5eff4d | Evgeny Voevodin | } |
3463 | 7b5eff4d | Evgeny Voevodin | srs = env->pregs[PR_SRS]; |
3464 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
|
3465 | 7b5eff4d | Evgeny Voevodin | if (srs < ARRAY_SIZE(env->sregs)) {
|
3466 | 7b5eff4d | Evgeny Voevodin | for (i = 0; i < 16; i++) { |
3467 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "s%2.2d=%8.8x ",
|
3468 | 7b5eff4d | Evgeny Voevodin | i, env->sregs[srs][i]); |
3469 | 7b5eff4d | Evgeny Voevodin | if ((i + 1) % 4 == 0) { |
3470 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\n");
|
3471 | 7b5eff4d | Evgeny Voevodin | } |
3472 | 7b5eff4d | Evgeny Voevodin | } |
3473 | 7b5eff4d | Evgeny Voevodin | } |
3474 | 7b5eff4d | Evgeny Voevodin | cpu_fprintf(f, "\n\n");
|
3475 | 8170028d | ths | |
3476 | 8170028d | ths | } |
3477 | 8170028d | ths | |
3478 | d1a94fec | Andreas Färber | void cris_initialize_tcg(void) |
3479 | d1a94fec | Andreas Färber | { |
3480 | d1a94fec | Andreas Färber | int i;
|
3481 | 05ba7d5f | edgar_igl | |
3482 | 40e9eddd | Edgar E. Iglesias | #define GEN_HELPER 2 |
3483 | 40e9eddd | Edgar E. Iglesias | #include "helper.h" |
3484 | 40e9eddd | Edgar E. Iglesias | |
3485 | dd10ce6d | Andreas Färber | cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
3486 | dd10ce6d | Andreas Färber | cc_x = tcg_global_mem_new(TCG_AREG0, |
3487 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_x), "cc_x");
|
3488 | dd10ce6d | Andreas Färber | cc_src = tcg_global_mem_new(TCG_AREG0, |
3489 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_src), "cc_src");
|
3490 | dd10ce6d | Andreas Färber | cc_dest = tcg_global_mem_new(TCG_AREG0, |
3491 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_dest), |
3492 | dd10ce6d | Andreas Färber | "cc_dest");
|
3493 | dd10ce6d | Andreas Färber | cc_result = tcg_global_mem_new(TCG_AREG0, |
3494 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_result), |
3495 | dd10ce6d | Andreas Färber | "cc_result");
|
3496 | dd10ce6d | Andreas Färber | cc_op = tcg_global_mem_new(TCG_AREG0, |
3497 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_op), "cc_op");
|
3498 | dd10ce6d | Andreas Färber | cc_size = tcg_global_mem_new(TCG_AREG0, |
3499 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_size), |
3500 | dd10ce6d | Andreas Färber | "cc_size");
|
3501 | dd10ce6d | Andreas Färber | cc_mask = tcg_global_mem_new(TCG_AREG0, |
3502 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, cc_mask), |
3503 | dd10ce6d | Andreas Färber | "cc_mask");
|
3504 | dd10ce6d | Andreas Färber | |
3505 | dd10ce6d | Andreas Färber | env_pc = tcg_global_mem_new(TCG_AREG0, |
3506 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, pc), |
3507 | dd10ce6d | Andreas Färber | "pc");
|
3508 | dd10ce6d | Andreas Färber | env_btarget = tcg_global_mem_new(TCG_AREG0, |
3509 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, btarget), |
3510 | dd10ce6d | Andreas Färber | "btarget");
|
3511 | dd10ce6d | Andreas Färber | env_btaken = tcg_global_mem_new(TCG_AREG0, |
3512 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, btaken), |
3513 | dd10ce6d | Andreas Färber | "btaken");
|
3514 | dd10ce6d | Andreas Färber | for (i = 0; i < 16; i++) { |
3515 | dd10ce6d | Andreas Färber | cpu_R[i] = tcg_global_mem_new(TCG_AREG0, |
3516 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, regs[i]), |
3517 | dd10ce6d | Andreas Färber | regnames[i]); |
3518 | dd10ce6d | Andreas Färber | } |
3519 | dd10ce6d | Andreas Färber | for (i = 0; i < 16; i++) { |
3520 | dd10ce6d | Andreas Färber | cpu_PR[i] = tcg_global_mem_new(TCG_AREG0, |
3521 | dd10ce6d | Andreas Färber | offsetof(CPUCRISState, pregs[i]), |
3522 | dd10ce6d | Andreas Färber | pregnames[i]); |
3523 | dd10ce6d | Andreas Färber | } |
3524 | 8170028d | ths | } |
3525 | 8170028d | ths | |
3526 | a1170bfd | Andreas Färber | void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos) |
3527 | d2856f1a | aurel32 | { |
3528 | 25983cad | Evgeny Voevodin | env->pc = tcg_ctx.gen_opc_pc[pc_pos]; |
3529 | d2856f1a | aurel32 | } |