aboutsummaryrefslogtreecommitdiff
path: root/target-alpha
diff options
context:
space:
mode:
Diffstat (limited to 'target-alpha')
-rw-r--r--target-alpha/cpu.h4
-rw-r--r--target-alpha/helper.h4
-rw-r--r--target-alpha/op_helper.c15
-rw-r--r--target-alpha/translate.c29
4 files changed, 48 insertions, 4 deletions
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c2e7bb31ef..9d61d45ab6 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -265,6 +265,10 @@ struct CPUAlphaState {
uint64_t scratch[24];
#endif
+ /* This alarm doesn't exist in real hardware; we wish it did. */
+ struct QEMUTimer *alarm_timer;
+ uint64_t alarm_expire;
+
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* temporary fixed-point registers
* used to emulate 64 bits target on 32 bits hosts
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index c352c2493e..b693ceea97 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -113,7 +113,11 @@ DEF_HELPER_2(stq_c_phys, i64, i64, i64)
DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
+
DEF_HELPER_1(halt, void, i64);
+
+DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
+DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64)
#endif
#include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 1896ab8b00..cc102dbd63 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1228,6 +1228,21 @@ void helper_halt(uint64_t restart)
qemu_system_shutdown_request();
}
}
+
+uint64_t helper_get_time(void)
+{
+ return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(uint64_t expire)
+{
+ if (expire) {
+ env->alarm_expire = expire;
+ qemu_mod_timer(env->alarm_timer, expire);
+ } else {
+ qemu_del_timer(env->alarm_timer);
+ }
+}
#endif
/*****************************************************************************/
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0acbd682d3..a961159d5d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1590,18 +1590,34 @@ static int cpu_pr_data(int pr)
return offsetof(CPUAlphaState, shadow[pr - 32]);
case 40 ... 63:
return offsetof(CPUAlphaState, scratch[pr - 40]);
+
+ case 251:
+ return offsetof(CPUAlphaState, alarm_expire);
}
return 0;
}
-static void gen_mfpr(int ra, int regno)
+static ExitStatus gen_mfpr(int ra, int regno)
{
int data = cpu_pr_data(regno);
/* In our emulated PALcode, these processor registers have no
side effects from reading. */
if (ra == 31) {
- return;
+ return NO_EXIT;
+ }
+
+ if (regno == 250) {
+ /* WALL_TIME */
+ if (use_icount) {
+ gen_io_start();
+ gen_helper_get_time(cpu_ir[ra]);
+ gen_io_end();
+ return EXIT_PC_STALE;
+ } else {
+ gen_helper_get_time(cpu_ir[ra]);
+ return NO_EXIT;
+ }
}
/* The basic registers are data only, and unknown registers
@@ -1615,6 +1631,7 @@ static void gen_mfpr(int ra, int regno)
} else {
tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
}
+ return NO_EXIT;
}
static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
@@ -1650,6 +1667,11 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
gen_helper_halt(tmp);
return EXIT_PC_STALE;
+ case 251:
+ /* ALARM */
+ gen_helper_set_alarm(tmp);
+ break;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
@@ -2772,8 +2794,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* HW_MFPR (PALcode) */
#ifndef CONFIG_USER_ONLY
if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
- gen_mfpr(ra, insn & 0xffff);
- break;
+ return gen_mfpr(ra, insn & 0xffff);
}
#endif
goto invalid_opc;