14c9649a9Sj_mayer /* 2c3082755SRichard Henderson * Helpers for loads and stores 34c9649a9Sj_mayer * 44c9649a9Sj_mayer * Copyright (c) 2007 Jocelyn Mayer 54c9649a9Sj_mayer * 64c9649a9Sj_mayer * This library is free software; you can redistribute it and/or 74c9649a9Sj_mayer * modify it under the terms of the GNU Lesser General Public 84c9649a9Sj_mayer * License as published by the Free Software Foundation; either 94c9649a9Sj_mayer * version 2 of the License, or (at your option) any later version. 104c9649a9Sj_mayer * 114c9649a9Sj_mayer * This library is distributed in the hope that it will be useful, 124c9649a9Sj_mayer * but WITHOUT ANY WARRANTY; without even the implied warranty of 134c9649a9Sj_mayer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 144c9649a9Sj_mayer * Lesser General Public License for more details. 154c9649a9Sj_mayer * 164c9649a9Sj_mayer * You should have received a copy of the GNU Lesser General Public 178167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 184c9649a9Sj_mayer */ 194c9649a9Sj_mayer 203e457172SBlue Swirl #include "cpu.h" 212ef6175aSRichard Henderson #include "exec/helper-proto.h" 224c9649a9Sj_mayer 234c9649a9Sj_mayer 244c9649a9Sj_mayer /* Softmmu support */ 25c3082755SRichard Henderson #ifndef CONFIG_USER_ONLY 26c3082755SRichard Henderson 27fdfba1a2SEdgar E. Iglesias uint64_t helper_ldl_phys(CPUAlphaState *env, uint64_t p) 284c9649a9Sj_mayer { 29d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 30fdfba1a2SEdgar E. Iglesias return (int32_t)ldl_phys(cs->as, p); 314c9649a9Sj_mayer } 324c9649a9Sj_mayer 332c17449bSEdgar E. Iglesias uint64_t helper_ldq_phys(CPUAlphaState *env, uint64_t p) 344c9649a9Sj_mayer { 35d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 362c17449bSEdgar E. Iglesias return ldq_phys(cs->as, p); 378bb6e981Saurel32 } 388bb6e981Saurel32 39c3082755SRichard Henderson uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p) 408bb6e981Saurel32 { 41d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 422374e73eSRichard Henderson env->lock_addr = p; 43fdfba1a2SEdgar E. Iglesias return env->lock_value = (int32_t)ldl_phys(cs->as, p); 448bb6e981Saurel32 } 458bb6e981Saurel32 46c3082755SRichard Henderson uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p) 478bb6e981Saurel32 { 48d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 492374e73eSRichard Henderson env->lock_addr = p; 502c17449bSEdgar E. Iglesias return env->lock_value = ldq_phys(cs->as, p); 518bb6e981Saurel32 } 528bb6e981Saurel32 53ab1da857SEdgar E. Iglesias void helper_stl_phys(CPUAlphaState *env, uint64_t p, uint64_t v) 548bb6e981Saurel32 { 55d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 56ab1da857SEdgar E. Iglesias stl_phys(cs->as, p, v); 578bb6e981Saurel32 } 588bb6e981Saurel32 59f606604fSEdgar E. Iglesias void helper_stq_phys(CPUAlphaState *env, uint64_t p, uint64_t v) 608bb6e981Saurel32 { 61d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 62f606604fSEdgar E. Iglesias stq_phys(cs->as, p, v); 638bb6e981Saurel32 } 648bb6e981Saurel32 65c3082755SRichard Henderson uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v) 668bb6e981Saurel32 { 67d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 682374e73eSRichard Henderson uint64_t ret = 0; 698bb6e981Saurel32 702374e73eSRichard Henderson if (p == env->lock_addr) { 71fdfba1a2SEdgar E. Iglesias int32_t old = ldl_phys(cs->as, p); 722374e73eSRichard Henderson if (old == (int32_t)env->lock_value) { 73ab1da857SEdgar E. Iglesias stl_phys(cs->as, p, v); 748bb6e981Saurel32 ret = 1; 752374e73eSRichard Henderson } 762374e73eSRichard Henderson } 772374e73eSRichard Henderson env->lock_addr = -1; 788bb6e981Saurel32 798bb6e981Saurel32 return ret; 808bb6e981Saurel32 } 818bb6e981Saurel32 82c3082755SRichard Henderson uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v) 838bb6e981Saurel32 { 84d2810ffdSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 852374e73eSRichard Henderson uint64_t ret = 0; 868bb6e981Saurel32 872374e73eSRichard Henderson if (p == env->lock_addr) { 882c17449bSEdgar E. Iglesias uint64_t old = ldq_phys(cs->as, p); 892374e73eSRichard Henderson if (old == env->lock_value) { 90f606604fSEdgar E. Iglesias stq_phys(cs->as, p, v); 918bb6e981Saurel32 ret = 1; 922374e73eSRichard Henderson } 932374e73eSRichard Henderson } 942374e73eSRichard Henderson env->lock_addr = -1; 958bb6e981Saurel32 968bb6e981Saurel32 return ret; 974c9649a9Sj_mayer } 984c9649a9Sj_mayer 9993e22326SPaolo Bonzini void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr, 10020503968SBlue Swirl int is_write, int is_user, uintptr_t retaddr) 1015b450407SRichard Henderson { 10293e22326SPaolo Bonzini AlphaCPU *cpu = ALPHA_CPU(cs); 10393e22326SPaolo Bonzini CPUAlphaState *env = &cpu->env; 1045b450407SRichard Henderson uint64_t pc; 1055b450407SRichard Henderson uint32_t insn; 1065b450407SRichard Henderson 107a8a826a3SBlue Swirl if (retaddr) { 1083f38f309SAndreas Färber cpu_restore_state(cs, retaddr); 109a8a826a3SBlue Swirl } 1105b450407SRichard Henderson 1115b450407SRichard Henderson pc = env->pc; 112c3082755SRichard Henderson insn = cpu_ldl_code(env, pc); 1135b450407SRichard Henderson 1145b450407SRichard Henderson env->trap_arg0 = addr; 1155b450407SRichard Henderson env->trap_arg1 = insn >> 26; /* opcode */ 1165b450407SRichard Henderson env->trap_arg2 = (insn >> 21) & 31; /* dest regno */ 11727103424SAndreas Färber cs->exception_index = EXCP_UNALIGN; 118b9f0923eSRichard Henderson env->error_code = 0; 1195638d180SAndreas Färber cpu_loop_exit(cs); 1205b450407SRichard Henderson } 1215b450407SRichard Henderson 122c658b94fSAndreas Färber void alpha_cpu_unassigned_access(CPUState *cs, hwaddr addr, 123c658b94fSAndreas Färber bool is_write, bool is_exec, int unused, 124c658b94fSAndreas Färber unsigned size) 1255b450407SRichard Henderson { 126c658b94fSAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 127c658b94fSAndreas Färber CPUAlphaState *env = &cpu->env; 128c658b94fSAndreas Färber 1295b450407SRichard Henderson env->trap_arg0 = addr; 130c658b94fSAndreas Färber env->trap_arg1 = is_write ? 1 : 0; 13120503968SBlue Swirl dynamic_excp(env, 0, EXCP_MCHK, 0); 1325b450407SRichard Henderson } 1335b450407SRichard Henderson 134022c62cbSPaolo Bonzini #include "exec/softmmu_exec.h" 1353e457172SBlue Swirl 1364c9649a9Sj_mayer #define MMUSUFFIX _mmu 1375b450407SRichard Henderson #define ALIGNED_ONLY 1384c9649a9Sj_mayer 1394c9649a9Sj_mayer #define SHIFT 0 140022c62cbSPaolo Bonzini #include "exec/softmmu_template.h" 1414c9649a9Sj_mayer 1424c9649a9Sj_mayer #define SHIFT 1 143022c62cbSPaolo Bonzini #include "exec/softmmu_template.h" 1444c9649a9Sj_mayer 1454c9649a9Sj_mayer #define SHIFT 2 146022c62cbSPaolo Bonzini #include "exec/softmmu_template.h" 1474c9649a9Sj_mayer 1484c9649a9Sj_mayer #define SHIFT 3 149022c62cbSPaolo Bonzini #include "exec/softmmu_template.h" 1504c9649a9Sj_mayer 1514c9649a9Sj_mayer /* try to fill the TLB and return an exception if error. If retaddr is 1524c9649a9Sj_mayer NULL, it means that the function was called in C code (i.e. not 1534c9649a9Sj_mayer from generated code or from helper.c) */ 1544c9649a9Sj_mayer /* XXX: fix it to restore all registers */ 155d5a11fefSAndreas Färber void tlb_fill(CPUState *cs, target_ulong addr, int is_write, 15620503968SBlue Swirl int mmu_idx, uintptr_t retaddr) 1574c9649a9Sj_mayer { 1584c9649a9Sj_mayer int ret; 1594c9649a9Sj_mayer 160d5a11fefSAndreas Färber ret = alpha_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx); 1612d9671d3SRichard Henderson if (unlikely(ret != 0)) { 162a8a826a3SBlue Swirl if (retaddr) { 1633f38f309SAndreas Färber cpu_restore_state(cs, retaddr); 164a8a826a3SBlue Swirl } 1654c9649a9Sj_mayer /* Exception index and error code are already set */ 1665638d180SAndreas Färber cpu_loop_exit(cs); 1674c9649a9Sj_mayer } 1684c9649a9Sj_mayer } 169c3082755SRichard Henderson #endif /* CONFIG_USER_ONLY */ 170