diff options
Diffstat (limited to 'target-alpha')
-rw-r--r-- | target-alpha/cpu.h | 4 | ||||
-rw-r--r-- | target-alpha/helper.h | 4 | ||||
-rw-r--r-- | target-alpha/op_helper.c | 15 | ||||
-rw-r--r-- | target-alpha/translate.c | 29 |
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; |