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