j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 1 | /* |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 2 | * Helpers for loads and stores |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 4 | * Copyright (c) 2007 Jocelyn Mayer |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
Blue Swirl | 8167ee8 | 2009-07-16 20:47:01 +0000 | [diff] [blame] | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 18 | */ |
| 19 | |
Blue Swirl | 3e45717 | 2011-07-13 12:44:15 +0000 | [diff] [blame] | 20 | #include "cpu.h" |
Richard Henderson | 2ef6175 | 2014-04-07 22:31:41 -0700 | [diff] [blame] | 21 | #include "exec/helper-proto.h" |
Paolo Bonzini | f08b617 | 2014-03-28 19:42:10 +0100 | [diff] [blame] | 22 | #include "exec/cpu_ldst.h" |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 23 | |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 24 | /* Softmmu support */ |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 25 | #ifndef CONFIG_USER_ONLY |
| 26 | |
Edgar E. Iglesias | fdfba1a | 2013-11-15 14:46:38 +0100 | [diff] [blame] | 27 | uint64_t helper_ldl_phys(CPUAlphaState *env, uint64_t p) |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 28 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 29 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Edgar E. Iglesias | fdfba1a | 2013-11-15 14:46:38 +0100 | [diff] [blame] | 30 | return (int32_t)ldl_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 31 | } |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 32 | |
Edgar E. Iglesias | 2c17449 | 2013-12-17 14:05:40 +1000 | [diff] [blame] | 33 | uint64_t helper_ldq_phys(CPUAlphaState *env, uint64_t p) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 34 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 35 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Edgar E. Iglesias | 2c17449 | 2013-12-17 14:05:40 +1000 | [diff] [blame] | 36 | return ldq_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 37 | } |
| 38 | |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 39 | uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 40 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 41 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 42 | env->lock_addr = p; |
Edgar E. Iglesias | fdfba1a | 2013-11-15 14:46:38 +0100 | [diff] [blame] | 43 | return env->lock_value = (int32_t)ldl_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 44 | } |
| 45 | |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 46 | uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 47 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 48 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 49 | env->lock_addr = p; |
Edgar E. Iglesias | 2c17449 | 2013-12-17 14:05:40 +1000 | [diff] [blame] | 50 | return env->lock_value = ldq_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 51 | } |
| 52 | |
Edgar E. Iglesias | ab1da85 | 2013-12-17 15:07:29 +1000 | [diff] [blame] | 53 | void helper_stl_phys(CPUAlphaState *env, uint64_t p, uint64_t v) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 54 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 55 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Edgar E. Iglesias | ab1da85 | 2013-12-17 15:07:29 +1000 | [diff] [blame] | 56 | stl_phys(cs->as, p, v); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 57 | } |
| 58 | |
Edgar E. Iglesias | f606604 | 2013-11-28 00:11:44 +0100 | [diff] [blame] | 59 | void helper_stq_phys(CPUAlphaState *env, uint64_t p, uint64_t v) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 60 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 61 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Edgar E. Iglesias | f606604 | 2013-11-28 00:11:44 +0100 | [diff] [blame] | 62 | stq_phys(cs->as, p, v); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 63 | } |
| 64 | |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 65 | uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v) |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 66 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 67 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 68 | uint64_t ret = 0; |
| 69 | |
| 70 | if (p == env->lock_addr) { |
Edgar E. Iglesias | fdfba1a | 2013-11-15 14:46:38 +0100 | [diff] [blame] | 71 | int32_t old = ldl_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 72 | if (old == (int32_t)env->lock_value) { |
Edgar E. Iglesias | ab1da85 | 2013-12-17 15:07:29 +1000 | [diff] [blame] | 73 | stl_phys(cs->as, p, v); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 74 | ret = 1; |
| 75 | } |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 76 | } |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 77 | env->lock_addr = -1; |
aurel32 | 8bb6e98 | 2008-09-30 06:45:44 +0000 | [diff] [blame] | 78 | |
| 79 | return ret; |
| 80 | } |
| 81 | |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 82 | uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v) |
aurel32 | 8bb6e98 | 2008-09-30 06:45:44 +0000 | [diff] [blame] | 83 | { |
Andreas Färber | d2810ff | 2014-03-09 18:58:57 +0100 | [diff] [blame] | 84 | CPUState *cs = CPU(alpha_env_get_cpu(env)); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 85 | uint64_t ret = 0; |
aurel32 | 8bb6e98 | 2008-09-30 06:45:44 +0000 | [diff] [blame] | 86 | |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 87 | if (p == env->lock_addr) { |
Edgar E. Iglesias | 2c17449 | 2013-12-17 14:05:40 +1000 | [diff] [blame] | 88 | uint64_t old = ldq_phys(cs->as, p); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 89 | if (old == env->lock_value) { |
Edgar E. Iglesias | f606604 | 2013-11-28 00:11:44 +0100 | [diff] [blame] | 90 | stq_phys(cs->as, p, v); |
Richard Henderson | 2374e73 | 2011-05-20 13:04:35 -0700 | [diff] [blame] | 91 | ret = 1; |
| 92 | } |
| 93 | } |
| 94 | env->lock_addr = -1; |
aurel32 | 8bb6e98 | 2008-09-30 06:45:44 +0000 | [diff] [blame] | 95 | |
| 96 | return ret; |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Paolo Bonzini | 93e2232 | 2014-03-28 18:14:58 +0100 | [diff] [blame] | 99 | void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr, |
| 100 | int is_write, int is_user, uintptr_t retaddr) |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 101 | { |
Paolo Bonzini | 93e2232 | 2014-03-28 18:14:58 +0100 | [diff] [blame] | 102 | AlphaCPU *cpu = ALPHA_CPU(cs); |
| 103 | CPUAlphaState *env = &cpu->env; |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 104 | uint64_t pc; |
| 105 | uint32_t insn; |
| 106 | |
Blue Swirl | a8a826a | 2012-12-04 20:16:07 +0000 | [diff] [blame] | 107 | if (retaddr) { |
Andreas Färber | 3f38f30 | 2013-09-01 16:51:34 +0200 | [diff] [blame] | 108 | cpu_restore_state(cs, retaddr); |
Blue Swirl | a8a826a | 2012-12-04 20:16:07 +0000 | [diff] [blame] | 109 | } |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 110 | |
| 111 | pc = env->pc; |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 112 | insn = cpu_ldl_code(env, pc); |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 113 | |
| 114 | env->trap_arg0 = addr; |
| 115 | env->trap_arg1 = insn >> 26; /* opcode */ |
| 116 | env->trap_arg2 = (insn >> 21) & 31; /* dest regno */ |
Andreas Färber | 2710342 | 2013-08-26 08:31:06 +0200 | [diff] [blame] | 117 | cs->exception_index = EXCP_UNALIGN; |
Richard Henderson | b9f0923 | 2012-03-24 09:51:08 -0700 | [diff] [blame] | 118 | env->error_code = 0; |
Andreas Färber | 5638d18 | 2013-08-27 17:52:12 +0200 | [diff] [blame] | 119 | cpu_loop_exit(cs); |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 120 | } |
| 121 | |
Andreas Färber | c658b94 | 2013-05-27 06:49:53 +0200 | [diff] [blame] | 122 | void alpha_cpu_unassigned_access(CPUState *cs, hwaddr addr, |
| 123 | bool is_write, bool is_exec, int unused, |
| 124 | unsigned size) |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 125 | { |
Andreas Färber | c658b94 | 2013-05-27 06:49:53 +0200 | [diff] [blame] | 126 | AlphaCPU *cpu = ALPHA_CPU(cs); |
| 127 | CPUAlphaState *env = &cpu->env; |
| 128 | |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 129 | env->trap_arg0 = addr; |
Andreas Färber | c658b94 | 2013-05-27 06:49:53 +0200 | [diff] [blame] | 130 | env->trap_arg1 = is_write ? 1 : 0; |
Blue Swirl | 2050396 | 2012-04-09 14:20:20 +0000 | [diff] [blame] | 131 | dynamic_excp(env, 0, EXCP_MCHK, 0); |
Richard Henderson | 5b45040 | 2011-04-18 16:13:12 -0700 | [diff] [blame] | 132 | } |
| 133 | |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 134 | /* try to fill the TLB and return an exception if error. If retaddr is |
| 135 | NULL, it means that the function was called in C code (i.e. not |
| 136 | from generated code or from helper.c) */ |
| 137 | /* XXX: fix it to restore all registers */ |
Andreas Färber | d5a11fe | 2013-08-27 00:28:06 +0200 | [diff] [blame] | 138 | void tlb_fill(CPUState *cs, target_ulong addr, int is_write, |
Blue Swirl | 2050396 | 2012-04-09 14:20:20 +0000 | [diff] [blame] | 139 | int mmu_idx, uintptr_t retaddr) |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 140 | { |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 141 | int ret; |
| 142 | |
Andreas Färber | d5a11fe | 2013-08-27 00:28:06 +0200 | [diff] [blame] | 143 | ret = alpha_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx); |
Richard Henderson | 2d9671d | 2011-04-25 12:20:27 -0700 | [diff] [blame] | 144 | if (unlikely(ret != 0)) { |
Blue Swirl | a8a826a | 2012-12-04 20:16:07 +0000 | [diff] [blame] | 145 | if (retaddr) { |
Andreas Färber | 3f38f30 | 2013-09-01 16:51:34 +0200 | [diff] [blame] | 146 | cpu_restore_state(cs, retaddr); |
Blue Swirl | a8a826a | 2012-12-04 20:16:07 +0000 | [diff] [blame] | 147 | } |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 148 | /* Exception index and error code are already set */ |
Andreas Färber | 5638d18 | 2013-08-27 17:52:12 +0200 | [diff] [blame] | 149 | cpu_loop_exit(cs); |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 150 | } |
j_mayer | 4c9649a | 2007-04-05 06:58:33 +0000 | [diff] [blame] | 151 | } |
Richard Henderson | c308275 | 2012-03-24 09:51:13 -0700 | [diff] [blame] | 152 | #endif /* CONFIG_USER_ONLY */ |