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 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 cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) 63 { 64 uint64_t reserved; 65 target_ulong cb = 0; 66 67 /* Do not allow reserved bits to be set. */ 68 if (hppa_is_pa20(env)) { 69 reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4); 70 reserved |= PSW_G; /* PA1.x only */ 71 reserved |= PSW_E; /* not implemented */ 72 } else { 73 reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2); 74 reserved |= PSW_O | PSW_W; /* PA2.0 only */ 75 reserved |= PSW_E | PSW_Y | PSW_Z; /* not implemented */ 76 } 77 psw &= ~reserved; 78 79 env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB); 80 env->psw_xb = psw & (PSW_X | PSW_B); 81 env->psw_n = (psw / PSW_N) & 1; 82 env->psw_v = -((psw / PSW_V) & 1); 83 84 env->psw_cb_msb = (psw >> 39) & 1; 85 cb |= ((psw >> 38) & 1) << 60; 86 cb |= ((psw >> 37) & 1) << 56; 87 cb |= ((psw >> 36) & 1) << 52; 88 cb |= ((psw >> 35) & 1) << 48; 89 cb |= ((psw >> 34) & 1) << 44; 90 cb |= ((psw >> 33) & 1) << 40; 91 cb |= ((psw >> 32) & 1) << 36; 92 cb |= ((psw >> 15) & 1) << 32; 93 cb |= ((psw >> 14) & 1) << 28; 94 cb |= ((psw >> 13) & 1) << 24; 95 cb |= ((psw >> 12) & 1) << 20; 96 cb |= ((psw >> 11) & 1) << 16; 97 cb |= ((psw >> 10) & 1) << 12; 98 cb |= ((psw >> 9) & 1) << 8; 99 cb |= ((psw >> 8) & 1) << 4; 100 env->psw_cb = cb; 101 } 102 103 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) 104 { 105 #ifndef CONFIG_USER_ONLY 106 static const char cr_name[32][5] = { 107 "RC", "CR1", "CR2", "CR3", 108 "CR4", "CR5", "CR6", "CR7", 109 "PID1", "PID2", "CCR", "SAR", 110 "PID3", "PID4", "IVA", "EIEM", 111 "ITMR", "ISQF", "IOQF", "IIR", 112 "ISR", "IOR", "IPSW", "EIRR", 113 "TR0", "TR1", "TR2", "TR3", 114 "TR4", "TR5", "TR6", "TR7", 115 }; 116 #endif 117 118 CPUHPPAState *env = cpu_env(cs); 119 target_ulong psw = cpu_hppa_get_psw(env); 120 target_ulong psw_cb; 121 char psw_c[20]; 122 int i, w; 123 uint64_t m; 124 125 if (hppa_is_pa20(env)) { 126 w = 16; 127 m = UINT64_MAX; 128 } else { 129 w = 8; 130 m = UINT32_MAX; 131 } 132 133 qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n" 134 "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n", 135 env->iasq_f >> 32, w, m & env->iaoq_f, 136 hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), 137 env->iasq_b >> 32, w, m & env->iaoq_b, 138 hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b)); 139 140 psw_c[0] = (psw & PSW_W ? 'W' : '-'); 141 psw_c[1] = (psw & PSW_E ? 'E' : '-'); 142 psw_c[2] = (psw & PSW_S ? 'S' : '-'); 143 psw_c[3] = (psw & PSW_T ? 'T' : '-'); 144 psw_c[4] = (psw & PSW_H ? 'H' : '-'); 145 psw_c[5] = (psw & PSW_L ? 'L' : '-'); 146 psw_c[6] = (psw & PSW_N ? 'N' : '-'); 147 psw_c[7] = (psw & PSW_X ? 'X' : '-'); 148 psw_c[8] = (psw & PSW_B ? 'B' : '-'); 149 psw_c[9] = (psw & PSW_C ? 'C' : '-'); 150 psw_c[10] = (psw & PSW_V ? 'V' : '-'); 151 psw_c[11] = (psw & PSW_M ? 'M' : '-'); 152 psw_c[12] = (psw & PSW_F ? 'F' : '-'); 153 psw_c[13] = (psw & PSW_R ? 'R' : '-'); 154 psw_c[14] = (psw & PSW_Q ? 'Q' : '-'); 155 psw_c[15] = (psw & PSW_P ? 'P' : '-'); 156 psw_c[16] = (psw & PSW_D ? 'D' : '-'); 157 psw_c[17] = (psw & PSW_I ? 'I' : '-'); 158 psw_c[18] = '\0'; 159 psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull) 160 | (env->psw_cb_msb << 60); 161 162 qemu_fprintf(f, "PSW %0*" PRIx64 " CB %0*" PRIx64 " %s\n", 163 w, m & psw, w, m & psw_cb, psw_c); 164 165 for (i = 0; i < 32; i++) { 166 qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c", 167 i, w, m & env->gr[i], 168 (i & 3) == 3 ? '\n' : ' '); 169 } 170 #ifndef CONFIG_USER_ONLY 171 for (i = 0; i < 32; i++) { 172 qemu_fprintf(f, "%-4s %0*" PRIx64 "%c", 173 cr_name[i], w, m & env->cr[i], 174 (i & 3) == 3 ? '\n' : ' '); 175 } 176 qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n", 177 w, m & env->cr_back[0], w, m & env->cr_back[1]); 178 for (i = 0; i < 8; i++) { 179 qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32), 180 (i & 3) == 3 ? '\n' : ' '); 181 } 182 #endif 183 184 if (flags & CPU_DUMP_FPU) { 185 static const char rm[4][4] = { "RN", "RZ", "R+", "R-" }; 186 char flg[6], ena[6]; 187 uint32_t fpsr = env->fr0_shadow; 188 189 flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-'); 190 flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-'); 191 flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-'); 192 flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-'); 193 flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-'); 194 flg[5] = '\0'; 195 196 ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-'); 197 ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-'); 198 ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-'); 199 ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-'); 200 ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-'); 201 ena[5] = '\0'; 202 203 qemu_fprintf(f, "FPSR %08x flag %s enable %s %s\n", 204 fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]); 205 206 for (i = 0; i < 32; i++) { 207 qemu_fprintf(f, "FR%02d %016" PRIx64 "%c", 208 i, env->fr[i], (i & 3) == 3 ? '\n' : ' '); 209 } 210 } 211 212 qemu_fprintf(f, "\n"); 213 } 214