Search
lxdream.org :: lxdream/src/xlat/x86/x86gen.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/x86/x86gen.c
changeset 1006:3a169c224c12
next1011:fdd58619b760
author nkeynes
date Tue Apr 07 10:55:03 2009 +0000 (15 years ago)
branchxlat-refactor
permissions -rw-r--r--
last change Commit current work-in-progress to xlat-refactor branch
file annotate diff log raw
nkeynes@1006
     1
/**
nkeynes@1006
     2
 * $Id: xir.h 931 2008-10-31 02:57:59Z nkeynes $
nkeynes@1006
     3
 * 
nkeynes@1006
     4
 * x86/x86-64 final code generation
nkeynes@1006
     5
 *
nkeynes@1006
     6
 * Copyright (c) 2009 Nathan Keynes.
nkeynes@1006
     7
 *
nkeynes@1006
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@1006
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@1006
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@1006
    11
 * (at your option) any later version.
nkeynes@1006
    12
 *
nkeynes@1006
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@1006
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@1006
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@1006
    16
 * GNU General Public License for more details.
nkeynes@1006
    17
 */
nkeynes@1006
    18
#include <assert.h>
nkeynes@1006
    19
nkeynes@1006
    20
#include "xlat/xir.h"
nkeynes@1006
    21
#include "xlat/xlat.h"
nkeynes@1006
    22
#include "xlat/x86/x86op.h"
nkeynes@1006
    23
nkeynes@1006
    24
typedef enum {
nkeynes@1006
    25
    SSE_NONE = 0,
nkeynes@1006
    26
    SSE_1,
nkeynes@1006
    27
    SSE_2,
nkeynes@1006
    28
    SSE_3,
nkeynes@1006
    29
    SSE_3_1, /* AKA SSSE3 */ 
nkeynes@1006
    30
    SSE_4_1,
nkeynes@1006
    31
    SSE_4_2
nkeynes@1006
    32
} sse_version_t;
nkeynes@1006
    33
nkeynes@1006
    34
/* 32-bit register groups:
nkeynes@1006
    35
 *   General regs 0..7
nkeynes@1006
    36
 *     - EAX, EDX - arguments, volatile
nkeynes@1006
    37
 *     - ECX - volatile
nkeynes@1006
    38
 *     - EBX, ESI, EDI - non-volatile
nkeynes@1006
    39
 *     - ESP, EBP - blocked out for system use.
nkeynes@1006
    40
 *   XMM regs 16..23
nkeynes@1006
    41
 *     - Floating or integer, all volatile
nkeynes@1006
    42
 *   MMX regs 32..39
nkeynes@1006
    43
 *     - integer, all volatile
nkeynes@1006
    44
 * OR (if SSE is unsupported)
nkeynes@1006
    45
 *   x87 regs 32..39
nkeynes@1006
    46
 *     - floating point, all volatile, stack allocator
nkeynes@1006
    47
 */
nkeynes@1006
    48
nkeynes@1006
    49
/*
nkeynes@1006
    50
 * 64-bit register groups:
nkeynes@1006
    51
 *   General regs 0..15
nkeynes@1006
    52
 *     - EDI, ESI - arguments, volatile
nkeynes@1006
    53
 *     - EAX, ECX, EDX, ... - volatile
nkeynes@1006
    54
 *     - EBX, ... non-volatile
nkeynes@1006
    55
 *     - ESP, EBP - blocked for system use (r13?)
nkeynes@1006
    56
 *   XMM regs 16..31
nkeynes@1006
    57
 *     - Floating or integer, all volatile
nkeynes@1006
    58
 *   MMX regs 32..39
nkeynes@1006
    59
 *     - integer, all volatile
nkeynes@1006
    60
 * OR
nkeynes@1006
    61
 *   x87 regs 32..39
nkeynes@1006
    62
 *     - floating point, all volatile, stack allocator
nkeynes@1006
    63
 */
nkeynes@1006
    64
nkeynes@1006
    65
nkeynes@1006
    66
nkeynes@1006
    67
nkeynes@1006
    68
struct x86_target_info_struct {
nkeynes@1006
    69
    sse_version_t sse_version;
nkeynes@1006
    70
} x86_target_info;
nkeynes@1006
    71
nkeynes@1006
    72
nkeynes@1006
    73
/**
nkeynes@1006
    74
 * Initialize x86_target_info - detect supported features from cpuid
nkeynes@1006
    75
 */
nkeynes@1006
    76
