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"
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;
56*20eee6cbSHelge 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
cpu_hppa_put_psw(CPUHPPAState * env,target_ulong psw)62c53e401eSRichard Henderson void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
6361766fe9SRichard Henderson {
64931adff3SRichard Henderson uint64_t reserved;
65c53e401eSRichard Henderson target_ulong cb = 0;
6661766fe9SRichard Henderson
67931adff3SRichard Henderson /* Do not allow reserved bits to be set. */
68931adff3SRichard Henderson if (hppa_is_pa20(env)) {
69931adff3SRichard Henderson reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4);
70931adff3SRichard Henderson reserved |= PSW_G; /* PA1.x only */
71931adff3SRichard Henderson reserved |= PSW_E; /* not implemented */
72931adff3SRichard Henderson } else {
73931adff3SRichard Henderson reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2);
74931adff3SRichard Henderson reserved |= PSW_O | PSW_W; /* PA2.0 only */
75931adff3SRichard Henderson reserved |= PSW_E | PSW_Y | PSW_Z; /* not implemented */
76931adff3SRichard Henderson }
77931adff3SRichard Henderson psw &= ~reserved;
78931adff3SRichard Henderson
79ebc9401aSRichard Henderson env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB);
80ebc9401aSRichard Henderson env->psw_xb = psw & (PSW_X | PSW_B);
81fa57e327SRichard Henderson env->psw_n = (psw / PSW_N) & 1;
82fa57e327SRichard Henderson env->psw_v = -((psw / PSW_V) & 1);
8361766fe9SRichard Henderson
84931adff3SRichard Henderson env->psw_cb_msb = (psw >> 39) & 1;
85931adff3SRichard Henderson cb |= ((psw >> 38) & 1) << 60;
86931adff3SRichard Henderson cb |= ((psw >> 37) & 1) << 56;
87931adff3SRichard Henderson cb |= ((psw >> 36) & 1) << 52;
88931adff3SRichard Henderson cb |= ((psw >> 35) & 1) << 48;
89931adff3SRichard Henderson cb |= ((psw >> 34) & 1) << 44;
90931adff3SRichard Henderson cb |= ((psw >> 33) & 1) << 40;
91931adff3SRichard Henderson cb |= ((psw >> 32) & 1) << 36;
92931adff3SRichard Henderson cb |= ((psw >> 15) & 1) << 32;
9361766fe9SRichard Henderson cb |= ((psw >> 14) & 1) << 28;
9461766fe9SRichard Henderson cb |= ((psw >> 13) & 1) << 24;
9561766fe9SRichard Henderson cb |= ((psw >> 12) & 1) << 20;
9661766fe9SRichard Henderson cb |= ((psw >> 11) & 1) << 16;
9761766fe9SRichard Henderson cb |= ((psw >> 10) & 1) << 12;
9861766fe9SRichard Henderson cb |= ((psw >> 9) & 1) << 8;
9961766fe9SRichard Henderson cb |= ((psw >> 8) & 1) << 4;
10061766fe9SRichard Henderson env->psw_cb = cb;
10161766fe9SRichard Henderson }
10261766fe9SRichard Henderson
hppa_cpu_dump_state(CPUState * cs,FILE * f,int flags)10390c84c56SMarkus Armbruster void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
10461766fe9SRichard Henderson {
105d2e22fdeSRichard Henderson #ifndef CONFIG_USER_ONLY
106d2e22fdeSRichard Henderson static const char cr_name[32][5] = {
107d2e22fdeSRichard Henderson "RC", "CR1", "CR2", "CR3",
108d2e22fdeSRichard Henderson "CR4", "CR5", "CR6", "CR7",
109d2e22fdeSRichard Henderson "PID1", "PID2", "CCR", "SAR",
110d2e22fdeSRichard Henderson "PID3", "PID4", "IVA", "EIEM",
111d2e22fdeSRichard Henderson "ITMR", "ISQF", "IOQF", "IIR",
112d2e22fdeSRichard Henderson "ISR", "IOR", "IPSW", "EIRR",
113d2e22fdeSRichard Henderson "TR0", "TR1", "TR2", "TR3",
114d2e22fdeSRichard Henderson "TR4", "TR5", "TR6", "TR7",
115d2e22fdeSRichard Henderson };
116d2e22fdeSRichard Henderson #endif
117d2e22fdeSRichard Henderson
1185718fe4cSRichard Henderson CPUHPPAState *env = cpu_env(cs);
119c53e401eSRichard Henderson target_ulong psw = cpu_hppa_get_psw(env);
120c53e401eSRichard Henderson target_ulong psw_cb;
121fa57e327SRichard Henderson char psw_c[20];
1225718fe4cSRichard Henderson int i, w;
1235718fe4cSRichard Henderson uint64_t m;
1245718fe4cSRichard Henderson
1255718fe4cSRichard Henderson if (hppa_is_pa20(env)) {
1265718fe4cSRichard Henderson w = 16;
1275718fe4cSRichard Henderson m = UINT64_MAX;
1285718fe4cSRichard Henderson } else {
1295718fe4cSRichard Henderson w = 8;
1305718fe4cSRichard Henderson m = UINT32_MAX;
1315718fe4cSRichard Henderson }
13261766fe9SRichard Henderson
133d2e22fdeSRichard Henderson qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
134d2e22fdeSRichard Henderson "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
135d2e22fdeSRichard Henderson env->iasq_f >> 32, w, m & env->iaoq_f,
136c301f34eSRichard Henderson hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
137d2e22fdeSRichard Henderson env->iasq_b >> 32, w, m & env->iaoq_b,
138d2e22fdeSRichard Henderson hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
139fa57e327SRichard Henderson
140fa57e327SRichard Henderson psw_c[0] = (psw & PSW_W ? 'W' : '-');
141fa57e327SRichard Henderson psw_c[1] = (psw & PSW_E ? 'E' : '-');
142fa57e327SRichard Henderson psw_c[2] = (psw & PSW_S ? 'S' : '-');
143fa57e327SRichard Henderson psw_c[3] = (psw & PSW_T ? 'T' : '-');
144fa57e327SRichard Henderson psw_c[4] = (psw & PSW_H ? 'H' : '-');
145fa57e327SRichard Henderson psw_c[5] = (psw & PSW_L ? 'L' : '-');
146fa57e327SRichard Henderson psw_c[6] = (psw & PSW_N ? 'N' : '-');
147fa57e327SRichard Henderson psw_c[7] = (psw & PSW_X ? 'X' : '-');
148fa57e327SRichard Henderson psw_c[8] = (psw & PSW_B ? 'B' : '-');
149fa57e327SRichard Henderson psw_c[9] = (psw & PSW_C ? 'C' : '-');
150fa57e327SRichard Henderson psw_c[10] = (psw & PSW_V ? 'V' : '-');
151fa57e327SRichard Henderson psw_c[11] = (psw & PSW_M ? 'M' : '-');
152fa57e327SRichard Henderson psw_c[12] = (psw & PSW_F ? 'F' : '-');
153fa57e327SRichard Henderson psw_c[13] = (psw & PSW_R ? 'R' : '-');
154fa57e327SRichard Henderson psw_c[14] = (psw & PSW_Q ? 'Q' : '-');
155fa57e327SRichard Henderson psw_c[15] = (psw & PSW_P ? 'P' : '-');
156fa57e327SRichard Henderson psw_c[16] = (psw & PSW_D ? 'D' : '-');
157fa57e327SRichard Henderson psw_c[17] = (psw & PSW_I ? 'I' : '-');
158fa57e327SRichard Henderson psw_c[18] = '\0';
159c53e401eSRichard Henderson psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull)
160c53e401eSRichard Henderson | (env->psw_cb_msb << 60);
161fa57e327SRichard Henderson
1625718fe4cSRichard Henderson qemu_fprintf(f, "PSW %0*" PRIx64 " CB %0*" PRIx64 " %s\n",
1635718fe4cSRichard Henderson w, m & psw, w, m & psw_cb, psw_c);
164fa57e327SRichard Henderson
165fa57e327SRichard Henderson for (i = 0; i < 32; i++) {
1665718fe4cSRichard Henderson qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c",
1675718fe4cSRichard Henderson i, w, m & env->gr[i],
16833423472SRichard Henderson (i & 3) == 3 ? '\n' : ' ');
16961766fe9SRichard Henderson }
17033423472SRichard Henderson #ifndef CONFIG_USER_ONLY
171d2e22fdeSRichard Henderson for (i = 0; i < 32; i++) {
172d2e22fdeSRichard Henderson qemu_fprintf(f, "%-4s %0*" PRIx64 "%c",
173d2e22fdeSRichard Henderson cr_name[i], w, m & env->cr[i],
174d2e22fdeSRichard Henderson (i & 3) == 3 ? '\n' : ' ');
175d2e22fdeSRichard Henderson }
176d2e22fdeSRichard Henderson qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n",
177d2e22fdeSRichard Henderson w, m & env->cr_back[0], w, m & env->cr_back[1]);
17833423472SRichard Henderson for (i = 0; i < 8; i++) {
17990c84c56SMarkus Armbruster qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
18033423472SRichard Henderson (i & 3) == 3 ? '\n' : ' ');
18161766fe9SRichard Henderson }
18233423472SRichard Henderson #endif
18361766fe9SRichard Henderson
184d2e22fdeSRichard Henderson if (flags & CPU_DUMP_FPU) {
185d2e22fdeSRichard Henderson static const char rm[4][4] = { "RN", "RZ", "R+", "R-" };
186d2e22fdeSRichard Henderson char flg[6], ena[6];
187d2e22fdeSRichard Henderson uint32_t fpsr = env->fr0_shadow;
188d2e22fdeSRichard Henderson
189d2e22fdeSRichard Henderson flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-');
190d2e22fdeSRichard Henderson flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-');
191d2e22fdeSRichard Henderson flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-');
192d2e22fdeSRichard Henderson flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-');
193d2e22fdeSRichard Henderson flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-');
194d2e22fdeSRichard Henderson flg[5] = '\0';
195d2e22fdeSRichard Henderson
196d2e22fdeSRichard Henderson ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-');
197d2e22fdeSRichard Henderson ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-');
198d2e22fdeSRichard Henderson ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-');
199d2e22fdeSRichard Henderson ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-');
200d2e22fdeSRichard Henderson ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-');
201d2e22fdeSRichard Henderson ena[5] = '\0';
202d2e22fdeSRichard Henderson
203d2e22fdeSRichard Henderson qemu_fprintf(f, "FPSR %08x flag %s enable %s %s\n",
204d2e22fdeSRichard Henderson fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]);
205d2e22fdeSRichard Henderson
206d2e22fdeSRichard Henderson for (i = 0; i < 32; i++) {
207d2e22fdeSRichard Henderson qemu_fprintf(f, "FR%02d %016" PRIx64 "%c",
208d2e22fdeSRichard Henderson i, env->fr[i], (i & 3) == 3 ? '\n' : ' ');
209d2e22fdeSRichard Henderson }
210d2e22fdeSRichard Henderson }
211d2e22fdeSRichard Henderson
212d2e22fdeSRichard Henderson qemu_fprintf(f, "\n");
21361766fe9SRichard Henderson }
214