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