void x86_target_init()
nkeynes@1006
    77
{
nkeynes@1006
    78
    uint32_t feature1, feature2;
nkeynes@1006
    79
    
nkeynes@1006
    80
    __asm__ __volatile__(
nkeynes@1006
    81
        "mov $0x01, %%eax\n\t"
nkeynes@1006
    82
        "cpuid\n\t" : "=c" (feature1), "=d" (feature2) : : "eax", "ebx");
nkeynes@1006
    83
    
nkeynes@1006
    84
    /* Walk through from oldest to newest - while it's normally the case 
nkeynes@1006
    85
     * that all older extensions are supported, you're not supposed to
nkeynes@1006
    86
     * depend on that assumption. So instead we stop as soon as we find
nkeynes@1006
    87
     * a missing feature bit. */
nkeynes@1006
    88
    if( (feature2 & 0x02000000) == 0 ) {
nkeynes@1006
    89
        x86_target_info.sse_version = SSE_NONE;
nkeynes@1006
    90
    } else if( (feature2 & 0x04000000) == 0 ) {
nkeynes@1006
    91
        x86_target_info.sse_version = SSE_1;
nkeynes@1006
    92
    } else if( (feature1 & 0x00000001) == 0 ) { /* SSE3 bit */
nkeynes@1006
    93
        x86_target_info.sse_version = SSE_2;
nkeynes@1006
    94
    } else if( (feature1 & 0x00000100) == 0 ) { /* SSSE3 bit */
nkeynes@1006
    95
        x86_target_info.sse_version = SSE_3;
nkeynes@1006
    96
    } else if( (feature1 & 0x00080000) == 0 ) { /* SSE4.1 bit */
nkeynes@1006
    97
        x86_target_info.sse_version = SSE_3_1;
nkeynes@1006
    98
    } else if( (feature1 & 0x00100000) == 0 ) { /* SSE4.2 bit */
nkeynes@1006
    99
        x86_target_info.sse_version = SSE_4_1;
nkeynes@1006
   100
    } else {
nkeynes@1006
   101
        x86_target_info.sse_version = SSE_4_2;
nkeynes@1006
   102
    }
nkeynes@1006
   103
}
nkeynes@1006
   104
nkeynes@1006
   105
#define IS_X86_64() (sizeof(void *)==8)
nkeynes@1006
   106
#define IS_XMM_REG(op,n) (XOP_REG(op,n) >= MIN_XMM_REGISTER && XOP_REG(op,n) <= MAX_AMD64_XMM_REGISTER)
nkeynes@1006
   107
nkeynes@1006
   108
#define RBP_OFFSET (-128)
nkeynes@1006
   109
nkeynes@1006
   110
#define NONE NO_OPERAND
nkeynes@1006
   111
#define SRC SOURCE_REGISTER_OPERAND
nkeynes@1006
   112
#define TGT TARGET_REGISTER_OPERAND
nkeynes@1006
   113
#define IMM INT_IMM_OPERAND
nkeynes@1006
   114
#define FLT FLOAT_IMM_OPERAND
nkeynes@1006
   115
#define DBL DOUBLE_IMM_OPERAND
nkeynes@1006
   116
nkeynes@1006
   117
#define MAX_X86_GENERAL_REGISTER  (MIN_TARGET_REGISTER+7)
nkeynes@1006
   118
#define MAX_AMD64_GENERAL_REGISTER (MIN_TARGET_REGISTER+15)
nkeynes@1006
   119
#define MIN_XMM_REGISTER (MIN_TARGET_REGISTER+16)
nkeynes@1006
   120
#define MAX_X86_XMM_REGISTER (MIN_TARGET_REGISTER+23)
nkeynes@1006
   121
#define MAX_AMD64_XMM_REGISTER (MIN_TARGET_REGISTER+31)
nkeynes@1006
   122
nkeynes@1006
   123
#define ILLOP(op) FATAL("Illegal x86 opcode %s %d %d\n", XIR_OPCODE_TABLE[op->opcode], op->operand[0].type, op->operand[1].type) 
nkeynes@1006
   124
nkeynes@1006
   125
// Convenience macros
nkeynes@1006
   126
