Commit 8984bd2e833ae0824caa3d63176639c70a6fe654
1 parent
5e3f878a
ARM TCG conversion 12/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4149 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
277 additions
and
330 deletions
target-arm/exec.h
... | ... | @@ -61,13 +61,6 @@ static inline int cpu_halted(CPUState *env) { |
61 | 61 | |
62 | 62 | /* In op_helper.c */ |
63 | 63 | |
64 | -void helper_set_cp(CPUState *, uint32_t, uint32_t); | |
65 | -uint32_t helper_get_cp(CPUState *, uint32_t); | |
66 | -void helper_set_cp15(CPUState *, uint32_t, uint32_t); | |
67 | -uint32_t helper_get_cp15(CPUState *, uint32_t); | |
68 | -uint32_t helper_v7m_mrs(CPUState *env, int reg); | |
69 | -void helper_v7m_msr(CPUState *env, int reg, uint32_t val); | |
70 | - | |
71 | 64 | void helper_mark_exclusive(CPUARMState *, uint32_t addr); |
72 | 65 | int helper_test_exclusive(CPUARMState *, uint32_t addr); |
73 | 66 | void helper_clrex(CPUARMState *env); | ... | ... |
target-arm/helper.c
... | ... | @@ -470,38 +470,38 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
470 | 470 | } |
471 | 471 | |
472 | 472 | /* These should probably raise undefined insn exceptions. */ |
473 | -void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val) | |
473 | +void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val) | |
474 | 474 | { |
475 | 475 | int op1 = (insn >> 8) & 0xf; |
476 | 476 | cpu_abort(env, "cp%i insn %08x\n", op1, insn); |
477 | 477 | return; |
478 | 478 | } |
479 | 479 | |
480 | -uint32_t helper_get_cp(CPUState *env, uint32_t insn) | |
480 | +uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn) | |
481 | 481 | { |
482 | 482 | int op1 = (insn >> 8) & 0xf; |
483 | 483 | cpu_abort(env, "cp%i insn %08x\n", op1, insn); |
484 | 484 | return 0; |
485 | 485 | } |
486 | 486 | |
487 | -void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) | |
487 | +void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val) | |
488 | 488 | { |
489 | 489 | cpu_abort(env, "cp15 insn %08x\n", insn); |
490 | 490 | } |
491 | 491 | |
492 | -uint32_t helper_get_cp15(CPUState *env, uint32_t insn) | |
492 | +uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn) | |
493 | 493 | { |
494 | 494 | cpu_abort(env, "cp15 insn %08x\n", insn); |
495 | 495 | return 0; |
496 | 496 | } |
497 | 497 | |
498 | 498 | /* These should probably raise undefined insn exceptions. */ |
499 | -void helper_v7m_msr(CPUState *env, int reg, uint32_t val) | |
499 | +void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val) | |
500 | 500 | { |
501 | 501 | cpu_abort(env, "v7m_mrs %d\n", reg); |
502 | 502 | } |
503 | 503 | |
504 | -uint32_t helper_v7m_mrs(CPUState *env, int reg) | |
504 | +uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg) | |
505 | 505 | { |
506 | 506 | cpu_abort(env, "v7m_mrs %d\n", reg); |
507 | 507 | return 0; |
... | ... | @@ -1191,7 +1191,7 @@ void helper_clrex(CPUState *env) |
1191 | 1191 | env->mmon_addr = -1; |
1192 | 1192 | } |
1193 | 1193 | |
1194 | -void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val) | |
1194 | +void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val) | |
1195 | 1195 | { |
1196 | 1196 | int cp_num = (insn >> 8) & 0xf; |
1197 | 1197 | int cp_info = (insn >> 5) & 7; |
... | ... | @@ -1203,7 +1203,7 @@ void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val) |
1203 | 1203 | cp_info, src, operand, val); |
1204 | 1204 | } |
1205 | 1205 | |
1206 | -uint32_t helper_get_cp(CPUState *env, uint32_t insn) | |
1206 | +uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn) | |
1207 | 1207 | { |
1208 | 1208 | int cp_num = (insn >> 8) & 0xf; |
1209 | 1209 | int cp_info = (insn >> 5) & 7; |
... | ... | @@ -1246,7 +1246,7 @@ static uint32_t extended_mpu_ap_bits(uint32_t val) |
1246 | 1246 | return ret; |
1247 | 1247 | } |
1248 | 1248 | |
1249 | -void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) | |
1249 | +void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val) | |
1250 | 1250 | { |
1251 | 1251 | int op1; |
1252 | 1252 | int op2; |
... | ... | @@ -1530,7 +1530,7 @@ bad_reg: |
1530 | 1530 | (insn >> 16) & 0xf, crm, op1, op2); |
1531 | 1531 | } |
1532 | 1532 | |
1533 | -uint32_t helper_get_cp15(CPUState *env, uint32_t insn) | |
1533 | +uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn) | |
1534 | 1534 | { |
1535 | 1535 | int op1; |
1536 | 1536 | int op2; |
... | ... | @@ -1803,7 +1803,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode) |
1803 | 1803 | return env->banked_r13[bank_number(mode)]; |
1804 | 1804 | } |
1805 | 1805 | |
1806 | -uint32_t helper_v7m_mrs(CPUState *env, int reg) | |
1806 | +uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg) | |
1807 | 1807 | { |
1808 | 1808 | switch (reg) { |
1809 | 1809 | case 0: /* APSR */ |
... | ... | @@ -1840,7 +1840,7 @@ uint32_t helper_v7m_mrs(CPUState *env, int reg) |
1840 | 1840 | } |
1841 | 1841 | } |
1842 | 1842 | |
1843 | -void helper_v7m_msr(CPUState *env, int reg, uint32_t val) | |
1843 | +void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val) | |
1844 | 1844 | { |
1845 | 1845 | switch (reg) { |
1846 | 1846 | case 0: /* APSR */ | ... | ... |
target-arm/helpers.h
... | ... | @@ -118,6 +118,15 @@ DEF_HELPER_0_0(wfi, void, (void)) |
118 | 118 | DEF_HELPER_0_2(cpsr_write, void, (uint32_t, uint32_t)) |
119 | 119 | DEF_HELPER_1_0(cpsr_read, uint32_t, (void)) |
120 | 120 | |
121 | +DEF_HELPER_0_3(v7m_msr, void, (CPUState *, uint32_t, uint32_t)) | |
122 | +DEF_HELPER_1_2(v7m_mrs, uint32_t, (CPUState *, uint32_t)) | |
123 | + | |
124 | +DEF_HELPER_0_3(set_cp15, void, (CPUState *, uint32_t, uint32_t)) | |
125 | +DEF_HELPER_1_2(get_cp15, uint32_t, (CPUState *, uint32_t)) | |
126 | + | |
127 | +DEF_HELPER_0_3(set_cp, void, (CPUState *, uint32_t, uint32_t)) | |
128 | +DEF_HELPER_1_2(get_cp, uint32_t, (CPUState *, uint32_t)) | |
129 | + | |
121 | 130 | DEF_HELPER_1_2(get_r13_banked, uint32_t, (CPUState *, uint32_t)) |
122 | 131 | DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t)) |
123 | 132 | |
... | ... | @@ -187,6 +196,20 @@ DEF_HELPER_1_2(rsqrte_f32, float32, (float32, CPUState *)) |
187 | 196 | DEF_HELPER_1_2(recpe_u32, uint32_t, (uint32_t, CPUState *)) |
188 | 197 | DEF_HELPER_1_2(rsqrte_u32, uint32_t, (uint32_t, CPUState *)) |
189 | 198 | |
199 | +DEF_HELPER_1_2(add_cc, uint32_t, (uint32_t, uint32_t)) | |
200 | +DEF_HELPER_1_2(adc_cc, uint32_t, (uint32_t, uint32_t)) | |
201 | +DEF_HELPER_1_2(sub_cc, uint32_t, (uint32_t, uint32_t)) | |
202 | +DEF_HELPER_1_2(sbc_cc, uint32_t, (uint32_t, uint32_t)) | |
203 | + | |
204 | +DEF_HELPER_1_2(shl, uint32_t, (uint32_t, uint32_t)) | |
205 | +DEF_HELPER_1_2(shr, uint32_t, (uint32_t, uint32_t)) | |
206 | +DEF_HELPER_1_2(sar, uint32_t, (uint32_t, uint32_t)) | |
207 | +DEF_HELPER_1_2(ror, uint32_t, (uint32_t, uint32_t)) | |
208 | +DEF_HELPER_1_2(shl_cc, uint32_t, (uint32_t, uint32_t)) | |
209 | +DEF_HELPER_1_2(shr_cc, uint32_t, (uint32_t, uint32_t)) | |
210 | +DEF_HELPER_1_2(sar_cc, uint32_t, (uint32_t, uint32_t)) | |
211 | +DEF_HELPER_1_2(ror_cc, uint32_t, (uint32_t, uint32_t)) | |
212 | + | |
190 | 213 | #undef DEF_HELPER |
191 | 214 | #undef DEF_HELPER_0_0 |
192 | 215 | #undef DEF_HELPER_0_1 | ... | ... |
target-arm/op.c
... | ... | @@ -20,66 +20,6 @@ |
20 | 20 | */ |
21 | 21 | #include "exec.h" |
22 | 22 | |
23 | -void OPPROTO op_addl_T0_T1_cc(void) | |
24 | -{ | |
25 | - unsigned int src1; | |
26 | - src1 = T0; | |
27 | - T0 += T1; | |
28 | - env->NZF = T0; | |
29 | - env->CF = T0 < src1; | |
30 | - env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | |
31 | -} | |
32 | - | |
33 | -void OPPROTO op_adcl_T0_T1_cc(void) | |
34 | -{ | |
35 | - unsigned int src1; | |
36 | - src1 = T0; | |
37 | - if (!env->CF) { | |
38 | - T0 += T1; | |
39 | - env->CF = T0 < src1; | |
40 | - } else { | |
41 | - T0 += T1 + 1; | |
42 | - env->CF = T0 <= src1; | |
43 | - } | |
44 | - env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | |
45 | - env->NZF = T0; | |
46 | - FORCE_RET(); | |
47 | -} | |
48 | - | |
49 | -#define OPSUB(sub, sbc, res, T0, T1) \ | |
50 | - \ | |
51 | -void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ | |
52 | -{ \ | |
53 | - unsigned int src1; \ | |
54 | - src1 = T0; \ | |
55 | - T0 -= T1; \ | |
56 | - env->NZF = T0; \ | |
57 | - env->CF = src1 >= T1; \ | |
58 | - env->VF = (src1 ^ T1) & (src1 ^ T0); \ | |
59 | - res = T0; \ | |
60 | -} \ | |
61 | - \ | |
62 | -void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ | |
63 | -{ \ | |
64 | - unsigned int src1; \ | |
65 | - src1 = T0; \ | |
66 | - if (!env->CF) { \ | |
67 | - T0 = T0 - T1 - 1; \ | |
68 | - env->CF = src1 > T1; \ | |
69 | - } else { \ | |
70 | - T0 = T0 - T1; \ | |
71 | - env->CF = src1 >= T1; \ | |
72 | - } \ | |
73 | - env->VF = (src1 ^ T1) & (src1 ^ T0); \ | |
74 | - env->NZF = T0; \ | |
75 | - res = T0; \ | |
76 | - FORCE_RET(); \ | |
77 | -} | |
78 | - | |
79 | -OPSUB(sub, sbc, T0, T0, T1) | |
80 | - | |
81 | -OPSUB(rsb, rsc, T0, T1, T0) | |
82 | - | |
83 | 23 | /* memory access */ |
84 | 24 | |
85 | 25 | #define MEMSUFFIX _raw |
... | ... | @@ -92,164 +32,6 @@ OPSUB(rsb, rsc, T0, T1, T0) |
92 | 32 | #include "op_mem.h" |
93 | 33 | #endif |
94 | 34 | |
95 | -void OPPROTO op_clrex(void) | |
96 | -{ | |
97 | - cpu_lock(); | |
98 | - helper_clrex(env); | |
99 | - cpu_unlock(); | |
100 | -} | |
101 | - | |
102 | -/* T1 based, use T0 as shift count */ | |
103 | - | |
104 | -void OPPROTO op_shll_T1_T0(void) | |
105 | -{ | |
106 | - int shift; | |
107 | - shift = T0 & 0xff; | |
108 | - if (shift >= 32) | |
109 | - T1 = 0; | |
110 | - else | |
111 | - T1 = T1 << shift; | |
112 | - FORCE_RET(); | |
113 | -} | |
114 | - | |
115 | -void OPPROTO op_shrl_T1_T0(void) | |
116 | -{ | |
117 | - int shift; | |
118 | - shift = T0 & 0xff; | |
119 | - if (shift >= 32) | |
120 | - T1 = 0; | |
121 | - else | |
122 | - T1 = (uint32_t)T1 >> shift; | |
123 | - FORCE_RET(); | |
124 | -} | |
125 | - | |
126 | -void OPPROTO op_sarl_T1_T0(void) | |
127 | -{ | |
128 | - int shift; | |
129 | - shift = T0 & 0xff; | |
130 | - if (shift >= 32) | |
131 | - shift = 31; | |
132 | - T1 = (int32_t)T1 >> shift; | |
133 | -} | |
134 | - | |
135 | -void OPPROTO op_rorl_T1_T0(void) | |
136 | -{ | |
137 | - int shift; | |
138 | - shift = T0 & 0x1f; | |
139 | - if (shift) { | |
140 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
141 | - } | |
142 | - FORCE_RET(); | |
143 | -} | |
144 | - | |
145 | -/* T1 based, use T0 as shift count and compute CF */ | |
146 | - | |
147 | -void OPPROTO op_shll_T1_T0_cc(void) | |
148 | -{ | |
149 | - int shift; | |
150 | - shift = T0 & 0xff; | |
151 | - if (shift >= 32) { | |
152 | - if (shift == 32) | |
153 | - env->CF = T1 & 1; | |
154 | - else | |
155 | - env->CF = 0; | |
156 | - T1 = 0; | |
157 | - } else if (shift != 0) { | |
158 | - env->CF = (T1 >> (32 - shift)) & 1; | |
159 | - T1 = T1 << shift; | |
160 | - } | |
161 | - FORCE_RET(); | |
162 | -} | |
163 | - | |
164 | -void OPPROTO op_shrl_T1_T0_cc(void) | |
165 | -{ | |
166 | - int shift; | |
167 | - shift = T0 & 0xff; | |
168 | - if (shift >= 32) { | |
169 | - if (shift == 32) | |
170 | - env->CF = (T1 >> 31) & 1; | |
171 | - else | |
172 | - env->CF = 0; | |
173 | - T1 = 0; | |
174 | - } else if (shift != 0) { | |
175 | - env->CF = (T1 >> (shift - 1)) & 1; | |
176 | - T1 = (uint32_t)T1 >> shift; | |
177 | - } | |
178 | - FORCE_RET(); | |
179 | -} | |
180 | - | |
181 | -void OPPROTO op_sarl_T1_T0_cc(void) | |
182 | -{ | |
183 | - int shift; | |
184 | - shift = T0 & 0xff; | |
185 | - if (shift >= 32) { | |
186 | - env->CF = (T1 >> 31) & 1; | |
187 | - T1 = (int32_t)T1 >> 31; | |
188 | - } else if (shift != 0) { | |
189 | - env->CF = (T1 >> (shift - 1)) & 1; | |
190 | - T1 = (int32_t)T1 >> shift; | |
191 | - } | |
192 | - FORCE_RET(); | |
193 | -} | |
194 | - | |
195 | -void OPPROTO op_rorl_T1_T0_cc(void) | |
196 | -{ | |
197 | - int shift1, shift; | |
198 | - shift1 = T0 & 0xff; | |
199 | - shift = shift1 & 0x1f; | |
200 | - if (shift == 0) { | |
201 | - if (shift1 != 0) | |
202 | - env->CF = (T1 >> 31) & 1; | |
203 | - } else { | |
204 | - env->CF = (T1 >> (shift - 1)) & 1; | |
205 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
206 | - } | |
207 | - FORCE_RET(); | |
208 | -} | |
209 | - | |
210 | -void OPPROTO op_movl_cp_T0(void) | |
211 | -{ | |
212 | - helper_set_cp(env, PARAM1, T0); | |
213 | - FORCE_RET(); | |
214 | -} | |
215 | - | |
216 | -void OPPROTO op_movl_T0_cp(void) | |
217 | -{ | |
218 | - T0 = helper_get_cp(env, PARAM1); | |
219 | - FORCE_RET(); | |
220 | -} | |
221 | - | |
222 | -void OPPROTO op_movl_cp15_T0(void) | |
223 | -{ | |
224 | - helper_set_cp15(env, PARAM1, T0); | |
225 | - FORCE_RET(); | |
226 | -} | |
227 | - | |
228 | -void OPPROTO op_movl_T0_cp15(void) | |
229 | -{ | |
230 | - T0 = helper_get_cp15(env, PARAM1); | |
231 | - FORCE_RET(); | |
232 | -} | |
233 | - | |
234 | -void OPPROTO op_v7m_mrs_T0(void) | |
235 | -{ | |
236 | - T0 = helper_v7m_mrs(env, PARAM1); | |
237 | -} | |
238 | - | |
239 | -void OPPROTO op_v7m_msr_T0(void) | |
240 | -{ | |
241 | - helper_v7m_msr(env, PARAM1, T0); | |
242 | -} | |
243 | - | |
244 | -void OPPROTO op_movl_T0_sp(void) | |
245 | -{ | |
246 | - if (PARAM1 == env->v7m.current_sp) | |
247 | - T0 = env->regs[13]; | |
248 | - else | |
249 | - T0 = env->v7m.other_sp; | |
250 | - FORCE_RET(); | |
251 | -} | |
252 | - | |
253 | 35 | #include "op_neon.h" |
254 | 36 | |
255 | 37 | /* iwMMXt support */ | ... | ... |
target-arm/op_helper.c
... | ... | @@ -304,3 +304,151 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val) |
304 | 304 | } |
305 | 305 | } |
306 | 306 | |
307 | +/* ??? Flag setting arithmetic is awkward because we need to do comparisons. | |
308 | + The only way to do that in TCG is a conditional branch, which clobbers | |
309 | + all our temporaries. For now implement these as helper functions. */ | |
310 | + | |
311 | +uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) | |
312 | +{ | |
313 | + uint32_t result; | |
314 | + result = T0 + T1; | |
315 | + env->NZF = result; | |
316 | + env->CF = result < a; | |
317 | + env->VF = (a ^ b ^ -1) & (a ^ result); | |
318 | + return result; | |
319 | +} | |
320 | + | |
321 | +uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) | |
322 | +{ | |
323 | + uint32_t result; | |
324 | + if (!env->CF) { | |
325 | + result = a + b; | |
326 | + env->CF = result < a; | |
327 | + } else { | |
328 | + result = a + b + 1; | |
329 | + env->CF = result <= a; | |
330 | + } | |
331 | + env->VF = (a ^ b ^ -1) & (a ^ result); | |
332 | + env->NZF = result; | |
333 | + return result; | |
334 | +} | |
335 | + | |
336 | +uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) | |
337 | +{ | |
338 | + uint32_t result; | |
339 | + result = a - b; | |
340 | + env->NZF = result; | |
341 | + env->CF = a >= b; | |
342 | + env->VF = (a ^ b) & (a ^ result); | |
343 | + return result; | |
344 | +} | |
345 | + | |
346 | +uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) | |
347 | +{ | |
348 | + uint32_t result; | |
349 | + if (!env->CF) { | |
350 | + result = a - b - 1; | |
351 | + env->CF = a > b; | |
352 | + } else { | |
353 | + result = a - b; | |
354 | + env->CF = a >= b; | |
355 | + } | |
356 | + env->VF = (a ^ b) & (a ^ result); | |
357 | + env->NZF = result; | |
358 | + return result; | |
359 | +} | |
360 | + | |
361 | +/* Similarly for variable shift instructions. */ | |
362 | + | |
363 | +uint32_t HELPER(shl)(uint32_t x, uint32_t i) | |
364 | +{ | |
365 | + int shift = i & 0xff; | |
366 | + if (shift >= 32) | |
367 | + return 0; | |
368 | + return x << shift; | |
369 | +} | |
370 | + | |
371 | +uint32_t HELPER(shr)(uint32_t x, uint32_t i) | |
372 | +{ | |
373 | + int shift = i & 0xff; | |
374 | + if (shift >= 32) | |
375 | + return 0; | |
376 | + return (uint32_t)x >> shift; | |
377 | +} | |
378 | + | |
379 | +uint32_t HELPER(sar)(uint32_t x, uint32_t i) | |
380 | +{ | |
381 | + int shift = i & 0xff; | |
382 | + if (shift >= 32) | |
383 | + shift = 31; | |
384 | + return (int32_t)x >> shift; | |
385 | +} | |
386 | + | |
387 | +uint32_t HELPER(ror)(uint32_t x, uint32_t i) | |
388 | +{ | |
389 | + int shift = i & 0xff; | |
390 | + if (shift == 0) | |
391 | + return x; | |
392 | + return (x >> shift) | (x << (32 - shift)); | |
393 | +} | |
394 | + | |
395 | +uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) | |
396 | +{ | |
397 | + int shift = i & 0xff; | |
398 | + if (shift >= 32) { | |
399 | + if (shift == 32) | |
400 | + env->CF = x & 1; | |
401 | + else | |
402 | + env->CF = 0; | |
403 | + return 0; | |
404 | + } else if (shift != 0) { | |
405 | + env->CF = (x >> (32 - shift)) & 1; | |
406 | + return x << shift; | |
407 | + } | |
408 | + return x; | |
409 | +} | |
410 | + | |
411 | +uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) | |
412 | +{ | |
413 | + int shift = i & 0xff; | |
414 | + if (shift >= 32) { | |
415 | + if (shift == 32) | |
416 | + env->CF = (x >> 31) & 1; | |
417 | + else | |
418 | + env->CF = 0; | |
419 | + return 0; | |
420 | + } else if (shift != 0) { | |
421 | + env->CF = (x >> (shift - 1)) & 1; | |
422 | + return x >> shift; | |
423 | + } | |
424 | + return x; | |
425 | +} | |
426 | + | |
427 | +uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) | |
428 | +{ | |
429 | + int shift = i & 0xff; | |
430 | + if (shift >= 32) { | |
431 | + env->CF = (x >> 31) & 1; | |
432 | + return (int32_t)x >> 31; | |
433 | + } else if (shift != 0) { | |
434 | + env->CF = (x >> (shift - 1)) & 1; | |
435 | + return (int32_t)x >> shift; | |
436 | + } | |
437 | + return x; | |
438 | +} | |
439 | + | |
440 | +uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) | |
441 | +{ | |
442 | + int shift1, shift; | |
443 | + shift1 = i & 0xff; | |
444 | + shift = shift1 & 0x1f; | |
445 | + if (shift == 0) { | |
446 | + if (shift1 != 0) | |
447 | + env->CF = (x >> 31) & 1; | |
448 | + return x; | |
449 | + } else { | |
450 | + env->CF = (x >> (shift - 1)) & 1; | |
451 | + return ((uint32_t)x >> shift) | (x << (32 - shift)); | |
452 | + } | |
453 | +} | |
454 | + | ... | ... |
target-arm/op_mem.h
1 | 1 | /* ARM memory operations. */ |
2 | 2 | |
3 | -/* Swap T0 with memory at address T1. */ | |
4 | -/* ??? Is this exception safe? */ | |
5 | -#define MEM_SWP_OP(name, lname) \ | |
6 | -void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \ | |
7 | -{ \ | |
8 | - uint32_t tmp; \ | |
9 | - cpu_lock(); \ | |
10 | - tmp = glue(ld##lname,MEMSUFFIX)(T1); \ | |
11 | - glue(st##name,MEMSUFFIX)(T1, T0); \ | |
12 | - T0 = tmp; \ | |
13 | - cpu_unlock(); \ | |
14 | - FORCE_RET(); \ | |
15 | -} | |
16 | - | |
17 | -MEM_SWP_OP(b, ub) | |
18 | -MEM_SWP_OP(l, l) | |
19 | - | |
20 | -#undef MEM_SWP_OP | |
21 | - | |
22 | 3 | /* Load-locked, store exclusive. */ |
23 | 4 | #define EXCLUSIVE_OP(suffix, ldsuffix) \ |
24 | 5 | void OPPROTO glue(op_ld##suffix##ex,MEMSUFFIX)(void) \ | ... | ... |
target-arm/translate.c
... | ... | @@ -201,6 +201,13 @@ static void store_reg(DisasContext *s, int reg, TCGv var) |
201 | 201 | #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1]) |
202 | 202 | #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0]) |
203 | 203 | |
204 | +#define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]) | |
205 | +#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1]) | |
206 | +#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1]) | |
207 | +#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1]) | |
208 | +#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0]) | |
209 | +#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0]) | |
210 | + | |
204 | 211 | #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1]) |
205 | 212 | #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1]) |
206 | 213 | #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1]) |
... | ... | @@ -538,6 +545,27 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) |
538 | 545 | } |
539 | 546 | }; |
540 | 547 | |
548 | +static inline void gen_arm_shift_reg(TCGv var, int shiftop, | |
549 | + TCGv shift, int flags) | |
550 | +{ | |
551 | + if (flags) { | |
552 | + switch (shiftop) { | |
553 | + case 0: gen_helper_shl_cc(var, var, shift); break; | |
554 | + case 1: gen_helper_shr_cc(var, var, shift); break; | |
555 | + case 2: gen_helper_sar_cc(var, var, shift); break; | |
556 | + case 3: gen_helper_ror_cc(var, var, shift); break; | |
557 | + } | |
558 | + } else { | |
559 | + switch (shiftop) { | |
560 | + case 0: gen_helper_shl(var, var, shift); break; | |
561 | + case 1: gen_helper_shr(var, var, shift); break; | |
562 | + case 2: gen_helper_sar(var, var, shift); break; | |
563 | + case 3: gen_helper_ror(var, var, shift); break; | |
564 | + } | |
565 | + } | |
566 | + dead_tmp(shift); | |
567 | +} | |
568 | + | |
541 | 569 | #define PAS_OP(pfx) \ |
542 | 570 | switch (op2) { \ |
543 | 571 | case 0: gen_pas_helper(glue(pfx,add16)); break; \ |
... | ... | @@ -746,20 +774,6 @@ const uint8_t table_logic_cc[16] = { |
746 | 774 | 1, /* mvn */ |
747 | 775 | }; |
748 | 776 | |
749 | -static GenOpFunc *gen_shift_T1_T0[4] = { | |
750 | - gen_op_shll_T1_T0, | |
751 | - gen_op_shrl_T1_T0, | |
752 | - gen_op_sarl_T1_T0, | |
753 | - gen_op_rorl_T1_T0, | |
754 | -}; | |
755 | - | |
756 | -static GenOpFunc *gen_shift_T1_T0_cc[4] = { | |
757 | - gen_op_shll_T1_T0_cc, | |
758 | - gen_op_shrl_T1_T0_cc, | |
759 | - gen_op_sarl_T1_T0_cc, | |
760 | - gen_op_rorl_T1_T0_cc, | |
761 | -}; | |
762 | - | |
763 | 777 | /* Set PC and Thumb state from an immediate address. */ |
764 | 778 | static inline void gen_bx_im(DisasContext *s, uint32_t addr) |
765 | 779 | { |
... | ... | @@ -2249,6 +2263,7 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) |
2249 | 2263 | instruction is not defined. */ |
2250 | 2264 | static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) |
2251 | 2265 | { |
2266 | + TCGv tmp; | |
2252 | 2267 | uint32_t rd = (insn >> 12) & 0xf; |
2253 | 2268 | uint32_t cp = (insn >> 8) & 0xf; |
2254 | 2269 | if (IS_USER(s)) { |
... | ... | @@ -2258,17 +2273,16 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) |
2258 | 2273 | if (insn & ARM_CP_RW_BIT) { |
2259 | 2274 | if (!env->cp[cp].cp_read) |
2260 | 2275 | return 1; |
2261 | - gen_op_movl_T0_im((uint32_t) s->pc); | |
2262 | - gen_set_pc_T0(); | |
2263 | - gen_op_movl_T0_cp(insn); | |
2264 | - gen_movl_reg_T0(s, rd); | |
2276 | + gen_set_pc_im(s->pc); | |
2277 | + tmp = new_tmp(); | |
2278 | + gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn)); | |
2279 | + store_reg(s, rd, tmp); | |
2265 | 2280 | } else { |
2266 | 2281 | if (!env->cp[cp].cp_write) |
2267 | 2282 | return 1; |
2268 | - gen_op_movl_T0_im((uint32_t) s->pc); | |
2269 | - gen_set_pc_T0(); | |
2270 | - gen_movl_T0_reg(s, rd); | |
2271 | - gen_op_movl_cp_T0(insn); | |
2283 | + gen_set_pc_im(s->pc); | |
2284 | + tmp = load_reg(s, rd); | |
2285 | + gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp); | |
2272 | 2286 | } |
2273 | 2287 | return 0; |
2274 | 2288 | } |
... | ... | @@ -2298,6 +2312,7 @@ static int cp15_user_ok(uint32_t insn) |
2298 | 2312 | static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) |
2299 | 2313 | { |
2300 | 2314 | uint32_t rd; |
2315 | + TCGv tmp; | |
2301 | 2316 | |
2302 | 2317 | /* M profile cores use memory mapped registers instead of cp15. */ |
2303 | 2318 | if (arm_feature(env, ARM_FEATURE_M)) |
... | ... | @@ -2321,20 +2336,23 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) |
2321 | 2336 | if ((insn & 0x0fff0fff) == 0x0e070f90 |
2322 | 2337 | || (insn & 0x0fff0fff) == 0x0e070f58) { |
2323 | 2338 | /* Wait for interrupt. */ |
2324 | - gen_op_movl_T0_im((long)s->pc); | |
2325 | - gen_set_pc_T0(); | |
2339 | + gen_set_pc_im(s->pc); | |
2326 | 2340 | s->is_jmp = DISAS_WFI; |
2327 | 2341 | return 0; |
2328 | 2342 | } |
2329 | 2343 | rd = (insn >> 12) & 0xf; |
2330 | 2344 | if (insn & ARM_CP_RW_BIT) { |
2331 | - gen_op_movl_T0_cp15(insn); | |
2345 | + tmp = new_tmp(); | |
2346 | + gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn)); | |
2332 | 2347 | /* If the destination register is r15 then sets condition codes. */ |
2333 | 2348 | if (rd != 15) |
2334 | - gen_movl_reg_T0(s, rd); | |
2349 | + store_reg(s, rd, tmp); | |
2350 | + else | |
2351 | + dead_tmp(tmp); | |
2335 | 2352 | } else { |
2336 | - gen_movl_T0_reg(s, rd); | |
2337 | - gen_op_movl_cp15_T0(insn); | |
2353 | + tmp = load_reg(s, rd); | |
2354 | + gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp); | |
2355 | + dead_tmp(tmp); | |
2338 | 2356 | /* Normally we would always end the TB here, but Linux |
2339 | 2357 | * arch/arm/mach-pxa/sleep.S expects two instructions following |
2340 | 2358 | * an MMU enable to execute from cache. Imitate this behaviour. */ |
... | ... | @@ -3052,12 +3070,10 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) |
3052 | 3070 | tb = s->tb; |
3053 | 3071 | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { |
3054 | 3072 | tcg_gen_goto_tb(n); |
3055 | - gen_op_movl_T0_im(dest); | |
3056 | - gen_set_pc_T0(); | |
3073 | + gen_set_pc_im(dest); | |
3057 | 3074 | tcg_gen_exit_tb((long)tb + n); |
3058 | 3075 | } else { |
3059 | - gen_op_movl_T0_im(dest); | |
3060 | - gen_set_pc_T0(); | |
3076 | + gen_set_pc_im(dest); | |
3061 | 3077 | tcg_gen_exit_tb(0); |
3062 | 3078 | } |
3063 | 3079 | } |
... | ... | @@ -3173,8 +3189,7 @@ static void gen_nop_hint(DisasContext *s, int val) |
3173 | 3189 | { |
3174 | 3190 | switch (val) { |
3175 | 3191 | case 3: /* wfi */ |
3176 | - gen_op_movl_T0_im((long)s->pc); | |
3177 | - gen_set_pc_T0(); | |
3192 | + gen_set_pc_im(s->pc); | |
3178 | 3193 | s->is_jmp = DISAS_WFI; |
3179 | 3194 | break; |
3180 | 3195 | case 2: /* wfe */ |
... | ... | @@ -5770,12 +5785,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
5770 | 5785 | gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc); |
5771 | 5786 | } else { |
5772 | 5787 | rs = (insn >> 8) & 0xf; |
5773 | - gen_movl_T0_reg(s, rs); | |
5774 | - if (logic_cc) { | |
5775 | - gen_shift_T1_T0_cc[shiftop](); | |
5776 | - } else { | |
5777 | - gen_shift_T1_T0[shiftop](); | |
5778 | - } | |
5788 | + tmp = load_reg(s, rs); | |
5789 | + gen_arm_shift_reg(cpu_T[1], shiftop, tmp, logic_cc); | |
5779 | 5790 | } |
5780 | 5791 | } |
5781 | 5792 | if (op1 != 0x0f && op1 != 0x0d) { |
... | ... | @@ -5977,14 +5988,20 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
5977 | 5988 | /* SWP instruction */ |
5978 | 5989 | rm = (insn) & 0xf; |
5979 | 5990 | |
5980 | - gen_movl_T0_reg(s, rm); | |
5981 | - gen_movl_T1_reg(s, rn); | |
5991 | + /* ??? This is not really atomic. However we know | |
5992 | + we never have multiple CPUs running in parallel, | |
5993 | + so it is good enough. */ | |
5994 | + addr = load_reg(s, rn); | |
5995 | + tmp = load_reg(s, rm); | |
5982 | 5996 | if (insn & (1 << 22)) { |
5983 | - gen_ldst(swpb, s); | |
5997 | + tmp2 = gen_ld8u(addr, IS_USER(s)); | |
5998 | + gen_st8(tmp, addr, IS_USER(s)); | |
5984 | 5999 | } else { |
5985 | - gen_ldst(swpl, s); | |
6000 | + tmp2 = gen_ld32(addr, IS_USER(s)); | |
6001 | + gen_st32(tmp, addr, IS_USER(s)); | |
5986 | 6002 | } |
5987 | - gen_movl_reg_T0(s, rd); | |
6003 | + dead_tmp(addr); | |
6004 | + store_reg(s, rd, tmp2); | |
5988 | 6005 | } |
5989 | 6006 | } |
5990 | 6007 | } else { |
... | ... | @@ -6903,18 +6920,16 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
6903 | 6920 | goto illegal_op; |
6904 | 6921 | switch (op) { |
6905 | 6922 | case 0: /* Register controlled shift. */ |
6906 | - gen_movl_T0_reg(s, rm); | |
6907 | - gen_movl_T1_reg(s, rn); | |
6923 | + tmp = load_reg(s, rn); | |
6924 | + tmp2 = load_reg(s, rm); | |
6908 | 6925 | if ((insn & 0x70) != 0) |
6909 | 6926 | goto illegal_op; |
6910 | 6927 | op = (insn >> 21) & 3; |
6911 | - if (insn & (1 << 20)) { | |
6912 | - gen_shift_T1_T0_cc[op](); | |
6913 | - gen_op_logic_T1_cc(); | |
6914 | - } else { | |
6915 | - gen_shift_T1_T0[op](); | |
6916 | - } | |
6917 | - gen_movl_reg_T1(s, rd); | |
6928 | + logic_cc = (insn & (1 << 20)) != 0; | |
6929 | + gen_arm_shift_reg(tmp, op, tmp2, logic_cc); | |
6930 | + if (logic_cc) | |
6931 | + gen_logic_CC(tmp); | |
6932 | + store_reg(s, rd, tmp); | |
6918 | 6933 | break; |
6919 | 6934 | case 1: /* Sign/zero extend. */ |
6920 | 6935 | tmp = load_reg(s, rm); |
... | ... | @@ -7208,8 +7223,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
7208 | 7223 | switch (op) { |
7209 | 7224 | case 0: /* msr cpsr. */ |
7210 | 7225 | if (IS_M(env)) { |
7211 | - gen_op_v7m_msr_T0(insn & 0xff); | |
7212 | - gen_movl_reg_T0(s, rn); | |
7226 | + tmp = load_reg(s, rn); | |
7227 | + addr = tcg_const_i32(insn & 0xff); | |
7228 | + gen_helper_v7m_msr(cpu_env, addr, tmp); | |
7213 | 7229 | gen_lookup_tb(s); |
7214 | 7230 | break; |
7215 | 7231 | } |
... | ... | @@ -7276,12 +7292,14 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
7276 | 7292 | /* Unpredictable in user mode. */ |
7277 | 7293 | goto illegal_op; |
7278 | 7294 | case 6: /* mrs cpsr. */ |
7295 | + tmp = new_tmp(); | |
7279 | 7296 | if (IS_M(env)) { |
7280 | - gen_op_v7m_mrs_T0(insn & 0xff); | |
7297 | + addr = tcg_const_i32(insn & 0xff); | |
7298 | + gen_helper_v7m_mrs(tmp, cpu_env, addr); | |
7281 | 7299 | } else { |
7282 | - gen_helper_cpsr_read(cpu_T[0]); | |
7300 | + gen_helper_cpsr_read(tmp); | |
7283 | 7301 | } |
7284 | - gen_movl_reg_T0(s, rd); | |
7302 | + store_reg(s, rd, tmp); | |
7285 | 7303 | break; |
7286 | 7304 | case 7: /* mrs spsr. */ |
7287 | 7305 | /* Not accessible in user mode. */ |
... | ... | @@ -7753,25 +7771,25 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
7753 | 7771 | break; |
7754 | 7772 | case 0x2: /* lsl */ |
7755 | 7773 | if (s->condexec_mask) { |
7756 | - gen_op_shll_T1_T0(); | |
7774 | + gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7757 | 7775 | } else { |
7758 | - gen_op_shll_T1_T0_cc(); | |
7776 | + gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7759 | 7777 | gen_op_logic_T1_cc(); |
7760 | 7778 | } |
7761 | 7779 | break; |
7762 | 7780 | case 0x3: /* lsr */ |
7763 | 7781 | if (s->condexec_mask) { |
7764 | - gen_op_shrl_T1_T0(); | |
7782 | + gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7765 | 7783 | } else { |
7766 | - gen_op_shrl_T1_T0_cc(); | |
7784 | + gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7767 | 7785 | gen_op_logic_T1_cc(); |
7768 | 7786 | } |
7769 | 7787 | break; |
7770 | 7788 | case 0x4: /* asr */ |
7771 | 7789 | if (s->condexec_mask) { |
7772 | - gen_op_sarl_T1_T0(); | |
7790 | + gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7773 | 7791 | } else { |
7774 | - gen_op_sarl_T1_T0_cc(); | |
7792 | + gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7775 | 7793 | gen_op_logic_T1_cc(); |
7776 | 7794 | } |
7777 | 7795 | break; |
... | ... | @@ -7789,9 +7807,9 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
7789 | 7807 | break; |
7790 | 7808 | case 0x7: /* ror */ |
7791 | 7809 | if (s->condexec_mask) { |
7792 | - gen_op_rorl_T1_T0(); | |
7810 | + gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7793 | 7811 | } else { |
7794 | - gen_op_rorl_T1_T0_cc(); | |
7812 | + gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]); | |
7795 | 7813 | gen_op_logic_T1_cc(); |
7796 | 7814 | } |
7797 | 7815 | break; |
... | ... | @@ -8118,15 +8136,17 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
8118 | 8136 | if (IS_USER(s)) |
8119 | 8137 | break; |
8120 | 8138 | if (IS_M(env)) { |
8121 | - val = (insn & (1 << 4)) != 0; | |
8122 | - gen_op_movl_T0_im(val); | |
8139 | + tmp = tcg_const_i32((insn & (1 << 4)) != 0); | |
8123 | 8140 | /* PRIMASK */ |
8124 | - if (insn & 1) | |
8125 | - gen_op_v7m_msr_T0(16); | |
8141 | + if (insn & 1) { | |
8142 | + addr = tcg_const_i32(16); | |
8143 | + gen_helper_v7m_msr(cpu_env, addr, tmp); | |
8144 | + } | |
8126 | 8145 | /* FAULTMASK */ |
8127 | - if (insn & 2) | |
8128 | - gen_op_v7m_msr_T0(17); | |
8129 | - | |
8146 | + if (insn & 2) { | |
8147 | + addr = tcg_const_i32(17); | |
8148 | + gen_helper_v7m_msr(cpu_env, addr, tmp); | |
8149 | + } | |
8130 | 8150 | gen_lookup_tb(s); |
8131 | 8151 | } else { |
8132 | 8152 | if (insn & (1 << 4)) | ... | ... |