#define SrcImmUByte (8<<4)      /* 8-bit unsigned immediate operand. */
 #define SrcImmU     (9<<4)      /* Immediate operand, unsigned */
 #define SrcSI       (0xa<<4)   /* Source is in the DS:RSI */
+#define SrcImmFAddr (0xb<<4)   /* Source is immediate far address */
+#define SrcMemFAddr (0xc<<4)   /* Source is far address in memory */
 #define SrcMask     (0xf<<4)
 /* Generic ModRM decode. */
 #define ModRM       (1<<8)
 #define Src2CL      (1<<29)
 #define Src2ImmByte (2<<29)
 #define Src2One     (3<<29)
-#define Src2Imm16   (4<<29)
-#define Src2Mem16   (5<<29) /* Used for Ep encoding. First argument has to be
-                              in memory and second argument is located
-                              immediately after the first one in memory. */
 #define Src2Mask    (7<<29)
 
 enum {
        /* 0x90 - 0x97 */
        DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
        /* 0x98 - 0x9F */
-       0, 0, SrcImm | Src2Imm16 | No64, 0,
+       0, 0, SrcImmFAddr | No64, 0,
        ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
        /* 0xA0 - 0xA7 */
        ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
        ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc,
        /* 0xE8 - 0xEF */
        SrcImm | Stack, SrcImm | ImplicitOps,
-       SrcImmU | Src2Imm16 | No64, SrcImmByte | ImplicitOps,
+       SrcImmFAddr | No64, SrcImmByte | ImplicitOps,
        SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
        SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
        /* 0xF0 - 0xF7 */
        [Group5*8] =
        DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
        SrcMem | ModRM | Stack, 0,
-       SrcMem | ModRM | Stack, SrcMem | ModRM | Src2Mem16 | ImplicitOps,
+       SrcMem | ModRM | Stack, SrcMemFAddr | ModRM | ImplicitOps,
        SrcMem | ModRM | Stack, 0,
        [Group7*8] =
        0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
        (_type)_x;                                                      \
 })
 
+#define insn_fetch_arr(_arr, _size, _eip)                                \
+({     rc = do_insn_fetch(ctxt, ops, (_eip), _arr, (_size));           \
+       if (rc != X86EMUL_CONTINUE)                                     \
+               goto done;                                              \
+       (_eip) += (_size);                                              \
+})
+
 static inline unsigned long ad_mask(struct decode_cache *c)
 {
        return (1UL << (c->ad_bytes << 3)) - 1;
                                         c->regs[VCPU_REGS_RSI]);
                c->src.val = 0;
                break;
+       case SrcImmFAddr:
+               c->src.type = OP_IMM;
+               c->src.ptr = (unsigned long *)c->eip;
+               c->src.bytes = c->op_bytes + 2;
+               insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
+               break;
+       case SrcMemFAddr:
+               c->src.type = OP_MEM;
+               c->src.ptr = (unsigned long *)c->modrm_ea;
+               c->src.bytes = c->op_bytes + 2;
+               break;
        }
 
        /*
                c->src2.bytes = 1;
                c->src2.val = insn_fetch(u8, 1, c->eip);
                break;
-       case Src2Imm16:
-               c->src2.type = OP_IMM;
-               c->src2.ptr = (unsigned long *)c->eip;
-               c->src2.bytes = 2;
-               c->src2.val = insn_fetch(u16, 2, c->eip);
-               break;
        case Src2One:
                c->src2.bytes = 1;
                c->src2.val = 1;
                break;
-       case Src2Mem16:
-               c->src2.type = OP_MEM;
-               c->src2.bytes = 2;
-               c->src2.ptr = (unsigned long *)(c->modrm_ea + c->src.bytes);
-               c->src2.val = 0;
-               break;
        }
 
        /* Decode and fetch the destination operand: register or memory. */
 
        if (c->src.type == OP_MEM) {
                rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr,
-                                       &c->src.val, c->src.bytes);
+                                       c->src.valptr, c->src.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                c->src.orig_val = c->src.val;
        }
        case 0xe9: /* jmp rel */
                goto jmp;
-       case 0xea: /* jmp far */
+       case 0xea: { /* jmp far */
+               unsigned short sel;
        jump_far:
-               if (load_segment_descriptor(ctxt, ops, c->src2.val,
-                                           VCPU_SREG_CS))
+               memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+
+               if (load_segment_descriptor(ctxt, ops, sel, VCPU_SREG_CS))
                        goto done;
 
-               c->eip = c->src.val;
+               c->eip = 0;
+               memcpy(&c->eip, c->src.valptr, c->op_bytes);
                break;
+       }
        case 0xeb:
              jmp:              /* jmp rel short */
                jmp_rel(c, c->src.val);