summaryrefslogtreecommitdiffstats
path: root/target/xtensa/op_helper.c
diff options
context:
space:
mode:
authorPeter Maydell2017-01-25 17:36:57 +0100
committerPeter Maydell2017-01-25 17:36:57 +0100
commite32c41e4f65f4d16508fe759a800538a73608839 (patch)
tree288ad9c192a4d6b58d3490eb088450de7153922c /target/xtensa/op_helper.c
parentMerge remote-tracking branch 'remotes/rth/tags/pull-nios-20170124' into staging (diff)
parenttarget-xtensa: implement RER/WER instructions (diff)
downloadqemu-e32c41e4f65f4d16508fe759a800538a73608839.tar.gz
qemu-e32c41e4f65f4d16508fe759a800538a73608839.tar.xz
qemu-e32c41e4f65f4d16508fe759a800538a73608839.zip
Merge remote-tracking branch 'remotes/xtensa/tags/20170124-xtensa' into staging
target/xtensa updates: - refactor CCOUNT/CCOMPARE (use QEMU timers instead of instruction counting); - support icount; run target/xtensa TCG tests with icount; - implement SMP prerequisites: static vector selection, RUNSTALL and RER/WER. # gpg: Signature made Wed 25 Jan 2017 00:27:51 GMT # gpg: using RSA key 0x51F9CC91F83FA044 # gpg: Good signature from "Max Filippov <max.filippov@cogentembedded.com>" # gpg: aka "Max Filippov <jcmvbkbc@gmail.com>" # Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044 * remotes/xtensa/tags/20170124-xtensa: target-xtensa: implement RER/WER instructions target/xtensa: tests: clean up interrupt tests target/xtensa: tests: add memctl test target/xtensa: implement MEMCTL SR target/xtensa: fix ICACHE/DCACHE options detection target/xtensa: tests: add ccount write tests target/xtensa: tests: replace hardcoded interrupt masks target/xtensa: tests: fix timer tests target/xtensa: tests: run tests with icount target/xtensa: don't continue translation after exception target/xtensa: support icount target/xtensa: refactor CCOUNT/CCOMPARE target/xtensa: implement RUNSTALL target/xtensa: add static vectors selection Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/xtensa/op_helper.c')
-rw-r--r--target/xtensa/op_helper.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c
index dc0dd351bb..af2723445d 100644
--- a/target/xtensa/op_helper.c
+++ b/target/xtensa/op_helper.c
@@ -105,6 +105,9 @@ void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
CPUState *cs = CPU(xtensa_env_get_cpu(env));
cs->exception_index = excp;
+ if (excp == EXCP_YIELD) {
+ env->yield_needed = 0;
+ }
if (excp == EXCP_DEBUG) {
env->exception_taken = 0;
}
@@ -385,22 +388,40 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
}
cpu = CPU(xtensa_env_get_cpu(env));
- env->halt_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
cpu->halted = 1;
- if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
- xtensa_rearm_ccompare_timer(env);
- }
HELPER(exception)(env, EXCP_HLT);
}
-void HELPER(timer_irq)(CPUXtensaState *env, uint32_t id, uint32_t active)
+void HELPER(update_ccount)(CPUXtensaState *env)
+{
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+ env->ccount_time = now;
+ env->sregs[CCOUNT] = env->ccount_base +
+ (uint32_t)((now - env->time_base) *
+ env->config->clock_freq_khz / 1000000);
+}
+
+void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v)
{
- xtensa_timer_irq(env, id, active);
+ int i;
+
+ HELPER(update_ccount)(env);
+ env->ccount_base += v - env->sregs[CCOUNT];
+ for (i = 0; i < env->config->nccompare; ++i) {
+ HELPER(update_ccompare)(env, i);
+ }
}
-void HELPER(advance_ccount)(CPUXtensaState *env, uint32_t d)
+void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i)
{
- xtensa_advance_ccount(env, d);
+ uint64_t dcc;
+
+ HELPER(update_ccount)(env);
+ dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1;
+ timer_mod(env->ccompare[i].timer,
+ env->ccount_time + (dcc * 1000000) / env->config->clock_freq_khz);
+ env->yield_needed = 1;
}
void HELPER(check_interrupts)(CPUXtensaState *env)
@@ -472,6 +493,30 @@ void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
}
}
+void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v)
+{
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) {
+ if (extract32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN) >
+ env->config->icache_ways) {
+ deposit32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN,
+ env->config->icache_ways);
+ }
+ }
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
+ if (extract32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN) >
+ env->config->dcache_ways) {
+ deposit32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN,
+ env->config->dcache_ways);
+ }
+ if (extract32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN) >
+ env->config->dcache_ways) {
+ deposit32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN,
+ env->config->dcache_ways);
+ }
+ }
+ env->sregs[MEMCTL] = v & env->config->memctl_mask;
+}
+
void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
{
XtensaCPU *cpu = xtensa_env_get_cpu(env);
@@ -969,3 +1014,15 @@ void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b)
int v = float32_compare_quiet(a, b, &env->fp_status);
set_br(env, v != float_relation_greater, br);
}
+
+uint32_t HELPER(rer)(CPUXtensaState *env, uint32_t addr)
+{
+ return address_space_ldl(env->address_space_er, addr,
+ (MemTxAttrs){0}, NULL);
+}
+
+void HELPER(wer)(CPUXtensaState *env, uint32_t data, uint32_t addr)
+{
+ address_space_stl(env->address_space_er, addr, data,
+ (MemTxAttrs){0}, NULL);
+}