169163fbbSRichard Henderson /* 269163fbbSRichard Henderson * Helpers for system instructions. 369163fbbSRichard Henderson * 469163fbbSRichard Henderson * Copyright (c) 2007 Jocelyn Mayer 569163fbbSRichard Henderson * 669163fbbSRichard Henderson * This library is free software; you can redistribute it and/or 769163fbbSRichard Henderson * modify it under the terms of the GNU Lesser General Public 869163fbbSRichard Henderson * License as published by the Free Software Foundation; either 969163fbbSRichard Henderson * version 2 of the License, or (at your option) any later version. 1069163fbbSRichard Henderson * 1169163fbbSRichard Henderson * This library is distributed in the hope that it will be useful, 1269163fbbSRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 1369163fbbSRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1469163fbbSRichard Henderson * Lesser General Public License for more details. 1569163fbbSRichard Henderson * 1669163fbbSRichard Henderson * You should have received a copy of the GNU Lesser General Public 1769163fbbSRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1869163fbbSRichard Henderson */ 1969163fbbSRichard Henderson 2069163fbbSRichard Henderson #include "cpu.h" 2169163fbbSRichard Henderson #include "helper.h" 229c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 231de7afc9SPaolo Bonzini #include "qemu/timer.h" 2469163fbbSRichard Henderson 2569163fbbSRichard Henderson 2669163fbbSRichard Henderson uint64_t helper_load_pcc(CPUAlphaState *env) 2769163fbbSRichard Henderson { 2869163fbbSRichard Henderson #ifndef CONFIG_USER_ONLY 2969163fbbSRichard Henderson /* In system mode we have access to a decent high-resolution clock. 3069163fbbSRichard Henderson In order to make OS-level time accounting work with the RPCC, 3169163fbbSRichard Henderson present it with a well-timed clock fixed at 250MHz. */ 3269163fbbSRichard Henderson return (((uint64_t)env->pcc_ofs << 32) 33bc72ad67SAlex Bligh | (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2)); 3469163fbbSRichard Henderson #else 35bc72ad67SAlex Bligh /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. Just pass through the host cpu 3669163fbbSRichard Henderson clock ticks. Also, don't bother taking PCC_OFS into account. */ 3769163fbbSRichard Henderson return (uint32_t)cpu_get_real_ticks(); 3869163fbbSRichard Henderson #endif 3969163fbbSRichard Henderson } 4069163fbbSRichard Henderson 4169163fbbSRichard Henderson /* PALcode support special instructions */ 4269163fbbSRichard Henderson #ifndef CONFIG_USER_ONLY 4369163fbbSRichard Henderson void helper_hw_ret(CPUAlphaState *env, uint64_t a) 4469163fbbSRichard Henderson { 4569163fbbSRichard Henderson env->pc = a & ~3; 4669163fbbSRichard Henderson env->intr_flag = 0; 4769163fbbSRichard Henderson env->lock_addr = -1; 4869163fbbSRichard Henderson if ((a & 1) == 0) { 4969163fbbSRichard Henderson env->pal_mode = 0; 5069163fbbSRichard Henderson swap_shadow_regs(env); 5169163fbbSRichard Henderson } 5269163fbbSRichard Henderson } 5369163fbbSRichard Henderson 54ba96394eSRichard Henderson void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs) 55ba96394eSRichard Henderson { 56ba96394eSRichard Henderson int pal_mode = env->pal_mode; 57ba96394eSRichard Henderson env->exc_addr = pc | pal_mode; 58ba96394eSRichard Henderson env->pc = env->palbr + entry_ofs; 59ba96394eSRichard Henderson if (!pal_mode) { 60ba96394eSRichard Henderson env->pal_mode = 1; 61ba96394eSRichard Henderson swap_shadow_regs(env); 62ba96394eSRichard Henderson } 63ba96394eSRichard Henderson } 64ba96394eSRichard Henderson 6569163fbbSRichard Henderson void helper_tbia(CPUAlphaState *env) 6669163fbbSRichard Henderson { 6769163fbbSRichard Henderson tlb_flush(env, 1); 6869163fbbSRichard Henderson } 6969163fbbSRichard Henderson 7069163fbbSRichard Henderson void helper_tbis(CPUAlphaState *env, uint64_t p) 7169163fbbSRichard Henderson { 7231b030d4SAndreas Färber tlb_flush_page(CPU(alpha_env_get_cpu(env)), p); 7369163fbbSRichard Henderson } 7469163fbbSRichard Henderson 75a9ead832SRichard Henderson void helper_tb_flush(CPUAlphaState *env) 76a9ead832SRichard Henderson { 77a9ead832SRichard Henderson tb_flush(env); 78a9ead832SRichard Henderson } 79a9ead832SRichard Henderson 8069163fbbSRichard Henderson void helper_halt(uint64_t restart) 8169163fbbSRichard Henderson { 8269163fbbSRichard Henderson if (restart) { 8369163fbbSRichard Henderson qemu_system_reset_request(); 8469163fbbSRichard Henderson } else { 8569163fbbSRichard Henderson qemu_system_shutdown_request(); 8669163fbbSRichard Henderson } 8769163fbbSRichard Henderson } 8869163fbbSRichard Henderson 8919e0cbb8SRichard Henderson uint64_t helper_get_vmtime(void) 9019e0cbb8SRichard Henderson { 91bc72ad67SAlex Bligh return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 9219e0cbb8SRichard Henderson } 9319e0cbb8SRichard Henderson 9419e0cbb8SRichard Henderson uint64_t helper_get_walltime(void) 9569163fbbSRichard Henderson { 96884f17c2SAlex Bligh return qemu_clock_get_ns(rtc_clock); 9769163fbbSRichard Henderson } 9869163fbbSRichard Henderson 9969163fbbSRichard Henderson void helper_set_alarm(CPUAlphaState *env, uint64_t expire) 10069163fbbSRichard Henderson { 101c9245853SAndreas Färber AlphaCPU *cpu = alpha_env_get_cpu(env); 102c9245853SAndreas Färber 10369163fbbSRichard Henderson if (expire) { 10469163fbbSRichard Henderson env->alarm_expire = expire; 105bc72ad67SAlex Bligh timer_mod(cpu->alarm_timer, expire); 10669163fbbSRichard Henderson } else { 107bc72ad67SAlex Bligh timer_del(cpu->alarm_timer); 10869163fbbSRichard Henderson } 10969163fbbSRichard Henderson } 110ba96394eSRichard Henderson 11169163fbbSRichard Henderson #endif /* CONFIG_USER_ONLY */ 112