Commit 99c475ab authored by bellard's avatar bellard
Browse files

armv5te support (Paul Brook)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1258 c046a42c-6fe2-441c-8c8c-71466251a162
parent dfe86665
......@@ -13,6 +13,8 @@ version 0.6.2:
- initial APIC support
- MMX/SSE/SSE2/PNI support
- PC parallel port support (Mark Jonckheere)
- initial SPARC64 support (Blue Swirl)
- armv5te user mode support (Paul Brook)
version 0.6.1:
......
......@@ -160,7 +160,8 @@ int cpu_exec(CPUState *env1)
env->CF = (psr >> 29) & 1;
env->NZF = (psr & 0xc0000000) ^ 0x40000000;
env->VF = (psr << 3) & 0x80000000;
env->cpsr = psr & ~0xf0000000;
env->QF = (psr >> 27) & 1;
env->cpsr = psr & ~CACHED_CPSR_BITS;
}
#elif defined(TARGET_SPARC)
#elif defined(TARGET_PPC)
......@@ -303,7 +304,7 @@ int cpu_exec(CPUState *env1)
#elif defined(TARGET_ARM)
env->cpsr = compute_cpsr();
cpu_dump_state(env, logfile, fprintf, 0);
env->cpsr &= ~0xf0000000;
env->cpsr &= ~CACHED_CPSR_BITS;
#elif defined(TARGET_SPARC)
cpu_dump_state (env, logfile, fprintf, 0);
#elif defined(TARGET_PPC)
......@@ -322,7 +323,7 @@ int cpu_exec(CPUState *env1)
cs_base = env->segs[R_CS].base;
pc = cs_base + env->eip;
#elif defined(TARGET_ARM)
flags = 0;
flags = env->thumb;
cs_base = 0;
pc = env->regs[15];
#elif defined(TARGET_SPARC)
......
......@@ -30,7 +30,7 @@ struct target_pt_regs {
#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
#if defined(TARGET_WORDS_BIGENDIAN)
#define UNAME_MACHINE "armv4b"
#define UNAME_MACHINE "armv5teb"
#else
#define UNAME_MACHINE "armv4l"
#define UNAME_MACHINE "armv5tel"
#endif
......@@ -2944,11 +2944,35 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
#endif
#ifdef TARGET_NR_getgroups32
case TARGET_NR_getgroups32:
goto unimplemented;
{
int gidsetsize = arg1;
uint32_t *target_grouplist = (void *)arg2;
gid_t *grouplist;
int i;
grouplist = alloca(gidsetsize * sizeof(gid_t));
ret = get_errno(getgroups(gidsetsize, grouplist));
if (!is_error(ret)) {
for(i = 0;i < gidsetsize; i++)
put_user(grouplist[i], &target_grouplist[i]);
}
}
break;
#endif
#ifdef TARGET_NR_setgroups32
case TARGET_NR_setgroups32:
goto unimplemented;
{
int gidsetsize = arg1;
uint32_t *target_grouplist = (void *)arg2;
gid_t *grouplist;
int i;
grouplist = alloca(gidsetsize * sizeof(gid_t));
for(i = 0;i < gidsetsize; i++)
get_user(grouplist[i], &target_grouplist[i]);
ret = get_errno(setgroups(gidsetsize, grouplist));
}
break;
#endif
#ifdef TARGET_NR_fchown32
case TARGET_NR_fchown32:
......
......@@ -35,6 +35,9 @@ typedef struct CPUARMState {
uint32_t CF; /* 0 or 1 */
uint32_t VF; /* V is the bit 31. All other bits are undefined */
uint32_t NZF; /* N is bit 31. Z is computed from NZF */
uint32_t QF; /* 0 or 1 */
int thumb; /* 0 = arm mode, 1 = thumb mode */
/* exception/interrupt handling */
jmp_buf jmp_env;
......
......@@ -31,12 +31,14 @@ void cpu_lock(void);
void cpu_unlock(void);
void cpu_loop_exit(void);
/* Implemented CPSR bits. */
#define CACHED_CPSR_BITS 0xf8000000
static inline int compute_cpsr(void)
{
int ZF;
ZF = (env->NZF == 0);
return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
(env->CF << 29) | ((env->VF & 0x80000000) >> 3);
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27);
}
static inline void env_to_regs(void)
......
......@@ -81,8 +81,15 @@
#define REGNAME r15
#define REG (env->regs[15])
#define SET_REG(x) REG = x & ~(uint32_t)1
#include "op_template.h"
void OPPROTO op_bx_T0(void)
{
env->regs[15] = T0 & ~(uint32_t)1;
env->thumb = (T0 & 1) != 0;
}
void OPPROTO op_movl_T0_0(void)
{
T0 = 0;
......@@ -382,6 +389,14 @@ void OPPROTO op_imull_T0_T1(void)
T0 = res;
}
/* 48 bit signed mul, top 32 bits */
void OPPROTO op_imulw_T0_T1(void)
{
uint64_t res;
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
T0 = res >> 16;
}
void OPPROTO op_addq_T0_T1(void)
{
uint64_t res;
......@@ -391,6 +406,15 @@ void OPPROTO op_addq_T0_T1(void)
T0 = res;
}
void OPPROTO op_addq_lo_T0_T1(void)
{
uint64_t res;
res = ((uint64_t)T1 << 32) | T0;
res += (uint64_t)(env->regs[PARAM1]);
T1 = res >> 32;
T0 = res;
}
void OPPROTO op_logicq_cc(void)
{
env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
......@@ -694,6 +718,126 @@ void OPPROTO op_rorl_T1_T0_cc(void)
FORCE_RET();
}
/* misc */
void OPPROTO op_clz_T0(void)
{
int count;
for (count = 32; T0 > 0; count--)
T0 = T0 >> 1;
T0 = count;
FORCE_RET();
}
void OPPROTO op_sarl_T0_im(void)
{
T0 = (int32_t)T0 >> PARAM1;
}
/* 16->32 Sign extend */
void OPPROTO op_sxl_T0(void)
{
T0 = (int16_t)T0;
}
void OPPROTO op_sxl_T1(void)
{
T1 = (int16_t)T1;
}
#define SIGNBIT (uint32_t)0x80000000
/* saturating arithmetic */
void OPPROTO op_addl_T0_T1_setq(void)
{
uint32_t res;
res = T0 + T1;
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
env->QF = 1;
T0 = res;
FORCE_RET();
}
void OPPROTO op_addl_T0_T1_saturate(void)
{
uint32_t res;
res = T0 + T1;
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
env->QF = 1;
if (T0 & SIGNBIT)
T0 = 0x80000000;
else
T0 = 0x7fffffff;
}
else
T0 = res;
FORCE_RET();
}
void OPPROTO op_subl_T0_T1_saturate(void)
{
uint32_t res;
res = T0 - T1;
if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
env->QF = 1;
if (T0 & SIGNBIT)
T0 = 0x8000000;
else
T0 = 0x7fffffff;
}
else
T0 = res;
FORCE_RET();
}
/* thumb shift by immediate */
void OPPROTO op_shll_T0_im_thumb(void)
{
int shift;
shift = PARAM1;
if (shift != 0) {
env->CF = (T1 >> (32 - shift)) & 1;
T0 = T0 << shift;
}
env->NZF = T0;
FORCE_RET();
}
void OPPROTO op_shrl_T0_im_thumb(void)
{
int shift;
shift = PARAM1;
if (shift == 0) {
env->CF = 0;
T0 = 0;
} else {
env->CF = (T0 >> (shift - 1)) & 1;
T0 = T0 >> shift;
}
FORCE_RET();
}
void OPPROTO op_sarl_T0_im_thumb(void)
{
int shift;
shift = PARAM1;
if (shift == 0) {
T0 = ((int32_t)T0) >> 31;
env->CF = T0 & 1;
} else {
env->CF = (T0 >> (shift - 1)) & 1;
T0 = ((int32_t)T0) >> shift;
}
env->NZF = T0;
FORCE_RET();
}
/* exceptions */
void OPPROTO op_swi(void)
......
......@@ -19,6 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SET_REG
#define SET_REG(x) REG = x
#endif
void OPPROTO glue(op_movl_T0_, REGNAME)(void)
{
T0 = REG;
......@@ -36,13 +40,14 @@ void OPPROTO glue(op_movl_T2_, REGNAME)(void)
void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void)
{
REG = T0;
SET_REG (T0);
}
void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void)
{
REG = T1;
SET_REG (T1);
}
#undef REG
#undef REGNAME
#undef SET_REG
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment