xref: /openbmc/qemu/target/hppa/helper.c (revision b2580720)
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 < 0) * 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