1 /* 2 * HPPA emulation cpu helpers for qemu. 3 * 4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 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.1 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 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "qemu/log.h" 22 #include "cpu.h" 23 #include "fpu/softfloat.h" 24 #include "exec/exec-all.h" 25 #include "exec/helper-proto.h" 26 #include "qemu/qemu-print.h" 27 #include "hw/hppa/hppa_hardware.h" 28 29 target_ulong cpu_hppa_get_psw(CPUHPPAState *env) 30 { 31 target_ulong psw; 32 target_ulong mask1 = (target_ulong)-1 / 0xf; 33 target_ulong maskf = (target_ulong)-1 / 0xffff * 0xf; 34 35 /* Fold carry bits down to 8 consecutive bits. */ 36 /* ^^^b^^^c^^^d^^^e^^^f^^^g^^^h^^^i^^^j^^^k^^^l^^^m^^^n^^^o^^^p^^^^ */ 37 psw = (env->psw_cb >> 4) & mask1; 38 /* .......b...c...d...e...f...g...h...i...j...k...l...m...n...o...p */ 39 psw |= psw >> 3; 40 /* .......b..bc..cd..de..ef..fg..gh..hi..ij..jk..kl..lm..mn..no..op */ 41 psw |= psw >> 6; 42 psw &= maskf; 43 /* .............bcd............efgh............ijkl............mnop */ 44 psw |= psw >> 12; 45 /* .............bcd.........bcdefgh........efghijkl........ijklmnop */ 46 psw |= env->psw_cb_msb << 39; 47 /* .............bcd........abcdefgh........efghijkl........ijklmnop */ 48 49 /* For hppa64, the two 8-bit fields are discontiguous. */ 50 if (hppa_is_pa20(env)) { 51 psw = (psw & 0xff00000000ull) | ((psw & 0xff) << 8); 52 } else { 53 psw = (psw & 0xff) << 8; 54 } 55 56 psw |= env->psw_n * PSW_N; 57 psw |= ((env->psw_v >> 31) & 1) * PSW_V; 58 psw |= env->psw | env->psw_xb; 59 60 return psw; 61 } 62 63 void update_gva_offset_mask(CPUHPPAState *env) 64 { 65 uint64_t gom; 66 67 if (env->psw & PSW_W) { 68 gom = (env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE) 69 ? MAKE_64BIT_MASK(0, 62) & 70 ~((uint64_t)HPPA64_PDC_CACHE_RET_SPID_VAL << 48) 71 : MAKE_64BIT_MASK(0, 62); 72 } else { 73 gom = MAKE_64BIT_MASK(0, 32); 74 } 75 76 env->gva_offset_mask = gom; 77 } 78 79 void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) 80 { 81 uint64_t reserved; 82 target_ulong cb = 0; 83 84 /* Do not allow reserved bits to be set. */ 85 if (hppa_is_pa20(env)) { 86 reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4); 87 reserved |= PSW_G; /* PA1.x only */ 88 reserved |= PSW_E; /* not implemented */ 89 } else { 90 reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2); 91 reserved |= PSW_O | PSW_W; /* PA2.0 only */ 92 reserved |= PSW_E | PSW_Y | PSW_Z; /* not implemented */ 93 } 94 psw &= ~reserved; 95 96 env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB); 97 env->psw_xb = psw & (PSW_X | PSW_B); 98 env->psw_n = (psw / PSW_N) & 1; 99 env->psw_v = -((psw / PSW_V) & 1); 100 101 env->psw_cb_msb = (psw >> 39) & 1; 102 cb |= ((psw >> 38) & 1) << 60; 103 cb |= ((psw >> 37) & 1) << 56; 104 cb |= ((psw >> 36) & 1) << 52; 105 cb |= ((psw >> 35) & 1) << 48; 106 cb |= ((psw >> 34) & 1) << 44; 107 cb |= ((psw >> 33) & 1) << 40; 108 cb |= ((psw >> 32) & 1) << 36; 109 cb |= ((psw >> 15) & 1) << 32; 110 cb |= ((psw >> 14) & 1) << 28; 111 cb |= ((psw >> 13) & 1) << 24; 112 cb |= ((psw >> 12) & 1) << 20; 113 cb |= ((psw >> 11) & 1) << 16; 114 cb |= ((psw >> 10) & 1) << 12; 115 cb |= ((psw >> 9) & 1) << 8; 116 cb |= ((psw >> 8) & 1) << 4; 117 env->psw_cb = cb; 118 119 update_gva_offset_mask(env); 120 } 121 122 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) 123 { 124 #ifndef CONFIG_USER_ONLY 125 static const char cr_name[32][5] = { 126 "RC", "CR1", "CR2", "CR3", 127 "CR4", "CR5", "CR6", "CR7", 128 "PID1", "PID2", "CCR", "SAR", 129 "PID3", "PID4", "IVA", "EIEM", 130 "ITMR", "ISQF", "IOQF", "IIR", 131 "ISR", "IOR", "IPSW", "EIRR", 132 "TR0", "TR1", "TR2", "TR3", 133 "TR4", "TR5", "TR6", "TR7", 134 }; 135 #endif 136 137 CPUHPPAState *env = cpu_env(cs); 138 target_ulong psw = cpu_hppa_get_psw(env); 139 target_ulong psw_cb; 140 char psw_c[20]; 141 int i, w; 142 uint64_t m; 143 144 if (hppa_is_pa20(env)) { 145 w = 16; 146 m = UINT64_MAX; 147 } else { 148 w = 8; 149 m = UINT32_MAX; 150 } 151 152 qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n" 153 "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n", 154 env->iasq_f >> 32, w, m & env->iaoq_f, 155 hppa_form_gva_mask(env->gva_offset_mask, env->iasq_f, 156 env->iaoq_f), 157 env->iasq_b >> 32, w, m & env->iaoq_b, 158 hppa_form_gva_mask(env->gva_offset_mask, env->iasq_b, 159 env->iaoq_b)); 160 161 psw_c[0] = (psw & PSW_W ? 'W' : '-'); 162 psw_c[1] = (psw & PSW_E ? 'E' : '-'); 163 psw_c[2] = (psw & PSW_S ? 'S' : '-'); 164 psw_c[3] = (psw & PSW_T ? 'T' : '-'); 165 psw_c[4] = (psw & PSW_H ? 'H' : '-'); 166 psw_c[5] = (psw & PSW_L ? 'L' : '-'); 167 psw_c[6] = (psw & PSW_N ? 'N' : '-'); 168 psw_c[7] = (psw & PSW_X ? 'X' : '-'); 169 psw_c[8] = (psw & PSW_B ? 'B' : '-'); 170 psw_c[9] = (psw & PSW_C ? 'C' : '-'); 171 psw_c[10] = (psw & PSW_V ? 'V' : '-'); 172 psw_c[11] = (psw & PSW_M ? 'M' : '-'); 173 psw_c[12] = (psw & PSW_F ? 'F' : '-'); 174 psw_c[13] = (psw & PSW_R ? 'R' : '-'); 175 psw_c[14] = (psw & PSW_Q ? 'Q' : '-'); 176 psw_c[15] = (psw & PSW_P ? 'P' : '-'); 177 psw_c[16] = (psw & PSW_D ? 'D' : '-'); 178 psw_c[17] = (psw & PSW_I ? 'I' : '-'); 179 psw_c[18] = '\0'; 180 psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull) 181 | (env->psw_cb_msb << 60); 182 183 qemu_fprintf(f, "PSW %0*" PRIx64 " CB %0*" PRIx64 " %s\n", 184 w, m & psw, w, m & psw_cb, psw_c); 185 186 for (i = 0; i < 32; i++) { 187 qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c", 188 i, w, m & env->gr[i], 189 (i & 3) == 3 ? '\n' : ' '); 190 } 191 #ifndef CONFIG_USER_ONLY 192 for (i = 0; i < 32; i++) { 193 qemu_fprintf(f, "%-4s %0*" PRIx64 "%c", 194 cr_name[i], w, m & env->cr[i], 195 (i & 3) == 3 ? '\n' : ' '); 196 } 197 qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n", 198 w, m & env->cr_back[0], w, m & env->cr_back[1]); 199 for (i = 0; i < 8; i++) { 200 qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32), 201 (i & 3) == 3 ? '\n' : ' '); 202 } 203 #endif 204 205 if (flags & CPU_DUMP_FPU) { 206 static const char rm[4][4] = { "RN", "RZ", "R+", "R-" }; 207 char flg[6], ena[6]; 208 uint32_t fpsr = env->fr0_shadow; 209 210 flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-'); 211 flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-'); 212 flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-'); 213 flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-'); 214 flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-'); 215 flg[5] = '\0'; 216 217 ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-'); 218 ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-'); 219 ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-'); 220 ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-'); 221 ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-'); 222 ena[5] = '\0'; 223 224 qemu_fprintf(f, "FPSR %08x flag %s enable %s %s\n", 225 fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]); 226 227 for (i = 0; i < 32; i++) { 228 qemu_fprintf(f, "FR%02d %016" PRIx64 "%c", 229 i, env->fr[i], (i & 3) == 3 ? '\n' : ' '); 230 } 231 } 232 233 qemu_fprintf(f, "\n"); 234 } 235