From 6ba169fcdee9a500d13112a06ae5b1dc9a5761a5 Mon Sep 17 00:00:00 2001 From: Mukesh Rathor Date: Mon, 24 Feb 2014 13:38:49 -0800 Subject: [PATCH] KDB: initial patch Signed-off-by: Mukesh Rathor --- xen/Makefile | 3 +- xen/Rules.mk | 3 + xen/arch/x86/hvm/svm/entry.S | 9 + xen/arch/x86/hvm/svm/svm.c | 8 + xen/arch/x86/hvm/svm/vmcb.c | 30 + xen/arch/x86/hvm/vmx/entry.S | 8 + xen/arch/x86/hvm/vmx/vmcs.c | 219 +++ xen/arch/x86/hvm/vmx/vmx.c | 25 +- xen/arch/x86/irq.c | 26 + xen/arch/x86/setup.c | 12 + xen/arch/x86/smp.c | 4 +- xen/arch/x86/time.c | 40 + xen/arch/x86/traps.c | 6 +- xen/arch/x86/x86_64/compat/entry.S | 4 + xen/arch/x86/x86_64/entry.S | 11 + xen/common/domain.c | 8 + xen/common/sched_credit.c | 31 + xen/common/schedule.c | 19 + xen/common/smp.c | 7 +- xen/common/symbols.c | 18 + xen/common/timer.c | 42 + xen/drivers/char/console.c | 27 + xen/include/asm-x86/debugger.h | 10 +- xen/include/xen/lib.h | 3 + xen/include/xen/sched.h | 5 +- xen/include/xen/smp.h | 2 +- xen/kdb/Makefile | 5 + xen/kdb/README | 243 +++ xen/kdb/guest/Makefile | 3 + xen/kdb/guest/kdb_guest.c | 342 ++++ xen/kdb/include/kdb_extern.h | 63 + xen/kdb/include/kdbdefs.h | 86 + xen/kdb/include/kdbinc.h | 70 + xen/kdb/include/kdbproto.h | 80 + xen/kdb/kdb_cmds.c | 3815 ++++++++++++++++++++++++++++++++++++ xen/kdb/kdb_io.c | 174 ++ xen/kdb/kdbmain.c | 746 +++++++ xen/kdb/x86/Makefile | 3 + xen/kdb/x86/kdb_wp.c | 310 +++ xen/kdb/x86/udis86-1.7/LICENSE | 22 + xen/kdb/x86/udis86-1.7/Makefile | 5 + xen/kdb/x86/udis86-1.7/README | 10 + xen/kdb/x86/udis86-1.7/decode.c | 1197 +++++++++++ xen/kdb/x86/udis86-1.7/decode.h | 273 +++ xen/kdb/x86/udis86-1.7/extern.h | 67 + xen/kdb/x86/udis86-1.7/input.c | 226 +++ xen/kdb/x86/udis86-1.7/input.h | 49 + xen/kdb/x86/udis86-1.7/itab.c | 3668 ++++++++++++++++++++++++++++++++++ xen/kdb/x86/udis86-1.7/itab.h | 719 +++++++ xen/kdb/x86/udis86-1.7/kdb_dis.c | 204 ++ xen/kdb/x86/udis86-1.7/syn-att.c | 211 ++ xen/kdb/x86/udis86-1.7/syn-intel.c | 208 ++ xen/kdb/x86/udis86-1.7/syn.c | 61 + xen/kdb/x86/udis86-1.7/syn.h | 27 + xen/kdb/x86/udis86-1.7/types.h | 186 ++ xen/kdb/x86/udis86-1.7/udis86.c | 156 ++ 56 files changed, 13799 insertions(+), 10 deletions(-) create mode 100644 xen/kdb/Makefile create mode 100644 xen/kdb/README create mode 100644 xen/kdb/guest/Makefile create mode 100644 xen/kdb/guest/kdb_guest.c create mode 100644 xen/kdb/include/kdb_extern.h create mode 100644 xen/kdb/include/kdbdefs.h create mode 100644 xen/kdb/include/kdbinc.h create mode 100644 xen/kdb/include/kdbproto.h create mode 100644 xen/kdb/kdb_cmds.c create mode 100644 xen/kdb/kdb_io.c create mode 100644 xen/kdb/kdbmain.c create mode 100644 xen/kdb/x86/Makefile create mode 100644 xen/kdb/x86/kdb_wp.c create mode 100644 xen/kdb/x86/udis86-1.7/LICENSE create mode 100644 xen/kdb/x86/udis86-1.7/Makefile create mode 100644 xen/kdb/x86/udis86-1.7/README create mode 100644 xen/kdb/x86/udis86-1.7/decode.c create mode 100644 xen/kdb/x86/udis86-1.7/decode.h create mode 100644 xen/kdb/x86/udis86-1.7/extern.h create mode 100644 xen/kdb/x86/udis86-1.7/input.c create mode 100644 xen/kdb/x86/udis86-1.7/input.h create mode 100644 xen/kdb/x86/udis86-1.7/itab.c create mode 100644 xen/kdb/x86/udis86-1.7/itab.h create mode 100644 xen/kdb/x86/udis86-1.7/kdb_dis.c create mode 100644 xen/kdb/x86/udis86-1.7/syn-att.c create mode 100644 xen/kdb/x86/udis86-1.7/syn-intel.c create mode 100644 xen/kdb/x86/udis86-1.7/syn.c create mode 100644 xen/kdb/x86/udis86-1.7/syn.h create mode 100644 xen/kdb/x86/udis86-1.7/types.h create mode 100644 xen/kdb/x86/udis86-1.7/udis86.c diff --git a/xen/Makefile b/xen/Makefile index 79fa8f2..9897ff9 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -84,6 +84,7 @@ _clean: delete-unfresh-files $(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean $(MAKE) -f $(BASEDIR)/Rules.mk -C crypto clean $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C kdb clean rm -f include/asm *.o $(TARGET) $(TARGET).gz $(TARGET)-syms *~ core rm -f include/asm-*/asm-offsets.h rm -f .banner @@ -154,7 +155,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s echo ""; \ echo "#endif") <$< >$@ -SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers +SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers kdb define all_sources ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \ find include -name 'asm-*' -prune -o -name '*.h' -print; \ diff --git a/xen/Rules.mk b/xen/Rules.mk index 3a6cec5..0f59d59 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -10,6 +10,7 @@ lock_profile ?= n crash_debug ?= n frame_pointer ?= n lto ?= n +kdb ?= n include $(XEN_ROOT)/Config.mk @@ -40,6 +41,7 @@ ALL_OBJS-y += $(BASEDIR)/drivers/built_in.o ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o ALL_OBJS-$(x86) += $(BASEDIR)/crypto/built_in.o +ALL_OBJS-$(kdb) += $(BASEDIR)/kdb/built_in.o CFLAGS += -fno-builtin -fno-common CFLAGS += -Werror -Wredundant-decls -Wno-pointer-arith @@ -61,6 +63,7 @@ CFLAGS-$(HAS_DEVICE_TREE) += -DHAS_DEVICE_TREE CFLAGS-$(HAS_PCI) += -DHAS_PCI CFLAGS-$(HAS_IOPORTS) += -DHAS_IOPORTS CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER +CFLAGS-$(kdb) += -DXEN_KDB_CONFIG ifneq ($(max_phys_cpus),) CFLAGS-y += -DMAX_PHYS_CPUS=$(max_phys_cpus) diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S index ef4d5f4..42def7f 100644 --- a/xen/arch/x86/hvm/svm/entry.S +++ b/xen/arch/x86/hvm/svm/entry.S @@ -39,6 +39,10 @@ ENTRY(svm_asm_do_resume) call nsvm_vcpu_switch ASSERT_NOT_IN_ATOMIC +#ifdef XEN_KDB_CONFIG + testl $1, kdb_session_begun(%rip) + jnz .Lkdb_skip_softirq +#endif mov VCPU_processor(%rbx),%eax lea irq_stat+IRQSTAT_softirq_pending(%rip),%rdx xor %ecx,%ecx @@ -47,6 +51,11 @@ ENTRY(svm_asm_do_resume) cmp %ecx,(%rdx,%rax,1) jne .Lsvm_process_softirqs +#ifdef XEN_KDB_CONFIG +.Lkdb_skip_softirq: + xor %ecx,%ecx +#endif + cmp %cl,VCPU_nsvm_hap_enabled(%rbx) UNLIKELY_START(ne, nsvm_hap) cmp %rcx,VCPU_nhvm_p2m(%rbx) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 406d394..c17f5ba 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2203,6 +2203,10 @@ void svm_vmexit_handler(struct cpu_user_regs *regs) break; case VMEXIT_EXCEPTION_DB: +#ifdef XEN_KDB_CONFIG + if (kdb_handle_trap_entry(TRAP_debug, regs)) + break; +#endif if ( !v->domain->debugger_attached ) goto exit_and_crash; domain_pause_for_debugger(); @@ -2215,6 +2219,10 @@ void svm_vmexit_handler(struct cpu_user_regs *regs) if ( (inst_len = __get_instruction_length(v, INSTR_INT3)) == 0 ) break; __update_guest_eip(regs, inst_len); +#ifdef XEN_KDB_CONFIG + if (kdb_handle_trap_entry(TRAP_int3, regs)) + break; +#endif current->arch.gdbsx_vcpu_event = TRAP_int3; domain_pause_for_debugger(); break; diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 21292bb..1d15d7a 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -315,6 +315,36 @@ void __init setup_vmcb_dump(void) register_keyhandler('v', &vmcb_dump_keyhandler); } +#if defined(XEN_KDB_CONFIG) +/* did == 0 : display for all HVM domains. domid 0 is never HVM. + * vid == -1 : display for all HVM VCPUs + */ +void kdb_dump_vmcb(domid_t did, int vid) +{ + struct domain *dp; + struct vcpu *vp; + + rcu_read_lock(&domlist_read_lock); + for_each_domain (dp) { + if (is_pv_domain(dp) || dp->is_dying) + continue; + if (did != 0 && did != dp->domain_id) + continue; + + for_each_vcpu (dp, vp) { + if (vid != -1 && vid != vp->vcpu_id) + continue; + + kdbp(" VMCB [domid: %d vcpu:%d]:\n", dp->domain_id, vp->vcpu_id); + svm_vmcb_dump("kdb", vp->arch.hvm_svm.vmcb); + kdbp("\n"); + } + kdbp("\n"); + } + rcu_read_unlock(&domlist_read_lock); +} +#endif + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/vmx/entry.S b/xen/arch/x86/hvm/vmx/entry.S index 664ed83..475981f 100644 --- a/xen/arch/x86/hvm/vmx/entry.S +++ b/xen/arch/x86/hvm/vmx/entry.S @@ -59,6 +59,10 @@ ENTRY(vmx_asm_vmexit_handler) call nvmx_switch_guest ASSERT_NOT_IN_ATOMIC +#ifdef XEN_KDB_CONFIG + testl $1, kdb_session_begun(%rip) + jnz .Lkdb_skip_softirq +#endif mov VCPU_processor(%rbx),%eax lea irq_stat+IRQSTAT_softirq_pending(%rip),%rdx xor %ecx,%ecx @@ -67,6 +71,10 @@ ENTRY(vmx_asm_vmexit_handler) cmp %ecx,(%rdx,%rax,1) jnz .Lvmx_process_softirqs +#ifdef XEN_KDB_CONFIG +.Lkdb_skip_softirq: + xor %ecx,%ecx +#endif cmp %cl,VCPU_vmx_emulate(%rbx) jne .Lvmx_goto_emulator cmp %cl,VCPU_vmx_realmode(%rbx) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 44f33cb..efd0953 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -1351,6 +1351,10 @@ void vmx_do_resume(struct vcpu *v) hvm_asid_flush_vcpu(v); } +#if defined(XEN_KDB_CONFIG) + __vmwrite(GUEST_DR7, kdb_dr7); +#endif + debug_state = v->domain->debugger_attached || v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_INT3] || v->domain->arch.hvm_domain.params[HVM_PARAM_MEMORY_EVENT_SINGLE_STEP]; @@ -1559,6 +1563,221 @@ void __init setup_vmcs_dump(void) register_keyhandler('v', &vmcs_dump_keyhandler); } +#if defined(XEN_KDB_CONFIG) +#define GUEST_EFER 0x2806 /* see Intel SDM page 23-20 */ +#define GUEST_EFER_HIGH 0x2807 /* see Intel SDM page 23-20 */ + +/* it's a shame we can't use vmcs_dump_vcpu(), but it does vmx_vmcs_enter which + * will IPI other CPUs. also, print a subset relevant to software debugging */ +static void noinline kdb_print_vmcs(struct vcpu *vp) +{ + struct cpu_user_regs *regs = &vp->arch.user_regs; + unsigned long long x; + + kdbp("*** Guest State ***\n"); + kdbp("CR0: actual=0x%016llx, shadow=0x%016llx, gh_mask=%016llx\n", + (unsigned long long)vmr(GUEST_CR0), + (unsigned long long)vmr(CR0_READ_SHADOW), + (unsigned long long)vmr(CR0_GUEST_HOST_MASK)); + kdbp("CR4: actual=0x%016llx, shadow=0x%016llx, gh_mask=%016llx\n", + (unsigned long long)vmr(GUEST_CR4), + (unsigned long long)vmr(CR4_READ_SHADOW), + (unsigned long long)vmr(CR4_GUEST_HOST_MASK)); + kdbp("CR3: actual=0x%016llx, target_count=%d\n", + (unsigned long long)vmr(GUEST_CR3), + (int)vmr(CR3_TARGET_COUNT)); + kdbp(" target0=%016llx, target1=%016llx\n", + (unsigned long long)vmr(CR3_TARGET_VALUE0), + (unsigned long long)vmr(CR3_TARGET_VALUE1)); + kdbp(" target2=%016llx, target3=%016llx\n", + (unsigned long long)vmr(CR3_TARGET_VALUE2), + (unsigned long long)vmr(CR3_TARGET_VALUE3)); + kdbp("RSP = 0x%016llx (0x%016llx) RIP = 0x%016llx (0x%016llx)\n", + (unsigned long long)vmr(GUEST_RSP), + (unsigned long long)regs->esp, + (unsigned long long)vmr(GUEST_RIP), + (unsigned long long)regs->eip); + kdbp("RFLAGS=0x%016llx (0x%016llx) DR7 = 0x%016llx\n", + (unsigned long long)vmr(GUEST_RFLAGS), + (unsigned long long)regs->eflags, + (unsigned long long)vmr(GUEST_DR7)); + kdbp("Sysenter RSP=%016llx CS:RIP=%04x:%016llx\n", + (unsigned long long)vmr(GUEST_SYSENTER_ESP), + (int)vmr(GUEST_SYSENTER_CS), + (unsigned long long)vmr(GUEST_SYSENTER_EIP)); + vmx_dump_sel("CS", GUEST_CS_SELECTOR); + vmx_dump_sel("DS", GUEST_DS_SELECTOR); + vmx_dump_sel("SS", GUEST_SS_SELECTOR); + vmx_dump_sel("ES", GUEST_ES_SELECTOR); + vmx_dump_sel("FS", GUEST_FS_SELECTOR); + vmx_dump_sel("GS", GUEST_GS_SELECTOR); + vmx_dump_sel2("GDTR", GUEST_GDTR_LIMIT); + vmx_dump_sel("LDTR", GUEST_LDTR_SELECTOR); + vmx_dump_sel2("IDTR", GUEST_IDTR_LIMIT); + vmx_dump_sel("TR", GUEST_TR_SELECTOR); + kdbp("Guest EFER = 0x%08x%08x\n", + (uint32_t)vmr(GUEST_EFER_HIGH), (uint32_t)vmr(GUEST_EFER)); + kdbp("Guest PAT = 0x%08x%08x\n", + (uint32_t)vmr(GUEST_PAT_HIGH), (uint32_t)vmr(GUEST_PAT)); + x = (unsigned long long)vmr(TSC_OFFSET_HIGH) << 32; + x |= (uint32_t)vmr(TSC_OFFSET); + kdbp("TSC Offset = %016llx\n", x); + x = (unsigned long long)vmr(GUEST_IA32_DEBUGCTL_HIGH) << 32; + x |= (uint32_t)vmr(GUEST_IA32_DEBUGCTL); + kdbp("DebugCtl=%016llx DebugExceptions=%016llx\n", x, + (unsigned long long)vmr(GUEST_PENDING_DBG_EXCEPTIONS)); + kdbp("Interruptibility=%04x ActivityState=%04x\n", + (int)vmr(GUEST_INTERRUPTIBILITY_INFO), + (int)vmr(GUEST_ACTIVITY_STATE)); + + kdbp("MSRs: entry_load:$%d exit_load:$%d exit_store:$%d\n", + vmr(VM_ENTRY_MSR_LOAD_COUNT), vmr(VM_EXIT_MSR_LOAD_COUNT), + vmr(VM_EXIT_MSR_STORE_COUNT)); + + kdbp("\n*** Host State ***\n"); + kdbp("RSP = 0x%016llx RIP = 0x%016llx\n", + (unsigned long long)vmr(HOST_RSP), + (unsigned long long)vmr(HOST_RIP)); + kdbp("CS=%04x DS=%04x ES=%04x FS=%04x GS=%04x SS=%04x TR=%04x\n", + (uint16_t)vmr(HOST_CS_SELECTOR), + (uint16_t)vmr(HOST_DS_SELECTOR), + (uint16_t)vmr(HOST_ES_SELECTOR), + (uint16_t)vmr(HOST_FS_SELECTOR), + (uint16_t)vmr(HOST_GS_SELECTOR), + (uint16_t)vmr(HOST_SS_SELECTOR), + (uint16_t)vmr(HOST_TR_SELECTOR)); + kdbp("FSBase=%016llx GSBase=%016llx TRBase=%016llx\n", + (unsigned long long)vmr(HOST_FS_BASE), + (unsigned long long)vmr(HOST_GS_BASE), + (unsigned long long)vmr(HOST_TR_BASE)); + kdbp("GDTBase=%016llx IDTBase=%016llx\n", + (unsigned long long)vmr(HOST_GDTR_BASE), + (unsigned long long)vmr(HOST_IDTR_BASE)); + kdbp("CR0=%016llx CR3=%016llx CR4=%016llx\n", + (unsigned long long)vmr(HOST_CR0), + (unsigned long long)vmr(HOST_CR3), + (unsigned long long)vmr(HOST_CR4)); + kdbp("Sysenter RSP=%016llx CS:RIP=%04x:%016llx\n", + (unsigned long long)vmr(HOST_SYSENTER_ESP), + (int)vmr(HOST_SYSENTER_CS), + (unsigned long long)vmr(HOST_SYSENTER_EIP)); + kdbp("Host PAT = 0x%08x%08x\n", + (uint32_t)vmr(HOST_PAT_HIGH), (uint32_t)vmr(HOST_PAT)); + + kdbp("\n*** Control State ***\n"); + kdbp("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n", + (uint32_t)vmr(PIN_BASED_VM_EXEC_CONTROL), + (uint32_t)vmr(CPU_BASED_VM_EXEC_CONTROL), + (uint32_t)vmr(SECONDARY_VM_EXEC_CONTROL)); + kdbp("EntryControls=%08x ExitControls=%08x\n", + (uint32_t)vmr(VM_ENTRY_CONTROLS), + (uint32_t)vmr(VM_EXIT_CONTROLS)); + kdbp("ExceptionBitmap=%08x\n", + (uint32_t)vmr(EXCEPTION_BITMAP)); + kdbp("PAGE_FAULT_ERROR_CODE MASK:0x%lx MATCH:0x%lx\n", + (unsigned long)vmr(PAGE_FAULT_ERROR_CODE_MASK), + (unsigned long)vmr(PAGE_FAULT_ERROR_CODE_MATCH)); + kdbp("VMEntry: intr_info=%08x errcode=%08x ilen=%08x\n", + (uint32_t)vmr(VM_ENTRY_INTR_INFO), + (uint32_t)vmr(VM_ENTRY_EXCEPTION_ERROR_CODE), + (uint32_t)vmr(VM_ENTRY_INSTRUCTION_LEN)); + kdbp("VMExit: intr_info=%08x errcode=%08x ilen=%08x\n", + (uint32_t)vmr(VM_EXIT_INTR_INFO), + (uint32_t)vmr(VM_EXIT_INTR_ERROR_CODE), + (uint32_t)vmr(VM_ENTRY_INSTRUCTION_LEN)); + kdbp(" reason=%08x qualification=%08x\n", + (uint32_t)vmr(VM_EXIT_REASON), + (uint32_t)vmr(EXIT_QUALIFICATION)); + kdbp("IDTVectoring: info=%08x errcode=%08x\n", + (uint32_t)vmr(IDT_VECTORING_INFO), + (uint32_t)vmr(IDT_VECTORING_ERROR_CODE)); + kdbp("TPR Threshold = 0x%02x\n", + (uint32_t)vmr(TPR_THRESHOLD)); + kdbp("EPT pointer = 0x%08x%08x\n", + (uint32_t)vmr(EPT_POINTER_HIGH), (uint32_t)vmr(EPT_POINTER)); + kdbp("Virtual processor ID = 0x%04x\n", + (uint32_t)vmr(VIRTUAL_PROCESSOR_ID)); + kdbp("=================================================================\n"); +} + +/* Flush VMCS on this cpu if it needs to: + * - Upon leaving kdb, the HVM cpu will resume in vmx_vmexit_handler() and + * do __vmreads. So, the VMCS pointer can't be left cleared. + * - Doing __vmpclear will set the vmx state to 'clear', so to resume a + * vmlaunch must be done and not vmresume. This means, we must clear + * arch_vmx->launched. + */ +void kdb_curr_cpu_flush_vmcs(void) +{ + struct domain *dp; + struct vcpu *vp; + int ccpu = smp_processor_id(); + struct vmcs_struct *cvp = this_cpu(current_vmcs); + + if (this_cpu(current_vmcs) == NULL) + return; /* no HVM active on this CPU */ + + kdbp("KDB:[%d] curvmcs:%lx/%lx\n", ccpu, cvp, virt_to_maddr(cvp)); + + /* looks like we got one. unfortunately, current_vmcs points to vmcs + * and not VCPU, so we gotta search the entire list... */ + for_each_domain (dp) { + if ( is_pv_domain(dp) || dp->is_dying ) + continue; + for_each_vcpu (dp, vp) { + if ( vp->arch.hvm_vmx.vmcs == cvp ) { + __vmpclear(virt_to_maddr(vp->arch.hvm_vmx.vmcs)); + __vmptrld(virt_to_maddr(vp->arch.hvm_vmx.vmcs)); + vp->arch.hvm_vmx.launched = 0; + this_cpu(current_vmcs) = NULL; + kdbp("KDB:[%d] %d:%d current_vmcs:%lx flushed\n", + ccpu, dp->domain_id, vp->vcpu_id, cvp, virt_to_maddr(cvp)); + } + } + } +} + +/* + * domid == 0 : display for all HVM domains (dom0 is never an HVM domain) + * vcpu id == -1 : display all vcpuids + * PreCondition: all HVM cpus (including current cpu) have flushed VMCS + */ +void kdb_dump_vmcs(domid_t did, int vid) +{ + struct domain *dp; + struct vcpu *vp; + struct vmcs_struct *vmcsp; + u64 addr = -1; + + ASSERT(!local_irq_is_enabled()); /* kdb should always run disabled */ + __vmptrst(&addr); + + for_each_domain ( dp ) + { + if ( is_pv_domain(dp) || dp->is_dying ) + continue; + if ( did != 0 && did != dp->domain_id ) + continue; + + for_each_vcpu (dp, vp) { + if ( vid != -1 && vid != vp->vcpu_id ) + continue; + + vmcsp = vp->arch.hvm_vmx.vmcs; + kdbp("VMCS %lx/%lx [domid:%d (%p) vcpu:%d (%p)]:\n", vmcsp, + virt_to_maddr(vmcsp), dp->domain_id, dp, vp->vcpu_id, vp); + __vmptrld(virt_to_maddr(vmcsp)); + kdb_print_vmcs(vp); + __vmpclear(virt_to_maddr(vmcsp)); + vp->arch.hvm_vmx.launched = 0; + } + kdbp("\n"); + } + /* restore orig vmcs pointer for __vmreads in vmx_vmexit_handler() */ + if (addr && addr != (u64)-1) + __vmptrld(addr); +} +#endif /* * Local variables: diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index f6409d6..2eff0d3 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2355,11 +2355,14 @@ static void vmx_failed_vmentry(unsigned int exit_reason, printk("reason not known yet!"); break; } - +#if defined(XEN_KDB_CONFIG) + kdbp("\n************* VMCS Area **************\n"); + kdb_dump_vmcs(curr->domain->domain_id, (curr)->vcpu_id); +#else printk("************* VMCS Area **************\n"); vmcs_dump_vcpu(curr); printk("**************************************\n"); - +#endif domain_crash(curr->domain); } @@ -2639,6 +2642,12 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) write_debugreg(6, exit_qualification | 0xffff0ff0); if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag ) goto exit_and_crash; + +#if defined(XEN_KDB_CONFIG) + /* TRAP_debug: IP points correctly to next instr */ + if (kdb_handle_trap_entry(vector, regs)) + break; +#endif domain_pause_for_debugger(); break; case TRAP_int3: @@ -2647,6 +2656,14 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) if ( v->domain->debugger_attached ) { update_guest_eip(); /* Safe: INT3 */ +#if defined(XEN_KDB_CONFIG) + /* + * vmcs.IP points to bp, kdb expects bp+1. Hence after above + * update_guest_eip which updates to bp+1. works for gdbsx too. + */ + if (kdb_handle_trap_entry(vector, regs)) + break; +#endif current->arch.gdbsx_vcpu_event = TRAP_int3; domain_pause_for_debugger(); break; @@ -2957,6 +2974,10 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) case EXIT_REASON_MONITOR_TRAP_FLAG: v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG; vmx_update_cpu_exec_control(v); +#if defined(XEN_KDB_CONFIG) + if (kdb_handle_trap_entry(TRAP_debug, regs)) + break; +#endif if ( v->arch.hvm_vcpu.single_step ) { hvm_memory_event_single_step(regs->eip); if ( v->domain->debugger_attached ) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index db70077..e235b4d 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -2484,3 +2484,29 @@ bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq) return is_hvm_domain(d) && pirq && pirq->arch.hvm.emuirq != IRQ_UNBOUND; } + +#ifdef XEN_KDB_CONFIG +void kdb_prnt_guest_mapped_irqs(void) +{ + int irq, j; + char affstr[NR_CPUS/4+NR_CPUS/32+2]; /* courtesy dump_irqs() */ + + kdbp("irq vec aff type domid:mapped-pirq pairs (all in decimal)\n"); + for (irq=0; irq < nr_irqs; irq++) { + irq_desc_t *dp = irq_to_desc(irq); + struct arch_irq_desc *archp = &dp->arch; + irq_guest_action_t *actp = (irq_guest_action_t *)dp->action; + + if (!dp->handler ||dp->handler==&no_irq_type || !(dp->status&IRQ_GUEST)) + continue; + + cpumask_scnprintf(affstr, sizeof(affstr), dp->affinity); + kdbp("[%3ld] %3d %3s %-13s ", irq, archp->vector, affstr, + dp->handler->typename); + for (j=0; j < actp->nr_guests; j++) + kdbp("%03d:%04d ", actp->guest[j]->domain_id, + domain_irq_to_pirq(actp->guest[j], irq)); + kdbp("\n"); + } +} +#endif diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index b49256d..058dcaa 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -49,6 +49,13 @@ #include #include +#ifdef XEN_KDB_CONFIG +#include + +int opt_earlykdb=0; +boolean_param("earlykdb", opt_earlykdb); +#endif + /* opt_nosmp: If true, secondary processors are ignored. */ static bool_t __initdata opt_nosmp; boolean_param("nosmp", opt_nosmp); @@ -1265,6 +1272,11 @@ void __init __start_xen(unsigned long mbi_p) trap_init(); +#ifdef XEN_KDB_CONFIG + kdb_init(); + if (opt_earlykdb) + kdb_trap_immed(KDB_TRAP_NONFATAL); +#endif rcu_init(); early_time_init(); diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index 0433f30..9416c93 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -276,7 +276,7 @@ void smp_send_call_function_mask(const cpumask_t *mask) if ( cpumask_test_cpu(smp_processor_id(), mask) ) { local_irq_disable(); - smp_call_function_interrupt(); + smp_call_function_interrupt(NULL); local_irq_enable(); } } @@ -343,5 +343,5 @@ void call_function_interrupt(struct cpu_user_regs *regs) { ack_APIC_irq(); perfc_incr(ipis); - smp_call_function_interrupt(); + smp_call_function_interrupt(regs); } diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 6e31e1f..b09aa4a 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -1978,6 +1978,46 @@ static int __init setup_dump_softtsc(void) } __initcall(setup_dump_softtsc); +#ifdef XEN_KDB_CONFIG +void kdb_time_resume(int update_domains) +{ + s_time_t now; + int ccpu = smp_processor_id(); + struct cpu_time *t = &this_cpu(cpu_time); + + if (!plt_src.read_counter) /* not initialized for earlykdb */ + return; + + if (update_domains) { + plt_stamp = plt_src.read_counter(); + platform_timer_stamp = plt_stamp64; + platform_time_calibration(); + do_settime(get_cmos_time(), 0, read_platform_stime()); + } + if (local_irq_is_enabled()) + kdbp("kdb BUG: enabled in time_resume(). ccpu:%d\n", ccpu); + + rdtscll(t->local_tsc_stamp); + now = read_platform_stime(); + t->stime_master_stamp = now; + t->stime_local_stamp = now; + + update_vcpu_system_time(current); + + if (update_domains) + set_timer(&calibration_timer, NOW() + EPOCH); +} + +void kdb_dump_time_pcpu(void) +{ + int cpu; + for_each_online_cpu(cpu) { + kdbp("[%d]: cpu_time: %016lx\n", cpu, &per_cpu(cpu_time, cpu)); + kdbp("[%d]: cpu_calibration: %016lx\n", cpu, + &per_cpu(cpu_calibration, cpu)); + } +} +#endif /* * Local variables: * mode: C diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 0bd43b9..9605275 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -260,7 +260,7 @@ static void _show_trace(unsigned long sp, unsigned long bp) #endif -static void show_trace(const struct cpu_user_regs *regs) +void show_trace(const struct cpu_user_regs *regs) { unsigned long *sp = ESP_BEFORE_EXCEPTION(regs); @@ -3232,6 +3232,10 @@ void do_nmi(struct cpu_user_regs *regs) if ( nmi_callback(regs, cpu) ) return; +#ifdef XEN_KDB_CONFIG + if (kdb_enabled && kdb_handle_trap_entry(TRAP_nmi, regs)) + return; +#endif if ( nmi_watchdog ) nmi_watchdog_tick(regs); diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 594b0b9..c1cde24 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -94,6 +94,10 @@ compat_skip_clobber: ENTRY(compat_test_all_events) ASSERT_NOT_IN_ATOMIC cli # tests must not race interrupts +#ifdef XEN_KDB_CONFIG + testl $1, kdb_session_begun(%rip) + jnz compat_restore_all_guest +#endif /*compat_test_softirqs:*/ movl VCPU_processor(%rbx),%eax shll $IRQSTAT_shift,%eax diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 3ea4683..fe4bd7e 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -193,6 +193,10 @@ skip_clobber: test_all_events: ASSERT_NOT_IN_ATOMIC cli # tests must not race interrupts +#ifdef XEN_KDB_CONFIG /* 64bit dom0 will resume here */ + testl $1, kdb_session_begun(%rip) + jnz restore_all_guest +#endif /*test_softirqs:*/ movl VCPU_processor(%rbx),%eax shll $IRQSTAT_shift,%eax @@ -558,6 +562,13 @@ ENTRY(debug) ENTRY(int3) pushq $0 +#ifdef XEN_KDB_CONFIG + pushq %rax + GET_CPUINFO_FIELD(processor_id, %rax) + movq (%rax), %rax + lock bts %rax, kdb_cpu_traps(%rip) + popq %rax +#endif movl $TRAP_int3,4(%rsp) jmp handle_exception diff --git a/xen/common/domain.c b/xen/common/domain.c index 2636fc9..93458d6 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -593,6 +593,14 @@ void domain_shutdown(struct domain *d, u8 reason) { struct vcpu *v; +#ifdef XEN_KDB_CONFIG + if (reason == SHUTDOWN_crash) { + if ( is_hardware_domain(d) ) + kdb_trap_immed(KDB_TRAP_FATAL); + else + kdb_trap_immed(KDB_TRAP_NONFATAL); + } +#endif spin_lock(&d->shutdown_lock); if ( d->shutdown_code == -1 ) diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index db5512e..be8fc83 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -1778,6 +1778,33 @@ csched_dump_vcpu(struct csched_vcpu *svc) printk("\n"); } +#ifdef XEN_KDB_CONFIG +static void kdb_csched_dump(int cpu) +{ + struct csched_pcpu *pcpup = CSCHED_PCPU(cpu); + struct vcpu *scurrvp = (CSCHED_VCPU(current))->vcpu; + struct list_head *tmp, *runq = RUNQ(cpu); + + kdbp(" csched_pcpu: %p\n", pcpup); + kdbp(" curr csched:%p {vcpu:%p id:%d domid:%d}\n", (current)->sched_priv, + scurrvp, scurrvp->vcpu_id, scurrvp->domain->domain_id); + kdbp(" runq:\n"); + + /* next is top of struct, so screw stupid, ugly hard to follow macros */ + if (offsetof(struct csched_vcpu, runq_elem.next) != 0) { + kdbp("next is not first in struct csched_vcpu. please fixme\n"); + return; /* otherwise for loop will crash */ + } + for (tmp = runq->next; tmp != runq; tmp = tmp->next) { + + struct csched_vcpu *csp = (struct csched_vcpu *)tmp; + struct vcpu *vp = csp->vcpu; + kdbp(" csp:%p pri:%02d vcpu: {p:%p id:%d domid:%d}\n", csp, + csp->pri, vp, vp->vcpu_id, vp->domain->domain_id); + }; +} +#endif + static void csched_dump_pcpu(const struct scheduler *ops, int cpu) { @@ -1787,6 +1814,10 @@ csched_dump_pcpu(const struct scheduler *ops, int cpu) int loop; #define cpustr keyhandler_scratch +#ifdef XEN_KDB_CONFIG + kdb_csched_dump(cpu); + return; +#endif spc = CSCHED_PCPU(cpu); runq = &spc->runq; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 1192fe2..c9d4b17 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -1537,6 +1537,25 @@ void wait(void) schedule(); } +#ifdef XEN_KDB_CONFIG +void kdb_print_sched_info(void) +{ + int cpu; + + kdbp("Scheduler: name:%s opt_name:%s id:%d\n", ops.name, ops.opt_name, + ops.sched_id); + kdbp("per cpu schedule_data:\n"); + for_each_online_cpu(cpu) { + struct schedule_data *p = &per_cpu(schedule_data, cpu); + kdbp(" cpu:%d &(per cpu)schedule_data:%p\n", cpu, p); + kdbp(" curr:%p sched_priv:%p\n", p->curr, p->sched_priv); + kdbp("\n"); + ops.dump_cpu_state(&ops, cpu); + kdbp("\n"); + } +} +#endif + #ifdef CONFIG_COMPAT #include "compat/schedule.c" #endif diff --git a/xen/common/smp.c b/xen/common/smp.c index 482a203..6937108 100644 --- a/xen/common/smp.c +++ b/xen/common/smp.c @@ -75,7 +75,7 @@ out: spin_unlock(&call_lock); } -void smp_call_function_interrupt(void) +void smp_call_function_interrupt(struct cpu_user_regs *regs) { void (*func)(void *info) = call_data.func; void *info = call_data.info; @@ -96,6 +96,11 @@ void smp_call_function_interrupt(void) { smp_mb(); cpumask_clear_cpu(cpu, &call_data.selected); +#ifdef XEN_KDB_CONFIG + if (info && !strcmp(info, "XENKDB")) /* called from kdb */ + (*(void (*)(struct cpu_user_regs *, void *))func)(regs, info); + else +#endif (*func)(info); } diff --git a/xen/common/symbols.c b/xen/common/symbols.c index 45941e1..93fd892 100644 --- a/xen/common/symbols.c +++ b/xen/common/symbols.c @@ -148,3 +148,21 @@ const char *symbols_lookup(unsigned long addr, *offset = addr - symbols_address(low); return namebuf; } + +#ifdef XEN_KDB_CONFIG +/* + * * Given a symbol, return its address + * */ +unsigned long address_lookup(char *symp) +{ + int i, off = 0; + char namebuf[KSYM_NAME_LEN+1]; + + for (i=0; i < symbols_num_syms; i++) { + off = symbols_expand_symbol(off, namebuf); + if (strcmp(namebuf, symp) == 0) /* found it */ + return symbols_address(i); + } + return 0; +} +#endif diff --git a/xen/common/timer.c b/xen/common/timer.c index 1895a78..d758034 100644 --- a/xen/common/timer.c +++ b/xen/common/timer.c @@ -641,6 +641,48 @@ void __init timer_init(void) register_keyhandler('a', &dump_timerq_keyhandler); } +#ifdef XEN_KDB_CONFIG +#include +void kdb_dump_timer_queues(void) +{ + struct timer *t; + struct timers *ts; + unsigned long sz, offs; + char buf[KSYM_NAME_LEN+1]; + int cpu, j; + u64 tsc; + + for_each_online_cpu( cpu ) + { + ts = &per_cpu(timers, cpu); + kdbp("CPU[%02d]:", cpu); + + if (cpu == smp_processor_id()) { + s_time_t now = NOW(); + rdtscll(tsc); + kdbp("NOW:0x%08x%08x TSC:0x%016lx\n", (u32)(now>>32),(u32)now, tsc); + } else + kdbp("\n"); + + /* timers in the heap */ + for ( j = 1; j <= GET_HEAP_SIZE(ts->heap); j++ ) { + t = ts->heap[j]; + kdbp(" %d: exp=0x%08x%08x fn:%s data:%p\n", + j, (u32)(t->expires>>32), (u32)t->expires, + symbols_lookup((unsigned long)t->function, &sz, &offs, buf), + t->data); + } + /* timers on the link list */ + for ( t = ts->list, j = 0; t != NULL; t = t->list_next, j++ ) { + kdbp(" L%d: exp=0x%08x%08x fn:%s data:%p\n", + j, (u32)(t->expires>>32), (u32)t->expires, + symbols_lookup((unsigned long)t->function, &sz, &offs, buf), + t->data); + } + } +} +#endif + /* * Local variables: * mode: C diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 532c426..ace0971 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -347,6 +347,21 @@ static void serial_rx(char c, struct cpu_user_regs *regs) { static int switch_code_count = 0; +#ifdef XEN_KDB_CONFIG + /* if ctrl-\ pressed and kdb handles it, return */ + if (kdb_enabled && c == 0x1c) { + if (!kdb_session_begun) { + if (kdb_keyboard(regs)) + return; + } else { + kdbp("Sorry... kdb session already active....\n"); + return; + } + } + if (kdb_session_begun) /* kdb should already be polling */ + return; /* swallow chars so they don't buffer in dom0 */ +#endif + if ( switch_code && (c == switch_code) ) { /* We eat CTRL- in groups of 3 to switch console input. */ @@ -815,6 +830,18 @@ void console_end_sync(void) atomic_dec(&print_everything); } +#ifdef XEN_KDB_CONFIG +void console_putc(char c) +{ + serial_putc(sercon_handle, c); +} + +int console_getc(void) +{ + return serial_getc(sercon_handle); +} +#endif + /* * printk rate limiting, lifted from Linux. * diff --git a/xen/include/asm-x86/debugger.h b/xen/include/asm-x86/debugger.h index 0408bec..5bc1360 100644 --- a/xen/include/asm-x86/debugger.h +++ b/xen/include/asm-x86/debugger.h @@ -39,7 +39,11 @@ #define DEBUGGER_trap_fatal(_v, _r) \ if ( debugger_trap_fatal(_v, _r) ) return; -#if defined(CRASH_DEBUG) +#if defined(XEN_KDB_CONFIG) +#define debugger_trap_immediate() kdb_trap_immed(KDB_TRAP_NONFATAL) +#define debugger_trap_fatal(_v, _r) kdb_trap_fatal(_v, _r) + +#elif defined(CRASH_DEBUG) #include @@ -70,6 +74,10 @@ static inline int debugger_trap_entry( { struct vcpu *v = current; +#ifdef XEN_KDB_CONFIG + if (kdb_handle_trap_entry(vector, regs)) + return 1; +#endif if ( guest_kernel_mode(v, regs) && v->domain->debugger_attached && ((vector == TRAP_int3) || (vector == TRAP_debug)) ) { diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 5b258fd..744c3f5 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -133,4 +133,7 @@ void dump_execstate(struct cpu_user_regs *); void init_constructors(void); +#ifdef XEN_KDB_CONFIG +#include "../../kdb/include/kdb_extern.h" +#endif #endif /* __LIB_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index fb8bd36..e981ab7 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -660,11 +660,14 @@ extern void (*dead_idle) (void); unsigned long hypercall_create_continuation( unsigned int op, const char *format, ...); void hypercall_cancel_continuation(void); - +#ifdef XEN_KDB_CONFIG +#define hypercall_preempt_check() (0) +#else #define hypercall_preempt_check() (unlikely( \ softirq_pending(smp_processor_id()) | \ local_events_need_delivery() \ )) +#endif extern struct domain *domain_list; diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h index 6febb56..3aa8a6c 100644 --- a/xen/include/xen/smp.h +++ b/xen/include/xen/smp.h @@ -61,7 +61,7 @@ static inline void on_each_cpu( /* * Call a function on the current CPU */ -void smp_call_function_interrupt(void); +void smp_call_function_interrupt(struct cpu_user_regs *regs); void smp_send_call_function_mask(const cpumask_t *mask); diff --git a/xen/kdb/Makefile b/xen/kdb/Makefile new file mode 100644 index 0000000..2c21498 --- /dev/null +++ b/xen/kdb/Makefile @@ -0,0 +1,5 @@ + +obj-y += kdbmain.o kdb_cmds.o kdb_io.o + +subdir-y += x86 guest + diff --git a/xen/kdb/README b/xen/kdb/README new file mode 100644 index 0000000..29acc50 --- /dev/null +++ b/xen/kdb/README @@ -0,0 +1,243 @@ + +Welcome to kdb for xen, a hypervisor built in debugger. + +FEATURES: + - set breakpoints in hypervisor + - examine virt/machine memory, registers, domains, vcpus, etc... + - single step, single step till jump/call, step over call to next + instruction after the call. + - examine memory of a PV/HVM guest. + - set breakpoints, single step, etc... for a PV guest. + - breaking into the debugger will freeze the system, all CPUs will pause, + no interrupts are acknowledged in the debugger. (Hence, the wall clock + will drift) + - single step will step only that cpu. + - earlykdb: break into kdb very early during boot. Put "earlykdb" on the + xen command line in grub.conf. + - generic tracing functions (see below) for quick tracing to debug timing + related problems. To use: + o set KDBTRCMAX to max num of recs in circular trc buffer in kdbmain.c + o call kdb_trc() from anywhere in xen + o turn tracing on by setting kdb_trcon in kdbmain.c or trcon command. + o trcp in kdb will give hints to dump trace recs. Use dd to see buffer + o trcz will zero out the entire buffer if needed. + +NOTE: + - since almost all numbers are in hex, 0x is not prefixed. Instead, decimal + numbers are preceded by $, as in $17 (sorry, one gets used to it). Note, + vcpu num, cpu num, domid are always displayed in decimal, without $. + - watchdog must be disabled to use kdb + +ISSUES: + - Currently, debug hypervisor is not supported. Make sure NDEBUG is defined + or compile with debug=n + - "timer went backwards" messages on dom0, but kdb/hyp should be fine. + I usually do "echo 2 > /proc/sys/kernel/printk" when using kdb. + - 32bit hypervisor may hang. Tested on 64bit hypervisor only. + + +TO BUILD: + - do >make kdb=y + +HOW TO USE: + 1. A serial line is needed to use the debugger. Set up a serial line + from the source machine to target victim. Make sure the serial line + is working properly by displaying login prompt and loging in etc.... + + 2. Add following to grub.conf: + kernel /xen.kdb console=com1,vga com1=57600,8n1 dom0_mem=542M + + (57600 or whatever used in step 1 above) + + 3. Boot the hypervisor built with the debugger. + + 4. ctrl-\ (ctrl and backslash) will break into the debugger. If the system is + badly hung, pressing NMI would also break into it. However, once kdb is + entered via NMI, normal execution can't continue. + + 5. type 'h' for list of commands. + + 6. Command line editing is limited to backspace. ctrl-c to start a new cmd. + + + +GUEST debug: + - type sym in the debugger + - for REL4, grep kallsyms_names, kallsyms_addresses, and kallsyms_num_syms + in the guest System.map* file. Run sym again with domid and the three + values on the command line. + - Now basic symbols can be used for guest debug. Note, if the binary is not + built with symbols, only function names are available, but not global vars. + + Eg: sym 0 c0696084 c068a590 c0696080 c06b43e8 c06b4740 + will set symbols for dom 0. Then : + + [4]xkdb> bp some_function 0 + + wills set bp at some_function in dom 0 + + [3]xkdb> dw c068a590 32 0 : display 32 bytes of dom0 memory + + +Tips: + - In "[0]xkdb>" : 0 is the cpu number in decimal + - In + 00000000c042645c: 0:do_timer+17 push %ebp + 0:do_timer : 0 is the domid in hex + offset +17 is in hex. + + absense of 0: would indicate it's a hypervisor function + + - commands starting with kdb (kdb*) are for kdb debug only. + + +Finally, + - think hex. + - bug/problem: enter kdbdbg, reproduce, and send me the output. + If the output is not enough, I may ask to run kdbdbg twice, then collect + output. + + +Thanks, +Mukesh Rathor +Oracle Corporatin, +Redwood Shores, CA 94065 + +-------------------------------------------------------------------------------- +COMMAND DESCRIPTION: + +info: Print basic info like version, compile flags, etc.. + +cur: print current domain id and vcpu id + +f: display current stack. If a vcpu ptr is given, then print stack for that + VCPU by using its IP and SP. + +fg: display stack for a guest given domid, SP and IP. + +dw: display words of memory. 'num' of bytes is optional, but if displaying guest + memory, then is required. + +dd: same as above, but display doublewords. + +dwm: same as above but the address is machine address instead of virtual. + +ddm: same as above, but display doublewords. + +dr: display registers. if 'sp' is specified then print few extra registers. + +drg: display guest context saved on stack bottom. + +dis: disassemble instructions. If disassembling for guest, then 'num' must + be specified. 'num' is number of instrs to display. + +dism: toggle disassembly mode between Intel and ATT/GAS. + +mw: modify word in memory given virtual address. 'domid' may be specified if + modifying guest memory. value is assumed in hex even without 0x. + +md: same as above but modify doubleword. + +mr: modify register. value is assumd hex. + +bc: clear given or all breakpoints + +bp: display breakpoints or set a breakpoint. Domid may be specified to set a bp + in guest. kdb functions may not be specified if debugging kdb. + Example: + xkdb> bp acpi_processor_idle : will set bp in xen + xkdb> bp default_idle 0 : will set bp in domid 0 + xkdb> bp idle_cpu 9 : will set bp in domid 9 + + Conditions may be specified for a bp: lhs == rhs or lhs != rhs + where : lhs is register like 'r6', 'rax', etc... or memory location + rhs is hex value with or without leading 0x. + Thus, + xkdb> bp acpi_processor_idle rdi == c000 + xkdb> bp 0xffffffff80062ebc 0 rsi == ffff880021edbc98 : will break into + kdb at 0xffffffff80062ebc in dom0 when rsi is ffff880021edbc98 + +btp: break point trace. Upon bp, print some info and continue without stopping. + Ex: btp idle_cpu 7 rax rbx 0x20ef5a5 r9 + + will print: rax, rbx, *(long *)0x20ef5a5, r9 upon hitting idle_cpu() and + continue. + +wp: set a watchpoint at a virtual address which can belong to hypervisor or + any guest. Do not specify wp in kdb path if debugging kdb. + +wc: clear given or all watchpoints. + +ni: single step, stepping over function calls. + +ss: single step. Be carefull when in interrupt handlers or context switches. + +ssb: single step to branch. Use with care. + +go: leave kdb and continue. + +cpu: go back to orig cpu when entering kdb. If 'cpu number' given, then switch + to that cpu. If 'all' then show status of all cpus. + +nmi: Only available in hung/crash state. Send NMI to a cpu that may be hung. + +sym: Initialize a symbol table for debugging a guest. Look into the System.map + file of guest for certain symbol values and provide them here. + +vcpuh: Given vcpu ptr, display hvm_vcpu struct. + +vcpu: Display current vcpu struct. If 'vcpu-ptr' given, display that vcpu. + +dom: display current domain. If 'domid' then display that domid. If 'all', then + display all domains. + +sched: show schedular info and run queues. + +mmu: print basic mmu info + +p2m: convert a gpfn to mfn given a domid. value in hex even without 0x. + +m2p: convert mfn to pfn. value in hex even without 0x. + +dpage: display struct page given a mfn or struct page ptr. Since, no info is + kept on page type, we display all possible page types. + +dtrq: display timer queues. + +didt: dump IDT table. + +dgt: dump GDT table. + +dirq: display IRQ bindings. + +dvmc: display all or given dom/vcpu VMCS or VMCB. + +trcon: turn tracing on. Trace hooks must be added in xen and kdb function + called directly from there. + +trcoff: turn tracing off. + +trcz: zero trace buffer. + +trcp: give hints to print the circular trace buffer, like current active ptr. + +usr1: allows to add any arbitraty command quickly. + +-------------------------------------------------------------------------------- +/* + * Copyright (C) 2008 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ diff --git a/xen/kdb/guest/Makefile b/xen/kdb/guest/Makefile new file mode 100644 index 0000000..5628b9a --- /dev/null +++ b/xen/kdb/guest/Makefile @@ -0,0 +1,3 @@ + +obj-y := kdb_guest.o + diff --git a/xen/kdb/guest/kdb_guest.c b/xen/kdb/guest/kdb_guest.c new file mode 100644 index 0000000..b6b6bb3 --- /dev/null +++ b/xen/kdb/guest/kdb_guest.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "../include/kdbinc.h" + +/* information for symbols for a guest (includeing dom 0 ) is saved here */ +struct gst_syminfo { /* guest symbols info */ + int domid; /* which domain */ + int bitness; /* 32 or 64 */ + void *addrtblp; /* ptr to (32/64)addresses tbl */ + u8 *toktbl; /* ptr to kallsyms_token_table */ + u16 *tokidxtbl; /* ptr to kallsyms_token_index */ + u8 *kallsyms_names; /* ptr to kallsyms_names */ + long kallsyms_num_syms; /* ptr to kallsyms_num_syms */ + kdbva_t stext; /* value of _stext in guest */ + kdbva_t etext; /* value of _etext in guest */ + kdbva_t sinittext; /* value of _sinittext in guest */ + kdbva_t einittext; /* value of _einittext in guest */ +}; + +#define MAX_CACHE 16 /* cache upto 16 guests */ +struct gst_syminfo gst_syminfoa[MAX_CACHE]; /* guest symbol info array */ + +static struct gst_syminfo * +kdb_get_syminfo_slot(void) +{ + int i; + for (i=0; i < MAX_CACHE; i++) + if (gst_syminfoa[i].addrtblp == NULL) + return (&gst_syminfoa[i]); + + return NULL; +} + +static struct gst_syminfo * +kdb_domid2syminfop(domid_t domid) +{ + int i; + for (i=0; i < MAX_CACHE; i++) + if (gst_syminfoa[i].domid == domid) + return (&gst_syminfoa[i]); + + return NULL; +} + +/* check if an address looks like text address in guest */ +int +kdb_is_addr_guest_text(kdbva_t addr, int domid) +{ + struct gst_syminfo *gp = kdb_domid2syminfop(domid); + + if (!gp || !gp->stext || !gp->etext) + return 0; + KDBGP1("guestaddr: addr:%lx domid:%d\n", addr, domid); + + return ( (addr >= gp->stext && addr <= gp->etext) || + (addr >= gp->sinittext && addr <= gp->einittext) ); +} + +/* + * returns: value of kallsyms_addresses[idx]; + */ +static kdbva_t +kdb_rd_guest_addrtbl(struct gst_syminfo *gp, int idx) +{ + kdbva_t addr, retaddr=0; + int num = gp->bitness/8; /* whether 4 byte or 8 byte ptrs */ + domid_t id = gp->domid; + + addr = (kdbva_t)(((char *)gp->addrtblp) + idx * num); + KDBGP1("rdguestaddrtbl:addr:%lx idx:%d\n", addr, idx); + + if (kdb_read_mem(addr, (kdbbyt_t *)&retaddr,num,id) != num) { + kdbp("Can't read addrtbl domid:%d at:%lx\n", id, addr); + return 0; + } + KDBGP1("rdguestaddrtbl:exit:retaddr:%lx\n", retaddr); + return retaddr; +} + +/* Based on el5 kallsyms.c file. */ +static unsigned int +kdb_expand_el5_sym(struct gst_syminfo *gp, unsigned int off, char *result) +{ + int len, skipped_first = 0; + u8 u8idx, *tptr, *datap; + domid_t domid = gp->domid; + + *result = '\0'; + + /* get the compressed symbol length from the first symbol byte */ + datap = gp->kallsyms_names + off; + len = 0; + if ((kdb_read_mem((kdbva_t)datap, (kdbbyt_t *)&len, 1, domid)) != 1) { + KDBGP("failed to read guest memory\n"); + return 0; + } + datap++; + + /* update the offset to return the offset for the next symbol on + * the compressed stream */ + off += len + 1; + + /* for every byte on the compressed symbol data, copy the table + * entry for that byte */ + while(len) { + u16 u16idx, *u16p; + if (kdb_read_mem((kdbva_t)datap,(kdbbyt_t *)&u8idx,1,domid)!=1){ + kdbp("memory (u8idx) read error:%p\n",gp->tokidxtbl); + return 0; + } + u16p = u8idx + gp->tokidxtbl; + if (kdb_read_mem((kdbva_t)u16p,(kdbbyt_t *)&u16idx,2,domid)!=2){ + kdbp("tokidxtbl read error:%p\n", u16p); + return 0; + } + tptr = gp->toktbl + u16idx; + datap++; + len--; + + while ((kdb_read_mem((kdbva_t)tptr, (kdbbyt_t *)&u8idx, 1, domid)==1) && + u8idx) { + + if(skipped_first) { + *result = u8idx; + result++; + } else + skipped_first = 1; + tptr++; + } + } + *result = '\0'; + return off; /* return to offset to the next symbol */ +} + +#define EL4_NMLEN 127 +/* so much pain, so not sure of it's worth .. :).. */ +static kdbva_t +kdb_expand_el4_sym(struct gst_syminfo *gp, int low, char *result, char *symp) +{ + int i, j; + u8 *nmp = gp->kallsyms_names; /* guest address space */ + kdbbyt_t byte, prefix; + domid_t id = gp->domid; + kdbva_t addr; + + KDBGP1("Eel4sym:nmp:%p maxidx:$%d sym:%s\n", nmp, low, symp); + for (i=0; i <= low; i++) { + /* unsigned prefix = *name++; */ + if (kdb_read_mem((kdbva_t)nmp, &prefix, 1, id) != 1) { + kdbp("failed to read:%p domid:%x\n", nmp, id); + return 0; + } + KDBGP2("el4:i:%d prefix:%x\n", i, prefix); + nmp++; + /* strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix); */ + addr = (long)result + prefix; + for (j=0; j < EL4_NMLEN-prefix; j++) { + if (kdb_read_mem((kdbva_t)nmp, &byte, 1, id) != 1) { + kdbp("failed read:%p domid:%x\n", nmp, id); + return 0; + } + KDBGP2("el4:j:%d byte:%x\n", j, byte); + *(kdbbyt_t *)addr = byte; + addr++; nmp++; + if (byte == '\0') + break; + } + KDBGP2("el4sym:i:%d res:%s\n", i, result); + if (symp && strcmp(result, symp) == 0) + return(kdb_rd_guest_addrtbl(gp, i)); + + /* kallsyms.c: name += strlen(name) + 1; */ + if (j == EL4_NMLEN-prefix && byte != '\0') + while (kdb_read_mem((kdbva_t)nmp, &byte, 1, id) && byte != '\0') + nmp++; + } + KDBGP1("Xel4sym: na-ga-da\n"); + return 0; +} + +static unsigned int +kdb_get_el5_symoffset(struct gst_syminfo *gp, long pos) +{ + int i; + u8 data, *namep; + domid_t domid = gp->domid; + + namep = gp->kallsyms_names; + for (i=0; i < pos; i++) { + if (kdb_read_mem((kdbva_t)namep, &data, 1, domid) != 1) { + kdbp("Can't read id:$%d mem:%p\n", domid, namep); + return 0; + } + namep = namep + data + 1; + } + return namep - gp->kallsyms_names; +} + +/* + * for a given guest domid (domid >= 0 && < KDB_HYPDOMID), convert addr to + * symbol. offset is set to addr - symbolstart + */ +char * +kdb_guest_addr2sym(unsigned long addr, domid_t domid, ulong *offsp) +{ + static char namebuf[KSYM_NAME_LEN+1]; + unsigned long low, high, mid; + struct gst_syminfo *gp = kdb_domid2syminfop(domid); + + *offsp = 0; + if(!gp || gp->kallsyms_num_syms == 0) + return " ??? "; + + namebuf[0] = namebuf[KSYM_NAME_LEN] = '\0'; + if (1) { + /* do a binary search on the sorted kallsyms_addresses array */ + low = 0; + high = gp->kallsyms_num_syms; + + while (high-low > 1) { + mid = (low + high) / 2; + if (kdb_rd_guest_addrtbl(gp, mid) <= addr) + low = mid; + else + high = mid; + } + /* Grab name */ + if (gp->toktbl) { + int symoff = kdb_get_el5_symoffset(gp,low); + kdb_expand_el5_sym(gp, symoff, namebuf); + } else + kdb_expand_el4_sym(gp, low, namebuf, NULL); + *offsp = addr - kdb_rd_guest_addrtbl(gp, low); + return namebuf; + } + return " ???? "; +} + + +/* + * save guest (dom0 and others) symbols info : domid and following addresses: + * &kallsyms_names &kallsyms_addresses &kallsyms_num_syms \ + * &kallsyms_token_table &kallsyms_token_index + */ +void +kdb_sav_dom_syminfo(domid_t domid, long namesp, long addrap, long nump, + long toktblp, long tokidxp) +{ + int bytes; + long val = 0; /* must be set to zero for 32 on 64 cases */ + struct gst_syminfo *gp = kdb_get_syminfo_slot(); + + if (gp == NULL) { + kdbp("kdb:kdb_sav_dom_syminfo():Table full.. symbols not saved\n"); + return; + } + memset(gp, 0, sizeof(*gp)); + + gp->domid = domid; + gp->bitness = kdb_guest_bitness(domid); + gp->addrtblp = (void *)addrap; + gp->kallsyms_names = (u8 *)namesp; + gp->toktbl = (u8 *)toktblp; + gp->tokidxtbl = (u16 *)tokidxp; + + KDBGP("domid:%x bitness:$%d numsyms:$%ld arrayp:%p\n", domid, + gp->bitness, gp->kallsyms_num_syms, gp->addrtblp); + + bytes = gp->bitness/8; + if (kdb_read_mem(nump, (kdbbyt_t *)&val, bytes, domid) != bytes) { + + kdbp("Unable to read number of symbols from:%lx\n", nump); + memset(gp, 0, sizeof(*gp)); + return; + } else + kdbp("Number of symbols:$%ld\n", val); + + gp->kallsyms_num_syms = val; + + bytes = (gp->bitness/8) * gp->kallsyms_num_syms; + gp->stext = kdb_guest_sym2addr("_stext", domid); + gp->etext = kdb_guest_sym2addr("_etext", domid); + if (!gp->stext || !gp->etext) + kdbp("Warn: Can't find stext/etext\n"); + + if (gp->toktbl && gp->tokidxtbl) { + gp->sinittext = kdb_guest_sym2addr("_sinittext", domid); + gp->einittext = kdb_guest_sym2addr("_einittext", domid); + if (!gp->sinittext || !gp->einittext) { + kdbp("Warn: Can't find sinittext/einittext\n"); + } + } + KDBGP1("stxt:%lx etxt:%lx sitxt:%lx eitxt:%lx\n", gp->stext, gp->etext, + gp->sinittext, gp->einittext); + kdbp("Succesfully saved symbol info\n"); +} + +/* + * given a symbol string for a guest/domid, return its address + */ +kdbva_t +kdb_guest_sym2addr(char *symp, domid_t domid) +{ + char namebuf[KSYM_NAME_LEN+1]; + int i, off=0; + struct gst_syminfo *gp = kdb_domid2syminfop(domid); + + KDBGP("sym2a: sym:%s domid:%x numsyms:%ld\n", symp, domid, + gp ? gp->kallsyms_num_syms: -1); + + if (!gp) + return 0; + + if (gp->toktbl == 0 || gp->tokidxtbl == 0) + return(kdb_expand_el4_sym(gp, gp->kallsyms_num_syms, namebuf, symp)); + + for (i=0; i < gp->kallsyms_num_syms; i++) { + off = kdb_expand_el5_sym(gp, off, namebuf); + KDBGP1("i:%d namebuf:%s\n", i, namebuf); + if (strcmp(namebuf, symp) == 0) { + return(kdb_rd_guest_addrtbl(gp, i)); + } + } + KDBGP("sym2a:exit:na-ga-da\n"); + return 0; +} diff --git a/xen/kdb/include/kdb_extern.h b/xen/kdb/include/kdb_extern.h new file mode 100644 index 0000000..585cd90 --- /dev/null +++ b/xen/kdb/include/kdb_extern.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _KDB_EXTERN_H +#define _KDB_EXTERN_H + +#define KDB_TRAP_FATAL 1 /* trap is fatal. can't resume from kdb */ +#define KDB_TRAP_NONFATAL 2 /* can resume from kdb */ +#define KDB_TRAP_KDBSTACK 3 /* to debug kdb itself. dump kdb stack */ + +/* following can be called from anywhere in xen to debug */ +extern void kdb_trap_immed(int); +extern void kdbtrc(unsigned int, unsigned int, uint64_t, uint64_t, uint64_t); +extern void kdbp(const char *fmt, ...); + +typedef unsigned long kdbva_t; +typedef unsigned char kdbbyt_t; +typedef unsigned long kdbma_t; + +extern unsigned long kdb_dr7; + + +extern volatile int kdb_session_begun; +extern volatile int kdb_enabled; +extern void kdb_init(void); +extern int kdb_keyboard(struct cpu_user_regs *); +extern void kdb_ssni_reenter(struct cpu_user_regs *); +extern int kdb_handle_trap_entry(int, struct cpu_user_regs *); +extern int kdb_trap_fatal(int, struct cpu_user_regs *); /* fatal with regs */ +extern void kdb_dump_vmcs(uint16_t did, int vid); +void kdb_dump_vmcb(uint16_t did, int vid); +extern void kdb_dump_time_pcpu(void); + + +#define VMPTRST_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /7 */ +#define MODRM_EAX_07 ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */ +static inline void __vmptrst(u64 *addr) +{ + asm volatile ( VMPTRST_OPCODE + MODRM_EAX_07 + : + : "a" (addr) + : "memory"); +} + +extern void mukchk(unsigned long); + +#endif /* _KDB_EXTERN_H */ diff --git a/xen/kdb/include/kdbdefs.h b/xen/kdb/include/kdbdefs.h new file mode 100644 index 0000000..ddc9b31 --- /dev/null +++ b/xen/kdb/include/kdbdefs.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _KDBDEFS_H +#define _KDBDEFS_H + +/* reason we are entering kdbmain (bp == breakpoint) */ +typedef enum { + KDB_REASON_KEYBOARD=1, /* Keyboard entry - always 1 */ + KDB_REASON_BPEXCP, /* #BP excp: sw bp (INT3) */ + KDB_REASON_DBEXCP, /* #DB excp: TF flag or HW bp */ + KDB_REASON_PAUSE_IPI, /* received pause IPI from another CPU */ +} kdb_reason_t; + + +/* cpu state: past, present, and future */ +typedef enum { + KDB_CPU_INVAL=0, /* invalid value. not in or leaving kdb */ + KDB_CPU_QUIT, /* main cpu does GO. all others do QUIT */ + KDB_CPU_PAUSE, /* cpu is paused */ + KDB_CPU_DISABLE, /* disable interrupts */ + KDB_CPU_SHOWPC, /* all cpus must display their pc */ + KDB_CPU_DO_VMEXIT, /* all cpus must do vmcs vmexit. intel only */ + KDB_CPU_MAIN_KDB, /* cpu in kdb main command loop */ + KDB_CPU_GO, /* user entered go for this cpu */ + KDB_CPU_SS, /* single step for this cpu */ + KDB_CPU_NI, /* go to next instr after the call instr */ + KDB_CPU_INSTALL_BP, /* delayed install of sw bp(s) by this cpu */ +} kdb_cpu_cmd_t; + +/* ============= kdb commands ============================================= */ + +typedef kdb_cpu_cmd_t (*kdb_func_t)(int, const char **, struct cpu_user_regs *); +typedef kdb_cpu_cmd_t (*kdb_usgf_t)(void); + +typedef enum { + KDB_REPEAT_NONE = 0, /* Do not repeat this command */ + KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ + KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ +} kdb_repeat_t; + +typedef struct _kdbtab { + char *kdb_cmd_name; /* Command name */ + kdb_func_t kdb_cmd_func; /* ptr to function to execute command */ + kdb_usgf_t kdb_cmd_usgf; /* usage function ptr */ + int kdb_cmd_crash_avail; /* available in sys fatal/crash state */ + kdb_repeat_t kdb_cmd_repeat; /* Does command auto repeat on enter? */ +} kdbtab_t; + + +/* ============= types and stuff ========================================= */ +#define BFD_INVAL (~0UL) /* invalid bfd_vma */ + +#if defined(__x86_64__) + #define KDBIP rip + #define KDBSP rsp +#else + #define KDBIP eip + #define KDBSP esp +#endif + +/* ============= macros ================================================== */ +extern volatile int kdbdbg; +#define KDBGP(...) {(kdbdbg) ? kdbp(__VA_ARGS__):0;} +#define KDBGP1(...) {(kdbdbg>1) ? kdbp(__VA_ARGS__):0;} +#define KDBGP2(...) {(kdbdbg>2) ? kdbp(__VA_ARGS__):0;} +#define KDBGP3(...) {0;}; + +#define KDBMIN(x,y) (((x)<(y))?(x):(y)) + +#endif /* !_KDBDEFS_H */ diff --git a/xen/kdb/include/kdbinc.h b/xen/kdb/include/kdbinc.h new file mode 100644 index 0000000..e030866 --- /dev/null +++ b/xen/kdb/include/kdbinc.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _KDBINC_H +#define _KDBINC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef _XEN_LATEST +#include +#endif + +#include + +#include "kdb_extern.h" +#include "kdbdefs.h" +#include "kdbproto.h" + +#endif /* !_KDBINC_H */ diff --git a/xen/kdb/include/kdbproto.h b/xen/kdb/include/kdbproto.h new file mode 100644 index 0000000..eed518b --- /dev/null +++ b/xen/kdb/include/kdbproto.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _KDBPROTO_H +#define _KDBPROTO_H + +/* hypervisor interfaces use by kdb or kdb interfaces in xen files */ +extern void console_putc(char); +extern int console_getc(void); +extern void show_trace(struct cpu_user_regs *); +extern void kdb_dump_timer_queues(void); +extern void kdb_time_resume(int); +extern void kdb_print_sched_info(void); +extern void kdb_curr_cpu_flush_vmcs(void); +extern unsigned long address_lookup(char *); +extern void kdb_prnt_guest_mapped_irqs(void); + +/* kdb globals */ +extern kdbtab_t *kdb_cmd_tbl; +extern char kdb_prompt[32]; +extern volatile int kdb_sys_crash; +extern volatile kdb_cpu_cmd_t kdb_cpu_cmd[NR_CPUS]; +extern volatile int kdb_trcon; + +/* kdb interfaces */ +extern void __init kdb_io_init(void); +extern void kdb_init_cmdtab(void); +extern void kdb_do_cmds(struct cpu_user_regs *); +extern int kdb_check_sw_bkpts(struct cpu_user_regs *); +extern int kdb_check_watchpoints(struct cpu_user_regs *); +extern void kdb_do_watchpoints(kdbva_t, int, int); +extern void kdb_install_watchpoints(void); +extern void kdb_clear_wps(int); +extern kdbma_t kdb_rd_dbgreg(int); + + + +extern char *kdb_get_cmdline(char *); +extern void kdb_clear_prev_cmd(void); +extern void kdb_toggle_dis_syntax(void); +extern int kdb_check_call_instr(domid_t, kdbva_t); +extern void kdb_display_pc(struct cpu_user_regs *); +extern kdbva_t kdb_print_instr(kdbva_t, long, domid_t); +extern int kdb_read_mmem(kdbva_t, kdbbyt_t *, int); +extern int kdb_read_mem(kdbva_t, kdbbyt_t *, int, domid_t); +extern int kdb_write_mem(kdbva_t, kdbbyt_t *, int, domid_t); + +extern void kdb_install_all_swbp(void); +extern void kdb_uninstall_all_swbp(void); +extern int kdb_swbp_exists(void); +extern void kdb_flush_swbp_table(void); +extern int kdb_is_addr_guest_text(kdbva_t, int); +extern kdbva_t kdb_guest_sym2addr(char *, domid_t); +extern char *kdb_guest_addr2sym(unsigned long, domid_t, ulong *); +extern void kdb_prnt_addr2sym(domid_t, kdbva_t, char *); +extern void kdb_sav_dom_syminfo(domid_t, long, long, long, long, long); +extern int kdb_guest_bitness(domid_t); +extern void kdb_nmi_pause_cpus(cpumask_t); + +extern void kdb_trczero(void); +void kdb_trcp(void); + + + +#endif /* !_KDBPROTO_H */ diff --git a/xen/kdb/kdb_cmds.c b/xen/kdb/kdb_cmds.c new file mode 100644 index 0000000..d34e861 --- /dev/null +++ b/xen/kdb/kdb_cmds.c @@ -0,0 +1,3815 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "include/kdbinc.h" + +#if defined(__x86_64__) + #define KDBF64 "%lx" + #define KDBFL "%016lx" /* print long all digits */ +#else + #define KDBF64 "%llx" + #define KDBFL "%08lx" +#endif + +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ + #define KDB_LKDEF(l) ((l).raw.lock) + #define KDB_PGLLE(t) ((t).tail) /* page list last element ^%$#@ */ +#else + #define KDB_LKDEF(l) ((l).lock) + #define KDB_PGLLE(t) ((t).prev) /* page list last element ^%$#@ */ +#endif + +#define KDB_CMD_HISTORY_COUNT 32 +#define CMD_BUFLEN 200 /* kdb_printf: max printline == 256 */ + +#define KDBMAXSBP 16 /* max number of software breakpoints */ +#define KDB_MAXARGC 16 /* max args in a kdb command */ +#define KDB_MAXBTP 8 /* max display args in btp */ + +/* condition is: 'r6 == 0x123f' or '0xffffffff82800000 != deadbeef' */ +struct kdb_bpcond { + kdbbyt_t bp_cond_status; /* 0 == off, 1 == register, 2 == memory */ + kdbbyt_t bp_cond_type; /* 0 == bad, 1 == equal, 2 == not equal */ + ulong bp_cond_lhs; /* lhs of condition: reg offset or mem loc */ + ulong bp_cond_rhs; /* right hand side of condition */ +}; + +/* software breakpoint structure */ +struct kdb_sbrkpt { + kdbva_t bp_addr; /* address the bp is set at */ + domid_t bp_domid; /* which domain the bp belongs to */ + kdbbyt_t bp_originst; /* save orig instr/s here */ + kdbbyt_t bp_deleted; /* delete pending on this bp */ + kdbbyt_t bp_ni; /* set for KDB_CPU_NI */ + kdbbyt_t bp_just_added; /* added in the current kdb session */ + kdbbyt_t bp_type; /* 0 = normal, 1 == cond, 2 == btp */ + union { + struct kdb_bpcond bp_cond; + ulong *bp_btp; + } u; +}; + +/* don't use kmalloc in kdb which hijacks all cpus */ +static ulong kdb_btp_argsa[KDBMAXSBP][KDB_MAXBTP]; +static ulong *kdb_btp_ap[KDBMAXSBP]; + +static struct kdb_reg_nmofs { + char *reg_nm; + int reg_offs; +} kdb_reg_nm_offs[] = { + { "rax", offsetof(struct cpu_user_regs, rax) }, + { "rbx", offsetof(struct cpu_user_regs, rbx) }, + { "rcx", offsetof(struct cpu_user_regs, rcx) }, + { "rdx", offsetof(struct cpu_user_regs, rdx) }, + { "rsi", offsetof(struct cpu_user_regs, rsi) }, + { "rdi", offsetof(struct cpu_user_regs, rdi) }, + { "rbp", offsetof(struct cpu_user_regs, rbp) }, + { "rsp", offsetof(struct cpu_user_regs, rsp) }, + { "r8", offsetof(struct cpu_user_regs, r8) }, + { "r9", offsetof(struct cpu_user_regs, r9) }, + { "r10", offsetof(struct cpu_user_regs, r10) }, + { "r11", offsetof(struct cpu_user_regs, r11) }, + { "r12", offsetof(struct cpu_user_regs, r12) }, + { "r13", offsetof(struct cpu_user_regs, r13) }, + { "r14", offsetof(struct cpu_user_regs, r14) }, + { "r15", offsetof(struct cpu_user_regs, r15) }, + { "rflags", offsetof(struct cpu_user_regs, rflags) } }; + +static const int KDBBPSZ=1; /* size of KDB_BPINST is 1 byte*/ +static kdbbyt_t kdb_bpinst = 0xcc; /* breakpoint instr: INT3 */ +static struct kdb_sbrkpt kdb_sbpa[KDBMAXSBP]; /* soft brkpt array/table */ +static kdbtab_t *tbp; + +static int kdb_set_bp(domid_t, kdbva_t, int, ulong *, char*, char*, char*); +static void kdb_print_uregs(struct cpu_user_regs *); + + +/* ===================== cmdline functions ================================ */ + +/* lp points to a string of only alpha numeric chars terminated by '\n'. + * Parse the string into argv pointers, and RETURN argc + * Eg: if lp --> "dr sp\n" : argv[0]=="dr\0" argv[1]=="sp\0" argc==2 + */ +static int +kdb_parse_cmdline(char *lp, const char **argv) +{ + int i=0; + + for (; *lp == ' '; lp++); /* note: isspace() skips '\n' also */ + while ( *lp != '\n' ) { + if (i == KDB_MAXARGC) { + printk("kdb: max args exceeded\n"); + break; + } + argv[i++] = lp; + for (; *lp != ' ' && *lp != '\n'; lp++); + if (*lp != '\n') + *lp++ = '\0'; + for (; *lp == ' '; lp++); + } + *lp = '\0'; + return i; +} + +void +kdb_clear_prev_cmd() /* so previous command is not repeated */ +{ + tbp = NULL; +} + +void +kdb_do_cmds(struct cpu_user_regs *regs) +{ + char *cmdlinep; + const char *argv[KDB_MAXARGC]; + int argc = 0, curcpu = smp_processor_id(); + kdb_cpu_cmd_t result = KDB_CPU_MAIN_KDB; + + snprintf(kdb_prompt, sizeof(kdb_prompt), "[%d]xkdb> ", curcpu); + + while (result == KDB_CPU_MAIN_KDB) { + cmdlinep = kdb_get_cmdline(kdb_prompt); + if (*cmdlinep == '\n') { + if (tbp==NULL || tbp->kdb_cmd_func==NULL) + continue; + else + argc = -1; /* repeat prev command */ + } else { + argc = kdb_parse_cmdline(cmdlinep, argv); + for(tbp=kdb_cmd_tbl; tbp->kdb_cmd_func; tbp++) { + if (strcmp(argv[0], tbp->kdb_cmd_name)==0) + break; + } + } + if (kdb_sys_crash && tbp->kdb_cmd_func && !tbp->kdb_cmd_crash_avail) { + kdbp("cmd not available in fatal/crashed state....\n"); + continue; + } + if (tbp->kdb_cmd_func) { + result = (*tbp->kdb_cmd_func)(argc, argv, regs); + if (tbp->kdb_cmd_repeat == KDB_REPEAT_NONE) + tbp = NULL; + } else + kdbp("kdb: Unknown cmd: %s\n", cmdlinep); + } + kdb_cpu_cmd[curcpu] = result; + return; +} + +/* ===================== Util functions ==================================== */ + +int +kdb_vcpu_valid(struct vcpu *in_vp) +{ + struct domain *dp; + struct vcpu *vp; + + for(dp=domain_list; in_vp && dp; dp=dp->next_in_list) + for_each_vcpu(dp, vp) + if (in_vp == vp) + return 1; + return 0; /* not found */ +} + +/* + * Given a symbol, find it's address + */ +static kdbva_t +kdb_sym2addr(const char *p, domid_t domid) +{ + kdbva_t addr; + + KDBGP1("sym2addr: p:%s domid:%d\n", p, domid); + if (domid == DOMID_IDLE) + addr = address_lookup((char *)p); + else + addr = (kdbva_t)kdb_guest_sym2addr((char *)p, domid); + KDBGP1("sym2addr: exit: addr returned:0x%lx\n", addr); + return addr; +} + +/* + * convert ascii to int decimal (base 10). + * Return: 0 : failed to convert, otherwise 1 + */ +static int +kdb_str2deci(const char *strp, int *intp) +{ + const char *endp; + + KDBGP2("str2deci: str:%s\n", strp); + if (!isdigit(*strp)) + return 0; + *intp = (int)simple_strtoul(strp, &endp, 10); + if (endp != strp+strlen(strp)) + return 0; + KDBGP2("str2deci: intval:$%d\n", *intp); + return 1; +} +/* + * convert ascii to long. NOTE: base is 16 + * Return: 0 : failed to convert, otherwise 1 + */ +static int +kdb_str2ulong(const char *strp, ulong *longp) +{ + ulong val; + const char *endp; + + KDBGP2("str2long: str:%s\n", strp); + if (!isxdigit(*strp)) + return 0; + val = (long)simple_strtoul(strp, &endp, 16); /* handles leading 0x */ + if (endp != strp+strlen(strp)) + return 0; + if (longp) + *longp = val; + KDBGP2("str2long: val:0x%lx\n", val); + return 1; +} +/* + * convert a symbol or ascii address to hex address + * Return: 0 : failed to convert, otherwise 1 + */ +static int +kdb_str2addr(const char *strp, kdbva_t *addrp, domid_t id) +{ + kdbva_t addr; + const char *endp; + + /* assume it's an address */ + KDBGP2("str2addr: str:%s id:%d\n", strp, id); + addr = (kdbva_t)simple_strtoul(strp, &endp, 16); /*handles leading 0x */ + if (endp != strp+strlen(strp)) + if ( !(addr=kdb_sym2addr(strp, id)) ) + return 0; + *addrp = addr; + KDBGP2("str2addr: addr:0x%lx\n", addr); + return 1; +} + +/* Given domid, return ptr to struct domain + * IF domid == DOMID_IDLE return ptr to idle_domain + * IF domid == valid domain, return ptr to domain struct + * else domid is bad and return NULL + */ +static struct domain * +kdb_domid2ptr(domid_t domid) +{ + struct domain *dp; + + /* get_domain_by_id() ret NULL for both DOMID_IDLE and bad domids */ + if (domid == DOMID_IDLE) + dp = idle_vcpu[smp_processor_id()]->domain; + else + dp = get_domain_by_id(domid); /* NULL now means bad domid */ + return dp; +} + +/* + * Returns: 0: failed. invalid domid or string, *idp not changed. + */ +static int +kdb_str2domid(const char *domstr, domid_t *idp, int perr) +{ + int id; + if (!kdb_str2deci(domstr, &id) || !kdb_domid2ptr((domid_t)id)) { + if (perr) + kdbp("Invalid domid:%s\n", domstr); + return 0; + } + *idp = (domid_t)id; + return 1; +} + +static struct domain * +kdb_strdomid2ptr(const char *domstr, int perror) +{ + domid_t domid; + if (kdb_str2domid(domstr, &domid, perror)) { + return(kdb_domid2ptr(domid)); + } + return NULL; +} + +/* return a guest bitness: 32 or 64 */ +int +kdb_guest_bitness(domid_t domid) +{ + const int HYPSZ = sizeof(long) * 8; + struct domain *dp = kdb_domid2ptr(domid); + int retval; + + if (is_idle_domain(dp)) + retval = HYPSZ; + else if (!is_pv_domain(dp)) + retval = (hvm_long_mode_enabled(dp->vcpu[0])) ? HYPSZ : 32; + else + retval = is_pv_32bit_domain(dp) ? 32 : HYPSZ; + KDBGP1("gbitness: domid:%d dp:%p bitness:%d\n", domid, dp, retval); + return retval; +} + +/* kdb_print_spin_lock(&xyz_lock, "xyz_lock:", "\n"); */ +static void +kdb_print_spin_lock(char *strp, spinlock_t *lkp, char *nlp) +{ + kdbp("%s %04hx %d %d%s", strp, KDB_LKDEF(*lkp), lkp->recurse_cpu, + lkp->recurse_cnt, nlp); +} + +/* check if register string is valid. if yes, return offset to the register + * in cpu_user_regs, else return -1 */ +static int +kdb_valid_reg(const char *nmp) +{ + int i; + for (i=0; i < sizeof(kdb_reg_nm_offs)/sizeof(kdb_reg_nm_offs[0]); i++) + if (strcmp(kdb_reg_nm_offs[i].reg_nm, nmp) == 0) + return kdb_reg_nm_offs[i].reg_offs; + return -1; +} + +/* given offset of register, return register name string. if offset is invalid + * return NULL */ +static char *kdb_regoffs_to_name(int offs) +{ + int i; + for (i=0; i < sizeof(kdb_reg_nm_offs)/sizeof(kdb_reg_nm_offs[0]); i++) + if (kdb_reg_nm_offs[i].reg_offs == offs) + return kdb_reg_nm_offs[i].reg_nm; + return NULL; +} + +/* ===================== util struct funcs ================================= */ +static void +kdb_prnt_timer(struct timer *tp) +{ +#if XEN_SUBVERSION == 0 + kdbp(" expires:%016lx expires_end:%016lx cpu:%d status:%x\n", tp->expires, + tp->expires_end, tp->cpu, tp->status); +#else + kdbp(" expires:%016lx cpu:%d status:%x\n", tp->expires, tp->cpu,tp->status); +#endif + kdbp(" function data:%p ptr:%p ", tp->data, tp->function); + kdb_prnt_addr2sym(DOMID_IDLE, (kdbva_t)tp->function, "\n"); +} + +static void +kdb_prnt_periodic_time(struct periodic_time *ptp) +{ + kdbp(" next:%p prev:%p\n", ptp->list.next, ptp->list.prev); + kdbp(" on_list:%d one_shot:%d dont_freeze:%d irq_issued:%d src:%x irq:%x\n", + ptp->on_list, ptp->one_shot, ptp->do_not_freeze, ptp->irq_issued, + ptp->source, ptp->irq); + kdbp(" vcpu:%p pending_intr_nr:%08x period:%016lx\n", ptp->vcpu, + ptp->pending_intr_nr, ptp->period); + kdbp(" scheduled:%016lx last_plt_gtime:%016lx\n", ptp->scheduled, + ptp->last_plt_gtime); + kdbp(" \n timer info:\n"); + kdb_prnt_timer(&ptp->timer); + kdbp("\n"); +} + +/* ===================== cmd functions ==================================== */ + +/* + * FUNCTION: Disassemble instructions + */ +static kdb_cpu_cmd_t +kdb_usgf_dis(void) +{ + kdbp("dis [addr|sym][num][domid] : Disassemble instrs\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dis(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int num = 8; /* display 8 instr by default */ + static kdbva_t addr = BFD_INVAL; + static domid_t domid; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dis(); + + if (argc != -1) /* not a command repeat */ + { + /* user gave addr but not domid, the addr then is xen */ + if (argc > 1 && argc < 4) + domid = DOMID_IDLE; + else + domid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; + } + + if (argc >= 4 && !kdb_str2domid(argv[3], &domid, 1)) { + return KDB_CPU_MAIN_KDB; + } + if (argc >= 3 && !kdb_str2deci(argv[2], &num)) { + kdbp("kdb:Invalid num\n"); + return KDB_CPU_MAIN_KDB; + } + if (argc > 1 && !kdb_str2addr(argv[1], &addr, domid)) { + kdbp("kdb:Invalid addr/sym\n"); + kdbp("(num has to be specified if providing domid)\n"); + return KDB_CPU_MAIN_KDB; + } + if (argc == 1) /* not command repeat */ + addr = regs->KDBIP; /* PC is the default */ + else if (addr == BFD_INVAL) { + kdbp("kdb:Invalid addr/sym\n"); + return KDB_CPU_MAIN_KDB; + } + addr = kdb_print_instr(addr, num, domid); + return KDB_CPU_MAIN_KDB; +} + +/* FUNCTION: kdb_cmdf_dism() Toggle disassembly syntax from Intel to ATT/GAS */ +static kdb_cpu_cmd_t +kdb_usgf_dism(void) +{ + kdbp("dism: toggle disassembly mode between ATT/GAS and INTEL\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dism(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dism(); + + kdb_toggle_dis_syntax(); + return KDB_CPU_MAIN_KDB; +} + +static void +_kdb_show_guest_stack(domid_t domid, kdbva_t ipaddr, kdbva_t spaddr) +{ + kdbva_t val; + int num=0, max=0, rd = kdb_guest_bitness(domid)/8; + + kdb_print_instr(ipaddr, 1, domid); + KDBGP("_guest_stack:sp:%lx domid:%d rd:$%d\n", spaddr, domid, rd); + val = 0; /* must zero, in case guest is 32bit */ + while((kdb_read_mem(spaddr,(kdbbyt_t *)&val,rd,domid)==rd) && num < 16){ + KDBGP1("gstk:addr:%lx val:%lx\n", spaddr, val); + if (kdb_is_addr_guest_text(val, domid)) { + kdb_print_instr(val, 1, domid); + num++; + } + if (max++ > 10000) /* don't walk down the stack forever */ + break; /* 10k is chosen randomly */ + spaddr += rd; + } +} + +/* Read guest memory and display address that looks like text. */ +static void +kdb_show_guest_stack(struct cpu_user_regs *regs, struct vcpu *vcpup) +{ + kdbva_t ipaddr=regs->KDBIP, spaddr = regs->KDBSP; + domid_t domid = vcpup->domain->domain_id; + + ASSERT(domid != DOMID_IDLE); + _kdb_show_guest_stack(domid, ipaddr, spaddr); +} + +/* display stack. if vcpu ptr given, then display stack for that. Otherwise, + * use current regs */ +static kdb_cpu_cmd_t +kdb_usgf_f(void) +{ + kdbp("f [vcpu-ptr]: dump current/vcpu stack\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_f(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_f(); + + if (argc > 1 ) { + struct vcpu *vp; + if (!kdb_str2ulong(argv[1], (ulong *)&vp) || !kdb_vcpu_valid(vp)) { + kdbp("kdb: Bad VCPU ptr:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + kdb_show_guest_stack(&vp->arch.user_regs, vp); + return KDB_CPU_MAIN_KDB; + } + if (guest_mode(regs)) + kdb_show_guest_stack(regs, current); + else + show_trace(regs); + return KDB_CPU_MAIN_KDB; +} + +/* given an spaddr and domid for guest, dump stack */ +static kdb_cpu_cmd_t +kdb_usgf_fg(void) +{ + kdbp("fg domid RIP ESP: dump guest stack given domid, RIP, and ESP\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_fg(int argc, const char **argv, struct cpu_user_regs *regs) +{ + domid_t domid; + kdbva_t ipaddr, spaddr; + + if (argc != 4) + return kdb_usgf_fg(); + + if (kdb_str2domid(argv[1], &domid, 1)==0) { + return KDB_CPU_MAIN_KDB; + } + if (kdb_str2ulong(argv[2], &ipaddr)==0) { + kdbp("Bad ipaddr:%s\n", argv[2]); + return KDB_CPU_MAIN_KDB; + } + if (kdb_str2ulong(argv[3], &spaddr)==0) { + kdbp("Bad spaddr:%s\n", argv[3]); + return KDB_CPU_MAIN_KDB; + } + _kdb_show_guest_stack(domid, ipaddr, spaddr); + return KDB_CPU_MAIN_KDB; +} + +/* Display kdb stack. for debugging kdb itself */ +static kdb_cpu_cmd_t +kdb_usgf_kdbf(void) +{ + kdbp("kdbf: display kdb stack. for debugging kdb only\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_kdbf(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_kdbf(); + + kdb_trap_immed(KDB_TRAP_KDBSTACK); + return KDB_CPU_MAIN_KDB; +} + +/* worker function to display memory. Request could be for any guest, domid. + * Also address could be machine or virtual */ +static void +_kdb_display_mem(kdbva_t *addrp, int *lenp, int wordsz, int domid, int is_maddr) +{ + #define DDBUFSZ 4096 + + kdbbyt_t buf[DDBUFSZ], *bp; + int numrd, bytes; + int len = *lenp; + kdbva_t addr = *addrp; + + /* round len down to wordsz boundry because on intel endian, printing + * characters is not prudent, (long and ints can't be interpreted + * easily) */ + len &= ~(wordsz-1); + len = KDBMIN(DDBUFSZ, len); + len = len ? len : wordsz; + + KDBGP("dmem:addr:%lx buf:%p len:$%d domid:%d sz:$%d maddr:%d\n", addr, + buf, len, domid, wordsz, is_maddr); + if (is_maddr) + numrd=kdb_read_mmem((kdbma_t)addr, buf, len); + else + numrd=kdb_read_mem(addr, buf, len, domid); + if (numrd != len) + kdbp("Memory read error. Bytes read:$%d\n", numrd); + + for (bp = buf; numrd > 0;) { + kdbp("%016lx: ", addr); + + /* display 16 bytes per line */ + for (bytes=0; bytes < 16 && numrd > 0; bytes += wordsz) { + if (numrd >= wordsz) { + if (wordsz == 8) + kdbp(" %016lx", *(long *)bp); + else + kdbp(" %08x", *(int *)bp); + bp += wordsz; + numrd -= wordsz; + addr += wordsz; + } + } + kdbp("\n"); + continue; + } + *lenp = len; + *addrp = addr; +} + +/* display machine mem, ie, the given address is machine address */ +static kdb_cpu_cmd_t +kdb_display_mmem(int argc, const char **argv, int wordsz, kdb_usgf_t usg_fp) +{ + static kdbma_t maddr; + static int len; + static domid_t id = DOMID_IDLE; + + if (argc == -1) { + _kdb_display_mem(&maddr, &len, wordsz, id, 1); /* cmd repeat */ + return KDB_CPU_MAIN_KDB; + } + if (argc <= 1 || *argv[1] == '?') + return (*usg_fp)(); + + /* check if num of bytes to display is given by user */ + if (argc >= 3) { + if (!kdb_str2deci(argv[2], &len)) { + kdbp("Invalid length:%s\n", argv[2]); + return KDB_CPU_MAIN_KDB; + } + } else + len = 32; /* default read len */ + + if (!kdb_str2ulong(argv[1], &maddr)) { + kdbp("Invalid argument:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + _kdb_display_mem(&maddr, &len, wordsz, 0, 1); + return KDB_CPU_MAIN_KDB; +} + +/* + * FUNCTION: Dispaly machine Memory Word + */ +static kdb_cpu_cmd_t +kdb_usgf_dwm(void) +{ + kdbp("dwm: maddr|sym [num] : dump memory word given machine addr\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dwm(int argc, const char **argv, struct cpu_user_regs *regs) +{ + return kdb_display_mmem(argc, argv, 4, kdb_usgf_dwm); +} + +/* + * FUNCTION: Dispaly machine Memory DoubleWord + */ +static kdb_cpu_cmd_t +kdb_usgf_ddm(void) +{ + kdbp("ddm: maddr|sym [num] : dump double word given machine addr\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_ddm(int argc, const char **argv, struct cpu_user_regs *regs) +{ + return kdb_display_mmem(argc, argv, 8, kdb_usgf_ddm); +} + +/* + * FUNCTION: Dispaly Memory : word or doubleword + * wordsz : bytes in word. 4 or 8 + * + * We display upto BUFSZ bytes. User can just press enter for more. + * addr is always in hex with or without leading 0x + */ +static kdb_cpu_cmd_t +kdb_display_mem(int argc, const char **argv, int wordsz, kdb_usgf_t usg_fp) +{ + static kdbva_t addr; + static int len; + static domid_t id = DOMID_IDLE; + + if (argc == -1) { + _kdb_display_mem(&addr, &len, wordsz, id, 0); /* cmd repeat */ + return KDB_CPU_MAIN_KDB; + } + if (argc <= 1 || *argv[1] == '?') + return (*usg_fp)(); + + id = DOMID_IDLE; /* not a command repeat, reset dom id */ + if (argc >= 4) { + if (!kdb_str2domid(argv[3], &id, 1)) + return KDB_CPU_MAIN_KDB; + } + /* check if num of bytes to display is given by user */ + if (argc >= 3) { + if (!kdb_str2deci(argv[2], &len)) { + kdbp("Invalid length:%s\n", argv[2]); + return KDB_CPU_MAIN_KDB; + } + } else + len = 32; /* default read len */ + if (!kdb_str2addr(argv[1], &addr, id)) { + kdbp("Invalid argument:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + + _kdb_display_mem(&addr, &len, wordsz, id, 0); + return KDB_CPU_MAIN_KDB; +} + +/* + * FUNCTION: Dispaly Memory Word + */ +static kdb_cpu_cmd_t +kdb_usgf_dw(void) +{ + kdbp("dw vaddr|sym [num][domid] : dump mem word. num required for domid\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dw(int argc, const char **argv, struct cpu_user_regs *regs) +{ + return kdb_display_mem(argc, argv, 4, kdb_usgf_dw); +} + +/* + * FUNCTION: Dispaly Memory DoubleWord + */ +static kdb_cpu_cmd_t +kdb_usgf_dd(void) +{ + kdbp("dd vaddr|sym [num][domid] : dump dword. num required for domid\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dd(int argc, const char **argv, struct cpu_user_regs *regs) +{ + return kdb_display_mem(argc, argv, 8, kdb_usgf_dd); +} + +/* + * FUNCTION: Modify Memory Word + */ +static kdb_cpu_cmd_t +kdb_usgf_mw(void) +{ + kdbp("mw vaddr|sym val [domid] : modify memory word in vaddr\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_mw(int argc, const char **argv, struct cpu_user_regs *regs) +{ + ulong val; + kdbva_t addr; + domid_t id = DOMID_IDLE; + + if (argc < 3) { + return kdb_usgf_mw(); + } + if (argc >=4) { + if (!kdb_str2domid(argv[3], &id, 1)) + return KDB_CPU_MAIN_KDB; + } + if (!kdb_str2ulong(argv[2], &val)) { + kdbp("Invalid val: %s\n", argv[2]); + return KDB_CPU_MAIN_KDB; + } + if (!kdb_str2addr(argv[1], &addr, id)) { + kdbp("Invalid addr/sym: %s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + if (kdb_write_mem(addr, (kdbbyt_t *)&val, 4, id) != 4) + kdbp("Unable to set 0x%lx to 0x%lx\n", addr, val); + return KDB_CPU_MAIN_KDB; +} + +/* + * FUNCTION: Modify Memory DoubleWord + */ +static kdb_cpu_cmd_t +kdb_usgf_md(void) +{ + kdbp("md vaddr|sym val [domid] : modify memory dword in vaddr\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_md(int argc, const char **argv, struct cpu_user_regs *regs) +{ + ulong val; + kdbva_t addr; + domid_t id = DOMID_IDLE; + + if (argc < 3) { + return kdb_usgf_md(); + } + if (argc >=4) { + if (!kdb_str2domid(argv[3], &id, 1)) { + return KDB_CPU_MAIN_KDB; + } + } + if (!kdb_str2ulong(argv[2], &val)) { + kdbp("Invalid val: %s\n", argv[2]); + return KDB_CPU_MAIN_KDB; + } + if (!kdb_str2addr(argv[1], &addr, id)) { + kdbp("Invalid addr/sym: %s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + if (kdb_write_mem(addr, (kdbbyt_t *)&val,sizeof(val),id) != sizeof(val)) + kdbp("Unable to set 0x%lx to 0x%lx\n", addr, val); + + return KDB_CPU_MAIN_KDB; +} + +struct Xgt_desc_struct { + unsigned short size; + unsigned long address __attribute__((packed)); +}; + +void +kdb_show_special_regs(struct cpu_user_regs *regs) +{ + struct Xgt_desc_struct desc; + unsigned short tr; /* Task Register segment selector */ + __u64 efer; + + kdbp("\nSpecial Registers:\n"); + __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory"); + kdbp("IDTR: addr: %016lx limit: %04x\n", desc.address, desc.size); + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory"); + kdbp("GDTR: addr: %016lx limit: %04x\n", desc.address, desc.size); + + kdbp("cr0: %016lx cr2: %016lx\n", read_cr0(), read_cr2()); + kdbp("cr3: %016lx cr4: %016lx\n", read_cr3(), read_cr4()); + __asm__ __volatile__ ("str (%0) \n":: "a"(&tr) : "memory"); + kdbp("TR: %x\n", tr); + + rdmsrl(MSR_EFER, efer); /* IA32_EFER */ + kdbp("efer:"KDBF64" LMA(IA-32e mode):%d SCE(syscall/sysret):%d\n", + efer, ((efer&EFER_LMA) != 0), ((efer&EFER_SCE) != 0)); + + kdbp("DR0: %016lx DR1:%016lx DR2:%016lx\n", kdb_rd_dbgreg(0), + kdb_rd_dbgreg(1), kdb_rd_dbgreg(2)); + kdbp("DR3: %016lx DR6:%016lx DR7:%016lx\n", kdb_rd_dbgreg(3), + kdb_rd_dbgreg(6), kdb_rd_dbgreg(7)); +} + +/* + * FUNCTION: Dispaly Registers. If "sp" argument, then display additional regs + */ +static kdb_cpu_cmd_t +kdb_usgf_dr(void) +{ + kdbp("dr [sp]: display registers. sp to display special regs also\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dr(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dr(); + + KDBGP1("regs:%p .rsp:%lx .rip:%lx\n", regs, regs->rsp, regs->rip); + show_registers(regs); + if (argc > 1 && !strcmp(argv[1], "sp")) + kdb_show_special_regs(regs); + return KDB_CPU_MAIN_KDB; +} + +/* show registers on stack bottom where guest context is. same as dr if + * not running in guest mode */ +static kdb_cpu_cmd_t +kdb_usgf_drg(void) +{ + kdbp("drg: display active guest registers at stack bottom\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_drg(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_drg(); + + kdbp("\tNote: ds/es/fs/gs etc.. are not saved from the cpu\n"); + kdb_print_uregs(guest_cpu_user_regs()); + return KDB_CPU_MAIN_KDB; +} + +/* + * FUNCTION: Modify Register + */ +static kdb_cpu_cmd_t +kdb_usgf_mr(void) +{ + kdbp("mr reg val : Modify Register. val assumed in hex\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_mr(int argc, const char **argv, struct cpu_user_regs *regs) +{ + const char *argp; + int regoffs; + ulong val; + + if (argc != 3 || !kdb_str2ulong(argv[2], &val)) { + return kdb_usgf_mr(); + } + argp = argv[1]; + +#if defined(__x86_64__) + if ((regoffs=kdb_valid_reg(argp)) != -1) + *((uint64_t *)((char *)regs+regoffs)) = val; +#else + if (!strcmp(argp, "eax")) + regs->eax = val; + else if (!strcmp(argp, "ebx")) + regs->ebx = val; + else if (!strcmp(argp, "ecx")) + regs->ecx = val; + else if (!strcmp(argp, "edx")) + regs->edx = val; + else if (!strcmp(argp, "esi")) + regs->esi = val; + else if (!strcmp(argp, "edi")) + regs->edi = val; + else if (!strcmp(argp, "ebp")) + regs->ebp = val; + else if (!strcmp(argp, "esp")) + regs->esp = val; + else if (!strcmp(argp, "eflags") || !strcmp(argp, "rflags")) + regs->eflags = val; +#endif + else + kdbp("Error. Bad register : %s\n", argp); + + return KDB_CPU_MAIN_KDB; +} + +/* + * FUNCTION: Single Step + */ +static kdb_cpu_cmd_t +kdb_usgf_ss(void) +{ + kdbp("ss: single step\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_ss(int argc, const char **argv, struct cpu_user_regs *regs) +{ + #define KDB_HALT_INSTR 0xf4 + + kdbbyt_t byte; + struct domain *dp = current->domain; + domid_t id = guest_mode(regs) ? dp->domain_id : DOMID_IDLE; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_ss(); + + KDBGP("enter kdb_cmdf_ss \n"); + if (!regs) { + kdbp("%s: regs not available\n", __FUNCTION__); + return KDB_CPU_MAIN_KDB; + } + if (kdb_read_mem(regs->KDBIP, &byte, 1, id) == 1) { + if (byte == KDB_HALT_INSTR) { + kdbp("kdb: jumping over halt instruction\n"); + regs->KDBIP++; + } + } else { + kdbp("kdb: Failed to read byte at: %lx\n", regs->KDBIP); + return KDB_CPU_MAIN_KDB; + } + if (guest_mode(regs) && !is_pv_vcpu(current)) { + dp->debugger_attached = 1; /* see svm_do_resume/vmx_do_ */ + + /* will set MTF in vmx_intr_assist */ + current->arch.hvm_vcpu.single_step = 1; + } else + regs->eflags |= X86_EFLAGS_TF; + + return KDB_CPU_SS; +} + +/* + * FUNCTION: Next Instruction, step over the call instr to the next instr + */ +static kdb_cpu_cmd_t +kdb_usgf_ni(void) +{ + kdbp("ni: single step, stepping over function calls\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_ni(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int sz, i; + domid_t id=guest_mode(regs) ? current->domain->domain_id:DOMID_IDLE; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_ni(); + + KDBGP("enter kdb_cmdf_ni \n"); + if (!regs) { + kdbp("%s: regs not available\n", __FUNCTION__); + return KDB_CPU_MAIN_KDB; + } + if ((sz=kdb_check_call_instr(id, regs->KDBIP)) == 0) /* !call instr */ + return kdb_cmdf_ss(argc, argv, regs); /* just do ss */ + + if ((i=kdb_set_bp(id, regs->KDBIP+sz, 1,0,0,0,0)) >= KDBMAXSBP) /* failed */ + return KDB_CPU_MAIN_KDB; + + kdb_sbpa[i].bp_ni = 1; + if (guest_mode(regs) && !is_pv_vcpu(current)) + current->arch.hvm_vcpu.single_step = 0; + else + regs->eflags &= ~X86_EFLAGS_TF; + + return KDB_CPU_NI; +} + +static void +kdb_btf_enable(void) +{ + u64 debugctl; + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 0x2); +} + +/* + * FUNCTION: Single Step to branch. Doesn't seem to work very well. + */ +static kdb_cpu_cmd_t +kdb_usgf_ssb(void) +{ + kdbp("ssb: singe step to branch\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_ssb(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_ssb(); + + KDBGP("kdb: enter kdb_cmdf_ssb\n"); + if (!regs) { + kdbp("%s: regs not available\n", __FUNCTION__); + return KDB_CPU_MAIN_KDB; + } + if (!is_pv_vcpu(current)) + current->domain->debugger_attached = 1; /* vmx/svm_do_resume()*/ + + regs->eflags |= X86_EFLAGS_TF; + kdb_btf_enable(); + return KDB_CPU_SS; +} + +/* + * FUNCTION: Continue Execution. TF must be cleared here as this could run on + * any cpu. Hence not OK to do it from kdb_end_session. + */ +static kdb_cpu_cmd_t +kdb_usgf_go(void) +{ + kdbp("go: leave kdb and continue execution\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_go(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_go(); + + regs->eflags &= ~X86_EFLAGS_TF; + return KDB_CPU_GO; +} + +/* All cpus must display their current context */ +static kdb_cpu_cmd_t +kdb_cpu_status_all(int ccpu, struct cpu_user_regs *regs) +{ + int cpu; + for_each_online_cpu(cpu) { + if (cpu == ccpu) { + kdbp("[%d]", ccpu); + kdb_display_pc(regs); + } else { + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) /* hung cpu */ + continue; + kdb_cpu_cmd[cpu] = KDB_CPU_SHOWPC; + while (kdb_cpu_cmd[cpu]==KDB_CPU_SHOWPC); + } + } + return KDB_CPU_MAIN_KDB; +} + +/* + * display/switch CPU. + * Argument: + * none: just go back to initial cpu + * cpunum: switch to given vpu + * "all": show one line status of all cpus + */ +extern volatile int kdb_init_cpu; +static kdb_cpu_cmd_t +kdb_usgf_cpu(void) +{ + kdbp("cpu [all|num]: none will switch back to initial cpu\n"); + kdbp(" cpunum to switch to the vcpu. all to show status\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_cpu(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int cpu; + int ccpu = smp_processor_id(); + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_cpu(); + + if (argc > 1) { + if (!strcmp(argv[1], "all")) + return kdb_cpu_status_all(ccpu, regs); + + cpu = (int)simple_strtoul(argv[1], NULL, 0); /* handles 0x */ + if (cpu >= 0 && cpu < NR_CPUS && cpu != ccpu && + cpu_online(cpu) && kdb_cpu_cmd[cpu] == KDB_CPU_PAUSE) + { + kdbp("Switching to cpu:%d\n", cpu); + kdb_cpu_cmd[cpu] = KDB_CPU_MAIN_KDB; + + /* clear any single step on the current cpu */ + regs->eflags &= ~X86_EFLAGS_TF; + return KDB_CPU_PAUSE; + } else { + if (cpu != ccpu) + kdbp("Unable to switch to cpu:%d\n", cpu); + else { + kdb_display_pc(regs); + } + return KDB_CPU_MAIN_KDB; + } + } + /* no arg means back to initial cpu */ + if (!kdb_sys_crash && ccpu != kdb_init_cpu) { + if (kdb_cpu_cmd[kdb_init_cpu] == KDB_CPU_PAUSE) { + regs->eflags &= ~X86_EFLAGS_TF; + kdb_cpu_cmd[kdb_init_cpu] = KDB_CPU_MAIN_KDB; + return KDB_CPU_PAUSE; + } else + kdbp("Unable to switch to: %d\n", kdb_init_cpu); + } + return KDB_CPU_MAIN_KDB; +} + +/* send NMI to all or given CPU. Must be crashed/fatal state */ +static kdb_cpu_cmd_t +kdb_usgf_nmi(void) +{ + kdbp("nmi cpu#|all: send nmi cpu/s. must reboot when done with kdb\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_nmi(int argc, const char **argv, struct cpu_user_regs *regs) +{ + cpumask_t cpumask; + int ccpu = smp_processor_id(); + + if (argc <= 1 || (argc > 1 && *argv[1] == '?')) + return kdb_usgf_nmi(); + + if (!kdb_sys_crash) { + kdbp("kdb: nmi cmd available in crashed state only\n"); + return KDB_CPU_MAIN_KDB; + } + if (!strcmp(argv[1], "all")) + cpumask = cpu_online_map; + else { + int cpu = (int)simple_strtoul(argv[1], NULL, 0); + if (cpu >= 0 && cpu < NR_CPUS && cpu != ccpu && cpu_online(cpu)) + cpumask = *cpumask_of(cpu); + else { + kdbp("KDB nmi: invalid cpu %s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + } + kdb_nmi_pause_cpus(cpumask); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_percpu(void) +{ + kdbp("percpu: display per cpu pointers\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_percpu(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_percpu(); + kdb_dump_time_pcpu(); + return KDB_CPU_MAIN_KDB; +} + +/* ========================= Breakpoints ==================================== */ + +static void +kdb_prnt_bp_cond(int bpnum) +{ + struct kdb_bpcond *bpcp = &kdb_sbpa[bpnum].u.bp_cond; + + if (bpcp->bp_cond_status == 1) { + kdbp(" ( %s %c%c %lx )\n", + kdb_regoffs_to_name(bpcp->bp_cond_lhs), + bpcp->bp_cond_type == 1 ? '=' : '!', '=', bpcp->bp_cond_rhs); + } else { + kdbp(" ( %lx %c%c %lx )\n", bpcp->bp_cond_lhs, + bpcp->bp_cond_type == 1 ? '=' : '!', '=', bpcp->bp_cond_rhs); + } +} + +static void +kdb_prnt_bp_extra(int bpnum) +{ + if (kdb_sbpa[bpnum].bp_type == 2) { + ulong i, arg, *btp = kdb_sbpa[bpnum].u.bp_btp; + + kdbp(" will trace "); + for (i=0; i < KDB_MAXBTP && btp[i]; i++) + if ((arg=btp[i]) < sizeof (struct cpu_user_regs)) { + kdbp(" %s ", kdb_regoffs_to_name(arg)); + } else { + kdbp(" %lx ", arg); + } + kdbp("\n"); + + } else if (kdb_sbpa[bpnum].bp_type == 1) + kdb_prnt_bp_cond(bpnum); +} + +/* + * List software breakpoints + */ +static kdb_cpu_cmd_t +kdb_display_sbkpts(void) +{ + int i; + for(i=0; i < KDBMAXSBP; i++) + if (kdb_sbpa[i].bp_addr && !kdb_sbpa[i].bp_deleted) { + struct domain *dp = kdb_domid2ptr(kdb_sbpa[i].bp_domid); + + if (dp == NULL || dp->is_dying) { + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + continue; + } + kdbp("[%d]: domid:%d 0x%lx ", i, + kdb_sbpa[i].bp_domid, kdb_sbpa[i].bp_addr); + kdb_prnt_addr2sym(kdb_sbpa[i].bp_domid, kdb_sbpa[i].bp_addr,"\n"); + kdb_prnt_bp_extra(i); + } + return KDB_CPU_MAIN_KDB; +} + +/* + * Check if any breakpoints that we need to install (delayed install) + * Returns: 1 if yes, 0 if none. + */ +int +kdb_swbp_exists(void) +{ + int i; + for (i=0; i < KDBMAXSBP; i++) + if (kdb_sbpa[i].bp_addr && !kdb_sbpa[i].bp_deleted) + return 1; + return 0; +} +/* + * Check if any breakpoints were deleted this kdb session + * Returns: 0 if none, 1 if yes + */ +static int +kdb_swbp_deleted(void) +{ + int i; + for (i=0; i < KDBMAXSBP; i++) + if (kdb_sbpa[i].bp_addr && kdb_sbpa[i].bp_deleted) + return 1; + return 0; +} + +/* + * Flush deleted sw breakpoints + */ +void +kdb_flush_swbp_table(void) +{ + int i; + KDBGP("ccpu:%d flush_swbp_table: deleted:%x\n", smp_processor_id(), + kdb_swbp_deleted()); + for(i=0; i < KDBMAXSBP; i++) + if (kdb_sbpa[i].bp_addr && kdb_sbpa[i].bp_deleted) { + KDBGP("flush:[%x] addr:0x%lx\n",i,kdb_sbpa[i].bp_addr); + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + } +} + +/* + * Delete/Clear a sw breakpoint + */ +static kdb_cpu_cmd_t +kdb_usgf_bc(void) +{ + kdbp("bc $num|all : clear given or all breakpoints\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_bc(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int i, bpnum = -1, delall = 0; + const char *argp; + + if (argc != 2 || *argv[1] == '?') + return kdb_usgf_bc(); + + if (!kdb_swbp_exists()) { + kdbp("No breakpoints are set\n"); + return KDB_CPU_MAIN_KDB; + } + argp = argv[1]; + + if (!strcmp(argp, "all")) + delall = 1; + else if (!kdb_str2deci(argp, &bpnum) || bpnum < 0 || bpnum > KDBMAXSBP) { + kdbp("Invalid bpnum: %s\n", argp); + return KDB_CPU_MAIN_KDB; + } + for (i=0; i < KDBMAXSBP; i++) { + if (delall && kdb_sbpa[i].bp_addr) { + kdbp("Deleted breakpoint [%x] addr:0x%lx domid:%d\n", + (int)i, kdb_sbpa[i].bp_addr, kdb_sbpa[i].bp_domid); + if (kdb_sbpa[i].bp_just_added) + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + else + kdb_sbpa[i].bp_deleted = 1; + continue; + } + if (bpnum != -1 && bpnum == i) { + kdbp("Deleted breakpoint [%x] at 0x%lx domid:%d\n", + (int)i, kdb_sbpa[i].bp_addr, kdb_sbpa[i].bp_domid); + if (kdb_sbpa[i].bp_just_added) + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + else + kdb_sbpa[i].bp_deleted = 1; + break; + } + } + if (i >= KDBMAXSBP && !delall) + kdbp("Unable to delete breakpoint: %s\n", argp); + + return KDB_CPU_MAIN_KDB; +} + +/* + * Install a breakpoint in the given array entry + * Returns: 0 : failed to install + * 1 : installed successfully + */ +static int +kdb_install_swbp(int idx) /* which entry in the bp array */ +{ + kdbva_t addr = kdb_sbpa[idx].bp_addr; + domid_t domid = kdb_sbpa[idx].bp_domid; + kdbbyt_t *p = &kdb_sbpa[idx].bp_originst; + struct domain *dp = kdb_domid2ptr(domid); + + if (dp == NULL || dp->is_dying) { + memset(&kdb_sbpa[idx], 0, sizeof(kdb_sbpa[idx])); + kdbp("Removed bp %d addr:%p domid:%d\n", idx, addr, domid); + return 0; + } + + if (kdb_read_mem(addr, p, KDBBPSZ, domid) != KDBBPSZ){ + kdbp("Failed(R) to install bp:%x at:0x%lx domid:%d\n", + idx, kdb_sbpa[idx].bp_addr, domid); + return 0; + } + if (kdb_write_mem(addr, &kdb_bpinst, KDBBPSZ, domid) != KDBBPSZ) { + kdbp("Failed(W) to install bp:%x at:0x%lx domid:%d\n", + idx, kdb_sbpa[idx].bp_addr, domid); + return 0; + } + KDBGP("install_swbp: installed bp:%x at:0x%lx ccpu:%x domid:%d\n", + idx, kdb_sbpa[idx].bp_addr, smp_processor_id(), domid); + return 1; +} + +/* + * Install all the software breakpoints + */ +void +kdb_install_all_swbp(void) +{ + int i; + for(i=0; i < KDBMAXSBP; i++) + if (!kdb_sbpa[i].bp_deleted && kdb_sbpa[i].bp_addr) + kdb_install_swbp(i); +} + +static void +kdb_uninstall_a_swbp(int i) +{ + kdbva_t addr = kdb_sbpa[i].bp_addr; + kdbbyt_t originst = kdb_sbpa[i].bp_originst; + domid_t id = kdb_sbpa[i].bp_domid; + + kdb_sbpa[i].bp_just_added = 0; + if (!addr) + return; + if (kdb_write_mem(addr, &originst, KDBBPSZ, id) != KDBBPSZ) { + kdbp("Failed to uninstall breakpoint %x at:0x%lx domid:%d\n", + i, kdb_sbpa[i].bp_addr, id); + } +} + +/* + * Uninstall all the software breakpoints at beginning of kdb session + */ +void +kdb_uninstall_all_swbp(void) +{ + int i; + for(i=0; i < KDBMAXSBP; i++) + kdb_uninstall_a_swbp(i); + KDBGP("ccpu:%d uninstalled all bps\n", smp_processor_id()); +} + +/* RETURNS: rc == 2: condition was not met, rc == 3: condition was met */ +static int +kdb_check_bp_condition(int bpnum, struct cpu_user_regs *regs, domid_t domid) +{ + ulong res = 0, lhsval=0; + struct kdb_bpcond *bpcp = &kdb_sbpa[bpnum].u.bp_cond; + + if (bpcp->bp_cond_status == 1) { /* register condition */ + uint64_t *rp = (uint64_t *)((char *)regs + bpcp->bp_cond_lhs); + lhsval = *rp; + } else if (bpcp->bp_cond_status == 2) { /* memaddr condition */ + ulong addr = bpcp->bp_cond_lhs; + int num = sizeof(lhsval); + + if (kdb_read_mem(addr, (kdbbyt_t *)&lhsval, num, domid) != num) { + kdbp("kdb: unable to read %d bytes at %lx\n", num, addr); + return 3; + } + } + if (bpcp->bp_cond_type == 1) /* lhs == rhs */ + res = (lhsval == bpcp->bp_cond_rhs); + else /* lhs != rhs */ + res = (lhsval != bpcp->bp_cond_rhs); + + if (!res) + kdbp("KDB: [%d]Ignoring bp:%d condition not met. val:%lx\n", + smp_processor_id(), bpnum, lhsval); + + KDBGP1("bpnum:%d domid:%d cond: %d %d %lx %lx res:%d\n", bpnum, domid, + bpcp->bp_cond_status, bpcp->bp_cond_type, bpcp->bp_cond_lhs, + bpcp->bp_cond_rhs, res); + + return (res ? 3 : 2); +} + +static void +kdb_prnt_btp_info(int bpnum, struct cpu_user_regs *regs, domid_t domid) +{ + ulong i, arg, val, num, *btp = kdb_sbpa[bpnum].u.bp_btp; + + kdb_prnt_addr2sym(domid, regs->KDBIP, "\n"); + num = kdb_guest_bitness(domid)/8; + for (i=0; i < KDB_MAXBTP && (arg=btp[i]); i++) { + if (arg < sizeof (struct cpu_user_regs)) { + uint64_t *rp = (uint64_t *)((char *)regs + arg); + kdbp(" %s: %016lx ", kdb_regoffs_to_name(arg), *rp); + } else { + if (kdb_read_mem(arg, (kdbbyt_t *)&val, num, domid) != num) + kdbp("kdb: unable to read %d bytes at %lx\n", num, arg); + if (num == 8) + kdbp(" %016lx:%016lx ", arg, val); + else + kdbp(" %08lx:%08lx ", arg, val); + } + } + kdbp("\n"); + KDBGP1("bpnum:%d domid:%d btp:%p num:%d\n", bpnum, domid, btp, num); +} + +/* + * Check if the BP trap belongs to us. + * Return: 0 : not one of ours. IP not changed. (leave kdb) + * 1 : one of ours but deleted. IP decremented. (leave kdb) + * 2 : one of ours but condition not met, or btp. IP decremented.(leave) + * 3 : one of ours and active. IP decremented. (stay in kdb) + */ +int +kdb_check_sw_bkpts(struct cpu_user_regs *regs) +{ + int i, rc=0; + domid_t curid; + + curid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; + for(i=0; i < KDBMAXSBP; i++) { + if (kdb_sbpa[i].bp_domid == curid && + kdb_sbpa[i].bp_addr == (regs->KDBIP- KDBBPSZ)) { + + regs->KDBIP -= KDBBPSZ; + rc = 3; + + if (kdb_sbpa[i].bp_ni) { + kdb_uninstall_a_swbp(i); + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + } else if (kdb_sbpa[i].bp_deleted) { + rc = 1; + } else if (kdb_sbpa[i].bp_type == 1) { + rc = kdb_check_bp_condition(i, regs, curid); + } else if (kdb_sbpa[i].bp_type == 2) { + kdb_prnt_btp_info(i, regs, curid); + rc = 2; + } + KDBGP1("ccpu:%d rc:%d curid:%d domid:%d addr:%lx\n", + smp_processor_id(), rc, curid, kdb_sbpa[i].bp_domid, + kdb_sbpa[i].bp_addr); + break; + } + } + return (rc); +} + +/* Eg: r6 == 0x123EDF or 0xFFFF2034 != 0xDEADBEEF + * regoffs: -1 means lhs is not reg. else offset of reg in cpu_user_regs + * addr: memory location if lhs is not register, eg, 0xFFFF2034 + * condp : points to != or == + * rhsval : right hand side value + */ +static void +kdb_set_bp_cond(int bpnum, int regoffs, ulong addr, char *condp, ulong rhsval) +{ + if (bpnum >= KDBMAXSBP) { + kdbp("BUG: %s got invalid bpnum\n", __FUNCTION__); + return; + } + if (regoffs != -1) { + kdb_sbpa[bpnum].u.bp_cond.bp_cond_status = 1; + kdb_sbpa[bpnum].u.bp_cond.bp_cond_lhs = regoffs; + } else if (addr != 0) { + kdb_sbpa[bpnum].u.bp_cond.bp_cond_status = 2; + kdb_sbpa[bpnum].u.bp_cond.bp_cond_lhs = addr; + } else { + kdbp("error: invalid call to kdb_set_bp_cond\n"); + return; + } + kdb_sbpa[bpnum].u.bp_cond.bp_cond_rhs = rhsval; + + if (*condp == '!') + kdb_sbpa[bpnum].u.bp_cond.bp_cond_type = 2; + else + kdb_sbpa[bpnum].u.bp_cond.bp_cond_type = 1; +} + +/* install breakpt at given addr. + * ni: bp for next instr + * btpa: ptr to args for btp for printing when bp is hit + * lhsp/condp/rhsp: point to strings of condition + * + * RETURNS: the index in array where installed. KDBMAXSBP if error + */ +static int +kdb_set_bp(domid_t domid, kdbva_t addr, int ni, ulong *btpa, char *lhsp, + char *condp, char *rhsp) +{ + int i, pre_existing = 0, regoffs = -1; + ulong memloc=0, rhsval=0, tmpul; + + if (btpa && (lhsp || rhsp || condp)) { + kdbp("internal error. btpa and (lhsp || rhsp || condp) set\n"); + return KDBMAXSBP; + } + if (lhsp && ((regoffs=kdb_valid_reg(lhsp)) == -1) && + kdb_str2ulong(lhsp, &memloc) && + kdb_read_mem(memloc, (kdbbyt_t *)&tmpul, sizeof(tmpul), domid)==0) { + + kdbp("error: invalid argument: %s\n", lhsp); + return KDBMAXSBP; + } + if (rhsp && ! kdb_str2ulong(rhsp, &rhsval)) { + kdbp("error: invalid argument: %s\n", rhsp); + return KDBMAXSBP; + } + + /* see if bp already set */ + for (i=0; i < KDBMAXSBP; i++) { + if (kdb_sbpa[i].bp_addr==addr && kdb_sbpa[i].bp_domid==domid) { + + if (kdb_sbpa[i].bp_deleted) { + /* just re-set this bp again */ + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + pre_existing = 1; + } else { + kdbp("Breakpoint already set \n"); + return KDBMAXSBP; + } + } + } + /* see if any room left for another breakpoint */ + for (i=0; i < KDBMAXSBP; i++) + if (!kdb_sbpa[i].bp_addr) + break; + if (i >= KDBMAXSBP) { + kdbp("ERROR: Breakpoint table full....\n"); + return i; + } + kdb_sbpa[i].bp_addr = addr; + kdb_sbpa[i].bp_domid = domid; + if (btpa) { + kdb_sbpa[i].bp_type = 2; + kdb_sbpa[i].u.bp_btp = btpa; + } else if (regoffs != -1 || memloc) { + kdb_sbpa[i].bp_type = 1; + kdb_set_bp_cond(i, regoffs, memloc, condp, rhsval); + } else + kdb_sbpa[i].bp_type = 0; + + if (kdb_install_swbp(i)) { /* make sure it can be done */ + if (ni) + return i; + + kdb_uninstall_a_swbp(i); /* dont' show user INT3 */ + if (!pre_existing) /* make sure no is cpu sitting on it */ + kdb_sbpa[i].bp_just_added = 1; + + kdbp("bp %d set for domid:%d at: 0x%lx ", i, kdb_sbpa[i].bp_domid, + kdb_sbpa[i].bp_addr); + kdb_prnt_addr2sym(domid, addr, "\n"); + kdb_prnt_bp_extra(i); + } else { + kdbp("ERROR:Can't install bp: 0x%lx domid:%d\n", addr, domid); + if (pre_existing) /* in case a cpu is sitting on this bp in traps */ + kdb_sbpa[i].bp_deleted = 1; + else + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); + return KDBMAXSBP; + } + /* make sure swbp reporting is enabled in the vmcb/vmcs */ + if (!is_pv_domain(kdb_domid2ptr(domid))) { + struct domain *dp = kdb_domid2ptr(domid); + dp->debugger_attached = 1; /* see svm_do_resume/vmx_do_ */ + KDBGP("debugger_attached set. domid:%d\n", domid); + } + return i; +} + +/* + * Set/List Software Breakpoint/s + */ +static kdb_cpu_cmd_t +kdb_usgf_bp(void) +{ + kdbp("bp [addr|sym][domid][condition]: display or set a breakpoint\n"); + kdbp(" where cond is like: r6 == 0x123F or rax != DEADBEEF or \n"); + kdbp(" ffff82c48038fe58 == 321E or 0xffff82c48038fe58 != 0\n"); + kdbp(" regs: rax rbx rcx rdx rsi rdi rbp rsp r8 r9"); + kdbp(" r10 r11 r12 r13 r14 r15 rflags\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_bp(int argc, const char **argv, struct cpu_user_regs *regs) +{ + kdbva_t addr; + int idx = -1; + domid_t domid = DOMID_IDLE; + char *domidstrp, *lhsp=NULL, *condp=NULL, *rhsp=NULL; + + if ((argc > 1 && *argv[1] == '?') || argc == 4 || argc > 6) + return kdb_usgf_bp(); + + if (argc < 2 || kdb_sys_crash) /* list all set breakpoints */ + return kdb_display_sbkpts(); + + /* valid argc either: 2 3 5 or 6 + * 'bp idle_loop r6 == 0xc000' OR 'bp idle_loop 3 r9 != 0xdeadbeef' */ + idx = (argc == 5) ? 2 : ((argc == 6) ? 3 : idx); + if (argc >= 5 ) { + lhsp = (char *)argv[idx]; + condp = (char *)argv[idx+1]; + rhsp = (char *)argv[idx+2]; + + if (!kdb_str2ulong(rhsp, NULL) || *(condp+1) != '=' || + (*condp != '=' && *condp != '!')) { + + return kdb_usgf_bp(); + } + } + domidstrp = (argc == 3 || argc == 6 ) ? (char *)argv[2] : NULL; + if (domidstrp && !kdb_str2domid(domidstrp, &domid, 1)) { + return kdb_usgf_bp(); + } + if (argc > 3 && !is_pv_domain(kdb_domid2ptr(domid))) { + kdbp("HVM domain not supported yet for conditional bp\n"); + return KDB_CPU_MAIN_KDB; + } + + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { + kdbp("Invalid argument:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + + /* make sure xen addr is in xen text, otherwise bp set in 64bit dom0/U */ + if (domid == DOMID_IDLE && + (addr < XEN_VIRT_START || addr > XEN_VIRT_END)) + { + kdbp("addr:%lx not in xen text\n", addr); + return KDB_CPU_MAIN_KDB; + } + kdb_set_bp(domid, addr, 0, NULL, lhsp, condp, rhsp); /* 0 is ni flag */ + return KDB_CPU_MAIN_KDB; +} + + +/* trace breakpoint, meaning, upon bp trace/print some info and continue */ + +static kdb_cpu_cmd_t +kdb_usgf_btp(void) +{ + kdbp("btp addr|sym [domid] reg|domid-mem-addr... : breakpoint trace\n"); + kdbp(" regs: rax rbx rcx rdx rsi rdi rbp rsp r8 r9 "); + kdbp("r10 r11 r12 r13 r14 r15 rflags\n"); + kdbp(" Eg. btp idle_cpu 7 rax rbx 0x20ef5a5 r9\n"); + kdbp(" will print rax, rbx, *(long *)0x20ef5a5, r9 and continue\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_btp(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int i, btpidx, numrd, argsidx, regoffs = -1; + kdbva_t addr, memloc=0; + domid_t domid = DOMID_IDLE; + ulong *btpa, tmpul; + + if ((argc > 1 && *argv[1] == '?') || argc < 3) + return kdb_usgf_btp(); + + argsidx = 2; /* assume 3rd arg is not domid */ + if (argc > 3 && kdb_str2domid(argv[2], &domid, 0)) { + + if (!is_pv_domain(kdb_domid2ptr(domid))) { + kdbp("HVM domains are not currently supprted\n"); + return KDB_CPU_MAIN_KDB; + } else + argsidx = 3; /* 3rd arg is a domid */ + } + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { + kdbp("Invalid argument:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + /* make sure xen addr is in xen text, otherwise will trace 64bit dom0/U */ + if (domid == DOMID_IDLE && + (addr < XEN_VIRT_START || addr > XEN_VIRT_END)) + { + kdbp("addr:%lx not in xen text\n", addr); + return KDB_CPU_MAIN_KDB; + } + + numrd = kdb_guest_bitness(domid)/8; + if (kdb_read_mem(addr, (kdbbyt_t *)&tmpul, numrd, domid) != numrd) { + kdbp("Unable to read mem from %s (%lx)\n", argv[1], addr); + return KDB_CPU_MAIN_KDB; + } + + for (btpidx=0; btpidx < KDBMAXSBP && kdb_btp_ap[btpidx]; btpidx++); + if (btpidx >= KDBMAXSBP) { + kdbp("error: table full. delete few breakpoints\n"); + return KDB_CPU_MAIN_KDB; + } + btpa = kdb_btp_argsa[btpidx]; + memset(btpa, 0, sizeof(kdb_btp_argsa[0])); + + for (i=0; argv[argsidx]; i++, argsidx++) { + + if (((regoffs=kdb_valid_reg(argv[argsidx])) == -1) && + kdb_str2ulong(argv[argsidx], &memloc) && + (memloc < sizeof (struct cpu_user_regs) || + kdb_read_mem(memloc, (kdbbyt_t *)&tmpul, sizeof(tmpul), domid)==0)){ + + kdbp("error: invalid argument: %s\n", argv[argsidx]); + return KDB_CPU_MAIN_KDB; + } + if (i >= KDB_MAXBTP) { + kdbp("error: cannot specify more than %d args\n", KDB_MAXBTP); + return KDB_CPU_MAIN_KDB; + } + btpa[i] = (regoffs == -1) ? memloc : regoffs; + } + + i = kdb_set_bp(domid, addr, 0, btpa, 0, 0, 0); /* 0 is ni flag */ + if (i < KDBMAXSBP) + kdb_btp_ap[btpidx] = kdb_btp_argsa[btpidx]; + + return KDB_CPU_MAIN_KDB; +} + +/* + * Set/List watchpoints, ie, hardware breakpoint/s, in hypervisor + * Usage: wp [sym|addr] [w|i] w == write only data watchpoint + * i == IO watchpoint (read/write) + * + * Eg: wp : list all watchpoints set + * wp addr : set a read/write wp at given addr + * wp addr w : set a write only wp at given addr + * wp addr i : set an IO wp at given addr (16bits port #) + * + * TBD: allow to be set on particular cpu + */ +static kdb_cpu_cmd_t +kdb_usgf_wp(void) +{ + kdbp("wp [addr|sym][w|i]: display or set watchpoint. writeonly or IO\n"); + kdbp("\tnote: watchpoint is triggered after the instruction executes\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_wp(int argc, const char **argv, struct cpu_user_regs *regs) +{ + kdbva_t addr; + domid_t domid = DOMID_IDLE; + int rw = 3, len = 4; /* for now just default to 4 bytes len */ + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_wp(); + + if (argc <= 1 || kdb_sys_crash) { /* list all set watchpoints */ + kdb_do_watchpoints(0, 0, 0); + return KDB_CPU_MAIN_KDB; + } + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { + kdbp("Invalid argument:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + if (argc > 2) { + if (!strcmp(argv[2], "w")) + rw = 1; + else if (!strcmp(argv[2], "i")) + rw = 2; + else { + return kdb_usgf_wp(); + } + } + kdb_do_watchpoints(addr, rw, len); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_wc(void) +{ + kdbp("wc $num|all : clear given or all watchpoints\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_wc(int argc, const char **argv, struct cpu_user_regs *regs) +{ + const char *argp; + int wpnum; /* wp num to delete. -1 for all */ + + if (argc != 2 || *argv[1] == '?') + return kdb_usgf_wc(); + + argp = argv[1]; + + if (!strcmp(argp, "all")) + wpnum = -1; + else if (!kdb_str2deci(argp, &wpnum)) { + kdbp("Invalid wpnum: %s\n", argp); + return KDB_CPU_MAIN_KDB; + } + kdb_clear_wps(wpnum); + return KDB_CPU_MAIN_KDB; +} + +static void +kdb_display_hvm_vcpu(struct vcpu *vp) +{ + struct hvm_vcpu *hvp = &vp->arch.hvm_vcpu; + struct vlapic *vlp = &hvp->vlapic; + struct nestedvcpu *nvp = &hvp->nvcpu; + struct hvm_io_op *ioop; + + kdbp("vcpu:%lx id:%d domid:%d\n", vp, vp->vcpu_id, vp->domain->domain_id); + + ioop = NULL; /* compiler warning */ + kdbp(" &hvm_vcpu:%lx guest_efer:"KDBFL"\n", hvp, hvp->guest_efer); + kdbp(" guest_cr: [0]:"KDBFL" [1]:"KDBFL" [2]:"KDBFL"\n", + hvp->guest_cr[0], hvp->guest_cr[1],hvp->guest_cr[2]); + kdbp(" [3]:"KDBFL" [4]:"KDBFL"\n", hvp->guest_cr[3], + hvp->guest_cr[4]); + kdbp(" hw_cr: [0]:"KDBFL" [1]:"KDBFL" [2]:"KDBFL"\n", hvp->hw_cr[0], + hvp->hw_cr[1], hvp->hw_cr[2]); + kdbp(" [3]:"KDBFL" [4]:"KDBFL"\n", hvp->hw_cr[3], + hvp->hw_cr[4]); + + kdbp(" VLAPIC: base msr:"KDBF64" dis:%x tmrdiv:%x\n", + vlp->hw.apic_base_msr, vlp->hw.disabled, vlp->hw.timer_divisor); + kdbp(" regs:%p regs_page:%p\n", vlp->regs, vlp->regs_page); + kdbp(" periodic time:\n"); + kdb_prnt_periodic_time(&vlp->pt); + + kdbp(" xen_port:%x flag_dr_dirty:%x dbg_st_latch:%x\n", hvp->xen_port, + hvp->flag_dr_dirty, hvp->debug_state_latch); + + kdbp(" Nested: nestedvcpu:%p nv_guestmode:%d\n", nvp, nvp->nv_guestmode); + kdbp(" pending: vmentry:%d vmexit:%d vmswitch:%d\n", + nvp->nv_vmentry_pending, nvp->nv_vmexit_pending, + nvp->nv_vmswitch_in_progress); + + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + + struct arch_vmx_struct *vxp = &hvp->u.vmx; + kdbp(" &vmx: %p vmcs:%lx active_cpu:%x launched:%x\n", vxp, + vxp->vmcs, vxp->active_cpu, vxp->launched); +#if XEN_VERSION != 4 /* xen 3.x.x */ + kdbp(" exec_ctrl:%x vpid:$%d\n", vxp->exec_control, vxp->vpid); +#endif + kdbp(" host_cr0: "KDBFL" vmx: {realm:%x emulate:%x segmask:%x}\n", + vxp->host_cr0, vxp->vmx_realmode, vxp->vmx_emulate, + vxp->vm86_segment_mask); + +#ifdef __x86_64__ + kdbp(" &msr_state:%p exception_bitmap:%lx\n", &vxp->msr_state, + vxp->exception_bitmap); +#endif + } else if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + struct arch_svm_struct *svp = &hvp->u.svm; +#if XEN_VERSION != 4 /* xen 3.x.x */ + kdbp(" &svm: vmcb:%lx pa:"KDBF64" asid:"KDBF64"\n", svp, svp->vmcb, + svp->vmcb_pa, svp->asid_generation); +#endif + kdbp(" msrpm:%p lnch_core:%x vmcb_sync:%x\n", svp->msrpm, + svp->launch_core, svp->vmcb_in_sync); + } + kdbp(" cachemode:%x io: {state: %x data: "KDBFL"}\n", hvp->cache_mode, + hvp->hvm_io.io_state, hvp->hvm_io.io_data); + kdbp(" mmio: {gva: "KDBFL" gpfn: "KDBFL"}\n", hvp->hvm_io.mmio_gva, + hvp->hvm_io.mmio_gpfn); +} + +/* display struct hvm_vcpu{} in struct vcpu.arch{} */ +static kdb_cpu_cmd_t +kdb_usgf_vcpuh(void) +{ + kdbp("vcpuh vcpu-ptr : display hvm_vcpu struct\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_vcpuh(int argc, const char **argv, struct cpu_user_regs *regs) +{ + struct vcpu *vp; + + if (argc < 2 || *argv[1] == '?') + return kdb_usgf_vcpuh(); + + if (!kdb_str2ulong(argv[1], (ulong *)&vp) || !kdb_vcpu_valid(vp) || + is_pv_vcpu(vp)) { + + kdbp("kdb: Bad VCPU: %s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + kdb_display_hvm_vcpu(vp); + return KDB_CPU_MAIN_KDB; +} + +/* also look into arch_get_info_guest() to get context */ +static void +kdb_print_uregs(struct cpu_user_regs *regs) +{ +#ifdef __x86_64__ + kdbp(" rflags: %016lx rip: %016lx\n", regs->rflags, regs->rip); + kdbp(" rax: %016lx rbx: %016lx rcx: %016lx\n", + regs->rax, regs->rbx, regs->rcx); + kdbp(" rdx: %016lx rsi: %016lx rdi: %016lx\n", + regs->rdx, regs->rsi, regs->rdi); + kdbp(" rbp: %016lx rsp: %016lx r8: %016lx\n", + regs->rbp, regs->rsp, regs->r8); + kdbp(" r9: %016lx r10: %016lx r11: %016lx\n", + regs->r9, regs->r10, regs->r11); + kdbp(" r12: %016lx r13: %016lx r14: %016lx\n", + regs->r12, regs->r13, regs->r14); + kdbp(" r15: %016lx\n", regs->r15); + kdbp(" ds: %04x es: %04x fs: %04x gs: %04x " + " ss: %04x cs: %04x\n", regs->ds, regs->es, regs->fs, + regs->gs, regs->ss, regs->cs); + kdbp(" errcode:%08lx entryvec:%08lx upcall_mask:%lx\n", + regs->error_code, regs->entry_vector, regs->saved_upcall_mask); +#else + kdbp(" eflags: %016lx eip: 016lx\n", regs->eflags, regs->eip); + kdbp(" eax: %08x ebx: %08x ecx: %08x edx: %08x\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + kdbp(" esi: %08x edi: %08x ebp: %08x esp: %08x\n", + regs->esi, regs->edi, regs->ebp, regs->esp); + kdbp(" ds: %04x es: %04x fs: %04x gs: %04x " + " ss: %04x cs: %04x\n", regs->ds, regs->es, regs->fs, + regs->gs, regs->ss, regs->cs); + kdbp(" errcode:%04lx entryvec:%04lx upcall_mask:%lx\n", + regs->error_code, regs->entry_vector, regs->saved_upcall_mask); +#endif +} + +#if XEN_SUBVERSION < 3 /* xen 3.1.x or xen 3.2.x */ +#ifdef CONFIG_COMPAT + #undef vcpu_info + #define vcpu_info(v, field) \ + (*(!has_32bit_shinfo((v)->domain) ? \ + (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->native.field : \ + (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->compat.field)) + + #undef __shared_info + #define __shared_info(d, s, field) \ + (*(!has_32bit_shinfo(d) ? \ + (typeof(&(s)->compat.field))&(s)->native.field : \ + (typeof(&(s)->compat.field))&(s)->compat.field)) +#endif +#endif + +static void kdb_display_pv_vcpu(struct vcpu *vp) +{ + int i; + struct pv_vcpu *gp = &vp->arch.pv_vcpu; + + kdbp(" GDT_VIRT_START(vcpu): %lx\n", GDT_VIRT_START(vp)); + kdbp(" GDT: entries:0x%lx frames:\n", gp->gdt_ents); + for (i=0; i < 16; i=i+4) + kdbp(" %016lx %016lx %016lx %016lx\n", gp->gdt_frames[i], + gp->gdt_frames[i+1], gp->gdt_frames[i+2],gp->gdt_frames[i+3]); + + kdbp(" trap_ctxt:%lx kernel_ss:%lx kernel_sp:%lx\n", gp->trap_ctxt, + gp->kernel_ss, gp->kernel_sp); + kdbp(" ctrlregs:\n"); + for (i=0; i < 8; i=i+4) + kdbp(" %016lx %016lx %016lx %016lx\n", gp->ctrlreg[i], + gp->ctrlreg[i+1], gp->ctrlreg[i+2], gp->ctrlreg[i+3]); +#ifdef __x86_64__ + kdbp(" callback: event: %016lx failsafe: %016lx\n", + gp->event_callback_eip, gp->failsafe_callback_eip); + kdbp(" base: fs:0x%lx gskern:0x%lx gsuser:0x%lx\n", + gp->fs_base, gp->gs_base_kernel, gp->gs_base_user); +#else + kdbp(" callback: event: %08lx:%08lx failsafe: %08lx:%08lx\n", + gp->event_callback_cs, gp->event_callback_eip, + gp->failsafe_callback_cs, gp->failsafe_callback_eip); +#endif + kdbp("\n"); +} + +/* Display one VCPU info */ +static void +kdb_display_vcpu(struct vcpu *vp) +{ + int i; + struct arch_vcpu *avp = &vp->arch; + struct paging_vcpu *pvp = &vp->arch.paging; + int domid = vp->domain->domain_id; + + kdbp("\nVCPU: vcpu-id:%d vcpu-ptr:%p ", vp->vcpu_id, vp); + kdbp(" processor:%d domid:%d domp:%p\n", vp->processor, domid,vp->domain); + + if (domid == DOMID_IDLE) { + kdbp(" IDLE vcpu.\n"); + return; + } + kdbp(" pause: flags:0x%016lx count:%x\n", vp->pause_flags, + vp->pause_count.counter); + kdbp(" vcpu: initdone:%d running:%d\n", + vp->is_initialised, vp->is_running); + kdbp(" mcepend:%d nmipend:%d shut: def:%d paused:%d\n", + vp->mce_pending, vp->nmi_pending, vp->defer_shutdown, + vp->paused_for_shutdown); + kdbp(" &vcpu_info:%p : evtchn_upc_pend:%x _mask:%x\n", + vp->vcpu_info, vcpu_info(vp, evtchn_upcall_pending), + vcpu_info(vp, evtchn_upcall_mask)); + kdbp(" evt_pend_sel:%lx poll_evtchn:%x ", + *(unsigned long *)&vcpu_info(vp, evtchn_pending_sel), vp->poll_evtchn); + kdb_print_spin_lock("virq_lock:", &vp->virq_lock, "\n"); + for (i=0; i < NR_VIRQS; i++) + if (vp->virq_to_evtchn[i] != 0) + kdbp(" virq:$%d port:$%d\n", i, vp->virq_to_evtchn[i]); + + kdbp(" next:%p periodic: period:0x%lx last_event:0x%lx\n", + vp->next_in_list, vp->periodic_period, vp->periodic_last_event); + kdbp(" cpu_affinity:0x%lx vcpu_dirty_cpumask:%p sched_priv:0x%p\n", + vp->cpu_affinity, vp->vcpu_dirty_cpumask, vp->sched_priv); + kdbp(" &runstate: %p state: %x (eg. RUNSTATE_running) guestptr:%p", + &vp->runstate, vp->runstate.state, runstate_guest(vp)); + kdbp(" vcpu_info_mfn:%lx\n", vp->vcpu_info_mfn); + kdbp("\n"); + kdbp(" arch info: (%p)\n", &vp->arch); + kdbp(" guest_context: VGCF_ flags:%lx", + vp->arch.vgc_flags); /* VGCF_in_kernel */ + if (!is_pv_vcpu(vp)) + kdbp(" (HVM guest: IP, SP, EFLAGS may be stale)"); + kdbp("\n"); + kdb_print_uregs(&vp->arch.user_regs); + kdbp(" debugregs:\n"); + for (i=0; i < 8; i=i+4) + kdbp(" %016lx %016lx %016lx %016lx\n", avp->debugreg[i], + avp->debugreg[i+1], avp->debugreg[i+2], avp->debugreg[i+3]); + + if (is_pv_vcpu(vp)) + kdb_display_pv_vcpu(vp); + else + kdb_display_hvm_vcpu(vp); + + kdbp(" TF_flags: %016lx monitor_tbl:%lx\n", + vp->arch.flags, vp->arch.monitor_table.pfn); + kdbp(" guest_table: %016lx cr3:%016lx\n", + vp->arch.guest_table.pfn, avp->cr3); + kdbp(" paging: \n"); + kdbp(" vtlb:%p\n", &pvp->vtlb); + kdbp(" &pg_mode:%p gstlevels:%d &shadow:%p shlevels:%d\n", + pvp->mode, pvp->mode->guest_levels, &pvp->mode->shadow, + pvp->mode->shadow.shadow_levels); + kdbp(" shadow_vcpu:\n"); + kdbp(" guest_vtable:%p last em_mfn:"KDBFL"\n", + pvp->shadow.guest_vtable, pvp->shadow.last_emulated_mfn); +#if CONFIG_PAGING_LEVELS >= 3 + kdbp(" l3tbl: 3:"KDBFL" 2:"KDBFL"\n" + " 1:"KDBFL" 0:"KDBFL"\n", + pvp->shadow.l3table[3].l3, pvp->shadow.l3table[2].l3, + pvp->shadow.l3table[1].l3, pvp->shadow.l3table[0].l3); + kdbp(" gl3tbl: 3:"KDBFL" 2:"KDBFL"\n" + " 1:"KDBFL" 0:"KDBFL"\n", + pvp->shadow.gl3e[3].l3, pvp->shadow.gl3e[2].l3, + pvp->shadow.gl3e[1].l3, pvp->shadow.gl3e[0].l3); +#endif + kdbp(" gdbsx_vcpu_event:%x\n", vp->arch.gdbsx_vcpu_event); +} + +/* + * FUNCTION: Dispaly (current) VCPU/s + */ +static kdb_cpu_cmd_t +kdb_usgf_vcpu(void) +{ + kdbp("vcpu [vcpu-ptr] : display current/vcpu-ptr vcpu info\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_vcpu(int argc, const char **argv, struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + + if (argc > 2 || (argc > 1 && *argv[1] == '?')) + kdb_usgf_vcpu(); + else if (argc <= 1) + kdb_display_vcpu(v); + else if (kdb_str2ulong(argv[1], (ulong *)&v) && kdb_vcpu_valid(v)) + kdb_display_vcpu(v); + else + kdbp("Invalid usage/argument:%s v:%lx\n", argv[1], (long)v); + return KDB_CPU_MAIN_KDB; +} + +/* from paging_dump_domain_info() */ +static void kdb_pr_dom_pg_modes(struct domain *d) +{ + if (paging_mode_enabled(d)) { + kdbp(" paging mode enabled"); + if ( paging_mode_shadow(d) ) + kdbp(" shadow(PG_SH_enable)"); + if ( paging_mode_hap(d) ) + kdbp(" hap(PG_HAP_enable) "); + if ( paging_mode_refcounts(d) ) + kdbp(" refcounts(PG_refcounts) "); + if ( paging_mode_log_dirty(d) ) + kdbp(" log_dirty(PG_log_dirty) "); + if ( paging_mode_translate(d) ) + kdbp(" translate(PG_translate) "); + if ( paging_mode_external(d) ) + kdbp(" external(PG_external) "); + } else + kdbp(" disabled"); + kdbp("\n"); +} + +/* print event channels info for a given domain + * NOTE: very confusing, port and event channel refer to the same thing. evtchn + * is arry of pointers to a bucket of pointers to 128 struct evtchn{}. while + * 64bit xen can handle 4096 max channels, a 32bit guest is limited to 1024 */ +static void noinline kdb_print_dom_eventinfo(struct domain *dp) +{ + uint chn; + + kdbp("\n"); + + kdbp("Fixme. Event channel redesigned\n"); + return; + + kdbp(" Evt: MAX_NR_EVTCHNS:$%d ptr:%p pollmsk:%08lx ", + MAX_NR_EVTCHNS, dp->evtchn, dp->poll_mask[0]); + kdb_print_spin_lock("lk:", &dp->event_lock, "\n"); + kdbp(" &evtchn_pending:%p &evtchn_mask:%p\n", + shared_info(dp, evtchn_pending), shared_info(dp, evtchn_mask)); + + kdbp(" Channels info: (everything is in decimal):\n"); + for (chn=0; chn < MAX_NR_EVTCHNS; chn++ ) { + struct evtchn *bktp = &dp->evtchn[chn/EVTCHNS_PER_BUCKET]; + struct evtchn *chnp = &bktp[chn & (EVTCHNS_PER_BUCKET-1)]; + char pbit = test_bit(chn, &shared_info(dp, evtchn_pending)) ? 'Y' : 'N'; + char mbit = test_bit(chn, &shared_info(dp, evtchn_mask)) ? 'Y' : 'N'; + + if (bktp==NULL || chnp->state==ECS_FREE) + continue; + + kdbp(" chn:%4u st:%d _xen=%d _vcpu_id:%2d ", chn, chnp->state, + chnp->xen_consumer, chnp->notify_vcpu_id); + if (chnp->state == ECS_UNBOUND) + kdbp(" rem-domid:%d", chnp->u.unbound.remote_domid); + else if (chnp->state == ECS_INTERDOMAIN) + kdbp(" rem-port:%d rem-dom:%d", chnp->u.interdomain.remote_port, + chnp->u.interdomain.remote_dom->domain_id); + else if (chnp->state == ECS_PIRQ) + kdbp(" pirq:%d", chnp->u.pirq); + else if (chnp->state == ECS_VIRQ) + kdbp(" virq:%d", chnp->u.virq); + + kdbp(" pend:%c mask:%c\n", pbit, mbit); + } +#if 0 + kdbp("pirq to evtchn mapping (pirq:evtchn) (all decimal):\n"); + for (i=0; i < dp->nr_pirqs; i ++) + if (dp->pirq_to_evtchn[i]) + kdbp("(%d:%d) ", i, dp->pirq_to_evtchn[i]); + kdbp("\n"); +#endif +} + +static void kdb_prnt_hvm_dom_info(struct domain *dp) +{ + struct hvm_domain *hvp = &dp->arch.hvm_domain; + + kdbp(" ioreq.page:%lx ioreq.va:%lx\n", hvp->ioreq.page, hvp->ioreq.va); + kdbp(" buf_ioreq.page:%lx ioreq.va:%lx\n", hvp->buf_ioreq.page, + hvp->buf_ioreq.va); + + kdbp(" HVM info: Hap is%s enabled\n", + dp->arch.hvm_domain.hap_enabled ? "" : " not"); + + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + struct p2m_domain *p2m = p2m_get_hostp2m(dp); + struct ept_data *ept = &p2m->ept; + kdbp(" EPT: ept_mt:%x ept_wl:%x asr:%013lx\n", + ept->ept_mt, ept->ept_wl, ept->asr); + } + if (hvp == NULL) + return; + + if (hvp->irq.callback_via_type == HVMIRQ_callback_vector) + kdbp(" HVMIRQ_callback_vector: %x\n", hvp->irq.callback_via.vector); + + if (!hvp->params) + return; + + kdbp(" HVM PARAMS (all in hex):\n"); + kdbp("\tHVM_PARAM_CALLBACK_IRQ: %x\n", hvp->params[HVM_PARAM_CALLBACK_IRQ]); + kdbp("\tHVM_PARAM_STORE_PFN: %x\n", hvp->params[HVM_PARAM_STORE_PFN]); + kdbp("\tHVM_PARAM_STORE_EVTCHN: %x\n", hvp->params[HVM_PARAM_STORE_EVTCHN]); + kdbp("\tHVM_PARAM_PAE_ENABLED: %x\n", hvp->params[HVM_PARAM_PAE_ENABLED]); + kdbp("\tHVM_PARAM_IOREQ_PFN: %x\n", hvp->params[HVM_PARAM_IOREQ_PFN]); + kdbp("\tHVM_PARAM_BUFIOREQ_PFN: %x\n", hvp->params[HVM_PARAM_BUFIOREQ_PFN]); + kdbp("\tHVM_PARAM_VIRIDIAN: %x\n", hvp->params[HVM_PARAM_VIRIDIAN]); + kdbp("\tHVM_PARAM_TIMER_MODE: %x\n", hvp->params[HVM_PARAM_TIMER_MODE]); + kdbp("\tHVM_PARAM_HPET_ENABLED: %x\n", hvp->params[HVM_PARAM_HPET_ENABLED]); + kdbp("\tHVM_PARAM_IDENT_PT: %x\n", hvp->params[HVM_PARAM_IDENT_PT]); + kdbp("\tHVM_PARAM_DM_DOMAIN: %x\n", hvp->params[HVM_PARAM_DM_DOMAIN]); + kdbp("\tHVM_PARAM_ACPI_S_STATE: %x\n", hvp->params[HVM_PARAM_ACPI_S_STATE]); + kdbp("\tHVM_PARAM_VM86_TSS: %x\n", hvp->params[HVM_PARAM_VM86_TSS]); + kdbp("\tHVM_PARAM_VPT_ALIGN: %x\n", hvp->params[HVM_PARAM_VPT_ALIGN]); + kdbp("\tHVM_PARAM_CONSOLE_PFN: %x\n", hvp->params[HVM_PARAM_CONSOLE_PFN]); + kdbp("\tHVM_PARAM_CONSOLE_EVTCHN: %x\n", + hvp->params[HVM_PARAM_CONSOLE_EVTCHN]); + kdbp("\tHVM_PARAM_ACPI_IOPORTS_LOCATION: %x\n", + hvp->params[HVM_PARAM_ACPI_IOPORTS_LOCATION]); + kdbp("\tHVM_PARAM_MEMORY_EVENT_SINGLE_STEP: %x\n", + hvp->params[HVM_PARAM_MEMORY_EVENT_SINGLE_STEP]); +} +static void kdb_print_rangesets(struct domain *dp) +{ + int locked = spin_is_locked(&dp->rangesets_lock); + + if (locked) + spin_unlock(&dp->rangesets_lock); + rangeset_domain_printk(dp); + if (locked) + spin_lock(&dp->rangesets_lock); +} + +static void kdb_pr_vtsc_info(struct arch_domain *ap) +{ + kdbp(" VTSC info: tsc_mode:%x vtsc:%x vtsc_last:%016lx\n", + ap->tsc_mode, ap->vtsc, ap->vtsc_last); + kdbp(" vtsc_offset:%016lx tsc_khz:%08lx incarnation:%x\n", + ap->vtsc_offset, ap->vtsc_offset, ap->incarnation); + kdbp(" vtsc_kerncount:%016lx _usercount:%016lx\n", + ap->vtsc_kerncount, ap->vtsc_usercount); +} + +static void kdb_print_p2mlock(struct domain *dp) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(dp); + mm_rwlock_t *lp = p2m ? &p2m->lock : NULL; + + if (lp == NULL) { + kdbp(" p2m lock ptr is null\n"); + return; + } + kdbp(" p2m lockval: %x unlock_level:%x recurse_count:%x locker cpu:%x\n", + lp->lock.raw.lock, lp->unlock_level, lp->recurse_count, + lp->locker); + kdbp(" p2m locker_function:%s\n", lp->locker_function); +} + +/* display one domain info */ +static void +kdb_display_dom(struct domain *dp) +{ + struct vcpu *vp; + int printed = 0; + struct grant_table *gp = dp->grant_table; + struct arch_domain *ap = &dp->arch; + + kdbp("\nDOMAIN : domid:0x%04x ptr:0x%p\n", dp->domain_id, dp); + if (dp->domain_id == DOMID_IDLE) { + kdbp(" IDLE domain.\n"); + return; + } + if (dp->is_dying) { + kdbp(" domain is DYING.\n"); + return; + } +#if 0 + kdb_print_spin_lock(" pgalk:", &dp->page_alloc_lock, "\n"); + kdbp(" pglist: 0x%p 0x%p\n", dp->page_list.next,KDB_PGLLE(dp->page_list)); + kdbp(" xpglist: 0x%p 0x%p\n", dp->xenpage_list.next, + KDB_PGLLE(dp->xenpage_list)); + kdbp(" next:0x%p hashnext:0x%p\n", + dp->next_in_list, dp->next_in_hashbucket); +#endif + kdbp(" PAGES: tot:0x%08x max:0x%08x xenheap:0x%08x\n", + dp->tot_pages, dp->max_pages, dp->xenheap_pages); + + kdb_print_rangesets(dp); + kdb_print_dom_eventinfo(dp); + kdbp("\n"); + kdbp(" Grant table: gp:0x%p\n", gp); + if (gp) { + kdbp(" nr_frames:0x%08x shpp:0x%p active:0x%p\n", + gp->nr_grant_frames, gp->shared_raw, gp->active); + kdbp(" maptrk:0x%p maphd:0x%08x maplmt:0x%08x\n", + gp->maptrack, gp->maptrack_head, gp->maptrack_limit); + kdbp(" mapcnt:"); + kdb_print_spin_lock("mapcnt: lk:", &gp->lock, "\n"); + } + kdbp(" guest_type:%s priv:%d need_iommu:%d dbg:%d dying:%d paused:%d\n", + is_pvh_domain(dp) ? "PVH" : is_hvm_domain(dp) ? "HVM" : "PV(not PVH)", + dp->is_privileged, dp->need_iommu, dp->debugger_attached, dp->is_dying, + dp->is_paused_by_controller); + kdb_print_spin_lock(" shutdown: lk:", &dp->shutdown_lock, "\n"); + kdbp(" shutn:%d shut:%d code:%d \n", dp->is_shutting_down, + dp->is_shut_down, dp->shutdown_code); + kdbp(" pausecnt:0x%08x vm_assist:0x"KDBFL" refcnt:0x%08x\n", + dp->pause_count.counter, dp->vm_assist, dp->refcnt.counter); + kdbp(" &domain_dirty_cpumask:%p\n", &dp->domain_dirty_cpumask); + + kdbp(" shared == vcpu_info[]: %p\n", dp->shared_info); + kdbp(" arch_shared: maxpfn: %lx pfn-mfn-frame-ll mfn: %lx\n", + arch_get_max_pfn(dp), arch_get_pfn_to_mfn_frame_list_list(dp)); + kdbp("\n"); + + if (!is_pv_domain(dp)) + kdb_prnt_hvm_dom_info(dp); + kdbp("\n"); + + kdbp(" arch_domain at : %p\n", ap); + kdbp(" ioport:0x%p &hvm_dom:0x%p\n", ap->ioport_caps, &ap->hvm_domain); + kdbp(" &pging_dom:%p mode: %lx", &ap->paging, ap->paging.mode); + kdb_pr_dom_pg_modes(dp); + kdbp(" p2m ptr:%p pages:{%p, %p}\n", ap->p2m, ap->p2m->pages.next, + KDB_PGLLE(ap->p2m->pages)); + kdb_print_p2mlock(dp); + kdbp(" max_mapped_pfn:"KDBFL, ap->p2m->max_mapped_pfn); +#if XEN_SUBVERSION > 0 && XEN_VERSION == 4 /* xen 4.1 and above */ + kdbp(" phys_table:%p\n", ap->p2m->phys_table.pfn); +#else + kdbp(" phys_table.pfn:"KDBFL"\n", ap->phys_table.pfn); +#endif + kdbp(" physaddr_bitsz:%d 32bit_pv:%d has_32bit_shinfo:%d\n", + ap->physaddr_bitsize, ap->is_32bit_pv, ap->has_32bit_shinfo); + kdb_pr_vtsc_info(ap); + kdbp(" sched:0x%p &handle:0x%p\n", dp->sched_priv, &dp->handle); + kdbp(" vcpu ptrs:\n "); + for_each_vcpu(dp, vp) { + kdbp(" %d:%p", vp->vcpu_id, vp); + if (++printed % 4 == 0) kdbp("\n "); + } + kdbp("\n"); +} + +/* + * FUNCTION: Dispaly (current) domain/s + */ +static kdb_cpu_cmd_t +kdb_usgf_dom(void) +{ + kdbp("dom [all|domid]: Display current/all/given domain/s\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dom(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int id; + struct domain *dp = current->domain; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dom(); + + if (argc > 1) { + for(dp=domain_list; dp; dp=dp->next_in_list) + if (kdb_str2deci(argv[1], &id) && dp->domain_id==id) + kdb_display_dom(dp); + else if (!strcmp(argv[1], "all")) + kdb_display_dom(dp); + } else { + kdbp("Displaying current domain :\n"); + kdb_display_dom(dp); + } + return KDB_CPU_MAIN_KDB; +} + +/* Dump irq desc table */ +static kdb_cpu_cmd_t +kdb_usgf_dirq(void) +{ + kdbp("dirq : dump irq bindings\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dirq(int argc, const char **argv, struct cpu_user_regs *regs) +{ + unsigned long irq, sz, offs, addr; + char buf[KSYM_NAME_LEN+1]; + char affstr[NR_CPUS/4+NR_CPUS/32+2]; /* courtesy dump_irqs() */ + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dirq(); + +#if XEN_VERSION < 4 && XEN_SUBVERSION < 5 /* xen 3.4.x or below */ + kdbp("idx/irq#/status: all are in decimal\n"); + kdbp("idx irq# status action(handler name devid)\n"); + for (irq=0; irq < NR_VECTORS; irq++) { + irq_desc_t *dp = &irq_desc[irq]; + if (!dp->action) + continue; + addr = (unsigned long)dp->action->handler; + kdbp("[%3ld]:irq:%3d st:%3d f:%s devnm:%s devid:0x%p\n", + i, vector_to_irq(irq), dp->status, (dp->status & IRQ_GUEST) ? + "GUEST IRQ" : symbols_lookup(addr, &sz, &offs, buf), + dp->action->name, dp->action->dev_id); + } +#else + kdbp("irq_desc[]:%p nr_irqs: $%d nr_irqs_gsi: $%d\n", irq_desc, nr_irqs, + nr_irqs_gsi); + kdbp("irq/vec#/status: in decimal. affinity in hex, not bitmap\n"); + kdbp("irq-- vec sta function----------- name---- type--------- "); + kdbp("aff devid------------\n"); + for (irq=0; irq < nr_irqs; irq++) { + void *devidp; + const char *symp, *nmp; + irq_desc_t *dp = irq_to_desc(irq); + struct arch_irq_desc *archp = &dp->arch; + + if (!dp->handler || dp->handler==&no_irq_type || dp->status & IRQ_GUEST) + continue; + + addr = dp->action ? (unsigned long)dp->action->handler : 0; + symp = addr ? symbols_lookup(addr, &sz, &offs, buf) : "n/a "; + nmp = addr ? dp->action->name : "n/a "; + devidp = addr ? dp->action->dev_id : NULL; + cpumask_scnprintf(affstr, sizeof(affstr), dp->affinity); + kdbp("[%3ld] %03d %03d %-19s %-8s %-13s %3s 0x%p\n", irq, archp->vector, + dp->status, symp, nmp, dp->handler->typename, affstr, devidp); + } + kdb_prnt_guest_mapped_irqs(); +#endif + return KDB_CPU_MAIN_KDB; +} + +static void +kdb_prnt_vec_irq_table(int cpu) +{ + int i,j, *tbl = per_cpu(vector_irq, cpu); + + kdbp("CPU %d : ", cpu); + for (i=0, j=0; i < NR_VECTORS; i++) + if (tbl[i] != -1) { + kdbp("(%3d:%3d) ", i, tbl[i]); + if (!(++j % 5)) + kdbp("\n "); + } + kdbp("\n"); +} + +/* Dump irq desc table */ +static kdb_cpu_cmd_t +kdb_usgf_dvit(void) +{ + kdbp("dvit [cpu|all]: dump (per cpu)vector irq table\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dvit(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int cpu, ccpu = smp_processor_id(); + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dvit(); + + if (argc > 1) { + if (!strcmp(argv[1], "all")) + cpu = -1; + else if (!kdb_str2deci(argv[1], &cpu)) { + kdbp("Invalid cpu:%d\n", cpu); + return kdb_usgf_dvit(); + } + } else + cpu = ccpu; + + kdbp("Per CPU vector irq table pairs (vector:irq) (all decimals):\n"); + if (cpu != -1) + kdb_prnt_vec_irq_table(cpu); + else + for_each_online_cpu(cpu) + kdb_prnt_vec_irq_table(cpu); + + return KDB_CPU_MAIN_KDB; +} + +/* do vmexit on all cpu's so intel VMCS can be dumped */ +static kdb_cpu_cmd_t +kdb_all_cpu_flush_vmcs(void) +{ + int cpu, ccpu = smp_processor_id(); + for_each_online_cpu(cpu) { + if (cpu == ccpu) { + kdb_curr_cpu_flush_vmcs(); + } else { + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE){ /* hung cpu */ + kdbp("Skipping (hung?) cpu %d\n", cpu); + continue; + } + kdb_cpu_cmd[cpu] = KDB_CPU_DO_VMEXIT; + while (kdb_cpu_cmd[cpu]==KDB_CPU_DO_VMEXIT); + } + } + return KDB_CPU_MAIN_KDB; +} + +/* Display VMCS or VMCB */ +static kdb_cpu_cmd_t +kdb_usgf_dvmc(void) +{ + kdbp("dvmc [domid][vcpuid] : Dump vmcs/vmcb\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dvmc(int argc, const char **argv, struct cpu_user_regs *regs) +{ + domid_t domid = 0; /* unsigned type don't like -1 */ + int vcpuid = -1; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dvmc(); + + if (argc > 1) { + if (!kdb_str2domid(argv[1], &domid, 1)) + return KDB_CPU_MAIN_KDB; + } + if (argc > 2 && !kdb_str2deci(argv[2], &vcpuid)) { + kdbp("Bad vcpuid: 0x%x\n", vcpuid); + return KDB_CPU_MAIN_KDB; + } + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + kdb_all_cpu_flush_vmcs(); + kdb_dump_vmcs(domid, (int)vcpuid); + } else { + kdb_dump_vmcb(domid, (int)vcpuid); + } + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_mmio(void) +{ + kdbp("mmio: dump mmio related info\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_mmio(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_mmio(); + + kdbp("r/o mmio ranges:\n"); + rangeset_printk(mmio_ro_ranges); + kdbp("\n"); + return KDB_CPU_MAIN_KDB; +} + +/* Dump timer/timers queues */ +static kdb_cpu_cmd_t +kdb_usgf_dtrq(void) +{ + kdbp("dtrq: dump timer queues on all cpus\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dtrq(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dtrq(); + + kdb_dump_timer_queues(); + return KDB_CPU_MAIN_KDB; +} + +struct idte { + uint16_t offs0_15; + uint16_t selector; + uint16_t meta; + uint16_t offs16_31; + uint32_t offs32_63; + uint32_t resvd; +}; + +#ifdef __x86_64__ +static void +kdb_print_idte(int num, struct idte *idtp) +{ + uint16_t mta = idtp->meta; + char dpl = ((mta & 0x6000) >> 13); + char present = ((mta &0x8000) >> 15); + int tval = ((mta &0x300) >> 8); + char *type = (tval == 1) ? "Task" : ((tval== 2) ? "Intr" : "Trap"); + domid_t domid = idtp->selector==__HYPERVISOR_CS64 ? DOMID_IDLE : + current->domain->domain_id; + uint64_t addr = idtp->offs0_15 | ((uint64_t)idtp->offs16_31 << 16) | + ((uint64_t)idtp->offs32_63 << 32); + + kdbp("[%03d]: %s %x %x %04x:%016lx ", num, type, dpl, present, + idtp->selector, addr); + kdb_prnt_addr2sym(domid, addr, "\n"); +} + +/* Dump 64bit idt table currently on this cpu. Intel Vol 3 section 5.14.1 */ +static kdb_cpu_cmd_t +kdb_usgf_didt(void) +{ + kdbp("didt : dump IDT table on the current cpu\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_didt(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int i; + struct idte *idtp = (struct idte *)idt_tables[smp_processor_id()]; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_didt(); + + kdbp("IDT at:%p\n", idtp); + kdbp("idt# Type DPL P addr (all hex except idt#)\n", idtp); + for (i=0; i < 256; i++, idtp++) + kdb_print_idte(i, idtp); + return KDB_CPU_MAIN_KDB; +} +#else +static kdb_cpu_cmd_t +kdb_cmdf_didt(int argc, const char **argv, struct cpu_user_regs *regs) +{ + kdbp("kdb: Please implement me in 32bit hypervisor\n"); + return KDB_CPU_MAIN_KDB; +} +#endif + +struct gdte { /* same for TSS and LDT */ + ulong limit0:16; + ulong base0:24; /* linear address base, not pa */ + ulong acctype:4; /* Type: access rights */ + ulong S:1; /* S: 0 = system, 1 = code/data */ + ulong DPL:2; /* DPL */ + ulong P:1; /* P: Segment Present */ + ulong limit1:4; + ulong AVL:1; /* AVL: avail for use by system software */ + ulong L:1; /* L: 64bit code segment */ + ulong DB:1; /* D/B */ + ulong G:1; /* G: granularity */ + ulong base1:8; /* linear address base, not pa */ +}; + +union gdte_u { + struct gdte gdte; + u64 gval; +}; + +struct call_gdte { + unsigned short offs0:16; + unsigned short sel:16; + unsigned short misc0:16; + unsigned short offs1:16; +}; + +struct idt_gdte { + unsigned long offs0:16; + unsigned long sel:16; + unsigned long ist:3; + unsigned long unused0:13; + unsigned long offs1:16; +}; +union sgdte_u { + struct call_gdte cgdte; + struct idt_gdte igdte; + u64 sgval; +}; + +/* return binary form of a hex in string : max 4 chars 0000 to 1111 */ +static char *kdb_ret_acctype(uint acctype) +{ + static char buf[16]; + char *p = buf; + int i; + + if (acctype > 0xf) { + buf[0] = buf[1] = buf[2] = buf[3] = '?'; + buf[5] = '\n'; + return buf; + } + for (i=0; i < 4; i++, p++, acctype=acctype>>1) + *p = (acctype & 0x1) ? '1' : '0'; + + return buf; +} + +/* Display GDT table. IA-32e mode is assumed. */ +/* first display non system descriptors then display system descriptors */ +static kdb_cpu_cmd_t +kdb_usgf_dgdt(void) +{ + kdbp("dgdt [gdt-ptr decimal-byte-size [domid]] dump GDT table on current " + "cpu or for given vcpu\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dgdt(int argc, const char **argv, struct cpu_user_regs *regs) +{ + struct Xgt_desc_struct desc; + union gdte_u u1; + ulong start_addr, end_addr, taddr=0; + domid_t domid = DOMID_IDLE; + int idx; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_dgdt(); + + if (argc > 1) { + if (argc == 4 && !kdb_str2domid(argv[3], &domid, 1)) + return kdb_usgf_dgdt(); + if (argc != 3 && argc != 4) + return kdb_usgf_dgdt(); + + if (kdb_str2ulong(argv[1], (ulong *)&start_addr) && + kdb_str2deci(argv[2], (int *)&taddr)) { + end_addr = start_addr + taddr; + } else { + kdbp("dgdt: Bad arg:%s or %s\n", argv[1], argv[2]); + return kdb_usgf_dgdt(); + } + } else { + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory"); + start_addr = (ulong)desc.address; + end_addr = (ulong)desc.address + desc.size; + } + kdbp("GDT: Will skip null desc at 0, start:%lx end:%lx\n", start_addr, + end_addr); + kdbp("[idx] sel --- val -------- Accs DPL P AVL L DB G " + "--Base Addr ---- Limit\n"); + kdbp(" Type\n"); + + /* skip first 8 null bytes */ + /* the cpu multiplies the index by 8 and adds to GDT.base */ + for (taddr = start_addr+8; taddr < end_addr; taddr += sizeof(ulong)) { + + /* not all entries are mapped. do this to avoid GP even if hyp */ + if (!kdb_read_mem(taddr, (kdbbyt_t *)&u1, sizeof(u1),domid) || !u1.gval) + continue; + + if (u1.gval == 0xffffffffffffffff || u1.gval == 0x5555555555555555) + continue; /* what an effin x86 mess */ + + idx = (taddr - start_addr) / 8; + if (u1.gdte.S == 0) { /* System Desc are 16 bytes in 64bit mode */ + taddr += sizeof(ulong); + continue; + } + kdbp("[%04x] %04x %016lx %4s %x %d %d %d %d %d %016lx %05x\n", + idx, (idx<<3), u1.gval, kdb_ret_acctype(u1.gdte.acctype), + u1.gdte.DPL, + u1.gdte.P, u1.gdte.AVL, u1.gdte.L, u1.gdte.DB, u1.gdte.G, + (u64)((u64)u1.gdte.base0 | (u64)((u64)u1.gdte.base1<<24)), + u1.gdte.limit0 | (u1.gdte.limit1<<16)); + } + + kdbp("\nSystem descriptors (S=0) : (skipping 0th entry)\n"); + for (taddr=start_addr+8; taddr < end_addr; taddr += sizeof(ulong)) { + uint acctype; + u64 upper, addr64=0; + + /* not all entries are mapped. do this to avoid GP even if hyp */ + if (kdb_read_mem(taddr, (kdbbyt_t *)&u1, sizeof(u1), domid)==0 || + u1.gval == 0 || u1.gdte.S == 1) { + continue; + } + idx = (taddr - start_addr) / 8; + taddr += sizeof(ulong); + if (kdb_read_mem(taddr, (kdbbyt_t *)&upper, 8, domid) == 0) { + kdbp("Could not read upper 8 bytes of system desc\n"); + upper = 0; + } + acctype = u1.gdte.acctype; + if (acctype != 2 && acctype != 9 && acctype != 11 && acctype !=12 && + acctype != 14 && acctype != 15) + continue; + + kdbp("[%04x] %04x val:%016lx DPL:%x P:%d type:%x ", + idx, (idx<<3), u1.gval, u1.gdte.DPL, u1.gdte.P, acctype); + + upper = (u64)((u64)(upper & 0xFFFFFFFF) << 32); + + /* Vol 3A: table: 3-2 page: 3-19 */ + if (acctype == 2) { + kdbp("LDT gate (0010)\n"); + } + else if (acctype == 9) { + kdbp("TSS avail gate(1001)\n"); + } + else if (acctype == 11) { + kdbp("TSS busy gate(1011)\n"); + } + else if (acctype == 12) { + kdbp("CALL gate (1100)\n"); + } + else if (acctype == 14) { + kdbp("IDT gate (1110)\n"); + } + else if (acctype == 15) { + kdbp("Trap gate (1111)\n"); + } + + if (acctype == 2 || acctype == 9 || acctype == 11) { + kdbp(" AVL:%d G:%d Base Addr:%016lx Limit:%x\n", + u1.gdte.AVL, u1.gdte.G, + (u64)((u64)u1.gdte.base0 | ((u64)u1.gdte.base1<<24)| upper), + (u32)u1.gdte.limit0 | (u32)((u32)u1.gdte.limit1<<16)); + + } else if (acctype == 12) { + union sgdte_u u2; + u2.sgval = u1.gval; + + addr64 = (u64)((u64)u2.cgdte.offs0 | + (u64)((u64)u2.cgdte.offs1<<16) | upper); + kdbp(" Entry: %04x:%016lx\n", u2.cgdte.sel, addr64); + } else if (acctype == 14 || acctype == 15) { + union sgdte_u u2; + u2.sgval = u1.gval; + + addr64 = (u64)((u64)u2.igdte.offs0 | + (u64)((u64)u2.igdte.offs1<<16) | upper); + kdbp(" Entry: %04x:%016lx ist:%03x\n", u2.igdte.sel, addr64, + u2.igdte.ist); + } else + kdbp(" Error: Unrecongized type:%lx\n", acctype); + } + return KDB_CPU_MAIN_KDB; +} + +/* Display scheduler basic and extended info */ +static kdb_cpu_cmd_t +kdb_usgf_sched(void) +{ + kdbp("sched: show schedular info and run queues\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_sched(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_sched(); + + kdb_print_sched_info(); + return KDB_CPU_MAIN_KDB; +} + +/* Display MMU basic and extended info */ +static kdb_cpu_cmd_t +kdb_usgf_mmu(void) +{ + kdbp("mmu: print basic MMU info\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_mmu(int argc, const char **argv, struct cpu_user_regs *regs) +{ + int cpu; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_mmu(); + + kdbp("MMU Info:\n"); + kdbp("total pages: %lx\n", total_pages); + kdbp("max page/mfn: %lx\n", max_page); + kdbp("total_free_pages(): %lx\n", total_free_pages()); + kdbp("frame_table: %p\n", frame_table); + kdbp("DIRECTMAP_VIRT_START: %lx\n", DIRECTMAP_VIRT_START); + kdbp("DIRECTMAP_VIRT_END: %lx\n", DIRECTMAP_VIRT_END); + kdbp("DIRECTMAP_SIZE: %lx\n", DIRECTMAP_SIZE); + kdbp("HYPERVISOR_VIRT_START: %lx\n", HYPERVISOR_VIRT_START); + kdbp("HYPERVISOR_VIRT_END: %lx\n", HYPERVISOR_VIRT_END); + kdbp("RO_MPT_VIRT_START: %lx\n", RO_MPT_VIRT_START); + kdbp("PERDOMAIN_VIRT_START: %lx\n", PERDOMAIN_VIRT_START); + kdbp("CONFIG_PAGING_LEVELS:%d\n", CONFIG_PAGING_LEVELS); + kdbp("__HYPERVISOR_COMPAT_VIRT_START: %lx\n", + (ulong)__HYPERVISOR_COMPAT_VIRT_START); + kdbp("&MPT[0] == %016lx\n", &machine_to_phys_mapping[0]); + + kdbp("\nFIRST_RESERVED_GDT_PAGE: %x\n", FIRST_RESERVED_GDT_PAGE); + kdbp("FIRST_RESERVED_GDT_ENTRY: %lx\n", (ulong)FIRST_RESERVED_GDT_ENTRY); + kdbp("LAST_RESERVED_GDT_ENTRY: %lx\n", (ulong)LAST_RESERVED_GDT_ENTRY); + kdbp(" Per cpu non-compat gdt_table:\n"); + for_each_online_cpu(cpu) { + kdbp("\tcpu:%d gdt_table:%p\n", cpu, per_cpu(gdt_table, cpu)); + } + kdbp(" Per cpu compat gdt_table:\n"); + for_each_online_cpu(cpu) { + kdbp("\tcpu:%d gdt_table:%p\n", cpu, per_cpu(compat_gdt_table, cpu)); + } + kdbp("\n"); + kdbp(" Per cpu tss:\n"); + for_each_online_cpu(cpu) { + struct tss_struct *tssp = &per_cpu(init_tss, cpu); + kdbp("\tcpu:%d tss:%p (rsp0:%016lx)\n", cpu, tssp, tssp->rsp0); + } +#ifdef USER_MAPPINGS_ARE_GLOBAL + kdbp("USER_MAPPINGS_ARE_GLOBAL is defined\n"); +#else + kdbp("USER_MAPPINGS_ARE_GLOBAL is NOT defined\n"); +#endif + kdbp("\n"); + return KDB_CPU_MAIN_KDB; +} + +/* for HVM/PVH guests, go thru EPT. For PV guest we need to go to the btree. + * btree: pfn_to_mfn_frame_list_list is root that points (has mfns of) upto 16 + * pages (call 'em l2 nodes) that contain mfns of guest p2m table pages + * NOTE: num of entries in a p2m page is same as num of entries in l2 node */ +static noinline ulong +kdb_gpfn2mfn(struct domain *dp, ulong gpfn, p2m_type_t *typep) +{ + int idx; + + if ( !paging_mode_translate(dp) ) { + unsigned long *mfn_va, mfn = arch_get_pfn_to_mfn_frame_list_list(dp); + int g_longsz = kdb_guest_bitness(dp->domain_id)/8; + int entries_per_pg = PAGE_SIZE/g_longsz; + const int shift = get_count_order(entries_per_pg); + + if ( !mfn_valid(mfn) ) { + kdbp("Invalid frame_list_list mfn:%lx for non-xlate guest\n", mfn); + return INVALID_MFN; + } + + mfn_va = map_domain_page(mfn); + idx = gpfn >> 2*shift; /* index in root page/node */ + if (idx > 15) { + kdbp("gpfn:%lx idx:%x not in frame list limit of z16\n", gpfn, idx); + unmap_domain_page(mfn_va); + return INVALID_MFN; + } + mfn = (g_longsz == 4) ? ((int *)mfn_va)[idx] : mfn_va[idx]; + if (mfn==0) { + kdbp("No mfn for idx:%d for gpfn:%lx in root pg\n", idx, gpfn); + unmap_domain_page(mfn_va); + return INVALID_MFN; + } + mfn_va = map_domain_page(mfn); + KDBGP1("p2m: idx:%x fll:%lx mfn of 2nd lvl page:%lx\n", idx, + arch_get_pfn_to_mfn_frame_list_list(dp), mfn); + + idx = (gpfn>>shift) & ((1< 1 && kdb_str2ulong(argv[1], &mfn)) + if (mfn_valid(mfn)) + kdbp("mpt[%x] == %lx\n", mfn, machine_to_phys_mapping[mfn]); + else + kdbp("Invalid mfn:%lx\n", mfn); + else + kdb_usgf_m2p(); + return KDB_CPU_MAIN_KDB; +} + +static void +kdb_pr_pg_pgt_flds(unsigned long type_info) +{ + switch (type_info & PGT_type_mask) { + case (PGT_l1_page_table): + kdbp(" page is PGT_l1_page_table\n"); + break; + case PGT_l2_page_table: + kdbp(" page is PGT_l2_page_table\n"); + break; + case PGT_l3_page_table: + kdbp(" page is PGT_l3_page_table\n"); + break; + case PGT_l4_page_table: + kdbp(" page is PGT_l4_page_table\n"); + break; + case PGT_seg_desc_page: + kdbp(" page is seg desc page\n"); + break; + case PGT_writable_page: + kdbp(" page is writable page\n"); + break; + case PGT_shared_page: + kdbp(" page is shared page\n"); + break; + } + if (type_info & PGT_pinned) + kdbp(" page is pinned\n"); + if (type_info & PGT_validated) + kdbp(" page is validated\n"); + if (type_info & PGT_pae_xen_l2) + kdbp(" page is PGT_pae_xen_l2\n"); + if (type_info & PGT_partial) + kdbp(" page is PGT_partial\n"); + if (type_info & PGT_locked) + kdbp(" page is PGT_locked\n"); +} + +static void +kdb_pr_pg_pgc_flds(unsigned long count_info) +{ + if (count_info & PGC_allocated) + kdbp(" PGC_allocated"); + if (count_info & PGC_xen_heap) + kdbp(" PGC_xen_heap"); + if (count_info & PGC_page_table) + kdbp(" PGC_page_table"); + if (count_info & PGC_broken) + kdbp(" PGC_broken"); +#if XEN_VERSION < 4 /* xen 3.x.x */ + if (count_info & PGC_offlining) + kdbp(" PGC_offlining"); + if (count_info & PGC_offlined) + kdbp(" PGC_offlined"); +#else + if (count_info & PGC_state_inuse) + kdbp(" PGC_inuse"); + if (count_info & PGC_state_offlining) + kdbp(" PGC_state_offlining"); + if (count_info & PGC_state_offlined) + kdbp(" PGC_state_offlined"); + if (count_info & PGC_state_free) + kdbp(" PGC_state_free"); +#endif + kdbp("\n"); +} + +/* print struct page_info{} given ptr to it or an mfn + * NOTE: that given an mfn there seems no way of knowing how it's used, so + * here we just print all info and let user decide what's applicable */ +static kdb_cpu_cmd_t +kdb_usgf_dpage(void) +{ + kdbp("dpage mfn|page-ptr : Display struct page\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dpage(int argc, const char **argv, struct cpu_user_regs *regs) +{ + unsigned long val; + struct page_info *pgp; + struct domain *dp; + + if (argc <= 1 || *argv[1] == '?') + return kdb_usgf_dpage(); + + if ((kdb_str2ulong(argv[1], &val) == 0) || + (val < (ulong)frame_table && !mfn_valid(val))) { + + kdbp("Invalid arg:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + kdbp("Page Info:\n"); + if (val <= (ulong)frame_table) { /* arg is mfn */ + pgp = mfn_to_page(val); + kdbp(" mfn: %lx page_info:%p\n", val, pgp); + } else { + pgp = (struct page_info *)val; /* arg is struct page{} */ + if (pgp < frame_table || pgp >= frame_table+max_page) { + kdbp("Invalid page ptr. below/beyond max_page\n"); + return KDB_CPU_MAIN_KDB; + } + kdbp(" mfn: %lx page_info:%p\n", page_to_mfn(pgp), pgp); + } + kdbp(" count_info: %016lx (refcnt: %x)\n", pgp->count_info, + pgp->count_info & PGC_count_mask); +#if XEN_VERSION > 3 || XEN_SUBVERSION > 3 /* xen 3.4.x or later */ + kdb_pr_pg_pgc_flds(pgp->count_info); + + kdbp("In use info:\n"); + kdbp(" type_info:%016lx\n", pgp->u.inuse.type_info); + kdb_pr_pg_pgt_flds(pgp->u.inuse.type_info); + dp = page_get_owner(pgp); + kdbp(" domid:%d (pickled:%lx)\n", dp ? dp->domain_id : -1, + pgp->v.inuse._domain); + + kdbp("Shadow Info:\n"); + kdbp(" type:%x pinned:%x count:%x\n", pgp->u.sh.type, pgp->u.sh.pinned, + pgp->u.sh.count); + kdbp(" back:%lx shadow_flags:%x next_shadow:%lx\n", pgp->v.sh.back, + pgp->shadow_flags, pgp->next_shadow); + + kdbp("Free Info\n"); + kdbp(" need_tlbflush:%d order:%d tlbflush_timestamp:%x\n", + pgp->u.free.need_tlbflush, pgp->v.free.order, + pgp->tlbflush_timestamp); +#else + if (pgp->count_info & PGC_allocated) /* page allocated */ + kdbp(" PGC_allocated"); + if (pgp->count_info & PGC_page_table) /* page table page */ + kdbp(" PGC_page_table"); + kdbp("\n"); + kdbp(" page is %s xen heap page\n", is_xen_heap_page(pgp) ? "a":"NOT"); + kdbp(" cacheattr:%x\n", (pgp->count_info>>PGC_cacheattr_base) & 7); + if (pgp->count_info & PGC_count_mask) { /* page in use */ + dp = pgp->u.inuse._domain; /* pickled domain */ + kdbp(" page is in use\n"); + kdbp(" domid: %d (pickled dom:%x)\n", + dp ? (unpickle_domptr(dp))->domain_id : -1, dp); + kdbp(" type_info: %lx\n", pgp->u.inuse.type_info); + kdb_prt_pg_type(pgp->u.inuse.type_info); + } else { /* page is free */ + kdbp(" page is free\n"); + kdbp(" order: %x\n", pgp->u.free.order); + kdbp(" cpumask: %lx\n", pgp->u.free.cpumask.bits); + } + kdbp(" tlbflush/shadow_flags: %lx\n", pgp->shadow_flags); +#endif + return KDB_CPU_MAIN_KDB; +} + +/* display asked msr value */ +static kdb_cpu_cmd_t +kdb_usgf_dmsr(void) +{ + kdbp("dmsr address : Display msr value\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_dmsr(int argc, const char **argv, struct cpu_user_regs *regs) +{ + unsigned long addr, val; + + if (argc <= 1 || *argv[1] == '?') + return kdb_usgf_dmsr(); + + if ((kdb_str2ulong(argv[1], &addr) == 0)) { + kdbp("Invalid arg:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } + rdmsrl(addr, val); + kdbp("msr: %lx val:%lx\n", addr, val); + + return KDB_CPU_MAIN_KDB; +} + +/* execute cpuid for given value */ +static kdb_cpu_cmd_t +kdb_usgf_cpuid(void) +{ + kdbp("cpuid eax : Display cpuid value returned in rax\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_cpuid(int argc, const char **argv, struct cpu_user_regs *regs) +{ + unsigned long rax=0, rbx=0, rcx=0, rdx=0; + + if (argc <= 1 || *argv[1] == '?') + return kdb_usgf_cpuid(); + + if ((kdb_str2ulong(argv[1], &rax) == 0)) { + kdbp("Invalid arg:%s\n", argv[1]); + return KDB_CPU_MAIN_KDB; + } +#if 0 + __asm__ __volatile__ ( + /* "pushl %%rax \n" */ + + "movl %0, %%rax \n" + "cpuid \n" + : "=&a" (rax), "=b" (rbx), "=c" (rcx), "=d" (rdx) + : "0" (rax) + : "rax", "rbx", "rcx", "rdx", "memory"); +#endif + cpuid(rax, &rax, &rbx, &rcx, &rdx); + kdbp("rax: %016lx rbx:%016lx rcx:%016lx rdx:%016lx\n", rax, rbx, + rcx, rdx); + return KDB_CPU_MAIN_KDB; +} + +/* execute cpuid for given value */ +static kdb_cpu_cmd_t +kdb_usgf_wept(void) +{ + kdbp("wept domid gfn: walk ept table for given domid and gfn\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_wept(int argc, const char **argv, struct cpu_user_regs *regs) +{ + struct domain *dp; + ulong gfn; + + if ((argc > 1 && *argv[1] == '?') || argc != 3) + return kdb_usgf_wept(); + if ((dp=kdb_strdomid2ptr(argv[1], 1)) && kdb_str2ulong(argv[2], &gfn)) + ept_walk_table(dp, gfn); + else + kdb_usgf_wept(); + + return KDB_CPU_MAIN_KDB; +} + +/* + * Save symbols info for a guest, dom0 or other... + */ +static kdb_cpu_cmd_t +kdb_usgf_sym(void) +{ + kdbp("sym domid &kallsyms_names &kallsyms_addresses &kallsyms_num_syms\n"); + kdbp("\t [&kallsyms_token_table] [&kallsyms_token_index]\n"); + kdbp("\ttoken _table and _index MUST be specified for el5\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_sym(int argc, const char **argv, struct cpu_user_regs *regs) +{ + ulong namesp, addrap, nump, toktblp, tokidxp; + domid_t domid; + + if (argc < 5) { + return kdb_usgf_sym(); + } + toktblp = tokidxp = 0; /* optional parameters */ + if (kdb_str2domid(argv[1], &domid, 1) && + kdb_str2ulong(argv[2], &namesp) && + kdb_str2ulong(argv[3], &addrap) && + kdb_str2ulong(argv[4], &nump) && + (argc==5 || (argc==7 && kdb_str2ulong(argv[5], &toktblp) && + kdb_str2ulong(argv[6], &tokidxp)))) { + + kdb_sav_dom_syminfo(domid, namesp, addrap,nump,toktblp,tokidxp); + } else + kdb_usgf_sym(); + return KDB_CPU_MAIN_KDB; +} + + +/* mods is the dumb ass &modules. modules is struct {nxt, prev}, and not ptr */ +static void +kdb_dump_linux_modules(domid_t domid, ulong mods, uint nxtoffs, uint nmoffs, + uint coreoffs) +{ + const int bufsz = 56; + char buf[bufsz]; + uint64_t addr, addrval, *nxtptr, *modptr; + uint i, num = 8; + + if (kdb_guest_bitness(domid) == 32) + num = 4; + + /* first read modules{}.next ptr */ + if (kdb_read_mem(mods, (kdbbyt_t *)&nxtptr, num, domid) != num) { + kdbp("ERROR: Could not read next at mod:%p\n", (void *)mods); + return; + } + + KDBGP("mods:%p nxtptr:%p nmoffs:%x coreoffs:%x\n", (void *)mods, nxtptr, + nmoffs, coreoffs); + + while ((uint64_t)nxtptr != mods) { + + modptr = (uint64_t *) ((ulong)nxtptr - nxtoffs); + + addr = (ulong)modptr + coreoffs; + if (kdb_read_mem(addr, (kdbbyt_t *)&addrval, num, domid) != num) { + kdbp("ERROR: Could not read mod addr at :%p\n", (void *)addr); + return; + } + + KDBGP("modptr:%p addr:%p\n", modptr, (void *)addr); + addr = (ulong)modptr + nmoffs; + i=0; + do { + if (kdb_read_mem(addr, (kdbbyt_t *)&buf[i], 1, domid) != 1) { + kdbp("ERROR:Could not read name ch at addr:%p\n", (void *)addr); + return; + } + addr++; + } while (buf[i] && i++ < bufsz); + buf[bufsz-1] = '\0'; + + kdbp("%016lx %016lx %s\n", modptr, addrval, buf); + + if (kdb_read_mem((ulong)nxtptr, (kdbbyt_t *)&nxtptr, num, domid)!=num) { + kdbp("ERROR: Could not read next at mod:%p\n", (void *)mods); + return; + } + KDBGP("nxtptr:%p addr:%p\n", nxtptr, (void *)addr); + } +} + +/* Display modules loaded in linux guest */ +static kdb_cpu_cmd_t +kdb_usgf_mod(void) +{ + kdbp("mod domid &modules next-offs name-offs module_core-offs\n"); + kdbp("\twhere next-offs: &((struct module *)0)->list.next\n"); + kdbp("\tname-offs: &((struct module *)0)->name etc..\n"); + kdbp("\tDisplays all loaded modules in the linux guest\n"); + kdbp("\tEg: mod 0 ffffffff80302780 8 0x18 0x178\n"); + + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_cmdf_mod(int argc, const char **argv, struct cpu_user_regs *regs) +{ + ulong mods, nxtoffs, nmoffs, coreoffs; + domid_t domid; + + if (argc < 6) { + return kdb_usgf_mod(); + } + if (kdb_str2domid(argv[1], &domid, 1) && + kdb_str2ulong(argv[2], &mods) && + kdb_str2ulong(argv[3], &nxtoffs) && + kdb_str2ulong(argv[4], &nmoffs) && + kdb_str2ulong(argv[5], &coreoffs)) { + + kdbp("modptr address name\n"); + kdb_dump_linux_modules(domid, mods, nxtoffs, nmoffs, coreoffs); + } else + kdb_usgf_mod(); + return KDB_CPU_MAIN_KDB; +} + +/* toggle kdb debug trace level */ +static kdb_cpu_cmd_t +kdb_usgf_kdbdbg(void) +{ + kdbp("kdbdbg : trace info to debug kdb\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_kdbdbg(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_kdbdbg(); + + kdbdbg = (kdbdbg==3) ? 0 : (kdbdbg+1); + kdbp("kdbdbg set to:%d\n", kdbdbg); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_reboot(void) +{ + kdbp("reboot: reboot system\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_reboot(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_reboot(); + + machine_restart(500); + return KDB_CPU_MAIN_KDB; /* not reached */ +} + + +static kdb_cpu_cmd_t +kdb_usgf_trcon(void) +{ + kdbp("trcon: turn user added kdb tracing on\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_trcon(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_trcon(); + + kdb_trcon = 1; + kdbp("kdb tracing is now on\n"); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_trcoff(void) +{ + kdbp("trcoff: turn user added kdb tracing off\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_trcoff(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_trcoff(); + + kdb_trcon = 0; + kdbp("kdb tracing is now off\n"); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_trcz(void) +{ + kdbp("trcz : zero entire trace buffer\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_trcz(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_trcz(); + + kdb_trczero(); + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_trcp(void) +{ + kdbp("trcp : give hints to dump trace buffer via dw/dd command\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_trcp(int argc, const char **argv, struct cpu_user_regs *regs) +{ + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_trcp(); + + kdb_trcp(); + return KDB_CPU_MAIN_KDB; +} + +/* print some basic info, constants, etc.. */ +static kdb_cpu_cmd_t +kdb_usgf_info(void) +{ + kdbp("info : display basic info, constants, etc..\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_info(int argc, const char **argv, struct cpu_user_regs *regs) +{ + struct domain *dp; + struct cpuinfo_x86 *bcdp; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_info(); + + kdbp("Version: %d.%d.%s (%s@%s) %s\n", xen_major_version(), + xen_minor_version(), xen_extra_version(), xen_compile_by(), + xen_compile_domain(), xen_compile_date()); + kdbp("__XEN_LATEST_INTERFACE_VERSION__ : 0x%x\n", + __XEN_LATEST_INTERFACE_VERSION__); + kdbp("__XEN_INTERFACE_VERSION__: 0x%x\n", __XEN_INTERFACE_VERSION__); + + bcdp = &boot_cpu_data; + kdbp("CPU: (all decimal)"); + if (bcdp->x86_vendor == X86_VENDOR_AMD) + kdbp(" AMD"); + else + kdbp(" INTEL"); + kdbp(" family:%d model:%d\n", bcdp->x86, bcdp->x86_model); + kdbp(" vendor_id:%16s model_id:%64s\n", bcdp->x86_vendor_id, + bcdp->x86_model_id); + kdbp(" cpuidlvl:%d cache:sz:%d align:%d\n", bcdp->cpuid_level, + bcdp->x86_cache_size, bcdp->x86_cache_alignment); + kdbp(" power:%d cores: max:%d booted:%d siblings:%d apicid:%d\n", + bcdp->x86_power, bcdp->x86_max_cores, bcdp->booted_cores, + bcdp->x86_num_siblings, bcdp->apicid); + kdbp(" "); + if (cpu_has_apic) + kdbp("_apic"); + if (cpu_has_sep) + kdbp("|_sep"); + if (cpu_has_xmm3) + kdbp("|_xmm3"); + if (cpu_has_ht) + kdbp("|_ht"); + if (cpu_has_nx) + kdbp("|_nx"); + if (cpu_has_clflush) + kdbp("|_clflush"); + if (cpu_has_page1gb) + kdbp("|_page1gb"); + if (cpu_has_ffxsr) + kdbp("|_ffxsr"); + if (cpu_has_x2apic) + kdbp("|_x2apic"); + kdbp("\n\n"); + kdbp("CC:"); +#if defined(CONFIG_X86_64) + kdbp(" CONFIG_X86_64"); +#endif +#if defined(CONFIG_COMPAT) + kdbp(" CONFIG_COMPAT"); +#endif +#if defined(CONFIG_PAGING_ASSISTANCE) + kdbp(" CONFIG_PAGING_ASSISTANCE"); +#endif + kdbp("\n"); + kdbp("cpu has following features:\n"); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_TSC_RELIABLE) ? + "X86_FEATURE_TSC_RELIABLE" : ""); + kdbp(" %s\n", + boot_cpu_has(X86_FEATURE_CONSTANT_TSC)? "X86_FEATURE_CONSTANT_TSC":""); + kdbp(" %s\n", + boot_cpu_has(X86_FEATURE_NONSTOP_TSC) ? "X86_FEATURE_NONSTOP_TSC" :""); + kdbp(" %s\n", + boot_cpu_has(X86_FEATURE_RDTSCP) ? "X86_FEATURE_RDTSCP" : ""); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_FXSR) ? "X86_FEATURE_FXSR" : ""); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_CPUID_FAULTING) ? + "X86_FEATURE_CPUID_FAULTING" : ""); + kdbp(" %s\n", + boot_cpu_has(X86_FEATURE_PAGE1GB) ? "X86_FEATURE_PAGE1GB" : ""); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_MWAIT) ? "X86_FEATURE_MWAIT" : ""); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_X2APIC) ? "X86_FEATURE_X2APIC":""); + kdbp(" %s\n", boot_cpu_has(X86_FEATURE_XSAVE) ? "X86_FEATURE_XSAVE":""); + kdbp("\n"); + + kdbp("MAX_VIRT_CPUS:$%d MAX_HVM_VCPUS:$%d\n", MAX_VIRT_CPUS,MAX_HVM_VCPUS); + kdbp("MAX_NR_EVTCHNS: $%d\n", MAX_NR_EVTCHNS); + kdbp("NR_EVTCHN_GROUPS: $%d\n", NR_EVTCHN_GROUPS); + + kdbp("\nDomains and their vcpus:\n"); + for_each_domain(dp) { + struct vcpu *vp; + int printed=0; + kdbp(" Domain: {id:%d 0x%x ptr:%p%s} VCPUs:\n", + dp->domain_id, dp->domain_id, dp, dp->is_dying ? " DYING":""); + for(vp=dp->vcpu[0]; vp; vp = vp->next_in_list) { + kdbp(" {id:%d p:%p runstate:%d}", vp->vcpu_id, vp, + vp->runstate.state); + if (++printed % 2 == 0) kdbp("\n"); + } + kdbp("\n"); + } + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_cur(void) +{ + kdbp("cur : display current domid and vcpu\n"); + return KDB_CPU_MAIN_KDB; +} + +/* Checking for guest_mode() not feasible here. if dom0->hcall->bp in xen, + * then g_m() will show xen, but vcpu is still dom0. hence just look at + * current only */ +static kdb_cpu_cmd_t +kdb_cmdf_cur(int argc, const char **argv, struct cpu_user_regs *regs) +{ + domid_t id = current->domain->domain_id; + + if (argc > 1 && *argv[1] == '?') + return kdb_usgf_cur(); + + kdbp("domid: %d{%p} %s vcpu:%d {%p} ", id, current->domain, + (id==DOMID_IDLE) ? "(IDLE)" : "", current->vcpu_id, current); + + /* if (id != DOMID_IDLE) { */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { + u64 addr = -1; + __vmptrst(&addr); + kdbp(" VMCS:"KDBFL, addr); + } + /* } */ + kdbp("\n"); + return KDB_CPU_MAIN_KDB; +} + +/* stub to quickly and easily add a new command */ +static kdb_cpu_cmd_t +kdb_usgf_usr1(void) +{ + kdbp("usr1: add any arbitrary cmd using this in kdb_cmds.c\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_usr1(int argc, const char **argv, struct cpu_user_regs *regs) +{ + return KDB_CPU_MAIN_KDB; +} + +static kdb_cpu_cmd_t +kdb_usgf_h(void) +{ + kdbp("h: display all commands. See kdb/README for more info\n"); + return KDB_CPU_MAIN_KDB; +} +static kdb_cpu_cmd_t +kdb_cmdf_h(int argc, const char **argv, struct cpu_user_regs *regs) +{ + kdbtab_t *tbp; + + kdbp(" - ccpu is current cpu \n"); + kdbp(" - following are always in decimal:\n"); + kdbp(" vcpu num, cpu num, domid\n"); + kdbp(" - otherwise, almost all numbers are in hex (0x not needed)\n"); + kdbp(" - output: $17 means decimal 17\n"); + kdbp(" - domid 7fff($32767) refers to hypervisor\n"); + kdbp(" - if no domid before function name, then it's hypervisor\n"); + kdbp(" - earlykdb in xen grub line to break into kdb during boot\n"); + kdbp(" - command ? will show the command usage\n"); + kdbp("\n"); + + for(tbp=kdb_cmd_tbl; tbp->kdb_cmd_usgf; tbp++) + (*tbp->kdb_cmd_usgf)(); + return KDB_CPU_MAIN_KDB; +} + +/* ===================== cmd table initialization ========================== */ +void __init +kdb_init_cmdtab(void) +{ + static kdbtab_t _kdb_cmd_table[] = { + + {"info", kdb_cmdf_info, kdb_usgf_info, 1, KDB_REPEAT_NONE}, + {"cur", kdb_cmdf_cur, kdb_usgf_cur, 1, KDB_REPEAT_NONE}, + + {"f", kdb_cmdf_f, kdb_usgf_f, 1, KDB_REPEAT_NONE}, + {"fg", kdb_cmdf_fg, kdb_usgf_fg, 1, KDB_REPEAT_NONE}, + + {"dw", kdb_cmdf_dw, kdb_usgf_dw, 1, KDB_REPEAT_NO_ARGS}, + {"dd", kdb_cmdf_dd, kdb_usgf_dd, 1, KDB_REPEAT_NO_ARGS}, + {"dwm", kdb_cmdf_dwm, kdb_usgf_dwm, 1, KDB_REPEAT_NO_ARGS}, + {"ddm", kdb_cmdf_ddm, kdb_usgf_ddm, 1, KDB_REPEAT_NO_ARGS}, + {"dr", kdb_cmdf_dr, kdb_usgf_dr, 1, KDB_REPEAT_NONE}, + {"drg", kdb_cmdf_drg, kdb_usgf_drg, 1, KDB_REPEAT_NONE}, + + {"dis", kdb_cmdf_dis, kdb_usgf_dis, 1, KDB_REPEAT_NO_ARGS}, + {"dism",kdb_cmdf_dism, kdb_usgf_dism, 1, KDB_REPEAT_NO_ARGS}, + + {"mw", kdb_cmdf_mw, kdb_usgf_mw, 1, KDB_REPEAT_NONE}, + {"md", kdb_cmdf_md, kdb_usgf_md, 1, KDB_REPEAT_NONE}, + {"mr", kdb_cmdf_mr, kdb_usgf_mr, 1, KDB_REPEAT_NONE}, + + {"bc", kdb_cmdf_bc, kdb_usgf_bc, 0, KDB_REPEAT_NONE}, + {"bp", kdb_cmdf_bp, kdb_usgf_bp, 1, KDB_REPEAT_NONE}, + {"btp", kdb_cmdf_btp, kdb_usgf_btp, 1, KDB_REPEAT_NONE}, + + {"wp", kdb_cmdf_wp, kdb_usgf_wp, 1, KDB_REPEAT_NONE}, + {"wc", kdb_cmdf_wc, kdb_usgf_wc, 0, KDB_REPEAT_NONE}, + + {"ni", kdb_cmdf_ni, kdb_usgf_ni, 0, KDB_REPEAT_NO_ARGS}, + {"ss", kdb_cmdf_ss, kdb_usgf_ss, 1, KDB_REPEAT_NO_ARGS}, + {"ssb",kdb_cmdf_ssb,kdb_usgf_ssb,0, KDB_REPEAT_NO_ARGS}, + {"go", kdb_cmdf_go, kdb_usgf_go, 0, KDB_REPEAT_NONE}, + + {"cpu",kdb_cmdf_cpu, kdb_usgf_cpu, 1, KDB_REPEAT_NONE}, + {"nmi",kdb_cmdf_nmi, kdb_usgf_nmi, 1, KDB_REPEAT_NONE}, + {"percpu",kdb_cmdf_percpu, kdb_usgf_percpu, 1, KDB_REPEAT_NONE}, + + {"sym", kdb_cmdf_sym, kdb_usgf_sym, 1, KDB_REPEAT_NONE}, + {"mod", kdb_cmdf_mod, kdb_usgf_mod, 1, KDB_REPEAT_NONE}, + + {"vcpuh",kdb_cmdf_vcpuh, kdb_usgf_vcpuh, 1, KDB_REPEAT_NONE}, + {"vcpu", kdb_cmdf_vcpu, kdb_usgf_vcpu, 1, KDB_REPEAT_NONE}, + {"dom", kdb_cmdf_dom, kdb_usgf_dom, 1, KDB_REPEAT_NONE}, + + {"sched", kdb_cmdf_sched, kdb_usgf_sched, 1, KDB_REPEAT_NONE}, + {"mmu", kdb_cmdf_mmu, kdb_usgf_mmu, 1, KDB_REPEAT_NONE}, + {"p2m", kdb_cmdf_p2m, kdb_usgf_p2m, 1, KDB_REPEAT_NONE}, + {"m2p", kdb_cmdf_m2p, kdb_usgf_m2p, 1, KDB_REPEAT_NONE}, + {"dpage", kdb_cmdf_dpage, kdb_usgf_dpage, 1, KDB_REPEAT_NONE}, + {"dmsr", kdb_cmdf_dmsr, kdb_usgf_dmsr, 1, KDB_REPEAT_NONE}, + {"cpuid", kdb_cmdf_cpuid, kdb_usgf_cpuid, 1, KDB_REPEAT_NONE}, + {"wept", kdb_cmdf_wept, kdb_usgf_wept, 1, KDB_REPEAT_NONE}, + + {"dtrq", kdb_cmdf_dtrq, kdb_usgf_dtrq, 1, KDB_REPEAT_NONE}, + {"didt", kdb_cmdf_didt, kdb_usgf_didt, 1, KDB_REPEAT_NONE}, + {"dgdt", kdb_cmdf_dgdt, kdb_usgf_dgdt, 1, KDB_REPEAT_NONE}, + {"dirq", kdb_cmdf_dirq, kdb_usgf_dirq, 1, KDB_REPEAT_NONE}, + {"dvit", kdb_cmdf_dvit, kdb_usgf_dvit, 1, KDB_REPEAT_NONE}, + {"dvmc", kdb_cmdf_dvmc, kdb_usgf_dvmc, 1, KDB_REPEAT_NONE}, + {"mmio", kdb_cmdf_mmio, kdb_usgf_mmio, 1, KDB_REPEAT_NONE}, + + /* tracing related commands */ + {"trcon", kdb_cmdf_trcon, kdb_usgf_trcon, 0, KDB_REPEAT_NONE}, + {"trcoff",kdb_cmdf_trcoff, kdb_usgf_trcoff, 0, KDB_REPEAT_NONE}, + {"trcz", kdb_cmdf_trcz, kdb_usgf_trcz, 0, KDB_REPEAT_NONE}, + {"trcp", kdb_cmdf_trcp, kdb_usgf_trcp, 1, KDB_REPEAT_NONE}, + + {"usr1", kdb_cmdf_usr1, kdb_usgf_usr1, 1, KDB_REPEAT_NONE}, + {"kdbf", kdb_cmdf_kdbf, kdb_usgf_kdbf, 1, KDB_REPEAT_NONE}, + {"kdbdbg",kdb_cmdf_kdbdbg, kdb_usgf_kdbdbg, 1, KDB_REPEAT_NONE}, + {"reboot",kdb_cmdf_reboot, kdb_usgf_reboot, 1, KDB_REPEAT_NONE}, + {"h", kdb_cmdf_h, kdb_usgf_h, 1, KDB_REPEAT_NONE}, + + {"", NULL, NULL, 0, 0}, + }; + kdb_cmd_tbl = _kdb_cmd_table; + return; +} diff --git a/xen/kdb/kdb_io.c b/xen/kdb/kdb_io.c new file mode 100644 index 0000000..b7465a1 --- /dev/null +++ b/xen/kdb/kdb_io.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ +#include "include/kdbinc.h" + +#define K_BACKSPACE 0x8 /* ctrl-H */ +#define K_BACKSPACE1 0x7f /* ctrl-? */ +#define K_UNDERSCORE 0x5f +#define K_CMD_BUFSZ 160 +#define K_CMD_MAXI (K_CMD_BUFSZ - 1) /* max index in buffer */ + +#if 0 /* make a history array some day */ +#define K_UP_ARROW /* sequence : 1b 5b 41 ie, '\e[A' */ +#define K_DN_ARROW /* sequence : 1b 5b 42 ie, '\e[B' */ +#define K_NUM_HIST 32 +static int cursor; +static char cmds_a[NUM_HIST][K_CMD_BUFSZ]; +#endif + +static char cmds_a[K_CMD_BUFSZ]; + + +static int +kdb_key_valid(int key) +{ + /* note: isspace() is more than ' ', hence we don't use it here */ + if (isalnum(key) || key == ' ' || key == K_BACKSPACE || key == '\n' || + key == '?' || key == K_UNDERSCORE || key == '=' || key == '!') + return 1; + return 0; +} + +/* display kdb prompt and read command from the console + * RETURNS: a '\n' terminated command buffer */ +char * +kdb_get_cmdline(char *prompt) +{ + #define K_BELL 0x7 + #define K_CTRL_C 0x3 + + int key, i=0; + + kdbp(prompt); + memset(cmds_a, 0, K_CMD_BUFSZ); + cmds_a[K_CMD_BUFSZ-1] = '\n'; + + do { + key = console_getc(); + if (key == '\r') + key = '\n'; + if (key == K_BACKSPACE1) + key = K_BACKSPACE; + + if (key == K_CTRL_C || (i==K_CMD_MAXI && key != '\n')) { + console_putc('\n'); + if (i >= K_CMD_MAXI) { + kdbp("KDB: cmd buffer overflow\n"); + console_putc(K_BELL); + } + memset(cmds_a, 0, K_CMD_BUFSZ); + i = 0; + kdbp(prompt); + continue; + } + if (!kdb_key_valid(key)) { + console_putc(K_BELL); + continue; + } + if (key == K_BACKSPACE) { + if (i==0) { + console_putc(K_BELL); + continue; + } else + cmds_a[--i] = '\0'; + console_putc(K_BACKSPACE); + console_putc(' '); /* erase character */ + } else + cmds_a[i++] = key; + + console_putc(key); + + } while (key != '\n'); + + return cmds_a; +} + +/* + * printk takes a lock, an NMI could come in after that, and another cpu may + * spin. also, the console lock is forced unlock, so panic is been seen on + * 8 way. hence, no printk() calls. + */ +static volatile int kdbp_gate = 0; +void +kdbp(const char *fmt, ...) +{ + static char buf[1024]; + va_list args; + char *p; + int i=0; + + while ((__cmpxchg(&kdbp_gate, 0,1, sizeof(kdbp_gate)) != 0) && i++<1000) + mdelay(10); + + va_start(args, fmt); + (void)vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for (p=buf; *p != '\0'; p++) + console_putc(*p); + kdbp_gate = 0; +} + + +/* + * copy/read machine memory. + * RETURNS: number of bytes copied + */ +int +kdb_read_mmem(kdbma_t maddr, kdbbyt_t *dbuf, int len) +{ + ulong remain, orig=len; + + while (len > 0) { + ulong pagecnt = min_t(long, PAGE_SIZE-(maddr&~PAGE_MASK), len); + char *va = map_domain_page(maddr >> PAGE_SHIFT); + + va = va + (maddr & (PAGE_SIZE-1)); /* add page offset */ + remain = __copy_from_user(dbuf, (void *)va, pagecnt); + KDBGP1("maddr:%x va:%p len:%x pagecnt:%x rem:%x\n", + maddr, va, len, pagecnt, remain); + unmap_domain_page(va); + len = len - (pagecnt - remain); + if (remain != 0) + break; + maddr += pagecnt; + dbuf += pagecnt; + } + return orig - len; +} + + +/* + * copy/read guest or hypervisor memory. (domid == DOMID_IDLE) => hyp + * RETURNS: number of bytes copied + */ +int +kdb_read_mem(kdbva_t saddr, kdbbyt_t *dbuf, int len, domid_t domid) +{ + return (len - dbg_rw_mem(saddr, dbuf, len, domid, 0, 0)); +} + +/* + * write guest or hypervisor memory. (domid == DOMID_IDLE) => hyp + * RETURNS: number of bytes written + */ +int +kdb_write_mem(kdbva_t daddr, kdbbyt_t *sbuf, int len, domid_t domid) +{ + return (len - dbg_rw_mem(daddr, sbuf, len, domid, 1, 0)); +} diff --git a/xen/kdb/kdbmain.c b/xen/kdb/kdbmain.c new file mode 100644 index 0000000..d60c365 --- /dev/null +++ b/xen/kdb/kdbmain.c @@ -0,0 +1,746 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "include/kdbinc.h" + +static int kdbmain(kdb_reason_t, struct cpu_user_regs *); +static int kdbmain_fatal(struct cpu_user_regs *, int); +static const char *kdb_gettrapname(int); + +/* ======================== GLOBAL VARIABLES =============================== */ +/* All global variables used by KDB must be defined here only. Module specific + * static variables must be declared in respective modules. + */ +kdbtab_t *kdb_cmd_tbl; +char kdb_prompt[32]; + +volatile kdb_cpu_cmd_t kdb_cpu_cmd[NR_CPUS]; +cpumask_t kdb_cpu_traps; /* bit per cpu to tell which cpus hit int3 */ + +#if 0 +#ifndef NDEBUG + #error KDB is not supported on debug xen. Turn debug off +#endif +#endif + +volatile int kdb_init_cpu = -1; /* initial kdb cpu */ +volatile int kdb_session_begun = 0; /* active kdb session? */ +volatile int kdb_enabled = 1; /* kdb enabled currently? */ +volatile int kdb_sys_crash = 0; /* are we in crashed state? */ +volatile int kdbdbg = 0; /* to debug kdb itself */ + +static volatile int kdb_trap_immed_reason = 0; /* reason for immed trap */ + +static cpumask_t kdb_fatal_cpumask; /* which cpus in fatal path */ + +/* return index of first bit set in val. if val is 0, retval is undefined */ +static inline unsigned int kdb_firstbit(unsigned long val) +{ + __asm__ ( "bsf %1,%0" : "=r" (val) : "r" (val), "0" (BITS_PER_LONG) ); + return (unsigned int)val; +} + +static void +kdb_dbg_prnt_ctrps(char *label, int ccpu) +{ + int i; + if (!kdbdbg) + return; + + if (label || *label) + kdbp("%s ", label); + if (ccpu != -1) + kdbp("ccpu:%d ", ccpu); + kdbp("cputrps:"); + for (i=sizeof(kdb_cpu_traps)/sizeof(kdb_cpu_traps.bits[0]) - 1; i >=0; i--) + kdbp(" %lx", kdb_cpu_traps.bits[i]); + kdbp("\n"); +} + +/* + * Hold this cpu. Don't disable until all CPUs in kdb to avoid IPI deadlock + */ +static void +kdb_hold_this_cpu(int ccpu, struct cpu_user_regs *regs) +{ + KDBGP("ccpu:%d hold. cmd:%x\n", kdb_cpu_cmd[ccpu]); + do { + for(; kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE; cpu_relax()); + KDBGP("ccpu:%d hold. cmd:%x\n", kdb_cpu_cmd[ccpu]); + + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DISABLE) { + local_irq_disable(); + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + } + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DO_VMEXIT) { + kdb_curr_cpu_flush_vmcs(); + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + } + if (kdb_cpu_cmd[ccpu] == KDB_CPU_SHOWPC) { + kdbp("[%d]", ccpu); + kdb_display_pc(regs); + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + } + } while (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE); /* No goto, eh! */ + KDBGP1("un hold: ccpu:%d cmd:%d\n", ccpu, kdb_cpu_cmd[ccpu]); +} + +/* + * Pause this cpu while one CPU does main kdb processing. If that CPU does + * a "cpu switch" to this cpu, this cpu will become the main kdb cpu. If the + * user next does single step of some sort, this function will be exited, + * and this cpu will come back into kdb via kdb_handle_trap_entry function. + */ +static void +kdb_pause_this_cpu(struct cpu_user_regs *regs, void *unused) +{ + kdbmain(KDB_REASON_PAUSE_IPI, regs); +} + +/* pause other cpus via an IPI. Note, disabled CPUs can't receive IPIs until + * enabled */ +static void +kdb_smp_pause_cpus(void) +{ + int cpu, wait_count = 0; + int ccpu = smp_processor_id(); /* current cpu */ + cpumask_t cpumask = cpu_online_map; + + cpumask_clear_cpu(smp_processor_id(), &cpumask); + for_each_cpu(cpu, &cpumask) + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) { + kdbp("KDB: won't pause cpu:%d, cmd[cpu]=%d\n",cpu,kdb_cpu_cmd[cpu]); + cpumask_clear_cpu(cpu, &cpumask); + } + KDBGP("ccpu:%d will pause cpus. mask:0x%lx\n", ccpu, cpumask.bits[0]); +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ + on_selected_cpus(&cpumask, (void (*)(void *))kdb_pause_this_cpu, + "XENKDB", 0); +#else + on_selected_cpus(cpumask, (void (*)(void *))kdb_pause_this_cpu, + "XENKDB", 0, 0); +#endif + mdelay(300); /* wait a bit for other CPUs to stop */ + while(wait_count++ < 10) { + int bummer = 0; + for_each_cpu(cpu, &cpumask) + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) + bummer = 1; + if (!bummer) + break; + kdbp("ccpu:%d trying to stop other cpus...\n", ccpu); + mdelay(100); /* wait 100 ms */ + }; + for_each_cpu(cpu, &cpumask) /* now check who is with us */ + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) + kdbp("Bummer cpu %d not paused. ccpu:%d\n", cpu,ccpu); + else { + kdb_cpu_cmd[cpu] = KDB_CPU_DISABLE; /* tell it to disable ints */ + while (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE); + } +} + +/* + * Do once per kdb session: A kdb session lasts from + * keybord/HWBP/SWBP till KDB_CPU_INSTALL_BP is done. Within a session, + * user may do several cpu switches, single step, next instr, etc.. + * + * DO: 1. pause other cpus if they are not already. they would already be + * if we are in single step mode + * 2. watchdog_disable() + * 3. uninstall all sw breakpoints so that user doesn't see them + */ +static void +kdb_begin_session(void) +{ + if (!kdb_session_begun) { + kdb_session_begun = 1; + kdb_smp_pause_cpus(); + local_irq_disable(); + watchdog_disable(); + kdb_uninstall_all_swbp(); + } +} + +static void +kdb_smp_unpause_cpus(int ccpu) +{ + int cpu; + + int wait_count = 0; + cpumask_t cpumask = cpu_online_map; + + cpumask_clear_cpu(smp_processor_id(), &cpumask); + + KDBGP("kdb_smp_unpause_other_cpus(). ccpu:%d\n", ccpu); + for_each_cpu(cpu, &cpumask) + kdb_cpu_cmd[cpu] = KDB_CPU_QUIT; + + while(wait_count++ < 10) { + int bummer = 0; + for_each_cpu(cpu, &cpumask) + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) + bummer = 1; + if (!bummer) + break; + mdelay(90); /* wait 90 ms, 50 too short on large systems */ + }; + /* now make sure they are all in there */ + for_each_cpu(cpu, &cpumask) + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) + kdbp("KDB: cpu %d still paused (cmd==%d). ccpu:%d\n", + cpu, kdb_cpu_cmd[cpu], ccpu); +} + +/* + * End of KDB session. + * This is called at the very end. In case of multiple cpus hitting BPs + * and sitting on a trap handlers, the last cpu to exit will call this. + * - isnstall all sw breakpoints, and purge deleted ones from table. + * - clear TF here also in case go is entered on a different cpu after switch + */ +static void +kdb_end_session(int ccpu, struct cpu_user_regs *regs) +{ + ASSERT(cpumask_empty(&kdb_cpu_traps)); + ASSERT(kdb_session_begun); + kdb_install_all_swbp(); + kdb_flush_swbp_table(); + kdb_install_watchpoints(); + + regs->eflags &= ~X86_EFLAGS_TF; + kdb_cpu_cmd[ccpu] = KDB_CPU_INVAL; + kdb_time_resume(1); + kdb_session_begun = 0; /* before unpause for kdb_install_watchpoints */ + kdb_smp_unpause_cpus(ccpu); + watchdog_enable(); + KDBGP("end_session:ccpu:%d\n", ccpu); +} + +/* + * check if we entered kdb because of DB trap. If yes, then check if + * we caused it or someone else. + * RETURNS: 0 : not one of ours. hypervisor must handle it. + * 1 : #DB for delayed sw bp install. + * 2 : this cpu must stay in kdb. + */ +static noinline int +kdb_check_dbtrap(kdb_reason_t *reasp, int ss_mode, struct cpu_user_regs *regs) +{ + int rc = 2; + int ccpu = smp_processor_id(); + + /* DB excp caused by hw breakpoint or the TF flag. The TF flag is set + * by us for ss mode or to install breakpoints. In ss mode, none of the + * breakpoints are installed. Check to make sure we intended BP INSTALL + * so we don't do it on a spurious DB trap. + * check for kdb_cpu_traps here also, because each cpu sitting on a trap + * must execute the instruction without the BP before passing control + * to next cpu in kdb_cpu_traps. + */ + if (*reasp == KDB_REASON_DBEXCP && !ss_mode) { + if (kdb_cpu_cmd[ccpu] == KDB_CPU_INSTALL_BP) { + if (!cpumask_empty(&kdb_cpu_traps)) { + int a_trap_cpu = cpumask_first(&kdb_cpu_traps); + KDBGP("ccpu:%d trapcpu:%d\n", ccpu, a_trap_cpu); + kdb_cpu_cmd[a_trap_cpu] = KDB_CPU_QUIT; + *reasp = KDB_REASON_PAUSE_IPI; + regs->eflags &= ~X86_EFLAGS_TF; /* hvm: exit handler ss = 0 */ + kdb_init_cpu = -1; + } else { + kdb_end_session(ccpu, regs); + rc = 1; + } + } else if (! kdb_check_watchpoints(regs)) { + rc = 0; /* hyp must handle it */ + } + } + return rc; +} + +/* + * Misc processing on kdb entry like displaying PC, adjust IP for sw bp.... + */ +static void +kdb_main_entry_misc(kdb_reason_t reason, struct cpu_user_regs *regs, + int ccpu, int ss_mode, int enabled) +{ + if (reason == KDB_REASON_KEYBOARD) + kdbp("\nEnter kdb (cpu:%d reason:%d vcpu=%d domid:%d" + " eflg:0x%lx irqs:%d)\n", ccpu, reason, current->vcpu_id, + current->domain->domain_id, regs->eflags, enabled); + else if (ss_mode) + KDBGP1("KDBG: KDB single step mode. ccpu:%d\n", ccpu); + + if (reason == KDB_REASON_BPEXCP && !ss_mode) + kdbp("Breakpoint on cpu %d at 0x%lx\n", ccpu, regs->KDBIP); + + /* display the current PC and instruction at it */ + if (reason != KDB_REASON_PAUSE_IPI) + kdb_display_pc(regs); + console_start_sync(); +} + +/* + * The MAIN kdb function. All cpus go thru this. IRQ is enabled on entry because + * a cpu could hit a bp set in disabled code. + * IPI: Even the main cpu must enable in case another CPU is trying to IPI us. + * That way, it would IPI us, then get out and be ready for our pause IPI. + * IRQs: The reason irqs enable/disable is scattered is because on a typical + * system IPIs are constantly going on amongs CPUs in a set of any size. + * As a result, to avoid deadlock, cpus have to loop enabled, until a + * quorum is established and the session has begun. + * Step: Intel Vol3B 18.3.1.4 : An external interrupt may be serviced upon + * single step. Since, the likely ext timer_interrupt and + * apic_timer_interrupt dont' mess with time data structs, we are prob OK + * leaving enabled. + * Time: Very messy. Most platform timers are readonly, so we can't stop time + * in the debugger. We take the only resort, let the TSC and plt run as + * normal, upon leaving, "attempt" to bring everybody to current time. + * kdbcputraps: bit per cpu. each cpu sets it bit in entry.S. The bit is + * reliable because upon traps, Ints are disabled. the bit is set + * before Ints are enabled. + * + * RETURNS: 0 : kdb was called for event it was not responsible + * 1 : event owned and handled by kdb + */ +static int +kdbmain(kdb_reason_t reason, struct cpu_user_regs *regs) +{ + int ccpu = smp_processor_id(); /* current cpu */ + int rc = 1, cmd = kdb_cpu_cmd[ccpu]; + int ss_mode = (cmd == KDB_CPU_SS || cmd == KDB_CPU_NI); + int delayed_install = (kdb_cpu_cmd[ccpu] == KDB_CPU_INSTALL_BP); + int enabled = local_irq_is_enabled(); + + KDBGP("kdbmain:ccpu:%d rsn:%d eflgs:0x%lx cmd:%d initc:%d irqs:%d " + "regs:%lx IP:%lx ", ccpu, reason, regs->eflags, cmd, + kdb_init_cpu, enabled, regs, regs->KDBIP); + kdb_dbg_prnt_ctrps("", -1); + + if (!ss_mode && !delayed_install) /* initial kdb enter */ + local_irq_enable(); /* so we can receive IPI */ + + if (!ss_mode && ccpu != kdb_init_cpu && reason != KDB_REASON_PAUSE_IPI){ + int sz = sizeof(kdb_init_cpu); + while (__cmpxchg(&kdb_init_cpu, -1, ccpu, sz) != -1) + for(; kdb_init_cpu != -1; cpu_relax()); + } + if (kdb_session_begun) + local_irq_disable(); /* kdb always runs disabled */ + + if (reason == KDB_REASON_BPEXCP) { /* INT 3 */ + cpumask_clear_cpu(ccpu, &kdb_cpu_traps); /* remove ourself */ + rc = kdb_check_sw_bkpts(regs); + if (rc == 0) { /* not one of ours. leave kdb */ + kdb_init_cpu = -1; + goto out; + } else if (rc == 1) { /* one of ours but deleted */ + if (cpumask_empty(&kdb_cpu_traps)) { + kdb_end_session(ccpu,regs); + kdb_init_cpu = -1; + goto out; + } else { + /* release another trap cpu, and put ourself in a pause mode */ + int a_trap_cpu = cpumask_first(&kdb_cpu_traps); + KDBGP("ccpu:%d cmd:%d rsn:%d atrpcpu:%d initcpu:%d\n", ccpu, + kdb_cpu_cmd[ccpu], reason, a_trap_cpu, kdb_init_cpu); + kdb_cpu_cmd[a_trap_cpu] = KDB_CPU_QUIT; + reason = KDB_REASON_PAUSE_IPI; + kdb_init_cpu = -1; + } + } else if (rc == 2) { /* one of ours but condition not met */ + kdb_begin_session(); + if (guest_mode(regs) && !is_pv_vcpu(current) ) + current->arch.hvm_vcpu.single_step = 1; + else + regs->eflags |= X86_EFLAGS_TF; + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; + goto out; + } + } + + /* following will take care of KDB_CPU_INSTALL_BP, and also release + * kdb_init_cpu. it should not be done twice */ + if ((rc=kdb_check_dbtrap(&reason, ss_mode, regs)) == 0 || rc == 1) { + kdb_init_cpu = -1; /* leaving kdb */ + goto out; /* rc properly set to 0 or 1 */ + } + if (reason != KDB_REASON_PAUSE_IPI) { + kdb_cpu_cmd[ccpu] = KDB_CPU_MAIN_KDB; + } else + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB && !ss_mode) + kdb_begin_session(); + + kdb_main_entry_misc(reason, regs, ccpu, ss_mode, enabled); + /* note, one or more cpu switches may occur in between */ + while (1) { + if (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE) + kdb_hold_this_cpu(ccpu, regs); + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB) + kdb_do_cmds(regs); + + if (kdb_cpu_cmd[ccpu] == KDB_CPU_GO) { + if (ccpu != kdb_init_cpu) { + kdb_cpu_cmd[kdb_init_cpu] = KDB_CPU_GO; + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + continue; /* for the pause guy */ + } + if (!cpumask_empty(&kdb_cpu_traps)) { + /* execute current instruction without 0xcc */ + kdb_dbg_prnt_ctrps("nempty:", ccpu); + if (guest_mode(regs) && !is_pv_vcpu(current)) + current->arch.hvm_vcpu.single_step = 1; + else + regs->eflags |= X86_EFLAGS_TF; + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; + goto out; + } + } + if (kdb_cpu_cmd[ccpu] != KDB_CPU_PAUSE && + kdb_cpu_cmd[ccpu] != KDB_CPU_MAIN_KDB) + break; + } + if (kdb_cpu_cmd[ccpu] == KDB_CPU_GO) { + ASSERT(cpumask_empty(&kdb_cpu_traps)); + if (kdb_swbp_exists()) { + if (reason == KDB_REASON_BPEXCP) { + /* do delayed install */ + if (guest_mode(regs) && !is_pv_vcpu(current)) + current->arch.hvm_vcpu.single_step = 1; + else + regs->eflags |= X86_EFLAGS_TF; + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; + goto out; + } + } + kdb_end_session(ccpu, regs); + kdb_init_cpu = -1; + } +out: + if (kdb_cpu_cmd[ccpu] == KDB_CPU_QUIT) { + KDBGP("ccpu:%d _quit IP: %lx\n", ccpu, regs->KDBIP); + if (! kdb_session_begun) + kdb_install_watchpoints(); + kdb_time_resume(0); + kdb_cpu_cmd[ccpu] = KDB_CPU_INVAL; + } + + /* for ss and delayed install, TF is set. not much in EXT INT handlers*/ + if (kdb_cpu_cmd[ccpu] == KDB_CPU_NI) + kdb_time_resume(1); + if (enabled) + local_irq_enable(); + + KDBGP("kdbmain:X:ccpu:%d rc:%d cmd:%d eflg:0x%lx initc:%d sesn:%d " + "cs:%x irqs:%d ", ccpu, rc, kdb_cpu_cmd[ccpu], regs->eflags, + kdb_init_cpu, kdb_session_begun, regs->cs, local_irq_is_enabled()); + kdb_dbg_prnt_ctrps("", -1); + return (rc ? 1 : 0); +} + +/* + * kdb entry function when coming in via a keyboard + * RETURNS: 0 : kdb was called for event it was not responsible + * 1 : event owned and handled by kdb + */ +int +kdb_keyboard(struct cpu_user_regs *regs) +{ + return kdbmain(KDB_REASON_KEYBOARD, regs); +} + +#if 0 +/* + * this function called when kdb session active and user presses ctrl\ again. + * the assumption is that the user typed ni/ss cmd, and it never got back into + * kdb, or the user is impatient. Either case, we just fake it that the SS did + * finish. Since, all other kdb cpus must be holding disabled, the interrupt + * would be on the CPU that did the ss/ni cmd + */ +void +kdb_ssni_reenter(struct cpu_user_regs *regs) +{ + int ccpu = smp_processor_id(); + int ccmd = kdb_cpu_cmd[ccpu]; + + if(ccmd == KDB_CPU_SS || ccmd == KDB_CPU_INSTALL_BP) + kdbmain(KDB_REASON_DBEXCP, regs); + else + kdbmain(KDB_REASON_KEYBOARD, regs); +} +#endif + +/* + * All traps are routed thru here. We care about BP (#3) trap (INT 3) and + * the DB trap(#1) only. + * returns: 0 kdb has nothing do with this trap + * 1 kdb handled this trap + */ +int +kdb_handle_trap_entry(int vector, struct cpu_user_regs *regs) +{ + int rc = 0; + int ccpu = smp_processor_id(); + + if (vector == TRAP_int3) { + rc = kdbmain(KDB_REASON_BPEXCP, regs); + + } else if (vector == TRAP_debug) { + KDBGP("ccpu:%d trapdbg reas:%d\n", ccpu, kdb_trap_immed_reason); + + if (kdb_trap_immed_reason == KDB_TRAP_FATAL) { + KDBGP("kdbtrp:fatal ccpu:%d vec:%d\n", ccpu, vector); + rc = kdbmain_fatal(regs, vector); + BUG(); /* no return */ + + } else if (kdb_trap_immed_reason == KDB_TRAP_KDBSTACK) { + kdb_trap_immed_reason = 0; /* show kdb stack */ + show_registers(regs); + show_stack(regs); + regs->eflags &= ~X86_EFLAGS_TF; + rc = 1; + + } else if (kdb_trap_immed_reason == KDB_TRAP_NONFATAL) { + kdb_trap_immed_reason = 0; + rc = kdb_keyboard(regs); + } else { /* ss/ni/delayed install... */ + if (guest_mode(regs) && !is_pv_vcpu(current)) + current->arch.hvm_vcpu.single_step = 0; + rc = kdbmain(KDB_REASON_DBEXCP, regs); + } + + } else if (vector == TRAP_nmi) { /* external nmi */ + /* when nmi is pressed, it could go to one or more or all cpus + * depending on the hardware. Also, for now assume it's fatal */ + KDBGP("kdbtrp:ccpu:%d vec:%d\n", ccpu, vector); + rc = kdbmain_fatal(regs, TRAP_nmi); + } + return rc; +} + +int +kdb_trap_fatal(int vector, struct cpu_user_regs *regs) +{ + kdbmain_fatal(regs, vector); + return 0; +} + +/* From smp_send_nmi_allbutself() in crash.c which is static */ +void +kdb_nmi_pause_cpus(cpumask_t cpumask) +{ + int ccpu = smp_processor_id(); + mdelay(200); + cpumask_complement(&cpumask, &cpumask); /* flip bit map */ + cpumask_and(&cpumask, &cpumask, &cpu_online_map); /* remove extra bits */ + cpumask_clear_cpu(ccpu, &cpumask);/* absolutely make sure we're not on it */ + + KDBGP("ccpu:%d nmi pause. mask:0x%lx\n", ccpu, cpumask.bits[0]); + if ( !cpumask_empty(&cpumask) ) +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ + send_IPI_mask(&cpumask, APIC_DM_NMI); +#else + send_IPI_mask(cpumask, APIC_DM_NMI); +#endif + mdelay(200); + KDBGP("ccpu:%d nmi pause done...\n", ccpu); +} + +/* + * Separate function from kdbmain to keep both within sanity levels. + */ +DEFINE_SPINLOCK(kdb_fatal_lk); +static int +kdbmain_fatal(struct cpu_user_regs *regs, int vector) +{ + int ccpu = smp_processor_id(); + + console_start_sync(); + + KDBGP("mainf:ccpu:%d vec:%d irq:%d\n", ccpu, vector,local_irq_is_enabled()); + cpumask_set_cpu(ccpu, &kdb_fatal_cpumask); /* uses LOCK_PREFIX */ + + if (spin_trylock(&kdb_fatal_lk)) { + + kdbp("*** kdb (Fatal Error on cpu:%d vec:%d %s):\n", ccpu, + vector, kdb_gettrapname(vector)); + kdb_cpu_cmd[ccpu] = KDB_CPU_MAIN_KDB; + kdb_display_pc(regs); + + watchdog_disable(); /* important */ + kdb_sys_crash = 1; + kdb_session_begun = 0; /* incase session already active */ + local_irq_enable(); + kdb_nmi_pause_cpus(kdb_fatal_cpumask); + + kdb_clear_prev_cmd(); /* buffered CRs will repeat prev cmd */ + kdb_session_begun = 1; /* for kdb_hold_this_cpu() */ + local_irq_disable(); + } else { + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; + } + while (1) { + if (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE) + kdb_hold_this_cpu(ccpu, regs); + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB) + kdb_do_cmds(regs); +#if 0 + /* dump is the only way to exit in crashed state */ + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DUMP) + kdb_do_dump(regs); +#endif + } + return 0; +} + +/* Mostly called in fatal cases. earlykdb calls non-fatal. + * kdb_trap_immed_reason is global, so allow only one cpu at a time. Also, + * multiple cpu may be crashing at the same time. We enable because if there + * is a bad hang, at least ctrl-\ will break into kdb. Also, we don't call + * call kdb_keyboard directly becaue we don't have the register context. + */ +DEFINE_SPINLOCK(kdb_immed_lk); +void +kdb_trap_immed(int reason) /* fatal, non-fatal, kdb stack etc... */ +{ + int ccpu = smp_processor_id(); + int disabled = !local_irq_is_enabled(); + + KDBGP("trapimm:ccpu:%d reas:%d\n", ccpu, reason); + local_irq_enable(); + spin_lock(&kdb_immed_lk); + kdb_trap_immed_reason = reason; + barrier(); + __asm__ __volatile__ ( "int $1" ); + kdb_trap_immed_reason = 0; + + spin_unlock(&kdb_immed_lk); + if (disabled) + local_irq_disable(); +} + +/* called very early during init, even before all CPUs are brought online */ +void +kdb_init(void) +{ + kdb_init_cmdtab(); /* Initialize Command Table */ +} + +static const char * +kdb_gettrapname(int trapno) +{ + char *ret; + switch (trapno) { + case 0: ret = "Divide Error"; break; + case 2: ret = "NMI Interrupt"; break; + case 3: ret = "Int 3 Trap"; break; + case 4: ret = "Overflow Error"; break; + case 6: ret = "Invalid Opcode"; break; + case 8: ret = "Double Fault"; break; + case 10: ret = "Invalid TSS"; break; + case 11: ret = "Segment Not Present"; break; + case 12: ret = "Stack-Segment Fault"; break; + case 13: ret = "General Protection"; break; + case 14: ret = "Page Fault"; break; + case 17: ret = "Alignment Check"; break; + default: ret = " ????? "; + } + return ret; +} + + +/* ====================== Generic tracing subsystem ======================== */ + +#define KDBTRCMAX 1 /* set this to max number of recs to trace. each rec + * is 32 bytes */ +volatile int kdb_trcon=1; /* turn tracing ON: set here or via the trcon cmd */ + +typedef struct { + union { + struct { uint d0; uint cpu_trcid; } s0; + uint64_t l0; + }u; + uint64_t l1, l2, l3; +} trc_rec_t; + +static volatile unsigned int trcidx; /* points to where new entry will go */ +static trc_rec_t trca[KDBTRCMAX]; /* trace array */ + +/* atomically: add i to *p, return prev value of *p (ie, val before add) */ +static int +kdb_fetch_and_add(int i, uint *p) +{ + asm volatile("lock xaddl %0, %1;" : "=r"(i) : "m"(*p), "0"(i)); + return i; +} + +/* zero out the entire buffer */ +void +kdb_trczero(void) +{ + for (trcidx = KDBTRCMAX-1; trcidx; trcidx--) { + memset(&trca[trcidx], 0, sizeof(trc_rec_t)); + } + memset(&trca[trcidx], 0, sizeof(trc_rec_t)); + kdbp("kdb trace buffer has been zeroed\n"); +} + +/* add trace entry: eg.: kdbtrc(0xe0f099, intdata, vcpu, domain, 0) + * where: 0xe0f099 : 24bits max trcid, lower 8 bits are set to cpuid */ +void +kdbtrc(uint trcid, uint int_d0, uint64_t d1_64, uint64_t d2_64, uint64_t d3_64) +{ + uint idx; + + if (!kdb_trcon) + return; + + idx = kdb_fetch_and_add(1, (uint*)&trcidx); + idx = idx % KDBTRCMAX; + +#if 0 + trca[idx].u.s0.cpu_trcid = (smp_processor_id()<<24) | trcid; +#endif + trca[idx].u.s0.cpu_trcid = (trcid<<8) | smp_processor_id(); + trca[idx].u.s0.d0 = int_d0; + trca[idx].l1 = d1_64; + trca[idx].l2 = d2_64; + trca[idx].l3 = d3_64; +} + +/* give hints so user can print trc buffer via the dd command. last has the + * most recent entry */ +void +kdb_trcp(void) +{ + int i = trcidx % KDBTRCMAX; + + i = (i==0) ? KDBTRCMAX-1 : i-1; + kdbp("trcbuf: [0]: %016lx [MAX-1]: %016lx\n", &trca[0], + &trca[KDBTRCMAX-1]); + kdbp(" [most recent]: %016lx trcidx: 0x%x\n", &trca[i], trcidx); +} + + +void noinline mukchk(unsigned long ul) +{ +} + diff --git a/xen/kdb/x86/Makefile b/xen/kdb/x86/Makefile new file mode 100644 index 0000000..aa46232 --- /dev/null +++ b/xen/kdb/x86/Makefile @@ -0,0 +1,3 @@ + +obj-y := kdb_wp.o +subdir-y += udis86-1.7 diff --git a/xen/kdb/x86/kdb_wp.c b/xen/kdb/x86/kdb_wp.c new file mode 100644 index 0000000..43c5b45 --- /dev/null +++ b/xen/kdb/x86/kdb_wp.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "../include/kdbinc.h" + +#if 0 +#define DR6_BT 0x00008000 +#define DR6_BS 0x00004000 +#define DR6_BD 0x00002000 +#endif +#define DR6_B3 0x00000008 +#define DR6_B2 0x00000004 +#define DR6_B1 0x00000002 +#define DR6_B0 0x00000001 + +#define KDB_MAXWP 4 /* DR0 thru DR3 */ + +struct kdb_wp { + kdbma_t wp_addr; + int wp_rwflag; + int wp_len; + int wp_deleted; /* pending delete */ +}; +static struct kdb_wp kdb_wpa[KDB_MAXWP]; + +/* following because vmcs has it's own dr7. when vmcs runs, it messes up the + * native dr7 so we need to save/restore it */ +unsigned long kdb_dr7; + + +/* Set G0-G3 bits in DR7. this does global enable of the corresponding wp */ +static void +kdb_set_gx_in_dr7(int regno, kdbma_t *dr7p) +{ + if (regno == 0) + *dr7p = *dr7p | 0x2; + else if (regno == 1) + *dr7p = *dr7p | 0x8; + else if (regno == 2) + *dr7p = *dr7p | 0x20; + else if (regno == 3) + *dr7p = *dr7p | 0x80; +} + +/* Set LEN0 - LEN3 pair bits in DR7 (len should be 1 2 4 or 8) */ +static void +kdb_set_len_in_dr7(int regno, kdbma_t *dr7p, int len) +{ + int lenbits = (len == 8) ? 2 : len-1; + + *dr7p &= ~(0x3 << (18 + 4*regno)); + *dr7p |= ((ulong)(lenbits & 0x3) << (18 + 4*regno)); +} + +static void +kdb_set_dr7_rw(int regno, kdbma_t *dr7p, int rw) +{ + *dr7p &= ~(0x3 << (16 + 4*regno)); + *dr7p |= ((ulong)(rw & 0x3)) << (16 + 4*regno); +} + +/* get value of a debug register: DR0-DR3 DR6 DR7. other values return 0 */ +kdbma_t +kdb_rd_dbgreg(int regnum) +{ + kdbma_t contents = 0; + + if (regnum == 0) + __asm__ ("movq %%db0,%0\n\t":"=r"(contents)); + else if (regnum == 1) + __asm__ ("movq %%db1,%0\n\t":"=r"(contents)); + else if (regnum == 2) + __asm__ ("movq %%db2,%0\n\t":"=r"(contents)); + else if (regnum == 3) + __asm__ ("movq %%db3,%0\n\t":"=r"(contents)); + else if (regnum == 6) + __asm__ ("movq %%db6,%0\n\t":"=r"(contents)); + else if (regnum == 7) + __asm__ ("movq %%db7,%0\n\t":"=r"(contents)); + + return contents; +} + +static void +kdb_wr_dbgreg(int regnum, kdbma_t contents) +{ + if (regnum == 0) + __asm__ ("movq %0,%%db0\n\t"::"r"(contents)); + else if (regnum == 1) + __asm__ ("movq %0,%%db1\n\t"::"r"(contents)); + else if (regnum == 2) + __asm__ ("movq %0,%%db2\n\t"::"r"(contents)); + else if (regnum == 3) + __asm__ ("movq %0,%%db3\n\t"::"r"(contents)); + else if (regnum == 6) + __asm__ ("movq %0,%%db6\n\t"::"r"(contents)); + else if (regnum == 7) + __asm__ ("movq %0,%%db7\n\t"::"r"(contents)); +} + +static void +kdb_print_wp_info(char *strp, int idx) +{ + kdbp("%s[%d]:%016lx len:%d ", strp, idx, kdb_wpa[idx].wp_addr, + kdb_wpa[idx].wp_len); + if (kdb_wpa[idx].wp_rwflag == 1) + kdbp("on data write only\n"); + else if (kdb_wpa[idx].wp_rwflag == 2) + kdbp("on IO read/write\n"); + else + kdbp("on data read/write\n"); +} + +/* + * Returns : 0 if not one of ours + * 1 if one of ours + */ +int +kdb_check_watchpoints(struct cpu_user_regs *regs) +{ + int wpnum; + kdbma_t dr6 = kdb_rd_dbgreg(6); + + KDBGP1("check_wp: IP:%lx EFLAGS:%lx\n", regs->rip, regs->rflags); + if (dr6 & DR6_B0) + wpnum = 0; + else if (dr6 & DR6_B1) + wpnum = 1; + else if (dr6 & DR6_B2) + wpnum = 2; + else if (dr6 & DR6_B3) + wpnum = 3; + else + return 0; + + kdb_print_wp_info("Watchpoint ", wpnum); + return 1; +} + +/* set a watchpoint at a given address + * PreCondition: addr != 0 */ +static void +kdb_set_wp(kdbva_t addr, int rwflag, int len) +{ + int regno; + + for (regno=0; regno < KDB_MAXWP; regno++) { + if (kdb_wpa[regno].wp_addr == addr && !kdb_wpa[regno].wp_deleted) { + kdbp("Watchpoint already set\n"); + return; + } + if (kdb_wpa[regno].wp_deleted) + memset(&kdb_wpa[regno], 0, sizeof(kdb_wpa[regno])); + } + for (regno=0; regno < KDB_MAXWP && kdb_wpa[regno].wp_addr; regno++); + if (regno >= KDB_MAXWP) { + kdbp("watchpoint table full. limit:%d\n", KDB_MAXWP); + return; + } + kdb_wpa[regno].wp_addr = addr; + kdb_wpa[regno].wp_rwflag = rwflag; + kdb_wpa[regno].wp_len = len; + kdb_print_wp_info("Watchpoint set ", regno); +} + +/* write reg DR0-3 with address. Update corresponding bits in DR7 */ +static void +kdb_install_watchpoint(int regno, kdbma_t *dr7p) +{ + kdb_set_gx_in_dr7(regno, dr7p); + kdb_set_len_in_dr7(regno, dr7p, kdb_wpa[regno].wp_len); + kdb_set_dr7_rw(regno, dr7p, kdb_wpa[regno].wp_rwflag); + kdb_wr_dbgreg(regno, kdb_wpa[regno].wp_addr); + + KDBGP1("ccpu:%d installed wp. addr:%lx rw:%x len:%x dr7:%016lx\n", + smp_processor_id(), kdb_wpa[regno].wp_addr, + kdb_wpa[regno].wp_rwflag, kdb_wpa[regno].wp_len, *dr7p); +} + +/* clear G0-G3 bits in DR7 for given DR0-3 */ +static void +kdb_clear_dr7_gx(int regno, kdbma_t *dr7p) +{ + if (regno == 0) + *dr7p = *dr7p & ~0x2; + else if (regno == 1) + *dr7p = *dr7p & ~0x8; + else if (regno == 2) + *dr7p = *dr7p & ~0x20; + else if (regno == 3) + *dr7p = *dr7p & ~0x80; +} + +/* update dr7 once, as it's slow to update debug regs and cpu's will still be + * paused when leaving kdb. + * + * Just leave DR0-3 clobbered but remove bits from DR7 to disable wp + */ +void +kdb_install_watchpoints(void) +{ + int regno; + kdbma_t dr7 = kdb_rd_dbgreg(7); + + for (regno=0; regno < KDB_MAXWP; regno++) { + /* do not clear wp_deleted here as all cpus must clear wps */ + if (kdb_wpa[regno].wp_deleted) { + kdb_clear_dr7_gx(regno, &dr7); + continue; + } + if (kdb_wpa[regno].wp_addr) + kdb_install_watchpoint(regno, &dr7); + } + /* always clear DR6 when leaving */ + kdb_wr_dbgreg(6, 0); + kdb_wr_dbgreg(7, dr7); + + if (dr7 & DR7_ACTIVE_MASK) + kdb_dr7 = dr7; + else + kdb_dr7 = 0; +#if 0 + for(dp=domain_list; dp; dp=dp->next_in_list) { + struct vcpu *vp; + for_each_vcpu(dp, vp) { + for (regno=0; regno < KDB_MAXWP; regno++) + vp->arch.guest_context.debugreg[regno] = kdb_wpa[regno].wp_addr; + + vp->arch.guest_context.debugreg[6] = 0; + vp->arch.guest_context.debugreg[7] = dr7; + KDBGP("kdb_install_watchpoints(): v:%p dr7:%lx\n", vp, dr7); + /* hvm_set_info_guest(vp);: Can't because can't vmcs_enter in kdb */ + } + } +#endif +} + +/* clear watchpoint/s. wpnum == -1 to clear all watchpoints */ +void +kdb_clear_wps(int wpnum) +{ + int i; + + if (wpnum >= KDB_MAXWP) { + kdbp("Invalid wpnum %d\n", wpnum); + return; + } + if (wpnum >=0) { + if (kdb_wpa[wpnum].wp_addr) { + kdb_wpa[wpnum].wp_deleted = 1; + kdb_print_wp_info("Deleted watchpoint", wpnum); + } else + kdbp("watchpoint %d not set\n", wpnum); + return; + } + for (i=0; i < KDB_MAXWP; i++) { + if (kdb_wpa[i].wp_addr) { + kdb_wpa[i].wp_deleted = 1; + kdb_print_wp_info("Deleted watchpoint", i); + } + } +} + +/* display any watchpoints that are set */ +static void +kdb_display_wps(void) +{ + int i; + for (i=0; i < KDB_MAXWP; i++) + if (kdb_wpa[i].wp_addr && !kdb_wpa[i].wp_deleted) + kdb_print_wp_info("", i); +} + +/* + * Display or Set hardware breakpoints, ie, watchpoints: + * - Upto 4 are allowed + * + * rw_flag should be one of: + * 01 == break on data write only + * 10 == break on IO read/write + * 11 == Break on data reads or writes + * + * len should be one of : 1 2 4 8 + */ +void +kdb_do_watchpoints(kdbva_t addr, int rw_flag, int len) +{ + if (addr == 0) { + kdb_display_wps(); /* display set watchpoints */ + return; + } + kdb_set_wp(addr, rw_flag, len); + return; +} + diff --git a/xen/kdb/x86/udis86-1.7/LICENSE b/xen/kdb/x86/udis86-1.7/LICENSE new file mode 100644 index 0000000..6cc1b78 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2002, 2003, 2004, 2005, 2006 +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/xen/kdb/x86/udis86-1.7/Makefile b/xen/kdb/x86/udis86-1.7/Makefile new file mode 100644 index 0000000..eef9f59 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/Makefile @@ -0,0 +1,5 @@ + +CFLAGS += -D__UD_STANDALONE__ +obj-y := decode.o input.o itab.o kdb_dis.o syn-att.o syn.o \ + syn-intel.o udis86.o + diff --git a/xen/kdb/x86/udis86-1.7/README b/xen/kdb/x86/udis86-1.7/README new file mode 100644 index 0000000..4c1cf89 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/README @@ -0,0 +1,10 @@ + +http://udis86.sourceforge.net/ +udis86-1.6 : + - cd libudis86 + - cp *c to here + - cp *h to here + +Mukesh Rathor +04/30/2008 + diff --git a/xen/kdb/x86/udis86-1.7/decode.c b/xen/kdb/x86/udis86-1.7/decode.c new file mode 100644 index 0000000..823bf9b --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/decode.c @@ -0,0 +1,1197 @@ +/* ----------------------------------------------------------------------------- + * decode.c + * + * Copyright (c) 2005, 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ + +#if 0 +#include +#include +#endif + +#include "types.h" +#include "itab.h" +#include "input.h" +#include "decode.h" + +/* The max number of prefixes to an instruction */ +#define MAX_PREFIXES 15 + +static struct ud_itab_entry ie_invalid = { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }; +static struct ud_itab_entry ie_pause = { UD_Ipause, O_NONE, O_NONE, O_NONE, P_none }; +static struct ud_itab_entry ie_nop = { UD_Inop, O_NONE, O_NONE, O_NONE, P_none }; + + +/* Looks up mnemonic code in the mnemonic string table + * Returns NULL if the mnemonic code is invalid + */ +const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ) +{ + if ( c < UD_Id3vil ) + return ud_mnemonics_str[ c ]; + return NULL; +} + + +/* Extracts instruction prefixes. + */ +static int get_prefixes( struct ud* u ) +{ + unsigned int have_pfx = 1; + unsigned int i; + uint8_t curr; + + /* if in error state, bail out */ + if ( u->error ) + return -1; + + /* keep going as long as there are prefixes available */ + for ( i = 0; have_pfx ; ++i ) { + + /* Get next byte. */ + inp_next(u); + if ( u->error ) + return -1; + curr = inp_curr( u ); + + /* rex prefixes in 64bit mode */ + if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) { + u->pfx_rex = curr; + } else { + switch ( curr ) + { + case 0x2E : + u->pfx_seg = UD_R_CS; + u->pfx_rex = 0; + break; + case 0x36 : + u->pfx_seg = UD_R_SS; + u->pfx_rex = 0; + break; + case 0x3E : + u->pfx_seg = UD_R_DS; + u->pfx_rex = 0; + break; + case 0x26 : + u->pfx_seg = UD_R_ES; + u->pfx_rex = 0; + break; + case 0x64 : + u->pfx_seg = UD_R_FS; + u->pfx_rex = 0; + break; + case 0x65 : + u->pfx_seg = UD_R_GS; + u->pfx_rex = 0; + break; + case 0x67 : /* adress-size override prefix */ + u->pfx_adr = 0x67; + u->pfx_rex = 0; + break; + case 0xF0 : + u->pfx_lock = 0xF0; + u->pfx_rex = 0; + break; + case 0x66: + /* the 0x66 sse prefix is only effective if no other sse prefix + * has already been specified. + */ + if ( !u->pfx_insn ) u->pfx_insn = 0x66; + u->pfx_opr = 0x66; + u->pfx_rex = 0; + break; + case 0xF2: + u->pfx_insn = 0xF2; + u->pfx_repne = 0xF2; + u->pfx_rex = 0; + break; + case 0xF3: + u->pfx_insn = 0xF3; + u->pfx_rep = 0xF3; + u->pfx_repe = 0xF3; + u->pfx_rex = 0; + break; + default : + /* No more prefixes */ + have_pfx = 0; + break; + } + } + + /* check if we reached max instruction length */ + if ( i + 1 == MAX_INSN_LENGTH ) { + u->error = 1; + break; + } + } + + /* return status */ + if ( u->error ) + return -1; + + /* rewind back one byte in stream, since the above loop + * stops with a non-prefix byte. + */ + inp_back(u); + + /* speculatively determine the effective operand mode, + * based on the prefixes and the current disassembly + * mode. This may be inaccurate, but useful for mode + * dependent decoding. + */ + if ( u->dis_mode == 64 ) { + u->opr_mode = REX_W( u->pfx_rex ) ? 64 : ( ( u->pfx_opr ) ? 16 : 32 ) ; + u->adr_mode = ( u->pfx_adr ) ? 32 : 64; + } else if ( u->dis_mode == 32 ) { + u->opr_mode = ( u->pfx_opr ) ? 16 : 32; + u->adr_mode = ( u->pfx_adr ) ? 16 : 32; + } else if ( u->dis_mode == 16 ) { + u->opr_mode = ( u->pfx_opr ) ? 32 : 16; + u->adr_mode = ( u->pfx_adr ) ? 32 : 16; + } + + return 0; +} + + +/* Searches the instruction tables for the right entry. + */ +static int search_itab( struct ud * u ) +{ + struct ud_itab_entry * e = NULL; + enum ud_itab_index table; + uint8_t peek; + uint8_t did_peek = 0; + uint8_t curr; + uint8_t index; + + /* if in state of error, return */ + if ( u->error ) + return -1; + + /* get first byte of opcode. */ + inp_next(u); + if ( u->error ) + return -1; + curr = inp_curr(u); + + /* resolve xchg, nop, pause crazyness */ + if ( 0x90 == curr ) { + if ( !( u->dis_mode == 64 && REX_B( u->pfx_rex ) ) ) { + if ( u->pfx_rep ) { + u->pfx_rep = 0; + e = & ie_pause; + } else { + e = & ie_nop; + } + goto found_entry; + } + } + + /* get top-level table */ + if ( 0x0F == curr ) { + table = ITAB__0F; + curr = inp_next(u); + if ( u->error ) + return -1; + + /* 2byte opcodes can be modified by 0x66, F3, and F2 prefixes */ + if ( 0x66 == u->pfx_insn ) { + if ( ud_itab_list[ ITAB__PFX_SSE66__0F ][ curr ].mnemonic != UD_Iinvalid ) { + table = ITAB__PFX_SSE66__0F; + u->pfx_opr = 0; + } + } else if ( 0xF2 == u->pfx_insn ) { + if ( ud_itab_list[ ITAB__PFX_SSEF2__0F ][ curr ].mnemonic != UD_Iinvalid ) { + table = ITAB__PFX_SSEF2__0F; + u->pfx_repne = 0; + } + } else if ( 0xF3 == u->pfx_insn ) { + if ( ud_itab_list[ ITAB__PFX_SSEF3__0F ][ curr ].mnemonic != UD_Iinvalid ) { + table = ITAB__PFX_SSEF3__0F; + u->pfx_repe = 0; + u->pfx_rep = 0; + } + } + /* pick an instruction from the 1byte table */ + } else { + table = ITAB__1BYTE; + } + + index = curr; + +search: + + e = & ud_itab_list[ table ][ index ]; + + /* if mnemonic constant is a standard instruction constant + * our search is over. + */ + + if ( e->mnemonic < UD_Id3vil ) { + if ( e->mnemonic == UD_Iinvalid ) { + if ( did_peek ) { + inp_next( u ); if ( u->error ) return -1; + } + goto found_entry; + } + goto found_entry; + } + + table = e->prefix; + + switch ( e->mnemonic ) + { + case UD_Igrp_reg: + peek = inp_peek( u ); + did_peek = 1; + index = MODRM_REG( peek ); + break; + + case UD_Igrp_mod: + peek = inp_peek( u ); + did_peek = 1; + index = MODRM_MOD( peek ); + if ( index == 3 ) + index = ITAB__MOD_INDX__11; + else + index = ITAB__MOD_INDX__NOT_11; + break; + + case UD_Igrp_rm: + curr = inp_next( u ); + did_peek = 0; + if ( u->error ) + return -1; + index = MODRM_RM( curr ); + break; + + case UD_Igrp_x87: + curr = inp_next( u ); + did_peek = 0; + if ( u->error ) + return -1; + index = curr - 0xC0; + break; + + case UD_Igrp_osize: + if ( u->opr_mode == 64 ) + index = ITAB__MODE_INDX__64; + else if ( u->opr_mode == 32 ) + index = ITAB__MODE_INDX__32; + else + index = ITAB__MODE_INDX__16; + break; + + case UD_Igrp_asize: + if ( u->adr_mode == 64 ) + index = ITAB__MODE_INDX__64; + else if ( u->adr_mode == 32 ) + index = ITAB__MODE_INDX__32; + else + index = ITAB__MODE_INDX__16; + break; + + case UD_Igrp_mode: + if ( u->dis_mode == 64 ) + index = ITAB__MODE_INDX__64; + else if ( u->dis_mode == 32 ) + index = ITAB__MODE_INDX__32; + else + index = ITAB__MODE_INDX__16; + break; + + case UD_Igrp_vendor: + if ( u->vendor == UD_VENDOR_INTEL ) + index = ITAB__VENDOR_INDX__INTEL; + else if ( u->vendor == UD_VENDOR_AMD ) + index = ITAB__VENDOR_INDX__AMD; + else { + kdbp("KDB:search_itab(): unrecognized vendor id\n"); + return -1; + } + break; + + case UD_Id3vil: + kdbp("KDB:search_itab(): invalid instr mnemonic constant Id3vil\n"); + return -1; + + default: + kdbp("KDB:search_itab(): invalid instruction mnemonic constant\n"); + return -1; + } + + goto search; + +found_entry: + + u->itab_entry = e; + u->mnemonic = u->itab_entry->mnemonic; + + return 0; +} + + +static unsigned int resolve_operand_size( const struct ud * u, unsigned int s ) +{ + switch ( s ) + { + case SZ_V: + return ( u->opr_mode ); + case SZ_Z: + return ( u->opr_mode == 16 ) ? 16 : 32; + case SZ_P: + return ( u->opr_mode == 16 ) ? SZ_WP : SZ_DP; + case SZ_MDQ: + return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; + case SZ_RDQ: + return ( u->dis_mode == 64 ) ? 64 : 32; + default: + return s; + } +} + + +static int resolve_mnemonic( struct ud* u ) +{ + /* far/near flags */ + u->br_far = 0; + u->br_near = 0; + /* readjust operand sizes for call/jmp instrcutions */ + if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) { + /* WP: 16bit pointer */ + if ( u->operand[ 0 ].size == SZ_WP ) { + u->operand[ 0 ].size = 16; + u->br_far = 1; + u->br_near= 0; + /* DP: 32bit pointer */ + } else if ( u->operand[ 0 ].size == SZ_DP ) { + u->operand[ 0 ].size = 32; + u->br_far = 1; + u->br_near= 0; + } else { + u->br_far = 0; + u->br_near= 1; + } + /* resolve 3dnow weirdness. */ + } else if ( u->mnemonic == UD_I3dnow ) { + u->mnemonic = ud_itab_list[ ITAB__3DNOW ][ inp_curr( u ) ].mnemonic; + } + /* SWAPGS is only valid in 64bits mode */ + if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { + u->error = 1; + return -1; + } + + return 0; +} + + +/* ----------------------------------------------------------------------------- + * decode_a()- Decodes operands of the type seg:offset + * ----------------------------------------------------------------------------- + */ +static void +decode_a(struct ud* u, struct ud_operand *op) +{ + if (u->opr_mode == 16) { + /* seg16:off16 */ + op->type = UD_OP_PTR; + op->size = 32; + op->lval.ptr.off = inp_uint16(u); + op->lval.ptr.seg = inp_uint16(u); + } else { + /* seg16:off32 */ + op->type = UD_OP_PTR; + op->size = 48; + op->lval.ptr.off = inp_uint32(u); + op->lval.ptr.seg = inp_uint16(u); + } +} + +/* ----------------------------------------------------------------------------- + * decode_gpr() - Returns decoded General Purpose Register + * ----------------------------------------------------------------------------- + */ +static enum ud_type +decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) +{ + s = resolve_operand_size(u, s); + + switch (s) { + case 64: + return UD_R_RAX + rm; + case SZ_DP: + case 32: + return UD_R_EAX + rm; + case SZ_WP: + case 16: + return UD_R_AX + rm; + case 8: + if (u->dis_mode == 64 && u->pfx_rex) { + if (rm >= 4) + return UD_R_SPL + (rm-4); + return UD_R_AL + rm; + } else return UD_R_AL + rm; + default: + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * resolve_gpr64() - 64bit General Purpose Register-Selection. + * ----------------------------------------------------------------------------- + */ +static enum ud_type +resolve_gpr64(struct ud* u, enum ud_operand_code gpr_op) +{ + if (gpr_op >= OP_rAXr8 && gpr_op <= OP_rDIr15) + gpr_op = (gpr_op - OP_rAXr8) | (REX_B(u->pfx_rex) << 3); + else gpr_op = (gpr_op - OP_rAX); + + if (u->opr_mode == 16) + return gpr_op + UD_R_AX; + if (u->dis_mode == 32 || + (u->opr_mode == 32 && ! (REX_W(u->pfx_rex) || u->default64))) { + return gpr_op + UD_R_EAX; + } + + return gpr_op + UD_R_RAX; +} + +/* ----------------------------------------------------------------------------- + * resolve_gpr32 () - 32bit General Purpose Register-Selection. + * ----------------------------------------------------------------------------- + */ +static enum ud_type +resolve_gpr32(struct ud* u, enum ud_operand_code gpr_op) +{ + gpr_op = gpr_op - OP_eAX; + + if (u->opr_mode == 16) + return gpr_op + UD_R_AX; + + return gpr_op + UD_R_EAX; +} + +/* ----------------------------------------------------------------------------- + * resolve_reg() - Resolves the register type + * ----------------------------------------------------------------------------- + */ +static enum ud_type +resolve_reg(struct ud* u, unsigned int type, unsigned char i) +{ + switch (type) { + case T_MMX : return UD_R_MM0 + (i & 7); + case T_XMM : return UD_R_XMM0 + i; + case T_CRG : return UD_R_CR0 + i; + case T_DBG : return UD_R_DR0 + i; + case T_SEG : return UD_R_ES + (i & 7); + case T_NONE: + default: return UD_NONE; + } +} + +/* ----------------------------------------------------------------------------- + * decode_imm() - Decodes Immediate values. + * ----------------------------------------------------------------------------- + */ +static void +decode_imm(struct ud* u, unsigned int s, struct ud_operand *op) +{ + op->size = resolve_operand_size(u, s); + op->type = UD_OP_IMM; + + switch (op->size) { + case 8: op->lval.sbyte = inp_uint8(u); break; + case 16: op->lval.uword = inp_uint16(u); break; + case 32: op->lval.udword = inp_uint32(u); break; + case 64: op->lval.uqword = inp_uint64(u); break; + default: return; + } +} + +/* ----------------------------------------------------------------------------- + * decode_modrm() - Decodes ModRM Byte + * ----------------------------------------------------------------------------- + */ +static void +decode_modrm(struct ud* u, struct ud_operand *op, unsigned int s, + unsigned char rm_type, struct ud_operand *opreg, + unsigned char reg_size, unsigned char reg_type) +{ + unsigned char mod, rm, reg; + + inp_next(u); + + /* get mod, r/m and reg fields */ + mod = MODRM_MOD(inp_curr(u)); + rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(inp_curr(u)); + reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(inp_curr(u)); + + op->size = resolve_operand_size(u, s); + + /* if mod is 11b, then the UD_R_m specifies a gpr/mmx/sse/control/debug */ + if (mod == 3) { + op->type = UD_OP_REG; + if (rm_type == T_GPR) + op->base = decode_gpr(u, op->size, rm); + else op->base = resolve_reg(u, rm_type, (REX_B(u->pfx_rex) << 3) | (rm&7)); + } + /* else its memory addressing */ + else { + op->type = UD_OP_MEM; + + /* 64bit addressing */ + if (u->adr_mode == 64) { + + op->base = UD_R_RAX + rm; + + /* get offset type */ + if (mod == 1) + op->offset = 8; + else if (mod == 2) + op->offset = 32; + else if (mod == 0 && (rm & 7) == 5) { + op->base = UD_R_RIP; + op->offset = 32; + } else op->offset = 0; + + /* Scale-Index-Base (SIB) */ + if ((rm & 7) == 4) { + inp_next(u); + + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + + /* special conditions for base reference */ + if (op->index == UD_R_RSP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } + + if (op->base == UD_R_RBP || op->base == UD_R_R13) { + if (mod == 0) + op->base = UD_NONE; + if (mod == 1) + op->offset = 8; + else op->offset = 32; + } + } + } + + /* 32-Bit addressing mode */ + else if (u->adr_mode == 32) { + + /* get base */ + op->base = UD_R_EAX + rm; + + /* get offset type */ + if (mod == 1) + op->offset = 8; + else if (mod == 2) + op->offset = 32; + else if (mod == 0 && rm == 5) { + op->base = UD_NONE; + op->offset = 32; + } else op->offset = 0; + + /* Scale-Index-Base (SIB) */ + if ((rm & 7) == 4) { + inp_next(u); + + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + + if (op->index == UD_R_ESP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } + + /* special condition for base reference */ + if (op->base == UD_R_EBP) { + if (mod == 0) + op->base = UD_NONE; + if (mod == 1) + op->offset = 8; + else op->offset = 32; + } + } + } + + /* 16bit addressing mode */ + else { + switch (rm) { + case 0: op->base = UD_R_BX; op->index = UD_R_SI; break; + case 1: op->base = UD_R_BX; op->index = UD_R_DI; break; + case 2: op->base = UD_R_BP; op->index = UD_R_SI; break; + case 3: op->base = UD_R_BP; op->index = UD_R_DI; break; + case 4: op->base = UD_R_SI; break; + case 5: op->base = UD_R_DI; break; + case 6: op->base = UD_R_BP; break; + case 7: op->base = UD_R_BX; break; + } + + if (mod == 0 && rm == 6) { + op->offset= 16; + op->base = UD_NONE; + } + else if (mod == 1) + op->offset = 8; + else if (mod == 2) + op->offset = 16; + } + } + + /* extract offset, if any */ + switch(op->offset) { + case 8 : op->lval.ubyte = inp_uint8(u); break; + case 16: op->lval.uword = inp_uint16(u); break; + case 32: op->lval.udword = inp_uint32(u); break; + case 64: op->lval.uqword = inp_uint64(u); break; + default: break; + } + + /* resolve register encoded in reg field */ + if (opreg) { + opreg->type = UD_OP_REG; + opreg->size = resolve_operand_size(u, reg_size); + if (reg_type == T_GPR) + opreg->base = decode_gpr(u, opreg->size, reg); + else opreg->base = resolve_reg(u, reg_type, reg); + } +} + +/* ----------------------------------------------------------------------------- + * decode_o() - Decodes offset + * ----------------------------------------------------------------------------- + */ +static void +decode_o(struct ud* u, unsigned int s, struct ud_operand *op) +{ + switch (u->adr_mode) { + case 64: + op->offset = 64; + op->lval.uqword = inp_uint64(u); + break; + case 32: + op->offset = 32; + op->lval.udword = inp_uint32(u); + break; + case 16: + op->offset = 16; + op->lval.uword = inp_uint16(u); + break; + default: + return; + } + op->type = UD_OP_MEM; + op->size = resolve_operand_size(u, s); +} + +/* ----------------------------------------------------------------------------- + * disasm_operands() - Disassembles Operands. + * ----------------------------------------------------------------------------- + */ +static int disasm_operands(register struct ud* u) +{ + + + /* mopXt = map entry, operand X, type; */ + enum ud_operand_code mop1t = u->itab_entry->operand1.type; + enum ud_operand_code mop2t = u->itab_entry->operand2.type; + enum ud_operand_code mop3t = u->itab_entry->operand3.type; + + /* mopXs = map entry, operand X, size */ + unsigned int mop1s = u->itab_entry->operand1.size; + unsigned int mop2s = u->itab_entry->operand2.size; + unsigned int mop3s = u->itab_entry->operand3.size; + + /* iop = instruction operand */ + register struct ud_operand* iop = u->operand; + + switch(mop1t) { + + case OP_A : + decode_a(u, &(iop[0])); + break; + + /* M[b] ... */ + case OP_M : + if (MODRM_MOD(inp_peek(u)) == 3) + u->error= 1; + /* E, G/P/V/I/CL/1/S */ + case OP_E : + if (mop2t == OP_G) { + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_GPR); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + else if (mop3t == OP_CL) { + iop[2].type = UD_OP_REG; + iop[2].base = UD_R_CL; + iop[2].size = 8; + } + } + else if (mop2t == OP_P) + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_MMX); + else if (mop2t == OP_V) + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_XMM); + else if (mop2t == OP_S) + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_SEG); + else { + decode_modrm(u, &(iop[0]), mop1s, T_GPR, NULL, 0, T_NONE); + if (mop2t == OP_CL) { + iop[1].type = UD_OP_REG; + iop[1].base = UD_R_CL; + iop[1].size = 8; + } else if (mop2t == OP_I1) { + iop[1].type = UD_OP_CONST; + u->operand[1].lval.udword = 1; + } else if (mop2t == OP_I) { + decode_imm(u, mop2s, &(iop[1])); + } + } + break; + + /* G, E/PR[,I]/VR */ + case OP_G : + if (mop2t == OP_M) { + if (MODRM_MOD(inp_peek(u)) == 3) + u->error= 1; + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); + } else if (mop2t == OP_E) { + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + } else if (mop2t == OP_PR) { + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_GPR); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + } else if (mop2t == OP_VR) { + if (MODRM_MOD(inp_peek(u)) != 3) + u->error = 1; + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); + } else if (mop2t == OP_W) + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); + break; + + /* AL..BH, I/O/DX */ + case OP_AL : case OP_CL : case OP_DL : case OP_BL : + case OP_AH : case OP_CH : case OP_DH : case OP_BH : + + iop[0].type = UD_OP_REG; + iop[0].base = UD_R_AL + (mop1t - OP_AL); + iop[0].size = 8; + + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + else if (mop2t == OP_DX) { + iop[1].type = UD_OP_REG; + iop[1].base = UD_R_DX; + iop[1].size = 16; + } + else if (mop2t == OP_O) + decode_o(u, mop2s, &(iop[1])); + break; + + /* rAX[r8]..rDI[r15], I/rAX..rDI/O */ + case OP_rAXr8 : case OP_rCXr9 : case OP_rDXr10 : case OP_rBXr11 : + case OP_rSPr12: case OP_rBPr13: case OP_rSIr14 : case OP_rDIr15 : + case OP_rAX : case OP_rCX : case OP_rDX : case OP_rBX : + case OP_rSP : case OP_rBP : case OP_rSI : case OP_rDI : + + iop[0].type = UD_OP_REG; + iop[0].base = resolve_gpr64(u, mop1t); + + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + else if (mop2t >= OP_rAX && mop2t <= OP_rDI) { + iop[1].type = UD_OP_REG; + iop[1].base = resolve_gpr64(u, mop2t); + } + else if (mop2t == OP_O) { + decode_o(u, mop2s, &(iop[1])); + iop[0].size = resolve_operand_size(u, mop2s); + } + break; + + /* AL[r8b]..BH[r15b], I */ + case OP_ALr8b : case OP_CLr9b : case OP_DLr10b : case OP_BLr11b : + case OP_AHr12b: case OP_CHr13b: case OP_DHr14b : case OP_BHr15b : + { + ud_type_t gpr = (mop1t - OP_ALr8b) + UD_R_AL + + (REX_B(u->pfx_rex) << 3); + if (UD_R_AH <= gpr && u->pfx_rex) + gpr = gpr + 4; + iop[0].type = UD_OP_REG; + iop[0].base = gpr; + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + break; + } + + /* eAX..eDX, DX/I */ + case OP_eAX : case OP_eCX : case OP_eDX : case OP_eBX : + case OP_eSP : case OP_eBP : case OP_eSI : case OP_eDI : + iop[0].type = UD_OP_REG; + iop[0].base = resolve_gpr32(u, mop1t); + if (mop2t == OP_DX) { + iop[1].type = UD_OP_REG; + iop[1].base = UD_R_DX; + iop[1].size = 16; + } else if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + break; + + /* ES..GS */ + case OP_ES : case OP_CS : case OP_DS : + case OP_SS : case OP_FS : case OP_GS : + + /* in 64bits mode, only fs and gs are allowed */ + if (u->dis_mode == 64) + if (mop1t != OP_FS && mop1t != OP_GS) + u->error= 1; + iop[0].type = UD_OP_REG; + iop[0].base = (mop1t - OP_ES) + UD_R_ES; + iop[0].size = 16; + + break; + + /* J */ + case OP_J : + decode_imm(u, mop1s, &(iop[0])); + iop[0].type = UD_OP_JIMM; + break ; + + /* PR, I */ + case OP_PR: + if (MODRM_MOD(inp_peek(u)) != 3) + u->error = 1; + decode_modrm(u, &(iop[0]), mop1s, T_MMX, NULL, 0, T_NONE); + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + break; + + /* VR, I */ + case OP_VR: + if (MODRM_MOD(inp_peek(u)) != 3) + u->error = 1; + decode_modrm(u, &(iop[0]), mop1s, T_XMM, NULL, 0, T_NONE); + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + break; + + /* P, Q[,I]/W/E[,I],VR */ + case OP_P : + if (mop2t == OP_Q) { + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_MMX); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + } else if (mop2t == OP_W) { + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); + } else if (mop2t == OP_VR) { + if (MODRM_MOD(inp_peek(u)) != 3) + u->error = 1; + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); + } else if (mop2t == OP_E) { + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_MMX); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + } + break; + + /* R, C/D */ + case OP_R : + if (mop2t == OP_C) + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_CRG); + else if (mop2t == OP_D) + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_DBG); + break; + + /* C, R */ + case OP_C : + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_CRG); + break; + + /* D, R */ + case OP_D : + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_DBG); + break; + + /* Q, P */ + case OP_Q : + decode_modrm(u, &(iop[0]), mop1s, T_MMX, &(iop[1]), mop2s, T_MMX); + break; + + /* S, E */ + case OP_S : + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_SEG); + break; + + /* W, V */ + case OP_W : + decode_modrm(u, &(iop[0]), mop1s, T_XMM, &(iop[1]), mop2s, T_XMM); + break; + + /* V, W[,I]/Q/M/E */ + case OP_V : + if (mop2t == OP_W) { + /* special cases for movlps and movhps */ + if (MODRM_MOD(inp_peek(u)) == 3) { + if (u->mnemonic == UD_Imovlps) + u->mnemonic = UD_Imovhlps; + else + if (u->mnemonic == UD_Imovhps) + u->mnemonic = UD_Imovlhps; + } + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_XMM); + if (mop3t == OP_I) + decode_imm(u, mop3s, &(iop[2])); + } else if (mop2t == OP_Q) + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); + else if (mop2t == OP_M) { + if (MODRM_MOD(inp_peek(u)) == 3) + u->error= 1; + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); + } else if (mop2t == OP_E) { + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); + } else if (mop2t == OP_PR) { + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); + } + break; + + /* DX, eAX/AL */ + case OP_DX : + iop[0].type = UD_OP_REG; + iop[0].base = UD_R_DX; + iop[0].size = 16; + + if (mop2t == OP_eAX) { + iop[1].type = UD_OP_REG; + iop[1].base = resolve_gpr32(u, mop2t); + } else if (mop2t == OP_AL) { + iop[1].type = UD_OP_REG; + iop[1].base = UD_R_AL; + iop[1].size = 8; + } + + break; + + /* I, I/AL/eAX */ + case OP_I : + decode_imm(u, mop1s, &(iop[0])); + if (mop2t == OP_I) + decode_imm(u, mop2s, &(iop[1])); + else if (mop2t == OP_AL) { + iop[1].type = UD_OP_REG; + iop[1].base = UD_R_AL; + iop[1].size = 16; + } else if (mop2t == OP_eAX) { + iop[1].type = UD_OP_REG; + iop[1].base = resolve_gpr32(u, mop2t); + } + break; + + /* O, AL/eAX */ + case OP_O : + decode_o(u, mop1s, &(iop[0])); + iop[1].type = UD_OP_REG; + iop[1].size = resolve_operand_size(u, mop1s); + if (mop2t == OP_AL) + iop[1].base = UD_R_AL; + else if (mop2t == OP_eAX) + iop[1].base = resolve_gpr32(u, mop2t); + else if (mop2t == OP_rAX) + iop[1].base = resolve_gpr64(u, mop2t); + break; + + /* 3 */ + case OP_I3 : + iop[0].type = UD_OP_CONST; + iop[0].lval.sbyte = 3; + break; + + /* ST(n), ST(n) */ + case OP_ST0 : case OP_ST1 : case OP_ST2 : case OP_ST3 : + case OP_ST4 : case OP_ST5 : case OP_ST6 : case OP_ST7 : + + iop[0].type = UD_OP_REG; + iop[0].base = (mop1t-OP_ST0) + UD_R_ST0; + iop[0].size = 0; + + if (mop2t >= OP_ST0 && mop2t <= OP_ST7) { + iop[1].type = UD_OP_REG; + iop[1].base = (mop2t-OP_ST0) + UD_R_ST0; + iop[1].size = 0; + } + break; + + /* AX */ + case OP_AX: + iop[0].type = UD_OP_REG; + iop[0].base = UD_R_AX; + iop[0].size = 16; + break; + + /* none */ + default : + iop[0].type = iop[1].type = iop[2].type = UD_NONE; + } + + return 0; +} + +/* ----------------------------------------------------------------------------- + * clear_insn() - clear instruction pointer + * ----------------------------------------------------------------------------- + */ +static int clear_insn(register struct ud* u) +{ + u->error = 0; + u->pfx_seg = 0; + u->pfx_opr = 0; + u->pfx_adr = 0; + u->pfx_lock = 0; + u->pfx_repne = 0; + u->pfx_rep = 0; + u->pfx_repe = 0; + u->pfx_seg = 0; + u->pfx_rex = 0; + u->pfx_insn = 0; + u->mnemonic = UD_Inone; + u->itab_entry = NULL; + + memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); + memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); + memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); + + return 0; +} + +static int do_mode( struct ud* u ) +{ + /* if in error state, bail out */ + if ( u->error ) return -1; + + /* propagate perfix effects */ + if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ + + /* Check validity of instruction m64 */ + if ( P_INV64( u->itab_entry->prefix ) ) { + u->error = 1; + return -1; + } + + /* effective rex prefix is the effective mask for the + * instruction hard-coded in the opcode map. + */ + u->pfx_rex = ( u->pfx_rex & 0x40 ) | + ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); + + /* whether this instruction has a default operand size of + * 64bit, also hardcoded into the opcode map. + */ + u->default64 = P_DEF64( u->itab_entry->prefix ); + /* calculate effective operand size */ + if ( REX_W( u->pfx_rex ) ) { + u->opr_mode = 64; + } else if ( u->pfx_opr ) { + u->opr_mode = 16; + } else { + /* unless the default opr size of instruction is 64, + * the effective operand size in the absence of rex.w + * prefix is 32. + */ + u->opr_mode = ( u->default64 ) ? 64 : 32; + } + + /* calculate effective address size */ + u->adr_mode = (u->pfx_adr) ? 32 : 64; + } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 16 : 32; + u->adr_mode = ( u->pfx_adr ) ? 16 : 32; + } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 32 : 16; + u->adr_mode = ( u->pfx_adr ) ? 32 : 16; + } + + /* These flags determine which operand to apply the operand size + * cast to. + */ + u->c1 = ( P_C1( u->itab_entry->prefix ) ) ? 1 : 0; + u->c2 = ( P_C2( u->itab_entry->prefix ) ) ? 1 : 0; + u->c3 = ( P_C3( u->itab_entry->prefix ) ) ? 1 : 0; + + /* set flags for implicit addressing */ + u->implicit_addr = P_IMPADDR( u->itab_entry->prefix ); + + return 0; +} + +static int gen_hex( struct ud *u ) +{ + unsigned int i; + unsigned char *src_ptr = inp_sess( u ); + char* src_hex; + + /* bail out if in error stat. */ + if ( u->error ) return -1; + /* output buffer pointe */ + src_hex = ( char* ) u->insn_hexcode; + /* for each byte used to decode instruction */ + for ( i = 0; i < u->inp_ctr; ++i, ++src_ptr) { + snprintf( src_hex, 2, "%02x", *src_ptr & 0xFF ); + src_hex += 2; + } + return 0; +} + +/* ============================================================================= + * ud_decode() - Instruction decoder. Returns the number of bytes decoded. + * ============================================================================= + */ +unsigned int ud_decode( struct ud* u ) +{ + inp_start(u); + + if ( clear_insn( u ) ) { + ; /* error */ + } else if ( get_prefixes( u ) != 0 ) { + ; /* error */ + } else if ( search_itab( u ) != 0 ) { + ; /* error */ + } else if ( do_mode( u ) != 0 ) { + ; /* error */ + } else if ( disasm_operands( u ) != 0 ) { + ; /* error */ + } else if ( resolve_mnemonic( u ) != 0 ) { + ; /* error */ + } + + /* Handle decode error. */ + if ( u->error ) { + /* clear out the decode data. */ + clear_insn( u ); + /* mark the sequence of bytes as invalid. */ + u->itab_entry = & ie_invalid; + u->mnemonic = u->itab_entry->mnemonic; + } + + u->insn_offset = u->pc; /* set offset of instruction */ + u->insn_fill = 0; /* set translation buffer index to 0 */ + u->pc += u->inp_ctr; /* move program counter by bytes decoded */ + gen_hex( u ); /* generate hex code */ + + /* return number of bytes disassembled. */ + return u->inp_ctr; +} + +/* vim:cindent + * vim:ts=4 + * vim:sw=4 + * vim:expandtab + */ diff --git a/xen/kdb/x86/udis86-1.7/decode.h b/xen/kdb/x86/udis86-1.7/decode.h new file mode 100644 index 0000000..b36190f --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/decode.h @@ -0,0 +1,273 @@ +#ifndef UD_DECODE_H +#define UD_DECODE_H + +#define MAX_INSN_LENGTH 15 + +/* register classes */ +#define T_NONE 0 +#define T_GPR 1 +#define T_MMX 2 +#define T_CRG 3 +#define T_DBG 4 +#define T_SEG 5 +#define T_XMM 6 + +/* itab prefix bits */ +#define P_none ( 0 ) +#define P_c1 ( 1 << 0 ) +#define P_C1(n) ( ( n >> 0 ) & 1 ) +#define P_rexb ( 1 << 1 ) +#define P_REXB(n) ( ( n >> 1 ) & 1 ) +#define P_depM ( 1 << 2 ) +#define P_DEPM(n) ( ( n >> 2 ) & 1 ) +#define P_c3 ( 1 << 3 ) +#define P_C3(n) ( ( n >> 3 ) & 1 ) +#define P_inv64 ( 1 << 4 ) +#define P_INV64(n) ( ( n >> 4 ) & 1 ) +#define P_rexw ( 1 << 5 ) +#define P_REXW(n) ( ( n >> 5 ) & 1 ) +#define P_c2 ( 1 << 6 ) +#define P_C2(n) ( ( n >> 6 ) & 1 ) +#define P_def64 ( 1 << 7 ) +#define P_DEF64(n) ( ( n >> 7 ) & 1 ) +#define P_rexr ( 1 << 8 ) +#define P_REXR(n) ( ( n >> 8 ) & 1 ) +#define P_oso ( 1 << 9 ) +#define P_OSO(n) ( ( n >> 9 ) & 1 ) +#define P_aso ( 1 << 10 ) +#define P_ASO(n) ( ( n >> 10 ) & 1 ) +#define P_rexx ( 1 << 11 ) +#define P_REXX(n) ( ( n >> 11 ) & 1 ) +#define P_ImpAddr ( 1 << 12 ) +#define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) + +/* rex prefix bits */ +#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) +#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) +#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) +#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) +#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ + ( P_REXR(n) << 2 ) | \ + ( P_REXX(n) << 1 ) | \ + ( P_REXB(n) << 0 ) ) + +/* scable-index-base bits */ +#define SIB_S(b) ( ( b ) >> 6 ) +#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) +#define SIB_B(b) ( ( b ) & 7 ) + +/* modrm bits */ +#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) +#define MODRM_RM(b) ( ( b ) & 7 ) + +/* operand type constants -- order is important! */ + +enum ud_operand_code { + OP_NONE, + + OP_A, OP_E, OP_M, OP_G, + OP_I, + + OP_AL, OP_CL, OP_DL, OP_BL, + OP_AH, OP_CH, OP_DH, OP_BH, + + OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b, + OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b, + + OP_AX, OP_CX, OP_DX, OP_BX, + OP_SI, OP_DI, OP_SP, OP_BP, + + OP_rAX, OP_rCX, OP_rDX, OP_rBX, + OP_rSP, OP_rBP, OP_rSI, OP_rDI, + + OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11, + OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15, + + OP_eAX, OP_eCX, OP_eDX, OP_eBX, + OP_eSP, OP_eBP, OP_eSI, OP_eDI, + + OP_ES, OP_CS, OP_SS, OP_DS, + OP_FS, OP_GS, + + OP_ST0, OP_ST1, OP_ST2, OP_ST3, + OP_ST4, OP_ST5, OP_ST6, OP_ST7, + + OP_J, OP_S, OP_O, + OP_I1, OP_I3, + + OP_V, OP_W, OP_Q, OP_P, + + OP_R, OP_C, OP_D, OP_VR, OP_PR +}; + + +/* operand size constants */ + +enum ud_operand_size { + SZ_NA = 0, + SZ_Z = 1, + SZ_V = 2, + SZ_P = 3, + SZ_WP = 4, + SZ_DP = 5, + SZ_MDQ = 6, + SZ_RDQ = 7, + + /* the following values are used as is, + * and thus hard-coded. changing them + * will break internals + */ + SZ_B = 8, + SZ_W = 16, + SZ_D = 32, + SZ_Q = 64, + SZ_T = 80, +}; + +/* itab entry operand definitions */ + +#define O_rSPr12 { OP_rSPr12, SZ_NA } +#define O_BL { OP_BL, SZ_NA } +#define O_BH { OP_BH, SZ_NA } +#define O_BP { OP_BP, SZ_NA } +#define O_AHr12b { OP_AHr12b, SZ_NA } +#define O_BX { OP_BX, SZ_NA } +#define O_Jz { OP_J, SZ_Z } +#define O_Jv { OP_J, SZ_V } +#define O_Jb { OP_J, SZ_B } +#define O_rSIr14 { OP_rSIr14, SZ_NA } +#define O_GS { OP_GS, SZ_NA } +#define O_D { OP_D, SZ_NA } +#define O_rBPr13 { OP_rBPr13, SZ_NA } +#define O_Ob { OP_O, SZ_B } +#define O_P { OP_P, SZ_NA } +#define O_Ow { OP_O, SZ_W } +#define O_Ov { OP_O, SZ_V } +#define O_Gw { OP_G, SZ_W } +#define O_Gv { OP_G, SZ_V } +#define O_rDX { OP_rDX, SZ_NA } +#define O_Gx { OP_G, SZ_MDQ } +#define O_Gd { OP_G, SZ_D } +#define O_Gb { OP_G, SZ_B } +#define O_rBXr11 { OP_rBXr11, SZ_NA } +#define O_rDI { OP_rDI, SZ_NA } +#define O_rSI { OP_rSI, SZ_NA } +#define O_ALr8b { OP_ALr8b, SZ_NA } +#define O_eDI { OP_eDI, SZ_NA } +#define O_Gz { OP_G, SZ_Z } +#define O_eDX { OP_eDX, SZ_NA } +#define O_DHr14b { OP_DHr14b, SZ_NA } +#define O_rSP { OP_rSP, SZ_NA } +#define O_PR { OP_PR, SZ_NA } +#define O_NONE { OP_NONE, SZ_NA } +#define O_rCX { OP_rCX, SZ_NA } +#define O_jWP { OP_J, SZ_WP } +#define O_rDXr10 { OP_rDXr10, SZ_NA } +#define O_Md { OP_M, SZ_D } +#define O_C { OP_C, SZ_NA } +#define O_G { OP_G, SZ_NA } +#define O_Mb { OP_M, SZ_B } +#define O_Mt { OP_M, SZ_T } +#define O_S { OP_S, SZ_NA } +#define O_Mq { OP_M, SZ_Q } +#define O_W { OP_W, SZ_NA } +#define O_ES { OP_ES, SZ_NA } +#define O_rBX { OP_rBX, SZ_NA } +#define O_Ed { OP_E, SZ_D } +#define O_DLr10b { OP_DLr10b, SZ_NA } +#define O_Mw { OP_M, SZ_W } +#define O_Eb { OP_E, SZ_B } +#define O_Ex { OP_E, SZ_MDQ } +#define O_Ez { OP_E, SZ_Z } +#define O_Ew { OP_E, SZ_W } +#define O_Ev { OP_E, SZ_V } +#define O_Ep { OP_E, SZ_P } +#define O_FS { OP_FS, SZ_NA } +#define O_Ms { OP_M, SZ_W } +#define O_rAXr8 { OP_rAXr8, SZ_NA } +#define O_eBP { OP_eBP, SZ_NA } +#define O_Isb { OP_I, SZ_SB } +#define O_eBX { OP_eBX, SZ_NA } +#define O_rCXr9 { OP_rCXr9, SZ_NA } +#define O_jDP { OP_J, SZ_DP } +#define O_CH { OP_CH, SZ_NA } +#define O_CL { OP_CL, SZ_NA } +#define O_R { OP_R, SZ_RDQ } +#define O_V { OP_V, SZ_NA } +#define O_CS { OP_CS, SZ_NA } +#define O_CHr13b { OP_CHr13b, SZ_NA } +#define O_eCX { OP_eCX, SZ_NA } +#define O_eSP { OP_eSP, SZ_NA } +#define O_SS { OP_SS, SZ_NA } +#define O_SP { OP_SP, SZ_NA } +#define O_BLr11b { OP_BLr11b, SZ_NA } +#define O_SI { OP_SI, SZ_NA } +#define O_eSI { OP_eSI, SZ_NA } +#define O_DL { OP_DL, SZ_NA } +#define O_DH { OP_DH, SZ_NA } +#define O_DI { OP_DI, SZ_NA } +#define O_DX { OP_DX, SZ_NA } +#define O_rBP { OP_rBP, SZ_NA } +#define O_Gvw { OP_G, SZ_MDQ } +#define O_I1 { OP_I1, SZ_NA } +#define O_I3 { OP_I3, SZ_NA } +#define O_DS { OP_DS, SZ_NA } +#define O_ST4 { OP_ST4, SZ_NA } +#define O_ST5 { OP_ST5, SZ_NA } +#define O_ST6 { OP_ST6, SZ_NA } +#define O_ST7 { OP_ST7, SZ_NA } +#define O_ST0 { OP_ST0, SZ_NA } +#define O_ST1 { OP_ST1, SZ_NA } +#define O_ST2 { OP_ST2, SZ_NA } +#define O_ST3 { OP_ST3, SZ_NA } +#define O_E { OP_E, SZ_NA } +#define O_AH { OP_AH, SZ_NA } +#define O_M { OP_M, SZ_NA } +#define O_AL { OP_AL, SZ_NA } +#define O_CLr9b { OP_CLr9b, SZ_NA } +#define O_Q { OP_Q, SZ_NA } +#define O_eAX { OP_eAX, SZ_NA } +#define O_VR { OP_VR, SZ_NA } +#define O_AX { OP_AX, SZ_NA } +#define O_rAX { OP_rAX, SZ_NA } +#define O_Iz { OP_I, SZ_Z } +#define O_rDIr15 { OP_rDIr15, SZ_NA } +#define O_Iw { OP_I, SZ_W } +#define O_Iv { OP_I, SZ_V } +#define O_Ap { OP_A, SZ_P } +#define O_CX { OP_CX, SZ_NA } +#define O_Ib { OP_I, SZ_B } +#define O_BHr15b { OP_BHr15b, SZ_NA } + + +/* A single operand of an entry in the instruction table. + * (internal use only) + */ +struct ud_itab_entry_operand +{ + enum ud_operand_code type; + enum ud_operand_size size; +}; + + +/* A single entry in an instruction table. + *(internal use only) + */ +struct ud_itab_entry +{ + enum ud_mnemonic_code mnemonic; + struct ud_itab_entry_operand operand1; + struct ud_itab_entry_operand operand2; + struct ud_itab_entry_operand operand3; + uint32_t prefix; +}; + +#endif /* UD_DECODE_H */ + +/* vim:cindent + * vim:expandtab + * vim:ts=4 + * vim:sw=4 + */ diff --git a/xen/kdb/x86/udis86-1.7/extern.h b/xen/kdb/x86/udis86-1.7/extern.h new file mode 100644 index 0000000..a8514ea --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/extern.h @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------------- + * extern.h + * + * Copyright (c) 2004, 2005, 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ +#ifndef UD_EXTERN_H +#define UD_EXTERN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* #include */ +#include "types.h" + +/* ============================= PUBLIC API ================================= */ + +extern void ud_init(struct ud*); + +extern void ud_set_mode(struct ud*, uint8_t); + +extern void ud_set_pc(struct ud*, uint64_t); + +extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); + +extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t); + +#ifndef __UD_STANDALONE__ +extern void ud_set_input_file(struct ud*, FILE*); +#endif /* __UD_STANDALONE__ */ + +extern void ud_set_vendor(struct ud*, unsigned); + +extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); + +extern void ud_input_skip(struct ud*, size_t); + +extern int ud_input_end(struct ud*); + +extern unsigned int ud_decode(struct ud*); + +extern unsigned int ud_disassemble(struct ud*); + +extern void ud_translate_intel(struct ud*); + +extern void ud_translate_att(struct ud*); + +extern char* ud_insn_asm(struct ud* u); + +extern uint8_t* ud_insn_ptr(struct ud* u); + +extern uint64_t ud_insn_off(struct ud*); + +extern char* ud_insn_hex(struct ud*); + +extern unsigned int ud_insn_len(struct ud* u); + +extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); + +/* ========================================================================== */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/xen/kdb/x86/udis86-1.7/input.c b/xen/kdb/x86/udis86-1.7/input.c new file mode 100644 index 0000000..cab612b --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/input.c @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------------- + * input.c + * + * Copyright (c) 2004, 2005, 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ +#include "extern.h" +#include "types.h" +#include "input.h" + +/* ----------------------------------------------------------------------------- + * inp_buff_hook() - Hook for buffered inputs. + * ----------------------------------------------------------------------------- + */ +static int +inp_buff_hook(struct ud* u) +{ + if (u->inp_buff < u->inp_buff_end) + return *u->inp_buff++; + else return -1; +} + +#ifndef __UD_STANDALONE__ +/* ----------------------------------------------------------------------------- + * inp_file_hook() - Hook for FILE inputs. + * ----------------------------------------------------------------------------- + */ +static int +inp_file_hook(struct ud* u) +{ + return fgetc(u->inp_file); +} +#endif /* __UD_STANDALONE__*/ + +/* ============================================================================= + * ud_inp_set_hook() - Sets input hook. + * ============================================================================= + */ +extern void +ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) +{ + u->inp_hook = hook; + inp_init(u); +} + +/* ============================================================================= + * ud_inp_set_buffer() - Set buffer as input. + * ============================================================================= + */ +extern void +ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len) +{ + u->inp_hook = inp_buff_hook; + u->inp_buff = buf; + u->inp_buff_end = buf + len; + inp_init(u); +} + +#ifndef __UD_STANDALONE__ +/* ============================================================================= + * ud_input_set_file() - Set buffer as input. + * ============================================================================= + */ +extern void +ud_set_input_file(register struct ud* u, FILE* f) +{ + u->inp_hook = inp_file_hook; + u->inp_file = f; + inp_init(u); +} +#endif /* __UD_STANDALONE__ */ + +/* ============================================================================= + * ud_input_skip() - Skip n input bytes. + * ============================================================================= + */ +extern void +ud_input_skip(struct ud* u, size_t n) +{ + while (n--) { + u->inp_hook(u); + } +} + +/* ============================================================================= + * ud_input_end() - Test for end of input. + * ============================================================================= + */ +extern int +ud_input_end(struct ud* u) +{ + return (u->inp_curr == u->inp_fill) && u->inp_end; +} + +/* ----------------------------------------------------------------------------- + * inp_next() - Loads and returns the next byte from input. + * + * inp_curr and inp_fill are pointers to the cache. The program is written based + * on the property that they are 8-bits in size, and will eventually wrap around + * forming a circular buffer. So, the size of the cache is 256 in size, kind of + * unnecessary yet optimized. + * + * A buffer inp_sess stores the bytes disassembled for a single session. + * ----------------------------------------------------------------------------- + */ +extern uint8_t inp_next(struct ud* u) +{ + int c = -1; + /* if current pointer is not upto the fill point in the + * input cache. + */ + if ( u->inp_curr != u->inp_fill ) { + c = u->inp_cache[ ++u->inp_curr ]; + /* if !end-of-input, call the input hook and get a byte */ + } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) { + /* end-of-input, mark it as an error, since the decoder, + * expected a byte more. + */ + u->error = 1; + /* flag end of input */ + u->inp_end = 1; + return 0; + } else { + /* increment pointers, we have a new byte. */ + u->inp_curr = ++u->inp_fill; + /* add the byte to the cache */ + u->inp_cache[ u->inp_fill ] = c; + } + /* record bytes input per decode-session. */ + u->inp_sess[ u->inp_ctr++ ] = c; + /* return byte */ + return ( uint8_t ) c; +} + +/* ----------------------------------------------------------------------------- + * inp_back() - Move back a single byte in the stream. + * ----------------------------------------------------------------------------- + */ +extern void +inp_back(struct ud* u) +{ + if ( u->inp_ctr > 0 ) { + --u->inp_curr; + --u->inp_ctr; + } +} + +/* ----------------------------------------------------------------------------- + * inp_peek() - Peek into the next byte in source. + * ----------------------------------------------------------------------------- + */ +extern uint8_t +inp_peek(struct ud* u) +{ + uint8_t r = inp_next(u); + if ( !u->error ) inp_back(u); /* Don't backup if there was an error */ + return r; +} + +/* ----------------------------------------------------------------------------- + * inp_move() - Move ahead n input bytes. + * ----------------------------------------------------------------------------- + */ +extern void +inp_move(struct ud* u, size_t n) +{ + while (n--) + inp_next(u); +} + +/*------------------------------------------------------------------------------ + * inp_uintN() - return uintN from source. + *------------------------------------------------------------------------------ + */ +extern uint8_t +inp_uint8(struct ud* u) +{ + return inp_next(u); +} + +extern uint16_t +inp_uint16(struct ud* u) +{ + uint16_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + return ret | (r << 8); +} + +extern uint32_t +inp_uint32(struct ud* u) +{ + uint32_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + return ret | (r << 24); +} + +extern uint64_t +inp_uint64(struct ud* u) +{ + uint64_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + ret = ret | (r << 24); + r = inp_next(u); + ret = ret | (r << 32); + r = inp_next(u); + ret = ret | (r << 40); + r = inp_next(u); + ret = ret | (r << 48); + r = inp_next(u); + return ret | (r << 56); +} diff --git a/xen/kdb/x86/udis86-1.7/input.h b/xen/kdb/x86/udis86-1.7/input.h new file mode 100644 index 0000000..217e768 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/input.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + * input.h + * + * Copyright (c) 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ +#ifndef UD_INPUT_H +#define UD_INPUT_H + +#include "types.h" + +uint8_t inp_next(struct ud*); +uint8_t inp_peek(struct ud*); +uint8_t inp_uint8(struct ud*); +uint16_t inp_uint16(struct ud*); +uint32_t inp_uint32(struct ud*); +uint64_t inp_uint64(struct ud*); +void inp_move(struct ud*, size_t); +void inp_back(struct ud*); + +/* inp_init() - Initializes the input system. */ +#define inp_init(u) \ +do { \ + u->inp_curr = 0; \ + u->inp_fill = 0; \ + u->inp_ctr = 0; \ + u->inp_end = 0; \ +} while (0) + +/* inp_start() - Should be called before each de-code operation. */ +#define inp_start(u) u->inp_ctr = 0 + +/* inp_back() - Resets the current pointer to its position before the current + * instruction disassembly was started. + */ +#define inp_reset(u) \ +do { \ + u->inp_curr -= u->inp_ctr; \ + u->inp_ctr = 0; \ +} while (0) + +/* inp_sess() - Returns the pointer to current session. */ +#define inp_sess(u) (u->inp_sess) + +/* inp_cur() - Returns the current input byte. */ +#define inp_curr(u) ((u)->inp_cache[(u)->inp_curr]) + +#endif diff --git a/xen/kdb/x86/udis86-1.7/itab.c b/xen/kdb/x86/udis86-1.7/itab.c new file mode 100644 index 0000000..52dc577 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/itab.c @@ -0,0 +1,3668 @@ + +/* itab.c -- auto generated by opgen.py, do not edit. */ + +#include "types.h" +#include "decode.h" +#include "itab.h" + +const char * ud_mnemonics_str[] = { + "3dnow", + "aaa", + "aad", + "aam", + "aas", + "adc", + "add", + "addpd", + "addps", + "addsd", + "addss", + "addsubpd", + "addsubps", + "and", + "andpd", + "andps", + "andnpd", + "andnps", + "arpl", + "movsxd", + "bound", + "bsf", + "bsr", + "bswap", + "bt", + "btc", + "btr", + "bts", + "call", + "cbw", + "cwde", + "cdqe", + "clc", + "cld", + "clflush", + "clgi", + "cli", + "clts", + "cmc", + "cmovo", + "cmovno", + "cmovb", + "cmovae", + "cmovz", + "cmovnz", + "cmovbe", + "cmova", + "cmovs", + "cmovns", + "cmovp", + "cmovnp", + "cmovl", + "cmovge", + "cmovle", + "cmovg", + "cmp", + "cmppd", + "cmpps", + "cmpsb", + "cmpsw", + "cmpsd", + "cmpsq", + "cmpss", + "cmpxchg", + "cmpxchg8b", + "comisd", + "comiss", + "cpuid", + "cvtdq2pd", + "cvtdq2ps", + "cvtpd2dq", + "cvtpd2pi", + "cvtpd2ps", + "cvtpi2ps", + "cvtpi2pd", + "cvtps2dq", + "cvtps2pi", + "cvtps2pd", + "cvtsd2si", + "cvtsd2ss", + "cvtsi2ss", + "cvtss2si", + "cvtss2sd", + "cvttpd2pi", + "cvttpd2dq", + "cvttps2dq", + "cvttps2pi", + "cvttsd2si", + "cvtsi2sd", + "cvttss2si", + "cwd", + "cdq", + "cqo", + "daa", + "das", + "dec", + "div", + "divpd", + "divps", + "divsd", + "divss", + "emms", + "enter", + "f2xm1", + "fabs", + "fadd", + "faddp", + "fbld", + "fbstp", + "fchs", + "fclex", + "fcmovb", + "fcmove", + "fcmovbe", + "fcmovu", + "fcmovnb", + "fcmovne", + "fcmovnbe", + "fcmovnu", + "fucomi", + "fcom", + "fcom2", + "fcomp3", + "fcomi", + "fucomip", + "fcomip", + "fcomp", + "fcomp5", + "fcompp", + "fcos", + "fdecstp", + "fdiv", + "fdivp", + "fdivr", + "fdivrp", + "femms", + "ffree", + "ffreep", + "ficom", + "ficomp", + "fild", + "fncstp", + "fninit", + "fiadd", + "fidivr", + "fidiv", + "fisub", + "fisubr", + "fist", + "fistp", + "fisttp", + "fld", + "fld1", + "fldl2t", + "fldl2e", + "fldlpi", + "fldlg2", + "fldln2", + "fldz", + "fldcw", + "fldenv", + "fmul", + "fmulp", + "fimul", + "fnop", + "fpatan", + "fprem", + "fprem1", + "fptan", + "frndint", + "frstor", + "fnsave", + "fscale", + "fsin", + "fsincos", + "fsqrt", + "fstp", + "fstp1", + "fstp8", + "fstp9", + "fst", + "fnstcw", + "fnstenv", + "fnstsw", + "fsub", + "fsubp", + "fsubr", + "fsubrp", + "ftst", + "fucom", + "fucomp", + "fucompp", + "fxam", + "fxch", + "fxch4", + "fxch7", + "fxrstor", + "fxsave", + "fpxtract", + "fyl2x", + "fyl2xp1", + "haddpd", + "haddps", + "hlt", + "hsubpd", + "hsubps", + "idiv", + "in", + "imul", + "inc", + "insb", + "insw", + "insd", + "int1", + "int3", + "int", + "into", + "invd", + "invlpg", + "invlpga", + "iretw", + "iretd", + "iretq", + "jo", + "jno", + "jb", + "jae", + "jz", + "jnz", + "jbe", + "ja", + "js", + "jns", + "jp", + "jnp", + "jl", + "jge", + "jle", + "jg", + "jcxz", + "jecxz", + "jrcxz", + "jmp", + "lahf", + "lar", + "lddqu", + "ldmxcsr", + "lds", + "lea", + "les", + "lfs", + "lgs", + "lidt", + "lss", + "leave", + "lfence", + "lgdt", + "lldt", + "lmsw", + "lock", + "lodsb", + "lodsw", + "lodsd", + "lodsq", + "loopnz", + "loope", + "loop", + "lsl", + "ltr", + "maskmovq", + "maxpd", + "maxps", + "maxsd", + "maxss", + "mfence", + "minpd", + "minps", + "minsd", + "minss", + "monitor", + "mov", + "movapd", + "movaps", + "movd", + "movddup", + "movdqa", + "movdqu", + "movdq2q", + "movhpd", + "movhps", + "movlhps", + "movlpd", + "movlps", + "movhlps", + "movmskpd", + "movmskps", + "movntdq", + "movnti", + "movntpd", + "movntps", + "movntq", + "movq", + "movqa", + "movq2dq", + "movsb", + "movsw", + "movsd", + "movsq", + "movsldup", + "movshdup", + "movss", + "movsx", + "movupd", + "movups", + "movzx", + "mul", + "mulpd", + "mulps", + "mulsd", + "mulss", + "mwait", + "neg", + "nop", + "not", + "or", + "orpd", + "orps", + "out", + "outsb", + "outsw", + "outsd", + "outsq", + "packsswb", + "packssdw", + "packuswb", + "paddb", + "paddw", + "paddq", + "paddsb", + "paddsw", + "paddusb", + "paddusw", + "pand", + "pandn", + "pause", + "pavgb", + "pavgw", + "pcmpeqb", + "pcmpeqw", + "pcmpeqd", + "pcmpgtb", + "pcmpgtw", + "pcmpgtd", + "pextrw", + "pinsrw", + "pmaddwd", + "pmaxsw", + "pmaxub", + "pminsw", + "pminub", + "pmovmskb", + "pmulhuw", + "pmulhw", + "pmullw", + "pmuludq", + "pop", + "popa", + "popad", + "popfw", + "popfd", + "popfq", + "por", + "prefetch", + "prefetchnta", + "prefetcht0", + "prefetcht1", + "prefetcht2", + "psadbw", + "pshufd", + "pshufhw", + "pshuflw", + "pshufw", + "pslldq", + "psllw", + "pslld", + "psllq", + "psraw", + "psrad", + "psrlw", + "psrld", + "psrlq", + "psrldq", + "psubb", + "psubw", + "psubd", + "psubq", + "psubsb", + "psubsw", + "psubusb", + "psubusw", + "punpckhbw", + "punpckhwd", + "punpckhdq", + "punpckhqdq", + "punpcklbw", + "punpcklwd", + "punpckldq", + "punpcklqdq", + "pi2fw", + "pi2fd", + "pf2iw", + "pf2id", + "pfnacc", + "pfpnacc", + "pfcmpge", + "pfmin", + "pfrcp", + "pfrsqrt", + "pfsub", + "pfadd", + "pfcmpgt", + "pfmax", + "pfrcpit1", + "pfrspit1", + "pfsubr", + "pfacc", + "pfcmpeq", + "pfmul", + "pfrcpit2", + "pmulhrw", + "pswapd", + "pavgusb", + "push", + "pusha", + "pushad", + "pushfw", + "pushfd", + "pushfq", + "pxor", + "rcl", + "rcr", + "rol", + "ror", + "rcpps", + "rcpss", + "rdmsr", + "rdpmc", + "rdtsc", + "rdtscp", + "repne", + "rep", + "ret", + "retf", + "rsm", + "rsqrtps", + "rsqrtss", + "sahf", + "sal", + "salc", + "sar", + "shl", + "shr", + "sbb", + "scasb", + "scasw", + "scasd", + "scasq", + "seto", + "setno", + "setb", + "setnb", + "setz", + "setnz", + "setbe", + "seta", + "sets", + "setns", + "setp", + "setnp", + "setl", + "setge", + "setle", + "setg", + "sfence", + "sgdt", + "shld", + "shrd", + "shufpd", + "shufps", + "sidt", + "sldt", + "smsw", + "sqrtps", + "sqrtpd", + "sqrtsd", + "sqrtss", + "stc", + "std", + "stgi", + "sti", + "skinit", + "stmxcsr", + "stosb", + "stosw", + "stosd", + "stosq", + "str", + "sub", + "subpd", + "subps", + "subsd", + "subss", + "swapgs", + "syscall", + "sysenter", + "sysexit", + "sysret", + "test", + "ucomisd", + "ucomiss", + "ud2", + "unpckhpd", + "unpckhps", + "unpcklps", + "unpcklpd", + "verr", + "verw", + "vmcall", + "vmclear", + "vmxon", + "vmptrld", + "vmptrst", + "vmresume", + "vmxoff", + "vmrun", + "vmmcall", + "vmload", + "vmsave", + "wait", + "wbinvd", + "wrmsr", + "xadd", + "xchg", + "xlatb", + "xor", + "xorpd", + "xorps", + "db", + "invalid", +}; + + + +static struct ud_itab_entry itab__0f[256] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_00__REG }, + /* 01 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG }, + /* 02 */ { UD_Ilar, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ilsl, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Isyscall, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iclts, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Isysret, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvd, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iwbinvd, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iud2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_0D__REG }, + /* 0E */ { UD_Ifemms, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Imovups, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 11 */ { UD_Imovups, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 12 */ { UD_Imovlps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 13 */ { UD_Imovlps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 14 */ { UD_Iunpcklps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 15 */ { UD_Iunpckhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 16 */ { UD_Imovhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 17 */ { UD_Imovhps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 18 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_18__REG }, + /* 19 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1A */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1B */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1C */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1D */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1E */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1F */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 20 */ { UD_Imov, O_R, O_C, O_NONE, P_rexr }, + /* 21 */ { UD_Imov, O_R, O_D, O_NONE, P_rexr }, + /* 22 */ { UD_Imov, O_C, O_R, O_NONE, P_rexr }, + /* 23 */ { UD_Imov, O_D, O_R, O_NONE, P_rexr }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Imovaps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 29 */ { UD_Imovaps, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2A */ { UD_Icvtpi2ps, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2B */ { UD_Imovntps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2C */ { UD_Icvttps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2D */ { UD_Icvtps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2E */ { UD_Iucomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2F */ { UD_Icomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 30 */ { UD_Iwrmsr, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Irdtsc, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Irdmsr, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Irdpmc, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* 35 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 40 */ { UD_Icmovo, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 41 */ { UD_Icmovno, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 42 */ { UD_Icmovb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 43 */ { UD_Icmovae, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 44 */ { UD_Icmovz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 45 */ { UD_Icmovnz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 46 */ { UD_Icmovbe, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 47 */ { UD_Icmova, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 48 */ { UD_Icmovs, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 49 */ { UD_Icmovns, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4A */ { UD_Icmovp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4B */ { UD_Icmovnp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4C */ { UD_Icmovl, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4D */ { UD_Icmovge, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4E */ { UD_Icmovle, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 4F */ { UD_Icmovg, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 50 */ { UD_Imovmskps, O_Gd, O_VR, O_NONE, P_oso|P_rexr|P_rexb }, + /* 51 */ { UD_Isqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 52 */ { UD_Irsqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 53 */ { UD_Ircpps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 54 */ { UD_Iandps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 55 */ { UD_Iandnps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 56 */ { UD_Iorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 57 */ { UD_Ixorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 58 */ { UD_Iaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 59 */ { UD_Imulps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5A */ { UD_Icvtps2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5B */ { UD_Icvtdq2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5C */ { UD_Isubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5D */ { UD_Iminps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5E */ { UD_Idivps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5F */ { UD_Imaxps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 60 */ { UD_Ipunpcklbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 61 */ { UD_Ipunpcklwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 62 */ { UD_Ipunpckldq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 63 */ { UD_Ipacksswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 64 */ { UD_Ipcmpgtb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 65 */ { UD_Ipcmpgtw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 66 */ { UD_Ipcmpgtd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 67 */ { UD_Ipackuswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 68 */ { UD_Ipunpckhbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 69 */ { UD_Ipunpckhwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6A */ { UD_Ipunpckhdq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6B */ { UD_Ipackssdw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6E */ { UD_Imovd, O_P, O_Ex, O_NONE, P_c2|P_aso|P_rexr|P_rexx|P_rexb }, + /* 6F */ { UD_Imovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 70 */ { UD_Ipshufw, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 71 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_71__REG }, + /* 72 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_72__REG }, + /* 73 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_73__REG }, + /* 74 */ { UD_Ipcmpeqb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 75 */ { UD_Ipcmpeqw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 76 */ { UD_Ipcmpeqd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 77 */ { UD_Iemms, O_NONE, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7E */ { UD_Imovd, O_Ex, O_P, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 7F */ { UD_Imovq, O_Q, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 80 */ { UD_Ijo, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 81 */ { UD_Ijno, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 82 */ { UD_Ijb, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 83 */ { UD_Ijae, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 84 */ { UD_Ijz, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 85 */ { UD_Ijnz, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 86 */ { UD_Ijbe, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 87 */ { UD_Ija, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 88 */ { UD_Ijs, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 89 */ { UD_Ijns, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8A */ { UD_Ijp, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8B */ { UD_Ijnp, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8C */ { UD_Ijl, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8D */ { UD_Ijge, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8E */ { UD_Ijle, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 8F */ { UD_Ijg, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, + /* 90 */ { UD_Iseto, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 91 */ { UD_Isetno, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 92 */ { UD_Isetb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 93 */ { UD_Isetnb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 94 */ { UD_Isetz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 95 */ { UD_Isetnz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 96 */ { UD_Isetbe, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 97 */ { UD_Iseta, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 98 */ { UD_Isets, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 99 */ { UD_Isetns, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9A */ { UD_Isetp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9B */ { UD_Isetnp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9C */ { UD_Isetl, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9D */ { UD_Isetge, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9E */ { UD_Isetle, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 9F */ { UD_Isetg, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* A0 */ { UD_Ipush, O_FS, O_NONE, O_NONE, P_none }, + /* A1 */ { UD_Ipop, O_FS, O_NONE, O_NONE, P_none }, + /* A2 */ { UD_Icpuid, O_NONE, O_NONE, O_NONE, P_none }, + /* A3 */ { UD_Ibt, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* A4 */ { UD_Ishld, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* A5 */ { UD_Ishld, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A8 */ { UD_Ipush, O_GS, O_NONE, O_NONE, P_none }, + /* A9 */ { UD_Ipop, O_GS, O_NONE, O_NONE, P_none }, + /* AA */ { UD_Irsm, O_NONE, O_NONE, O_NONE, P_none }, + /* AB */ { UD_Ibts, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* AC */ { UD_Ishrd, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* AD */ { UD_Ishrd, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* AE */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG }, + /* AF */ { UD_Iimul, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B0 */ { UD_Icmpxchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* B1 */ { UD_Icmpxchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B2 */ { UD_Ilss, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B3 */ { UD_Ibtr, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B4 */ { UD_Ilfs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B5 */ { UD_Ilgs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B6 */ { UD_Imovzx, O_Gv, O_Eb, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B7 */ { UD_Imovzx, O_Gv, O_Ew, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BA */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_BA__REG }, + /* BB */ { UD_Ibtc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* BC */ { UD_Ibsf, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* BD */ { UD_Ibsr, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* BE */ { UD_Imovsx, O_Gv, O_Eb, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* BF */ { UD_Imovsx, O_Gv, O_Ew, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C2 */ { UD_Icmpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C3 */ { UD_Imovnti, O_M, O_Gvw, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C4 */ { UD_Ipinsrw, O_P, O_Ew, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C5 */ { UD_Ipextrw, O_Gd, O_PR, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C6 */ { UD_Ishufps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG }, + /* C8 */ { UD_Ibswap, O_rAXr8, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* C9 */ { UD_Ibswap, O_rCXr9, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CA */ { UD_Ibswap, O_rDXr10, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CB */ { UD_Ibswap, O_rBXr11, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CC */ { UD_Ibswap, O_rSPr12, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CD */ { UD_Ibswap, O_rBPr13, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CE */ { UD_Ibswap, O_rSIr14, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* CF */ { UD_Ibswap, O_rDIr15, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D1 */ { UD_Ipsrlw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D2 */ { UD_Ipsrld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D3 */ { UD_Ipsrlq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D4 */ { UD_Ipaddq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D5 */ { UD_Ipmullw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D7 */ { UD_Ipmovmskb, O_Gd, O_PR, O_NONE, P_oso|P_rexr|P_rexb }, + /* D8 */ { UD_Ipsubusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D9 */ { UD_Ipsubusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DA */ { UD_Ipminub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DB */ { UD_Ipand, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DC */ { UD_Ipaddusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DD */ { UD_Ipaddusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DE */ { UD_Ipmaxub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DF */ { UD_Ipandn, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E0 */ { UD_Ipavgb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E1 */ { UD_Ipsraw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E2 */ { UD_Ipsrad, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E3 */ { UD_Ipavgw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E4 */ { UD_Ipmulhuw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E5 */ { UD_Ipmulhw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E7 */ { UD_Imovntq, O_M, O_P, O_NONE, P_none }, + /* E8 */ { UD_Ipsubsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E9 */ { UD_Ipsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EA */ { UD_Ipminsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EB */ { UD_Ipor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EC */ { UD_Ipaddsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* ED */ { UD_Ipaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EE */ { UD_Ipmaxsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EF */ { UD_Ipxor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F1 */ { UD_Ipsllw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F2 */ { UD_Ipslld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F3 */ { UD_Ipsllq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F4 */ { UD_Ipmuludq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F5 */ { UD_Ipmaddwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F6 */ { UD_Ipsadbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F7 */ { UD_Imaskmovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F8 */ { UD_Ipsubb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F9 */ { UD_Ipsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FA */ { UD_Ipsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FB */ { UD_Ipsubq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FC */ { UD_Ipaddb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FD */ { UD_Ipaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_00__reg[8] = { + /* 00 */ { UD_Isldt, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Istr, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Illdt, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Iltr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iverr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Iverw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg[8] = { + /* 00 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD }, + /* 01 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_01__MOD }, + /* 02 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_02__MOD }, + /* 03 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD }, + /* 04 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_04__MOD }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_06__MOD }, + /* 07 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod[2] = { + /* 00 */ { UD_Isgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR }, + /* 04 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_01__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_03__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_04__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_01__mod[2] = { + /* 00 */ { UD_Isidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_01__mod__op_01__rm[8] = { + /* 00 */ { UD_Imonitor, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Imwait, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_02__mod[2] = { + /* 00 */ { UD_Ilgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod[2] = { + /* 00 */ { UD_Ilidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm[8] = { + /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR }, + /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR }, + /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR }, + /* 03 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR }, + /* 04 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR }, + /* 05 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR }, + /* 06 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR }, + /* 07 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_00__vendor[2] = { + /* 00 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_01__vendor[2] = { + /* 00 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_02__vendor[2] = { + /* 00 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_03__vendor[2] = { + /* 00 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_04__vendor[2] = { + /* 00 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_05__vendor[2] = { + /* 00 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_06__vendor[2] = { + /* 00 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_07__vendor[2] = { + /* 00 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_04__mod[2] = { + /* 00 */ { UD_Ismsw, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_06__mod[2] = { + /* 00 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod[2] = { + /* 00 */ { UD_Iinvlpg, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod__op_01__rm[8] = { + /* 00 */ { UD_Iswapgs, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod__op_01__rm__op_01__vendor[2] = { + /* 00 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_0d__reg[8] = { + /* 00 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__0f__op_18__reg[8] = { + /* 00 */ { UD_Iprefetchnta, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iprefetcht0, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iprefetcht1, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Iprefetcht2, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_71__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrlw, O_PR, O_Ib, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ipsraw, O_PR, O_Ib, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipsllw, O_PR, O_Ib, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_72__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrld, O_PR, O_Ib, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ipsrad, O_PR, O_Ib, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipslld, O_PR, O_Ib, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_73__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrlq, O_PR, O_Ib, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipsllq, O_PR, O_Ib, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ildmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Istmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_05__MOD }, + /* 06 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_06__MOD }, + /* 07 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_07__MOD }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_05__mod[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_05__mod__op_01__rm[8] = { + /* 00 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_06__mod[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_06__mod__op_01__rm[8] = { + /* 00 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_07__mod[2] = { + /* 00 */ { UD_Iclflush, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM }, +}; + +static struct ud_itab_entry itab__0f__op_ae__reg__op_07__mod__op_01__rm[8] = { + /* 00 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__0f__op_ba__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ibt, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ibts, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ibtr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ibtc, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__0f__op_c7__reg[8] = { + /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG__OP_00__VENDOR }, + /* 01 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG__OP_07__VENDOR }, +}; + +static struct ud_itab_entry itab__0f__op_c7__reg__op_00__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__0f__op_c7__reg__op_07__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__0f__op_d9__mod[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_D9__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__0f__op_d9__mod__op_01__x87[64] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Ifabs, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_If2xm1, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte[256] = { + /* 00 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iadd, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Iadd, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iadd, O_AL, O_Ib, O_NONE, P_none }, + /* 05 */ { UD_Iadd, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 06 */ { UD_Ipush, O_ES, O_NONE, O_NONE, P_inv64|P_none }, + /* 07 */ { UD_Ipop, O_ES, O_NONE, O_NONE, P_inv64|P_none }, + /* 08 */ { UD_Ior, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 09 */ { UD_Ior, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0A */ { UD_Ior, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0B */ { UD_Ior, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0C */ { UD_Ior, O_AL, O_Ib, O_NONE, P_none }, + /* 0D */ { UD_Ior, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 0E */ { UD_Ipush, O_CS, O_NONE, O_NONE, P_inv64|P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Iadc, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 11 */ { UD_Iadc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 12 */ { UD_Iadc, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 13 */ { UD_Iadc, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 14 */ { UD_Iadc, O_AL, O_Ib, O_NONE, P_none }, + /* 15 */ { UD_Iadc, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 16 */ { UD_Ipush, O_SS, O_NONE, O_NONE, P_inv64|P_none }, + /* 17 */ { UD_Ipop, O_SS, O_NONE, O_NONE, P_inv64|P_none }, + /* 18 */ { UD_Isbb, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 19 */ { UD_Isbb, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1A */ { UD_Isbb, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1B */ { UD_Isbb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1C */ { UD_Isbb, O_AL, O_Ib, O_NONE, P_none }, + /* 1D */ { UD_Isbb, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 1E */ { UD_Ipush, O_DS, O_NONE, O_NONE, P_inv64|P_none }, + /* 1F */ { UD_Ipop, O_DS, O_NONE, O_NONE, P_inv64|P_none }, + /* 20 */ { UD_Iand, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 21 */ { UD_Iand, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 22 */ { UD_Iand, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 23 */ { UD_Iand, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 24 */ { UD_Iand, O_AL, O_Ib, O_NONE, P_none }, + /* 25 */ { UD_Iand, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Idaa, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* 28 */ { UD_Isub, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 29 */ { UD_Isub, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 2A */ { UD_Isub, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2B */ { UD_Isub, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 2C */ { UD_Isub, O_AL, O_Ib, O_NONE, P_none }, + /* 2D */ { UD_Isub, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Idas, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* 30 */ { UD_Ixor, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 31 */ { UD_Ixor, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 32 */ { UD_Ixor, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 33 */ { UD_Ixor, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 34 */ { UD_Ixor, O_AL, O_Ib, O_NONE, P_none }, + /* 35 */ { UD_Ixor, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iaaa, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* 38 */ { UD_Icmp, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 39 */ { UD_Icmp, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 3A */ { UD_Icmp, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 3B */ { UD_Icmp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 3C */ { UD_Icmp, O_AL, O_Ib, O_NONE, P_none }, + /* 3D */ { UD_Icmp, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iaas, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* 40 */ { UD_Iinc, O_eAX, O_NONE, O_NONE, P_oso }, + /* 41 */ { UD_Iinc, O_eCX, O_NONE, O_NONE, P_oso }, + /* 42 */ { UD_Iinc, O_eDX, O_NONE, O_NONE, P_oso }, + /* 43 */ { UD_Iinc, O_eBX, O_NONE, O_NONE, P_oso }, + /* 44 */ { UD_Iinc, O_eSP, O_NONE, O_NONE, P_oso }, + /* 45 */ { UD_Iinc, O_eBP, O_NONE, O_NONE, P_oso }, + /* 46 */ { UD_Iinc, O_eSI, O_NONE, O_NONE, P_oso }, + /* 47 */ { UD_Iinc, O_eDI, O_NONE, O_NONE, P_oso }, + /* 48 */ { UD_Idec, O_eAX, O_NONE, O_NONE, P_oso }, + /* 49 */ { UD_Idec, O_eCX, O_NONE, O_NONE, P_oso }, + /* 4A */ { UD_Idec, O_eDX, O_NONE, O_NONE, P_oso }, + /* 4B */ { UD_Idec, O_eBX, O_NONE, O_NONE, P_oso }, + /* 4C */ { UD_Idec, O_eSP, O_NONE, O_NONE, P_oso }, + /* 4D */ { UD_Idec, O_eBP, O_NONE, O_NONE, P_oso }, + /* 4E */ { UD_Idec, O_eSI, O_NONE, O_NONE, P_oso }, + /* 4F */ { UD_Idec, O_eDI, O_NONE, O_NONE, P_oso }, + /* 50 */ { UD_Ipush, O_rAXr8, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 51 */ { UD_Ipush, O_rCXr9, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 52 */ { UD_Ipush, O_rDXr10, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 53 */ { UD_Ipush, O_rBXr11, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 54 */ { UD_Ipush, O_rSPr12, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 55 */ { UD_Ipush, O_rBPr13, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 56 */ { UD_Ipush, O_rSIr14, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 57 */ { UD_Ipush, O_rDIr15, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 58 */ { UD_Ipop, O_rAXr8, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 59 */ { UD_Ipop, O_rCXr9, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5A */ { UD_Ipop, O_rDXr10, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5B */ { UD_Ipop, O_rBXr11, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5C */ { UD_Ipop, O_rSPr12, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5D */ { UD_Ipop, O_rBPr13, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5E */ { UD_Ipop, O_rSIr14, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 5F */ { UD_Ipop, O_rDIr15, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, + /* 60 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_60__OSIZE }, + /* 61 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_61__OSIZE }, + /* 62 */ { UD_Ibound, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, + /* 63 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_63__MODE }, + /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 68 */ { UD_Ipush, O_Iz, O_NONE, O_NONE, P_c1|P_oso }, + /* 69 */ { UD_Iimul, O_Gv, O_Ev, O_Iz, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 6A */ { UD_Ipush, O_Ib, O_NONE, O_NONE, P_none }, + /* 6B */ { UD_Iimul, O_Gv, O_Ev, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 6C */ { UD_Iinsb, O_NONE, O_NONE, O_NONE, P_none }, + /* 6D */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_6D__OSIZE }, + /* 6E */ { UD_Ioutsb, O_NONE, O_NONE, O_NONE, P_none }, + /* 6F */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_6F__OSIZE }, + /* 70 */ { UD_Ijo, O_Jb, O_NONE, O_NONE, P_none }, + /* 71 */ { UD_Ijno, O_Jb, O_NONE, O_NONE, P_none }, + /* 72 */ { UD_Ijb, O_Jb, O_NONE, O_NONE, P_none }, + /* 73 */ { UD_Ijae, O_Jb, O_NONE, O_NONE, P_none }, + /* 74 */ { UD_Ijz, O_Jb, O_NONE, O_NONE, P_none }, + /* 75 */ { UD_Ijnz, O_Jb, O_NONE, O_NONE, P_none }, + /* 76 */ { UD_Ijbe, O_Jb, O_NONE, O_NONE, P_none }, + /* 77 */ { UD_Ija, O_Jb, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Ijs, O_Jb, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Ijns, O_Jb, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Ijp, O_Jb, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Ijnp, O_Jb, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Ijl, O_Jb, O_NONE, O_NONE, P_none }, + /* 7D */ { UD_Ijge, O_Jb, O_NONE, O_NONE, P_none }, + /* 7E */ { UD_Ijle, O_Jb, O_NONE, O_NONE, P_none }, + /* 7F */ { UD_Ijg, O_Jb, O_NONE, O_NONE, P_none }, + /* 80 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_80__REG }, + /* 81 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_81__REG }, + /* 82 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_82__REG }, + /* 83 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_83__REG }, + /* 84 */ { UD_Itest, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 85 */ { UD_Itest, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 86 */ { UD_Ixchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 87 */ { UD_Ixchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 88 */ { UD_Imov, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 89 */ { UD_Imov, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 8A */ { UD_Imov, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 8B */ { UD_Imov, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 8C */ { UD_Imov, O_Ev, O_S, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 8D */ { UD_Ilea, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 8E */ { UD_Imov, O_S, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 8F */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_8F__REG }, + /* 90 */ { UD_Ixchg, O_rAXr8, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 91 */ { UD_Ixchg, O_rCXr9, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 92 */ { UD_Ixchg, O_rDXr10, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 93 */ { UD_Ixchg, O_rBXr11, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 94 */ { UD_Ixchg, O_rSPr12, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 95 */ { UD_Ixchg, O_rBPr13, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 96 */ { UD_Ixchg, O_rSIr14, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 97 */ { UD_Ixchg, O_rDIr15, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 98 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_98__OSIZE }, + /* 99 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_99__OSIZE }, + /* 9A */ { UD_Icall, O_Ap, O_NONE, O_NONE, P_inv64|P_oso }, + /* 9B */ { UD_Iwait, O_NONE, O_NONE, O_NONE, P_none }, + /* 9C */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE }, + /* 9D */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE }, + /* 9E */ { UD_Isahf, O_NONE, O_NONE, O_NONE, P_none }, + /* 9F */ { UD_Ilahf, O_NONE, O_NONE, O_NONE, P_none }, + /* A0 */ { UD_Imov, O_AL, O_Ob, O_NONE, P_none }, + /* A1 */ { UD_Imov, O_rAX, O_Ov, O_NONE, P_aso|P_oso|P_rexw }, + /* A2 */ { UD_Imov, O_Ob, O_AL, O_NONE, P_none }, + /* A3 */ { UD_Imov, O_Ov, O_rAX, O_NONE, P_aso|P_oso|P_rexw }, + /* A4 */ { UD_Imovsb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, + /* A5 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_A5__OSIZE }, + /* A6 */ { UD_Icmpsb, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_A7__OSIZE }, + /* A8 */ { UD_Itest, O_AL, O_Ib, O_NONE, P_none }, + /* A9 */ { UD_Itest, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, + /* AA */ { UD_Istosb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, + /* AB */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AB__OSIZE }, + /* AC */ { UD_Ilodsb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, + /* AD */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AD__OSIZE }, + /* AE */ { UD_Iscasb, O_NONE, O_NONE, O_NONE, P_none }, + /* AF */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AF__OSIZE }, + /* B0 */ { UD_Imov, O_ALr8b, O_Ib, O_NONE, P_rexb }, + /* B1 */ { UD_Imov, O_CLr9b, O_Ib, O_NONE, P_rexb }, + /* B2 */ { UD_Imov, O_DLr10b, O_Ib, O_NONE, P_rexb }, + /* B3 */ { UD_Imov, O_BLr11b, O_Ib, O_NONE, P_rexb }, + /* B4 */ { UD_Imov, O_AHr12b, O_Ib, O_NONE, P_rexb }, + /* B5 */ { UD_Imov, O_CHr13b, O_Ib, O_NONE, P_rexb }, + /* B6 */ { UD_Imov, O_DHr14b, O_Ib, O_NONE, P_rexb }, + /* B7 */ { UD_Imov, O_BHr15b, O_Ib, O_NONE, P_rexb }, + /* B8 */ { UD_Imov, O_rAXr8, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* B9 */ { UD_Imov, O_rCXr9, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BA */ { UD_Imov, O_rDXr10, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BB */ { UD_Imov, O_rBXr11, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BC */ { UD_Imov, O_rSPr12, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BD */ { UD_Imov, O_rBPr13, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BE */ { UD_Imov, O_rSIr14, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* BF */ { UD_Imov, O_rDIr15, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* C0 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C0__REG }, + /* C1 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C1__REG }, + /* C2 */ { UD_Iret, O_Iw, O_NONE, O_NONE, P_none }, + /* C3 */ { UD_Iret, O_NONE, O_NONE, O_NONE, P_none }, + /* C4 */ { UD_Iles, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, + /* C5 */ { UD_Ilds, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, + /* C6 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C6__REG }, + /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C7__REG }, + /* C8 */ { UD_Ienter, O_Iw, O_Ib, O_NONE, P_def64|P_depM|P_none }, + /* C9 */ { UD_Ileave, O_NONE, O_NONE, O_NONE, P_none }, + /* CA */ { UD_Iretf, O_Iw, O_NONE, O_NONE, P_none }, + /* CB */ { UD_Iretf, O_NONE, O_NONE, O_NONE, P_none }, + /* CC */ { UD_Iint3, O_NONE, O_NONE, O_NONE, P_none }, + /* CD */ { UD_Iint, O_Ib, O_NONE, O_NONE, P_none }, + /* CE */ { UD_Iinto, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* CF */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_CF__OSIZE }, + /* D0 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D0__REG }, + /* D1 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D1__REG }, + /* D2 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D2__REG }, + /* D3 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D3__REG }, + /* D4 */ { UD_Iaam, O_Ib, O_NONE, O_NONE, P_inv64|P_none }, + /* D5 */ { UD_Iaad, O_Ib, O_NONE, O_NONE, P_inv64|P_none }, + /* D6 */ { UD_Isalc, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, + /* D7 */ { UD_Ixlatb, O_NONE, O_NONE, O_NONE, P_rexw }, + /* D8 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD }, + /* D9 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD }, + /* DA */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD }, + /* DB */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD }, + /* DC */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD }, + /* DD */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD }, + /* DE */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD }, + /* DF */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD }, + /* E0 */ { UD_Iloopnz, O_Jb, O_NONE, O_NONE, P_none }, + /* E1 */ { UD_Iloope, O_Jb, O_NONE, O_NONE, P_none }, + /* E2 */ { UD_Iloop, O_Jb, O_NONE, O_NONE, P_none }, + /* E3 */ { UD_Igrp_asize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_E3__ASIZE }, + /* E4 */ { UD_Iin, O_AL, O_Ib, O_NONE, P_none }, + /* E5 */ { UD_Iin, O_eAX, O_Ib, O_NONE, P_oso }, + /* E6 */ { UD_Iout, O_Ib, O_AL, O_NONE, P_none }, + /* E7 */ { UD_Iout, O_Ib, O_eAX, O_NONE, P_oso }, + /* E8 */ { UD_Icall, O_Jz, O_NONE, O_NONE, P_def64|P_oso }, + /* E9 */ { UD_Ijmp, O_Jz, O_NONE, O_NONE, P_def64|P_depM|P_oso }, + /* EA */ { UD_Ijmp, O_Ap, O_NONE, O_NONE, P_inv64|P_none }, + /* EB */ { UD_Ijmp, O_Jb, O_NONE, O_NONE, P_none }, + /* EC */ { UD_Iin, O_AL, O_DX, O_NONE, P_none }, + /* ED */ { UD_Iin, O_eAX, O_DX, O_NONE, P_oso }, + /* EE */ { UD_Iout, O_DX, O_AL, O_NONE, P_none }, + /* EF */ { UD_Iout, O_DX, O_eAX, O_NONE, P_oso }, + /* F0 */ { UD_Ilock, O_NONE, O_NONE, O_NONE, P_none }, + /* F1 */ { UD_Iint1, O_NONE, O_NONE, O_NONE, P_none }, + /* F2 */ { UD_Irepne, O_NONE, O_NONE, O_NONE, P_none }, + /* F3 */ { UD_Irep, O_NONE, O_NONE, O_NONE, P_none }, + /* F4 */ { UD_Ihlt, O_NONE, O_NONE, O_NONE, P_none }, + /* F5 */ { UD_Icmc, O_NONE, O_NONE, O_NONE, P_none }, + /* F6 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_F6__REG }, + /* F7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_F7__REG }, + /* F8 */ { UD_Iclc, O_NONE, O_NONE, O_NONE, P_none }, + /* F9 */ { UD_Istc, O_NONE, O_NONE, O_NONE, P_none }, + /* FA */ { UD_Icli, O_NONE, O_NONE, O_NONE, P_none }, + /* FB */ { UD_Isti, O_NONE, O_NONE, O_NONE, P_none }, + /* FC */ { UD_Icld, O_NONE, O_NONE, O_NONE, P_none }, + /* FD */ { UD_Istd, O_NONE, O_NONE, O_NONE, P_none }, + /* FE */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_FE__REG }, + /* FF */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_FF__REG }, +}; + +static struct ud_itab_entry itab__1byte__op_60__osize[3] = { + /* 00 */ { UD_Ipusha, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, + /* 01 */ { UD_Ipushad, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_61__osize[3] = { + /* 00 */ { UD_Ipopa, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, + /* 01 */ { UD_Ipopad, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_63__mode[3] = { + /* 00 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_inv64|P_aso }, + /* 01 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_inv64|P_aso }, + /* 02 */ { UD_Imovsxd, O_Gv, O_Ed, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexx|P_rexr|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_6d__osize[3] = { + /* 00 */ { UD_Iinsw, O_NONE, O_NONE, O_NONE, P_oso }, + /* 01 */ { UD_Iinsd, O_NONE, O_NONE, O_NONE, P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_6f__osize[3] = { + /* 00 */ { UD_Ioutsw, O_NONE, O_NONE, O_NONE, P_oso }, + /* 01 */ { UD_Ioutsd, O_NONE, O_NONE, O_NONE, P_oso }, + /* 02 */ { UD_Ioutsq, O_NONE, O_NONE, O_NONE, P_oso }, +}; + +static struct ud_itab_entry itab__1byte__op_80__reg[8] = { + /* 00 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_81__reg[8] = { + /* 00 */ { UD_Iadd, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ior, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iadc, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Isbb, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iand, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Isub, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ixor, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Icmp, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_82__reg[8] = { + /* 00 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_83__reg[8] = { + /* 00 */ { UD_Iadd, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ior, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iadc, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Isbb, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iand, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Isub, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ixor, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Icmp, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_8f__reg[8] = { + /* 00 */ { UD_Ipop, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_98__osize[3] = { + /* 00 */ { UD_Icbw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 01 */ { UD_Icwde, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 02 */ { UD_Icdqe, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_99__osize[3] = { + /* 00 */ { UD_Icwd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 01 */ { UD_Icdq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 02 */ { UD_Icqo, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_9c__mode[3] = { + /* 00 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE }, + /* 01 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE }, + /* 02 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_def64|P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_9c__mode__op_00__osize[3] = { + /* 00 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, + /* 01 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_9c__mode__op_01__osize[3] = { + /* 00 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, + /* 01 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_9d__mode[3] = { + /* 00 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE }, + /* 01 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE }, + /* 02 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, +}; + +static struct ud_itab_entry itab__1byte__op_9d__mode__op_00__osize[3] = { + /* 00 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, + /* 01 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_9d__mode__op_01__osize[3] = { + /* 00 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, + /* 01 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_a5__osize[3] = { + /* 00 */ { UD_Imovsw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 01 */ { UD_Imovsd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 02 */ { UD_Imovsq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_a7__osize[3] = { + /* 00 */ { UD_Icmpsw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 01 */ { UD_Icmpsd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 02 */ { UD_Icmpsq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_ab__osize[3] = { + /* 00 */ { UD_Istosw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 01 */ { UD_Istosd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 02 */ { UD_Istosq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_ad__osize[3] = { + /* 00 */ { UD_Ilodsw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 01 */ { UD_Ilodsd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, + /* 02 */ { UD_Ilodsq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_ae__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AE__MOD__OP_00__REG }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_ae__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifxsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifxrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_af__osize[3] = { + /* 00 */ { UD_Iscasw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 01 */ { UD_Iscasd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 02 */ { UD_Iscasq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_c0__reg[8] = { + /* 00 */ { UD_Irol, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_c1__reg[8] = { + /* 00 */ { UD_Irol, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_c6__reg[8] = { + /* 00 */ { UD_Imov, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_c7__reg[8] = { + /* 00 */ { UD_Imov, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_cf__osize[3] = { + /* 00 */ { UD_Iiretw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 01 */ { UD_Iiretd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 02 */ { UD_Iiretq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, +}; + +static struct ud_itab_entry itab__1byte__op_d0__reg[8] = { + /* 00 */ { UD_Irol, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d1__reg[8] = { + /* 00 */ { UD_Irol, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d2__reg[8] = { + /* 00 */ { UD_Irol, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d3__reg[8] = { + /* 00 */ { UD_Irol, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iror, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ircl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ircr, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ishr, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Isar, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d8__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_d8__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifadd, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifmul, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ifcom, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifcomp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifsub, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifsubr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifdiv, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifdivr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d8__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifadd, O_ST0, O_ST1, O_NONE, P_none }, + /* 02 */ { UD_Ifadd, O_ST0, O_ST2, O_NONE, P_none }, + /* 03 */ { UD_Ifadd, O_ST0, O_ST3, O_NONE, P_none }, + /* 04 */ { UD_Ifadd, O_ST0, O_ST4, O_NONE, P_none }, + /* 05 */ { UD_Ifadd, O_ST0, O_ST5, O_NONE, P_none }, + /* 06 */ { UD_Ifadd, O_ST0, O_ST6, O_NONE, P_none }, + /* 07 */ { UD_Ifadd, O_ST0, O_ST7, O_NONE, P_none }, + /* 08 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifmul, O_ST0, O_ST1, O_NONE, P_none }, + /* 0A */ { UD_Ifmul, O_ST0, O_ST2, O_NONE, P_none }, + /* 0B */ { UD_Ifmul, O_ST0, O_ST3, O_NONE, P_none }, + /* 0C */ { UD_Ifmul, O_ST0, O_ST4, O_NONE, P_none }, + /* 0D */ { UD_Ifmul, O_ST0, O_ST5, O_NONE, P_none }, + /* 0E */ { UD_Ifmul, O_ST0, O_ST6, O_NONE, P_none }, + /* 0F */ { UD_Ifmul, O_ST0, O_ST7, O_NONE, P_none }, + /* 10 */ { UD_Ifcom, O_ST0, O_ST0, O_NONE, P_none }, + /* 11 */ { UD_Ifcom, O_ST0, O_ST1, O_NONE, P_none }, + /* 12 */ { UD_Ifcom, O_ST0, O_ST2, O_NONE, P_none }, + /* 13 */ { UD_Ifcom, O_ST0, O_ST3, O_NONE, P_none }, + /* 14 */ { UD_Ifcom, O_ST0, O_ST4, O_NONE, P_none }, + /* 15 */ { UD_Ifcom, O_ST0, O_ST5, O_NONE, P_none }, + /* 16 */ { UD_Ifcom, O_ST0, O_ST6, O_NONE, P_none }, + /* 17 */ { UD_Ifcom, O_ST0, O_ST7, O_NONE, P_none }, + /* 18 */ { UD_Ifcomp, O_ST0, O_ST0, O_NONE, P_none }, + /* 19 */ { UD_Ifcomp, O_ST0, O_ST1, O_NONE, P_none }, + /* 1A */ { UD_Ifcomp, O_ST0, O_ST2, O_NONE, P_none }, + /* 1B */ { UD_Ifcomp, O_ST0, O_ST3, O_NONE, P_none }, + /* 1C */ { UD_Ifcomp, O_ST0, O_ST4, O_NONE, P_none }, + /* 1D */ { UD_Ifcomp, O_ST0, O_ST5, O_NONE, P_none }, + /* 1E */ { UD_Ifcomp, O_ST0, O_ST6, O_NONE, P_none }, + /* 1F */ { UD_Ifcomp, O_ST0, O_ST7, O_NONE, P_none }, + /* 20 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, + /* 21 */ { UD_Ifsub, O_ST0, O_ST1, O_NONE, P_none }, + /* 22 */ { UD_Ifsub, O_ST0, O_ST2, O_NONE, P_none }, + /* 23 */ { UD_Ifsub, O_ST0, O_ST3, O_NONE, P_none }, + /* 24 */ { UD_Ifsub, O_ST0, O_ST4, O_NONE, P_none }, + /* 25 */ { UD_Ifsub, O_ST0, O_ST5, O_NONE, P_none }, + /* 26 */ { UD_Ifsub, O_ST0, O_ST6, O_NONE, P_none }, + /* 27 */ { UD_Ifsub, O_ST0, O_ST7, O_NONE, P_none }, + /* 28 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, + /* 29 */ { UD_Ifsubr, O_ST0, O_ST1, O_NONE, P_none }, + /* 2A */ { UD_Ifsubr, O_ST0, O_ST2, O_NONE, P_none }, + /* 2B */ { UD_Ifsubr, O_ST0, O_ST3, O_NONE, P_none }, + /* 2C */ { UD_Ifsubr, O_ST0, O_ST4, O_NONE, P_none }, + /* 2D */ { UD_Ifsubr, O_ST0, O_ST5, O_NONE, P_none }, + /* 2E */ { UD_Ifsubr, O_ST0, O_ST6, O_NONE, P_none }, + /* 2F */ { UD_Ifsubr, O_ST0, O_ST7, O_NONE, P_none }, + /* 30 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, + /* 31 */ { UD_Ifdiv, O_ST0, O_ST1, O_NONE, P_none }, + /* 32 */ { UD_Ifdiv, O_ST0, O_ST2, O_NONE, P_none }, + /* 33 */ { UD_Ifdiv, O_ST0, O_ST3, O_NONE, P_none }, + /* 34 */ { UD_Ifdiv, O_ST0, O_ST4, O_NONE, P_none }, + /* 35 */ { UD_Ifdiv, O_ST0, O_ST5, O_NONE, P_none }, + /* 36 */ { UD_Ifdiv, O_ST0, O_ST6, O_NONE, P_none }, + /* 37 */ { UD_Ifdiv, O_ST0, O_ST7, O_NONE, P_none }, + /* 38 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, + /* 39 */ { UD_Ifdivr, O_ST0, O_ST1, O_NONE, P_none }, + /* 3A */ { UD_Ifdivr, O_ST0, O_ST2, O_NONE, P_none }, + /* 3B */ { UD_Ifdivr, O_ST0, O_ST3, O_NONE, P_none }, + /* 3C */ { UD_Ifdivr, O_ST0, O_ST4, O_NONE, P_none }, + /* 3D */ { UD_Ifdivr, O_ST0, O_ST5, O_NONE, P_none }, + /* 3E */ { UD_Ifdivr, O_ST0, O_ST6, O_NONE, P_none }, + /* 3F */ { UD_Ifdivr, O_ST0, O_ST7, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_d9__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_d9__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifld, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ifst, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifstp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifldenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifldcw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifnstenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifnstcw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_d9__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifld, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifld, O_ST0, O_ST1, O_NONE, P_none }, + /* 02 */ { UD_Ifld, O_ST0, O_ST2, O_NONE, P_none }, + /* 03 */ { UD_Ifld, O_ST0, O_ST3, O_NONE, P_none }, + /* 04 */ { UD_Ifld, O_ST0, O_ST4, O_NONE, P_none }, + /* 05 */ { UD_Ifld, O_ST0, O_ST5, O_NONE, P_none }, + /* 06 */ { UD_Ifld, O_ST0, O_ST6, O_NONE, P_none }, + /* 07 */ { UD_Ifld, O_ST0, O_ST7, O_NONE, P_none }, + /* 08 */ { UD_Ifxch, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifxch, O_ST0, O_ST1, O_NONE, P_none }, + /* 0A */ { UD_Ifxch, O_ST0, O_ST2, O_NONE, P_none }, + /* 0B */ { UD_Ifxch, O_ST0, O_ST3, O_NONE, P_none }, + /* 0C */ { UD_Ifxch, O_ST0, O_ST4, O_NONE, P_none }, + /* 0D */ { UD_Ifxch, O_ST0, O_ST5, O_NONE, P_none }, + /* 0E */ { UD_Ifxch, O_ST0, O_ST6, O_NONE, P_none }, + /* 0F */ { UD_Ifxch, O_ST0, O_ST7, O_NONE, P_none }, + /* 10 */ { UD_Ifnop, O_NONE, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Ifstp1, O_ST0, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Ifstp1, O_ST1, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Ifstp1, O_ST2, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Ifstp1, O_ST3, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Ifstp1, O_ST4, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Ifstp1, O_ST5, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Ifstp1, O_ST6, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Ifstp1, O_ST7, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Ifchs, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iftst, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Ifxam, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Ifld1, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Ifldl2t, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Ifldl2e, O_NONE, O_NONE, O_NONE, P_none }, + /* 2B */ { UD_Ifldlpi, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Ifldlg2, O_NONE, O_NONE, O_NONE, P_none }, + /* 2D */ { UD_Ifldln2, O_NONE, O_NONE, O_NONE, P_none }, + /* 2E */ { UD_Ifldz, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Ifyl2x, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Ifptan, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Ifpatan, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Ifpxtract, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Ifprem1, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Ifdecstp, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Ifncstp, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Ifprem, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Ifyl2xp1, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Ifsqrt, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Ifsincos, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Ifrndint, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Ifscale, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Ifsin, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Ifcos, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_da__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_da__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifiadd, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifimul, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ificom, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ificomp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifisub, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifisubr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifidiv, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifidivr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_da__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifcmovb, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifcmovb, O_ST0, O_ST1, O_NONE, P_none }, + /* 02 */ { UD_Ifcmovb, O_ST0, O_ST2, O_NONE, P_none }, + /* 03 */ { UD_Ifcmovb, O_ST0, O_ST3, O_NONE, P_none }, + /* 04 */ { UD_Ifcmovb, O_ST0, O_ST4, O_NONE, P_none }, + /* 05 */ { UD_Ifcmovb, O_ST0, O_ST5, O_NONE, P_none }, + /* 06 */ { UD_Ifcmovb, O_ST0, O_ST6, O_NONE, P_none }, + /* 07 */ { UD_Ifcmovb, O_ST0, O_ST7, O_NONE, P_none }, + /* 08 */ { UD_Ifcmove, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifcmove, O_ST0, O_ST1, O_NONE, P_none }, + /* 0A */ { UD_Ifcmove, O_ST0, O_ST2, O_NONE, P_none }, + /* 0B */ { UD_Ifcmove, O_ST0, O_ST3, O_NONE, P_none }, + /* 0C */ { UD_Ifcmove, O_ST0, O_ST4, O_NONE, P_none }, + /* 0D */ { UD_Ifcmove, O_ST0, O_ST5, O_NONE, P_none }, + /* 0E */ { UD_Ifcmove, O_ST0, O_ST6, O_NONE, P_none }, + /* 0F */ { UD_Ifcmove, O_ST0, O_ST7, O_NONE, P_none }, + /* 10 */ { UD_Ifcmovbe, O_ST0, O_ST0, O_NONE, P_none }, + /* 11 */ { UD_Ifcmovbe, O_ST0, O_ST1, O_NONE, P_none }, + /* 12 */ { UD_Ifcmovbe, O_ST0, O_ST2, O_NONE, P_none }, + /* 13 */ { UD_Ifcmovbe, O_ST0, O_ST3, O_NONE, P_none }, + /* 14 */ { UD_Ifcmovbe, O_ST0, O_ST4, O_NONE, P_none }, + /* 15 */ { UD_Ifcmovbe, O_ST0, O_ST5, O_NONE, P_none }, + /* 16 */ { UD_Ifcmovbe, O_ST0, O_ST6, O_NONE, P_none }, + /* 17 */ { UD_Ifcmovbe, O_ST0, O_ST7, O_NONE, P_none }, + /* 18 */ { UD_Ifcmovu, O_ST0, O_ST0, O_NONE, P_none }, + /* 19 */ { UD_Ifcmovu, O_ST0, O_ST1, O_NONE, P_none }, + /* 1A */ { UD_Ifcmovu, O_ST0, O_ST2, O_NONE, P_none }, + /* 1B */ { UD_Ifcmovu, O_ST0, O_ST3, O_NONE, P_none }, + /* 1C */ { UD_Ifcmovu, O_ST0, O_ST4, O_NONE, P_none }, + /* 1D */ { UD_Ifcmovu, O_ST0, O_ST5, O_NONE, P_none }, + /* 1E */ { UD_Ifcmovu, O_ST0, O_ST6, O_NONE, P_none }, + /* 1F */ { UD_Ifcmovu, O_ST0, O_ST7, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Ifucompp, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_db__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_db__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifild, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifisttp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ifist, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifistp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Ifld, O_Mt, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Ifstp, O_Mt, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_db__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifcmovnb, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifcmovnb, O_ST0, O_ST1, O_NONE, P_none }, + /* 02 */ { UD_Ifcmovnb, O_ST0, O_ST2, O_NONE, P_none }, + /* 03 */ { UD_Ifcmovnb, O_ST0, O_ST3, O_NONE, P_none }, + /* 04 */ { UD_Ifcmovnb, O_ST0, O_ST4, O_NONE, P_none }, + /* 05 */ { UD_Ifcmovnb, O_ST0, O_ST5, O_NONE, P_none }, + /* 06 */ { UD_Ifcmovnb, O_ST0, O_ST6, O_NONE, P_none }, + /* 07 */ { UD_Ifcmovnb, O_ST0, O_ST7, O_NONE, P_none }, + /* 08 */ { UD_Ifcmovne, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifcmovne, O_ST0, O_ST1, O_NONE, P_none }, + /* 0A */ { UD_Ifcmovne, O_ST0, O_ST2, O_NONE, P_none }, + /* 0B */ { UD_Ifcmovne, O_ST0, O_ST3, O_NONE, P_none }, + /* 0C */ { UD_Ifcmovne, O_ST0, O_ST4, O_NONE, P_none }, + /* 0D */ { UD_Ifcmovne, O_ST0, O_ST5, O_NONE, P_none }, + /* 0E */ { UD_Ifcmovne, O_ST0, O_ST6, O_NONE, P_none }, + /* 0F */ { UD_Ifcmovne, O_ST0, O_ST7, O_NONE, P_none }, + /* 10 */ { UD_Ifcmovnbe, O_ST0, O_ST0, O_NONE, P_none }, + /* 11 */ { UD_Ifcmovnbe, O_ST0, O_ST1, O_NONE, P_none }, + /* 12 */ { UD_Ifcmovnbe, O_ST0, O_ST2, O_NONE, P_none }, + /* 13 */ { UD_Ifcmovnbe, O_ST0, O_ST3, O_NONE, P_none }, + /* 14 */ { UD_Ifcmovnbe, O_ST0, O_ST4, O_NONE, P_none }, + /* 15 */ { UD_Ifcmovnbe, O_ST0, O_ST5, O_NONE, P_none }, + /* 16 */ { UD_Ifcmovnbe, O_ST0, O_ST6, O_NONE, P_none }, + /* 17 */ { UD_Ifcmovnbe, O_ST0, O_ST7, O_NONE, P_none }, + /* 18 */ { UD_Ifcmovnu, O_ST0, O_ST0, O_NONE, P_none }, + /* 19 */ { UD_Ifcmovnu, O_ST0, O_ST1, O_NONE, P_none }, + /* 1A */ { UD_Ifcmovnu, O_ST0, O_ST2, O_NONE, P_none }, + /* 1B */ { UD_Ifcmovnu, O_ST0, O_ST3, O_NONE, P_none }, + /* 1C */ { UD_Ifcmovnu, O_ST0, O_ST4, O_NONE, P_none }, + /* 1D */ { UD_Ifcmovnu, O_ST0, O_ST5, O_NONE, P_none }, + /* 1E */ { UD_Ifcmovnu, O_ST0, O_ST6, O_NONE, P_none }, + /* 1F */ { UD_Ifcmovnu, O_ST0, O_ST7, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Ifclex, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Ifninit, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Ifucomi, O_ST0, O_ST0, O_NONE, P_none }, + /* 29 */ { UD_Ifucomi, O_ST0, O_ST1, O_NONE, P_none }, + /* 2A */ { UD_Ifucomi, O_ST0, O_ST2, O_NONE, P_none }, + /* 2B */ { UD_Ifucomi, O_ST0, O_ST3, O_NONE, P_none }, + /* 2C */ { UD_Ifucomi, O_ST0, O_ST4, O_NONE, P_none }, + /* 2D */ { UD_Ifucomi, O_ST0, O_ST5, O_NONE, P_none }, + /* 2E */ { UD_Ifucomi, O_ST0, O_ST6, O_NONE, P_none }, + /* 2F */ { UD_Ifucomi, O_ST0, O_ST7, O_NONE, P_none }, + /* 30 */ { UD_Ifcomi, O_ST0, O_ST0, O_NONE, P_none }, + /* 31 */ { UD_Ifcomi, O_ST0, O_ST1, O_NONE, P_none }, + /* 32 */ { UD_Ifcomi, O_ST0, O_ST2, O_NONE, P_none }, + /* 33 */ { UD_Ifcomi, O_ST0, O_ST3, O_NONE, P_none }, + /* 34 */ { UD_Ifcomi, O_ST0, O_ST4, O_NONE, P_none }, + /* 35 */ { UD_Ifcomi, O_ST0, O_ST5, O_NONE, P_none }, + /* 36 */ { UD_Ifcomi, O_ST0, O_ST6, O_NONE, P_none }, + /* 37 */ { UD_Ifcomi, O_ST0, O_ST7, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_dc__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_dc__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifadd, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifmul, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ifcom, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifcomp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifsub, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifsubr, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifdiv, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifdivr, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_dc__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifadd, O_ST1, O_ST0, O_NONE, P_none }, + /* 02 */ { UD_Ifadd, O_ST2, O_ST0, O_NONE, P_none }, + /* 03 */ { UD_Ifadd, O_ST3, O_ST0, O_NONE, P_none }, + /* 04 */ { UD_Ifadd, O_ST4, O_ST0, O_NONE, P_none }, + /* 05 */ { UD_Ifadd, O_ST5, O_ST0, O_NONE, P_none }, + /* 06 */ { UD_Ifadd, O_ST6, O_ST0, O_NONE, P_none }, + /* 07 */ { UD_Ifadd, O_ST7, O_ST0, O_NONE, P_none }, + /* 08 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifmul, O_ST1, O_ST0, O_NONE, P_none }, + /* 0A */ { UD_Ifmul, O_ST2, O_ST0, O_NONE, P_none }, + /* 0B */ { UD_Ifmul, O_ST3, O_ST0, O_NONE, P_none }, + /* 0C */ { UD_Ifmul, O_ST4, O_ST0, O_NONE, P_none }, + /* 0D */ { UD_Ifmul, O_ST5, O_ST0, O_NONE, P_none }, + /* 0E */ { UD_Ifmul, O_ST6, O_ST0, O_NONE, P_none }, + /* 0F */ { UD_Ifmul, O_ST7, O_ST0, O_NONE, P_none }, + /* 10 */ { UD_Ifcom2, O_ST0, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Ifcom2, O_ST1, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Ifcom2, O_ST2, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Ifcom2, O_ST3, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Ifcom2, O_ST4, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Ifcom2, O_ST5, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Ifcom2, O_ST6, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Ifcom2, O_ST7, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Ifcomp3, O_ST0, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Ifcomp3, O_ST1, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Ifcomp3, O_ST2, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Ifcomp3, O_ST3, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Ifcomp3, O_ST4, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Ifcomp3, O_ST5, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Ifcomp3, O_ST6, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Ifcomp3, O_ST7, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, + /* 21 */ { UD_Ifsubr, O_ST1, O_ST0, O_NONE, P_none }, + /* 22 */ { UD_Ifsubr, O_ST2, O_ST0, O_NONE, P_none }, + /* 23 */ { UD_Ifsubr, O_ST3, O_ST0, O_NONE, P_none }, + /* 24 */ { UD_Ifsubr, O_ST4, O_ST0, O_NONE, P_none }, + /* 25 */ { UD_Ifsubr, O_ST5, O_ST0, O_NONE, P_none }, + /* 26 */ { UD_Ifsubr, O_ST6, O_ST0, O_NONE, P_none }, + /* 27 */ { UD_Ifsubr, O_ST7, O_ST0, O_NONE, P_none }, + /* 28 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, + /* 29 */ { UD_Ifsub, O_ST1, O_ST0, O_NONE, P_none }, + /* 2A */ { UD_Ifsub, O_ST2, O_ST0, O_NONE, P_none }, + /* 2B */ { UD_Ifsub, O_ST3, O_ST0, O_NONE, P_none }, + /* 2C */ { UD_Ifsub, O_ST4, O_ST0, O_NONE, P_none }, + /* 2D */ { UD_Ifsub, O_ST5, O_ST0, O_NONE, P_none }, + /* 2E */ { UD_Ifsub, O_ST6, O_ST0, O_NONE, P_none }, + /* 2F */ { UD_Ifsub, O_ST7, O_ST0, O_NONE, P_none }, + /* 30 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, + /* 31 */ { UD_Ifdivr, O_ST1, O_ST0, O_NONE, P_none }, + /* 32 */ { UD_Ifdivr, O_ST2, O_ST0, O_NONE, P_none }, + /* 33 */ { UD_Ifdivr, O_ST3, O_ST0, O_NONE, P_none }, + /* 34 */ { UD_Ifdivr, O_ST4, O_ST0, O_NONE, P_none }, + /* 35 */ { UD_Ifdivr, O_ST5, O_ST0, O_NONE, P_none }, + /* 36 */ { UD_Ifdivr, O_ST6, O_ST0, O_NONE, P_none }, + /* 37 */ { UD_Ifdivr, O_ST7, O_ST0, O_NONE, P_none }, + /* 38 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, + /* 39 */ { UD_Ifdiv, O_ST1, O_ST0, O_NONE, P_none }, + /* 3A */ { UD_Ifdiv, O_ST2, O_ST0, O_NONE, P_none }, + /* 3B */ { UD_Ifdiv, O_ST3, O_ST0, O_NONE, P_none }, + /* 3C */ { UD_Ifdiv, O_ST4, O_ST0, O_NONE, P_none }, + /* 3D */ { UD_Ifdiv, O_ST5, O_ST0, O_NONE, P_none }, + /* 3E */ { UD_Ifdiv, O_ST6, O_ST0, O_NONE, P_none }, + /* 3F */ { UD_Ifdiv, O_ST7, O_ST0, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_dd__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_dd__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifld, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifisttp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ifst, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifstp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifrstor, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ifnsave, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifnstsw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_dd__mod__op_01__x87[64] = { + /* 00 */ { UD_Iffree, O_ST0, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iffree, O_ST1, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iffree, O_ST2, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iffree, O_ST3, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iffree, O_ST4, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iffree, O_ST5, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iffree, O_ST6, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iffree, O_ST7, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Ifxch4, O_ST0, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Ifxch4, O_ST1, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Ifxch4, O_ST2, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Ifxch4, O_ST3, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Ifxch4, O_ST4, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Ifxch4, O_ST5, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Ifxch4, O_ST6, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Ifxch4, O_ST7, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Ifst, O_ST0, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Ifst, O_ST1, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Ifst, O_ST2, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Ifst, O_ST3, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Ifst, O_ST4, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Ifst, O_ST5, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Ifst, O_ST6, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Ifst, O_ST7, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Ifstp, O_ST0, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Ifstp, O_ST1, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Ifstp, O_ST2, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Ifstp, O_ST3, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Ifstp, O_ST4, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Ifstp, O_ST5, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Ifstp, O_ST6, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Ifstp, O_ST7, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Ifucom, O_ST0, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Ifucom, O_ST1, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Ifucom, O_ST2, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Ifucom, O_ST3, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Ifucom, O_ST4, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Ifucom, O_ST5, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Ifucom, O_ST6, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Ifucom, O_ST7, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Ifucomp, O_ST0, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Ifucomp, O_ST1, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Ifucomp, O_ST2, O_NONE, O_NONE, P_none }, + /* 2B */ { UD_Ifucomp, O_ST3, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Ifucomp, O_ST4, O_NONE, O_NONE, P_none }, + /* 2D */ { UD_Ifucomp, O_ST5, O_NONE, O_NONE, P_none }, + /* 2E */ { UD_Ifucomp, O_ST6, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Ifucomp, O_ST7, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_de__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_de__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifiadd, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifimul, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ificom, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ificomp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifisub, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifisubr, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifidiv, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifidivr, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_de__mod__op_01__x87[64] = { + /* 00 */ { UD_Ifaddp, O_ST0, O_ST0, O_NONE, P_none }, + /* 01 */ { UD_Ifaddp, O_ST1, O_ST0, O_NONE, P_none }, + /* 02 */ { UD_Ifaddp, O_ST2, O_ST0, O_NONE, P_none }, + /* 03 */ { UD_Ifaddp, O_ST3, O_ST0, O_NONE, P_none }, + /* 04 */ { UD_Ifaddp, O_ST4, O_ST0, O_NONE, P_none }, + /* 05 */ { UD_Ifaddp, O_ST5, O_ST0, O_NONE, P_none }, + /* 06 */ { UD_Ifaddp, O_ST6, O_ST0, O_NONE, P_none }, + /* 07 */ { UD_Ifaddp, O_ST7, O_ST0, O_NONE, P_none }, + /* 08 */ { UD_Ifmulp, O_ST0, O_ST0, O_NONE, P_none }, + /* 09 */ { UD_Ifmulp, O_ST1, O_ST0, O_NONE, P_none }, + /* 0A */ { UD_Ifmulp, O_ST2, O_ST0, O_NONE, P_none }, + /* 0B */ { UD_Ifmulp, O_ST3, O_ST0, O_NONE, P_none }, + /* 0C */ { UD_Ifmulp, O_ST4, O_ST0, O_NONE, P_none }, + /* 0D */ { UD_Ifmulp, O_ST5, O_ST0, O_NONE, P_none }, + /* 0E */ { UD_Ifmulp, O_ST6, O_ST0, O_NONE, P_none }, + /* 0F */ { UD_Ifmulp, O_ST7, O_ST0, O_NONE, P_none }, + /* 10 */ { UD_Ifcomp5, O_ST0, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Ifcomp5, O_ST1, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Ifcomp5, O_ST2, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Ifcomp5, O_ST3, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Ifcomp5, O_ST4, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Ifcomp5, O_ST5, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Ifcomp5, O_ST6, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Ifcomp5, O_ST7, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Ifcompp, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Ifsubrp, O_ST0, O_ST0, O_NONE, P_none }, + /* 21 */ { UD_Ifsubrp, O_ST1, O_ST0, O_NONE, P_none }, + /* 22 */ { UD_Ifsubrp, O_ST2, O_ST0, O_NONE, P_none }, + /* 23 */ { UD_Ifsubrp, O_ST3, O_ST0, O_NONE, P_none }, + /* 24 */ { UD_Ifsubrp, O_ST4, O_ST0, O_NONE, P_none }, + /* 25 */ { UD_Ifsubrp, O_ST5, O_ST0, O_NONE, P_none }, + /* 26 */ { UD_Ifsubrp, O_ST6, O_ST0, O_NONE, P_none }, + /* 27 */ { UD_Ifsubrp, O_ST7, O_ST0, O_NONE, P_none }, + /* 28 */ { UD_Ifsubp, O_ST0, O_ST0, O_NONE, P_none }, + /* 29 */ { UD_Ifsubp, O_ST1, O_ST0, O_NONE, P_none }, + /* 2A */ { UD_Ifsubp, O_ST2, O_ST0, O_NONE, P_none }, + /* 2B */ { UD_Ifsubp, O_ST3, O_ST0, O_NONE, P_none }, + /* 2C */ { UD_Ifsubp, O_ST4, O_ST0, O_NONE, P_none }, + /* 2D */ { UD_Ifsubp, O_ST5, O_ST0, O_NONE, P_none }, + /* 2E */ { UD_Ifsubp, O_ST6, O_ST0, O_NONE, P_none }, + /* 2F */ { UD_Ifsubp, O_ST7, O_ST0, O_NONE, P_none }, + /* 30 */ { UD_Ifdivrp, O_ST0, O_ST0, O_NONE, P_none }, + /* 31 */ { UD_Ifdivrp, O_ST1, O_ST0, O_NONE, P_none }, + /* 32 */ { UD_Ifdivrp, O_ST2, O_ST0, O_NONE, P_none }, + /* 33 */ { UD_Ifdivrp, O_ST3, O_ST0, O_NONE, P_none }, + /* 34 */ { UD_Ifdivrp, O_ST4, O_ST0, O_NONE, P_none }, + /* 35 */ { UD_Ifdivrp, O_ST5, O_ST0, O_NONE, P_none }, + /* 36 */ { UD_Ifdivrp, O_ST6, O_ST0, O_NONE, P_none }, + /* 37 */ { UD_Ifdivrp, O_ST7, O_ST0, O_NONE, P_none }, + /* 38 */ { UD_Ifdivp, O_ST0, O_ST0, O_NONE, P_none }, + /* 39 */ { UD_Ifdivp, O_ST1, O_ST0, O_NONE, P_none }, + /* 3A */ { UD_Ifdivp, O_ST2, O_ST0, O_NONE, P_none }, + /* 3B */ { UD_Ifdivp, O_ST3, O_ST0, O_NONE, P_none }, + /* 3C */ { UD_Ifdivp, O_ST4, O_ST0, O_NONE, P_none }, + /* 3D */ { UD_Ifdivp, O_ST5, O_ST0, O_NONE, P_none }, + /* 3E */ { UD_Ifdivp, O_ST6, O_ST0, O_NONE, P_none }, + /* 3F */ { UD_Ifdivp, O_ST7, O_ST0, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_df__mod[2] = { + /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD__OP_00__REG }, + /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD__OP_01__X87 }, +}; + +static struct ud_itab_entry itab__1byte__op_df__mod__op_00__reg[8] = { + /* 00 */ { UD_Ifild, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Ifisttp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Ifist, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ifistp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ifbld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ifild, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ifbstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Ifistp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_df__mod__op_01__x87[64] = { + /* 00 */ { UD_Iffreep, O_ST0, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iffreep, O_ST1, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iffreep, O_ST2, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iffreep, O_ST3, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iffreep, O_ST4, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iffreep, O_ST5, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iffreep, O_ST6, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iffreep, O_ST7, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Ifxch7, O_ST0, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Ifxch7, O_ST1, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Ifxch7, O_ST2, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Ifxch7, O_ST3, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Ifxch7, O_ST4, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Ifxch7, O_ST5, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Ifxch7, O_ST6, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Ifxch7, O_ST7, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Ifstp8, O_ST0, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Ifstp8, O_ST1, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Ifstp8, O_ST2, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Ifstp8, O_ST3, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Ifstp8, O_ST4, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Ifstp8, O_ST5, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Ifstp8, O_ST6, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Ifstp8, O_ST7, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Ifstp9, O_ST0, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Ifstp9, O_ST1, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Ifstp9, O_ST2, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Ifstp9, O_ST3, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Ifstp9, O_ST4, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Ifstp9, O_ST5, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Ifstp9, O_ST6, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Ifstp9, O_ST7, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Ifnstsw, O_AX, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Ifucomip, O_ST0, O_ST0, O_NONE, P_none }, + /* 29 */ { UD_Ifucomip, O_ST0, O_ST1, O_NONE, P_none }, + /* 2A */ { UD_Ifucomip, O_ST0, O_ST2, O_NONE, P_none }, + /* 2B */ { UD_Ifucomip, O_ST0, O_ST3, O_NONE, P_none }, + /* 2C */ { UD_Ifucomip, O_ST0, O_ST4, O_NONE, P_none }, + /* 2D */ { UD_Ifucomip, O_ST0, O_ST5, O_NONE, P_none }, + /* 2E */ { UD_Ifucomip, O_ST0, O_ST6, O_NONE, P_none }, + /* 2F */ { UD_Ifucomip, O_ST0, O_ST7, O_NONE, P_none }, + /* 30 */ { UD_Ifcomip, O_ST0, O_ST0, O_NONE, P_none }, + /* 31 */ { UD_Ifcomip, O_ST0, O_ST1, O_NONE, P_none }, + /* 32 */ { UD_Ifcomip, O_ST0, O_ST2, O_NONE, P_none }, + /* 33 */ { UD_Ifcomip, O_ST0, O_ST3, O_NONE, P_none }, + /* 34 */ { UD_Ifcomip, O_ST0, O_ST4, O_NONE, P_none }, + /* 35 */ { UD_Ifcomip, O_ST0, O_ST5, O_NONE, P_none }, + /* 36 */ { UD_Ifcomip, O_ST0, O_ST6, O_NONE, P_none }, + /* 37 */ { UD_Ifcomip, O_ST0, O_ST7, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_e3__asize[3] = { + /* 00 */ { UD_Ijcxz, O_Jb, O_NONE, O_NONE, P_aso }, + /* 01 */ { UD_Ijecxz, O_Jb, O_NONE, O_NONE, P_aso }, + /* 02 */ { UD_Ijrcxz, O_Jb, O_NONE, O_NONE, P_aso }, +}; + +static struct ud_itab_entry itab__1byte__op_f6__reg[8] = { + /* 00 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Inot, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ineg, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Imul, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Iimul, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Idiv, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Iidiv, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_f7__reg[8] = { + /* 00 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Inot, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Ineg, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Imul, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Iimul, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Idiv, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Iidiv, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__1byte__op_fe__reg[8] = { + /* 00 */ { UD_Iinc, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Idec, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__1byte__op_ff__reg[8] = { + /* 00 */ { UD_Iinc, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 01 */ { UD_Idec, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 02 */ { UD_Icall, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 03 */ { UD_Icall, O_Ep, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 04 */ { UD_Ijmp, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 05 */ { UD_Ijmp, O_Ep, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 06 */ { UD_Ipush, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__3dnow[256] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 51 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 58 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 59 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 70 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f[256] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Imovupd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 11 */ { UD_Imovupd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 12 */ { UD_Imovlpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 13 */ { UD_Imovlpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 14 */ { UD_Iunpcklpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 15 */ { UD_Iunpckhpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 16 */ { UD_Imovhpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 17 */ { UD_Imovhpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Imovapd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 29 */ { UD_Imovapd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2A */ { UD_Icvtpi2pd, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2B */ { UD_Imovntpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2C */ { UD_Icvttpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2D */ { UD_Icvtpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2E */ { UD_Iucomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 2F */ { UD_Icomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 50 */ { UD_Imovmskpd, O_Gd, O_VR, O_NONE, P_oso|P_rexr|P_rexb }, + /* 51 */ { UD_Isqrtpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 54 */ { UD_Iandpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 55 */ { UD_Iandnpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 56 */ { UD_Iorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 57 */ { UD_Ixorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 58 */ { UD_Iaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 59 */ { UD_Imulpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5A */ { UD_Icvtpd2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5B */ { UD_Icvtps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5C */ { UD_Isubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5D */ { UD_Iminpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5E */ { UD_Idivpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5F */ { UD_Imaxpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 60 */ { UD_Ipunpcklbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 61 */ { UD_Ipunpcklwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 62 */ { UD_Ipunpckldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 63 */ { UD_Ipacksswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 64 */ { UD_Ipcmpgtb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 65 */ { UD_Ipcmpgtw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 66 */ { UD_Ipcmpgtd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 67 */ { UD_Ipackuswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 68 */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 69 */ { UD_Ipunpckhwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6A */ { UD_Ipunpckhdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6B */ { UD_Ipackssdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6C */ { UD_Ipunpcklqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6D */ { UD_Ipunpckhqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 6E */ { UD_Imovd, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 6F */ { UD_Imovqa, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 70 */ { UD_Ipshufd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 71 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_71__REG }, + /* 72 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_72__REG }, + /* 73 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_73__REG }, + /* 74 */ { UD_Ipcmpeqb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 75 */ { UD_Ipcmpeqw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 76 */ { UD_Ipcmpeqd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Ihaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 7D */ { UD_Ihsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 7E */ { UD_Imovd, O_Ex, O_V, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 7F */ { UD_Imovdqa, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C2 */ { UD_Icmppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C4 */ { UD_Ipinsrw, O_V, O_Ew, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C5 */ { UD_Ipextrw, O_Gd, O_VR, O_Ib, P_aso|P_rexr|P_rexb }, + /* C6 */ { UD_Ishufpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_C7__REG }, + /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D0 */ { UD_Iaddsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D1 */ { UD_Ipsrlw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D2 */ { UD_Ipsrld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D3 */ { UD_Ipsrlq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D4 */ { UD_Ipaddq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D5 */ { UD_Ipmullw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D6 */ { UD_Imovq, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D7 */ { UD_Ipmovmskb, O_Gd, O_VR, O_NONE, P_rexr|P_rexb }, + /* D8 */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D9 */ { UD_Ipsubusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DA */ { UD_Ipminub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DB */ { UD_Ipand, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DC */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DD */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DE */ { UD_Ipmaxub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* DF */ { UD_Ipandn, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E0 */ { UD_Ipavgb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E1 */ { UD_Ipsraw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E2 */ { UD_Ipsrad, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E3 */ { UD_Ipavgw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E4 */ { UD_Ipmulhuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E5 */ { UD_Ipmulhw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E6 */ { UD_Icvttpd2dq, O_V, O_W, O_NONE, P_none }, + /* E7 */ { UD_Imovntdq, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E8 */ { UD_Ipsubsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E9 */ { UD_Ipsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EA */ { UD_Ipminsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EB */ { UD_Ipor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EC */ { UD_Ipaddsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* ED */ { UD_Ipaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EE */ { UD_Ipmaxsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* EF */ { UD_Ipxor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F1 */ { UD_Ipsllw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F2 */ { UD_Ipslld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F3 */ { UD_Ipsllq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F4 */ { UD_Ipmuludq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F5 */ { UD_Ipmaddwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F6 */ { UD_Ipsadbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F7 */ { UD_Imaskmovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F8 */ { UD_Ipsubb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F9 */ { UD_Ipsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FA */ { UD_Ipsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FB */ { UD_Ipsubq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FC */ { UD_Ipaddb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FD */ { UD_Ipaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f__op_71__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrlw, O_VR, O_Ib, O_NONE, P_rexb }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ipsraw, O_VR, O_Ib, O_NONE, P_rexb }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipsllw, O_VR, O_Ib, O_NONE, P_rexb }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f__op_72__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrld, O_VR, O_Ib, O_NONE, P_rexb }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Ipsrad, O_VR, O_Ib, O_NONE, P_rexb }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipslld, O_VR, O_Ib, O_NONE, P_rexb }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f__op_73__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Ipsrlq, O_VR, O_Ib, O_NONE, P_rexb }, + /* 03 */ { UD_Ipsrldq, O_VR, O_Ib, O_NONE, P_rexb }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Ipsllq, O_VR, O_Ib, O_NONE, P_rexb }, + /* 07 */ { UD_Ipslldq, O_VR, O_Ib, O_NONE, P_rexb }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f__op_c7__reg[8] = { + /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_C7__REG__OP_00__VENDOR }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_sse66__0f__op_c7__reg__op_00__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, +}; + +static struct ud_itab_entry itab__pfx_ssef2__0f[256] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Imovsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 11 */ { UD_Imovsd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 12 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Icvtsi2sd, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Icvttsd2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 2D */ { UD_Icvtsd2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 51 */ { UD_Isqrtsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 58 */ { UD_Iaddsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 59 */ { UD_Imulsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5A */ { UD_Icvtsd2ss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 5C */ { UD_Isubsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5D */ { UD_Iminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5E */ { UD_Idivsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5F */ { UD_Imaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 70 */ { UD_Ipshuflw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Ihaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 7D */ { UD_Ihsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 7E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* C2 */ { UD_Icmpsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D0 */ { UD_Iaddsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D6 */ { UD_Imovdq2q, O_P, O_VR, O_NONE, P_aso|P_rexb }, + /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E6 */ { UD_Icvtpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F0 */ { UD_Ilddqu, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_ssef3__0f[256] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 10 */ { UD_Imovss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 11 */ { UD_Imovss, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 12 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 16 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2A */ { UD_Icvtsi2ss, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexr|P_rexx|P_rexb }, + /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2C */ { UD_Icvttss2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 2D */ { UD_Icvtss2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, + /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 51 */ { UD_Isqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 52 */ { UD_Irsqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 53 */ { UD_Ircpss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 58 */ { UD_Iaddss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 59 */ { UD_Imulss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5A */ { UD_Icvtss2sd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5B */ { UD_Icvttps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5C */ { UD_Isubss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5D */ { UD_Iminss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5E */ { UD_Idivss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 5F */ { UD_Imaxss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 6F */ { UD_Imovdqu, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 70 */ { UD_Ipshufhw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 7E */ { UD_Imovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 7F */ { UD_Imovdqu, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* C2 */ { UD_Icmpss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSEF3__0F__OP_C7__REG }, + /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D6 */ { UD_Imovq2dq, O_V, O_PR, O_NONE, P_aso }, + /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E6 */ { UD_Icvtdq2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, +}; + +static struct ud_itab_entry itab__pfx_ssef3__0f__op_c7__reg[8] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 07 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_07__VENDOR }, +}; + +static struct ud_itab_entry itab__pfx_ssef3__0f__op_c7__reg__op_07__vendor[2] = { + /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 01 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, +}; + +/* the order of this table matches enum ud_itab_index */ +struct ud_itab_entry * ud_itab_list[] = { + itab__0f, + itab__0f__op_00__reg, + itab__0f__op_01__reg, + itab__0f__op_01__reg__op_00__mod, + itab__0f__op_01__reg__op_00__mod__op_01__rm, + itab__0f__op_01__reg__op_00__mod__op_01__rm__op_01__vendor, + itab__0f__op_01__reg__op_00__mod__op_01__rm__op_03__vendor, + itab__0f__op_01__reg__op_00__mod__op_01__rm__op_04__vendor, + itab__0f__op_01__reg__op_01__mod, + itab__0f__op_01__reg__op_01__mod__op_01__rm, + itab__0f__op_01__reg__op_02__mod, + itab__0f__op_01__reg__op_03__mod, + itab__0f__op_01__reg__op_03__mod__op_01__rm, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_00__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_01__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_02__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_03__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_04__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_05__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_06__vendor, + itab__0f__op_01__reg__op_03__mod__op_01__rm__op_07__vendor, + itab__0f__op_01__reg__op_04__mod, + itab__0f__op_01__reg__op_06__mod, + itab__0f__op_01__reg__op_07__mod, + itab__0f__op_01__reg__op_07__mod__op_01__rm, + itab__0f__op_01__reg__op_07__mod__op_01__rm__op_01__vendor, + itab__0f__op_0d__reg, + itab__0f__op_18__reg, + itab__0f__op_71__reg, + itab__0f__op_72__reg, + itab__0f__op_73__reg, + itab__0f__op_ae__reg, + itab__0f__op_ae__reg__op_05__mod, + itab__0f__op_ae__reg__op_05__mod__op_01__rm, + itab__0f__op_ae__reg__op_06__mod, + itab__0f__op_ae__reg__op_06__mod__op_01__rm, + itab__0f__op_ae__reg__op_07__mod, + itab__0f__op_ae__reg__op_07__mod__op_01__rm, + itab__0f__op_ba__reg, + itab__0f__op_c7__reg, + itab__0f__op_c7__reg__op_00__vendor, + itab__0f__op_c7__reg__op_07__vendor, + itab__0f__op_d9__mod, + itab__0f__op_d9__mod__op_01__x87, + itab__1byte, + itab__1byte__op_60__osize, + itab__1byte__op_61__osize, + itab__1byte__op_63__mode, + itab__1byte__op_6d__osize, + itab__1byte__op_6f__osize, + itab__1byte__op_80__reg, + itab__1byte__op_81__reg, + itab__1byte__op_82__reg, + itab__1byte__op_83__reg, + itab__1byte__op_8f__reg, + itab__1byte__op_98__osize, + itab__1byte__op_99__osize, + itab__1byte__op_9c__mode, + itab__1byte__op_9c__mode__op_00__osize, + itab__1byte__op_9c__mode__op_01__osize, + itab__1byte__op_9d__mode, + itab__1byte__op_9d__mode__op_00__osize, + itab__1byte__op_9d__mode__op_01__osize, + itab__1byte__op_a5__osize, + itab__1byte__op_a7__osize, + itab__1byte__op_ab__osize, + itab__1byte__op_ad__osize, + itab__1byte__op_ae__mod, + itab__1byte__op_ae__mod__op_00__reg, + itab__1byte__op_af__osize, + itab__1byte__op_c0__reg, + itab__1byte__op_c1__reg, + itab__1byte__op_c6__reg, + itab__1byte__op_c7__reg, + itab__1byte__op_cf__osize, + itab__1byte__op_d0__reg, + itab__1byte__op_d1__reg, + itab__1byte__op_d2__reg, + itab__1byte__op_d3__reg, + itab__1byte__op_d8__mod, + itab__1byte__op_d8__mod__op_00__reg, + itab__1byte__op_d8__mod__op_01__x87, + itab__1byte__op_d9__mod, + itab__1byte__op_d9__mod__op_00__reg, + itab__1byte__op_d9__mod__op_01__x87, + itab__1byte__op_da__mod, + itab__1byte__op_da__mod__op_00__reg, + itab__1byte__op_da__mod__op_01__x87, + itab__1byte__op_db__mod, + itab__1byte__op_db__mod__op_00__reg, + itab__1byte__op_db__mod__op_01__x87, + itab__1byte__op_dc__mod, + itab__1byte__op_dc__mod__op_00__reg, + itab__1byte__op_dc__mod__op_01__x87, + itab__1byte__op_dd__mod, + itab__1byte__op_dd__mod__op_00__reg, + itab__1byte__op_dd__mod__op_01__x87, + itab__1byte__op_de__mod, + itab__1byte__op_de__mod__op_00__reg, + itab__1byte__op_de__mod__op_01__x87, + itab__1byte__op_df__mod, + itab__1byte__op_df__mod__op_00__reg, + itab__1byte__op_df__mod__op_01__x87, + itab__1byte__op_e3__asize, + itab__1byte__op_f6__reg, + itab__1byte__op_f7__reg, + itab__1byte__op_fe__reg, + itab__1byte__op_ff__reg, + itab__3dnow, + itab__pfx_sse66__0f, + itab__pfx_sse66__0f__op_71__reg, + itab__pfx_sse66__0f__op_72__reg, + itab__pfx_sse66__0f__op_73__reg, + itab__pfx_sse66__0f__op_c7__reg, + itab__pfx_sse66__0f__op_c7__reg__op_00__vendor, + itab__pfx_ssef2__0f, + itab__pfx_ssef3__0f, + itab__pfx_ssef3__0f__op_c7__reg, + itab__pfx_ssef3__0f__op_c7__reg__op_07__vendor, +}; diff --git a/xen/kdb/x86/udis86-1.7/itab.h b/xen/kdb/x86/udis86-1.7/itab.h new file mode 100644 index 0000000..737112c --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/itab.h @@ -0,0 +1,719 @@ + +/* itab.h -- auto generated by opgen.py, do not edit. */ + +#ifndef UD_ITAB_H +#define UD_ITAB_H + + + +enum ud_itab_vendor_index { + ITAB__VENDOR_INDX__AMD, + ITAB__VENDOR_INDX__INTEL, +}; + + +enum ud_itab_mode_index { + ITAB__MODE_INDX__16, + ITAB__MODE_INDX__32, + ITAB__MODE_INDX__64 +}; + + +enum ud_itab_mod_index { + ITAB__MOD_INDX__NOT_11, + ITAB__MOD_INDX__11 +}; + + +enum ud_itab_index { + ITAB__0F, + ITAB__0F__OP_00__REG, + ITAB__0F__OP_01__REG, + ITAB__0F__OP_01__REG__OP_00__MOD, + ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM, + ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR, + ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR, + ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR, + ITAB__0F__OP_01__REG__OP_01__MOD, + ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM, + ITAB__0F__OP_01__REG__OP_02__MOD, + ITAB__0F__OP_01__REG__OP_03__MOD, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR, + ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR, + ITAB__0F__OP_01__REG__OP_04__MOD, + ITAB__0F__OP_01__REG__OP_06__MOD, + ITAB__0F__OP_01__REG__OP_07__MOD, + ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM, + ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR, + ITAB__0F__OP_0D__REG, + ITAB__0F__OP_18__REG, + ITAB__0F__OP_71__REG, + ITAB__0F__OP_72__REG, + ITAB__0F__OP_73__REG, + ITAB__0F__OP_AE__REG, + ITAB__0F__OP_AE__REG__OP_05__MOD, + ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM, + ITAB__0F__OP_AE__REG__OP_06__MOD, + ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM, + ITAB__0F__OP_AE__REG__OP_07__MOD, + ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM, + ITAB__0F__OP_BA__REG, + ITAB__0F__OP_C7__REG, + ITAB__0F__OP_C7__REG__OP_00__VENDOR, + ITAB__0F__OP_C7__REG__OP_07__VENDOR, + ITAB__0F__OP_D9__MOD, + ITAB__0F__OP_D9__MOD__OP_01__X87, + ITAB__1BYTE, + ITAB__1BYTE__OP_60__OSIZE, + ITAB__1BYTE__OP_61__OSIZE, + ITAB__1BYTE__OP_63__MODE, + ITAB__1BYTE__OP_6D__OSIZE, + ITAB__1BYTE__OP_6F__OSIZE, + ITAB__1BYTE__OP_80__REG, + ITAB__1BYTE__OP_81__REG, + ITAB__1BYTE__OP_82__REG, + ITAB__1BYTE__OP_83__REG, + ITAB__1BYTE__OP_8F__REG, + ITAB__1BYTE__OP_98__OSIZE, + ITAB__1BYTE__OP_99__OSIZE, + ITAB__1BYTE__OP_9C__MODE, + ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE, + ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE, + ITAB__1BYTE__OP_9D__MODE, + ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE, + ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE, + ITAB__1BYTE__OP_A5__OSIZE, + ITAB__1BYTE__OP_A7__OSIZE, + ITAB__1BYTE__OP_AB__OSIZE, + ITAB__1BYTE__OP_AD__OSIZE, + ITAB__1BYTE__OP_AE__MOD, + ITAB__1BYTE__OP_AE__MOD__OP_00__REG, + ITAB__1BYTE__OP_AF__OSIZE, + ITAB__1BYTE__OP_C0__REG, + ITAB__1BYTE__OP_C1__REG, + ITAB__1BYTE__OP_C6__REG, + ITAB__1BYTE__OP_C7__REG, + ITAB__1BYTE__OP_CF__OSIZE, + ITAB__1BYTE__OP_D0__REG, + ITAB__1BYTE__OP_D1__REG, + ITAB__1BYTE__OP_D2__REG, + ITAB__1BYTE__OP_D3__REG, + ITAB__1BYTE__OP_D8__MOD, + ITAB__1BYTE__OP_D8__MOD__OP_00__REG, + ITAB__1BYTE__OP_D8__MOD__OP_01__X87, + ITAB__1BYTE__OP_D9__MOD, + ITAB__1BYTE__OP_D9__MOD__OP_00__REG, + ITAB__1BYTE__OP_D9__MOD__OP_01__X87, + ITAB__1BYTE__OP_DA__MOD, + ITAB__1BYTE__OP_DA__MOD__OP_00__REG, + ITAB__1BYTE__OP_DA__MOD__OP_01__X87, + ITAB__1BYTE__OP_DB__MOD, + ITAB__1BYTE__OP_DB__MOD__OP_00__REG, + ITAB__1BYTE__OP_DB__MOD__OP_01__X87, + ITAB__1BYTE__OP_DC__MOD, + ITAB__1BYTE__OP_DC__MOD__OP_00__REG, + ITAB__1BYTE__OP_DC__MOD__OP_01__X87, + ITAB__1BYTE__OP_DD__MOD, + ITAB__1BYTE__OP_DD__MOD__OP_00__REG, + ITAB__1BYTE__OP_DD__MOD__OP_01__X87, + ITAB__1BYTE__OP_DE__MOD, + ITAB__1BYTE__OP_DE__MOD__OP_00__REG, + ITAB__1BYTE__OP_DE__MOD__OP_01__X87, + ITAB__1BYTE__OP_DF__MOD, + ITAB__1BYTE__OP_DF__MOD__OP_00__REG, + ITAB__1BYTE__OP_DF__MOD__OP_01__X87, + ITAB__1BYTE__OP_E3__ASIZE, + ITAB__1BYTE__OP_F6__REG, + ITAB__1BYTE__OP_F7__REG, + ITAB__1BYTE__OP_FE__REG, + ITAB__1BYTE__OP_FF__REG, + ITAB__3DNOW, + ITAB__PFX_SSE66__0F, + ITAB__PFX_SSE66__0F__OP_71__REG, + ITAB__PFX_SSE66__0F__OP_72__REG, + ITAB__PFX_SSE66__0F__OP_73__REG, + ITAB__PFX_SSE66__0F__OP_C7__REG, + ITAB__PFX_SSE66__0F__OP_C7__REG__OP_00__VENDOR, + ITAB__PFX_SSEF2__0F, + ITAB__PFX_SSEF3__0F, + ITAB__PFX_SSEF3__0F__OP_C7__REG, + ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_07__VENDOR, +}; + + +enum ud_mnemonic_code { + UD_I3dnow, + UD_Iaaa, + UD_Iaad, + UD_Iaam, + UD_Iaas, + UD_Iadc, + UD_Iadd, + UD_Iaddpd, + UD_Iaddps, + UD_Iaddsd, + UD_Iaddss, + UD_Iaddsubpd, + UD_Iaddsubps, + UD_Iand, + UD_Iandpd, + UD_Iandps, + UD_Iandnpd, + UD_Iandnps, + UD_Iarpl, + UD_Imovsxd, + UD_Ibound, + UD_Ibsf, + UD_Ibsr, + UD_Ibswap, + UD_Ibt, + UD_Ibtc, + UD_Ibtr, + UD_Ibts, + UD_Icall, + UD_Icbw, + UD_Icwde, + UD_Icdqe, + UD_Iclc, + UD_Icld, + UD_Iclflush, + UD_Iclgi, + UD_Icli, + UD_Iclts, + UD_Icmc, + UD_Icmovo, + UD_Icmovno, + UD_Icmovb, + UD_Icmovae, + UD_Icmovz, + UD_Icmovnz, + UD_Icmovbe, + UD_Icmova, + UD_Icmovs, + UD_Icmovns, + UD_Icmovp, + UD_Icmovnp, + UD_Icmovl, + UD_Icmovge, + UD_Icmovle, + UD_Icmovg, + UD_Icmp, + UD_Icmppd, + UD_Icmpps, + UD_Icmpsb, + UD_Icmpsw, + UD_Icmpsd, + UD_Icmpsq, + UD_Icmpss, + UD_Icmpxchg, + UD_Icmpxchg8b, + UD_Icomisd, + UD_Icomiss, + UD_Icpuid, + UD_Icvtdq2pd, + UD_Icvtdq2ps, + UD_Icvtpd2dq, + UD_Icvtpd2pi, + UD_Icvtpd2ps, + UD_Icvtpi2ps, + UD_Icvtpi2pd, + UD_Icvtps2dq, + UD_Icvtps2pi, + UD_Icvtps2pd, + UD_Icvtsd2si, + UD_Icvtsd2ss, + UD_Icvtsi2ss, + UD_Icvtss2si, + UD_Icvtss2sd, + UD_Icvttpd2pi, + UD_Icvttpd2dq, + UD_Icvttps2dq, + UD_Icvttps2pi, + UD_Icvttsd2si, + UD_Icvtsi2sd, + UD_Icvttss2si, + UD_Icwd, + UD_Icdq, + UD_Icqo, + UD_Idaa, + UD_Idas, + UD_Idec, + UD_Idiv, + UD_Idivpd, + UD_Idivps, + UD_Idivsd, + UD_Idivss, + UD_Iemms, + UD_Ienter, + UD_If2xm1, + UD_Ifabs, + UD_Ifadd, + UD_Ifaddp, + UD_Ifbld, + UD_Ifbstp, + UD_Ifchs, + UD_Ifclex, + UD_Ifcmovb, + UD_Ifcmove, + UD_Ifcmovbe, + UD_Ifcmovu, + UD_Ifcmovnb, + UD_Ifcmovne, + UD_Ifcmovnbe, + UD_Ifcmovnu, + UD_Ifucomi, + UD_Ifcom, + UD_Ifcom2, + UD_Ifcomp3, + UD_Ifcomi, + UD_Ifucomip, + UD_Ifcomip, + UD_Ifcomp, + UD_Ifcomp5, + UD_Ifcompp, + UD_Ifcos, + UD_Ifdecstp, + UD_Ifdiv, + UD_Ifdivp, + UD_Ifdivr, + UD_Ifdivrp, + UD_Ifemms, + UD_Iffree, + UD_Iffreep, + UD_Ificom, + UD_Ificomp, + UD_Ifild, + UD_Ifncstp, + UD_Ifninit, + UD_Ifiadd, + UD_Ifidivr, + UD_Ifidiv, + UD_Ifisub, + UD_Ifisubr, + UD_Ifist, + UD_Ifistp, + UD_Ifisttp, + UD_Ifld, + UD_Ifld1, + UD_Ifldl2t, + UD_Ifldl2e, + UD_Ifldlpi, + UD_Ifldlg2, + UD_Ifldln2, + UD_Ifldz, + UD_Ifldcw, + UD_Ifldenv, + UD_Ifmul, + UD_Ifmulp, + UD_Ifimul, + UD_Ifnop, + UD_Ifpatan, + UD_Ifprem, + UD_Ifprem1, + UD_Ifptan, + UD_Ifrndint, + UD_Ifrstor, + UD_Ifnsave, + UD_Ifscale, + UD_Ifsin, + UD_Ifsincos, + UD_Ifsqrt, + UD_Ifstp, + UD_Ifstp1, + UD_Ifstp8, + UD_Ifstp9, + UD_Ifst, + UD_Ifnstcw, + UD_Ifnstenv, + UD_Ifnstsw, + UD_Ifsub, + UD_Ifsubp, + UD_Ifsubr, + UD_Ifsubrp, + UD_Iftst, + UD_Ifucom, + UD_Ifucomp, + UD_Ifucompp, + UD_Ifxam, + UD_Ifxch, + UD_Ifxch4, + UD_Ifxch7, + UD_Ifxrstor, + UD_Ifxsave, + UD_Ifpxtract, + UD_Ifyl2x, + UD_Ifyl2xp1, + UD_Ihaddpd, + UD_Ihaddps, + UD_Ihlt, + UD_Ihsubpd, + UD_Ihsubps, + UD_Iidiv, + UD_Iin, + UD_Iimul, + UD_Iinc, + UD_Iinsb, + UD_Iinsw, + UD_Iinsd, + UD_Iint1, + UD_Iint3, + UD_Iint, + UD_Iinto, + UD_Iinvd, + UD_Iinvlpg, + UD_Iinvlpga, + UD_Iiretw, + UD_Iiretd, + UD_Iiretq, + UD_Ijo, + UD_Ijno, + UD_Ijb, + UD_Ijae, + UD_Ijz, + UD_Ijnz, + UD_Ijbe, + UD_Ija, + UD_Ijs, + UD_Ijns, + UD_Ijp, + UD_Ijnp, + UD_Ijl, + UD_Ijge, + UD_Ijle, + UD_Ijg, + UD_Ijcxz, + UD_Ijecxz, + UD_Ijrcxz, + UD_Ijmp, + UD_Ilahf, + UD_Ilar, + UD_Ilddqu, + UD_Ildmxcsr, + UD_Ilds, + UD_Ilea, + UD_Iles, + UD_Ilfs, + UD_Ilgs, + UD_Ilidt, + UD_Ilss, + UD_Ileave, + UD_Ilfence, + UD_Ilgdt, + UD_Illdt, + UD_Ilmsw, + UD_Ilock, + UD_Ilodsb, + UD_Ilodsw, + UD_Ilodsd, + UD_Ilodsq, + UD_Iloopnz, + UD_Iloope, + UD_Iloop, + UD_Ilsl, + UD_Iltr, + UD_Imaskmovq, + UD_Imaxpd, + UD_Imaxps, + UD_Imaxsd, + UD_Imaxss, + UD_Imfence, + UD_Iminpd, + UD_Iminps, + UD_Iminsd, + UD_Iminss, + UD_Imonitor, + UD_Imov, + UD_Imovapd, + UD_Imovaps, + UD_Imovd, + UD_Imovddup, + UD_Imovdqa, + UD_Imovdqu, + UD_Imovdq2q, + UD_Imovhpd, + UD_Imovhps, + UD_Imovlhps, + UD_Imovlpd, + UD_Imovlps, + UD_Imovhlps, + UD_Imovmskpd, + UD_Imovmskps, + UD_Imovntdq, + UD_Imovnti, + UD_Imovntpd, + UD_Imovntps, + UD_Imovntq, + UD_Imovq, + UD_Imovqa, + UD_Imovq2dq, + UD_Imovsb, + UD_Imovsw, + UD_Imovsd, + UD_Imovsq, + UD_Imovsldup, + UD_Imovshdup, + UD_Imovss, + UD_Imovsx, + UD_Imovupd, + UD_Imovups, + UD_Imovzx, + UD_Imul, + UD_Imulpd, + UD_Imulps, + UD_Imulsd, + UD_Imulss, + UD_Imwait, + UD_Ineg, + UD_Inop, + UD_Inot, + UD_Ior, + UD_Iorpd, + UD_Iorps, + UD_Iout, + UD_Ioutsb, + UD_Ioutsw, + UD_Ioutsd, + UD_Ioutsq, + UD_Ipacksswb, + UD_Ipackssdw, + UD_Ipackuswb, + UD_Ipaddb, + UD_Ipaddw, + UD_Ipaddq, + UD_Ipaddsb, + UD_Ipaddsw, + UD_Ipaddusb, + UD_Ipaddusw, + UD_Ipand, + UD_Ipandn, + UD_Ipause, + UD_Ipavgb, + UD_Ipavgw, + UD_Ipcmpeqb, + UD_Ipcmpeqw, + UD_Ipcmpeqd, + UD_Ipcmpgtb, + UD_Ipcmpgtw, + UD_Ipcmpgtd, + UD_Ipextrw, + UD_Ipinsrw, + UD_Ipmaddwd, + UD_Ipmaxsw, + UD_Ipmaxub, + UD_Ipminsw, + UD_Ipminub, + UD_Ipmovmskb, + UD_Ipmulhuw, + UD_Ipmulhw, + UD_Ipmullw, + UD_Ipmuludq, + UD_Ipop, + UD_Ipopa, + UD_Ipopad, + UD_Ipopfw, + UD_Ipopfd, + UD_Ipopfq, + UD_Ipor, + UD_Iprefetch, + UD_Iprefetchnta, + UD_Iprefetcht0, + UD_Iprefetcht1, + UD_Iprefetcht2, + UD_Ipsadbw, + UD_Ipshufd, + UD_Ipshufhw, + UD_Ipshuflw, + UD_Ipshufw, + UD_Ipslldq, + UD_Ipsllw, + UD_Ipslld, + UD_Ipsllq, + UD_Ipsraw, + UD_Ipsrad, + UD_Ipsrlw, + UD_Ipsrld, + UD_Ipsrlq, + UD_Ipsrldq, + UD_Ipsubb, + UD_Ipsubw, + UD_Ipsubd, + UD_Ipsubq, + UD_Ipsubsb, + UD_Ipsubsw, + UD_Ipsubusb, + UD_Ipsubusw, + UD_Ipunpckhbw, + UD_Ipunpckhwd, + UD_Ipunpckhdq, + UD_Ipunpckhqdq, + UD_Ipunpcklbw, + UD_Ipunpcklwd, + UD_Ipunpckldq, + UD_Ipunpcklqdq, + UD_Ipi2fw, + UD_Ipi2fd, + UD_Ipf2iw, + UD_Ipf2id, + UD_Ipfnacc, + UD_Ipfpnacc, + UD_Ipfcmpge, + UD_Ipfmin, + UD_Ipfrcp, + UD_Ipfrsqrt, + UD_Ipfsub, + UD_Ipfadd, + UD_Ipfcmpgt, + UD_Ipfmax, + UD_Ipfrcpit1, + UD_Ipfrspit1, + UD_Ipfsubr, + UD_Ipfacc, + UD_Ipfcmpeq, + UD_Ipfmul, + UD_Ipfrcpit2, + UD_Ipmulhrw, + UD_Ipswapd, + UD_Ipavgusb, + UD_Ipush, + UD_Ipusha, + UD_Ipushad, + UD_Ipushfw, + UD_Ipushfd, + UD_Ipushfq, + UD_Ipxor, + UD_Ircl, + UD_Ircr, + UD_Irol, + UD_Iror, + UD_Ircpps, + UD_Ircpss, + UD_Irdmsr, + UD_Irdpmc, + UD_Irdtsc, + UD_Irdtscp, + UD_Irepne, + UD_Irep, + UD_Iret, + UD_Iretf, + UD_Irsm, + UD_Irsqrtps, + UD_Irsqrtss, + UD_Isahf, + UD_Isal, + UD_Isalc, + UD_Isar, + UD_Ishl, + UD_Ishr, + UD_Isbb, + UD_Iscasb, + UD_Iscasw, + UD_Iscasd, + UD_Iscasq, + UD_Iseto, + UD_Isetno, + UD_Isetb, + UD_Isetnb, + UD_Isetz, + UD_Isetnz, + UD_Isetbe, + UD_Iseta, + UD_Isets, + UD_Isetns, + UD_Isetp, + UD_Isetnp, + UD_Isetl, + UD_Isetge, + UD_Isetle, + UD_Isetg, + UD_Isfence, + UD_Isgdt, + UD_Ishld, + UD_Ishrd, + UD_Ishufpd, + UD_Ishufps, + UD_Isidt, + UD_Isldt, + UD_Ismsw, + UD_Isqrtps, + UD_Isqrtpd, + UD_Isqrtsd, + UD_Isqrtss, + UD_Istc, + UD_Istd, + UD_Istgi, + UD_Isti, + UD_Iskinit, + UD_Istmxcsr, + UD_Istosb, + UD_Istosw, + UD_Istosd, + UD_Istosq, + UD_Istr, + UD_Isub, + UD_Isubpd, + UD_Isubps, + UD_Isubsd, + UD_Isubss, + UD_Iswapgs, + UD_Isyscall, + UD_Isysenter, + UD_Isysexit, + UD_Isysret, + UD_Itest, + UD_Iucomisd, + UD_Iucomiss, + UD_Iud2, + UD_Iunpckhpd, + UD_Iunpckhps, + UD_Iunpcklps, + UD_Iunpcklpd, + UD_Iverr, + UD_Iverw, + UD_Ivmcall, + UD_Ivmclear, + UD_Ivmxon, + UD_Ivmptrld, + UD_Ivmptrst, + UD_Ivmresume, + UD_Ivmxoff, + UD_Ivmrun, + UD_Ivmmcall, + UD_Ivmload, + UD_Ivmsave, + UD_Iwait, + UD_Iwbinvd, + UD_Iwrmsr, + UD_Ixadd, + UD_Ixchg, + UD_Ixlatb, + UD_Ixor, + UD_Ixorpd, + UD_Ixorps, + UD_Idb, + UD_Iinvalid, + UD_Id3vil, + UD_Ina, + UD_Igrp_reg, + UD_Igrp_rm, + UD_Igrp_vendor, + UD_Igrp_x87, + UD_Igrp_mode, + UD_Igrp_osize, + UD_Igrp_asize, + UD_Igrp_mod, + UD_Inone, +}; + + + +extern const char* ud_mnemonics_str[];; +extern struct ud_itab_entry* ud_itab_list[]; + +#endif diff --git a/xen/kdb/x86/udis86-1.7/kdb_dis.c b/xen/kdb/x86/udis86-1.7/kdb_dis.c new file mode 100644 index 0000000..7dadb60 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/kdb_dis.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include /* for XEN_SUBVERSION */ +#include "../../include/kdbinc.h" +#include "extern.h" + +static void (*dis_syntax)(ud_t*) = UD_SYN_ATT; /* default dis-assembly syntax */ + +static struct { /* info for kdb_read_byte_for_ud() */ + kdbva_t kud_instr_addr; + domid_t kud_domid; +} kdb_ud_rd_info; + +/* called via function ptr by ud when disassembling. + * kdb info passed via kdb_ud_rd_info{} + */ +static int +kdb_read_byte_for_ud(struct ud *udp) +{ + kdbbyt_t bytebuf; + domid_t domid = kdb_ud_rd_info.kud_domid; + kdbva_t addr = kdb_ud_rd_info.kud_instr_addr; + + if (kdb_read_mem(addr, &bytebuf, 1, domid) == 1) { + kdb_ud_rd_info.kud_instr_addr++; + KDBGP1("udrd:addr:%lx domid:%d byt:%x\n", addr, domid, bytebuf); + return bytebuf; + } + KDBGP1("udrd:addr:%lx domid:%d err\n", addr, domid); + return UD_EOI; +} + +/* + * given a domid, convert addr to symbol and print it + * Eg: ffff828c801235e2: idle_loop+52 jmp idle_loop+55 + * Called twice here for idle_loop. In first case, nl is null, + * in the second case nl == '\n' + */ +void +kdb_prnt_addr2sym(domid_t domid, kdbva_t addr, char *nl) +{ + unsigned long sz, offs; + char buf[KSYM_NAME_LEN+1], pbuf[150], prefix[8]; + char *p = buf; + + prefix[0]='\0'; + if (domid != DOMID_IDLE) { + snprintf(prefix, 8, "%x:", domid); + p = kdb_guest_addr2sym(addr, domid, &offs); + } else + symbols_lookup(addr, &sz, &offs, buf); + + snprintf(pbuf, 150, "%s%s+%lx", prefix, p, offs); + if (*nl != '\n') + kdbp("%-30s%s", pbuf, nl); /* prints more than 30 if needed */ + else + kdbp("%s%s", pbuf, nl); + +} + +static int +kdb_jump_instr(enum ud_mnemonic_code mnemonic) +{ + return (mnemonic >= UD_Ijo && mnemonic <= UD_Ijmp); +} + +/* + * print one instr: function so that we can print offsets of jmp etc.. as + * symbol+offset instead of just address + */ +static void +kdb_print_one_instr(struct ud *udp, domid_t domid) +{ + signed long val = 0; + ud_type_t type = udp->operand[0].type; + + if ((udp->mnemonic == UD_Icall || kdb_jump_instr(udp->mnemonic)) && + type == UD_OP_JIMM) { + + int sz = udp->operand[0].size; + char *p, ibuf[40], *q = ibuf; + kdbva_t addr; + + if (sz == 8) val = udp->operand[0].lval.sbyte; + else if (sz == 16) val = udp->operand[0].lval.sword; + else if (sz == 32) val = udp->operand[0].lval.sdword; + else if (sz == 64) val = udp->operand[0].lval.sqword; + else kdbp("kdb_print_one_instr: Inval sz:z%d\n", sz); + + addr = udp->pc + val; + for(p=ud_insn_asm(udp); (*q=*p) && *p!=' '; p++,q++); + *q='\0'; + kdbp(" %-4s ", ibuf); /* space before for long func names */ + kdb_prnt_addr2sym(domid, addr, "\n"); + } else + kdbp(" %-24s\n", ud_insn_asm(udp)); +#if 0 + kdbp("mnemonic:z%d ", udp->mnemonic); + if (type == UD_OP_CONST) kdbp("type is const\n"); + else if (type == UD_OP_JIMM) kdbp("type is JIMM\n"); + else if (type == UD_OP_IMM) kdbp("type is IMM\n"); + else if (type == UD_OP_PTR) kdbp("type is PTR\n"); +#endif +} + +static void +kdb_setup_ud(struct ud *udp, kdbva_t addr, domid_t domid) +{ + int bitness = kdb_guest_bitness(domid); + uint vendor = (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) ? + UD_VENDOR_AMD : UD_VENDOR_INTEL; + + KDBGP1("setup_ud:domid:%d bitness:%d addr:%lx\n", domid, bitness, addr); + ud_init(udp); + ud_set_mode(udp, kdb_guest_bitness(domid)); + ud_set_syntax(udp, dis_syntax); + ud_set_vendor(udp, vendor); /* HVM: vmx/svm different instrs*/ + ud_set_pc(udp, addr); /* for numbers printed on left */ + ud_set_input_hook(udp, kdb_read_byte_for_ud); + kdb_ud_rd_info.kud_instr_addr = addr; + kdb_ud_rd_info.kud_domid = domid; +} + +/* + * given an addr, print given number of instructions. + * Returns: address of next instruction in the stream + */ +kdbva_t +kdb_print_instr(kdbva_t addr, long num, domid_t domid) +{ + struct ud ud_s; + + KDBGP1("print_instr:addr:0x%lx num:%ld domid:%x\n", addr, num, domid); + + kdb_setup_ud(&ud_s, addr, domid); + while(num--) { + if (ud_disassemble(&ud_s)) { + uint64_t pc = ud_insn_off(&ud_s); + /* kdbp("%08x: ",(int)pc); */ + kdbp("%016lx: ", pc); + kdb_prnt_addr2sym(domid, pc, ""); + kdb_print_one_instr(&ud_s, domid); + } else + kdbp("KDB:Couldn't disassemble PC:0x%lx\n", addr); + /* for stack reads, don't always display error */ + } + KDBGP1("print_instr:kudaddr:0x%lx\n", kdb_ud_rd_info.kud_instr_addr); + return kdb_ud_rd_info.kud_instr_addr; +} + +void +kdb_display_pc(struct cpu_user_regs *regs) +{ + domid_t domid; + struct cpu_user_regs regs1 = *regs; + domid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; + + regs1.KDBIP = regs->KDBIP; + kdb_print_instr(regs1.KDBIP, 1, domid); +} + +/* check if the instr at the addr is call instruction + * RETURNS: size of the instr if it's a call instr, else 0 + */ +int +kdb_check_call_instr(domid_t domid, kdbva_t addr) +{ + struct ud ud_s; + int sz; + + kdb_setup_ud(&ud_s, addr, domid); + if ((sz=ud_disassemble(&ud_s)) && ud_s.mnemonic == UD_Icall) + return (sz); + return 0; +} + +/* toggle ATT and Intel syntaxes */ +void +kdb_toggle_dis_syntax(void) +{ + if (dis_syntax == UD_SYN_INTEL) { + dis_syntax = UD_SYN_ATT; + kdbp("dis syntax now set to ATT (Gas)\n"); + } else { + dis_syntax = UD_SYN_INTEL; + kdbp("dis syntax now set to Intel (NASM)\n"); + } +} diff --git a/xen/kdb/x86/udis86-1.7/syn-att.c b/xen/kdb/x86/udis86-1.7/syn-att.c new file mode 100644 index 0000000..79fcc7f --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/syn-att.c @@ -0,0 +1,211 @@ +/* ----------------------------------------------------------------------------- + * syn-att.c + * + * Copyright (c) 2004, 2005, 2006 Vivek Mohan + * All rights reserved. See (LICENSE) + * ----------------------------------------------------------------------------- + */ + +#include "types.h" +#include "extern.h" +#include "decode.h" +#include "itab.h" +#include "syn.h" + +/* ----------------------------------------------------------------------------- + * opr_cast() - Prints an operand cast. + * ----------------------------------------------------------------------------- + */ +static void +opr_cast(struct ud* u, struct ud_operand* op) +{ + switch(op->size) { + case 16 : case 32 : + mkasm(u, "*"); break; + default: break; + } +} + +/* ----------------------------------------------------------------------------- + * gen_operand() - Generates assembly output for each operand. + * ----------------------------------------------------------------------------- + */ +static void +gen_operand(struct ud* u, struct ud_operand* op) +{ + switch(op->type) { + case UD_OP_REG: + mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: + if (u->br_far) opr_cast(u, op); + if (u->pfx_seg) + mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + if (op->offset == 8) { + if (op->lval.sbyte < 0) + mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff); + else mkasm(u, "0x%x", op->lval.sbyte); + } + else if (op->offset == 16) + mkasm(u, "0x%x", op->lval.uword); + else if (op->offset == 32) + mkasm(u, "0x%lx", op->lval.udword); + else if (op->offset == 64) + mkasm(u, "0x" FMT64 "x", op->lval.uqword); + + if (op->base) + mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); + if (op->index) { + if (op->base) + mkasm(u, ","); + else mkasm(u, "("); + mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); + } + if (op->scale) + mkasm(u, ",%d", op->scale); + if (op->base || op->index) + mkasm(u, ")"); + break; + + case UD_OP_IMM: + switch (op->size) { + case 8: mkasm(u, "$0x%x", op->lval.ubyte); break; + case 16: mkasm(u, "$0x%x", op->lval.uword); break; + case 32: mkasm(u, "$0x%lx", op->lval.udword); break; + case 64: mkasm(u, "$0x" FMT64 "x", op->lval.uqword); break; + default: break; + } + break; + + case UD_OP_JIMM: + switch (op->size) { + case 8: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); + break; + case 16: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); + break; + case 32: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); + break; + default:break; + } + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + default: return; + } +} + +/* ============================================================================= + * translates to AT&T syntax + * ============================================================================= + */ +extern void +ud_translate_att(struct ud *u) +{ + int size = 0; + + /* check if P_OSO prefix is used */ + if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { + switch (u->dis_mode) { + case 16: + mkasm(u, "o32 "); + break; + case 32: + case 64: + mkasm(u, "o16 "); + break; + } + } + + /* check if P_ASO prefix was used */ + if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { + switch (u->dis_mode) { + case 16: + mkasm(u, "a32 "); + break; + case 32: + mkasm(u, "a16 "); + break; + case 64: + mkasm(u, "a32 "); + break; + } + } + + if (u->pfx_lock) + mkasm(u, "lock "); + if (u->pfx_rep) + mkasm(u, "rep "); + if (u->pfx_repne) + mkasm(u, "repne "); + + /* special instructions */ + switch (u->mnemonic) { + case UD_Iretf: + mkasm(u, "lret "); + break; + case UD_Idb: + mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte); + return; + case UD_Ijmp: + case UD_Icall: + if (u->br_far) mkasm(u, "l"); + mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + break; + case UD_Ibound: + case UD_Ienter: + if (u->operand[0].type != UD_NONE) + gen_operand(u, &u->operand[0]); + if (u->operand[1].type != UD_NONE) { + mkasm(u, ","); + gen_operand(u, &u->operand[1]); + } + return; + default: + mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + } + + if (u->c1) + size = u->operand[0].size; + else if (u->c2) + size = u->operand[1].size; + else if (u->c3) + size = u->operand[2].size; + + if (size == 8) + mkasm(u, "b"); + else if (size == 16) + mkasm(u, "w"); + else if (size == 64) + mkasm(u, "q"); + + mkasm(u, " "); + + if (u->operand[2].type != UD_NONE) { + gen_operand(u, &u->operand[2]); + mkasm(u, ", "); + } + + if (u->operand[1].type != UD_NONE) { + gen_operand(u, &u->operand[1]); + mkasm(u, ", "); + } + + if (u->operand[0].type != UD_NONE) + gen_operand(u, &u->operand[0]); +} diff --git a/xen/kdb/x86/udis86-1.7/syn-intel.c b/xen/kdb/x86/udis86-1.7/syn-intel.c new file mode 100644 index 0000000..350253a --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/syn-intel.c @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- + * syn-intel.c + * + * Copyright (c) 2002, 2003, 2004 Vivek Mohan + * All rights reserved. See (LICENSE) + * ----------------------------------------------------------------------------- + */ + +#include "types.h" +#include "extern.h" +#include "decode.h" +#include "itab.h" +#include "syn.h" + +/* ----------------------------------------------------------------------------- + * opr_cast() - Prints an operand cast. + * ----------------------------------------------------------------------------- + */ +static void +opr_cast(struct ud* u, struct ud_operand* op) +{ + switch(op->size) { + case 8: mkasm(u, "byte " ); break; + case 16: mkasm(u, "word " ); break; + case 32: mkasm(u, "dword "); break; + case 64: mkasm(u, "qword "); break; + case 80: mkasm(u, "tword "); break; + default: break; + } + if (u->br_far) + mkasm(u, "far "); + else if (u->br_near) + mkasm(u, "near "); +} + +/* ----------------------------------------------------------------------------- + * gen_operand() - Generates assembly output for each operand. + * ----------------------------------------------------------------------------- + */ +static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) +{ + switch(op->type) { + case UD_OP_REG: + mkasm(u, ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: { + + int op_f = 0; + + if (syn_cast) + opr_cast(u, op); + + mkasm(u, "["); + + if (u->pfx_seg) + mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + + if (op->base) { + mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); + op_f = 1; + } + + if (op->index) { + if (op_f) + mkasm(u, "+"); + mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]); + op_f = 1; + } + + if (op->scale) + mkasm(u, "*%d", op->scale); + + if (op->offset == 8) { + if (op->lval.sbyte < 0) + mkasm(u, "-0x%x", -op->lval.sbyte); + else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte); + } + else if (op->offset == 16) + mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword); + else if (op->offset == 32) { + if (u->adr_mode == 64) { + if (op->lval.sdword < 0) + mkasm(u, "-0x%x", -op->lval.sdword); + else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword); + } + else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", op->lval.udword); + } + else if (op->offset == 64) + mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword); + + mkasm(u, "]"); + break; + } + + case UD_OP_IMM: + if (syn_cast) opr_cast(u, op); + switch (op->size) { + case 8: mkasm(u, "0x%x", op->lval.ubyte); break; + case 16: mkasm(u, "0x%x", op->lval.uword); break; + case 32: mkasm(u, "0x%lx", op->lval.udword); break; + case 64: mkasm(u, "0x" FMT64 "x", op->lval.uqword); break; + default: break; + } + break; + + case UD_OP_JIMM: + if (syn_cast) opr_cast(u, op); + switch (op->size) { + case 8: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); + break; + case 16: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); + break; + case 32: + mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); + break; + default:break; + } + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + case UD_OP_CONST: + if (syn_cast) opr_cast(u, op); + mkasm(u, "%d", op->lval.udword); + break; + + default: return; + } +} + +/* ============================================================================= + * translates to intel syntax + * ============================================================================= + */ +extern void ud_translate_intel(struct ud* u) +{ + /* -- prefixes -- */ + + /* check if P_OSO prefix is used */ + if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { + switch (u->dis_mode) { + case 16: + mkasm(u, "o32 "); + break; + case 32: + case 64: + mkasm(u, "o16 "); + break; + } + } + + /* check if P_ASO prefix was used */ + if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { + switch (u->dis_mode) { + case 16: + mkasm(u, "a32 "); + break; + case 32: + mkasm(u, "a16 "); + break; + case 64: + mkasm(u, "a32 "); + break; + } + } + + if (u->pfx_lock) + mkasm(u, "lock "); + if (u->pfx_rep) + mkasm(u, "rep "); + if (u->pfx_repne) + mkasm(u, "repne "); + if (u->implicit_addr && u->pfx_seg) + mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); + + /* print the instruction mnemonic */ + mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic)); + + /* operand 1 */ + if (u->operand[0].type != UD_NONE) { + gen_operand(u, &u->operand[0], u->c1); + } + /* operand 2 */ + if (u->operand[1].type != UD_NONE) { + mkasm(u, ", "); + gen_operand(u, &u->operand[1], u->c2); + } + + /* operand 3 */ + if (u->operand[2].type != UD_NONE) { + mkasm(u, ", "); + gen_operand(u, &u->operand[2], u->c3); + } +} diff --git a/xen/kdb/x86/udis86-1.7/syn.c b/xen/kdb/x86/udis86-1.7/syn.c new file mode 100644 index 0000000..8019a11 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/syn.c @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------- + * syn.c + * + * Copyright (c) 2002, 2003, 2004 Vivek Mohan + * All rights reserved. See (LICENSE) + * ----------------------------------------------------------------------------- + */ + +/* ----------------------------------------------------------------------------- + * Intel Register Table - Order Matters (types.h)! + * ----------------------------------------------------------------------------- + */ +const char* ud_reg_tab[] = +{ + "al", "cl", "dl", "bl", + "ah", "ch", "dh", "bh", + "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", + "r12b", "r13b", "r14b", "r15b", + + "ax", "cx", "dx", "bx", + "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", + "r12w", "r13W" , "r14w", "r15w", + + "eax", "ecx", "edx", "ebx", + "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", + "r12d", "r13d", "r14d", "r15d", + + "rax", "rcx", "rdx", "rbx", + "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + + "es", "cs", "ss", "ds", + "fs", "gs", + + "cr0", "cr1", "cr2", "cr3", + "cr4", "cr5", "cr6", "cr7", + "cr8", "cr9", "cr10", "cr11", + "cr12", "cr13", "cr14", "cr15", + + "dr0", "dr1", "dr2", "dr3", + "dr4", "dr5", "dr6", "dr7", + "dr8", "dr9", "dr10", "dr11", + "dr12", "dr13", "dr14", "dr15", + + "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7", + + "st0", "st1", "st2", "st3", + "st4", "st5", "st6", "st7", + + "xmm0", "xmm1", "xmm2", "xmm3", + "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15", + + "rip" +}; diff --git a/xen/kdb/x86/udis86-1.7/syn.h b/xen/kdb/x86/udis86-1.7/syn.h new file mode 100644 index 0000000..5cd6b26 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/syn.h @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + * syn.h + * + * Copyright (c) 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ +#ifndef UD_SYN_H +#define UD_SYN_H + +#if 0 +#include +#include +#endif +#include "types.h" + +extern const char* ud_reg_tab[]; + +static void mkasm(struct ud* u, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + u->insn_fill += vsnprintf((char*) u->insn_buffer + u->insn_fill, 64, fmt, ap); + va_end(ap); +} + +#endif diff --git a/xen/kdb/x86/udis86-1.7/types.h b/xen/kdb/x86/udis86-1.7/types.h new file mode 100644 index 0000000..2396a02 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/types.h @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------------- + * types.h + * + * Copyright (c) 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ +#ifndef UD_TYPES_H +#define UD_TYPES_H + + +#include "../../include/kdbinc.h" + +#define FMT64 "%ll" +#include "itab.h" + +/* ----------------------------------------------------------------------------- + * All possible "types" of objects in udis86. Order is Important! + * ----------------------------------------------------------------------------- + */ +enum ud_type +{ + UD_NONE, + + /* 8 bit GPRs */ + UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, + UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, + UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, + UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, + UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, + + /* 16 bit GPRs */ + UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, + UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, + UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, + UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, + + /* 32 bit GPRs */ + UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, + UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, + UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, + UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, + + /* 64 bit GPRs */ + UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, + UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, + UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, + UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, + + /* segment registers */ + UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, + UD_R_FS, UD_R_GS, + + /* control registers*/ + UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, + UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, + UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, + UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, + + /* debug registers */ + UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, + UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, + UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, + UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, + + /* mmx registers */ + UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, + UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, + + /* x87 registers */ + UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, + UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, + + /* extended multimedia registers */ + UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, + UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, + UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, + UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, + + UD_R_RIP, + + /* Operand Types */ + UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, + UD_OP_JIMM, UD_OP_CONST +}; + +/* ----------------------------------------------------------------------------- + * struct ud_operand - Disassembled instruction Operand. + * ----------------------------------------------------------------------------- + */ +struct ud_operand +{ + enum ud_type type; + uint8_t size; + union { + int8_t sbyte; + uint8_t ubyte; + int16_t sword; + uint16_t uword; + int32_t sdword; + uint32_t udword; + int64_t sqword; + uint64_t uqword; + + struct { + uint16_t seg; + uint32_t off; + } ptr; + } lval; + + enum ud_type base; + enum ud_type index; + uint8_t offset; + uint8_t scale; +}; + +/* ----------------------------------------------------------------------------- + * struct ud - The udis86 object. + * ----------------------------------------------------------------------------- + */ +struct ud +{ + int (*inp_hook) (struct ud*); + uint8_t inp_curr; + uint8_t inp_fill; + uint8_t inp_ctr; + uint8_t* inp_buff; + uint8_t* inp_buff_end; + uint8_t inp_end; + void (*translator)(struct ud*); + uint64_t insn_offset; + char insn_hexcode[32]; + char insn_buffer[64]; + unsigned int insn_fill; + uint8_t dis_mode; + uint64_t pc; + uint8_t vendor; + struct map_entry* mapen; + enum ud_mnemonic_code mnemonic; + struct ud_operand operand[3]; + uint8_t error; + uint8_t pfx_rex; + uint8_t pfx_seg; + uint8_t pfx_opr; + uint8_t pfx_adr; + uint8_t pfx_lock; + uint8_t pfx_rep; + uint8_t pfx_repe; + uint8_t pfx_repne; + uint8_t pfx_insn; + uint8_t default64; + uint8_t opr_mode; + uint8_t adr_mode; + uint8_t br_far; + uint8_t br_near; + uint8_t implicit_addr; + uint8_t c1; + uint8_t c2; + uint8_t c3; + uint8_t inp_cache[256]; + uint8_t inp_sess[64]; + struct ud_itab_entry * itab_entry; +}; + +/* ----------------------------------------------------------------------------- + * Type-definitions + * ----------------------------------------------------------------------------- + */ +typedef enum ud_type ud_type_t; +typedef enum ud_mnemonic_code ud_mnemonic_code_t; + +typedef struct ud ud_t; +typedef struct ud_operand ud_operand_t; + +#define UD_SYN_INTEL ud_translate_intel +#define UD_SYN_ATT ud_translate_att +#define UD_EOI -1 +#define UD_INP_CACHE_SZ 32 +#define UD_VENDOR_AMD 0 +#define UD_VENDOR_INTEL 1 + +#define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code ) +#define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 ) +#define catch_error() else + +#endif diff --git a/xen/kdb/x86/udis86-1.7/udis86.c b/xen/kdb/x86/udis86-1.7/udis86.c new file mode 100644 index 0000000..9cc2e61 --- /dev/null +++ b/xen/kdb/x86/udis86-1.7/udis86.c @@ -0,0 +1,156 @@ +/* ----------------------------------------------------------------------------- + * udis86.c + * + * Copyright (c) 2004, 2005, 2006, Vivek Mohan + * All rights reserved. See LICENSE + * ----------------------------------------------------------------------------- + */ + +#if 0 +#include +#include +#include +#endif + +#include "input.h" +#include "extern.h" + +/* ============================================================================= + * ud_init() - Initializes ud_t object. + * ============================================================================= + */ +extern void +ud_init(struct ud* u) +{ + memset((void*)u, 0, sizeof(struct ud)); + ud_set_mode(u, 16); + u->mnemonic = UD_Iinvalid; + ud_set_pc(u, 0); +#ifndef __UD_STANDALONE__ + ud_set_input_file(u, stdin); +#endif /* __UD_STANDALONE__ */ +} + +/* ============================================================================= + * ud_disassemble() - disassembles one instruction and returns the number of + * bytes disassembled. A zero means end of disassembly. + * ============================================================================= + */ +extern unsigned int +ud_disassemble(struct ud* u) +{ + if (ud_input_end(u)) + return 0; + + + u->insn_buffer[0] = u->insn_hexcode[0] = 0; + + + if (ud_decode(u) == 0) + return 0; + if (u->translator) + u->translator(u); + return ud_insn_len(u); +} + +/* ============================================================================= + * ud_set_mode() - Set Disassemly Mode. + * ============================================================================= + */ +extern void +ud_set_mode(struct ud* u, uint8_t m) +{ + switch(m) { + case 16: + case 32: + case 64: u->dis_mode = m ; return; + default: u->dis_mode = 16; return; + } +} + +/* ============================================================================= + * ud_set_vendor() - Set vendor. + * ============================================================================= + */ +extern void +ud_set_vendor(struct ud* u, unsigned v) +{ + switch(v) { + case UD_VENDOR_INTEL: + u->vendor = v; + break; + default: + u->vendor = UD_VENDOR_AMD; + } +} + +/* ============================================================================= + * ud_set_pc() - Sets code origin. + * ============================================================================= + */ +extern void +ud_set_pc(struct ud* u, uint64_t o) +{ + u->pc = o; +} + +/* ============================================================================= + * ud_set_syntax() - Sets the output syntax. + * ============================================================================= + */ +extern void +ud_set_syntax(struct ud* u, void (*t)(struct ud*)) +{ + u->translator = t; +} + +/* ============================================================================= + * ud_insn() - returns the disassembled instruction + * ============================================================================= + */ +extern char* +ud_insn_asm(struct ud* u) +{ + return u->insn_buffer; +} + +/* ============================================================================= + * ud_insn_offset() - Returns the offset. + * ============================================================================= + */ +extern uint64_t +ud_insn_off(struct ud* u) +{ + return u->insn_offset; +} + + +/* ============================================================================= + * ud_insn_hex() - Returns hex form of disassembled instruction. + * ============================================================================= + */ +extern char* +ud_insn_hex(struct ud* u) +{ + return u->insn_hexcode; +} + +/* ============================================================================= + * ud_insn_ptr() - Returns code disassembled. + * ============================================================================= + */ +extern uint8_t* +ud_insn_ptr(struct ud* u) +{ + return u->inp_sess; +} + +/* ============================================================================= + * ud_insn_len() - Returns the count of bytes disassembled. + * ============================================================================= + */ +extern unsigned int +ud_insn_len(struct ud* u) +{ + return u->inp_ctr; +} -- 1.8.3.1