161766fe9SRichard Henderson /* 261766fe9SRichard Henderson * HPPA emulation cpu helpers for qemu. 361766fe9SRichard Henderson * 461766fe9SRichard Henderson * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 561766fe9SRichard Henderson * 661766fe9SRichard Henderson * This library is free software; you can redistribute it and/or 761766fe9SRichard Henderson * modify it under the terms of the GNU Lesser General Public 861766fe9SRichard Henderson * License as published by the Free Software Foundation; either 9d6ea4236SChetan Pant * version 2.1 of the License, or (at your option) any later version. 1061766fe9SRichard Henderson * 1161766fe9SRichard Henderson * This library is distributed in the hope that it will be useful, 1261766fe9SRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 1361766fe9SRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1461766fe9SRichard Henderson * Lesser General Public License for more details. 1561766fe9SRichard Henderson * 1661766fe9SRichard Henderson * You should have received a copy of the GNU Lesser General Public 1761766fe9SRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1861766fe9SRichard Henderson */ 1961766fe9SRichard Henderson 2061766fe9SRichard Henderson #include "qemu/osdep.h" 21cd617484SPhilippe Mathieu-Daudé #include "qemu/log.h" 2261766fe9SRichard Henderson #include "cpu.h" 2361766fe9SRichard Henderson #include "fpu/softfloat.h" 24d5de20bdSSven Schnelle #include "exec/exec-all.h" 2561766fe9SRichard Henderson #include "exec/helper-proto.h" 2690c84c56SMarkus Armbruster #include "qemu/qemu-print.h" 27*644ce5dfSHelge Deller #include "hw/hppa/hppa_hardware.h" 2861766fe9SRichard Henderson 29c53e401eSRichard Henderson target_ulong cpu_hppa_get_psw(CPUHPPAState *env) 3061766fe9SRichard Henderson { 31c53e401eSRichard Henderson target_ulong psw; 32c53e401eSRichard Henderson target_ulong mask1 = (target_ulong)-1 / 0xf; 33c53e401eSRichard Henderson target_ulong maskf = (target_ulong)-1 / 0xffff * 0xf; 3461766fe9SRichard Henderson 3561766fe9SRichard Henderson /* Fold carry bits down to 8 consecutive bits. */ 36931adff3SRichard Henderson /* ^^^b^^^c^^^d^^^e^^^f^^^g^^^h^^^i^^^j^^^k^^^l^^^m^^^n^^^o^^^p^^^^ */ 37931adff3SRichard Henderson psw = (env->psw_cb >> 4) & mask1; 38931adff3SRichard Henderson /* .......b...c...d...e...f...g...h...i...j...k...l...m...n...o...p */ 3961766fe9SRichard Henderson psw |= psw >> 3; 40931adff3SRichard Henderson /* .......b..bc..cd..de..ef..fg..gh..hi..ij..jk..kl..lm..mn..no..op */ 41931adff3SRichard Henderson psw |= psw >> 6; 42931adff3SRichard Henderson psw &= maskf; 43931adff3SRichard Henderson /* .............bcd............efgh............ijkl............mnop */ 44931adff3SRichard Henderson psw |= psw >> 12; 45931adff3SRichard Henderson /* .............bcd.........bcdefgh........efghijkl........ijklmnop */ 46c53e401eSRichard Henderson psw |= env->psw_cb_msb << 39; 47931adff3SRichard Henderson /* .............bcd........abcdefgh........efghijkl........ijklmnop */ 48931adff3SRichard Henderson 49931adff3SRichard Henderson /* For hppa64, the two 8-bit fields are discontiguous. */ 50931adff3SRichard Henderson if (hppa_is_pa20(env)) { 51931adff3SRichard Henderson psw = (psw & 0xff00000000ull) | ((psw & 0xff) << 8); 52931adff3SRichard Henderson } else { 53fa57e327SRichard Henderson psw = (psw & 0xff) << 8; 54931adff3SRichard Henderson } 5561766fe9SRichard Henderson 56fa57e327SRichard Henderson psw |= env->psw_n * PSW_N; 57ead5078cSHelge Deller psw |= ((env->psw_v >> 31) & 1) * PSW_V; 58ebc9401aSRichard Henderson psw |= env->psw | env->psw_xb; 5961766fe9SRichard Henderson 6061766fe9SRichard Henderson return psw; 6161766fe9SRichard Henderson } 6261766fe9SRichard Henderson 63*644ce5dfSHelge Deller void update_gva_offset_mask(CPUHPPAState *env) 64*644ce5dfSHelge Deller { 65*644ce5dfSHelge Deller uint64_t gom; 66*644ce5dfSHelge Deller 67*644ce5dfSHelge Deller if (env->psw & PSW_W) { 68*644ce5dfSHelge Deller gom = (env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE) 69*644ce5dfSHelge Deller ? MAKE_64BIT_MASK(0, 62) & 70*644ce5dfSHelge Deller ~((uint64_t)HPPA64_PDC_CACHE_RET_SPID_VAL << 48) 71*644ce5dfSHelge Deller : MAKE_64BIT_MASK(0, 62); 72*644ce5dfSHelge Deller } else { 73*644ce5dfSHelge Deller gom = MAKE_64BIT_MASK(0, 32); 74*644ce5dfSHelge Deller } 75*644ce5dfSHelge Deller 76*644ce5dfSHelge Deller env->gva_offset_mask = gom; 77*644ce5dfSHelge Deller } 78*644ce5dfSHelge Deller 79c53e401eSRichard Henderson void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) 8061766fe9SRichard Henderson { 81931adff3SRichard Henderson uint64_t reserved; 82c53e401eSRichard Henderson target_ulong cb = 0; 8361766fe9SRichard Henderson 84931adff3SRichard Henderson /* Do not allow reserved bits to be set. */ 85931adff3SRichard Henderson if (hppa_is_pa20(env)) { 86931adff3SRichard Henderson reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4); 87931adff3SRichard Henderson reserved |= PSW_G; /* PA1.x only */ 88931adff3SRichard Henderson reserved |= PSW_E; /* not implemented */ 89931adff3SRichard Henderson } else { 90931adff3SRichard Henderson reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2); 91931adff3SRichard Henderson reserved |= PSW_O | PSW_W; /* PA2.0 only */ 92931adff3SRichard Henderson reserved |= PSW_E | PSW_Y | PSW_Z; /* not implemented */ 93931adff3SRichard Henderson } 94931adff3SRichard Henderson psw &= ~reserved; 95931adff3SRichard Henderson 96ebc9401aSRichard Henderson env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB); 97ebc9401aSRichard Henderson env->psw_xb = psw & (PSW_X | PSW_B); 98fa57e327SRichard Henderson env->psw_n = (psw / PSW_N) & 1; 99fa57e327SRichard Henderson env->psw_v = -((psw / PSW_V) & 1); 10061766fe9SRichard Henderson 101931adff3SRichard Henderson env->psw_cb_msb = (psw >> 39) & 1; 102931adff3SRichard Henderson cb |= ((psw >> 38) & 1) << 60; 103931adff3SRichard Henderson cb |= ((psw >> 37) & 1) << 56; 104931adff3SRichard Henderson cb |= ((psw >> 36) & 1) << 52; 105931adff3SRichard Henderson cb |= ((psw >> 35) & 1) << 48; 106931adff3SRichard Henderson cb |= ((psw >> 34) & 1) << 44; 107931adff3SRichard Henderson cb |= ((psw >> 33) & 1) << 40; 108931adff3SRichard Henderson cb |= ((psw >> 32) & 1) << 36; 109931adff3SRichard Henderson cb |= ((psw >> 15) & 1) << 32; 11061766fe9SRichard Henderson cb |= ((psw >> 14) & 1) << 28; 11161766fe9SRichard Henderson cb |= ((psw >> 13) & 1) << 24; 11261766fe9SRichard Henderson cb |= ((psw >> 12) & 1) << 20; 11361766fe9SRichard Henderson cb |= ((psw >> 11) & 1) << 16; 11461766fe9SRichard Henderson cb |= ((psw >> 10) & 1) << 12; 11561766fe9SRichard Henderson cb |= ((psw >> 9) & 1) << 8; 11661766fe9SRichard Henderson cb |= ((psw >> 8) & 1) << 4; 11761766fe9SRichard Henderson env->psw_cb = cb; 118*644ce5dfSHelge Deller 119*644ce5dfSHelge Deller update_gva_offset_mask(env); 12061766fe9SRichard Henderson } 12161766fe9SRichard Henderson 12290c84c56SMarkus Armbruster void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) 12361766fe9SRichard Henderson { 124d2e22fdeSRichard Henderson #ifndef CONFIG_USER_ONLY 125d2e22fdeSRichard Henderson static const char cr_name[32][5] = { 126d2e22fdeSRichard Henderson "RC", "CR1", "CR2", "CR3", 127d2e22fdeSRichard Henderson "CR4", "CR5", "CR6", "CR7", 128d2e22fdeSRichard Henderson "PID1", "PID2", "CCR", "SAR", 129d2e22fdeSRichard Henderson "PID3", "PID4", "IVA", "EIEM", 130d2e22fdeSRichard Henderson "ITMR", "ISQF", "IOQF", "IIR", 131d2e22fdeSRichard Henderson "ISR", "IOR", "IPSW", "EIRR", 132d2e22fdeSRichard Henderson "TR0", "TR1", "TR2", "TR3", 133d2e22fdeSRichard Henderson "TR4", "TR5", "TR6", "TR7", 134d2e22fdeSRichard Henderson }; 135d2e22fdeSRichard Henderson #endif 136d2e22fdeSRichard Henderson 1375718fe4cSRichard Henderson CPUHPPAState *env = cpu_env(cs); 138c53e401eSRichard Henderson target_ulong psw = cpu_hppa_get_psw(env); 139c53e401eSRichard Henderson target_ulong psw_cb; 140fa57e327SRichard Henderson char psw_c[20]; 1415718fe4cSRichard Henderson int i, w; 1425718fe4cSRichard Henderson uint64_t m; 1435718fe4cSRichard Henderson 1445718fe4cSRichard Henderson if (hppa_is_pa20(env)) { 1455718fe4cSRichard Henderson w = 16; 1465718fe4cSRichard Henderson m = UINT64_MAX; 1475718fe4cSRichard Henderson } else { 1485718fe4cSRichard Henderson w = 8; 1495718fe4cSRichard Henderson m = UINT32_MAX; 1505718fe4cSRichard Henderson } 15161766fe9SRichard Henderson 152d2e22fdeSRichard Henderson qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n" 153d2e22fdeSRichard Henderson "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n", 154d2e22fdeSRichard Henderson env->iasq_f >> 32, w, m & env->iaoq_f, 155*644ce5dfSHelge Deller hppa_form_gva_mask(env->gva_offset_mask, env->iasq_f, 156*644ce5dfSHelge Deller env->iaoq_f), 157d2e22fdeSRichard Henderson env->iasq_b >> 32, w, m & env->iaoq_b, 158*644ce5dfSHelge Deller hppa_form_gva_mask(env->gva_offset_mask, env->iasq_b, 159*644ce5dfSHelge Deller env->iaoq_b)); 160fa57e327SRichard Henderson 161fa57e327SRichard Henderson psw_c[0] = (psw & PSW_W ? 'W' : '-'); 162fa57e327SRichard Henderson psw_c[1] = (psw & PSW_E ? 'E' : '-'); 163fa57e327SRichard Henderson psw_c[2] = (psw & PSW_S ? 'S' : '-'); 164fa57e327SRichard Henderson psw_c[3] = (psw & PSW_T ? 'T' : '-'); 165fa57e327SRichard Henderson psw_c[4] = (psw & PSW_H ? 'H' : '-'); 166fa57e327SRichard Henderson psw_c[5] = (psw & PSW_L ? 'L' : '-'); 167fa57e327SRichard Henderson psw_c[6] = (psw & PSW_N ? 'N' : '-'); 168fa57e327SRichard Henderson psw_c[7] = (psw & PSW_X ? 'X' : '-'); 169fa57e327SRichard Henderson psw_c[8] = (psw & PSW_B ? 'B' : '-'); 170fa57e327SRichard Henderson psw_c[9] = (psw & PSW_C ? 'C' : '-'); 171fa57e327SRichard Henderson psw_c[10] = (psw & PSW_V ? 'V' : '-'); 172fa57e327SRichard Henderson psw_c[11] = (psw & PSW_M ? 'M' : '-'); 173fa57e327SRichard Henderson psw_c[12] = (psw & PSW_F ? 'F' : '-'); 174fa57e327SRichard Henderson psw_c[13] = (psw & PSW_R ? 'R' : '-'); 175fa57e327SRichard Henderson psw_c[14] = (psw & PSW_Q ? 'Q' : '-'); 176fa57e327SRichard Henderson psw_c[15] = (psw & PSW_P ? 'P' : '-'); 177fa57e327SRichard Henderson psw_c[16] = (psw & PSW_D ? 'D' : '-'); 178fa57e327SRichard Henderson psw_c[17] = (psw & PSW_I ? 'I' : '-'); 179fa57e327SRichard Henderson psw_c[18] = '\0'; 180c53e401eSRichard Henderson psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull) 181c53e401eSRichard Henderson | (env->psw_cb_msb << 60); 182fa57e327SRichard Henderson 1835718fe4cSRichard Henderson qemu_fprintf(f, "PSW %0*" PRIx64 " CB %0*" PRIx64 " %s\n", 1845718fe4cSRichard Henderson w, m & psw, w, m & psw_cb, psw_c); 185fa57e327SRichard Henderson 186fa57e327SRichard Henderson for (i = 0; i < 32; i++) { 1875718fe4cSRichard Henderson qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c", 1885718fe4cSRichard Henderson i, w, m & env->gr[i], 18933423472SRichard Henderson (i & 3) == 3 ? '\n' : ' '); 19061766fe9SRichard Henderson } 19133423472SRichard Henderson #ifndef CONFIG_USER_ONLY 192d2e22fdeSRichard Henderson for (i = 0; i < 32; i++) { 193d2e22fdeSRichard Henderson qemu_fprintf(f, "%-4s %0*" PRIx64 "%c", 194d2e22fdeSRichard Henderson cr_name[i], w, m & env->cr[i], 195d2e22fdeSRichard Henderson (i & 3) == 3 ? '\n' : ' '); 196d2e22fdeSRichard Henderson } 197d2e22fdeSRichard Henderson qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n", 198d2e22fdeSRichard Henderson w, m & env->cr_back[0], w, m & env->cr_back[1]); 19933423472SRichard Henderson for (i = 0; i < 8; i++) { 20090c84c56SMarkus Armbruster qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32), 20133423472SRichard Henderson (i & 3) == 3 ? '\n' : ' '); 20261766fe9SRichard Henderson } 20333423472SRichard Henderson #endif 20461766fe9SRichard Henderson 205d2e22fdeSRichard Henderson if (flags & CPU_DUMP_FPU) { 206d2e22fdeSRichard Henderson static const char rm[4][4] = { "RN", "RZ", "R+", "R-" }; 207d2e22fdeSRichard Henderson char flg[6], ena[6]; 208d2e22fdeSRichard Henderson uint32_t fpsr = env->fr0_shadow; 209d2e22fdeSRichard Henderson 210d2e22fdeSRichard Henderson flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-'); 211d2e22fdeSRichard Henderson flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-'); 212d2e22fdeSRichard Henderson flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-'); 213d2e22fdeSRichard Henderson flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-'); 214d2e22fdeSRichard Henderson flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-'); 215d2e22fdeSRichard Henderson flg[5] = '\0'; 216d2e22fdeSRichard Henderson 217d2e22fdeSRichard Henderson ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-'); 218d2e22fdeSRichard Henderson ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-'); 219d2e22fdeSRichard Henderson ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-'); 220d2e22fdeSRichard Henderson ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-'); 221d2e22fdeSRichard Henderson ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-'); 222d2e22fdeSRichard Henderson ena[5] = '\0'; 223d2e22fdeSRichard Henderson 224d2e22fdeSRichard Henderson qemu_fprintf(f, "FPSR %08x flag %s enable %s %s\n", 225d2e22fdeSRichard Henderson fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]); 226d2e22fdeSRichard Henderson 227d2e22fdeSRichard Henderson for (i = 0; i < 32; i++) { 228d2e22fdeSRichard Henderson qemu_fprintf(f, "FR%02d %016" PRIx64 "%c", 229d2e22fdeSRichard Henderson i, env->fr[i], (i & 3) == 3 ? '\n' : ' '); 230d2e22fdeSRichard Henderson } 231d2e22fdeSRichard Henderson } 232d2e22fdeSRichard Henderson 233d2e22fdeSRichard Henderson qemu_fprintf(f, "\n"); 23461766fe9SRichard Henderson } 235