]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/blob - target-unicore32/op_helper.c
cpu-exec: Change cpu_loop_exit() argument to CPUState
[lisovros/qemu_apohw.git] / target-unicore32 / op_helper.c
1 /*
2  *  UniCore32 helper routines
3  *
4  * Copyright (C) 2010-2012 Guan Xuetao
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation, or (at your option) any
9  * later version. See the COPYING file in the top-level directory.
10  */
11 #include "cpu.h"
12 #include "helper.h"
13
14 #define SIGNBIT (uint32_t)0x80000000
15 #define SIGNBIT64 ((uint64_t)1 << 63)
16
17 void HELPER(exception)(CPUUniCore32State *env, uint32_t excp)
18 {
19     CPUState *cs = CPU(uc32_env_get_cpu(env));
20
21     cs->exception_index = excp;
22     cpu_loop_exit(cs);
23 }
24
25 static target_ulong asr_read(CPUUniCore32State *env)
26 {
27     int ZF;
28     ZF = (env->ZF == 0);
29     return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
30         (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
31 }
32
33 target_ulong cpu_asr_read(CPUUniCore32State *env)
34 {
35     return asr_read(env);
36 }
37
38 target_ulong HELPER(asr_read)(CPUUniCore32State *env)
39 {
40     return asr_read(env);
41 }
42
43 static void asr_write(CPUUniCore32State *env, target_ulong val,
44                       target_ulong mask)
45 {
46     if (mask & ASR_NZCV) {
47         env->ZF = (~val) & ASR_Z;
48         env->NF = val;
49         env->CF = (val >> 29) & 1;
50         env->VF = (val << 3) & 0x80000000;
51     }
52
53     if ((env->uncached_asr ^ val) & mask & ASR_M) {
54         switch_mode(env, val & ASR_M);
55     }
56     mask &= ~ASR_NZCV;
57     env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
58 }
59
60 void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask)
61 {
62     asr_write(env, val, mask);
63 }
64
65 void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val,
66                        target_ulong mask)
67 {
68     asr_write(env, val, mask);
69 }
70
71 /* Access to user mode registers from privileged modes.  */
72 uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno)
73 {
74     uint32_t val;
75
76     if (regno == 29) {
77         val = env->banked_r29[0];
78     } else if (regno == 30) {
79         val = env->banked_r30[0];
80     } else {
81         val = env->regs[regno];
82     }
83     return val;
84 }
85
86 void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val)
87 {
88     if (regno == 29) {
89         env->banked_r29[0] = val;
90     } else if (regno == 30) {
91         env->banked_r30[0] = val;
92     } else {
93         env->regs[regno] = val;
94     }
95 }
96
97 /* ??? Flag setting arithmetic is awkward because we need to do comparisons.
98    The only way to do that in TCG is a conditional branch, which clobbers
99    all our temporaries.  For now implement these as helper functions.  */
100
101 uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
102 {
103     uint32_t result;
104     result = a + b;
105     env->NF = env->ZF = result;
106     env->CF = result < a;
107     env->VF = (a ^ b ^ -1) & (a ^ result);
108     return result;
109 }
110
111 uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
112 {
113     uint32_t result;
114     if (!env->CF) {
115         result = a + b;
116         env->CF = result < a;
117     } else {
118         result = a + b + 1;
119         env->CF = result <= a;
120     }
121     env->VF = (a ^ b ^ -1) & (a ^ result);
122     env->NF = env->ZF = result;
123     return result;
124 }
125
126 uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
127 {
128     uint32_t result;
129     result = a - b;
130     env->NF = env->ZF = result;
131     env->CF = a >= b;
132     env->VF = (a ^ b) & (a ^ result);
133     return result;
134 }
135
136 uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
137 {
138     uint32_t result;
139     if (!env->CF) {
140         result = a - b - 1;
141         env->CF = a > b;
142     } else {
143         result = a - b;
144         env->CF = a >= b;
145     }
146     env->VF = (a ^ b) & (a ^ result);
147     env->NF = env->ZF = result;
148     return result;
149 }
150
151 /* Similarly for variable shift instructions.  */
152
153 uint32_t HELPER(shl)(uint32_t x, uint32_t i)
154 {
155     int shift = i & 0xff;
156     if (shift >= 32) {
157         return 0;
158     }
159     return x << shift;
160 }
161
162 uint32_t HELPER(shr)(uint32_t x, uint32_t i)
163 {
164     int shift = i & 0xff;
165     if (shift >= 32) {
166         return 0;
167     }
168     return (uint32_t)x >> shift;
169 }
170
171 uint32_t HELPER(sar)(uint32_t x, uint32_t i)
172 {
173     int shift = i & 0xff;
174     if (shift >= 32) {
175         shift = 31;
176     }
177     return (int32_t)x >> shift;
178 }
179
180 uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
181 {
182     int shift = i & 0xff;
183     if (shift >= 32) {
184         if (shift == 32) {
185             env->CF = x & 1;
186         } else {
187             env->CF = 0;
188         }
189         return 0;
190     } else if (shift != 0) {
191         env->CF = (x >> (32 - shift)) & 1;
192         return x << shift;
193     }
194     return x;
195 }
196
197 uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
198 {
199     int shift = i & 0xff;
200     if (shift >= 32) {
201         if (shift == 32) {
202             env->CF = (x >> 31) & 1;
203         } else {
204             env->CF = 0;
205         }
206         return 0;
207     } else if (shift != 0) {
208         env->CF = (x >> (shift - 1)) & 1;
209         return x >> shift;
210     }
211     return x;
212 }
213
214 uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
215 {
216     int shift = i & 0xff;
217     if (shift >= 32) {
218         env->CF = (x >> 31) & 1;
219         return (int32_t)x >> 31;
220     } else if (shift != 0) {
221         env->CF = (x >> (shift - 1)) & 1;
222         return (int32_t)x >> shift;
223     }
224     return x;
225 }
226
227 uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
228 {
229     int shift1, shift;
230     shift1 = i & 0xff;
231     shift = shift1 & 0x1f;
232     if (shift == 0) {
233         if (shift1 != 0) {
234             env->CF = (x >> 31) & 1;
235         }
236         return x;
237     } else {
238         env->CF = (x >> (shift - 1)) & 1;
239         return ((uint32_t)x >> shift) | (x << (32 - shift));
240     }
241 }
242
243 #ifndef CONFIG_USER_ONLY
244 #include "exec/softmmu_exec.h"
245
246 #define MMUSUFFIX _mmu
247
248 #define SHIFT 0
249 #include "exec/softmmu_template.h"
250
251 #define SHIFT 1
252 #include "exec/softmmu_template.h"
253
254 #define SHIFT 2
255 #include "exec/softmmu_template.h"
256
257 #define SHIFT 3
258 #include "exec/softmmu_template.h"
259
260 void tlb_fill(CPUState *cs, target_ulong addr, int is_write,
261               int mmu_idx, uintptr_t retaddr)
262 {
263     int ret;
264
265     ret = uc32_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
266     if (unlikely(ret)) {
267         UniCore32CPU *cpu = UNICORE32_CPU(cs);
268         CPUUniCore32State *env = &cpu->env;
269
270         if (retaddr) {
271             /* now we have a real cpu fault */
272             cpu_restore_state(env, retaddr);
273         }
274         cpu_loop_exit(cs);
275     }
276 }
277 #endif