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