xref: /openbmc/qemu/target/i386/cpu-dump.c (revision c94bee4cd6693c1c65ba43bb8970cf909dec378b)
1  /*
2   *  i386 CPU dump to FILE
3   *
4   *  Copyright (c) 2003 Fabrice Bellard
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 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 "cpu.h"
22  #include "qemu/qemu-print.h"
23  #ifndef CONFIG_USER_ONLY
24  #include "hw/i386/apic_internal.h"
25  #endif
26  
27  /***********************************************************/
28  /* x86 debug */
29  
30  static const char * const cc_op_str[] = {
31      [CC_OP_DYNAMIC] = "DYNAMIC",
32  
33      [CC_OP_EFLAGS] = "EFLAGS",
34      [CC_OP_ADCX] = "ADCX",
35      [CC_OP_ADOX] = "ADOX",
36      [CC_OP_ADCOX] = "ADCOX",
37  
38      [CC_OP_MULB] = "MULB",
39      [CC_OP_MULW] = "MULW",
40      [CC_OP_MULL] = "MULL",
41      [CC_OP_MULQ] = "MULQ",
42  
43      [CC_OP_ADDB] = "ADDB",
44      [CC_OP_ADDW] = "ADDW",
45      [CC_OP_ADDL] = "ADDL",
46      [CC_OP_ADDQ] = "ADDQ",
47  
48      [CC_OP_ADCB] = "ADCB",
49      [CC_OP_ADCW] = "ADCW",
50      [CC_OP_ADCL] = "ADCL",
51      [CC_OP_ADCQ] = "ADCQ",
52  
53      [CC_OP_SUBB] = "SUBB",
54      [CC_OP_SUBW] = "SUBW",
55      [CC_OP_SUBL] = "SUBL",
56      [CC_OP_SUBQ] = "SUBQ",
57  
58      [CC_OP_SBBB] = "SBBB",
59      [CC_OP_SBBW] = "SBBW",
60      [CC_OP_SBBL] = "SBBL",
61      [CC_OP_SBBQ] = "SBBQ",
62  
63      [CC_OP_LOGICB] = "LOGICB",
64      [CC_OP_LOGICW] = "LOGICW",
65      [CC_OP_LOGICL] = "LOGICL",
66      [CC_OP_LOGICQ] = "LOGICQ",
67  
68      [CC_OP_INCB] = "INCB",
69      [CC_OP_INCW] = "INCW",
70      [CC_OP_INCL] = "INCL",
71      [CC_OP_INCQ] = "INCQ",
72  
73      [CC_OP_DECB] = "DECB",
74      [CC_OP_DECW] = "DECW",
75      [CC_OP_DECL] = "DECL",
76      [CC_OP_DECQ] = "DECQ",
77  
78      [CC_OP_SHLB] = "SHLB",
79      [CC_OP_SHLW] = "SHLW",
80      [CC_OP_SHLL] = "SHLL",
81      [CC_OP_SHLQ] = "SHLQ",
82  
83      [CC_OP_SARB] = "SARB",
84      [CC_OP_SARW] = "SARW",
85      [CC_OP_SARL] = "SARL",
86      [CC_OP_SARQ] = "SARQ",
87  
88      [CC_OP_BMILGB] = "BMILGB",
89      [CC_OP_BMILGW] = "BMILGW",
90      [CC_OP_BMILGL] = "BMILGL",
91      [CC_OP_BMILGQ] = "BMILGQ",
92  
93      [CC_OP_POPCNT] = "POPCNT",
94  };
95  
96  static void
cpu_x86_dump_seg_cache(CPUX86State * env,FILE * f,const char * name,struct SegmentCache * sc)97  cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f,
98                         const char *name, struct SegmentCache *sc)
99  {
100  #ifdef TARGET_X86_64
101      if (env->hflags & HF_CS64_MASK) {
102          qemu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
103                       sc->selector, sc->base, sc->limit,
104                       sc->flags & 0x00ffff00);
105      } else
106  #endif
107      {
108          qemu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
109                       (uint32_t)sc->base, sc->limit,
110                       sc->flags & 0x00ffff00);
111      }
112  
113      if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
114          goto done;
115  
116      qemu_fprintf(f, " DPL=%d ",
117                   (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
118      if (sc->flags & DESC_S_MASK) {
119          if (sc->flags & DESC_CS_MASK) {
120              qemu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
121                           ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
122              qemu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
123                           (sc->flags & DESC_R_MASK) ? 'R' : '-');
124          } else {
125              qemu_fprintf(f, (sc->flags & DESC_B_MASK
126                               || env->hflags & HF_LMA_MASK)
127                           ? "DS  " : "DS16");
128              qemu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
129                           (sc->flags & DESC_W_MASK) ? 'W' : '-');
130          }
131          qemu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
132      } else {
133          static const char *sys_type_name[2][16] = {
134              { /* 32 bit mode */
135                  "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
136                  "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
137                  "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
138                  "CallGate32", "Reserved", "IntGate32", "TrapGate32"
139              },
140              { /* 64 bit mode */
141                  "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
142                  "Reserved", "Reserved", "Reserved", "Reserved",
143                  "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
144                  "Reserved", "IntGate64", "TrapGate64"
145              }
146          };
147          qemu_fprintf(f, "%s",
148                       sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
149                       [(sc->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT]);
150      }
151  done:
152      qemu_fprintf(f, "\n");
153  }
154  
155  #ifndef CONFIG_USER_ONLY
156  
157  /* ARRAY_SIZE check is not required because
158   * DeliveryMode(dm) has a size of 3 bit.
159   */
dm2str(uint32_t dm)160  static inline const char *dm2str(uint32_t dm)
161  {
162      static const char *str[] = {
163          "Fixed",
164          "...",
165          "SMI",
166          "...",
167          "NMI",
168          "INIT",
169          "...",
170          "ExtINT"
171      };
172      return str[dm];
173  }
174  
dump_apic_lvt(const char * name,uint32_t lvt,bool is_timer)175  static void dump_apic_lvt(const char *name, uint32_t lvt, bool is_timer)
176  {
177      uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
178      qemu_printf("%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
179                  name, lvt,
180                  lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
181                  lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
182                  lvt & APIC_LVT_MASKED ? "masked" : "",
183                  lvt & APIC_LVT_DELIV_STS ? "pending" : "",
184                  !is_timer ?
185                      "" : lvt & APIC_LVT_TIMER_PERIODIC ?
186                              "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
187                                              "tsc-deadline" : "one-shot",
188                  dm2str(dm));
189      if (dm != APIC_DM_NMI) {
190          qemu_printf(" (vec %u)\n", lvt & APIC_VECTOR_MASK);
191      } else {
192          qemu_printf("\n");
193      }
194  }
195  
196  /* ARRAY_SIZE check is not required because
197   * destination shorthand has a size of 2 bit.
198   */
shorthand2str(uint32_t shorthand)199  static inline const char *shorthand2str(uint32_t shorthand)
200  {
201      const char *str[] = {
202          "no-shorthand", "self", "all-self", "all"
203      };
204      return str[shorthand];
205  }
206  
divider_conf(uint32_t divide_conf)207  static inline uint8_t divider_conf(uint32_t divide_conf)
208  {
209      uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
210  
211      return divide_val == 7 ? 1 : 2 << divide_val;
212  }
213  
mask2str(char * str,uint32_t val,uint8_t size)214  static inline void mask2str(char *str, uint32_t val, uint8_t size)
215  {
216      while (size--) {
217          *str++ = (val >> size) & 1 ? '1' : '0';
218      }
219      *str = 0;
220  }
221  
222  #define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
223  
dump_apic_icr(APICCommonState * s,CPUX86State * env)224  static void dump_apic_icr(APICCommonState *s, CPUX86State *env)
225  {
226      uint32_t icr = s->icr[0], icr2 = s->icr[1];
227      uint8_t dest_shorthand = \
228          (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
229      bool logical_mod = icr & APIC_ICR_DEST_MOD;
230      char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
231      uint32_t dest_field;
232      bool x2apic;
233  
234      qemu_printf("ICR\t 0x%08x %s %s %s %s\n",
235                  icr,
236                  logical_mod ? "logical" : "physical",
237                  icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
238                  icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
239                  shorthand2str(dest_shorthand));
240  
241      qemu_printf("ICR2\t 0x%08x", icr2);
242      if (dest_shorthand != 0) {
243          qemu_printf("\n");
244          return;
245      }
246      x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
247      dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
248  
249      if (!logical_mod) {
250          if (x2apic) {
251              qemu_printf(" cpu %u (X2APIC ID)\n", dest_field);
252          } else {
253              qemu_printf(" cpu %u (APIC ID)\n",
254                          dest_field & APIC_LOGDEST_XAPIC_ID);
255          }
256          return;
257      }
258  
259      if (s->dest_mode == 0xf) { /* flat mode */
260          mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
261          qemu_printf(" mask %s (APIC ID)\n", apic_id_str);
262      } else if (s->dest_mode == 0) { /* cluster mode */
263          if (x2apic) {
264              mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
265              qemu_printf(" cluster %u mask %s (X2APIC ID)\n",
266                          dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
267          } else {
268              mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
269              qemu_printf(" cluster %u mask %s (APIC ID)\n",
270                          dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
271          }
272      }
273  }
274  
dump_apic_interrupt(const char * name,uint32_t * ireg_tab,uint32_t * tmr_tab)275  static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab,
276                                  uint32_t *tmr_tab)
277  {
278      int i, empty = true;
279  
280      qemu_printf("%s\t ", name);
281      for (i = 0; i < 256; i++) {
282          if (apic_get_bit(ireg_tab, i)) {
283              qemu_printf("%u%s ", i,
284                          apic_get_bit(tmr_tab, i) ? "(level)" : "");
285              empty = false;
286          }
287      }
288      qemu_printf("%s\n", empty ? "(none)" : "");
289  }
290  
x86_cpu_dump_local_apic_state(CPUState * cs,int flags)291  void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
292  {
293      X86CPU *cpu = X86_CPU(cs);
294      APICCommonState *s = APIC_COMMON(cpu->apic_state);
295      if (!s) {
296          qemu_printf("local apic state not available\n");
297          return;
298      }
299      uint32_t *lvt = s->lvt;
300  
301      qemu_printf("dumping local APIC state for CPU %-2u\n\n",
302                  CPU(cpu)->cpu_index);
303      dump_apic_lvt("LVT0", lvt[APIC_LVT_LINT0], false);
304      dump_apic_lvt("LVT1", lvt[APIC_LVT_LINT1], false);
305      dump_apic_lvt("LVTPC", lvt[APIC_LVT_PERFORM], false);
306      dump_apic_lvt("LVTERR", lvt[APIC_LVT_ERROR], false);
307      dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false);
308      dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true);
309  
310      qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u"
311                  " current_count = %u\n",
312                  s->divide_conf & APIC_DCR_MASK,
313                  divider_conf(s->divide_conf),
314                  s->initial_count, apic_get_current_count(s));
315  
316      qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
317                  s->spurious_vec,
318                  s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
319                  s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
320                  s->spurious_vec & APIC_VECTOR_MASK);
321  
322      dump_apic_icr(s, &cpu->env);
323  
324      qemu_printf("ESR\t 0x%08x\n", s->esr);
325  
326      dump_apic_interrupt("ISR", s->isr, s->tmr);
327      dump_apic_interrupt("IRR", s->irr, s->tmr);
328  
329      qemu_printf("\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
330                  s->arb_id, s->tpr, s->dest_mode, s->log_dest);
331      if (s->dest_mode == 0) {
332          qemu_printf("(cluster %u: id %u)",
333                      s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
334                      s->log_dest & APIC_LOGDEST_XAPIC_ID);
335      }
336      qemu_printf(" PPR 0x%02x\n", apic_get_ppr(s));
337  }
338  
339  #endif /* !CONFIG_USER_ONLY */
340  
341  #define DUMP_CODE_BYTES_TOTAL    50
342  #define DUMP_CODE_BYTES_BACKWARD 20
343  
x86_cpu_dump_state(CPUState * cs,FILE * f,int flags)344  void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags)
345  {
346      X86CPU *cpu = X86_CPU(cs);
347      CPUX86State *env = &cpu->env;
348      int eflags, i, nb;
349      static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
350  
351      eflags = cpu_compute_eflags(env);
352  #ifdef TARGET_X86_64
353      if (env->hflags & HF_CS64_MASK) {
354          qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
355                       "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
356                       "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
357                       "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
358                       "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
359                       env->regs[R_EAX],
360                       env->regs[R_EBX],
361                       env->regs[R_ECX],
362                       env->regs[R_EDX],
363                       env->regs[R_ESI],
364                       env->regs[R_EDI],
365                       env->regs[R_EBP],
366                       env->regs[R_ESP],
367                       env->regs[8],
368                       env->regs[9],
369                       env->regs[10],
370                       env->regs[11],
371                       env->regs[12],
372                       env->regs[13],
373                       env->regs[14],
374                       env->regs[15],
375                       env->eip, eflags,
376                       eflags & DF_MASK ? 'D' : '-',
377                       eflags & CC_O ? 'O' : '-',
378                       eflags & CC_S ? 'S' : '-',
379                       eflags & CC_Z ? 'Z' : '-',
380                       eflags & CC_A ? 'A' : '-',
381                       eflags & CC_P ? 'P' : '-',
382                       eflags & CC_C ? 'C' : '-',
383                       env->hflags & HF_CPL_MASK,
384                       (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
385                       (env->a20_mask >> 20) & 1,
386                       (env->hflags >> HF_SMM_SHIFT) & 1,
387                       cs->halted);
388      } else
389  #endif
390      {
391          qemu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
392                       "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
393                       "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
394                       (uint32_t)env->regs[R_EAX],
395                       (uint32_t)env->regs[R_EBX],
396                       (uint32_t)env->regs[R_ECX],
397                       (uint32_t)env->regs[R_EDX],
398                       (uint32_t)env->regs[R_ESI],
399                       (uint32_t)env->regs[R_EDI],
400                       (uint32_t)env->regs[R_EBP],
401                       (uint32_t)env->regs[R_ESP],
402                       (uint32_t)env->eip, eflags,
403                       eflags & DF_MASK ? 'D' : '-',
404                       eflags & CC_O ? 'O' : '-',
405                       eflags & CC_S ? 'S' : '-',
406                       eflags & CC_Z ? 'Z' : '-',
407                       eflags & CC_A ? 'A' : '-',
408                       eflags & CC_P ? 'P' : '-',
409                       eflags & CC_C ? 'C' : '-',
410                       env->hflags & HF_CPL_MASK,
411                       (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
412                       (env->a20_mask >> 20) & 1,
413                       (env->hflags >> HF_SMM_SHIFT) & 1,
414                       cs->halted);
415      }
416  
417      for(i = 0; i < 6; i++) {
418          cpu_x86_dump_seg_cache(env, f, seg_name[i], &env->segs[i]);
419      }
420      cpu_x86_dump_seg_cache(env, f, "LDT", &env->ldt);
421      cpu_x86_dump_seg_cache(env, f, "TR", &env->tr);
422  
423  #ifdef TARGET_X86_64
424      if (env->hflags & HF_LMA_MASK) {
425          qemu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
426                       env->gdt.base, env->gdt.limit);
427          qemu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
428                       env->idt.base, env->idt.limit);
429          qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
430                       (uint32_t)env->cr[0],
431                       env->cr[2],
432                       env->cr[3],
433                       (uint32_t)env->cr[4]);
434          for(i = 0; i < 4; i++)
435              qemu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
436          qemu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
437                       env->dr[6], env->dr[7]);
438      } else
439  #endif
440      {
441          qemu_fprintf(f, "GDT=     %08x %08x\n",
442                       (uint32_t)env->gdt.base, env->gdt.limit);
443          qemu_fprintf(f, "IDT=     %08x %08x\n",
444                       (uint32_t)env->idt.base, env->idt.limit);
445          qemu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
446                       (uint32_t)env->cr[0],
447                       (uint32_t)env->cr[2],
448                       (uint32_t)env->cr[3],
449                       (uint32_t)env->cr[4]);
450          for(i = 0; i < 4; i++) {
451              qemu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
452          }
453          qemu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
454                       env->dr[6], env->dr[7]);
455      }
456      if (flags & CPU_DUMP_CCOP) {
457          const char *cc_op_name = NULL;
458          char cc_op_buf[32];
459  
460          if ((unsigned)env->cc_op < ARRAY_SIZE(cc_op_str)) {
461              cc_op_name = cc_op_str[env->cc_op];
462          }
463          if (cc_op_name == NULL) {
464              snprintf(cc_op_buf, sizeof(cc_op_buf), "[%d]", env->cc_op);
465              cc_op_name = cc_op_buf;
466          }
467  #ifdef TARGET_X86_64
468          if (env->hflags & HF_CS64_MASK) {
469              qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%s\n",
470                           env->cc_src, env->cc_dst,
471                           cc_op_name);
472          } else
473  #endif
474          {
475              qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%s\n",
476                           (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
477                           cc_op_name);
478          }
479      }
480      qemu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
481      if (flags & CPU_DUMP_FPU) {
482          int fptag;
483          const uint64_t avx512_mask = XSTATE_OPMASK_MASK | \
484                                       XSTATE_ZMM_Hi256_MASK | \
485                                       XSTATE_Hi16_ZMM_MASK | \
486                                       XSTATE_YMM_MASK | XSTATE_SSE_MASK,
487                         avx_mask = XSTATE_YMM_MASK | XSTATE_SSE_MASK;
488          fptag = 0;
489          for(i = 0; i < 8; i++) {
490              fptag |= ((!env->fptags[i]) << i);
491          }
492          update_mxcsr_from_sse_status(env);
493          qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
494                       env->fpuc,
495                       (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
496                       env->fpstt,
497                       fptag,
498                       env->mxcsr);
499          for(i=0;i<8;i++) {
500              CPU_LDoubleU u;
501              u.d = env->fpregs[i].d;
502              qemu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
503                           i, u.l.lower, u.l.upper);
504              if ((i & 1) == 1)
505                  qemu_fprintf(f, "\n");
506              else
507                  qemu_fprintf(f, " ");
508          }
509  
510          if ((env->xcr0 & avx512_mask) == avx512_mask) {
511              /* XSAVE enabled AVX512 */
512              for (i = 0; i < NB_OPMASK_REGS; i++) {
513                  qemu_fprintf(f, "Opmask%02d=%016"PRIx64"%s", i,
514                               env->opmask_regs[i], ((i & 3) == 3) ? "\n" : " ");
515              }
516  
517              nb = (env->hflags & HF_CS64_MASK) ? 32 : 8;
518              for (i = 0; i < nb; i++) {
519                  qemu_fprintf(f, "ZMM%02d=%016"PRIx64" %016"PRIx64" %016"PRIx64
520                               " %016"PRIx64" %016"PRIx64" %016"PRIx64
521                               " %016"PRIx64" %016"PRIx64"\n",
522                               i,
523                               env->xmm_regs[i].ZMM_Q(7),
524                               env->xmm_regs[i].ZMM_Q(6),
525                               env->xmm_regs[i].ZMM_Q(5),
526                               env->xmm_regs[i].ZMM_Q(4),
527                               env->xmm_regs[i].ZMM_Q(3),
528                               env->xmm_regs[i].ZMM_Q(2),
529                               env->xmm_regs[i].ZMM_Q(1),
530                               env->xmm_regs[i].ZMM_Q(0));
531              }
532          } else if ((env->xcr0 & avx_mask)  == avx_mask) {
533              /* XSAVE enabled AVX */
534              nb = env->hflags & HF_CS64_MASK ? 16 : 8;
535              for (i = 0; i < nb; i++) {
536                  qemu_fprintf(f, "YMM%02d=%016"PRIx64" %016"PRIx64" %016"PRIx64
537                               " %016"PRIx64"\n", i,
538                               env->xmm_regs[i].ZMM_Q(3),
539                               env->xmm_regs[i].ZMM_Q(2),
540                               env->xmm_regs[i].ZMM_Q(1),
541                               env->xmm_regs[i].ZMM_Q(0));
542              }
543          } else { /* SSE and below cases */
544              nb = env->hflags & HF_CS64_MASK ? 16 : 8;
545              for (i = 0; i < nb; i++) {
546                  qemu_fprintf(f, "XMM%02d=%016"PRIx64" %016"PRIx64"%s",
547                               i,
548                               env->xmm_regs[i].ZMM_Q(1),
549                               env->xmm_regs[i].ZMM_Q(0),
550                               (i & 1) ? "\n" : " ");
551              }
552          }
553      }
554      if (flags & CPU_DUMP_CODE) {
555          target_ulong base = env->segs[R_CS].base + env->eip;
556          target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
557          uint8_t code;
558          char codestr[3];
559  
560          qemu_fprintf(f, "Code=");
561          for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
562              if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
563                  snprintf(codestr, sizeof(codestr), "%02x", code);
564              } else {
565                  snprintf(codestr, sizeof(codestr), "??");
566              }
567              qemu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
568                           i == offs ? "<" : "", codestr, i == offs ? ">" : "");
569          }
570          qemu_fprintf(f, "\n");
571      }
572  }
573