#define X86L_IMMS_REG(opname, op) \
nkeynes@1006
   127
    if( XOP_IS_FORM(op,IMM,TGT) ) { opname##_imms_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   128
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imms_rbpdisp(XOP_INT(op,0),XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   129
    else { ILLOP(op); }
nkeynes@1006
   130
nkeynes@1006
   131
#define X86L_REG_TGT(opname,op) \
nkeynes@1006
   132
    if( XOP_IS_FORM(op,TGT,TGT) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   133
    else if( XOP_IS_FORM(op,SRC,TGT) ) { opname##_rbpdisp_r32(XOP_REG(op,0)+RBP_OFFSET,XOP_REG(op,1)); } \
nkeynes@1006
   134
    else { ILLOP(op); }
nkeynes@1006
   135
nkeynes@1006
   136
#define X86F_REG_TGT(opname,op ) \
nkeynes@1006
   137
    if( XOP_IS_FORM(op,TGT,TGT) ) { opname##_xmm_xmm(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   138
    else if( XOP_IS_FORM(op,SRC,TGT) ) { opname##_rbpdisp_xmm(XOP_REG(op,0)+RBP_OFFSET,XOP_REG(op,1)); } \
nkeynes@1006
   139
    else { ILLOP(op); }
nkeynes@1006
   140
    
nkeynes@1006
   141
#define X86L_REG_REG(opname,op) \
nkeynes@1006
   142
    if( XOP_IS_FORM(op,TGT,TGT) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   143
    else if( XOP_IS_FORM(op,SRC,TGT) ) { opname##_rbpdisp_r32(XOP_REG(op,0)+RBP_OFFSET,XOP_REG(op,1)); } \
nkeynes@1006
   144
    else if( XOP_IS_FORM(op,TGT,SRC) ) { opname##_r32_rbpdisp(XOP_REG(op,0),XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   145
    else { ILLOP(op); }
nkeynes@1006
   146
nkeynes@1006
   147
#define X86L_REG(opname,op) \
nkeynes@1006
   148
    if( XOP_IS_TGTREG(op,0) ) { opname##_r32(XOP_REG(op,0)); } \
nkeynes@1006
   149
    else if( XOP_IS_SRCREG(op,0) ) { opname##_rbpdisp(XOP_REG(op,0)+RBP_OFFSET); } \
nkeynes@1006
   150
    else { ILLOP(op); }
nkeynes@1006
   151
nkeynes@1006
   152
#define X86L_CL_REG(opname,op) \
nkeynes@1006
   153
    if( XOP_IS_FORM(op,TGT,TGT) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32(XOP_REG(op,1)); } \
nkeynes@1006
   154
    else if( XOP_IS_FORM(op,TGT,SRC) && XOP_REG(op,0) == REG_CL ) { opname##_cl_rbpdisp(XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   155
    else { ILLOP(op); }
nkeynes@1006
   156
nkeynes@1006
   157
#define X86L_IMMCL_REG(opname,op) \
nkeynes@1006
   158
    if( XOP_IS_FORM(op,IMM,TGT) ) { opname##_imm_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   159
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imm_rbpdisp(XOP_INT(op,0),XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   160
    else if( XOP_IS_FORM(op,TGT,TGT) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32(XOP_REG(op,1)); } \
nkeynes@1006
   161
    else if( XOP_IS_FORM(op,TGT,SRC) && XOP_REG(op,0) == REG_CL ) { opname##_cl_rbpdisp(XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   162
    else { ILLOP(op); }
nkeynes@1006
   163
nkeynes@1006
   164
// Standard ALU forms - imms,reg or reg,reg
nkeynes@1006
   165
#define X86L_ALU_REG(opname,op) \
nkeynes@1006
   166
    if( XOP_IS_FORM(op,IMM,TGT) ) { opname##_imms_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   167
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imms_rbpdisp(XOP_INT(op,0),XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   168
    else if( XOP_IS_FORM(op,TGT,TGT) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   169
    else if( XOP_IS_FORM(op,SRC,TGT) ) { opname##_rbpdisp_r32(XOP_REG(op,0)+RBP_OFFSET,XOP_REG(op,1)); } \
nkeynes@1006
   170
    else if( XOP_IS_FORM(op,TGT,SRC) ) { opname##_r32_rbpdisp(XOP_REG(op,0),XOP_REG(op,1)+RBP_OFFSET); } \
nkeynes@1006
   171
    else { ILLOP(op); }
nkeynes@1006
   172
nkeynes@1006
   173
uint32_t x86_target_get_code_size( xir_op_t begin, xir_op_t end )
nkeynes@1006
   174
{
nkeynes@1006
   175
    return -1;
nkeynes@1006
   176
}
nkeynes@1006
   177
nkeynes@1006
   178
nkeynes@1006
   179
/**
nkeynes@1006
   180
 * Note: Assumes that the IR is x86-legal (ie doesn't contain any unencodeable instructions).
nkeynes@1006
   181
 */
nkeynes@1006
   182
uint32_t x86_target_codegen( target_data_t td, xir_op_t begin, xir_op_t end )
nkeynes@1006
   183
{
nkeynes@1006
   184
    int ss;
nkeynes@1006
   185
    xir_op_t it;
nkeynes@1006
   186
    
nkeynes@1006
   187
    /* Prologue */
nkeynes@1006
   188
    
nkeynes@1006
   189
    for( it=begin; it != NULL; it = it->next ) {
nkeynes@1006
   190
        switch( it->opcode ) {
nkeynes@1006
   191
        case OP_ENTER:
nkeynes@1006
   192
        case OP_BARRIER:
nkeynes@1006
   193
        case OP_NOP:
nkeynes@1006
   194
            /* No code to generate */
nkeynes@1006
   195
            break;
nkeynes@1006
   196
        case OP_MOV:
nkeynes@1006
   197
            if( XOP_IS_FORM(it, IMM, SRC) ) {
nkeynes@1006
   198
                MOVL_imm32_rbpdisp( XOP_INT(it,0), XOP_REG2(it)+RBP_OFFSET );
nkeynes@1006
   199
            } else if( XOP_IS_FORM(it, IMM, TGT) ) {
nkeynes@1006
   200
                MOVL_imm32_r32( XOP_INT(it,0), XOP_REG2(it) );
nkeynes@1006
   201
            } else if( XOP_IS_FORM(it, TGT, SRC) ) {
nkeynes@1006
   202
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   203
                    MOVSS_xmm_rbpdisp( XOP_REG1(it), XOP_REG2(it)+RBP_OFFSET );
nkeynes@1006
   204
                } else {
nkeynes@1006
   205
                    MOVL_r32_rbpdisp( XOP_REG1(it), XOP_REG2(it)+RBP_OFFSET );
nkeynes@1006
   206
                }
nkeynes@1006
   207
            } else if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   208
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   209
                    if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   210
                        MOVSS_xmm_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   211
                    } else {
nkeynes@1006
   212
                        MOVL_xmm_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   213
                    }
nkeynes@1006
   214
                } else if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   215
                    MOVL_r32_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   216
                } else {
nkeynes@1006
   217
                    MOVL_r32_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   218
                }
nkeynes@1006
   219
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   220
                if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   221
                    MOVSS_rbpdisp_xmm( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   222
                } else {
nkeynes@1006
   223
                    MOVL_rbpdisp_r32( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   224
                }
nkeynes@1006
   225
            } else {
nkeynes@1006
   226
                ILLOP(it);
nkeynes@1006
   227
            }
nkeynes@1006
   228
            break;
nkeynes@1006
   229
        case OP_MOVQ:
nkeynes@1006
   230
            if( XOP_IS_FORM(it, IMM, SRC) ) {
nkeynes@1006
   231
                ILLOP(it);
nkeynes@1006
   232
            } else if( XOP_IS_FORM(it, IMM, TGT) ) {
nkeynes@1006
   233
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   234
                    if( XOP_INT(it,0) == 0 ) {
nkeynes@1006
   235
                        XORPD_xmm_xmm( XOP_REG2(it), XOP_REG2(it) );
nkeynes@1006
   236
                    }
nkeynes@1006
   237
                } else {
nkeynes@1006
   238
                    MOVQ_imm64_r64( XOP_INT(it,0), XOP_REG2(it) );
nkeynes@1006
   239
                }
nkeynes@1006
   240
            } else if( XOP_IS_FORM(it, TGT, SRC) ) {
nkeynes@1006
   241
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   242
                    MOVSD_xmm_rbpdisp( XOP_REG1(it), XOP_REG2(it)+RBP_OFFSET );
nkeynes@1006
   243
                } else {
nkeynes@1006
   244
                    MOVQ_r64_rbpdisp( XOP_REG1(it), XOP_REG2(it)+RBP_OFFSET );
nkeynes@1006
   245
                }
nkeynes@1006
   246
            } else if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   247
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   248
                    if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   249
                        MOVSD_xmm_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   250
                    } else {
nkeynes@1006
   251
                        MOVQ_xmm_r64( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   252
                    }
nkeynes@1006
   253
                } else if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   254
                    MOVQ_r64_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   255
                } else {
nkeynes@1006
   256
                    MOVQ_r64_r64( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   257
                }
nkeynes@1006
   258
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   259
                if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   260
                    MOVSD_rbpdisp_xmm( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   261
                } else {
nkeynes@1006
   262
                    MOVQ_rbpdisp_r64( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   263
                }
nkeynes@1006
   264
            } else {
nkeynes@1006
   265
                ILLOP(it);
nkeynes@1006
   266
            }
nkeynes@1006
   267
            break;
nkeynes@1006
   268
        case OP_MOVSX8:
nkeynes@1006
   269
            if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   270
                MOVSXL_r8_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   271
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   272
                MOVSXL_rbpdisp8_r32( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   273
            } else {
nkeynes@1006
   274
                ILLOP(it);
nkeynes@1006
   275
            }
nkeynes@1006
   276
            break;
nkeynes@1006
   277
        case OP_MOVSX16:
nkeynes@1006
   278
            if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   279
                MOVSXL_r16_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   280
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   281
                MOVSXL_rbpdisp16_r32( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   282
            } else {
nkeynes@1006
   283
                ILLOP(it);
nkeynes@1006
   284
            }
nkeynes@1006
   285
            break;
nkeynes@1006
   286
        case OP_MOVZX8:
nkeynes@1006
   287
            if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   288
                MOVZXL_r8_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   289
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   290
                MOVZXL_rbpdisp8_r32( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   291
            } else {
nkeynes@1006
   292
                ILLOP(it);
nkeynes@1006
   293
            }
nkeynes@1006
   294
            break;
nkeynes@1006
   295
        case OP_MOVZX16:
nkeynes@1006
   296
            if( XOP_IS_FORM(it, TGT, TGT) ) {
nkeynes@1006
   297
                MOVZXL_r16_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   298
            } else if( XOP_IS_FORM(it, SRC, TGT) ) {
nkeynes@1006
   299
                MOVZXL_rbpdisp16_r32( XOP_REG1(it)+RBP_OFFSET, XOP_REG2(it) );
nkeynes@1006
   300
            } else {
nkeynes@1006
   301
                ILLOP(it);
nkeynes@1006
   302
            }
nkeynes@1006
   303
            break;
nkeynes@1006
   304
        case OP_ADD: 
nkeynes@1006
   305
        case OP_ADDS: X86L_ALU_REG(ADDL,it);  break;
nkeynes@1006
   306
        case OP_ADDCS: X86L_ALU_REG(ADCL,it); break;
nkeynes@1006
   307
        case OP_AND:  X86L_ALU_REG(ANDL,it); break;
nkeynes@1006
   308
        case OP_CMP:
nkeynes@1006
   309
            X86L_ALU_REG(CMPL,it); break;
nkeynes@1006
   310
        case OP_DEC:
nkeynes@1006
   311
            if( XOP_IS_FORM(it,TGT,NONE) ) {
nkeynes@1006
   312
                DECL_r32(XOP_REG(it,0));
nkeynes@1006
   313
            } else if( XOP_IS_FORM(it,SRC,NONE) ) {
nkeynes@1006
   314
                DECL_rbpdisp(XOP_REG(it,0)+RBP_OFFSET);
nkeynes@1006
   315
            } else {
nkeynes@1006
   316
                ILLOP(it);
nkeynes@1006
   317
            }
nkeynes@1006
   318
            break;
nkeynes@1006
   319
        case OP_MUL: 
nkeynes@1006
   320
            X86L_REG_TGT(IMULL,it); 
nkeynes@1006
   321
            break;
nkeynes@1006
   322
        case OP_NEG:  X86L_REG(NEGL,it); break;
nkeynes@1006
   323
        case OP_NOT:  X86L_REG(NOTL,it); break;
nkeynes@1006
   324
        case OP_OR:   X86L_ALU_REG(ORL,it); break;
nkeynes@1006
   325
        case OP_RCL:  X86L_IMMCL_REG(RCLL,it); break;
nkeynes@1006
   326
        case OP_RCR:  X86L_IMMCL_REG(RCRL,it); break;
nkeynes@1006
   327
        case OP_ROL:  X86L_IMMCL_REG(ROLL,it); break;
nkeynes@1006
   328
        case OP_ROR:  X86L_IMMCL_REG(RORL,it); break;
nkeynes@1006
   329
        case OP_SAR: 
nkeynes@1006
   330
        case OP_SARS: X86L_IMMCL_REG(SARL,it); break;
nkeynes@1006
   331
        case OP_SUBBS: X86L_ALU_REG(SBBL,it); break;
nkeynes@1006
   332
        case OP_SLL: 
nkeynes@1006
   333
        case OP_SLLS: X86L_IMMCL_REG(SHLL,it); break;
nkeynes@1006
   334
        case OP_SLR: 
nkeynes@1006
   335
        case OP_SLRS: X86L_IMMCL_REG(SHRL,it); break;
nkeynes@1006
   336
        case OP_SUB: 
nkeynes@1006
   337
        case OP_SUBS: X86L_ALU_REG(SUBL,it); break;
nkeynes@1006
   338
        case OP_SHUFFLE:
nkeynes@1006
   339
            if( XOP_IS_FORM(it,IMM,TGT) ) {
nkeynes@1006
   340
                if( XOP_INT(it,0) == 0x4321 ) {
nkeynes@1006
   341
                    BSWAPL_r32( XOP_REG(it,1) );
nkeynes@1006
   342
                } else if( it->operand[1].value.i == 0x1243 ) {
nkeynes@1006
   343
                    XCHGB_r8_r8( REG_AL, REG_AH ); 
nkeynes@1006
   344
                            /* XCHG al, ah */
nkeynes@1006
   345
                }
nkeynes@1006
   346
            }
nkeynes@1006
   347
            break;
nkeynes@1006
   348
        case OP_TST:  X86L_ALU_REG(TESTL,it); break;
nkeynes@1006
   349
        case OP_XOR:  X86L_ALU_REG(XORL,it); break;
nkeynes@1006
   350
            
nkeynes@1006
   351
            // Float
nkeynes@1006
   352
        case OP_ABSF:
nkeynes@1006
   353
        case OP_ABSD:
nkeynes@1006
   354
            // Why is there no SSE FP ABS instruction?
nkeynes@1006
   355
            break;
nkeynes@1006
   356
        case OP_ADDF: X86F_REG_TGT(ADDSS,it); break;
nkeynes@1006
   357
        case OP_ADDD: X86F_REG_TGT(ADDSD,it); break;
nkeynes@1006
   358
        case OP_CMPF:
nkeynes@1006
   359
            break;
nkeynes@1006
   360
        case OP_CMPD: // UCOMISD
nkeynes@1006
   361
            break;
nkeynes@1006
   362
        case OP_DIVF: X86F_REG_TGT(DIVSS,it); break;
nkeynes@1006
   363
        case OP_DIVD: X86F_REG_TGT(DIVSD,it); break;
nkeynes@1006
   364
        case OP_MULF: X86F_REG_TGT(MULSS,it); break;
nkeynes@1006
   365
        case OP_MULD: X86F_REG_TGT(MULSD,it); break;
nkeynes@1006
   366
        case OP_RSQRTF:X86F_REG_TGT(RSQRTSS,it); break;
nkeynes@1006
   367
        case OP_SQRTF: X86F_REG_TGT(SQRTSS,it); break;
nkeynes@1006
   368
        case OP_SQRTD: X86F_REG_TGT(SQRTSD,it); break;
nkeynes@1006
   369
        case OP_SUBF:  X86F_REG_TGT(SUBSS,it); break;
nkeynes@1006
   370
        case OP_SUBD:  X86F_REG_TGT(SUBSD,it); break;
nkeynes@1006
   371
nkeynes@1006
   372
        case OP_DOTPRODV:
nkeynes@1006
   373
            MULPS_rbpdisp_xmm( XOP_REG1(it), 4 );
nkeynes@1006
   374
            HADDPS_xmm_xmm( 4, 4 ); 
nkeynes@1006
   375
            HADDPS_xmm_xmm( 4, 4 );
nkeynes@1006
   376
            MOVSS_xmm_rbpdisp( 4, XOP_REG1(it) );
nkeynes@1006
   377
            break;
nkeynes@1006
   378
        case OP_SINCOSF:
nkeynes@1006
   379
        case OP_MATMULV:
nkeynes@1006
   380
            break;
nkeynes@1006
   381
        case OP_FTOD:
nkeynes@1006
   382
            if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   383
                CVTSS2SD_xmm_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1006
   384
            } else if( XOP_IS_FORM(it,SRC,TGT) ) {
nkeynes@1006
   385
                CVTSS2SD_rbpdisp_xmm( XOP_REG(it,0)+RBP_OFFSET, XOP_REG(it,1) );
nkeynes@1006
   386
            } else {
nkeynes@1006
   387
                ILLOP(it);
nkeynes@1006
   388
            }
nkeynes@1006
   389
            break;
nkeynes@1006
   390
        case OP_DTOF:
nkeynes@1006
   391
            if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   392
                CVTSS2SD_xmm_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1006
   393
            } else if( XOP_IS_FORM(it, SRC,TGT) ) {
nkeynes@1006
   394
                CVTSS2SD_rbpdisp_xmm( XOP_REG(it,0)+RBP_OFFSET, XOP_REG(it,1) );
nkeynes@1006
   395
            } else {
nkeynes@1006
   396
                ILLOP(it);
nkeynes@1006
   397
            }
nkeynes@1006
   398
            break;
nkeynes@1006
   399
        case OP_ITOD:
nkeynes@1006
   400
            if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   401
                CVTSI2SDL_r32_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1006
   402
            } else if( XOP_IS_FORM(it,SRC,TGT) ) {
nkeynes@1006
   403
                CVTSI2SDL_rbpdisp_xmm( XOP_REG(it,0)+RBP_OFFSET, XOP_REG(it,1) );
nkeynes@1006
   404
            } else {
nkeynes@1006
   405
                ILLOP(it);
nkeynes@1006
   406
            }
nkeynes@1006
   407
            break;
nkeynes@1006
   408
        case OP_DTOI:
nkeynes@1006
   409
            if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   410
                CVTSD2SIL_xmm_r32( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1006
   411
            } else if( XOP_IS_FORM(it,SRC,TGT) ) {
nkeynes@1006
   412
                CVTSD2SIL_rbpdisp_r32( XOP_REG(it,0)+RBP_OFFSET, XOP_REG(it,1) );
nkeynes@1006
   413
            } else {
nkeynes@1006
   414
                ILLOP(it);
nkeynes@1006
   415
            }
nkeynes@1006
   416
            break;
nkeynes@1006
   417
        case OP_ITOF:
nkeynes@1006
   418
        case OP_FTOI:
nkeynes@1006
   419
            
nkeynes@1006
   420
        case OP_BRCOND:
nkeynes@1006
   421
        case OP_BRREL:
nkeynes@1006
   422
        case OP_BR:
nkeynes@1006
   423
        case OP_BRCONDDEL:
nkeynes@1006
   424
nkeynes@1006
   425
        case OP_CALL0: 
nkeynes@1006
   426
            if( XOP_IS_INTIMM(it,0) ) { 
nkeynes@1006
   427
                CALL_imm32( XOP_INT(it,0) );
nkeynes@1006
   428
            } else if( XOP_IS_SRCREG(it,0) ) {
nkeynes@1006
   429
                CALL_r32( XOP_INT(it,0) );
nkeynes@1006
   430
            } else {
nkeynes@1006
   431
                ILLOP(it);
nkeynes@1006
   432
            }
nkeynes@1006
   433
            break;
nkeynes@1006
   434
        case OP_XLAT:
nkeynes@1006
   435
            if( IS_X86_64() ) {
nkeynes@1006
   436
                ss = 3;
nkeynes@1006
   437
            } else {
nkeynes@1006
   438
                ss = 2;
nkeynes@1006
   439
            }
nkeynes@1006
   440
            if( XOP_IS_FORM(it,IMM,TGT) ) {
nkeynes@1006
   441
                MOVP_sib_rptr(ss, XOP_REG(it,1), -1, XOP_INT(it,0), XOP_REG(it,1));
nkeynes@1006
   442
            } else if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   443
                MOVP_sib_rptr(ss, XOP_REG(it,1), XOP_REG(it,0), 0, XOP_REG(it,1));
nkeynes@1006
   444
            } else {
nkeynes@1006
   445
                ILLOP(it);
nkeynes@1006
   446
            }
nkeynes@1006
   447
            break;
nkeynes@1006
   448
        case OP_CALLLUT:
nkeynes@1006
   449
            if( XOP_IS_FORM(it,TGT,IMM) ) {
nkeynes@1006
   450
                CALL_r32disp(XOP_REG(it,0),XOP_INT(it,1));
nkeynes@1006
   451
            } else if( XOP_IS_FORM(it,TGT,TGT) ) {
nkeynes@1006
   452
                CALL_sib(0,XOP_REG(it,0),XOP_REG(it,1),0);
nkeynes@1006
   453
            } else if( XOP_IS_FORM(it,IMM,TGT) ) {
nkeynes@1006
   454
                CALL_r32disp(XOP_REG(it,1),XOP_INT(it,0));
nkeynes@1006
   455
            } else {
nkeynes@1006
   456
                ILLOP(it);
nkeynes@1006
   457
            }
nkeynes@1006
   458
            break;
nkeynes@1006
   459
nkeynes@1006
   460
            // SH4-specific macro operations
nkeynes@1006
   461
        case OP_RAISEME:
nkeynes@1006
   462
            
nkeynes@1006
   463
        case OP_RAISEMNE:
nkeynes@1006
   464
            
nkeynes@1006
   465
        case OP_CMPSTR:
nkeynes@1006
   466
            break;
nkeynes@1006
   467
        case OP_DIV1: 
nkeynes@1006
   468
            break;
nkeynes@1006
   469
        case OP_SHAD:
nkeynes@1006
   470
            assert( it->operand[0].type == TGT && XOP_REG(it,0) == REG_ECX );
nkeynes@1006
   471
            CMPL_imms_r32(0,REG_ECX);
nkeynes@1006
   472
            JNGE_label(shad_shr);
nkeynes@1006
   473
            X86L_CL_REG(SHLL,it);
nkeynes@1006
   474
            JMP_label(shad_end);
nkeynes@1006
   475
nkeynes@1006
   476
            JMP_TARGET(shad_shr);
nkeynes@1006
   477
            if( IS_X86_64() && it->operand[1].type == TGT ) {
nkeynes@1006
   478
                /* We can do this a little more simply with a 64-bit shift */
nkeynes@1006
   479
                ORL_imms_r32(0xFFFFFFE0,REG_ECX);
nkeynes@1006
   480
                NEGL_r32(REG_ECX);
nkeynes@1006
   481
                MOVSXQ_r32_r64(XOP_REG(it,1), XOP_REG(it,1)); // sign-extend
nkeynes@1006
   482
                SARQ_cl_r64(XOP_REG(it,1));
nkeynes@1006
   483
            } else {
nkeynes@1006
   484
                NEGL_r32(REG_ECX);
nkeynes@1006
   485
                ANDB_imms_r8( 0x1F, REG_ECX );
nkeynes@1006
   486
                JE_label(emptyshr );
nkeynes@1006
   487
                X86L_CL_REG(SARL,it);
nkeynes@1006
   488
                JMP_label(shad_end2);
nkeynes@1006
   489
nkeynes@1006
   490
                JMP_TARGET(emptyshr);
nkeynes@1006
   491
                if( it->operand[1].type == TGT ) {
nkeynes@1006
   492
                    SARL_imm_r32( 31, XOP_REG(it,1) );
nkeynes@1006
   493
                } else {
nkeynes@1006
   494
                    SARL_imm_rbpdisp( 32, XOP_REG(it,1)+RBP_OFFSET );
nkeynes@1006
   495
                }
nkeynes@1006
   496
                JMP_TARGET(shad_end2);
nkeynes@1006
   497
            }
nkeynes@1006
   498
            JMP_TARGET(shad_end);
nkeynes@1006
   499
            break;
nkeynes@1006
   500
nkeynes@1006
   501
        case OP_SHLD:
nkeynes@1006
   502
            assert( it->operand[0].type == TGT && XOP_REG(it,0) == REG_ECX );
nkeynes@1006
   503
            CMPL_imms_r32(0,REG_ECX);
nkeynes@1006
   504
            JNGE_label(shld_shr);
nkeynes@1006
   505
            X86L_CL_REG(SHLL,it);
nkeynes@1006
   506
            JMP_label(shld_end);
nkeynes@1006
   507
nkeynes@1006
   508
            JMP_TARGET(shld_shr);
nkeynes@1006
   509
            if( IS_X86_64() && it->operand[1].type == TGT ) {
nkeynes@1006
   510
                /* We can do this a little more simply with a 64-bit shift */
nkeynes@1006
   511
                ORL_imms_r32(0xFFFFFFE0,REG_ECX);
nkeynes@1006
   512
                NEGL_r32(REG_ECX);
nkeynes@1006
   513
                MOVL_r32_r32(XOP_REG(it,1), XOP_REG(it,1)); // Ensure high bits are 0
nkeynes@1006
   514
                SHRQ_cl_r64(XOP_REG(it,1));
nkeynes@1006
   515
            } else {
nkeynes@1006
   516
                NEGL_r32(REG_ECX);
nkeynes@1006
   517
                ANDB_imms_r8( 0x1F, REG_ECX );
nkeynes@1006
   518
                JE_label(emptyshr );
nkeynes@1006
   519
                X86L_CL_REG(SHRL,it);
nkeynes@1006
   520
                JMP_label(shld_end2);
nkeynes@1006
   521
nkeynes@1006
   522
                JMP_TARGET(emptyshr);
nkeynes@1006
   523
                XORL_r32_r32( REG_EAX, REG_EAX );
nkeynes@1006
   524
                JMP_TARGET(shld_end2);
nkeynes@1006
   525
            }
nkeynes@1006
   526
            JMP_TARGET(shld_end);
nkeynes@1006
   527
            break;
nkeynes@1006
   528
nkeynes@1006
   529
        case OP_MULQ:
nkeynes@1006
   530
        case OP_ADDQSAT32:
nkeynes@1006
   531
        case OP_ADDQSAT48:
nkeynes@1006
   532
nkeynes@1006
   533
            // Should not occur (should be have been lowered in target_lower)
nkeynes@1006
   534
        case OP_NEGF:
nkeynes@1006
   535
        case OP_NEGD:
nkeynes@1006
   536
        case OP_LOADB:
nkeynes@1006
   537
        case OP_LOADBFW:
nkeynes@1006
   538
        case OP_LOADW:
nkeynes@1006
   539
        case OP_LOADL:
nkeynes@1006
   540
        case OP_LOADQ:
nkeynes@1006
   541
        case OP_STOREB:
nkeynes@1006
   542
        case OP_STOREW:
nkeynes@1006
   543
        case OP_STOREL:
nkeynes@1006
   544
        case OP_STOREQ:
nkeynes@1006
   545
        case OP_STORELCA:
nkeynes@1006
   546
        case OP_OCBI:
nkeynes@1006
   547
        case OP_OCBP:
nkeynes@1006
   548
        case OP_OCBWB:
nkeynes@1006
   549
        case OP_PREF:
nkeynes@1006
   550
        default:
nkeynes@1006
   551
            ILLOP(it);
nkeynes@1006
   552
        }
nkeynes@1006
   553
        if( it == end )
nkeynes@1006
   554
            break;
nkeynes@1006
   555
    /* Epilogue */
nkeynes@1006
   556
    }
nkeynes@1006
   557
}
.