static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        int host_reg1, host_reg2;

        MMX_ENTER();
        
        LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
        
        if ((fetchdat & 0xc0) == 0xc0)
        {
                STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
        }
        else
        {
                x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);

                STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
                        
                CHECK_SEG_WRITE(target_seg);
                CHECK_SEG_LIMITS(target_seg, 7);
                
                MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
        }

        return op_pc + 1;
}

static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        MMX_ENTER();
        
        if ((fetchdat & 0xc0) == 0xc0)
        {
                int host_reg1, host_reg2;
        
                LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
                STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
        }
        else
        {
                x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);

                STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);

                CHECK_SEG_READ(target_seg);

                MEM_LOAD_ADDR_EA_Q(target_seg);
                STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
        }

        return op_pc + 1;
}

static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        int host_reg;

        MMX_ENTER();
        
        host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
        
        if ((fetchdat & 0xc0) == 0xc0)
        {
                STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
        }
        else
        {
                x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);

                STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
                        
                CHECK_SEG_WRITE(target_seg);
                CHECK_SEG_LIMITS(target_seg, 3);
                
                MEM_STORE_ADDR_EA_L(target_seg, host_reg);
        }

        return op_pc + 1;
}
static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        MMX_ENTER();
        
        if ((fetchdat & 0xc0) == 0xc0)
        {
                int host_reg = LOAD_REG_L(fetchdat & 7);
                STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
        }
        else
        {
                x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);

                STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);

                CHECK_SEG_READ(target_seg);

                MEM_LOAD_ADDR_EA_L(target_seg);
                STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
        }

        return op_pc + 1;
}

#define MMX_OP(name, func)                                                                                      \
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)     \
{                                                                                                               \
        int src_reg1, src_reg2;                                                                                 \
        int xmm_src, xmm_dst;                                                                                   \
                                                                                                                \
        MMX_ENTER();                                                                                            \
                                                                                                                \
        if ((fetchdat & 0xc0) == 0xc0)                                                                          \
        {                                                                                                       \
                xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7);                                                         \
        }                                                                                                       \
        else                                                                                                    \
        {                                                                                                       \
                x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);                    \
                                                                                                                \
                STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);                                                 \
                                                                                                                \
                CHECK_SEG_READ(target_seg);                                                                     \
                                                                                                                \
                MEM_LOAD_ADDR_EA_Q(target_seg);                                                                 \
                src_reg1 = LOAD_Q_REG_1;                                                                        \
                src_reg2 = LOAD_Q_REG_2;                                                                        \
                xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2);                                                  \
        }                                                                                                       \
        xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7);                                                          \
        func(xmm_dst, xmm_src);                                                                              \
        STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst);                                                          \
                                                                                                                \
        return op_pc + 1;                                                                                       \
}

MMX_OP(ropPAND,  MMX_AND)
MMX_OP(ropPANDN, MMX_ANDN)
MMX_OP(ropPOR,   MMX_OR)
MMX_OP(ropPXOR,  MMX_XOR)

MMX_OP(ropPADDB,    MMX_ADDB)
MMX_OP(ropPADDW,    MMX_ADDW)
MMX_OP(ropPADDD,    MMX_ADDD)
MMX_OP(ropPADDSB,   MMX_ADDSB)
MMX_OP(ropPADDSW,   MMX_ADDSW)
MMX_OP(ropPADDUSB,  MMX_ADDUSB)
MMX_OP(ropPADDUSW,  MMX_ADDUSW)

MMX_OP(ropPSUBB,    MMX_SUBB)
MMX_OP(ropPSUBW,    MMX_SUBW)
MMX_OP(ropPSUBD,    MMX_SUBD)
MMX_OP(ropPSUBSB,   MMX_SUBSB)
MMX_OP(ropPSUBSW,   MMX_SUBSW)
MMX_OP(ropPSUBUSB,  MMX_SUBUSB)
MMX_OP(ropPSUBUSW,  MMX_SUBUSW)

MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW);
MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD);
MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ);
MMX_OP(ropPACKSSWB,  MMX_PACKSSWB);
MMX_OP(ropPCMPGTB,   MMX_PCMPGTB);
MMX_OP(ropPCMPGTW,   MMX_PCMPGTW);
MMX_OP(ropPCMPGTD,   MMX_PCMPGTD);
MMX_OP(ropPACKUSWB,  MMX_PACKUSWB);
MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW);
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
MMX_OP(ropPACKSSDW,  MMX_PACKSSDW);

MMX_OP(ropPCMPEQB,   MMX_PCMPEQB);
MMX_OP(ropPCMPEQW,   MMX_PCMPEQW);
MMX_OP(ropPCMPEQD,   MMX_PCMPEQD);

MMX_OP(ropPSRLW,    MMX_PSRLW)
MMX_OP(ropPSRLD,    MMX_PSRLD)
MMX_OP(ropPSRLQ,    MMX_PSRLQ)
MMX_OP(ropPSRAW,    MMX_PSRAW)
MMX_OP(ropPSRAD,    MMX_PSRAD)
MMX_OP(ropPSLLW,    MMX_PSLLW)
MMX_OP(ropPSLLD,    MMX_PSLLD)
MMX_OP(ropPSLLQ,    MMX_PSLLQ)

MMX_OP(ropPMULLW,   MMX_PMULLW);
MMX_OP(ropPMULHW,   MMX_PMULHW);
MMX_OP(ropPMADDWD,  MMX_PMADDWD);

static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        int xmm_dst;

        if ((fetchdat & 0xc0) != 0xc0)
                return 0;
        if ((fetchdat & 0x08) || !(fetchdat & 0x30))
                return 0;
        
        MMX_ENTER();
        
        xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
        switch (fetchdat & 0x38)
        {
                case 0x10: /*PSRLW*/
                MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x20: /*PSRAW*/
                MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x30: /*PSLLW*/
                MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
        }
        STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
        
        return op_pc + 2;
}
static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        int xmm_dst;

        if ((fetchdat & 0xc0) != 0xc0)
                return 0;
        if ((fetchdat & 0x08) || !(fetchdat & 0x30))
                return 0;
        
        MMX_ENTER();
        
        xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
        switch (fetchdat & 0x38)
        {
                case 0x10: /*PSRLD*/
                MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x20: /*PSRAD*/
                MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x30: /*PSLLD*/
                MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
        }
        STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
        
        return op_pc + 2;
}
static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        int xmm_dst;

        if ((fetchdat & 0xc0) != 0xc0)
                return 0;
        if ((fetchdat & 0x08) || !(fetchdat & 0x30))
                return 0;
        
        MMX_ENTER();
        
        xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
        switch (fetchdat & 0x38)
        {
                case 0x10: /*PSRLQ*/
                MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x20: /*PSRAQ*/
                MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
                case 0x30: /*PSLLQ*/
                MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
                break;
        }
        STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
        
        return op_pc + 2;
}

static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
        codegen_mmx_entered = 0;
        
        return 0;
}
