xref: /qemu/target/hppa/helper.c (revision f07a5674cf97b8473e5d06d7b1df9b51e97d553f)
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 #include "hw/hppa/hppa_hardware.h"
28 
29 target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
30 {
31     target_ulong psw;
32     target_ulong mask1 = (target_ulong)-1 / 0xf;
33     target_ulong maskf = (target_ulong)-1 / 0xffff * 0xf;
34 
35     /* Fold carry bits down to 8 consecutive bits.  */
36     /* ^^^b^^^c^^^d^^^e^^^f^^^g^^^h^^^i^^^j^^^k^^^l^^^m^^^n^^^o^^^p^^^^ */
37     psw = (env->psw_cb >> 4) & mask1;
38     /* .......b...c...d...e...f...g...h...i...j...k...l...m...n...o...p */
39     psw |= psw >> 3;
40     /* .......b..bc..cd..de..ef..fg..gh..hi..ij..jk..kl..lm..mn..no..op */
41     psw |= psw >> 6;
42     psw &= maskf;
43     /* .............bcd............efgh............ijkl............mnop */
44     psw |= psw >> 12;
45     /* .............bcd.........bcdefgh........efghijkl........ijklmnop */
46     psw |= env->psw_cb_msb << 39;
47     /* .............bcd........abcdefgh........efghijkl........ijklmnop */
48 
49     /* For hppa64, the two 8-bit fields are discontiguous. */
50     if (hppa_is_pa20(env)) {
51         psw = (psw & 0xff00000000ull) | ((psw & 0xff) << 8);
52     } else {
53         psw = (psw & 0xff) << 8;
54     }
55 
56     psw |= env->psw_n * PSW_N;
57     psw |= ((env->psw_v >> 31) & 1) * PSW_V;
58     psw |= env->psw | env->psw_xb;
59 
60     return psw;
61 }
62 
63 void update_gva_offset_mask(CPUHPPAState *env)
64 {
65     uint64_t gom;
66 
67     if (env->psw & PSW_W) {
68         gom = (env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE)
69             ? MAKE_64BIT_MASK(0, 62) &
70                 ~((uint64_t)HPPA64_PDC_CACHE_RET_SPID_VAL << 48)
71             : MAKE_64BIT_MASK(0, 62);
72     } else {
73         gom = MAKE_64BIT_MASK(0, 32);
74     }
75 
76     env->gva_offset_mask = gom;
77 }
78 
79 void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
80 {
81     uint64_t reserved;
82     target_ulong cb = 0;
83 
84     /* Do not allow reserved bits to be set. */
85     if (hppa_is_pa20(env)) {
86         reserved = MAKE_64BIT_MASK(40, 24) | MAKE_64BIT_MASK(28, 4);
87         reserved |= PSW_G;                  /* PA1.x only */
88         reserved |= PSW_E;                  /* not implemented */
89     } else {
90         reserved = MAKE_64BIT_MASK(32, 32) | MAKE_64BIT_MASK(28, 2);
91         reserved |= PSW_O | PSW_W;          /* PA2.0 only */
92         reserved |= PSW_E | PSW_Y | PSW_Z;  /* not implemented */
93     }
94     psw &= ~reserved;
95 
96     env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB);
97     env->psw_xb = psw & (PSW_X | PSW_B);
98     env->psw_n = (psw / PSW_N) & 1;
99     env->psw_v = -((psw / PSW_V) & 1);
100 
101     env->psw_cb_msb = (psw >> 39) & 1;
102     cb |= ((psw >> 38) & 1) << 60;
103     cb |= ((psw >> 37) & 1) << 56;
104     cb |= ((psw >> 36) & 1) << 52;
105     cb |= ((psw >> 35) & 1) << 48;
106     cb |= ((psw >> 34) & 1) << 44;
107     cb |= ((psw >> 33) & 1) << 40;
108     cb |= ((psw >> 32) & 1) << 36;
109     cb |= ((psw >> 15) & 1) << 32;
110     cb |= ((psw >> 14) & 1) << 28;
111     cb |= ((psw >> 13) & 1) << 24;
112     cb |= ((psw >> 12) & 1) << 20;
113     cb |= ((psw >> 11) & 1) << 16;
114     cb |= ((psw >> 10) & 1) << 12;
115     cb |= ((psw >>  9) & 1) <<  8;
116     cb |= ((psw >>  8) & 1) <<  4;
117     env->psw_cb = cb;
118 
119     update_gva_offset_mask(env);
120 }
121 
122 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
123 {
124 #ifndef CONFIG_USER_ONLY
125     static const char cr_name[32][5] = {
126         "RC",    "CR1",   "CR2",   "CR3",
127         "CR4",   "CR5",   "CR6",   "CR7",
128         "PID1",  "PID2",  "CCR",   "SAR",
129         "PID3",  "PID4",  "IVA",   "EIEM",
130         "ITMR",  "ISQF",  "IOQF",  "IIR",
131         "ISR",   "IOR",   "IPSW",  "EIRR",
132         "TR0",   "TR1",   "TR2",   "TR3",
133         "TR4",   "TR5",   "TR6",   "TR7",
134     };
135 #endif
136 
137     CPUHPPAState *env = cpu_env(cs);
138     target_ulong psw = cpu_hppa_get_psw(env);
139     target_ulong psw_cb;
140     char psw_c[20];
141     int i, w;
142     uint64_t m;
143 
144     if (hppa_is_pa20(env)) {
145         w = 16;
146         m = UINT64_MAX;
147     } else {
148         w = 8;
149         m = UINT32_MAX;
150     }
151 
152     qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
153                     "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
154                  env->iasq_f >> 32, w, m & env->iaoq_f,
155                  hppa_form_gva_mask(env->gva_offset_mask, env->iasq_f,
156 				    env->iaoq_f),
157                  env->iasq_b >> 32, w, m & env->iaoq_b,
158                  hppa_form_gva_mask(env->gva_offset_mask, env->iasq_b,
159 				    env->iaoq_b));
160 
161     psw_c[0]  = (psw & PSW_W ? 'W' : '-');
162     psw_c[1]  = (psw & PSW_E ? 'E' : '-');
163     psw_c[2]  = (psw & PSW_S ? 'S' : '-');
164     psw_c[3]  = (psw & PSW_T ? 'T' : '-');
165     psw_c[4]  = (psw & PSW_H ? 'H' : '-');
166     psw_c[5]  = (psw & PSW_L ? 'L' : '-');
167     psw_c[6]  = (psw & PSW_N ? 'N' : '-');
168     psw_c[7]  = (psw & PSW_X ? 'X' : '-');
169     psw_c[8]  = (psw & PSW_B ? 'B' : '-');
170     psw_c[9]  = (psw & PSW_C ? 'C' : '-');
171     psw_c[10] = (psw & PSW_V ? 'V' : '-');
172     psw_c[11] = (psw & PSW_M ? 'M' : '-');
173     psw_c[12] = (psw & PSW_F ? 'F' : '-');
174     psw_c[13] = (psw & PSW_R ? 'R' : '-');
175     psw_c[14] = (psw & PSW_Q ? 'Q' : '-');
176     psw_c[15] = (psw & PSW_P ? 'P' : '-');
177     psw_c[16] = (psw & PSW_D ? 'D' : '-');
178     psw_c[17] = (psw & PSW_I ? 'I' : '-');
179     psw_c[18] = '\0';
180     psw_cb = ((env->psw_cb >> 4) & 0x1111111111111111ull)
181            | (env->psw_cb_msb << 60);
182 
183     qemu_fprintf(f, "PSW  %0*" PRIx64 " CB   %0*" PRIx64 " %s\n",
184                  w, m & psw, w, m & psw_cb, psw_c);
185 
186     for (i = 0; i < 32; i++) {
187         qemu_fprintf(f, "GR%02d %0*" PRIx64 "%c",
188                      i, w, m & env->gr[i],
189                      (i & 3) == 3 ? '\n' : ' ');
190     }
191 #ifndef CONFIG_USER_ONLY
192     for (i = 0; i < 32; i++) {
193         qemu_fprintf(f, "%-4s %0*" PRIx64 "%c",
194                      cr_name[i], w, m & env->cr[i],
195                      (i & 3) == 3 ? '\n' : ' ');
196     }
197     qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n",
198                  w, m & env->cr_back[0], w, m & env->cr_back[1]);
199     for (i = 0; i < 8; i++) {
200         qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
201                      (i & 3) == 3 ? '\n' : ' ');
202     }
203 #endif
204 
205     if (flags & CPU_DUMP_FPU) {
206         static const char rm[4][4] = { "RN", "RZ", "R+", "R-" };
207         char flg[6], ena[6];
208         uint32_t fpsr = env->fr0_shadow;
209 
210         flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-');
211         flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-');
212         flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-');
213         flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-');
214         flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-');
215         flg[5] = '\0';
216 
217         ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-');
218         ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-');
219         ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-');
220         ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-');
221         ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-');
222         ena[5] = '\0';
223 
224         qemu_fprintf(f, "FPSR %08x flag    %s enable  %s %s\n",
225                      fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]);
226 
227         for (i = 0; i < 32; i++) {
228             qemu_fprintf(f, "FR%02d %016" PRIx64 "%c",
229                      i, env->fr[i], (i & 3) == 3 ? '\n' : ' ');
230         }
231     }
232 
233     qemu_fprintf(f, "\n");
234 }
235