xref: /qemu/target/hppa/helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
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"
2461766fe9SRichard Henderson #include "exec/helper-proto.h"
2590c84c56SMarkus Armbruster #include "qemu/qemu-print.h"
26*644ce5dfSHelge Deller #include "hw/hppa/hppa_hardware.h"
2761766fe9SRichard Henderson 
cpu_hppa_get_psw(CPUHPPAState * env)28c53e401eSRichard Henderson target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
2961766fe9SRichard Henderson {
30c53e401eSRichard Henderson     target_ulong psw;
31c53e401eSRichard Henderson     target_ulong mask1 = (target_ulong)-1 / 0xf;
32c53e401eSRichard Henderson     target_ulong maskf = (target_ulong)-1 / 0xffff * 0xf;
3361766fe9SRichard Henderson 
3461766fe9SRichard Henderson     /* Fold carry bits down to 8 consecutive bits.  */
35931adff3SRichard Henderson     /* ^^^b^^^c^^^d^^^e^^^f^^^g^^^h^^^i^^^j^^^k^^^l^^^m^^^n^^^o^^^p^^^^ */
36931adff3SRichard Henderson     psw = (env->psw_cb >> 4) & mask1;
37931adff3SRichard Henderson     /* .......b...c...d...e...f...g...h...i...j...k...l...m...n...o...p */
3861766fe9SRichard Henderson     psw |= psw >> 3;
39931adff3SRichard Henderson     /* .......b..bc..cd..de..ef..fg..gh..hi..ij..jk..kl..lm..mn..no..op */
40931adff3SRichard Henderson     psw |= psw >> 6;
41931adff3SRichard Henderson     psw &= maskf;
42931adff3SRichard Henderson     /* .............bcd............efgh............ijkl............mnop */
43931adff3SRichard Henderson     psw |= psw >> 12;
44931adff3SRichard Henderson     /* .............bcd.........bcdefgh........efghijkl........ijklmnop */
45c53e401eSRichard Henderson     psw |= env->psw_cb_msb << 39;
46931adff3SRichard Henderson     /* .............bcd........abcdefgh........efghijkl........ijklmnop */
47931adff3SRichard Henderson 
48931adff3SRichard Henderson     /* For hppa64, the two 8-bit fields are discontiguous. */
49931adff3SRichard Henderson     if (hppa_is_pa20(env)) {
50931adff3SRichard Henderson         psw = (psw & 0xff00000000ull) | ((psw & 0xff) << 8);
51931adff3SRichard Henderson     } else {
52fa57e327SRichard Henderson         psw = (psw & 0xff) << 8;
53931adff3SRichard Henderson     }
5461766fe9SRichard Henderson 
55fa57e327SRichard Henderson     psw |= env->psw_n * PSW_N;
56ead5078cSHelge Deller     psw |= ((env->psw_v >> 31) & 1) * PSW_V;
57ebc9401aSRichard Henderson     psw |= env->psw | env->psw_xb;
5861766fe9SRichard Henderson 
5961766fe9SRichard Henderson     return psw;
6061766fe9SRichard Henderson }
6161766fe9SRichard Henderson 
update_gva_offset_mask(CPUHPPAState * env)62*644ce5dfSHelge Deller void update_gva_offset_mask(CPUHPPAState *env)
63*644ce5dfSHelge Deller {
64*644ce5dfSHelge Deller     uint64_t gom;
65*644ce5dfSHelge Deller 
66*644ce5dfSHelge Deller     if (env->psw & PSW_W) {
67*644ce5dfSHelge Deller         gom = (env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE)
68*644ce5dfSHelge Deller             ? MAKE_64BIT_MASK(0, 62) &
69*644ce5dfSHelge Deller                 ~((uint64_t)HPPA64_PDC_CACHE_RET_SPID_VAL << 48)
70*644ce5dfSHelge Deller             : MAKE_64BIT_MASK(0, 62);
71*644ce5dfSHelge Deller     } else {
72*644ce5dfSHelge Deller         gom = MAKE_64BIT_MASK(0, 32);
73*644ce5dfSHelge Deller     }
74*644ce5dfSHelge Deller 
75*644ce5dfSHelge Deller     env->gva_offset_mask = gom;
76*644ce5dfSHelge Deller }
77*644ce5dfSHelge Deller 
cpu_hppa_put_psw(CPUHPPAState * env,target_ulong psw)78c53e401eSRichard Henderson void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
7961766fe9SRichard Henderson {
80931adff3SRichard Henderson     uint64_t reserved;
81c53e401eSRichard Henderson     target_ulong cb = 0;
8261766fe9SRichard Henderson 
83931adff3SRichard Henderson     /* Do not allow reserved bits to be set. */
84931adff3SRichard Henderson     if (hppa_is_pa20(env)) {
85931adff3SRichard Henderson         reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4);
86931adff3SRichard Henderson         reserved |= PSW_G;                  /* PA1.x only */
87931adff3SRichard Henderson         reserved |= PSW_E;                  /* not implemented */
88931adff3SRichard Henderson     } else {
89931adff3SRichard Henderson         reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2);
90931adff3SRichard Henderson         reserved |= PSW_O | PSW_W;          /* PA2.0 only */
91931adff3SRichard Henderson         reserved |= PSW_E | PSW_Y | PSW_Z;  /* not implemented */
92931adff3SRichard Henderson     }
93931adff3SRichard Henderson     psw &= ~reserved;
94931adff3SRichard Henderson 
95ebc9401aSRichard Henderson     env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB);
96ebc9401aSRichard Henderson     env->psw_xb = psw & (PSW_X | PSW_B);
97fa57e327SRichard Henderson     env->psw_n = (psw / PSW_N) & 1;
98fa57e327SRichard Henderson     env->psw_v = -((psw / PSW_V) & 1);
9961766fe9SRichard Henderson 
100931adff3SRichard Henderson     env->psw_cb_msb = (psw >> 39) & 1;
101931adff3SRichard Henderson     cb |= ((psw >> 38) & 1) << 60;
102931adff3SRichard Henderson     cb |= ((psw >> 37) & 1) << 56;
103931adff3SRichard Henderson     cb |= ((psw >> 36) & 1) << 52;
104931adff3SRichard Henderson     cb |= ((psw >> 35) & 1) << 48;
105931adff3SRichard Henderson     cb |= ((psw >> 34) & 1) << 44;
106931adff3SRichard Henderson     cb |= ((psw >> 33) & 1) << 40;
107931adff3SRichard Henderson     cb |= ((psw >> 32) & 1) << 36;
108931adff3SRichard Henderson     cb |= ((psw >> 15) & 1) << 32;
10961766fe9SRichard Henderson     cb |= ((psw >> 14) & 1) << 28;
11061766fe9SRichard Henderson     cb |= ((psw >> 13) & 1) << 24;
11161766fe9SRichard Henderson     cb |= ((psw >> 12) & 1) << 20;
11261766fe9SRichard Henderson     cb |= ((psw >> 11) & 1) << 16;
11361766fe9SRichard Henderson     cb |= ((psw >> 10) & 1) << 12;
11461766fe9SRichard Henderson     cb |= ((psw >>  9) & 1) <<  8;
11561766fe9SRichard Henderson     cb |= ((psw >>  8) & 1) <<  4;
11661766fe9SRichard Henderson     env->psw_cb = cb;
117*644ce5dfSHelge Deller 
118*644ce5dfSHelge Deller     update_gva_offset_mask(env);
11961766fe9SRichard Henderson }
12061766fe9SRichard Henderson 
hppa_cpu_dump_state(CPUState * cs,FILE * f,int flags)12190c84c56SMarkus Armbruster void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
12261766fe9SRichard Henderson {
123d2e22fdeSRichard Henderson #ifndef CONFIG_USER_ONLY
124d2e22fdeSRichard Henderson     static const char cr_name[32][5] = {
125d2e22fdeSRichard Henderson         "RC",    "CR1",   "CR2",   "CR3",
126d2e22fdeSRichard Henderson         "CR4",   "CR5",   "CR6",   "CR7",
127d2e22fdeSRichard Henderson         "PID1",  "PID2",  "CCR",   "SAR",
128d2e22fdeSRichard Henderson         "PID3",  "PID4",  "IVA",   "EIEM",
129d2e22fdeSRichard Henderson         "ITMR",  "ISQF",  "IOQF",  "IIR",
130d2e22fdeSRichard Henderson         "ISR",   "IOR",   "IPSW",  "EIRR",
131d2e22fdeSRichard Henderson         "TR0",   "TR1",   "TR2",   "TR3",
132d2e22fdeSRichard Henderson         "TR4",   "TR5",   "TR6",   "TR7",
133d2e22fdeSRichard Henderson     };
134d2e22fdeSRichard Henderson #endif
135d2e22fdeSRichard Henderson 
1365718fe4cSRichard Henderson     CPUHPPAState *env = cpu_env(cs);
137c53e401eSRichard Henderson     target_ulong psw = cpu_hppa_get_psw(env);
138c53e401eSRichard Henderson     target_ulong psw_cb;
139fa57e327SRichard Henderson     char psw_c[20];
1405718fe4cSRichard Henderson     int i, w;
1415718fe4cSRichard Henderson     uint64_t m;
1425718fe4cSRichard Henderson 
1435718fe4cSRichard Henderson     if (hppa_is_pa20(env)) {
1445718fe4cSRichard Henderson         w = 16;
1455718fe4cSRichard Henderson         m = UINT64_MAX;
1465718fe4cSRichard Henderson     } else {
1475718fe4cSRichard Henderson         w = 8;
1485718fe4cSRichard Henderson         m = UINT32_MAX;
1495718fe4cSRichard Henderson     }
15061766fe9SRichard Henderson 
151d2e22fdeSRichard Henderson     qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
152d2e22fdeSRichard Henderson                     "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
153d2e22fdeSRichard Henderson                  env->iasq_f >> 32, w, m & env->iaoq_f,
154*644ce5dfSHelge Deller                  hppa_form_gva_mask(env->gva_offset_mask, env->iasq_f,
155*644ce5dfSHelge Deller 				    env->iaoq_f),
156d2e22fdeSRichard Henderson                  env->iasq_b >> 32, w, m & env->iaoq_b,
157*644ce5dfSHelge Deller                  hppa_form_gva_mask(env->gva_offset_mask, env->iasq_b,
158*644ce5dfSHelge Deller 				    env->iaoq_b));
159fa57e327SRichard Henderson 
160fa57e327SRichard Henderson     psw_c[0]  = (psw & PSW_W ? 'W' : '-');
161fa57e327SRichard Henderson     psw_c[1]  = (psw & PSW_E ? 'E' : '-');
162fa57e327SRichard Henderson     psw_c[2]  = (psw & PSW_S ? 'S' : '-');
163fa57e327SRichard Henderson     psw_c[3]  = (psw & PSW_T ? 'T' : '-');
164fa57e327SRichard Henderson     psw_c[4]  = (psw & PSW_H ? 'H' : '-');
165fa57e327SRichard Henderson     psw_c[5]  = (psw & PSW_L ? 'L' : '-');
166fa57e327SRichard Henderson     psw_c[6]  = (psw & PSW_N ? 'N' : '-');
167fa57e327SRichard Henderson     psw_c[7]  = (psw & PSW_X ? 'X' : '-');
168fa57e327SRichard Henderson     psw_c[8]  = (psw & PSW_B ? 'B' : '-');
169fa57e327SRichard Henderson     psw_c[9]  = (psw & PSW_C ? 'C' : '-');
170fa57e327SRichard Henderson     psw_c[10] = (psw & PSW_V ? 'V' : '-');
171fa57e327SRichard Henderson     psw_c[11] = (psw & PSW_M ? 'M' : '-');
172fa57e327SRichard Henderson     psw_c[12] = (psw & PSW_F ? 'F' : '-');
173fa57e327SRichard Henderson     psw_c[13] = (psw & PSW_R ? 'R' : '-');
174fa57e327SRichard Henderson     psw_c[14] = (psw & PSW_Q ? 'Q' : '-');
175fa57e327SRichard Henderson     psw_c[15] = (psw & PSW_P ? 'P' : '-');
176fa57e327SRichard Henderson     psw_c[16] = (psw & PSW_D ? 'D' : '-');
177fa57e327SRichard Henderson     psw_c[17] = (psw & PSW_I ? 'I' : '-');
178fa57e327SRichard Henderson     psw_c[18] = '\0';
179c53e401eSRichard Henderson     psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull)
180c53e401eSRichard Henderson            | (env->psw_cb_msb << 60);
181fa57e327SRichard Henderson 
1825718fe4cSRichard Henderson     qemu_fprintf(f, "PSW  %0*" PRIx64 " CB   %0*" PRIx64 " %s\n",
1835718fe4cSRichard Henderson                  w, m & psw, w, m & psw_cb, psw_c);
184fa57e327SRichard Henderson 
185fa57e327SRichard Henderson     for (i = 0; i < 32; i++) {
1865718fe4cSRichard Henderson         qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c",
1875718fe4cSRichard Henderson                      i, w, m & env->gr[i],
18833423472SRichard Henderson                      (i & 3) == 3 ? '\n' : ' ');
18961766fe9SRichard Henderson     }
19033423472SRichard Henderson #ifndef CONFIG_USER_ONLY
191d2e22fdeSRichard Henderson     for (i = 0; i < 32; i++) {
192d2e22fdeSRichard Henderson         qemu_fprintf(f, "%-4s %0*" PRIx64 "%c",
193d2e22fdeSRichard Henderson                      cr_name[i], w, m & env->cr[i],
194d2e22fdeSRichard Henderson                      (i & 3) == 3 ? '\n' : ' ');
195d2e22fdeSRichard Henderson     }
196d2e22fdeSRichard Henderson     qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n",
197d2e22fdeSRichard Henderson                  w, m & env->cr_back[0], w, m & env->cr_back[1]);
19833423472SRichard Henderson     for (i = 0; i < 8; i++) {
19990c84c56SMarkus Armbruster         qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
20033423472SRichard Henderson                      (i & 3) == 3 ? '\n' : ' ');
20161766fe9SRichard Henderson     }
20233423472SRichard Henderson #endif
20361766fe9SRichard Henderson 
204d2e22fdeSRichard Henderson     if (flags & CPU_DUMP_FPU) {
205d2e22fdeSRichard Henderson         static const char rm[4][4] = { "RN", "RZ", "R+", "R-" };
206d2e22fdeSRichard Henderson         char flg[6], ena[6];
207d2e22fdeSRichard Henderson         uint32_t fpsr = env->fr0_shadow;
208d2e22fdeSRichard Henderson 
209d2e22fdeSRichard Henderson         flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-');
210d2e22fdeSRichard Henderson         flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-');
211d2e22fdeSRichard Henderson         flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-');
212d2e22fdeSRichard Henderson         flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-');
213d2e22fdeSRichard Henderson         flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-');
214d2e22fdeSRichard Henderson         flg[5] = '\0';
215d2e22fdeSRichard Henderson 
216d2e22fdeSRichard Henderson         ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-');
217d2e22fdeSRichard Henderson         ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-');
218d2e22fdeSRichard Henderson         ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-');
219d2e22fdeSRichard Henderson         ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-');
220d2e22fdeSRichard Henderson         ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-');
221d2e22fdeSRichard Henderson         ena[5] = '\0';
222d2e22fdeSRichard Henderson 
223d2e22fdeSRichard Henderson         qemu_fprintf(f, "FPSR %08x flag    %s enable  %s %s\n",
224d2e22fdeSRichard Henderson                      fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]);
225d2e22fdeSRichard Henderson 
226d2e22fdeSRichard Henderson         for (i = 0; i < 32; i++) {
227d2e22fdeSRichard Henderson             qemu_fprintf(f, "FR%02d %016" PRIx64 "%c",
228d2e22fdeSRichard Henderson                      i, env->fr[i], (i & 3) == 3 ? '\n' : ' ');
229d2e22fdeSRichard Henderson         }
230d2e22fdeSRichard Henderson     }
231d2e22fdeSRichard Henderson 
232d2e22fdeSRichard Henderson     qemu_fprintf(f, "\n");
23361766fe9SRichard Henderson }
234