2 * UniCore32 helper routines
4 * Copyright (C) 2010-2012 Guan Xuetao
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.
11 #include "qemu/osdep.h"
13 #include "exec/helper-proto.h"
14 #include "exec/exec-all.h"
15 #include "exec/cpu_ldst.h"
17 #define SIGNBIT (uint32_t)0x80000000
18 #define SIGNBIT64 ((uint64_t)1 << 63)
20 void HELPER(exception
)(CPUUniCore32State
*env
, uint32_t excp
)
22 CPUState
*cs
= CPU(uc32_env_get_cpu(env
));
24 cs
->exception_index
= excp
;
28 static target_ulong
asr_read(CPUUniCore32State
*env
)
32 return env
->uncached_asr
| (env
->NF
& 0x80000000) | (ZF
<< 30) |
33 (env
->CF
<< 29) | ((env
->VF
& 0x80000000) >> 3);
36 target_ulong
cpu_asr_read(CPUUniCore32State
*env
)
41 target_ulong
HELPER(asr_read
)(CPUUniCore32State
*env
)
46 static void asr_write(CPUUniCore32State
*env
, target_ulong val
,
49 if (mask
& ASR_NZCV
) {
50 env
->ZF
= (~val
) & ASR_Z
;
52 env
->CF
= (val
>> 29) & 1;
53 env
->VF
= (val
<< 3) & 0x80000000;
56 if ((env
->uncached_asr
^ val
) & mask
& ASR_M
) {
57 switch_mode(env
, val
& ASR_M
);
60 env
->uncached_asr
= (env
->uncached_asr
& ~mask
) | (val
& mask
);
63 void cpu_asr_write(CPUUniCore32State
*env
, target_ulong val
, target_ulong mask
)
65 asr_write(env
, val
, mask
);
68 void HELPER(asr_write
)(CPUUniCore32State
*env
, target_ulong val
,
71 asr_write(env
, val
, mask
);
74 /* Access to user mode registers from privileged modes. */
75 uint32_t HELPER(get_user_reg
)(CPUUniCore32State
*env
, uint32_t regno
)
80 val
= env
->banked_r29
[0];
81 } else if (regno
== 30) {
82 val
= env
->banked_r30
[0];
84 val
= env
->regs
[regno
];
89 void HELPER(set_user_reg
)(CPUUniCore32State
*env
, uint32_t regno
, uint32_t val
)
92 env
->banked_r29
[0] = val
;
93 } else if (regno
== 30) {
94 env
->banked_r30
[0] = val
;
96 env
->regs
[regno
] = val
;
100 /* ??? Flag setting arithmetic is awkward because we need to do comparisons.
101 The only way to do that in TCG is a conditional branch, which clobbers
102 all our temporaries. For now implement these as helper functions. */
104 uint32_t HELPER(add_cc
)(CPUUniCore32State
*env
, uint32_t a
, uint32_t b
)
108 env
->NF
= env
->ZF
= result
;
109 env
->CF
= result
< a
;
110 env
->VF
= (a
^ b
^ -1) & (a
^ result
);
114 uint32_t HELPER(adc_cc
)(CPUUniCore32State
*env
, uint32_t a
, uint32_t b
)
119 env
->CF
= result
< a
;
122 env
->CF
= result
<= a
;
124 env
->VF
= (a
^ b
^ -1) & (a
^ result
);
125 env
->NF
= env
->ZF
= result
;
129 uint32_t HELPER(sub_cc
)(CPUUniCore32State
*env
, uint32_t a
, uint32_t b
)
133 env
->NF
= env
->ZF
= result
;
135 env
->VF
= (a
^ b
) & (a
^ result
);
139 uint32_t HELPER(sbc_cc
)(CPUUniCore32State
*env
, uint32_t a
, uint32_t b
)
149 env
->VF
= (a
^ b
) & (a
^ result
);
150 env
->NF
= env
->ZF
= result
;
154 /* Similarly for variable shift instructions. */
156 uint32_t HELPER(shl
)(uint32_t x
, uint32_t i
)
158 int shift
= i
& 0xff;
165 uint32_t HELPER(shr
)(uint32_t x
, uint32_t i
)
167 int shift
= i
& 0xff;
171 return (uint32_t)x
>> shift
;
174 uint32_t HELPER(sar
)(uint32_t x
, uint32_t i
)
176 int shift
= i
& 0xff;
180 return (int32_t)x
>> shift
;
183 uint32_t HELPER(shl_cc
)(CPUUniCore32State
*env
, uint32_t x
, uint32_t i
)
185 int shift
= i
& 0xff;
193 } else if (shift
!= 0) {
194 env
->CF
= (x
>> (32 - shift
)) & 1;
200 uint32_t HELPER(shr_cc
)(CPUUniCore32State
*env
, uint32_t x
, uint32_t i
)
202 int shift
= i
& 0xff;
205 env
->CF
= (x
>> 31) & 1;
210 } else if (shift
!= 0) {
211 env
->CF
= (x
>> (shift
- 1)) & 1;
217 uint32_t HELPER(sar_cc
)(CPUUniCore32State
*env
, uint32_t x
, uint32_t i
)
219 int shift
= i
& 0xff;
221 env
->CF
= (x
>> 31) & 1;
222 return (int32_t)x
>> 31;
223 } else if (shift
!= 0) {
224 env
->CF
= (x
>> (shift
- 1)) & 1;
225 return (int32_t)x
>> shift
;
230 uint32_t HELPER(ror_cc
)(CPUUniCore32State
*env
, uint32_t x
, uint32_t i
)
234 shift
= shift1
& 0x1f;
237 env
->CF
= (x
>> 31) & 1;
241 env
->CF
= (x
>> (shift
- 1)) & 1;
242 return ((uint32_t)x
>> shift
) | (x
<< (32 - shift
));
246 #ifndef CONFIG_USER_ONLY
247 void tlb_fill(CPUState
*cs
, target_ulong addr
, int is_write
,
248 int mmu_idx
, uintptr_t retaddr
)
252 ret
= uc32_cpu_handle_mmu_fault(cs
, addr
, is_write
, mmu_idx
);
255 /* now we have a real cpu fault */
256 cpu_restore_state(cs
, retaddr
);