root / target-unicore32 / translate.c @ 6ce2d77a
History | View | Annotate | Download (56.9 kB)
1 | 6e64da3c | Guan Xuetao | /*
|
---|---|---|---|
2 | 6e64da3c | Guan Xuetao | * UniCore32 translation
|
3 | 6e64da3c | Guan Xuetao | *
|
4 | 6e64da3c | Guan Xuetao | * Copyright (C) 2010-2011 GUAN Xue-tao
|
5 | 6e64da3c | Guan Xuetao | *
|
6 | 6e64da3c | Guan Xuetao | * This program is free software; you can redistribute it and/or modify
|
7 | 6e64da3c | Guan Xuetao | * it under the terms of the GNU General Public License version 2 as
|
8 | 6e64da3c | Guan Xuetao | * published by the Free Software Foundation.
|
9 | 6e64da3c | Guan Xuetao | */
|
10 | 6e64da3c | Guan Xuetao | #include <stdarg.h> |
11 | 6e64da3c | Guan Xuetao | #include <stdlib.h> |
12 | 6e64da3c | Guan Xuetao | #include <stdio.h> |
13 | 6e64da3c | Guan Xuetao | #include <string.h> |
14 | 6e64da3c | Guan Xuetao | #include <inttypes.h> |
15 | 6e64da3c | Guan Xuetao | |
16 | 6e64da3c | Guan Xuetao | #include "cpu.h" |
17 | 6e64da3c | Guan Xuetao | #include "disas.h" |
18 | 6e64da3c | Guan Xuetao | #include "tcg-op.h" |
19 | 6e64da3c | Guan Xuetao | #include "qemu-log.h" |
20 | 6e64da3c | Guan Xuetao | |
21 | 6e64da3c | Guan Xuetao | #include "helper.h" |
22 | 6e64da3c | Guan Xuetao | #define GEN_HELPER 1 |
23 | 6e64da3c | Guan Xuetao | #include "helper.h" |
24 | 6e64da3c | Guan Xuetao | |
25 | 6e64da3c | Guan Xuetao | /* internal defines */
|
26 | 6e64da3c | Guan Xuetao | typedef struct DisasContext { |
27 | 6e64da3c | Guan Xuetao | target_ulong pc; |
28 | 6e64da3c | Guan Xuetao | int is_jmp;
|
29 | 6e64da3c | Guan Xuetao | /* Nonzero if this instruction has been conditionally skipped. */
|
30 | 6e64da3c | Guan Xuetao | int condjmp;
|
31 | 6e64da3c | Guan Xuetao | /* The label that will be jumped to when the instruction is skipped. */
|
32 | 6e64da3c | Guan Xuetao | int condlabel;
|
33 | 6e64da3c | Guan Xuetao | struct TranslationBlock *tb;
|
34 | 6e64da3c | Guan Xuetao | int singlestep_enabled;
|
35 | 6e64da3c | Guan Xuetao | } DisasContext; |
36 | 6e64da3c | Guan Xuetao | |
37 | 6e64da3c | Guan Xuetao | #define IS_USER(s) 1 |
38 | 6e64da3c | Guan Xuetao | |
39 | 6e64da3c | Guan Xuetao | /* These instructions trap after executing, so defer them until after the
|
40 | 6e64da3c | Guan Xuetao | conditional executions state has been updated. */
|
41 | 6e64da3c | Guan Xuetao | #define DISAS_SYSCALL 5 |
42 | 6e64da3c | Guan Xuetao | |
43 | 6e64da3c | Guan Xuetao | static TCGv_ptr cpu_env;
|
44 | 6e64da3c | Guan Xuetao | static TCGv_i32 cpu_R[32]; |
45 | 6e64da3c | Guan Xuetao | |
46 | 6e64da3c | Guan Xuetao | /* FIXME: These should be removed. */
|
47 | 6e64da3c | Guan Xuetao | static TCGv cpu_F0s, cpu_F1s;
|
48 | 6e64da3c | Guan Xuetao | static TCGv_i64 cpu_F0d, cpu_F1d;
|
49 | 6e64da3c | Guan Xuetao | |
50 | 6e64da3c | Guan Xuetao | #include "gen-icount.h" |
51 | 6e64da3c | Guan Xuetao | |
52 | 6e64da3c | Guan Xuetao | static const char *regnames[] = { |
53 | 6e64da3c | Guan Xuetao | "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07", |
54 | 6e64da3c | Guan Xuetao | "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15", |
55 | 6e64da3c | Guan Xuetao | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
56 | 6e64da3c | Guan Xuetao | "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" }; |
57 | 6e64da3c | Guan Xuetao | |
58 | 6e64da3c | Guan Xuetao | /* initialize TCG globals. */
|
59 | 6e64da3c | Guan Xuetao | void uc32_translate_init(void) |
60 | 6e64da3c | Guan Xuetao | { |
61 | 6e64da3c | Guan Xuetao | int i;
|
62 | 6e64da3c | Guan Xuetao | |
63 | 6e64da3c | Guan Xuetao | cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
64 | 6e64da3c | Guan Xuetao | |
65 | 6e64da3c | Guan Xuetao | for (i = 0; i < 32; i++) { |
66 | 6e64da3c | Guan Xuetao | cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, |
67 | 6e64da3c | Guan Xuetao | offsetof(CPUState, regs[i]), regnames[i]); |
68 | 6e64da3c | Guan Xuetao | } |
69 | 6e64da3c | Guan Xuetao | |
70 | 6e64da3c | Guan Xuetao | #define GEN_HELPER 2 |
71 | 6e64da3c | Guan Xuetao | #include "helper.h" |
72 | 6e64da3c | Guan Xuetao | } |
73 | 6e64da3c | Guan Xuetao | |
74 | 6e64da3c | Guan Xuetao | static int num_temps; |
75 | 6e64da3c | Guan Xuetao | |
76 | 6e64da3c | Guan Xuetao | /* Allocate a temporary variable. */
|
77 | 6e64da3c | Guan Xuetao | static TCGv_i32 new_tmp(void) |
78 | 6e64da3c | Guan Xuetao | { |
79 | 6e64da3c | Guan Xuetao | num_temps++; |
80 | 6e64da3c | Guan Xuetao | return tcg_temp_new_i32();
|
81 | 6e64da3c | Guan Xuetao | } |
82 | 6e64da3c | Guan Xuetao | |
83 | 6e64da3c | Guan Xuetao | /* Release a temporary variable. */
|
84 | 6e64da3c | Guan Xuetao | static void dead_tmp(TCGv tmp) |
85 | 6e64da3c | Guan Xuetao | { |
86 | 6e64da3c | Guan Xuetao | tcg_temp_free(tmp); |
87 | 6e64da3c | Guan Xuetao | num_temps--; |
88 | 6e64da3c | Guan Xuetao | } |
89 | 6e64da3c | Guan Xuetao | |
90 | 6e64da3c | Guan Xuetao | static inline TCGv load_cpu_offset(int offset) |
91 | 6e64da3c | Guan Xuetao | { |
92 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
93 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(tmp, cpu_env, offset); |
94 | 6e64da3c | Guan Xuetao | return tmp;
|
95 | 6e64da3c | Guan Xuetao | } |
96 | 6e64da3c | Guan Xuetao | |
97 | 6e64da3c | Guan Xuetao | #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
|
98 | 6e64da3c | Guan Xuetao | |
99 | 6e64da3c | Guan Xuetao | static inline void store_cpu_offset(TCGv var, int offset) |
100 | 6e64da3c | Guan Xuetao | { |
101 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(var, cpu_env, offset); |
102 | 6e64da3c | Guan Xuetao | dead_tmp(var); |
103 | 6e64da3c | Guan Xuetao | } |
104 | 6e64da3c | Guan Xuetao | |
105 | 6e64da3c | Guan Xuetao | #define store_cpu_field(var, name) \
|
106 | 6e64da3c | Guan Xuetao | store_cpu_offset(var, offsetof(CPUState, name)) |
107 | 6e64da3c | Guan Xuetao | |
108 | 6e64da3c | Guan Xuetao | /* Set a variable to the value of a CPU register. */
|
109 | 6e64da3c | Guan Xuetao | static void load_reg_var(DisasContext *s, TCGv var, int reg) |
110 | 6e64da3c | Guan Xuetao | { |
111 | 6e64da3c | Guan Xuetao | if (reg == 31) { |
112 | 6e64da3c | Guan Xuetao | uint32_t addr; |
113 | 6e64da3c | Guan Xuetao | /* normaly, since we updated PC */
|
114 | 6e64da3c | Guan Xuetao | addr = (long)s->pc;
|
115 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(var, addr); |
116 | 6e64da3c | Guan Xuetao | } else {
|
117 | 6e64da3c | Guan Xuetao | tcg_gen_mov_i32(var, cpu_R[reg]); |
118 | 6e64da3c | Guan Xuetao | } |
119 | 6e64da3c | Guan Xuetao | } |
120 | 6e64da3c | Guan Xuetao | |
121 | 6e64da3c | Guan Xuetao | /* Create a new temporary and set it to the value of a CPU register. */
|
122 | 6e64da3c | Guan Xuetao | static inline TCGv load_reg(DisasContext *s, int reg) |
123 | 6e64da3c | Guan Xuetao | { |
124 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
125 | 6e64da3c | Guan Xuetao | load_reg_var(s, tmp, reg); |
126 | 6e64da3c | Guan Xuetao | return tmp;
|
127 | 6e64da3c | Guan Xuetao | } |
128 | 6e64da3c | Guan Xuetao | |
129 | 6e64da3c | Guan Xuetao | /* Set a CPU register. The source must be a temporary and will be
|
130 | 6e64da3c | Guan Xuetao | marked as dead. */
|
131 | 6e64da3c | Guan Xuetao | static void store_reg(DisasContext *s, int reg, TCGv var) |
132 | 6e64da3c | Guan Xuetao | { |
133 | 6e64da3c | Guan Xuetao | if (reg == 31) { |
134 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(var, var, ~3);
|
135 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_JUMP; |
136 | 6e64da3c | Guan Xuetao | } |
137 | 6e64da3c | Guan Xuetao | tcg_gen_mov_i32(cpu_R[reg], var); |
138 | 6e64da3c | Guan Xuetao | dead_tmp(var); |
139 | 6e64da3c | Guan Xuetao | } |
140 | 6e64da3c | Guan Xuetao | |
141 | 6e64da3c | Guan Xuetao | /* Value extensions. */
|
142 | 6e64da3c | Guan Xuetao | #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
|
143 | 6e64da3c | Guan Xuetao | #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
|
144 | 6e64da3c | Guan Xuetao | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
|
145 | 6e64da3c | Guan Xuetao | #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
|
146 | 6e64da3c | Guan Xuetao | |
147 | 6e64da3c | Guan Xuetao | #define UCOP_REG_M (((insn) >> 0) & 0x1f) |
148 | 6e64da3c | Guan Xuetao | #define UCOP_REG_N (((insn) >> 19) & 0x1f) |
149 | 6e64da3c | Guan Xuetao | #define UCOP_REG_D (((insn) >> 14) & 0x1f) |
150 | 6e64da3c | Guan Xuetao | #define UCOP_REG_S (((insn) >> 9) & 0x1f) |
151 | 6e64da3c | Guan Xuetao | #define UCOP_REG_LO (((insn) >> 14) & 0x1f) |
152 | 6e64da3c | Guan Xuetao | #define UCOP_REG_HI (((insn) >> 9) & 0x1f) |
153 | 6e64da3c | Guan Xuetao | #define UCOP_SH_OP (((insn) >> 6) & 0x03) |
154 | 6e64da3c | Guan Xuetao | #define UCOP_SH_IM (((insn) >> 9) & 0x1f) |
155 | 6e64da3c | Guan Xuetao | #define UCOP_OPCODES (((insn) >> 25) & 0x0f) |
156 | 6e64da3c | Guan Xuetao | #define UCOP_IMM_9 (((insn) >> 0) & 0x1ff) |
157 | 6e64da3c | Guan Xuetao | #define UCOP_IMM10 (((insn) >> 0) & 0x3ff) |
158 | 6e64da3c | Guan Xuetao | #define UCOP_IMM14 (((insn) >> 0) & 0x3fff) |
159 | 6e64da3c | Guan Xuetao | #define UCOP_COND (((insn) >> 25) & 0x0f) |
160 | 6e64da3c | Guan Xuetao | #define UCOP_CMOV_COND (((insn) >> 19) & 0x0f) |
161 | 6e64da3c | Guan Xuetao | #define UCOP_CPNUM (((insn) >> 10) & 0x0f) |
162 | 6e64da3c | Guan Xuetao | #define UCOP_UCF64_FMT (((insn) >> 24) & 0x03) |
163 | 6e64da3c | Guan Xuetao | #define UCOP_UCF64_FUNC (((insn) >> 6) & 0x0f) |
164 | 6e64da3c | Guan Xuetao | #define UCOP_UCF64_COND (((insn) >> 6) & 0x0f) |
165 | 6e64da3c | Guan Xuetao | |
166 | 6e64da3c | Guan Xuetao | #define UCOP_SET(i) ((insn) & (1 << (i))) |
167 | 6e64da3c | Guan Xuetao | #define UCOP_SET_P UCOP_SET(28) |
168 | 6e64da3c | Guan Xuetao | #define UCOP_SET_U UCOP_SET(27) |
169 | 6e64da3c | Guan Xuetao | #define UCOP_SET_B UCOP_SET(26) |
170 | 6e64da3c | Guan Xuetao | #define UCOP_SET_W UCOP_SET(25) |
171 | 6e64da3c | Guan Xuetao | #define UCOP_SET_L UCOP_SET(24) |
172 | 6e64da3c | Guan Xuetao | #define UCOP_SET_S UCOP_SET(24) |
173 | 6e64da3c | Guan Xuetao | |
174 | 6e64da3c | Guan Xuetao | #define ILLEGAL cpu_abort(env, \
|
175 | 6e64da3c | Guan Xuetao | "Illegal UniCore32 instruction %x at line %d!", \
|
176 | 6e64da3c | Guan Xuetao | insn, __LINE__) |
177 | 6e64da3c | Guan Xuetao | |
178 | 6e64da3c | Guan Xuetao | static inline void gen_set_asr(TCGv var, uint32_t mask) |
179 | 6e64da3c | Guan Xuetao | { |
180 | 6e64da3c | Guan Xuetao | TCGv tmp_mask = tcg_const_i32(mask); |
181 | 6e64da3c | Guan Xuetao | gen_helper_asr_write(var, tmp_mask); |
182 | 6e64da3c | Guan Xuetao | tcg_temp_free_i32(tmp_mask); |
183 | 6e64da3c | Guan Xuetao | } |
184 | 6e64da3c | Guan Xuetao | /* Set NZCV flags from the high 4 bits of var. */
|
185 | 6e64da3c | Guan Xuetao | #define gen_set_nzcv(var) gen_set_asr(var, ASR_NZCV)
|
186 | 6e64da3c | Guan Xuetao | |
187 | 6e64da3c | Guan Xuetao | static void gen_exception(int excp) |
188 | 6e64da3c | Guan Xuetao | { |
189 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
190 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp, excp); |
191 | 6e64da3c | Guan Xuetao | gen_helper_exception(tmp); |
192 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
193 | 6e64da3c | Guan Xuetao | } |
194 | 6e64da3c | Guan Xuetao | |
195 | 6e64da3c | Guan Xuetao | /* FIXME: Most targets have native widening multiplication.
|
196 | 6e64da3c | Guan Xuetao | It would be good to use that instead of a full wide multiply. */
|
197 | 6e64da3c | Guan Xuetao | /* 32x32->64 multiply. Marks inputs as dead. */
|
198 | 6e64da3c | Guan Xuetao | static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
|
199 | 6e64da3c | Guan Xuetao | { |
200 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp1 = tcg_temp_new_i64(); |
201 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp2 = tcg_temp_new_i64(); |
202 | 6e64da3c | Guan Xuetao | |
203 | 6e64da3c | Guan Xuetao | tcg_gen_extu_i32_i64(tmp1, a); |
204 | 6e64da3c | Guan Xuetao | dead_tmp(a); |
205 | 6e64da3c | Guan Xuetao | tcg_gen_extu_i32_i64(tmp2, b); |
206 | 6e64da3c | Guan Xuetao | dead_tmp(b); |
207 | 6e64da3c | Guan Xuetao | tcg_gen_mul_i64(tmp1, tmp1, tmp2); |
208 | 6e64da3c | Guan Xuetao | tcg_temp_free_i64(tmp2); |
209 | 6e64da3c | Guan Xuetao | return tmp1;
|
210 | 6e64da3c | Guan Xuetao | } |
211 | 6e64da3c | Guan Xuetao | |
212 | 6e64da3c | Guan Xuetao | static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
|
213 | 6e64da3c | Guan Xuetao | { |
214 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp1 = tcg_temp_new_i64(); |
215 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp2 = tcg_temp_new_i64(); |
216 | 6e64da3c | Guan Xuetao | |
217 | 6e64da3c | Guan Xuetao | tcg_gen_ext_i32_i64(tmp1, a); |
218 | 6e64da3c | Guan Xuetao | dead_tmp(a); |
219 | 6e64da3c | Guan Xuetao | tcg_gen_ext_i32_i64(tmp2, b); |
220 | 6e64da3c | Guan Xuetao | dead_tmp(b); |
221 | 6e64da3c | Guan Xuetao | tcg_gen_mul_i64(tmp1, tmp1, tmp2); |
222 | 6e64da3c | Guan Xuetao | tcg_temp_free_i64(tmp2); |
223 | 6e64da3c | Guan Xuetao | return tmp1;
|
224 | 6e64da3c | Guan Xuetao | } |
225 | 6e64da3c | Guan Xuetao | |
226 | 6e64da3c | Guan Xuetao | #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
|
227 | 6e64da3c | Guan Xuetao | |
228 | 6e64da3c | Guan Xuetao | /* Set CF to the top bit of var. */
|
229 | 6e64da3c | Guan Xuetao | static void gen_set_CF_bit31(TCGv var) |
230 | 6e64da3c | Guan Xuetao | { |
231 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
232 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i32(tmp, var, 31);
|
233 | 6e64da3c | Guan Xuetao | gen_set_CF(tmp); |
234 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
235 | 6e64da3c | Guan Xuetao | } |
236 | 6e64da3c | Guan Xuetao | |
237 | 6e64da3c | Guan Xuetao | /* Set N and Z flags from var. */
|
238 | 6e64da3c | Guan Xuetao | static inline void gen_logic_CC(TCGv var) |
239 | 6e64da3c | Guan Xuetao | { |
240 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF)); |
241 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF)); |
242 | 6e64da3c | Guan Xuetao | } |
243 | 6e64da3c | Guan Xuetao | |
244 | 6e64da3c | Guan Xuetao | /* dest = T0 + T1 + CF. */
|
245 | 6e64da3c | Guan Xuetao | static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) |
246 | 6e64da3c | Guan Xuetao | { |
247 | 6e64da3c | Guan Xuetao | TCGv tmp; |
248 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(dest, t0, t1); |
249 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
250 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(dest, dest, tmp); |
251 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
252 | 6e64da3c | Guan Xuetao | } |
253 | 6e64da3c | Guan Xuetao | |
254 | 6e64da3c | Guan Xuetao | /* dest = T0 - T1 + CF - 1. */
|
255 | 6e64da3c | Guan Xuetao | static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) |
256 | 6e64da3c | Guan Xuetao | { |
257 | 6e64da3c | Guan Xuetao | TCGv tmp; |
258 | 6e64da3c | Guan Xuetao | tcg_gen_sub_i32(dest, t0, t1); |
259 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
260 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(dest, dest, tmp); |
261 | 6e64da3c | Guan Xuetao | tcg_gen_subi_i32(dest, dest, 1);
|
262 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
263 | 6e64da3c | Guan Xuetao | } |
264 | 6e64da3c | Guan Xuetao | |
265 | 6e64da3c | Guan Xuetao | static void shifter_out_im(TCGv var, int shift) |
266 | 6e64da3c | Guan Xuetao | { |
267 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
268 | 6e64da3c | Guan Xuetao | if (shift == 0) { |
269 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(tmp, var, 1);
|
270 | 6e64da3c | Guan Xuetao | } else {
|
271 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i32(tmp, var, shift); |
272 | 6e64da3c | Guan Xuetao | if (shift != 31) { |
273 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(tmp, tmp, 1);
|
274 | 6e64da3c | Guan Xuetao | } |
275 | 6e64da3c | Guan Xuetao | } |
276 | 6e64da3c | Guan Xuetao | gen_set_CF(tmp); |
277 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
278 | 6e64da3c | Guan Xuetao | } |
279 | 6e64da3c | Guan Xuetao | |
280 | 6e64da3c | Guan Xuetao | /* Shift by immediate. Includes special handling for shift == 0. */
|
281 | 6e64da3c | Guan Xuetao | static inline void gen_uc32_shift_im(TCGv var, int shiftop, int shift, |
282 | 6e64da3c | Guan Xuetao | int flags)
|
283 | 6e64da3c | Guan Xuetao | { |
284 | 6e64da3c | Guan Xuetao | switch (shiftop) {
|
285 | 6e64da3c | Guan Xuetao | case 0: /* LSL */ |
286 | 6e64da3c | Guan Xuetao | if (shift != 0) { |
287 | 6e64da3c | Guan Xuetao | if (flags) {
|
288 | 6e64da3c | Guan Xuetao | shifter_out_im(var, 32 - shift);
|
289 | 6e64da3c | Guan Xuetao | } |
290 | 6e64da3c | Guan Xuetao | tcg_gen_shli_i32(var, var, shift); |
291 | 6e64da3c | Guan Xuetao | } |
292 | 6e64da3c | Guan Xuetao | break;
|
293 | 6e64da3c | Guan Xuetao | case 1: /* LSR */ |
294 | 6e64da3c | Guan Xuetao | if (shift == 0) { |
295 | 6e64da3c | Guan Xuetao | if (flags) {
|
296 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i32(var, var, 31);
|
297 | 6e64da3c | Guan Xuetao | gen_set_CF(var); |
298 | 6e64da3c | Guan Xuetao | } |
299 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(var, 0);
|
300 | 6e64da3c | Guan Xuetao | } else {
|
301 | 6e64da3c | Guan Xuetao | if (flags) {
|
302 | 6e64da3c | Guan Xuetao | shifter_out_im(var, shift - 1);
|
303 | 6e64da3c | Guan Xuetao | } |
304 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i32(var, var, shift); |
305 | 6e64da3c | Guan Xuetao | } |
306 | 6e64da3c | Guan Xuetao | break;
|
307 | 6e64da3c | Guan Xuetao | case 2: /* ASR */ |
308 | 6e64da3c | Guan Xuetao | if (shift == 0) { |
309 | 6e64da3c | Guan Xuetao | shift = 32;
|
310 | 6e64da3c | Guan Xuetao | } |
311 | 6e64da3c | Guan Xuetao | if (flags) {
|
312 | 6e64da3c | Guan Xuetao | shifter_out_im(var, shift - 1);
|
313 | 6e64da3c | Guan Xuetao | } |
314 | 6e64da3c | Guan Xuetao | if (shift == 32) { |
315 | 6e64da3c | Guan Xuetao | shift = 31;
|
316 | 6e64da3c | Guan Xuetao | } |
317 | 6e64da3c | Guan Xuetao | tcg_gen_sari_i32(var, var, shift); |
318 | 6e64da3c | Guan Xuetao | break;
|
319 | 6e64da3c | Guan Xuetao | case 3: /* ROR/RRX */ |
320 | 6e64da3c | Guan Xuetao | if (shift != 0) { |
321 | 6e64da3c | Guan Xuetao | if (flags) {
|
322 | 6e64da3c | Guan Xuetao | shifter_out_im(var, shift - 1);
|
323 | 6e64da3c | Guan Xuetao | } |
324 | 6e64da3c | Guan Xuetao | tcg_gen_rotri_i32(var, var, shift); break;
|
325 | 6e64da3c | Guan Xuetao | } else {
|
326 | 6e64da3c | Guan Xuetao | TCGv tmp = load_cpu_field(CF); |
327 | 6e64da3c | Guan Xuetao | if (flags) {
|
328 | 6e64da3c | Guan Xuetao | shifter_out_im(var, 0);
|
329 | 6e64da3c | Guan Xuetao | } |
330 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i32(var, var, 1);
|
331 | 6e64da3c | Guan Xuetao | tcg_gen_shli_i32(tmp, tmp, 31);
|
332 | 6e64da3c | Guan Xuetao | tcg_gen_or_i32(var, var, tmp); |
333 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
334 | 6e64da3c | Guan Xuetao | } |
335 | 6e64da3c | Guan Xuetao | } |
336 | 6e64da3c | Guan Xuetao | }; |
337 | 6e64da3c | Guan Xuetao | |
338 | 6e64da3c | Guan Xuetao | static inline void gen_uc32_shift_reg(TCGv var, int shiftop, |
339 | 6e64da3c | Guan Xuetao | TCGv shift, int flags)
|
340 | 6e64da3c | Guan Xuetao | { |
341 | 6e64da3c | Guan Xuetao | if (flags) {
|
342 | 6e64da3c | Guan Xuetao | switch (shiftop) {
|
343 | 6e64da3c | Guan Xuetao | case 0: |
344 | 6e64da3c | Guan Xuetao | gen_helper_shl_cc(var, var, shift); |
345 | 6e64da3c | Guan Xuetao | break;
|
346 | 6e64da3c | Guan Xuetao | case 1: |
347 | 6e64da3c | Guan Xuetao | gen_helper_shr_cc(var, var, shift); |
348 | 6e64da3c | Guan Xuetao | break;
|
349 | 6e64da3c | Guan Xuetao | case 2: |
350 | 6e64da3c | Guan Xuetao | gen_helper_sar_cc(var, var, shift); |
351 | 6e64da3c | Guan Xuetao | break;
|
352 | 6e64da3c | Guan Xuetao | case 3: |
353 | 6e64da3c | Guan Xuetao | gen_helper_ror_cc(var, var, shift); |
354 | 6e64da3c | Guan Xuetao | break;
|
355 | 6e64da3c | Guan Xuetao | } |
356 | 6e64da3c | Guan Xuetao | } else {
|
357 | 6e64da3c | Guan Xuetao | switch (shiftop) {
|
358 | 6e64da3c | Guan Xuetao | case 0: |
359 | 6e64da3c | Guan Xuetao | gen_helper_shl(var, var, shift); |
360 | 6e64da3c | Guan Xuetao | break;
|
361 | 6e64da3c | Guan Xuetao | case 1: |
362 | 6e64da3c | Guan Xuetao | gen_helper_shr(var, var, shift); |
363 | 6e64da3c | Guan Xuetao | break;
|
364 | 6e64da3c | Guan Xuetao | case 2: |
365 | 6e64da3c | Guan Xuetao | gen_helper_sar(var, var, shift); |
366 | 6e64da3c | Guan Xuetao | break;
|
367 | 6e64da3c | Guan Xuetao | case 3: |
368 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(shift, shift, 0x1f);
|
369 | 6e64da3c | Guan Xuetao | tcg_gen_rotr_i32(var, var, shift); |
370 | 6e64da3c | Guan Xuetao | break;
|
371 | 6e64da3c | Guan Xuetao | } |
372 | 6e64da3c | Guan Xuetao | } |
373 | 6e64da3c | Guan Xuetao | dead_tmp(shift); |
374 | 6e64da3c | Guan Xuetao | } |
375 | 6e64da3c | Guan Xuetao | |
376 | 6e64da3c | Guan Xuetao | static void gen_test_cc(int cc, int label) |
377 | 6e64da3c | Guan Xuetao | { |
378 | 6e64da3c | Guan Xuetao | TCGv tmp; |
379 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
380 | 6e64da3c | Guan Xuetao | int inv;
|
381 | 6e64da3c | Guan Xuetao | |
382 | 6e64da3c | Guan Xuetao | switch (cc) {
|
383 | 6e64da3c | Guan Xuetao | case 0: /* eq: Z */ |
384 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
385 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
386 | 6e64da3c | Guan Xuetao | break;
|
387 | 6e64da3c | Guan Xuetao | case 1: /* ne: !Z */ |
388 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
389 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
|
390 | 6e64da3c | Guan Xuetao | break;
|
391 | 6e64da3c | Guan Xuetao | case 2: /* cs: C */ |
392 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
393 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
|
394 | 6e64da3c | Guan Xuetao | break;
|
395 | 6e64da3c | Guan Xuetao | case 3: /* cc: !C */ |
396 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
397 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
398 | 6e64da3c | Guan Xuetao | break;
|
399 | 6e64da3c | Guan Xuetao | case 4: /* mi: N */ |
400 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(NF); |
401 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
|
402 | 6e64da3c | Guan Xuetao | break;
|
403 | 6e64da3c | Guan Xuetao | case 5: /* pl: !N */ |
404 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(NF); |
405 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
|
406 | 6e64da3c | Guan Xuetao | break;
|
407 | 6e64da3c | Guan Xuetao | case 6: /* vs: V */ |
408 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
409 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
|
410 | 6e64da3c | Guan Xuetao | break;
|
411 | 6e64da3c | Guan Xuetao | case 7: /* vc: !V */ |
412 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
413 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
|
414 | 6e64da3c | Guan Xuetao | break;
|
415 | 6e64da3c | Guan Xuetao | case 8: /* hi: C && !Z */ |
416 | 6e64da3c | Guan Xuetao | inv = gen_new_label(); |
417 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
418 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
|
419 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
420 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
421 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
|
422 | 6e64da3c | Guan Xuetao | gen_set_label(inv); |
423 | 6e64da3c | Guan Xuetao | break;
|
424 | 6e64da3c | Guan Xuetao | case 9: /* ls: !C || Z */ |
425 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(CF); |
426 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
427 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
428 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
429 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
430 | 6e64da3c | Guan Xuetao | break;
|
431 | 6e64da3c | Guan Xuetao | case 10: /* ge: N == V -> N ^ V == 0 */ |
432 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
433 | 6e64da3c | Guan Xuetao | tmp2 = load_cpu_field(NF); |
434 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
435 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
436 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
|
437 | 6e64da3c | Guan Xuetao | break;
|
438 | 6e64da3c | Guan Xuetao | case 11: /* lt: N != V -> N ^ V != 0 */ |
439 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
440 | 6e64da3c | Guan Xuetao | tmp2 = load_cpu_field(NF); |
441 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
442 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
443 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
|
444 | 6e64da3c | Guan Xuetao | break;
|
445 | 6e64da3c | Guan Xuetao | case 12: /* gt: !Z && N == V */ |
446 | 6e64da3c | Guan Xuetao | inv = gen_new_label(); |
447 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
448 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
|
449 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
450 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
451 | 6e64da3c | Guan Xuetao | tmp2 = load_cpu_field(NF); |
452 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
453 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
454 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
|
455 | 6e64da3c | Guan Xuetao | gen_set_label(inv); |
456 | 6e64da3c | Guan Xuetao | break;
|
457 | 6e64da3c | Guan Xuetao | case 13: /* le: Z || N != V */ |
458 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(ZF); |
459 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
460 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
461 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(VF); |
462 | 6e64da3c | Guan Xuetao | tmp2 = load_cpu_field(NF); |
463 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
464 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
465 | 6e64da3c | Guan Xuetao | tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
|
466 | 6e64da3c | Guan Xuetao | break;
|
467 | 6e64da3c | Guan Xuetao | default:
|
468 | 6e64da3c | Guan Xuetao | fprintf(stderr, "Bad condition code 0x%x\n", cc);
|
469 | 6e64da3c | Guan Xuetao | abort(); |
470 | 6e64da3c | Guan Xuetao | } |
471 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
472 | 6e64da3c | Guan Xuetao | } |
473 | 6e64da3c | Guan Xuetao | |
474 | 6e64da3c | Guan Xuetao | static const uint8_t table_logic_cc[16] = { |
475 | 6e64da3c | Guan Xuetao | 1, /* and */ 1, /* xor */ 0, /* sub */ 0, /* rsb */ |
476 | 6e64da3c | Guan Xuetao | 0, /* add */ 0, /* adc */ 0, /* sbc */ 0, /* rsc */ |
477 | 6e64da3c | Guan Xuetao | 1, /* andl */ 1, /* xorl */ 0, /* cmp */ 0, /* cmn */ |
478 | 6e64da3c | Guan Xuetao | 1, /* orr */ 1, /* mov */ 1, /* bic */ 1, /* mvn */ |
479 | 6e64da3c | Guan Xuetao | }; |
480 | 6e64da3c | Guan Xuetao | |
481 | 6e64da3c | Guan Xuetao | /* Set PC state from an immediate address. */
|
482 | 6e64da3c | Guan Xuetao | static inline void gen_bx_im(DisasContext *s, uint32_t addr) |
483 | 6e64da3c | Guan Xuetao | { |
484 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_UPDATE; |
485 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(cpu_R[31], addr & ~3); |
486 | 6e64da3c | Guan Xuetao | } |
487 | 6e64da3c | Guan Xuetao | |
488 | 6e64da3c | Guan Xuetao | /* Set PC state from var. var is marked as dead. */
|
489 | 6e64da3c | Guan Xuetao | static inline void gen_bx(DisasContext *s, TCGv var) |
490 | 6e64da3c | Guan Xuetao | { |
491 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_UPDATE; |
492 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(cpu_R[31], var, ~3); |
493 | 6e64da3c | Guan Xuetao | dead_tmp(var); |
494 | 6e64da3c | Guan Xuetao | } |
495 | 6e64da3c | Guan Xuetao | |
496 | 6e64da3c | Guan Xuetao | static inline void store_reg_bx(DisasContext *s, int reg, TCGv var) |
497 | 6e64da3c | Guan Xuetao | { |
498 | 6e64da3c | Guan Xuetao | store_reg(s, reg, var); |
499 | 6e64da3c | Guan Xuetao | } |
500 | 6e64da3c | Guan Xuetao | |
501 | 6e64da3c | Guan Xuetao | static inline TCGv gen_ld8s(TCGv addr, int index) |
502 | 6e64da3c | Guan Xuetao | { |
503 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
504 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld8s(tmp, addr, index); |
505 | 6e64da3c | Guan Xuetao | return tmp;
|
506 | 6e64da3c | Guan Xuetao | } |
507 | 6e64da3c | Guan Xuetao | |
508 | 6e64da3c | Guan Xuetao | static inline TCGv gen_ld8u(TCGv addr, int index) |
509 | 6e64da3c | Guan Xuetao | { |
510 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
511 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld8u(tmp, addr, index); |
512 | 6e64da3c | Guan Xuetao | return tmp;
|
513 | 6e64da3c | Guan Xuetao | } |
514 | 6e64da3c | Guan Xuetao | |
515 | 6e64da3c | Guan Xuetao | static inline TCGv gen_ld16s(TCGv addr, int index) |
516 | 6e64da3c | Guan Xuetao | { |
517 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
518 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld16s(tmp, addr, index); |
519 | 6e64da3c | Guan Xuetao | return tmp;
|
520 | 6e64da3c | Guan Xuetao | } |
521 | 6e64da3c | Guan Xuetao | |
522 | 6e64da3c | Guan Xuetao | static inline TCGv gen_ld16u(TCGv addr, int index) |
523 | 6e64da3c | Guan Xuetao | { |
524 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
525 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld16u(tmp, addr, index); |
526 | 6e64da3c | Guan Xuetao | return tmp;
|
527 | 6e64da3c | Guan Xuetao | } |
528 | 6e64da3c | Guan Xuetao | |
529 | 6e64da3c | Guan Xuetao | static inline TCGv gen_ld32(TCGv addr, int index) |
530 | 6e64da3c | Guan Xuetao | { |
531 | 6e64da3c | Guan Xuetao | TCGv tmp = new_tmp(); |
532 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld32u(tmp, addr, index); |
533 | 6e64da3c | Guan Xuetao | return tmp;
|
534 | 6e64da3c | Guan Xuetao | } |
535 | 6e64da3c | Guan Xuetao | |
536 | 6e64da3c | Guan Xuetao | static inline TCGv_i64 gen_ld64(TCGv addr, int index) |
537 | 6e64da3c | Guan Xuetao | { |
538 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp = tcg_temp_new_i64(); |
539 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_ld64(tmp, addr, index); |
540 | 6e64da3c | Guan Xuetao | return tmp;
|
541 | 6e64da3c | Guan Xuetao | } |
542 | 6e64da3c | Guan Xuetao | |
543 | 6e64da3c | Guan Xuetao | static inline void gen_st8(TCGv val, TCGv addr, int index) |
544 | 6e64da3c | Guan Xuetao | { |
545 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_st8(val, addr, index); |
546 | 6e64da3c | Guan Xuetao | dead_tmp(val); |
547 | 6e64da3c | Guan Xuetao | } |
548 | 6e64da3c | Guan Xuetao | |
549 | 6e64da3c | Guan Xuetao | static inline void gen_st16(TCGv val, TCGv addr, int index) |
550 | 6e64da3c | Guan Xuetao | { |
551 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_st16(val, addr, index); |
552 | 6e64da3c | Guan Xuetao | dead_tmp(val); |
553 | 6e64da3c | Guan Xuetao | } |
554 | 6e64da3c | Guan Xuetao | |
555 | 6e64da3c | Guan Xuetao | static inline void gen_st32(TCGv val, TCGv addr, int index) |
556 | 6e64da3c | Guan Xuetao | { |
557 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_st32(val, addr, index); |
558 | 6e64da3c | Guan Xuetao | dead_tmp(val); |
559 | 6e64da3c | Guan Xuetao | } |
560 | 6e64da3c | Guan Xuetao | |
561 | 6e64da3c | Guan Xuetao | static inline void gen_st64(TCGv_i64 val, TCGv addr, int index) |
562 | 6e64da3c | Guan Xuetao | { |
563 | 6e64da3c | Guan Xuetao | tcg_gen_qemu_st64(val, addr, index); |
564 | 6e64da3c | Guan Xuetao | tcg_temp_free_i64(val); |
565 | 6e64da3c | Guan Xuetao | } |
566 | 6e64da3c | Guan Xuetao | |
567 | 6e64da3c | Guan Xuetao | static inline void gen_set_pc_im(uint32_t val) |
568 | 6e64da3c | Guan Xuetao | { |
569 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(cpu_R[31], val);
|
570 | 6e64da3c | Guan Xuetao | } |
571 | 6e64da3c | Guan Xuetao | |
572 | 6e64da3c | Guan Xuetao | /* Force a TB lookup after an instruction that changes the CPU state. */
|
573 | 6e64da3c | Guan Xuetao | static inline void gen_lookup_tb(DisasContext *s) |
574 | 6e64da3c | Guan Xuetao | { |
575 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(cpu_R[31], s->pc & ~1); |
576 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_UPDATE; |
577 | 6e64da3c | Guan Xuetao | } |
578 | 6e64da3c | Guan Xuetao | |
579 | 6e64da3c | Guan Xuetao | static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, |
580 | 6e64da3c | Guan Xuetao | TCGv var) |
581 | 6e64da3c | Guan Xuetao | { |
582 | 6e64da3c | Guan Xuetao | int val;
|
583 | 6e64da3c | Guan Xuetao | TCGv offset; |
584 | 6e64da3c | Guan Xuetao | |
585 | 6e64da3c | Guan Xuetao | if (UCOP_SET(29)) { |
586 | 6e64da3c | Guan Xuetao | /* immediate */
|
587 | 6e64da3c | Guan Xuetao | val = UCOP_IMM14; |
588 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
589 | 6e64da3c | Guan Xuetao | val = -val; |
590 | 6e64da3c | Guan Xuetao | } |
591 | 6e64da3c | Guan Xuetao | if (val != 0) { |
592 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(var, var, val); |
593 | 6e64da3c | Guan Xuetao | } |
594 | 6e64da3c | Guan Xuetao | } else {
|
595 | 6e64da3c | Guan Xuetao | /* shift/register */
|
596 | 6e64da3c | Guan Xuetao | offset = load_reg(s, UCOP_REG_M); |
597 | 6e64da3c | Guan Xuetao | gen_uc32_shift_im(offset, UCOP_SH_OP, UCOP_SH_IM, 0);
|
598 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
599 | 6e64da3c | Guan Xuetao | tcg_gen_sub_i32(var, var, offset); |
600 | 6e64da3c | Guan Xuetao | } else {
|
601 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(var, var, offset); |
602 | 6e64da3c | Guan Xuetao | } |
603 | 6e64da3c | Guan Xuetao | dead_tmp(offset); |
604 | 6e64da3c | Guan Xuetao | } |
605 | 6e64da3c | Guan Xuetao | } |
606 | 6e64da3c | Guan Xuetao | |
607 | 6e64da3c | Guan Xuetao | static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, |
608 | 6e64da3c | Guan Xuetao | TCGv var) |
609 | 6e64da3c | Guan Xuetao | { |
610 | 6e64da3c | Guan Xuetao | int val;
|
611 | 6e64da3c | Guan Xuetao | TCGv offset; |
612 | 6e64da3c | Guan Xuetao | |
613 | 6e64da3c | Guan Xuetao | if (UCOP_SET(26)) { |
614 | 6e64da3c | Guan Xuetao | /* immediate */
|
615 | 6e64da3c | Guan Xuetao | val = (insn & 0x1f) | ((insn >> 4) & 0x3e0); |
616 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
617 | 6e64da3c | Guan Xuetao | val = -val; |
618 | 6e64da3c | Guan Xuetao | } |
619 | 6e64da3c | Guan Xuetao | if (val != 0) { |
620 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(var, var, val); |
621 | 6e64da3c | Guan Xuetao | } |
622 | 6e64da3c | Guan Xuetao | } else {
|
623 | 6e64da3c | Guan Xuetao | /* register */
|
624 | 6e64da3c | Guan Xuetao | offset = load_reg(s, UCOP_REG_M); |
625 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
626 | 6e64da3c | Guan Xuetao | tcg_gen_sub_i32(var, var, offset); |
627 | 6e64da3c | Guan Xuetao | } else {
|
628 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(var, var, offset); |
629 | 6e64da3c | Guan Xuetao | } |
630 | 6e64da3c | Guan Xuetao | dead_tmp(offset); |
631 | 6e64da3c | Guan Xuetao | } |
632 | 6e64da3c | Guan Xuetao | } |
633 | 6e64da3c | Guan Xuetao | |
634 | 6e64da3c | Guan Xuetao | static inline long ucf64_reg_offset(int reg) |
635 | 6e64da3c | Guan Xuetao | { |
636 | 6e64da3c | Guan Xuetao | if (reg & 1) { |
637 | 6e64da3c | Guan Xuetao | return offsetof(CPUState, ucf64.regs[reg >> 1]) |
638 | 6e64da3c | Guan Xuetao | + offsetof(CPU_DoubleU, l.upper); |
639 | 6e64da3c | Guan Xuetao | } else {
|
640 | 6e64da3c | Guan Xuetao | return offsetof(CPUState, ucf64.regs[reg >> 1]) |
641 | 6e64da3c | Guan Xuetao | + offsetof(CPU_DoubleU, l.lower); |
642 | 6e64da3c | Guan Xuetao | } |
643 | 6e64da3c | Guan Xuetao | } |
644 | 6e64da3c | Guan Xuetao | |
645 | 6e64da3c | Guan Xuetao | #define ucf64_gen_ld32(reg) load_cpu_offset(ucf64_reg_offset(reg))
|
646 | 6e64da3c | Guan Xuetao | #define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg))
|
647 | 6e64da3c | Guan Xuetao | |
648 | 6e64da3c | Guan Xuetao | /* UniCore-F64 single load/store I_offset */
|
649 | 6e64da3c | Guan Xuetao | static void do_ucf64_ldst_i(CPUState *env, DisasContext *s, uint32_t insn) |
650 | 6e64da3c | Guan Xuetao | { |
651 | 6e64da3c | Guan Xuetao | int offset;
|
652 | 6e64da3c | Guan Xuetao | TCGv tmp; |
653 | 6e64da3c | Guan Xuetao | TCGv addr; |
654 | 6e64da3c | Guan Xuetao | |
655 | 6e64da3c | Guan Xuetao | addr = load_reg(s, UCOP_REG_N); |
656 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_P && !UCOP_SET_W) {
|
657 | 6e64da3c | Guan Xuetao | ILLEGAL; |
658 | 6e64da3c | Guan Xuetao | } |
659 | 6e64da3c | Guan Xuetao | |
660 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
661 | 6e64da3c | Guan Xuetao | offset = UCOP_IMM10 << 2;
|
662 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
663 | 6e64da3c | Guan Xuetao | offset = -offset; |
664 | 6e64da3c | Guan Xuetao | } |
665 | 6e64da3c | Guan Xuetao | if (offset != 0) { |
666 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, offset); |
667 | 6e64da3c | Guan Xuetao | } |
668 | 6e64da3c | Guan Xuetao | } |
669 | 6e64da3c | Guan Xuetao | |
670 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) { /* load */ |
671 | 6e64da3c | Guan Xuetao | tmp = gen_ld32(addr, IS_USER(s)); |
672 | 6e64da3c | Guan Xuetao | ucf64_gen_st32(tmp, UCOP_REG_D); |
673 | 6e64da3c | Guan Xuetao | } else { /* store */ |
674 | 6e64da3c | Guan Xuetao | tmp = ucf64_gen_ld32(UCOP_REG_D); |
675 | 6e64da3c | Guan Xuetao | gen_st32(tmp, addr, IS_USER(s)); |
676 | 6e64da3c | Guan Xuetao | } |
677 | 6e64da3c | Guan Xuetao | |
678 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_P) {
|
679 | 6e64da3c | Guan Xuetao | offset = UCOP_IMM10 << 2;
|
680 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_U) {
|
681 | 6e64da3c | Guan Xuetao | offset = -offset; |
682 | 6e64da3c | Guan Xuetao | } |
683 | 6e64da3c | Guan Xuetao | if (offset != 0) { |
684 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, offset); |
685 | 6e64da3c | Guan Xuetao | } |
686 | 6e64da3c | Guan Xuetao | } |
687 | 6e64da3c | Guan Xuetao | if (UCOP_SET_W) {
|
688 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, addr); |
689 | 6e64da3c | Guan Xuetao | } else {
|
690 | 6e64da3c | Guan Xuetao | dead_tmp(addr); |
691 | 6e64da3c | Guan Xuetao | } |
692 | 6e64da3c | Guan Xuetao | } |
693 | 6e64da3c | Guan Xuetao | |
694 | 6e64da3c | Guan Xuetao | /* UniCore-F64 load/store multiple words */
|
695 | 6e64da3c | Guan Xuetao | static void do_ucf64_ldst_m(CPUState *env, DisasContext *s, uint32_t insn) |
696 | 6e64da3c | Guan Xuetao | { |
697 | 6e64da3c | Guan Xuetao | unsigned int i; |
698 | 6e64da3c | Guan Xuetao | int j, n, freg;
|
699 | 6e64da3c | Guan Xuetao | TCGv tmp; |
700 | 6e64da3c | Guan Xuetao | TCGv addr; |
701 | 6e64da3c | Guan Xuetao | |
702 | 6e64da3c | Guan Xuetao | if (UCOP_REG_D != 0) { |
703 | 6e64da3c | Guan Xuetao | ILLEGAL; |
704 | 6e64da3c | Guan Xuetao | } |
705 | 6e64da3c | Guan Xuetao | if (UCOP_REG_N == 31) { |
706 | 6e64da3c | Guan Xuetao | ILLEGAL; |
707 | 6e64da3c | Guan Xuetao | } |
708 | 6e64da3c | Guan Xuetao | if ((insn << 24) == 0) { |
709 | 6e64da3c | Guan Xuetao | ILLEGAL; |
710 | 6e64da3c | Guan Xuetao | } |
711 | 6e64da3c | Guan Xuetao | |
712 | 6e64da3c | Guan Xuetao | addr = load_reg(s, UCOP_REG_N); |
713 | 6e64da3c | Guan Xuetao | |
714 | 6e64da3c | Guan Xuetao | n = 0;
|
715 | 6e64da3c | Guan Xuetao | for (i = 0; i < 8; i++) { |
716 | 6e64da3c | Guan Xuetao | if (UCOP_SET(i)) {
|
717 | 6e64da3c | Guan Xuetao | n++; |
718 | 6e64da3c | Guan Xuetao | } |
719 | 6e64da3c | Guan Xuetao | } |
720 | 6e64da3c | Guan Xuetao | |
721 | 6e64da3c | Guan Xuetao | if (UCOP_SET_U) {
|
722 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) { /* pre increment */ |
723 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
724 | 6e64da3c | Guan Xuetao | } /* unnecessary to do anything when post increment */
|
725 | 6e64da3c | Guan Xuetao | } else {
|
726 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) { /* pre decrement */ |
727 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -(n * 4));
|
728 | 6e64da3c | Guan Xuetao | } else { /* post decrement */ |
729 | 6e64da3c | Guan Xuetao | if (n != 1) { |
730 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); |
731 | 6e64da3c | Guan Xuetao | } |
732 | 6e64da3c | Guan Xuetao | } |
733 | 6e64da3c | Guan Xuetao | } |
734 | 6e64da3c | Guan Xuetao | |
735 | 6e64da3c | Guan Xuetao | freg = ((insn >> 8) & 3) << 3; /* freg should be 0, 8, 16, 24 */ |
736 | 6e64da3c | Guan Xuetao | |
737 | 6e64da3c | Guan Xuetao | for (i = 0, j = 0; i < 8; i++, freg++) { |
738 | 6e64da3c | Guan Xuetao | if (!UCOP_SET(i)) {
|
739 | 6e64da3c | Guan Xuetao | continue;
|
740 | 6e64da3c | Guan Xuetao | } |
741 | 6e64da3c | Guan Xuetao | |
742 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) { /* load */ |
743 | 6e64da3c | Guan Xuetao | tmp = gen_ld32(addr, IS_USER(s)); |
744 | 6e64da3c | Guan Xuetao | ucf64_gen_st32(tmp, freg); |
745 | 6e64da3c | Guan Xuetao | } else { /* store */ |
746 | 6e64da3c | Guan Xuetao | tmp = ucf64_gen_ld32(freg); |
747 | 6e64da3c | Guan Xuetao | gen_st32(tmp, addr, IS_USER(s)); |
748 | 6e64da3c | Guan Xuetao | } |
749 | 6e64da3c | Guan Xuetao | |
750 | 6e64da3c | Guan Xuetao | j++; |
751 | 6e64da3c | Guan Xuetao | /* unnecessary to add after the last transfer */
|
752 | 6e64da3c | Guan Xuetao | if (j != n) {
|
753 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
754 | 6e64da3c | Guan Xuetao | } |
755 | 6e64da3c | Guan Xuetao | } |
756 | 6e64da3c | Guan Xuetao | |
757 | 6e64da3c | Guan Xuetao | if (UCOP_SET_W) { /* write back */ |
758 | 6e64da3c | Guan Xuetao | if (UCOP_SET_U) {
|
759 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_P) { /* post increment */ |
760 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
761 | 6e64da3c | Guan Xuetao | } /* unnecessary to do anything when pre increment */
|
762 | 6e64da3c | Guan Xuetao | } else {
|
763 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
764 | 6e64da3c | Guan Xuetao | /* pre decrement */
|
765 | 6e64da3c | Guan Xuetao | if (n != 1) { |
766 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); |
767 | 6e64da3c | Guan Xuetao | } |
768 | 6e64da3c | Guan Xuetao | } else {
|
769 | 6e64da3c | Guan Xuetao | /* post decrement */
|
770 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -(n * 4));
|
771 | 6e64da3c | Guan Xuetao | } |
772 | 6e64da3c | Guan Xuetao | } |
773 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, addr); |
774 | 6e64da3c | Guan Xuetao | } else {
|
775 | 6e64da3c | Guan Xuetao | dead_tmp(addr); |
776 | 6e64da3c | Guan Xuetao | } |
777 | 6e64da3c | Guan Xuetao | } |
778 | 6e64da3c | Guan Xuetao | |
779 | 6e64da3c | Guan Xuetao | /* UniCore-F64 mrc/mcr */
|
780 | 6e64da3c | Guan Xuetao | static void do_ucf64_trans(CPUState *env, DisasContext *s, uint32_t insn) |
781 | 6e64da3c | Guan Xuetao | { |
782 | 6e64da3c | Guan Xuetao | TCGv tmp; |
783 | 6e64da3c | Guan Xuetao | |
784 | 6e64da3c | Guan Xuetao | if ((insn & 0xfe0003ff) == 0xe2000000) { |
785 | 6e64da3c | Guan Xuetao | /* control register */
|
786 | 6e64da3c | Guan Xuetao | if ((UCOP_REG_N != UC32_UCF64_FPSCR) || (UCOP_REG_D == 31)) { |
787 | 6e64da3c | Guan Xuetao | ILLEGAL; |
788 | 6e64da3c | Guan Xuetao | } |
789 | 6e64da3c | Guan Xuetao | if (UCOP_SET(24)) { |
790 | 6e64da3c | Guan Xuetao | /* CFF */
|
791 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
792 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_get_fpscr(tmp, cpu_env); |
793 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
794 | 6e64da3c | Guan Xuetao | } else {
|
795 | 6e64da3c | Guan Xuetao | /* CTF */
|
796 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_D); |
797 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_set_fpscr(cpu_env, tmp); |
798 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
799 | 6e64da3c | Guan Xuetao | gen_lookup_tb(s); |
800 | 6e64da3c | Guan Xuetao | } |
801 | 6e64da3c | Guan Xuetao | return;
|
802 | 6e64da3c | Guan Xuetao | } |
803 | 6e64da3c | Guan Xuetao | if ((insn & 0xfe0003ff) == 0xe0000000) { |
804 | 6e64da3c | Guan Xuetao | /* general register */
|
805 | 6e64da3c | Guan Xuetao | if (UCOP_REG_D == 31) { |
806 | 6e64da3c | Guan Xuetao | ILLEGAL; |
807 | 6e64da3c | Guan Xuetao | } |
808 | 6e64da3c | Guan Xuetao | if (UCOP_SET(24)) { /* MFF */ |
809 | 6e64da3c | Guan Xuetao | tmp = ucf64_gen_ld32(UCOP_REG_N); |
810 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
811 | 6e64da3c | Guan Xuetao | } else { /* MTF */ |
812 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_D); |
813 | 6e64da3c | Guan Xuetao | ucf64_gen_st32(tmp, UCOP_REG_N); |
814 | 6e64da3c | Guan Xuetao | } |
815 | 6e64da3c | Guan Xuetao | return;
|
816 | 6e64da3c | Guan Xuetao | } |
817 | 6e64da3c | Guan Xuetao | if ((insn & 0xfb000000) == 0xe9000000) { |
818 | 6e64da3c | Guan Xuetao | /* MFFC */
|
819 | 6e64da3c | Guan Xuetao | if (UCOP_REG_D != 31) { |
820 | 6e64da3c | Guan Xuetao | ILLEGAL; |
821 | 6e64da3c | Guan Xuetao | } |
822 | 6e64da3c | Guan Xuetao | if (UCOP_UCF64_COND & 0x8) { |
823 | 6e64da3c | Guan Xuetao | ILLEGAL; |
824 | 6e64da3c | Guan Xuetao | } |
825 | 6e64da3c | Guan Xuetao | |
826 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
827 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp, UCOP_UCF64_COND); |
828 | 6e64da3c | Guan Xuetao | if (UCOP_SET(26)) { |
829 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N)); |
830 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
831 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, tmp, cpu_env); |
832 | 6e64da3c | Guan Xuetao | } else {
|
833 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N)); |
834 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
835 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, tmp, cpu_env); |
836 | 6e64da3c | Guan Xuetao | } |
837 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
838 | 6e64da3c | Guan Xuetao | return;
|
839 | 6e64da3c | Guan Xuetao | } |
840 | 6e64da3c | Guan Xuetao | ILLEGAL; |
841 | 6e64da3c | Guan Xuetao | } |
842 | 6e64da3c | Guan Xuetao | |
843 | 6e64da3c | Guan Xuetao | /* UniCore-F64 convert instructions */
|
844 | 6e64da3c | Guan Xuetao | static void do_ucf64_fcvt(CPUState *env, DisasContext *s, uint32_t insn) |
845 | 6e64da3c | Guan Xuetao | { |
846 | 6e64da3c | Guan Xuetao | if (UCOP_UCF64_FMT == 3) { |
847 | 6e64da3c | Guan Xuetao | ILLEGAL; |
848 | 6e64da3c | Guan Xuetao | } |
849 | 6e64da3c | Guan Xuetao | if (UCOP_REG_N != 0) { |
850 | 6e64da3c | Guan Xuetao | ILLEGAL; |
851 | 6e64da3c | Guan Xuetao | } |
852 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FUNC) {
|
853 | 6e64da3c | Guan Xuetao | case 0: /* cvt.s */ |
854 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FMT) {
|
855 | 6e64da3c | Guan Xuetao | case 1 /* d */: |
856 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
857 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_df2sf(cpu_F0s, cpu_F0d, cpu_env); |
858 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
859 | 6e64da3c | Guan Xuetao | break;
|
860 | 6e64da3c | Guan Xuetao | case 2 /* w */: |
861 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
862 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_si2sf(cpu_F0s, cpu_F0s, cpu_env); |
863 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
864 | 6e64da3c | Guan Xuetao | break;
|
865 | 6e64da3c | Guan Xuetao | default /* s */: |
866 | 6e64da3c | Guan Xuetao | ILLEGAL; |
867 | 6e64da3c | Guan Xuetao | break;
|
868 | 6e64da3c | Guan Xuetao | } |
869 | 6e64da3c | Guan Xuetao | break;
|
870 | 6e64da3c | Guan Xuetao | case 1: /* cvt.d */ |
871 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FMT) {
|
872 | 6e64da3c | Guan Xuetao | case 0 /* s */: |
873 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
874 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_sf2df(cpu_F0d, cpu_F0s, cpu_env); |
875 | 6e64da3c | Guan Xuetao | tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
876 | 6e64da3c | Guan Xuetao | break;
|
877 | 6e64da3c | Guan Xuetao | case 2 /* w */: |
878 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
879 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_si2df(cpu_F0d, cpu_F0s, cpu_env); |
880 | 6e64da3c | Guan Xuetao | tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
881 | 6e64da3c | Guan Xuetao | break;
|
882 | 6e64da3c | Guan Xuetao | default /* d */: |
883 | 6e64da3c | Guan Xuetao | ILLEGAL; |
884 | 6e64da3c | Guan Xuetao | break;
|
885 | 6e64da3c | Guan Xuetao | } |
886 | 6e64da3c | Guan Xuetao | break;
|
887 | 6e64da3c | Guan Xuetao | case 4: /* cvt.w */ |
888 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FMT) {
|
889 | 6e64da3c | Guan Xuetao | case 0 /* s */: |
890 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
891 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_sf2si(cpu_F0s, cpu_F0s, cpu_env); |
892 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
893 | 6e64da3c | Guan Xuetao | break;
|
894 | 6e64da3c | Guan Xuetao | case 1 /* d */: |
895 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
896 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_df2si(cpu_F0s, cpu_F0d, cpu_env); |
897 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); |
898 | 6e64da3c | Guan Xuetao | break;
|
899 | 6e64da3c | Guan Xuetao | default /* w */: |
900 | 6e64da3c | Guan Xuetao | ILLEGAL; |
901 | 6e64da3c | Guan Xuetao | break;
|
902 | 6e64da3c | Guan Xuetao | } |
903 | 6e64da3c | Guan Xuetao | break;
|
904 | 6e64da3c | Guan Xuetao | default:
|
905 | 6e64da3c | Guan Xuetao | ILLEGAL; |
906 | 6e64da3c | Guan Xuetao | } |
907 | 6e64da3c | Guan Xuetao | } |
908 | 6e64da3c | Guan Xuetao | |
909 | 6e64da3c | Guan Xuetao | /* UniCore-F64 compare instructions */
|
910 | 6e64da3c | Guan Xuetao | static void do_ucf64_fcmp(CPUState *env, DisasContext *s, uint32_t insn) |
911 | 6e64da3c | Guan Xuetao | { |
912 | 6e64da3c | Guan Xuetao | if (UCOP_SET(25)) { |
913 | 6e64da3c | Guan Xuetao | ILLEGAL; |
914 | 6e64da3c | Guan Xuetao | } |
915 | 6e64da3c | Guan Xuetao | if (UCOP_REG_D != 0) { |
916 | 6e64da3c | Guan Xuetao | ILLEGAL; |
917 | 6e64da3c | Guan Xuetao | } |
918 | 6e64da3c | Guan Xuetao | |
919 | 6e64da3c | Guan Xuetao | ILLEGAL; /* TODO */
|
920 | 6e64da3c | Guan Xuetao | if (UCOP_SET(24)) { |
921 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N)); |
922 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
923 | 6e64da3c | Guan Xuetao | /* gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, cpu_env); */
|
924 | 6e64da3c | Guan Xuetao | } else {
|
925 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N)); |
926 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); |
927 | 6e64da3c | Guan Xuetao | /* gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, cpu_env); */
|
928 | 6e64da3c | Guan Xuetao | } |
929 | 6e64da3c | Guan Xuetao | } |
930 | 6e64da3c | Guan Xuetao | |
931 | 6e64da3c | Guan Xuetao | #define gen_helper_ucf64_movs(x, y) do { } while (0) |
932 | 6e64da3c | Guan Xuetao | #define gen_helper_ucf64_movd(x, y) do { } while (0) |
933 | 6e64da3c | Guan Xuetao | |
934 | 6e64da3c | Guan Xuetao | #define UCF64_OP1(name) do { \ |
935 | 6e64da3c | Guan Xuetao | if (UCOP_REG_N != 0) { \ |
936 | 6e64da3c | Guan Xuetao | ILLEGAL; \ |
937 | 6e64da3c | Guan Xuetao | } \ |
938 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FMT) { \
|
939 | 6e64da3c | Guan Xuetao | case 0 /* s */: \ |
940 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, \ |
941 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_M)); \ |
942 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_##name##s(cpu_F0s, cpu_F0s); \ |
943 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, \ |
944 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_D)); \ |
945 | 6e64da3c | Guan Xuetao | break; \
|
946 | 6e64da3c | Guan Xuetao | case 1 /* d */: \ |
947 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, \ |
948 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_M)); \ |
949 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_##name##d(cpu_F0d, cpu_F0d); \ |
950 | 6e64da3c | Guan Xuetao | tcg_gen_st_i64(cpu_F0d, cpu_env, \ |
951 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_D)); \ |
952 | 6e64da3c | Guan Xuetao | break; \
|
953 | 6e64da3c | Guan Xuetao | case 2 /* w */: \ |
954 | 6e64da3c | Guan Xuetao | ILLEGAL; \ |
955 | 6e64da3c | Guan Xuetao | break; \
|
956 | 6e64da3c | Guan Xuetao | } \ |
957 | 6e64da3c | Guan Xuetao | } while (0) |
958 | 6e64da3c | Guan Xuetao | |
959 | 6e64da3c | Guan Xuetao | #define UCF64_OP2(name) do { \ |
960 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FMT) { \
|
961 | 6e64da3c | Guan Xuetao | case 0 /* s */: \ |
962 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F0s, cpu_env, \ |
963 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_N)); \ |
964 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i32(cpu_F1s, cpu_env, \ |
965 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_M)); \ |
966 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_##name##s(cpu_F0s, \ |
967 | 6e64da3c | Guan Xuetao | cpu_F0s, cpu_F1s, cpu_env); \ |
968 | 6e64da3c | Guan Xuetao | tcg_gen_st_i32(cpu_F0s, cpu_env, \ |
969 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_D)); \ |
970 | 6e64da3c | Guan Xuetao | break; \
|
971 | 6e64da3c | Guan Xuetao | case 1 /* d */: \ |
972 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F0d, cpu_env, \ |
973 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_N)); \ |
974 | 6e64da3c | Guan Xuetao | tcg_gen_ld_i64(cpu_F1d, cpu_env, \ |
975 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_M)); \ |
976 | 6e64da3c | Guan Xuetao | gen_helper_ucf64_##name##d(cpu_F0d, \ |
977 | 6e64da3c | Guan Xuetao | cpu_F0d, cpu_F1d, cpu_env); \ |
978 | 6e64da3c | Guan Xuetao | tcg_gen_st_i64(cpu_F0d, cpu_env, \ |
979 | 6e64da3c | Guan Xuetao | ucf64_reg_offset(UCOP_REG_D)); \ |
980 | 6e64da3c | Guan Xuetao | break; \
|
981 | 6e64da3c | Guan Xuetao | case 2 /* w */: \ |
982 | 6e64da3c | Guan Xuetao | ILLEGAL; \ |
983 | 6e64da3c | Guan Xuetao | break; \
|
984 | 6e64da3c | Guan Xuetao | } \ |
985 | 6e64da3c | Guan Xuetao | } while (0) |
986 | 6e64da3c | Guan Xuetao | |
987 | 6e64da3c | Guan Xuetao | /* UniCore-F64 data processing */
|
988 | 6e64da3c | Guan Xuetao | static void do_ucf64_datap(CPUState *env, DisasContext *s, uint32_t insn) |
989 | 6e64da3c | Guan Xuetao | { |
990 | 6e64da3c | Guan Xuetao | if (UCOP_UCF64_FMT == 3) { |
991 | 6e64da3c | Guan Xuetao | ILLEGAL; |
992 | 6e64da3c | Guan Xuetao | } |
993 | 6e64da3c | Guan Xuetao | switch (UCOP_UCF64_FUNC) {
|
994 | 6e64da3c | Guan Xuetao | case 0: /* add */ |
995 | 6e64da3c | Guan Xuetao | UCF64_OP2(add); |
996 | 6e64da3c | Guan Xuetao | break;
|
997 | 6e64da3c | Guan Xuetao | case 1: /* sub */ |
998 | 6e64da3c | Guan Xuetao | UCF64_OP2(sub); |
999 | 6e64da3c | Guan Xuetao | break;
|
1000 | 6e64da3c | Guan Xuetao | case 2: /* mul */ |
1001 | 6e64da3c | Guan Xuetao | UCF64_OP2(mul); |
1002 | 6e64da3c | Guan Xuetao | break;
|
1003 | 6e64da3c | Guan Xuetao | case 4: /* div */ |
1004 | 6e64da3c | Guan Xuetao | UCF64_OP2(div); |
1005 | 6e64da3c | Guan Xuetao | break;
|
1006 | 6e64da3c | Guan Xuetao | case 5: /* abs */ |
1007 | 6e64da3c | Guan Xuetao | UCF64_OP1(abs); |
1008 | 6e64da3c | Guan Xuetao | break;
|
1009 | 6e64da3c | Guan Xuetao | case 6: /* mov */ |
1010 | 6e64da3c | Guan Xuetao | UCF64_OP1(mov); |
1011 | 6e64da3c | Guan Xuetao | break;
|
1012 | 6e64da3c | Guan Xuetao | case 7: /* neg */ |
1013 | 6e64da3c | Guan Xuetao | UCF64_OP1(neg); |
1014 | 6e64da3c | Guan Xuetao | break;
|
1015 | 6e64da3c | Guan Xuetao | default:
|
1016 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1017 | 6e64da3c | Guan Xuetao | } |
1018 | 6e64da3c | Guan Xuetao | } |
1019 | 6e64da3c | Guan Xuetao | |
1020 | 6e64da3c | Guan Xuetao | /* Disassemble an F64 instruction */
|
1021 | 6e64da3c | Guan Xuetao | static void disas_ucf64_insn(CPUState *env, DisasContext *s, uint32_t insn) |
1022 | 6e64da3c | Guan Xuetao | { |
1023 | 6e64da3c | Guan Xuetao | if (!UCOP_SET(29)) { |
1024 | 6e64da3c | Guan Xuetao | if (UCOP_SET(26)) { |
1025 | 6e64da3c | Guan Xuetao | do_ucf64_ldst_m(env, s, insn); |
1026 | 6e64da3c | Guan Xuetao | } else {
|
1027 | 6e64da3c | Guan Xuetao | do_ucf64_ldst_i(env, s, insn); |
1028 | 6e64da3c | Guan Xuetao | } |
1029 | 6e64da3c | Guan Xuetao | } else {
|
1030 | 6e64da3c | Guan Xuetao | if (UCOP_SET(5)) { |
1031 | 6e64da3c | Guan Xuetao | switch ((insn >> 26) & 0x3) { |
1032 | 6e64da3c | Guan Xuetao | case 0: |
1033 | 6e64da3c | Guan Xuetao | do_ucf64_datap(env, s, insn); |
1034 | 6e64da3c | Guan Xuetao | break;
|
1035 | 6e64da3c | Guan Xuetao | case 1: |
1036 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1037 | 6e64da3c | Guan Xuetao | break;
|
1038 | 6e64da3c | Guan Xuetao | case 2: |
1039 | 6e64da3c | Guan Xuetao | do_ucf64_fcvt(env, s, insn); |
1040 | 6e64da3c | Guan Xuetao | break;
|
1041 | 6e64da3c | Guan Xuetao | case 3: |
1042 | 6e64da3c | Guan Xuetao | do_ucf64_fcmp(env, s, insn); |
1043 | 6e64da3c | Guan Xuetao | break;
|
1044 | 6e64da3c | Guan Xuetao | } |
1045 | 6e64da3c | Guan Xuetao | } else {
|
1046 | 6e64da3c | Guan Xuetao | do_ucf64_trans(env, s, insn); |
1047 | 6e64da3c | Guan Xuetao | } |
1048 | 6e64da3c | Guan Xuetao | } |
1049 | 6e64da3c | Guan Xuetao | } |
1050 | 6e64da3c | Guan Xuetao | |
1051 | 6e64da3c | Guan Xuetao | static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) |
1052 | 6e64da3c | Guan Xuetao | { |
1053 | 6e64da3c | Guan Xuetao | TranslationBlock *tb; |
1054 | 6e64da3c | Guan Xuetao | |
1055 | 6e64da3c | Guan Xuetao | tb = s->tb; |
1056 | 6e64da3c | Guan Xuetao | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
|
1057 | 6e64da3c | Guan Xuetao | tcg_gen_goto_tb(n); |
1058 | 6e64da3c | Guan Xuetao | gen_set_pc_im(dest); |
1059 | 3feaca9e | Stefan Weil | tcg_gen_exit_tb((tcg_target_long)tb + n); |
1060 | 6e64da3c | Guan Xuetao | } else {
|
1061 | 6e64da3c | Guan Xuetao | gen_set_pc_im(dest); |
1062 | 6e64da3c | Guan Xuetao | tcg_gen_exit_tb(0);
|
1063 | 6e64da3c | Guan Xuetao | } |
1064 | 6e64da3c | Guan Xuetao | } |
1065 | 6e64da3c | Guan Xuetao | |
1066 | 6e64da3c | Guan Xuetao | static inline void gen_jmp(DisasContext *s, uint32_t dest) |
1067 | 6e64da3c | Guan Xuetao | { |
1068 | 6e64da3c | Guan Xuetao | if (unlikely(s->singlestep_enabled)) {
|
1069 | 6e64da3c | Guan Xuetao | /* An indirect jump so that we still trigger the debug exception. */
|
1070 | 6e64da3c | Guan Xuetao | gen_bx_im(s, dest); |
1071 | 6e64da3c | Guan Xuetao | } else {
|
1072 | 6e64da3c | Guan Xuetao | gen_goto_tb(s, 0, dest);
|
1073 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_TB_JUMP; |
1074 | 6e64da3c | Guan Xuetao | } |
1075 | 6e64da3c | Guan Xuetao | } |
1076 | 6e64da3c | Guan Xuetao | |
1077 | 6e64da3c | Guan Xuetao | static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y) |
1078 | 6e64da3c | Guan Xuetao | { |
1079 | 6e64da3c | Guan Xuetao | if (x) {
|
1080 | 6e64da3c | Guan Xuetao | tcg_gen_sari_i32(t0, t0, 16);
|
1081 | 6e64da3c | Guan Xuetao | } else {
|
1082 | 6e64da3c | Guan Xuetao | gen_sxth(t0); |
1083 | 6e64da3c | Guan Xuetao | } |
1084 | 6e64da3c | Guan Xuetao | if (y) {
|
1085 | 6e64da3c | Guan Xuetao | tcg_gen_sari_i32(t1, t1, 16);
|
1086 | 6e64da3c | Guan Xuetao | } else {
|
1087 | 6e64da3c | Guan Xuetao | gen_sxth(t1); |
1088 | 6e64da3c | Guan Xuetao | } |
1089 | 6e64da3c | Guan Xuetao | tcg_gen_mul_i32(t0, t0, t1); |
1090 | 6e64da3c | Guan Xuetao | } |
1091 | 6e64da3c | Guan Xuetao | |
1092 | 6e64da3c | Guan Xuetao | /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
|
1093 | 6e64da3c | Guan Xuetao | static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0) |
1094 | 6e64da3c | Guan Xuetao | { |
1095 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1096 | 6e64da3c | Guan Xuetao | if (bsr) {
|
1097 | 6e64da3c | Guan Xuetao | /* ??? This is also undefined in system mode. */
|
1098 | 6e64da3c | Guan Xuetao | if (IS_USER(s)) {
|
1099 | 6e64da3c | Guan Xuetao | return 1; |
1100 | 6e64da3c | Guan Xuetao | } |
1101 | 6e64da3c | Guan Xuetao | |
1102 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(bsr); |
1103 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(tmp, tmp, ~mask); |
1104 | 6e64da3c | Guan Xuetao | tcg_gen_andi_i32(t0, t0, mask); |
1105 | 6e64da3c | Guan Xuetao | tcg_gen_or_i32(tmp, tmp, t0); |
1106 | 6e64da3c | Guan Xuetao | store_cpu_field(tmp, bsr); |
1107 | 6e64da3c | Guan Xuetao | } else {
|
1108 | 6e64da3c | Guan Xuetao | gen_set_asr(t0, mask); |
1109 | 6e64da3c | Guan Xuetao | } |
1110 | 6e64da3c | Guan Xuetao | dead_tmp(t0); |
1111 | 6e64da3c | Guan Xuetao | gen_lookup_tb(s); |
1112 | 6e64da3c | Guan Xuetao | return 0; |
1113 | 6e64da3c | Guan Xuetao | } |
1114 | 6e64da3c | Guan Xuetao | |
1115 | 6e64da3c | Guan Xuetao | /* Generate an old-style exception return. Marks pc as dead. */
|
1116 | 6e64da3c | Guan Xuetao | static void gen_exception_return(DisasContext *s, TCGv pc) |
1117 | 6e64da3c | Guan Xuetao | { |
1118 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1119 | 6e64da3c | Guan Xuetao | store_reg(s, 31, pc);
|
1120 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(bsr); |
1121 | 6e64da3c | Guan Xuetao | gen_set_asr(tmp, 0xffffffff);
|
1122 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1123 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_UPDATE; |
1124 | 6e64da3c | Guan Xuetao | } |
1125 | 6e64da3c | Guan Xuetao | |
1126 | 6e64da3c | Guan Xuetao | static void disas_coproc_insn(CPUState *env, DisasContext *s, uint32_t insn) |
1127 | 6e64da3c | Guan Xuetao | { |
1128 | 6e64da3c | Guan Xuetao | switch (UCOP_CPNUM) {
|
1129 | 6e64da3c | Guan Xuetao | case 2: |
1130 | 6e64da3c | Guan Xuetao | disas_ucf64_insn(env, s, insn); |
1131 | 6e64da3c | Guan Xuetao | break;
|
1132 | 6e64da3c | Guan Xuetao | default:
|
1133 | 6e64da3c | Guan Xuetao | /* Unknown coprocessor. */
|
1134 | 6e64da3c | Guan Xuetao | cpu_abort(env, "Unknown coprocessor!");
|
1135 | 6e64da3c | Guan Xuetao | } |
1136 | 6e64da3c | Guan Xuetao | } |
1137 | 6e64da3c | Guan Xuetao | |
1138 | 6e64da3c | Guan Xuetao | |
1139 | 6e64da3c | Guan Xuetao | /* Store a 64-bit value to a register pair. Clobbers val. */
|
1140 | 6e64da3c | Guan Xuetao | static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) |
1141 | 6e64da3c | Guan Xuetao | { |
1142 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1143 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1144 | 6e64da3c | Guan Xuetao | tcg_gen_trunc_i64_i32(tmp, val); |
1145 | 6e64da3c | Guan Xuetao | store_reg(s, rlow, tmp); |
1146 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1147 | 6e64da3c | Guan Xuetao | tcg_gen_shri_i64(val, val, 32);
|
1148 | 6e64da3c | Guan Xuetao | tcg_gen_trunc_i64_i32(tmp, val); |
1149 | 6e64da3c | Guan Xuetao | store_reg(s, rhigh, tmp); |
1150 | 6e64da3c | Guan Xuetao | } |
1151 | 6e64da3c | Guan Xuetao | |
1152 | 6e64da3c | Guan Xuetao | /* load and add a 64-bit value from a register pair. */
|
1153 | 6e64da3c | Guan Xuetao | static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) |
1154 | 6e64da3c | Guan Xuetao | { |
1155 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp; |
1156 | 6e64da3c | Guan Xuetao | TCGv tmpl; |
1157 | 6e64da3c | Guan Xuetao | TCGv tmph; |
1158 | 6e64da3c | Guan Xuetao | |
1159 | 6e64da3c | Guan Xuetao | /* Load 64-bit value rd:rn. */
|
1160 | 6e64da3c | Guan Xuetao | tmpl = load_reg(s, rlow); |
1161 | 6e64da3c | Guan Xuetao | tmph = load_reg(s, rhigh); |
1162 | 6e64da3c | Guan Xuetao | tmp = tcg_temp_new_i64(); |
1163 | 6e64da3c | Guan Xuetao | tcg_gen_concat_i32_i64(tmp, tmpl, tmph); |
1164 | 6e64da3c | Guan Xuetao | dead_tmp(tmpl); |
1165 | 6e64da3c | Guan Xuetao | dead_tmp(tmph); |
1166 | 6e64da3c | Guan Xuetao | tcg_gen_add_i64(val, val, tmp); |
1167 | 6e64da3c | Guan Xuetao | tcg_temp_free_i64(tmp); |
1168 | 6e64da3c | Guan Xuetao | } |
1169 | 6e64da3c | Guan Xuetao | |
1170 | 6e64da3c | Guan Xuetao | /* data processing instructions */
|
1171 | 6e64da3c | Guan Xuetao | static void do_datap(CPUState *env, DisasContext *s, uint32_t insn) |
1172 | 6e64da3c | Guan Xuetao | { |
1173 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1174 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
1175 | 6e64da3c | Guan Xuetao | int logic_cc;
|
1176 | 6e64da3c | Guan Xuetao | |
1177 | 6e64da3c | Guan Xuetao | if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) { |
1178 | 6e64da3c | Guan Xuetao | if (UCOP_SET(23)) { /* CMOV instructions */ |
1179 | 6e64da3c | Guan Xuetao | if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) { |
1180 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1181 | 6e64da3c | Guan Xuetao | } |
1182 | 6e64da3c | Guan Xuetao | /* if not always execute, we generate a conditional jump to
|
1183 | 6e64da3c | Guan Xuetao | next instruction */
|
1184 | 6e64da3c | Guan Xuetao | s->condlabel = gen_new_label(); |
1185 | 6e64da3c | Guan Xuetao | gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel);
|
1186 | 6e64da3c | Guan Xuetao | s->condjmp = 1;
|
1187 | 6e64da3c | Guan Xuetao | } |
1188 | 6e64da3c | Guan Xuetao | } |
1189 | 6e64da3c | Guan Xuetao | |
1190 | 6e64da3c | Guan Xuetao | logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24);
|
1191 | 6e64da3c | Guan Xuetao | |
1192 | 6e64da3c | Guan Xuetao | if (UCOP_SET(29)) { |
1193 | 6e64da3c | Guan Xuetao | unsigned int val; |
1194 | 6e64da3c | Guan Xuetao | /* immediate operand */
|
1195 | 6e64da3c | Guan Xuetao | val = UCOP_IMM_9; |
1196 | 6e64da3c | Guan Xuetao | if (UCOP_SH_IM) {
|
1197 | 6e64da3c | Guan Xuetao | val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
|
1198 | 6e64da3c | Guan Xuetao | } |
1199 | 6e64da3c | Guan Xuetao | tmp2 = new_tmp(); |
1200 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp2, val); |
1201 | 6e64da3c | Guan Xuetao | if (logic_cc && UCOP_SH_IM) {
|
1202 | 6e64da3c | Guan Xuetao | gen_set_CF_bit31(tmp2); |
1203 | 6e64da3c | Guan Xuetao | } |
1204 | 6e64da3c | Guan Xuetao | } else {
|
1205 | 6e64da3c | Guan Xuetao | /* register */
|
1206 | 6e64da3c | Guan Xuetao | tmp2 = load_reg(s, UCOP_REG_M); |
1207 | 6e64da3c | Guan Xuetao | if (UCOP_SET(5)) { |
1208 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_S); |
1209 | 6e64da3c | Guan Xuetao | gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc); |
1210 | 6e64da3c | Guan Xuetao | } else {
|
1211 | 6e64da3c | Guan Xuetao | gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc); |
1212 | 6e64da3c | Guan Xuetao | } |
1213 | 6e64da3c | Guan Xuetao | } |
1214 | 6e64da3c | Guan Xuetao | |
1215 | 6e64da3c | Guan Xuetao | if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) { |
1216 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_N); |
1217 | 6e64da3c | Guan Xuetao | } else {
|
1218 | 6e64da3c | Guan Xuetao | TCGV_UNUSED(tmp); |
1219 | 6e64da3c | Guan Xuetao | } |
1220 | 6e64da3c | Guan Xuetao | |
1221 | 6e64da3c | Guan Xuetao | switch (UCOP_OPCODES) {
|
1222 | 6e64da3c | Guan Xuetao | case 0x00: |
1223 | 6e64da3c | Guan Xuetao | tcg_gen_and_i32(tmp, tmp, tmp2); |
1224 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1225 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1226 | 6e64da3c | Guan Xuetao | } |
1227 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1228 | 6e64da3c | Guan Xuetao | break;
|
1229 | 6e64da3c | Guan Xuetao | case 0x01: |
1230 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
1231 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1232 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1233 | 6e64da3c | Guan Xuetao | } |
1234 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1235 | 6e64da3c | Guan Xuetao | break;
|
1236 | 6e64da3c | Guan Xuetao | case 0x02: |
1237 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S && UCOP_REG_D == 31) { |
1238 | 6e64da3c | Guan Xuetao | /* SUBS r31, ... is used for exception return. */
|
1239 | 6e64da3c | Guan Xuetao | if (IS_USER(s)) {
|
1240 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1241 | 6e64da3c | Guan Xuetao | } |
1242 | 6e64da3c | Guan Xuetao | gen_helper_sub_cc(tmp, tmp, tmp2); |
1243 | 6e64da3c | Guan Xuetao | gen_exception_return(s, tmp); |
1244 | 6e64da3c | Guan Xuetao | } else {
|
1245 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1246 | 6e64da3c | Guan Xuetao | gen_helper_sub_cc(tmp, tmp, tmp2); |
1247 | 6e64da3c | Guan Xuetao | } else {
|
1248 | 6e64da3c | Guan Xuetao | tcg_gen_sub_i32(tmp, tmp, tmp2); |
1249 | 6e64da3c | Guan Xuetao | } |
1250 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1251 | 6e64da3c | Guan Xuetao | } |
1252 | 6e64da3c | Guan Xuetao | break;
|
1253 | 6e64da3c | Guan Xuetao | case 0x03: |
1254 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1255 | 6e64da3c | Guan Xuetao | gen_helper_sub_cc(tmp, tmp2, tmp); |
1256 | 6e64da3c | Guan Xuetao | } else {
|
1257 | 6e64da3c | Guan Xuetao | tcg_gen_sub_i32(tmp, tmp2, tmp); |
1258 | 6e64da3c | Guan Xuetao | } |
1259 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1260 | 6e64da3c | Guan Xuetao | break;
|
1261 | 6e64da3c | Guan Xuetao | case 0x04: |
1262 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1263 | 6e64da3c | Guan Xuetao | gen_helper_add_cc(tmp, tmp, tmp2); |
1264 | 6e64da3c | Guan Xuetao | } else {
|
1265 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(tmp, tmp, tmp2); |
1266 | 6e64da3c | Guan Xuetao | } |
1267 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1268 | 6e64da3c | Guan Xuetao | break;
|
1269 | 6e64da3c | Guan Xuetao | case 0x05: |
1270 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1271 | 6e64da3c | Guan Xuetao | gen_helper_adc_cc(tmp, tmp, tmp2); |
1272 | 6e64da3c | Guan Xuetao | } else {
|
1273 | 6e64da3c | Guan Xuetao | gen_add_carry(tmp, tmp, tmp2); |
1274 | 6e64da3c | Guan Xuetao | } |
1275 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1276 | 6e64da3c | Guan Xuetao | break;
|
1277 | 6e64da3c | Guan Xuetao | case 0x06: |
1278 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1279 | 6e64da3c | Guan Xuetao | gen_helper_sbc_cc(tmp, tmp, tmp2); |
1280 | 6e64da3c | Guan Xuetao | } else {
|
1281 | 6e64da3c | Guan Xuetao | gen_sub_carry(tmp, tmp, tmp2); |
1282 | 6e64da3c | Guan Xuetao | } |
1283 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1284 | 6e64da3c | Guan Xuetao | break;
|
1285 | 6e64da3c | Guan Xuetao | case 0x07: |
1286 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1287 | 6e64da3c | Guan Xuetao | gen_helper_sbc_cc(tmp, tmp2, tmp); |
1288 | 6e64da3c | Guan Xuetao | } else {
|
1289 | 6e64da3c | Guan Xuetao | gen_sub_carry(tmp, tmp2, tmp); |
1290 | 6e64da3c | Guan Xuetao | } |
1291 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1292 | 6e64da3c | Guan Xuetao | break;
|
1293 | 6e64da3c | Guan Xuetao | case 0x08: |
1294 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1295 | 6e64da3c | Guan Xuetao | tcg_gen_and_i32(tmp, tmp, tmp2); |
1296 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1297 | 6e64da3c | Guan Xuetao | } |
1298 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1299 | 6e64da3c | Guan Xuetao | break;
|
1300 | 6e64da3c | Guan Xuetao | case 0x09: |
1301 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1302 | 6e64da3c | Guan Xuetao | tcg_gen_xor_i32(tmp, tmp, tmp2); |
1303 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1304 | 6e64da3c | Guan Xuetao | } |
1305 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1306 | 6e64da3c | Guan Xuetao | break;
|
1307 | 6e64da3c | Guan Xuetao | case 0x0a: |
1308 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1309 | 6e64da3c | Guan Xuetao | gen_helper_sub_cc(tmp, tmp, tmp2); |
1310 | 6e64da3c | Guan Xuetao | } |
1311 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1312 | 6e64da3c | Guan Xuetao | break;
|
1313 | 6e64da3c | Guan Xuetao | case 0x0b: |
1314 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1315 | 6e64da3c | Guan Xuetao | gen_helper_add_cc(tmp, tmp, tmp2); |
1316 | 6e64da3c | Guan Xuetao | } |
1317 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1318 | 6e64da3c | Guan Xuetao | break;
|
1319 | 6e64da3c | Guan Xuetao | case 0x0c: |
1320 | 6e64da3c | Guan Xuetao | tcg_gen_or_i32(tmp, tmp, tmp2); |
1321 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1322 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1323 | 6e64da3c | Guan Xuetao | } |
1324 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1325 | 6e64da3c | Guan Xuetao | break;
|
1326 | 6e64da3c | Guan Xuetao | case 0x0d: |
1327 | 6e64da3c | Guan Xuetao | if (logic_cc && UCOP_REG_D == 31) { |
1328 | 6e64da3c | Guan Xuetao | /* MOVS r31, ... is used for exception return. */
|
1329 | 6e64da3c | Guan Xuetao | if (IS_USER(s)) {
|
1330 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1331 | 6e64da3c | Guan Xuetao | } |
1332 | 6e64da3c | Guan Xuetao | gen_exception_return(s, tmp2); |
1333 | 6e64da3c | Guan Xuetao | } else {
|
1334 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1335 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp2); |
1336 | 6e64da3c | Guan Xuetao | } |
1337 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp2); |
1338 | 6e64da3c | Guan Xuetao | } |
1339 | 6e64da3c | Guan Xuetao | break;
|
1340 | 6e64da3c | Guan Xuetao | case 0x0e: |
1341 | 6e64da3c | Guan Xuetao | tcg_gen_andc_i32(tmp, tmp, tmp2); |
1342 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1343 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1344 | 6e64da3c | Guan Xuetao | } |
1345 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp); |
1346 | 6e64da3c | Guan Xuetao | break;
|
1347 | 6e64da3c | Guan Xuetao | default:
|
1348 | 6e64da3c | Guan Xuetao | case 0x0f: |
1349 | 6e64da3c | Guan Xuetao | tcg_gen_not_i32(tmp2, tmp2); |
1350 | 6e64da3c | Guan Xuetao | if (logic_cc) {
|
1351 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp2); |
1352 | 6e64da3c | Guan Xuetao | } |
1353 | 6e64da3c | Guan Xuetao | store_reg_bx(s, UCOP_REG_D, tmp2); |
1354 | 6e64da3c | Guan Xuetao | break;
|
1355 | 6e64da3c | Guan Xuetao | } |
1356 | 6e64da3c | Guan Xuetao | if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) { |
1357 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
1358 | 6e64da3c | Guan Xuetao | } |
1359 | 6e64da3c | Guan Xuetao | } |
1360 | 6e64da3c | Guan Xuetao | |
1361 | 6e64da3c | Guan Xuetao | /* multiply */
|
1362 | 6e64da3c | Guan Xuetao | static void do_mult(CPUState *env, DisasContext *s, uint32_t insn) |
1363 | 6e64da3c | Guan Xuetao | { |
1364 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1365 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
1366 | 6e64da3c | Guan Xuetao | TCGv_i64 tmp64; |
1367 | 6e64da3c | Guan Xuetao | |
1368 | 6e64da3c | Guan Xuetao | if (UCOP_SET(27)) { |
1369 | 6e64da3c | Guan Xuetao | /* 64 bit mul */
|
1370 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1371 | 6e64da3c | Guan Xuetao | tmp2 = load_reg(s, UCOP_REG_N); |
1372 | 6e64da3c | Guan Xuetao | if (UCOP_SET(26)) { |
1373 | 6e64da3c | Guan Xuetao | tmp64 = gen_muls_i64_i32(tmp, tmp2); |
1374 | 6e64da3c | Guan Xuetao | } else {
|
1375 | 6e64da3c | Guan Xuetao | tmp64 = gen_mulu_i64_i32(tmp, tmp2); |
1376 | 6e64da3c | Guan Xuetao | } |
1377 | 6e64da3c | Guan Xuetao | if (UCOP_SET(25)) { /* mult accumulate */ |
1378 | 6e64da3c | Guan Xuetao | gen_addq(s, tmp64, UCOP_REG_LO, UCOP_REG_HI); |
1379 | 6e64da3c | Guan Xuetao | } |
1380 | 6e64da3c | Guan Xuetao | gen_storeq_reg(s, UCOP_REG_LO, UCOP_REG_HI, tmp64); |
1381 | 6e64da3c | Guan Xuetao | tcg_temp_free_i64(tmp64); |
1382 | 6e64da3c | Guan Xuetao | } else {
|
1383 | 6e64da3c | Guan Xuetao | /* 32 bit mul */
|
1384 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1385 | 6e64da3c | Guan Xuetao | tmp2 = load_reg(s, UCOP_REG_N); |
1386 | 6e64da3c | Guan Xuetao | tcg_gen_mul_i32(tmp, tmp, tmp2); |
1387 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
1388 | 6e64da3c | Guan Xuetao | if (UCOP_SET(25)) { |
1389 | 6e64da3c | Guan Xuetao | /* Add */
|
1390 | 6e64da3c | Guan Xuetao | tmp2 = load_reg(s, UCOP_REG_S); |
1391 | 6e64da3c | Guan Xuetao | tcg_gen_add_i32(tmp, tmp, tmp2); |
1392 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
1393 | 6e64da3c | Guan Xuetao | } |
1394 | 6e64da3c | Guan Xuetao | if (UCOP_SET_S) {
|
1395 | 6e64da3c | Guan Xuetao | gen_logic_CC(tmp); |
1396 | 6e64da3c | Guan Xuetao | } |
1397 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
1398 | 6e64da3c | Guan Xuetao | } |
1399 | 6e64da3c | Guan Xuetao | } |
1400 | 6e64da3c | Guan Xuetao | |
1401 | 6e64da3c | Guan Xuetao | /* miscellaneous instructions */
|
1402 | 6e64da3c | Guan Xuetao | static void do_misc(CPUState *env, DisasContext *s, uint32_t insn) |
1403 | 6e64da3c | Guan Xuetao | { |
1404 | 6e64da3c | Guan Xuetao | unsigned int val; |
1405 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1406 | 6e64da3c | Guan Xuetao | |
1407 | 6e64da3c | Guan Xuetao | if ((insn & 0xffffffe0) == 0x10ffc120) { |
1408 | 6e64da3c | Guan Xuetao | /* Trivial implementation equivalent to bx. */
|
1409 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1410 | 6e64da3c | Guan Xuetao | gen_bx(s, tmp); |
1411 | 6e64da3c | Guan Xuetao | return;
|
1412 | 6e64da3c | Guan Xuetao | } |
1413 | 6e64da3c | Guan Xuetao | |
1414 | 6e64da3c | Guan Xuetao | if ((insn & 0xfbffc000) == 0x30ffc000) { |
1415 | 6e64da3c | Guan Xuetao | /* PSR = immediate */
|
1416 | 6e64da3c | Guan Xuetao | val = UCOP_IMM_9; |
1417 | 6e64da3c | Guan Xuetao | if (UCOP_SH_IM) {
|
1418 | 6e64da3c | Guan Xuetao | val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
|
1419 | 6e64da3c | Guan Xuetao | } |
1420 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1421 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp, val); |
1422 | 6e64da3c | Guan Xuetao | if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
|
1423 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1424 | 6e64da3c | Guan Xuetao | } |
1425 | 6e64da3c | Guan Xuetao | return;
|
1426 | 6e64da3c | Guan Xuetao | } |
1427 | 6e64da3c | Guan Xuetao | |
1428 | 6e64da3c | Guan Xuetao | if ((insn & 0xfbffffe0) == 0x12ffc020) { |
1429 | 6e64da3c | Guan Xuetao | /* PSR.flag = reg */
|
1430 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1431 | 6e64da3c | Guan Xuetao | if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) {
|
1432 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1433 | 6e64da3c | Guan Xuetao | } |
1434 | 6e64da3c | Guan Xuetao | return;
|
1435 | 6e64da3c | Guan Xuetao | } |
1436 | 6e64da3c | Guan Xuetao | |
1437 | 6e64da3c | Guan Xuetao | if ((insn & 0xfbffffe0) == 0x10ffc020) { |
1438 | 6e64da3c | Guan Xuetao | /* PSR = reg */
|
1439 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1440 | 6e64da3c | Guan Xuetao | if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
|
1441 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1442 | 6e64da3c | Guan Xuetao | } |
1443 | 6e64da3c | Guan Xuetao | return;
|
1444 | 6e64da3c | Guan Xuetao | } |
1445 | 6e64da3c | Guan Xuetao | |
1446 | 6e64da3c | Guan Xuetao | if ((insn & 0xfbf83fff) == 0x10f80000) { |
1447 | 6e64da3c | Guan Xuetao | /* reg = PSR */
|
1448 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B) {
|
1449 | 6e64da3c | Guan Xuetao | if (IS_USER(s)) {
|
1450 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1451 | 6e64da3c | Guan Xuetao | } |
1452 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(bsr); |
1453 | 6e64da3c | Guan Xuetao | } else {
|
1454 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1455 | 6e64da3c | Guan Xuetao | gen_helper_asr_read(tmp); |
1456 | 6e64da3c | Guan Xuetao | } |
1457 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
1458 | 6e64da3c | Guan Xuetao | return;
|
1459 | 6e64da3c | Guan Xuetao | } |
1460 | 6e64da3c | Guan Xuetao | |
1461 | 6e64da3c | Guan Xuetao | if ((insn & 0xfbf83fe0) == 0x12f80120) { |
1462 | 6e64da3c | Guan Xuetao | /* clz */
|
1463 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1464 | 6e64da3c | Guan Xuetao | if (UCOP_SET(26)) { |
1465 | 6e64da3c | Guan Xuetao | gen_helper_clo(tmp, tmp); |
1466 | 6e64da3c | Guan Xuetao | } else {
|
1467 | 6e64da3c | Guan Xuetao | gen_helper_clz(tmp, tmp); |
1468 | 6e64da3c | Guan Xuetao | } |
1469 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
1470 | 6e64da3c | Guan Xuetao | return;
|
1471 | 6e64da3c | Guan Xuetao | } |
1472 | 6e64da3c | Guan Xuetao | |
1473 | 6e64da3c | Guan Xuetao | /* otherwise */
|
1474 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1475 | 6e64da3c | Guan Xuetao | } |
1476 | 6e64da3c | Guan Xuetao | |
1477 | 6e64da3c | Guan Xuetao | /* load/store I_offset and R_offset */
|
1478 | 6e64da3c | Guan Xuetao | static void do_ldst_ir(CPUState *env, DisasContext *s, uint32_t insn) |
1479 | 6e64da3c | Guan Xuetao | { |
1480 | 6e64da3c | Guan Xuetao | unsigned int i; |
1481 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1482 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
1483 | 6e64da3c | Guan Xuetao | |
1484 | 6e64da3c | Guan Xuetao | tmp2 = load_reg(s, UCOP_REG_N); |
1485 | 6e64da3c | Guan Xuetao | i = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); |
1486 | 6e64da3c | Guan Xuetao | |
1487 | 6e64da3c | Guan Xuetao | /* immediate */
|
1488 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1489 | 6e64da3c | Guan Xuetao | gen_add_data_offset(s, insn, tmp2); |
1490 | 6e64da3c | Guan Xuetao | } |
1491 | 6e64da3c | Guan Xuetao | |
1492 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) {
|
1493 | 6e64da3c | Guan Xuetao | /* load */
|
1494 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B) {
|
1495 | 6e64da3c | Guan Xuetao | tmp = gen_ld8u(tmp2, i); |
1496 | 6e64da3c | Guan Xuetao | } else {
|
1497 | 6e64da3c | Guan Xuetao | tmp = gen_ld32(tmp2, i); |
1498 | 6e64da3c | Guan Xuetao | } |
1499 | 6e64da3c | Guan Xuetao | } else {
|
1500 | 6e64da3c | Guan Xuetao | /* store */
|
1501 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_D); |
1502 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B) {
|
1503 | 6e64da3c | Guan Xuetao | gen_st8(tmp, tmp2, i); |
1504 | 6e64da3c | Guan Xuetao | } else {
|
1505 | 6e64da3c | Guan Xuetao | gen_st32(tmp, tmp2, i); |
1506 | 6e64da3c | Guan Xuetao | } |
1507 | 6e64da3c | Guan Xuetao | } |
1508 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_P) {
|
1509 | 6e64da3c | Guan Xuetao | gen_add_data_offset(s, insn, tmp2); |
1510 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, tmp2); |
1511 | 6e64da3c | Guan Xuetao | } else if (UCOP_SET_W) { |
1512 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, tmp2); |
1513 | 6e64da3c | Guan Xuetao | } else {
|
1514 | 6e64da3c | Guan Xuetao | dead_tmp(tmp2); |
1515 | 6e64da3c | Guan Xuetao | } |
1516 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) {
|
1517 | 6e64da3c | Guan Xuetao | /* Complete the load. */
|
1518 | 6e64da3c | Guan Xuetao | if (UCOP_REG_D == 31) { |
1519 | 6e64da3c | Guan Xuetao | gen_bx(s, tmp); |
1520 | 6e64da3c | Guan Xuetao | } else {
|
1521 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
1522 | 6e64da3c | Guan Xuetao | } |
1523 | 6e64da3c | Guan Xuetao | } |
1524 | 6e64da3c | Guan Xuetao | } |
1525 | 6e64da3c | Guan Xuetao | |
1526 | 6e64da3c | Guan Xuetao | /* SWP instruction */
|
1527 | 6e64da3c | Guan Xuetao | static void do_swap(CPUState *env, DisasContext *s, uint32_t insn) |
1528 | 6e64da3c | Guan Xuetao | { |
1529 | 6e64da3c | Guan Xuetao | TCGv addr; |
1530 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1531 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
1532 | 6e64da3c | Guan Xuetao | |
1533 | 6e64da3c | Guan Xuetao | if ((insn & 0xff003fe0) != 0x40000120) { |
1534 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1535 | 6e64da3c | Guan Xuetao | } |
1536 | 6e64da3c | Guan Xuetao | |
1537 | 6e64da3c | Guan Xuetao | /* ??? This is not really atomic. However we know
|
1538 | 6e64da3c | Guan Xuetao | we never have multiple CPUs running in parallel,
|
1539 | 6e64da3c | Guan Xuetao | so it is good enough. */
|
1540 | 6e64da3c | Guan Xuetao | addr = load_reg(s, UCOP_REG_N); |
1541 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_M); |
1542 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B) {
|
1543 | 6e64da3c | Guan Xuetao | tmp2 = gen_ld8u(addr, IS_USER(s)); |
1544 | 6e64da3c | Guan Xuetao | gen_st8(tmp, addr, IS_USER(s)); |
1545 | 6e64da3c | Guan Xuetao | } else {
|
1546 | 6e64da3c | Guan Xuetao | tmp2 = gen_ld32(addr, IS_USER(s)); |
1547 | 6e64da3c | Guan Xuetao | gen_st32(tmp, addr, IS_USER(s)); |
1548 | 6e64da3c | Guan Xuetao | } |
1549 | 6e64da3c | Guan Xuetao | dead_tmp(addr); |
1550 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp2); |
1551 | 6e64da3c | Guan Xuetao | } |
1552 | 6e64da3c | Guan Xuetao | |
1553 | 6e64da3c | Guan Xuetao | /* load/store hw/sb */
|
1554 | 6e64da3c | Guan Xuetao | static void do_ldst_hwsb(CPUState *env, DisasContext *s, uint32_t insn) |
1555 | 6e64da3c | Guan Xuetao | { |
1556 | 6e64da3c | Guan Xuetao | TCGv addr; |
1557 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1558 | 6e64da3c | Guan Xuetao | |
1559 | 6e64da3c | Guan Xuetao | if (UCOP_SH_OP == 0) { |
1560 | 6e64da3c | Guan Xuetao | do_swap(env, s, insn); |
1561 | 6e64da3c | Guan Xuetao | return;
|
1562 | 6e64da3c | Guan Xuetao | } |
1563 | 6e64da3c | Guan Xuetao | |
1564 | 6e64da3c | Guan Xuetao | addr = load_reg(s, UCOP_REG_N); |
1565 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1566 | 6e64da3c | Guan Xuetao | gen_add_datah_offset(s, insn, addr); |
1567 | 6e64da3c | Guan Xuetao | } |
1568 | 6e64da3c | Guan Xuetao | |
1569 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) { /* load */ |
1570 | 6e64da3c | Guan Xuetao | switch (UCOP_SH_OP) {
|
1571 | 6e64da3c | Guan Xuetao | case 1: |
1572 | 6e64da3c | Guan Xuetao | tmp = gen_ld16u(addr, IS_USER(s)); |
1573 | 6e64da3c | Guan Xuetao | break;
|
1574 | 6e64da3c | Guan Xuetao | case 2: |
1575 | 6e64da3c | Guan Xuetao | tmp = gen_ld8s(addr, IS_USER(s)); |
1576 | 6e64da3c | Guan Xuetao | break;
|
1577 | 6e64da3c | Guan Xuetao | default: /* see do_swap */ |
1578 | 6e64da3c | Guan Xuetao | case 3: |
1579 | 6e64da3c | Guan Xuetao | tmp = gen_ld16s(addr, IS_USER(s)); |
1580 | 6e64da3c | Guan Xuetao | break;
|
1581 | 6e64da3c | Guan Xuetao | } |
1582 | 6e64da3c | Guan Xuetao | } else { /* store */ |
1583 | 6e64da3c | Guan Xuetao | if (UCOP_SH_OP != 1) { |
1584 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1585 | 6e64da3c | Guan Xuetao | } |
1586 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, UCOP_REG_D); |
1587 | 6e64da3c | Guan Xuetao | gen_st16(tmp, addr, IS_USER(s)); |
1588 | 6e64da3c | Guan Xuetao | } |
1589 | 6e64da3c | Guan Xuetao | /* Perform base writeback before the loaded value to
|
1590 | 6e64da3c | Guan Xuetao | ensure correct behavior with overlapping index registers. */
|
1591 | 6e64da3c | Guan Xuetao | if (!UCOP_SET_P) {
|
1592 | 6e64da3c | Guan Xuetao | gen_add_datah_offset(s, insn, addr); |
1593 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, addr); |
1594 | 6e64da3c | Guan Xuetao | } else if (UCOP_SET_W) { |
1595 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, addr); |
1596 | 6e64da3c | Guan Xuetao | } else {
|
1597 | 6e64da3c | Guan Xuetao | dead_tmp(addr); |
1598 | 6e64da3c | Guan Xuetao | } |
1599 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) {
|
1600 | 6e64da3c | Guan Xuetao | /* Complete the load. */
|
1601 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_D, tmp); |
1602 | 6e64da3c | Guan Xuetao | } |
1603 | 6e64da3c | Guan Xuetao | } |
1604 | 6e64da3c | Guan Xuetao | |
1605 | 6e64da3c | Guan Xuetao | /* load/store multiple words */
|
1606 | 6e64da3c | Guan Xuetao | static void do_ldst_m(CPUState *env, DisasContext *s, uint32_t insn) |
1607 | 6e64da3c | Guan Xuetao | { |
1608 | 6e64da3c | Guan Xuetao | unsigned int val, i; |
1609 | 6e64da3c | Guan Xuetao | int j, n, reg, user, loaded_base;
|
1610 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1611 | 6e64da3c | Guan Xuetao | TCGv tmp2; |
1612 | 6e64da3c | Guan Xuetao | TCGv addr; |
1613 | 6e64da3c | Guan Xuetao | TCGv loaded_var; |
1614 | 6e64da3c | Guan Xuetao | |
1615 | 6e64da3c | Guan Xuetao | if (UCOP_SET(7)) { |
1616 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1617 | 6e64da3c | Guan Xuetao | } |
1618 | 6e64da3c | Guan Xuetao | /* XXX: store correct base if write back */
|
1619 | 6e64da3c | Guan Xuetao | user = 0;
|
1620 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B) { /* S bit in instruction table */ |
1621 | 6e64da3c | Guan Xuetao | if (IS_USER(s)) {
|
1622 | 6e64da3c | Guan Xuetao | ILLEGAL; /* only usable in supervisor mode */
|
1623 | 6e64da3c | Guan Xuetao | } |
1624 | 6e64da3c | Guan Xuetao | if (UCOP_SET(18) == 0) { /* pc reg */ |
1625 | 6e64da3c | Guan Xuetao | user = 1;
|
1626 | 6e64da3c | Guan Xuetao | } |
1627 | 6e64da3c | Guan Xuetao | } |
1628 | 6e64da3c | Guan Xuetao | |
1629 | 6e64da3c | Guan Xuetao | addr = load_reg(s, UCOP_REG_N); |
1630 | 6e64da3c | Guan Xuetao | |
1631 | 6e64da3c | Guan Xuetao | /* compute total size */
|
1632 | 6e64da3c | Guan Xuetao | loaded_base = 0;
|
1633 | 6e64da3c | Guan Xuetao | TCGV_UNUSED(loaded_var); |
1634 | 6e64da3c | Guan Xuetao | n = 0;
|
1635 | 6e64da3c | Guan Xuetao | for (i = 0; i < 6; i++) { |
1636 | 6e64da3c | Guan Xuetao | if (UCOP_SET(i)) {
|
1637 | 6e64da3c | Guan Xuetao | n++; |
1638 | 6e64da3c | Guan Xuetao | } |
1639 | 6e64da3c | Guan Xuetao | } |
1640 | 6e64da3c | Guan Xuetao | for (i = 9; i < 19; i++) { |
1641 | 6e64da3c | Guan Xuetao | if (UCOP_SET(i)) {
|
1642 | 6e64da3c | Guan Xuetao | n++; |
1643 | 6e64da3c | Guan Xuetao | } |
1644 | 6e64da3c | Guan Xuetao | } |
1645 | 6e64da3c | Guan Xuetao | /* XXX: test invalid n == 0 case ? */
|
1646 | 6e64da3c | Guan Xuetao | if (UCOP_SET_U) {
|
1647 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1648 | 6e64da3c | Guan Xuetao | /* pre increment */
|
1649 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
1650 | 6e64da3c | Guan Xuetao | } else {
|
1651 | 6e64da3c | Guan Xuetao | /* post increment */
|
1652 | 6e64da3c | Guan Xuetao | } |
1653 | 6e64da3c | Guan Xuetao | } else {
|
1654 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1655 | 6e64da3c | Guan Xuetao | /* pre decrement */
|
1656 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -(n * 4));
|
1657 | 6e64da3c | Guan Xuetao | } else {
|
1658 | 6e64da3c | Guan Xuetao | /* post decrement */
|
1659 | 6e64da3c | Guan Xuetao | if (n != 1) { |
1660 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); |
1661 | 6e64da3c | Guan Xuetao | } |
1662 | 6e64da3c | Guan Xuetao | } |
1663 | 6e64da3c | Guan Xuetao | } |
1664 | 6e64da3c | Guan Xuetao | |
1665 | 6e64da3c | Guan Xuetao | j = 0;
|
1666 | 6e64da3c | Guan Xuetao | reg = UCOP_SET(6) ? 16 : 0; |
1667 | 6e64da3c | Guan Xuetao | for (i = 0; i < 19; i++, reg++) { |
1668 | 6e64da3c | Guan Xuetao | if (i == 6) { |
1669 | 6e64da3c | Guan Xuetao | i = i + 3;
|
1670 | 6e64da3c | Guan Xuetao | } |
1671 | 6e64da3c | Guan Xuetao | if (UCOP_SET(i)) {
|
1672 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) { /* load */ |
1673 | 6e64da3c | Guan Xuetao | tmp = gen_ld32(addr, IS_USER(s)); |
1674 | 6e64da3c | Guan Xuetao | if (reg == 31) { |
1675 | 6e64da3c | Guan Xuetao | gen_bx(s, tmp); |
1676 | 6e64da3c | Guan Xuetao | } else if (user) { |
1677 | 6e64da3c | Guan Xuetao | tmp2 = tcg_const_i32(reg); |
1678 | 6e64da3c | Guan Xuetao | gen_helper_set_user_reg(tmp2, tmp); |
1679 | 6e64da3c | Guan Xuetao | tcg_temp_free_i32(tmp2); |
1680 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1681 | 6e64da3c | Guan Xuetao | } else if (reg == UCOP_REG_N) { |
1682 | 6e64da3c | Guan Xuetao | loaded_var = tmp; |
1683 | 6e64da3c | Guan Xuetao | loaded_base = 1;
|
1684 | 6e64da3c | Guan Xuetao | } else {
|
1685 | 6e64da3c | Guan Xuetao | store_reg(s, reg, tmp); |
1686 | 6e64da3c | Guan Xuetao | } |
1687 | 6e64da3c | Guan Xuetao | } else { /* store */ |
1688 | 6e64da3c | Guan Xuetao | if (reg == 31) { |
1689 | 6e64da3c | Guan Xuetao | /* special case: r31 = PC + 4 */
|
1690 | 6e64da3c | Guan Xuetao | val = (long)s->pc;
|
1691 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1692 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp, val); |
1693 | 6e64da3c | Guan Xuetao | } else if (user) { |
1694 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1695 | 6e64da3c | Guan Xuetao | tmp2 = tcg_const_i32(reg); |
1696 | 6e64da3c | Guan Xuetao | gen_helper_get_user_reg(tmp, tmp2); |
1697 | 6e64da3c | Guan Xuetao | tcg_temp_free_i32(tmp2); |
1698 | 6e64da3c | Guan Xuetao | } else {
|
1699 | 6e64da3c | Guan Xuetao | tmp = load_reg(s, reg); |
1700 | 6e64da3c | Guan Xuetao | } |
1701 | 6e64da3c | Guan Xuetao | gen_st32(tmp, addr, IS_USER(s)); |
1702 | 6e64da3c | Guan Xuetao | } |
1703 | 6e64da3c | Guan Xuetao | j++; |
1704 | 6e64da3c | Guan Xuetao | /* no need to add after the last transfer */
|
1705 | 6e64da3c | Guan Xuetao | if (j != n) {
|
1706 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
1707 | 6e64da3c | Guan Xuetao | } |
1708 | 6e64da3c | Guan Xuetao | } |
1709 | 6e64da3c | Guan Xuetao | } |
1710 | 6e64da3c | Guan Xuetao | if (UCOP_SET_W) { /* write back */ |
1711 | 6e64da3c | Guan Xuetao | if (UCOP_SET_U) {
|
1712 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1713 | 6e64da3c | Guan Xuetao | /* pre increment */
|
1714 | 6e64da3c | Guan Xuetao | } else {
|
1715 | 6e64da3c | Guan Xuetao | /* post increment */
|
1716 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, 4);
|
1717 | 6e64da3c | Guan Xuetao | } |
1718 | 6e64da3c | Guan Xuetao | } else {
|
1719 | 6e64da3c | Guan Xuetao | if (UCOP_SET_P) {
|
1720 | 6e64da3c | Guan Xuetao | /* pre decrement */
|
1721 | 6e64da3c | Guan Xuetao | if (n != 1) { |
1722 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); |
1723 | 6e64da3c | Guan Xuetao | } |
1724 | 6e64da3c | Guan Xuetao | } else {
|
1725 | 6e64da3c | Guan Xuetao | /* post decrement */
|
1726 | 6e64da3c | Guan Xuetao | tcg_gen_addi_i32(addr, addr, -(n * 4));
|
1727 | 6e64da3c | Guan Xuetao | } |
1728 | 6e64da3c | Guan Xuetao | } |
1729 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, addr); |
1730 | 6e64da3c | Guan Xuetao | } else {
|
1731 | 6e64da3c | Guan Xuetao | dead_tmp(addr); |
1732 | 6e64da3c | Guan Xuetao | } |
1733 | 6e64da3c | Guan Xuetao | if (loaded_base) {
|
1734 | 6e64da3c | Guan Xuetao | store_reg(s, UCOP_REG_N, loaded_var); |
1735 | 6e64da3c | Guan Xuetao | } |
1736 | 6e64da3c | Guan Xuetao | if (UCOP_SET_B && !user) {
|
1737 | 6e64da3c | Guan Xuetao | /* Restore ASR from BSR. */
|
1738 | 6e64da3c | Guan Xuetao | tmp = load_cpu_field(bsr); |
1739 | 6e64da3c | Guan Xuetao | gen_set_asr(tmp, 0xffffffff);
|
1740 | 6e64da3c | Guan Xuetao | dead_tmp(tmp); |
1741 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_UPDATE; |
1742 | 6e64da3c | Guan Xuetao | } |
1743 | 6e64da3c | Guan Xuetao | } |
1744 | 6e64da3c | Guan Xuetao | |
1745 | 6e64da3c | Guan Xuetao | /* branch (and link) */
|
1746 | 6e64da3c | Guan Xuetao | static void do_branch(CPUState *env, DisasContext *s, uint32_t insn) |
1747 | 6e64da3c | Guan Xuetao | { |
1748 | 6e64da3c | Guan Xuetao | unsigned int val; |
1749 | 6e64da3c | Guan Xuetao | int32_t offset; |
1750 | 6e64da3c | Guan Xuetao | TCGv tmp; |
1751 | 6e64da3c | Guan Xuetao | |
1752 | 6e64da3c | Guan Xuetao | if (UCOP_COND == 0xf) { |
1753 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1754 | 6e64da3c | Guan Xuetao | } |
1755 | 6e64da3c | Guan Xuetao | |
1756 | 6e64da3c | Guan Xuetao | if (UCOP_COND != 0xe) { |
1757 | 6e64da3c | Guan Xuetao | /* if not always execute, we generate a conditional jump to
|
1758 | 6e64da3c | Guan Xuetao | next instruction */
|
1759 | 6e64da3c | Guan Xuetao | s->condlabel = gen_new_label(); |
1760 | 6e64da3c | Guan Xuetao | gen_test_cc(UCOP_COND ^ 1, s->condlabel);
|
1761 | 6e64da3c | Guan Xuetao | s->condjmp = 1;
|
1762 | 6e64da3c | Guan Xuetao | } |
1763 | 6e64da3c | Guan Xuetao | |
1764 | 6e64da3c | Guan Xuetao | val = (int32_t)s->pc; |
1765 | 6e64da3c | Guan Xuetao | if (UCOP_SET_L) {
|
1766 | 6e64da3c | Guan Xuetao | tmp = new_tmp(); |
1767 | 6e64da3c | Guan Xuetao | tcg_gen_movi_i32(tmp, val); |
1768 | 6e64da3c | Guan Xuetao | store_reg(s, 30, tmp);
|
1769 | 6e64da3c | Guan Xuetao | } |
1770 | 6e64da3c | Guan Xuetao | offset = (((int32_t)insn << 8) >> 8); |
1771 | 6e64da3c | Guan Xuetao | val += (offset << 2); /* unicore is pc+4 */ |
1772 | 6e64da3c | Guan Xuetao | gen_jmp(s, val); |
1773 | 6e64da3c | Guan Xuetao | } |
1774 | 6e64da3c | Guan Xuetao | |
1775 | 6e64da3c | Guan Xuetao | static void disas_uc32_insn(CPUState *env, DisasContext *s) |
1776 | 6e64da3c | Guan Xuetao | { |
1777 | 6e64da3c | Guan Xuetao | unsigned int insn; |
1778 | 6e64da3c | Guan Xuetao | |
1779 | 6e64da3c | Guan Xuetao | insn = ldl_code(s->pc); |
1780 | 6e64da3c | Guan Xuetao | s->pc += 4;
|
1781 | 6e64da3c | Guan Xuetao | |
1782 | 6e64da3c | Guan Xuetao | /* UniCore instructions class:
|
1783 | 6e64da3c | Guan Xuetao | * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx
|
1784 | 6e64da3c | Guan Xuetao | * AAA : see switch case
|
1785 | 6e64da3c | Guan Xuetao | * BBBB : opcodes or cond or PUBW
|
1786 | 6e64da3c | Guan Xuetao | * C : S OR L
|
1787 | 6e64da3c | Guan Xuetao | * D : 8
|
1788 | 6e64da3c | Guan Xuetao | * E : 5
|
1789 | 6e64da3c | Guan Xuetao | */
|
1790 | 6e64da3c | Guan Xuetao | switch (insn >> 29) { |
1791 | fa4e49c0 | Gerd Hoffmann | case 0x0: |
1792 | 6e64da3c | Guan Xuetao | if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) { |
1793 | 6e64da3c | Guan Xuetao | do_mult(env, s, insn); |
1794 | 6e64da3c | Guan Xuetao | break;
|
1795 | 6e64da3c | Guan Xuetao | } |
1796 | 6e64da3c | Guan Xuetao | |
1797 | 6e64da3c | Guan Xuetao | if (UCOP_SET(8)) { |
1798 | 6e64da3c | Guan Xuetao | do_misc(env, s, insn); |
1799 | 6e64da3c | Guan Xuetao | break;
|
1800 | 6e64da3c | Guan Xuetao | } |
1801 | fa4e49c0 | Gerd Hoffmann | case 0x1: |
1802 | 6e64da3c | Guan Xuetao | if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) { |
1803 | 6e64da3c | Guan Xuetao | do_misc(env, s, insn); |
1804 | 6e64da3c | Guan Xuetao | break;
|
1805 | 6e64da3c | Guan Xuetao | } |
1806 | 6e64da3c | Guan Xuetao | do_datap(env, s, insn); |
1807 | 6e64da3c | Guan Xuetao | break;
|
1808 | 6e64da3c | Guan Xuetao | |
1809 | fa4e49c0 | Gerd Hoffmann | case 0x2: |
1810 | 6e64da3c | Guan Xuetao | if (UCOP_SET(8) && UCOP_SET(5)) { |
1811 | 6e64da3c | Guan Xuetao | do_ldst_hwsb(env, s, insn); |
1812 | 6e64da3c | Guan Xuetao | break;
|
1813 | 6e64da3c | Guan Xuetao | } |
1814 | 6e64da3c | Guan Xuetao | if (UCOP_SET(8) || UCOP_SET(5)) { |
1815 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1816 | 6e64da3c | Guan Xuetao | } |
1817 | fa4e49c0 | Gerd Hoffmann | case 0x3: |
1818 | 6e64da3c | Guan Xuetao | do_ldst_ir(env, s, insn); |
1819 | 6e64da3c | Guan Xuetao | break;
|
1820 | 6e64da3c | Guan Xuetao | |
1821 | fa4e49c0 | Gerd Hoffmann | case 0x4: |
1822 | 6e64da3c | Guan Xuetao | if (UCOP_SET(8)) { |
1823 | 6e64da3c | Guan Xuetao | ILLEGAL; /* extended instructions */
|
1824 | 6e64da3c | Guan Xuetao | } |
1825 | 6e64da3c | Guan Xuetao | do_ldst_m(env, s, insn); |
1826 | 6e64da3c | Guan Xuetao | break;
|
1827 | fa4e49c0 | Gerd Hoffmann | case 0x5: |
1828 | 6e64da3c | Guan Xuetao | do_branch(env, s, insn); |
1829 | 6e64da3c | Guan Xuetao | break;
|
1830 | fa4e49c0 | Gerd Hoffmann | case 0x6: |
1831 | 6e64da3c | Guan Xuetao | /* Coprocessor. */
|
1832 | 6e64da3c | Guan Xuetao | disas_coproc_insn(env, s, insn); |
1833 | 6e64da3c | Guan Xuetao | break;
|
1834 | fa4e49c0 | Gerd Hoffmann | case 0x7: |
1835 | 6e64da3c | Guan Xuetao | if (!UCOP_SET(28)) { |
1836 | 6e64da3c | Guan Xuetao | disas_coproc_insn(env, s, insn); |
1837 | 6e64da3c | Guan Xuetao | break;
|
1838 | 6e64da3c | Guan Xuetao | } |
1839 | 6e64da3c | Guan Xuetao | if ((insn & 0xff000000) == 0xff000000) { /* syscall */ |
1840 | 6e64da3c | Guan Xuetao | gen_set_pc_im(s->pc); |
1841 | 6e64da3c | Guan Xuetao | s->is_jmp = DISAS_SYSCALL; |
1842 | 6e64da3c | Guan Xuetao | break;
|
1843 | 6e64da3c | Guan Xuetao | } |
1844 | 6e64da3c | Guan Xuetao | ILLEGAL; |
1845 | 6e64da3c | Guan Xuetao | } |
1846 | 6e64da3c | Guan Xuetao | |
1847 | 6e64da3c | Guan Xuetao | return;
|
1848 | 6e64da3c | Guan Xuetao | } |
1849 | 6e64da3c | Guan Xuetao | |
1850 | 6e64da3c | Guan Xuetao | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
|
1851 | 6e64da3c | Guan Xuetao | basic block 'tb'. If search_pc is TRUE, also generate PC
|
1852 | 6e64da3c | Guan Xuetao | information for each intermediate instruction. */
|
1853 | 6e64da3c | Guan Xuetao | static inline void gen_intermediate_code_internal(CPUState *env, |
1854 | 6e64da3c | Guan Xuetao | TranslationBlock *tb, int search_pc)
|
1855 | 6e64da3c | Guan Xuetao | { |
1856 | 6e64da3c | Guan Xuetao | DisasContext dc1, *dc = &dc1; |
1857 | 6e64da3c | Guan Xuetao | CPUBreakpoint *bp; |
1858 | 6e64da3c | Guan Xuetao | uint16_t *gen_opc_end; |
1859 | 6e64da3c | Guan Xuetao | int j, lj;
|
1860 | 6e64da3c | Guan Xuetao | target_ulong pc_start; |
1861 | 6e64da3c | Guan Xuetao | uint32_t next_page_start; |
1862 | 6e64da3c | Guan Xuetao | int num_insns;
|
1863 | 6e64da3c | Guan Xuetao | int max_insns;
|
1864 | 6e64da3c | Guan Xuetao | |
1865 | 6e64da3c | Guan Xuetao | /* generate intermediate code */
|
1866 | 6e64da3c | Guan Xuetao | num_temps = 0;
|
1867 | 6e64da3c | Guan Xuetao | |
1868 | 6e64da3c | Guan Xuetao | pc_start = tb->pc; |
1869 | 6e64da3c | Guan Xuetao | |
1870 | 6e64da3c | Guan Xuetao | dc->tb = tb; |
1871 | 6e64da3c | Guan Xuetao | |
1872 | 6e64da3c | Guan Xuetao | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
1873 | 6e64da3c | Guan Xuetao | |
1874 | 6e64da3c | Guan Xuetao | dc->is_jmp = DISAS_NEXT; |
1875 | 6e64da3c | Guan Xuetao | dc->pc = pc_start; |
1876 | 6e64da3c | Guan Xuetao | dc->singlestep_enabled = env->singlestep_enabled; |
1877 | 6e64da3c | Guan Xuetao | dc->condjmp = 0;
|
1878 | 6e64da3c | Guan Xuetao | cpu_F0s = tcg_temp_new_i32(); |
1879 | 6e64da3c | Guan Xuetao | cpu_F1s = tcg_temp_new_i32(); |
1880 | 6e64da3c | Guan Xuetao | cpu_F0d = tcg_temp_new_i64(); |
1881 | 6e64da3c | Guan Xuetao | cpu_F1d = tcg_temp_new_i64(); |
1882 | 6e64da3c | Guan Xuetao | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
1883 | 6e64da3c | Guan Xuetao | lj = -1;
|
1884 | 6e64da3c | Guan Xuetao | num_insns = 0;
|
1885 | 6e64da3c | Guan Xuetao | max_insns = tb->cflags & CF_COUNT_MASK; |
1886 | 6e64da3c | Guan Xuetao | if (max_insns == 0) { |
1887 | 6e64da3c | Guan Xuetao | max_insns = CF_COUNT_MASK; |
1888 | 6e64da3c | Guan Xuetao | } |
1889 | 6e64da3c | Guan Xuetao | |
1890 | 6e64da3c | Guan Xuetao | gen_icount_start(); |
1891 | 6e64da3c | Guan Xuetao | do {
|
1892 | 6e64da3c | Guan Xuetao | if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
|
1893 | 6e64da3c | Guan Xuetao | QTAILQ_FOREACH(bp, &env->breakpoints, entry) { |
1894 | 6e64da3c | Guan Xuetao | if (bp->pc == dc->pc) {
|
1895 | 6e64da3c | Guan Xuetao | gen_set_pc_im(dc->pc); |
1896 | 6e64da3c | Guan Xuetao | gen_exception(EXCP_DEBUG); |
1897 | 6e64da3c | Guan Xuetao | dc->is_jmp = DISAS_JUMP; |
1898 | 6e64da3c | Guan Xuetao | /* Advance PC so that clearing the breakpoint will
|
1899 | 6e64da3c | Guan Xuetao | invalidate this TB. */
|
1900 | 6e64da3c | Guan Xuetao | dc->pc += 2; /* FIXME */ |
1901 | 6e64da3c | Guan Xuetao | goto done_generating;
|
1902 | 6e64da3c | Guan Xuetao | break;
|
1903 | 6e64da3c | Guan Xuetao | } |
1904 | 6e64da3c | Guan Xuetao | } |
1905 | 6e64da3c | Guan Xuetao | } |
1906 | 6e64da3c | Guan Xuetao | if (search_pc) {
|
1907 | 6e64da3c | Guan Xuetao | j = gen_opc_ptr - gen_opc_buf; |
1908 | 6e64da3c | Guan Xuetao | if (lj < j) {
|
1909 | 6e64da3c | Guan Xuetao | lj++; |
1910 | 6e64da3c | Guan Xuetao | while (lj < j) {
|
1911 | 6e64da3c | Guan Xuetao | gen_opc_instr_start[lj++] = 0;
|
1912 | 6e64da3c | Guan Xuetao | } |
1913 | 6e64da3c | Guan Xuetao | } |
1914 | 6e64da3c | Guan Xuetao | gen_opc_pc[lj] = dc->pc; |
1915 | 6e64da3c | Guan Xuetao | gen_opc_instr_start[lj] = 1;
|
1916 | 6e64da3c | Guan Xuetao | gen_opc_icount[lj] = num_insns; |
1917 | 6e64da3c | Guan Xuetao | } |
1918 | 6e64da3c | Guan Xuetao | |
1919 | 6e64da3c | Guan Xuetao | if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { |
1920 | 6e64da3c | Guan Xuetao | gen_io_start(); |
1921 | 6e64da3c | Guan Xuetao | } |
1922 | 6e64da3c | Guan Xuetao | |
1923 | 6e64da3c | Guan Xuetao | disas_uc32_insn(env, dc); |
1924 | 6e64da3c | Guan Xuetao | |
1925 | 6e64da3c | Guan Xuetao | if (num_temps) {
|
1926 | 6e64da3c | Guan Xuetao | fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
|
1927 | 6e64da3c | Guan Xuetao | num_temps = 0;
|
1928 | 6e64da3c | Guan Xuetao | } |
1929 | 6e64da3c | Guan Xuetao | |
1930 | 6e64da3c | Guan Xuetao | if (dc->condjmp && !dc->is_jmp) {
|
1931 | 6e64da3c | Guan Xuetao | gen_set_label(dc->condlabel); |
1932 | 6e64da3c | Guan Xuetao | dc->condjmp = 0;
|
1933 | 6e64da3c | Guan Xuetao | } |
1934 | 6e64da3c | Guan Xuetao | /* Translation stops when a conditional branch is encountered.
|
1935 | 6e64da3c | Guan Xuetao | * Otherwise the subsequent code could get translated several times.
|
1936 | 6e64da3c | Guan Xuetao | * Also stop translation when a page boundary is reached. This
|
1937 | 6e64da3c | Guan Xuetao | * ensures prefetch aborts occur at the right place. */
|
1938 | 6e64da3c | Guan Xuetao | num_insns++; |
1939 | 6e64da3c | Guan Xuetao | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
|
1940 | 6e64da3c | Guan Xuetao | !env->singlestep_enabled && |
1941 | 6e64da3c | Guan Xuetao | !singlestep && |
1942 | 6e64da3c | Guan Xuetao | dc->pc < next_page_start && |
1943 | 6e64da3c | Guan Xuetao | num_insns < max_insns); |
1944 | 6e64da3c | Guan Xuetao | |
1945 | 6e64da3c | Guan Xuetao | if (tb->cflags & CF_LAST_IO) {
|
1946 | 6e64da3c | Guan Xuetao | if (dc->condjmp) {
|
1947 | 6e64da3c | Guan Xuetao | /* FIXME: This can theoretically happen with self-modifying
|
1948 | 6e64da3c | Guan Xuetao | code. */
|
1949 | 6e64da3c | Guan Xuetao | cpu_abort(env, "IO on conditional branch instruction");
|
1950 | 6e64da3c | Guan Xuetao | } |
1951 | 6e64da3c | Guan Xuetao | gen_io_end(); |
1952 | 6e64da3c | Guan Xuetao | } |
1953 | 6e64da3c | Guan Xuetao | |
1954 | 6e64da3c | Guan Xuetao | /* At this stage dc->condjmp will only be set when the skipped
|
1955 | 6e64da3c | Guan Xuetao | instruction was a conditional branch or trap, and the PC has
|
1956 | 6e64da3c | Guan Xuetao | already been written. */
|
1957 | 6e64da3c | Guan Xuetao | if (unlikely(env->singlestep_enabled)) {
|
1958 | 6e64da3c | Guan Xuetao | /* Make sure the pc is updated, and raise a debug exception. */
|
1959 | 6e64da3c | Guan Xuetao | if (dc->condjmp) {
|
1960 | 6e64da3c | Guan Xuetao | if (dc->is_jmp == DISAS_SYSCALL) {
|
1961 | 6e64da3c | Guan Xuetao | gen_exception(UC32_EXCP_PRIV); |
1962 | 6e64da3c | Guan Xuetao | } else {
|
1963 | 6e64da3c | Guan Xuetao | gen_exception(EXCP_DEBUG); |
1964 | 6e64da3c | Guan Xuetao | } |
1965 | 6e64da3c | Guan Xuetao | gen_set_label(dc->condlabel); |
1966 | 6e64da3c | Guan Xuetao | } |
1967 | 6e64da3c | Guan Xuetao | if (dc->condjmp || !dc->is_jmp) {
|
1968 | 6e64da3c | Guan Xuetao | gen_set_pc_im(dc->pc); |
1969 | 6e64da3c | Guan Xuetao | dc->condjmp = 0;
|
1970 | 6e64da3c | Guan Xuetao | } |
1971 | 6e64da3c | Guan Xuetao | if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) {
|
1972 | 6e64da3c | Guan Xuetao | gen_exception(UC32_EXCP_PRIV); |
1973 | 6e64da3c | Guan Xuetao | } else {
|
1974 | 6e64da3c | Guan Xuetao | gen_exception(EXCP_DEBUG); |
1975 | 6e64da3c | Guan Xuetao | } |
1976 | 6e64da3c | Guan Xuetao | } else {
|
1977 | 6e64da3c | Guan Xuetao | /* While branches must always occur at the end of an IT block,
|
1978 | 6e64da3c | Guan Xuetao | there are a few other things that can cause us to terminate
|
1979 | 6e64da3c | Guan Xuetao | the TB in the middel of an IT block:
|
1980 | 6e64da3c | Guan Xuetao | - Exception generating instructions (bkpt, swi, undefined).
|
1981 | 6e64da3c | Guan Xuetao | - Page boundaries.
|
1982 | 6e64da3c | Guan Xuetao | - Hardware watchpoints.
|
1983 | 6e64da3c | Guan Xuetao | Hardware breakpoints have already been handled and skip this code.
|
1984 | 6e64da3c | Guan Xuetao | */
|
1985 | 6e64da3c | Guan Xuetao | switch (dc->is_jmp) {
|
1986 | 6e64da3c | Guan Xuetao | case DISAS_NEXT:
|
1987 | 6e64da3c | Guan Xuetao | gen_goto_tb(dc, 1, dc->pc);
|
1988 | 6e64da3c | Guan Xuetao | break;
|
1989 | 6e64da3c | Guan Xuetao | default:
|
1990 | 6e64da3c | Guan Xuetao | case DISAS_JUMP:
|
1991 | 6e64da3c | Guan Xuetao | case DISAS_UPDATE:
|
1992 | 6e64da3c | Guan Xuetao | /* indicate that the hash table must be used to find the next TB */
|
1993 | 6e64da3c | Guan Xuetao | tcg_gen_exit_tb(0);
|
1994 | 6e64da3c | Guan Xuetao | break;
|
1995 | 6e64da3c | Guan Xuetao | case DISAS_TB_JUMP:
|
1996 | 6e64da3c | Guan Xuetao | /* nothing more to generate */
|
1997 | 6e64da3c | Guan Xuetao | break;
|
1998 | 6e64da3c | Guan Xuetao | case DISAS_SYSCALL:
|
1999 | 6e64da3c | Guan Xuetao | gen_exception(UC32_EXCP_PRIV); |
2000 | 6e64da3c | Guan Xuetao | break;
|
2001 | 6e64da3c | Guan Xuetao | } |
2002 | 6e64da3c | Guan Xuetao | if (dc->condjmp) {
|
2003 | 6e64da3c | Guan Xuetao | gen_set_label(dc->condlabel); |
2004 | 6e64da3c | Guan Xuetao | gen_goto_tb(dc, 1, dc->pc);
|
2005 | 6e64da3c | Guan Xuetao | dc->condjmp = 0;
|
2006 | 6e64da3c | Guan Xuetao | } |
2007 | 6e64da3c | Guan Xuetao | } |
2008 | 6e64da3c | Guan Xuetao | |
2009 | 6e64da3c | Guan Xuetao | done_generating:
|
2010 | 6e64da3c | Guan Xuetao | gen_icount_end(tb, num_insns); |
2011 | 6e64da3c | Guan Xuetao | *gen_opc_ptr = INDEX_op_end; |
2012 | 6e64da3c | Guan Xuetao | |
2013 | 6e64da3c | Guan Xuetao | #ifdef DEBUG_DISAS
|
2014 | 6e64da3c | Guan Xuetao | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
2015 | 6e64da3c | Guan Xuetao | qemu_log("----------------\n");
|
2016 | 6e64da3c | Guan Xuetao | qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
2017 | 6e64da3c | Guan Xuetao | log_target_disas(pc_start, dc->pc - pc_start, 0);
|
2018 | 6e64da3c | Guan Xuetao | qemu_log("\n");
|
2019 | 6e64da3c | Guan Xuetao | } |
2020 | 6e64da3c | Guan Xuetao | #endif
|
2021 | 6e64da3c | Guan Xuetao | if (search_pc) {
|
2022 | 6e64da3c | Guan Xuetao | j = gen_opc_ptr - gen_opc_buf; |
2023 | 6e64da3c | Guan Xuetao | lj++; |
2024 | 6e64da3c | Guan Xuetao | while (lj <= j) {
|
2025 | 6e64da3c | Guan Xuetao | gen_opc_instr_start[lj++] = 0;
|
2026 | 6e64da3c | Guan Xuetao | } |
2027 | 6e64da3c | Guan Xuetao | } else {
|
2028 | 6e64da3c | Guan Xuetao | tb->size = dc->pc - pc_start; |
2029 | 6e64da3c | Guan Xuetao | tb->icount = num_insns; |
2030 | 6e64da3c | Guan Xuetao | } |
2031 | 6e64da3c | Guan Xuetao | } |
2032 | 6e64da3c | Guan Xuetao | |
2033 | 6e64da3c | Guan Xuetao | void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
|
2034 | 6e64da3c | Guan Xuetao | { |
2035 | 6e64da3c | Guan Xuetao | gen_intermediate_code_internal(env, tb, 0);
|
2036 | 6e64da3c | Guan Xuetao | } |
2037 | 6e64da3c | Guan Xuetao | |
2038 | 6e64da3c | Guan Xuetao | void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
|
2039 | 6e64da3c | Guan Xuetao | { |
2040 | 6e64da3c | Guan Xuetao | gen_intermediate_code_internal(env, tb, 1);
|
2041 | 6e64da3c | Guan Xuetao | } |
2042 | 6e64da3c | Guan Xuetao | |
2043 | 6e64da3c | Guan Xuetao | static const char *cpu_mode_names[16] = { |
2044 | 6e64da3c | Guan Xuetao | "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP", |
2045 | 6e64da3c | Guan Xuetao | "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR" |
2046 | 6e64da3c | Guan Xuetao | }; |
2047 | 6e64da3c | Guan Xuetao | |
2048 | 6e64da3c | Guan Xuetao | #define UCF64_DUMP_STATE
|
2049 | 6e64da3c | Guan Xuetao | void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
|
2050 | 6e64da3c | Guan Xuetao | int flags)
|
2051 | 6e64da3c | Guan Xuetao | { |
2052 | 6e64da3c | Guan Xuetao | int i;
|
2053 | 6e64da3c | Guan Xuetao | #ifdef UCF64_DUMP_STATE
|
2054 | 6e64da3c | Guan Xuetao | union {
|
2055 | 6e64da3c | Guan Xuetao | uint32_t i; |
2056 | 6e64da3c | Guan Xuetao | float s;
|
2057 | 6e64da3c | Guan Xuetao | } s0, s1; |
2058 | 6e64da3c | Guan Xuetao | CPU_DoubleU d; |
2059 | 6e64da3c | Guan Xuetao | /* ??? This assumes float64 and double have the same layout.
|
2060 | 6e64da3c | Guan Xuetao | Oh well, it's only debug dumps. */
|
2061 | 6e64da3c | Guan Xuetao | union {
|
2062 | 6e64da3c | Guan Xuetao | float64 f64; |
2063 | 6e64da3c | Guan Xuetao | double d;
|
2064 | 6e64da3c | Guan Xuetao | } d0; |
2065 | 6e64da3c | Guan Xuetao | #endif
|
2066 | 6e64da3c | Guan Xuetao | uint32_t psr; |
2067 | 6e64da3c | Guan Xuetao | |
2068 | 6e64da3c | Guan Xuetao | for (i = 0; i < 32; i++) { |
2069 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
|
2070 | 6e64da3c | Guan Xuetao | if ((i % 4) == 3) { |
2071 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, "\n");
|
2072 | 6e64da3c | Guan Xuetao | } else {
|
2073 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, " ");
|
2074 | 6e64da3c | Guan Xuetao | } |
2075 | 6e64da3c | Guan Xuetao | } |
2076 | 6e64da3c | Guan Xuetao | psr = cpu_asr_read(env); |
2077 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, "PSR=%08x %c%c%c%c %s\n",
|
2078 | 6e64da3c | Guan Xuetao | psr, |
2079 | 6e64da3c | Guan Xuetao | psr & (1 << 31) ? 'N' : '-', |
2080 | 6e64da3c | Guan Xuetao | psr & (1 << 30) ? 'Z' : '-', |
2081 | 6e64da3c | Guan Xuetao | psr & (1 << 29) ? 'C' : '-', |
2082 | 6e64da3c | Guan Xuetao | psr & (1 << 28) ? 'V' : '-', |
2083 | 6e64da3c | Guan Xuetao | cpu_mode_names[psr & 0xf]);
|
2084 | 6e64da3c | Guan Xuetao | |
2085 | 6e64da3c | Guan Xuetao | #ifdef UCF64_DUMP_STATE
|
2086 | 6e64da3c | Guan Xuetao | for (i = 0; i < 16; i++) { |
2087 | 6e64da3c | Guan Xuetao | d.d = env->ucf64.regs[i]; |
2088 | 6e64da3c | Guan Xuetao | s0.i = d.l.lower; |
2089 | 6e64da3c | Guan Xuetao | s1.i = d.l.upper; |
2090 | 6e64da3c | Guan Xuetao | d0.f64 = d.d; |
2091 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%" PRIx64 "(%8g)\n", |
2092 | 6e64da3c | Guan Xuetao | i * 2, (int)s0.i, s0.s, |
2093 | 6e64da3c | Guan Xuetao | i * 2 + 1, (int)s1.i, s1.s, |
2094 | 6e64da3c | Guan Xuetao | i, (uint64_t)d0.f64, d0.d); |
2095 | 6e64da3c | Guan Xuetao | } |
2096 | 6e64da3c | Guan Xuetao | cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]); |
2097 | 6e64da3c | Guan Xuetao | #endif
|
2098 | 6e64da3c | Guan Xuetao | } |
2099 | 6e64da3c | Guan Xuetao | |
2100 | e87b7cb0 | Stefan Weil | void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos) |
2101 | 6e64da3c | Guan Xuetao | { |
2102 | 6e64da3c | Guan Xuetao | env->regs[31] = gen_opc_pc[pc_pos];
|
2103 | 6e64da3c | Guan Xuetao | } |