summaryrefslogtreecommitdiff
path: root/target-sparc
diff options
context:
space:
mode:
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-25 18:50:28 +0000
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-25 18:50:28 +0000
commit20c9f095c4536e64e60432a5c72fce38e8306cbb (patch)
treefe68375301d78efc0eb73138da36199a00bcde7a /target-sparc
parent8d05ea8a33c9d450d2a3079e967c69ea38ec28ba (diff)
downloadqemu-20c9f095c4536e64e60432a5c72fce38e8306cbb.zip
Implement Sparc64 CPU timers using ptimers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2860 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc')
-rw-r--r--target-sparc/cpu.h5
-rw-r--r--target-sparc/op.c30
-rw-r--r--target-sparc/op_helper.c17
-rw-r--r--target-sparc/translate.c13
4 files changed, 58 insertions, 7 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index b067d7b9bd..c5ccd28a82 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -226,10 +226,12 @@ typedef struct CPUSPARCState {
uint64_t mgregs[8]; /* mmu general registers */
uint64_t fprs;
uint64_t tick_cmpr, stick_cmpr;
+ void *tick, *stick;
uint64_t gsr;
uint32_t gl; // UA2005
/* UA 2005 hyperprivileged registers */
uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr;
+ void *hstick; // UA 2005
#endif
#if !defined(TARGET_SPARC64) && !defined(reg_T2)
target_ulong t2;
@@ -292,6 +294,9 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
void raise_exception(int tt);
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
int is_asi);
+void do_tick_set_count(void *opaque, uint64_t count);
+uint64_t do_tick_get_count(void *opaque);
+void do_tick_set_limit(void *opaque, uint64_t limit);
#include "cpu-all.h"
diff --git a/target-sparc/op.c b/target-sparc/op.c
index 5fbbd6db0f..c0aee8f4ac 100644
--- a/target-sparc/op.c
+++ b/target-sparc/op.c
@@ -1096,12 +1096,38 @@ void OPPROTO op_wrccr(void)
void OPPROTO op_rdtick(void)
{
- T0 = 0; // XXX read cycle counter and bit 31
+ T0 = do_tick_get_count(env->tick);
}
void OPPROTO op_wrtick(void)
{
- T0 = 0; // XXX write cycle counter and bit 31
+ do_tick_set_count(env->tick, T0);
+}
+
+void OPPROTO op_wrtick_cmpr(void)
+{
+ do_tick_set_limit(env->tick, T0);
+}
+
+void OPPROTO op_rdstick(void)
+{
+ T0 = do_tick_get_count(env->stick);
+}
+
+void OPPROTO op_wrstick(void)
+{
+ do_tick_set_count(env->stick, T0);
+ do_tick_set_count(env->hstick, T0);
+}
+
+void OPPROTO op_wrstick_cmpr(void)
+{
+ do_tick_set_limit(env->stick, T0);
+}
+
+void OPPROTO op_wrhstick_cmpr(void)
+{
+ do_tick_set_limit(env->hstick, T0);
}
void OPPROTO op_rdtpc(void)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 93f61a8025..b2f982f4ee 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1133,3 +1133,20 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
raise_exception(TT_DATA_ACCESS);
}
#endif
+
+#ifdef TARGET_SPARC64
+void do_tick_set_count(void *opaque, uint64_t count)
+{
+ ptimer_set_count(opaque, -count);
+}
+
+uint64_t do_tick_get_count(void *opaque)
+{
+ return -ptimer_get_count(opaque);
+}
+
+void do_tick_set_limit(void *opaque, uint64_t limit)
+{
+ ptimer_set_limit(opaque, -limit, 0);
+}
+#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 38d2a13195..8dbe3370fe 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1202,7 +1202,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_movl_T0_reg(rd);
break;
case 0x18: /* System tick */
- gen_op_rdtick(); // XXX
+ gen_op_rdstick();
gen_movl_T0_reg(rd);
break;
case 0x19: /* System tick compare */
@@ -1991,21 +1991,23 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc))
goto illegal_insn;
#endif
- gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
+ gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
+ gen_op_wrtick_cmpr();
break;
case 0x18: /* System tick */
#if !defined(CONFIG_USER_ONLY)
if (!supervisor(dc))
goto illegal_insn;
#endif
- gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+ gen_op_wrstick();
break;
case 0x19: /* System tick compare */
#if !defined(CONFIG_USER_ONLY)
if (!supervisor(dc))
goto illegal_insn;
#endif
- gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+ gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+ gen_op_wrstick_cmpr();
break;
case 0x10: /* Performance Control */
@@ -2155,7 +2157,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
break;
case 31: // hstick_cmpr
- gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+ gen_op_movtl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+ gen_op_wrhstick_cmpr();
break;
case 6: // hver readonly
default: