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 1011:fdd58619b760
prev1006:3a169c224c12
next1012:0b8cc74ac83a
author nkeynes
date Sun Apr 12 07:24:45 2009 +0000 (15 years ago)
branchxlat-refactor
permissions -rw-r--r--
last change Restructure operand types -
rename to forms to avoid conflict for actual data types
temporary operands are now a first class form
remove explicit types for immediates - now implied by opcode
Initial work on promote-source-reg pass
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@1011
   108
#define NONE NO_OPERAND
nkeynes@1011
   109
#define SRC SOURCE_OPERAND
nkeynes@1011
   110
#define DST DEST_OPERAND
nkeynes@1011
   111
#define TMP TEMP_OPERAND
nkeynes@1011
   112
#define IMM IMMEDIATE_OPERAND
nkeynes@1006
   113
nkeynes@1011
   114
#define MAX_X86_GENERAL_REGISTER  7
nkeynes@1011
   115
#define MAX_AMD64_GENERAL_REGISTER 15
nkeynes@1011
   116
#define MIN_XMM_REGISTER 16
nkeynes@1011
   117
#define MAX_X86_XMM_REGISTER 23
nkeynes@1011
   118
#define MAX_AMD64_XMM_REGISTER 31
nkeynes@1006
   119
nkeynes@1011
   120
#define SRCADDR(op,n) (XOP_REG(op,n) - 128)
nkeynes@1011
   121
#define TMPADDR(op,n) (XOP_REG(op,n))  /* FIXME */
nkeynes@1006
   122
nkeynes@1011
   123
#define ILLOP(op) FATAL("Illegal x86 opcode %s %d %d\n", XIR_OPCODE_TABLE[op->opcode], op->operand[0].form, op->operand[1].form) 
nkeynes@1006
   124
nkeynes@1006
   125
// Convenience macros
nkeynes@1006
   126
#define X86L_IMMS_REG(opname, op) \
nkeynes@1011
   127
    if( XOP_IS_FORM(op,IMM,DST) ) { opname##_imms_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   128
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imms_r32disp(XOP_INT(op,0),REG_RBP,SRCADDR(op,1)); } \
nkeynes@1011
   129
    else if( XOP_IS_FORM(op,IMM,TMP) ) { opname##_imms_r32disp(XOP_INT(op,0),REG_RSP,TMPADDR(op,1)); } \
nkeynes@1006
   130
    else { ILLOP(op); }
nkeynes@1006
   131
nkeynes@1011
   132
#define X86L_REG_DST(opname,op) \
nkeynes@1011
   133
    if( XOP_IS_FORM(op,DST,DST) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   134
    else if( XOP_IS_FORM(op,SRC,DST) ) { opname##_r32disp_r32(REG_RBP, SRCADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   135
    else if( XOP_IS_FORM(op,TMP,DST) ) { opname##_r32disp_r32(REG_RSP, TMPADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   136
    else { ILLOP(op); }
nkeynes@1006
   137
nkeynes@1011
   138
#define X86F_REG_DST(opname,op ) \
nkeynes@1011
   139
    if( XOP_IS_FORM(op,DST,DST) ) { opname##_xmm_xmm(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   140
    else if( XOP_IS_FORM(op,SRC,DST) ) { opname##_r32disp_xmm(REG_RBP, SRCADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   141
    else if( XOP_IS_FORM(op,TMP,DST) ) { opname##_r32disp_xmm(REG_RSP, TMPADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1006
   142
    else { ILLOP(op); }
nkeynes@1006
   143
    
nkeynes@1006
   144
#define X86L_REG_REG(opname,op) \
nkeynes@1011
   145
    if( XOP_IS_FORM(op,DST,DST) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   146
    else if( XOP_IS_FORM(op,SRC,DST) ) { opname##_r32disp_r32(REG_RBP, SRCADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   147
    else if( XOP_IS_FORM(op,DST,SRC) ) { opname##_r32_r32disp(XOP_REG(op,0),REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   148
    else if( XOP_IS_FORM(op,TMP,DST) ) { opname##_r32disp_r32(REG_RSP, TMPADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   149
    else if( XOP_IS_FORM(op,DST,TMP) ) { opname##_r32_r32disp(XOP_REG(op,0),REG_RSP, TMPADDR(op,1)); } \
nkeynes@1006
   150
    else { ILLOP(op); }
nkeynes@1006
   151
nkeynes@1006
   152
#define X86L_REG(opname,op) \
nkeynes@1011
   153
    if( XOP_IS_DST(op,0) ) { opname##_r32(XOP_REG(op,0)); } \
nkeynes@1011
   154
    else if( XOP_IS_SRC(op,0) ) { opname##_r32disp(REG_RBP,SRCADDR(op,0)); } \
nkeynes@1011
   155
    else if( XOP_IS_TMP(op,0) ) { opname##_r32disp(REG_RSP,TMPADDR(op,0)); } \
nkeynes@1006
   156
    else { ILLOP(op); }
nkeynes@1006
   157
nkeynes@1006
   158
#define X86L_CL_REG(opname,op) \
nkeynes@1011
   159
    if( XOP_IS_FORM(op,DST,DST) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32(XOP_REG(op,1)); } \
nkeynes@1011
   160
    else if( XOP_IS_FORM(op,DST,SRC) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32disp(REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   161
    else if( XOP_IS_FORM(op,DST,TMP) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32disp(REG_RSP, TMPADDR(op,1)); } \
nkeynes@1006
   162
    else { ILLOP(op); }
nkeynes@1006
   163
nkeynes@1006
   164
#define X86L_IMMCL_REG(opname,op) \
nkeynes@1011
   165
    if( XOP_IS_FORM(op,IMM,DST) ) { opname##_imm_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   166
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imm_r32disp(XOP_INT(op,0),REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   167
    else if( XOP_IS_FORM(op,IMM,TMP) ) { opname##_imm_r32disp(XOP_INT(op,0),REG_RSP, TMPADDR(op,1)); } \
nkeynes@1011
   168
    else if( XOP_IS_FORM(op,DST,DST) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32(XOP_REG(op,1)); } \
nkeynes@1011
   169
    else if( XOP_IS_FORM(op,DST,SRC) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32disp(REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   170
    else if( XOP_IS_FORM(op,DST,TMP) && XOP_REG(op,0) == REG_CL ) { opname##_cl_r32disp(REG_RSP, TMPADDR(op,1)); } \
nkeynes@1006
   171
    else { ILLOP(op); }
nkeynes@1006
   172
nkeynes@1006
   173
// Standard ALU forms - imms,reg or reg,reg
nkeynes@1006
   174
#define X86L_ALU_REG(opname,op) \
nkeynes@1011
   175
    if( XOP_IS_FORM(op,IMM,DST) ) { opname##_imms_r32(XOP_INT(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   176
    else if( XOP_IS_FORM(op,IMM,SRC) ) { opname##_imms_r32disp(XOP_INT(op,0),REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   177
    else if( XOP_IS_FORM(op,IMM,TMP) ) { opname##_imms_r32disp(XOP_INT(op,0),REG_RSP, TMPADDR(op,1)); } \
nkeynes@1011
   178
    else if( XOP_IS_FORM(op,DST,DST) ) { opname##_r32_r32(XOP_REG(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   179
    else if( XOP_IS_FORM(op,SRC,DST) ) { opname##_r32disp_r32(REG_RBP, SRCADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   180
    else if( XOP_IS_FORM(op,DST,SRC) ) { opname##_r32_r32disp(XOP_REG(op,0),REG_RBP, SRCADDR(op,1)); } \
nkeynes@1011
   181
    else if( XOP_IS_FORM(op,TMP,DST) ) { opname##_r32disp_r32(REG_RSP, TMPADDR(op,0),XOP_REG(op,1)); } \
nkeynes@1011
   182
    else if( XOP_IS_FORM(op,DST,TMP) ) { opname##_r32_r32disp(XOP_REG(op,0),REG_RSP, TMPADDR(op,1)); } \
nkeynes@1006
   183
    else { ILLOP(op); }
nkeynes@1006
   184
nkeynes@1006
   185
uint32_t x86_target_get_code_size( xir_op_t begin, xir_op_t end )
nkeynes@1006
   186
{
nkeynes@1006
   187
    return -1;
nkeynes@1006
   188
}
nkeynes@1006
   189
nkeynes@1006
   190
nkeynes@1006
   191
/**
nkeynes@1006
   192
 * Note: Assumes that the IR is x86-legal (ie doesn't contain any unencodeable instructions).
nkeynes@1006
   193
 */
nkeynes@1006
   194
uint32_t x86_target_codegen( target_data_t td, xir_op_t begin, xir_op_t end )
nkeynes@1006
   195
{
nkeynes@1006
   196
    int ss;
nkeynes@1006
   197
    xir_op_t it;
nkeynes@1006
   198
    
nkeynes@1006
   199
    /* Prologue */
nkeynes@1006
   200
    
nkeynes@1006
   201
    for( it=begin; it != NULL; it = it->next ) {
nkeynes@1006
   202
        switch( it->opcode ) {
nkeynes@1006
   203
        case OP_ENTER:
nkeynes@1006
   204
        case OP_BARRIER:
nkeynes@1006
   205
        case OP_NOP:
nkeynes@1006
   206
            /* No code to generate */
nkeynes@1006
   207
            break;
nkeynes@1006
   208
        case OP_MOV:
nkeynes@1011
   209
            if( XOP_IS_FORM(it, IMM, DST) ) {
nkeynes@1006
   210
                MOVL_imm32_r32( XOP_INT(it,0), XOP_REG2(it) );
nkeynes@1011
   211
            } else if( XOP_IS_FORM(it, IMM, SRC) ) {
nkeynes@1011
   212
                MOVL_imm32_r32disp( XOP_INT(it,0), REG_RBP, SRCADDR(it,1) );
nkeynes@1011
   213
            } else if( XOP_IS_FORM(it, IMM, TMP) ) {
nkeynes@1011
   214
                MOVL_imm32_r32disp( XOP_INT(it,0), REG_RSP, TMPADDR(it,1) );
nkeynes@1011
   215
            } else if( XOP_IS_FORM(it, DST, SRC) ) {
nkeynes@1006
   216
                if( IS_XMM_REG(it,0) ) {
nkeynes@1011
   217
                    MOVSS_xmm_r32disp( XOP_REG1(it), REG_RBP, SRCADDR(it,1) );
nkeynes@1006
   218
                } else {
nkeynes@1011
   219
                    MOVL_r32_r32disp( XOP_REG1(it), REG_RBP, SRCADDR(it,1) );
nkeynes@1006
   220
                }
nkeynes@1011
   221
            } else if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   222
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   223
                    if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   224
                        MOVSS_xmm_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   225
                    } else {
nkeynes@1006
   226
                        MOVL_xmm_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   227
                    }
nkeynes@1006
   228
                } else if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   229
                    MOVL_r32_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   230
                } else {
nkeynes@1006
   231
                    MOVL_r32_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   232
                }
nkeynes@1011
   233
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1006
   234
                if( IS_XMM_REG(it,1) ) {
nkeynes@1011
   235
                    MOVSS_r32disp_xmm( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   236
                } else {
nkeynes@1011
   237
                    MOVL_r32disp_r32( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   238
                }
nkeynes@1006
   239
            } else {
nkeynes@1006
   240
                ILLOP(it);
nkeynes@1006
   241
            }
nkeynes@1006
   242
            break;
nkeynes@1006
   243
        case OP_MOVQ:
nkeynes@1006
   244
            if( XOP_IS_FORM(it, IMM, SRC) ) {
nkeynes@1006
   245
                ILLOP(it);
nkeynes@1011
   246
            } else if( XOP_IS_FORM(it, IMM, DST) ) {
nkeynes@1006
   247
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   248
                    if( XOP_INT(it,0) == 0 ) {
nkeynes@1006
   249
                        XORPD_xmm_xmm( XOP_REG2(it), XOP_REG2(it) );
nkeynes@1006
   250
                    }
nkeynes@1006
   251
                } else {
nkeynes@1006
   252
                    MOVQ_imm64_r64( XOP_INT(it,0), XOP_REG2(it) );
nkeynes@1006
   253
                }
nkeynes@1011
   254
            } else if( XOP_IS_FORM(it, DST, SRC) ) {
nkeynes@1006
   255
                if( IS_XMM_REG(it,0) ) {
nkeynes@1011
   256
                    MOVSD_xmm_r32disp( XOP_REG1(it), REG_RBP, SRCADDR(it,1) );
nkeynes@1006
   257
                } else {
nkeynes@1011
   258
                    MOVQ_r64_r64disp( XOP_REG1(it), REG_RBP, SRCADDR(it,1) );
nkeynes@1006
   259
                }
nkeynes@1011
   260
            } else if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   261
                if( IS_XMM_REG(it,0) ) {
nkeynes@1006
   262
                    if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   263
                        MOVSD_xmm_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   264
                    } else {
nkeynes@1006
   265
                        MOVQ_xmm_r64( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   266
                    }
nkeynes@1006
   267
                } else if( IS_XMM_REG(it,1) ) {
nkeynes@1006
   268
                    MOVQ_r64_xmm( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   269
                } else {
nkeynes@1006
   270
                    MOVQ_r64_r64( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1006
   271
                }
nkeynes@1011
   272
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1006
   273
                if( IS_XMM_REG(it,1) ) {
nkeynes@1011
   274
                    MOVSD_r32disp_xmm( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   275
                } else {
nkeynes@1011
   276
                    MOVQ_r64disp_r64( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   277
                }
nkeynes@1006
   278
            } else {
nkeynes@1006
   279
                ILLOP(it);
nkeynes@1006
   280
            }
nkeynes@1006
   281
            break;
nkeynes@1006
   282
        case OP_MOVSX8:
nkeynes@1011
   283
            if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   284
                MOVSXL_r8_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1011
   285
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1011
   286
                MOVSXL_r32disp8_r32( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   287
            } else {
nkeynes@1006
   288
                ILLOP(it);
nkeynes@1006
   289
            }
nkeynes@1006
   290
            break;
nkeynes@1006
   291
        case OP_MOVSX16:
nkeynes@1011
   292
            if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   293
                MOVSXL_r16_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1011
   294
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1011
   295
                MOVSXL_r32disp16_r32( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   296
            } else {
nkeynes@1006
   297
                ILLOP(it);
nkeynes@1006
   298
            }
nkeynes@1006
   299
            break;
nkeynes@1006
   300
        case OP_MOVZX8:
nkeynes@1011
   301
            if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   302
                MOVZXL_r8_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1011
   303
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1011
   304
                MOVZXL_r32disp8_r32( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   305
            } else {
nkeynes@1006
   306
                ILLOP(it);
nkeynes@1006
   307
            }
nkeynes@1006
   308
            break;
nkeynes@1006
   309
        case OP_MOVZX16:
nkeynes@1011
   310
            if( XOP_IS_FORM(it, DST, DST) ) {
nkeynes@1006
   311
                MOVZXL_r16_r32( XOP_REG1(it), XOP_REG2(it) );
nkeynes@1011
   312
            } else if( XOP_IS_FORM(it, SRC, DST) ) {
nkeynes@1011
   313
                MOVZXL_r32disp16_r32( REG_RBP, SRCADDR(it,0), XOP_REG2(it) );
nkeynes@1006
   314
            } else {
nkeynes@1006
   315
                ILLOP(it);
nkeynes@1006
   316
            }
nkeynes@1006
   317
            break;
nkeynes@1006
   318
        case OP_ADD: 
nkeynes@1006
   319
        case OP_ADDS: X86L_ALU_REG(ADDL,it);  break;
nkeynes@1006
   320
        case OP_ADDCS: X86L_ALU_REG(ADCL,it); break;
nkeynes@1006
   321
        case OP_AND:  X86L_ALU_REG(ANDL,it); break;
nkeynes@1006
   322
        case OP_CMP:
nkeynes@1006
   323
            X86L_ALU_REG(CMPL,it); break;
nkeynes@1006
   324
        case OP_DEC:
nkeynes@1011
   325
            if( XOP_IS_FORM(it,DST,NONE) ) {
nkeynes@1006
   326
                DECL_r32(XOP_REG(it,0));
nkeynes@1006
   327
            } else if( XOP_IS_FORM(it,SRC,NONE) ) {
nkeynes@1011
   328
                DECL_r32disp( REG_RBP, SRCADDR(it,0) );
nkeynes@1006
   329
            } else {
nkeynes@1006
   330
                ILLOP(it);
nkeynes@1006
   331
            }
nkeynes@1006
   332
            break;
nkeynes@1006
   333
        case OP_MUL: 
nkeynes@1011
   334
            X86L_REG_DST(IMULL,it); 
nkeynes@1006
   335
            break;
nkeynes@1006
   336
        case OP_NEG:  X86L_REG(NEGL,it); break;
nkeynes@1006
   337
        case OP_NOT:  X86L_REG(NOTL,it); break;
nkeynes@1006
   338
        case OP_OR:   X86L_ALU_REG(ORL,it); break;
nkeynes@1006
   339
        case OP_RCL:  X86L_IMMCL_REG(RCLL,it); break;
nkeynes@1006
   340
        case OP_RCR:  X86L_IMMCL_REG(RCRL,it); break;
nkeynes@1006
   341
        case OP_ROL:  X86L_IMMCL_REG(ROLL,it); break;
nkeynes@1006
   342
        case OP_ROR:  X86L_IMMCL_REG(RORL,it); break;
nkeynes@1006
   343
        case OP_SAR: 
nkeynes@1006
   344
        case OP_SARS: X86L_IMMCL_REG(SARL,it); break;
nkeynes@1006
   345
        case OP_SUBBS: X86L_ALU_REG(SBBL,it); break;
nkeynes@1006
   346
        case OP_SLL: 
nkeynes@1006
   347
        case OP_SLLS: X86L_IMMCL_REG(SHLL,it); break;
nkeynes@1006
   348
        case OP_SLR: 
nkeynes@1006
   349
        case OP_SLRS: X86L_IMMCL_REG(SHRL,it); break;
nkeynes@1006
   350
        case OP_SUB: 
nkeynes@1006
   351
        case OP_SUBS: X86L_ALU_REG(SUBL,it); break;
nkeynes@1006
   352
        case OP_SHUFFLE:
nkeynes@1011
   353
            if( XOP_IS_FORM(it,IMM,DST) ) {
nkeynes@1006
   354
                if( XOP_INT(it,0) == 0x4321 ) {
nkeynes@1006
   355
                    BSWAPL_r32( XOP_REG(it,1) );
nkeynes@1006
   356
                } else if( it->operand[1].value.i == 0x1243 ) {
nkeynes@1006
   357
                    XCHGB_r8_r8( REG_AL, REG_AH ); 
nkeynes@1006
   358
                            /* XCHG al, ah */
nkeynes@1006
   359
                }
nkeynes@1006
   360
            }
nkeynes@1006
   361
            break;
nkeynes@1006
   362
        case OP_TST:  X86L_ALU_REG(TESTL,it); break;
nkeynes@1006
   363
        case OP_XOR:  X86L_ALU_REG(XORL,it); break;
nkeynes@1006
   364
            
nkeynes@1006
   365
            // Float
nkeynes@1006
   366
        case OP_ABSF:
nkeynes@1006
   367
        case OP_ABSD:
nkeynes@1006
   368
            // Why is there no SSE FP ABS instruction?
nkeynes@1006
   369
            break;
nkeynes@1011
   370
        case OP_ADDF: X86F_REG_DST(ADDSS,it); break;
nkeynes@1011
   371
        case OP_ADDD: X86F_REG_DST(ADDSD,it); break;
nkeynes@1006
   372
        case OP_CMPF:
nkeynes@1006
   373
            break;
nkeynes@1006
   374
        case OP_CMPD: // UCOMISD
nkeynes@1006
   375
            break;
nkeynes@1011
   376
        case OP_DIVF: X86F_REG_DST(DIVSS,it); break;
nkeynes@1011
   377
        case OP_DIVD: X86F_REG_DST(DIVSD,it); break;
nkeynes@1011
   378
        case OP_MULF: X86F_REG_DST(MULSS,it); break;
nkeynes@1011
   379
        case OP_MULD: X86F_REG_DST(MULSD,it); break;
nkeynes@1011
   380
        case OP_RSQRTF:X86F_REG_DST(RSQRTSS,it); break;
nkeynes@1011
   381
        case OP_SQRTF: X86F_REG_DST(SQRTSS,it); break;
nkeynes@1011
   382
        case OP_SQRTD: X86F_REG_DST(SQRTSD,it); break;
nkeynes@1011
   383
        case OP_SUBF:  X86F_REG_DST(SUBSS,it); break;
nkeynes@1011
   384
        case OP_SUBD:  X86F_REG_DST(SUBSD,it); break;
nkeynes@1006
   385
nkeynes@1006
   386
        case OP_DOTPRODV:
nkeynes@1011
   387
            MULPS_r32disp_xmm( REG_RBP, SRCADDR(it,0), 4 );
nkeynes@1006
   388
            HADDPS_xmm_xmm( 4, 4 ); 
nkeynes@1006
   389
            HADDPS_xmm_xmm( 4, 4 );
nkeynes@1011
   390
            MOVSS_xmm_r32disp( 4, REG_RBP, SRCADDR(it,0) );
nkeynes@1006
   391
            break;
nkeynes@1006
   392
        case OP_SINCOSF:
nkeynes@1006
   393
        case OP_MATMULV:
nkeynes@1006
   394
            break;
nkeynes@1006
   395
        case OP_FTOD:
nkeynes@1011
   396
            if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   397
                CVTSS2SD_xmm_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1011
   398
            } else if( XOP_IS_FORM(it,SRC,DST) ) {
nkeynes@1011
   399
                CVTSS2SD_r32disp_xmm( REG_RBP, SRCADDR(it,0), XOP_REG(it,1) );
nkeynes@1006
   400
            } else {
nkeynes@1006
   401
                ILLOP(it);
nkeynes@1006
   402
            }
nkeynes@1006
   403
            break;
nkeynes@1006
   404
        case OP_DTOF:
nkeynes@1011
   405
            if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   406
                CVTSS2SD_xmm_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1011
   407
            } else if( XOP_IS_FORM(it, SRC,DST) ) {
nkeynes@1011
   408
                CVTSS2SD_r32disp_xmm( REG_RBP, SRCADDR(it,0), XOP_REG(it,1) );
nkeynes@1006
   409
            } else {
nkeynes@1006
   410
                ILLOP(it);
nkeynes@1006
   411
            }
nkeynes@1006
   412
            break;
nkeynes@1006
   413
        case OP_ITOD:
nkeynes@1011
   414
            if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   415
                CVTSI2SDL_r32_xmm( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1011
   416
            } else if( XOP_IS_FORM(it,SRC,DST) ) {
nkeynes@1011
   417
                CVTSI2SDL_r32disp_xmm( REG_RBP, SRCADDR(it,0), XOP_REG(it,1) );
nkeynes@1006
   418
            } else {
nkeynes@1006
   419
                ILLOP(it);
nkeynes@1006
   420
            }
nkeynes@1006
   421
            break;
nkeynes@1006
   422
        case OP_DTOI:
nkeynes@1011
   423
            if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   424
                CVTSD2SIL_xmm_r32( XOP_REG(it,0), XOP_REG(it,1) );
nkeynes@1011
   425
            } else if( XOP_IS_FORM(it,SRC,DST) ) {
nkeynes@1011
   426
                CVTSD2SIL_r32disp_r32( REG_RBP, SRCADDR(it,0), XOP_REG(it,1) );
nkeynes@1006
   427
            } else {
nkeynes@1006
   428
                ILLOP(it);
nkeynes@1006
   429
            }
nkeynes@1006
   430
            break;
nkeynes@1006
   431
        case OP_ITOF:
nkeynes@1006
   432
        case OP_FTOI:
nkeynes@1006
   433
            
nkeynes@1006
   434
        case OP_BRCOND:
nkeynes@1006
   435
        case OP_BRREL:
nkeynes@1006
   436
        case OP_BR:
nkeynes@1006
   437
        case OP_BRCONDDEL:
nkeynes@1006
   438
nkeynes@1006
   439
        case OP_CALL0: 
nkeynes@1011
   440
            if( XOP_IS_IMM(it,0) ) { 
nkeynes@1006
   441
                CALL_imm32( XOP_INT(it,0) );
nkeynes@1011
   442
            } else if( XOP_IS_SRC(it,0) ) {
nkeynes@1006
   443
                CALL_r32( XOP_INT(it,0) );
nkeynes@1006
   444
            } else {
nkeynes@1006
   445
                ILLOP(it);
nkeynes@1006
   446
            }
nkeynes@1006
   447
            break;
nkeynes@1006
   448
        case OP_XLAT:
nkeynes@1006
   449
            if( IS_X86_64() ) {
nkeynes@1006
   450
                ss = 3;
nkeynes@1006
   451
            } else {
nkeynes@1006
   452
                ss = 2;
nkeynes@1006
   453
            }
nkeynes@1011
   454
            if( XOP_IS_FORM(it,IMM,DST) ) {
nkeynes@1006
   455
                MOVP_sib_rptr(ss, XOP_REG(it,1), -1, XOP_INT(it,0), XOP_REG(it,1));
nkeynes@1011
   456
            } else if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   457
                MOVP_sib_rptr(ss, XOP_REG(it,1), XOP_REG(it,0), 0, XOP_REG(it,1));
nkeynes@1006
   458
            } else {
nkeynes@1006
   459
                ILLOP(it);
nkeynes@1006
   460
            }
nkeynes@1006
   461
            break;
nkeynes@1006
   462
        case OP_CALLLUT:
nkeynes@1011
   463
            if( XOP_IS_FORM(it,DST,IMM) ) {
nkeynes@1006
   464
                CALL_r32disp(XOP_REG(it,0),XOP_INT(it,1));
nkeynes@1011
   465
            } else if( XOP_IS_FORM(it,DST,DST) ) {
nkeynes@1006
   466
                CALL_sib(0,XOP_REG(it,0),XOP_REG(it,1),0);
nkeynes@1011
   467
            } else if( XOP_IS_FORM(it,IMM,DST) ) {
nkeynes@1006
   468
                CALL_r32disp(XOP_REG(it,1),XOP_INT(it,0));
nkeynes@1006
   469
            } else {
nkeynes@1006
   470
                ILLOP(it);
nkeynes@1006
   471
            }
nkeynes@1006
   472
            break;
nkeynes@1006
   473
nkeynes@1006
   474
            // SH4-specific macro operations
nkeynes@1006
   475
        case OP_RAISEME:
nkeynes@1006
   476
            
nkeynes@1006
   477
        case OP_RAISEMNE:
nkeynes@1006
   478
            
nkeynes@1006
   479
        case OP_CMPSTR:
nkeynes@1006
   480
            break;
nkeynes@1006
   481
        case OP_DIV1: 
nkeynes@1006
   482
            break;
nkeynes@1006
   483
        case OP_SHAD:
nkeynes@1011
   484
            assert( it->operand[0].form == DST && XOP_REG(it,0) == REG_ECX );
nkeynes@1006
   485
            CMPL_imms_r32(0,REG_ECX);
nkeynes@1006
   486
            JNGE_label(shad_shr);
nkeynes@1006
   487
            X86L_CL_REG(SHLL,it);
nkeynes@1006
   488
            JMP_label(shad_end);
nkeynes@1006
   489
nkeynes@1006
   490
            JMP_TARGET(shad_shr);
nkeynes@1011
   491
            if( IS_X86_64() && it->operand[1].form == DST ) {
nkeynes@1006
   492
                /* We can do this a little more simply with a 64-bit shift */
nkeynes@1006
   493
                ORL_imms_r32(0xFFFFFFE0,REG_ECX);
nkeynes@1006
   494
                NEGL_r32(REG_ECX);
nkeynes@1006
   495
                MOVSXQ_r32_r64(XOP_REG(it,1), XOP_REG(it,1)); // sign-extend
nkeynes@1006
   496
                SARQ_cl_r64(XOP_REG(it,1));
nkeynes@1006
   497
            } else {
nkeynes@1006
   498
                NEGL_r32(REG_ECX);
nkeynes@1006
   499
                ANDB_imms_r8( 0x1F, REG_ECX );
nkeynes@1006
   500
                JE_label(emptyshr );
nkeynes@1006
   501
                X86L_CL_REG(SARL,it);
nkeynes@1006
   502
                JMP_label(shad_end2);
nkeynes@1006
   503
nkeynes@1006
   504
                JMP_TARGET(emptyshr);
nkeynes@1011
   505
                if( it->operand[1].form == DST ) {
nkeynes@1006
   506
                    SARL_imm_r32( 31, XOP_REG(it,1) );
nkeynes@1011
   507
                } else if( it->operand[1].form == SRC ) {
nkeynes@1011
   508
                    SARL_imm_r32disp( 32, REG_RBP, SRCADDR(it,1) );
nkeynes@1006
   509
                } else {
nkeynes@1011
   510
                    SARL_imm_r32disp( 32, REG_RSP, TMPADDR(it,1) );
nkeynes@1006
   511
                }
nkeynes@1006
   512
                JMP_TARGET(shad_end2);
nkeynes@1006
   513
            }
nkeynes@1006
   514
            JMP_TARGET(shad_end);
nkeynes@1006
   515
            break;
nkeynes@1006
   516
nkeynes@1006
   517
        case OP_SHLD:
nkeynes@1011
   518
            assert( it->operand[0].form == DST && XOP_REG(it,0) == REG_ECX );
nkeynes@1006
   519
            CMPL_imms_r32(0,REG_ECX);
nkeynes@1006
   520
            JNGE_label(shld_shr);
nkeynes@1006
   521
            X86L_CL_REG(SHLL,it);
nkeynes@1006
   522
            JMP_label(shld_end);
nkeynes@1006
   523
nkeynes@1006
   524
            JMP_TARGET(shld_shr);
nkeynes@1011
   525
            if( IS_X86_64() && it->operand[1].form == DST ) {
nkeynes@1006
   526
                /* We can do this a little more simply with a 64-bit shift */
nkeynes@1006
   527
                ORL_imms_r32(0xFFFFFFE0,REG_ECX);
nkeynes@1006
   528
                NEGL_r32(REG_ECX);
nkeynes@1006
   529
                MOVL_r32_r32(XOP_REG(it,1), XOP_REG(it,1)); // Ensure high bits are 0
nkeynes@1006
   530
                SHRQ_cl_r64(XOP_REG(it,1));
nkeynes@1006
   531
            } else {
nkeynes@1006
   532
                NEGL_r32(REG_ECX);
nkeynes@1006
   533
                ANDB_imms_r8( 0x1F, REG_ECX );
nkeynes@1006
   534
                JE_label(emptyshr );
nkeynes@1006
   535
                X86L_CL_REG(SHRL,it);
nkeynes@1006
   536
                JMP_label(shld_end2);
nkeynes@1006
   537
nkeynes@1006
   538
                JMP_TARGET(emptyshr);
nkeynes@1006
   539
                XORL_r32_r32( REG_EAX, REG_EAX );
nkeynes@1006
   540
                JMP_TARGET(shld_end2);
nkeynes@1006
   541
            }
nkeynes@1006
   542
            JMP_TARGET(shld_end);
nkeynes@1006
   543
            break;
nkeynes@1006
   544
nkeynes@1006
   545
        case OP_MULQ:
nkeynes@1006
   546
        case OP_ADDQSAT32:
nkeynes@1006
   547
        case OP_ADDQSAT48:
nkeynes@1006
   548
nkeynes@1006
   549
            // Should not occur (should be have been lowered in target_lower)
nkeynes@1006
   550
        case OP_NEGF:
nkeynes@1006
   551
        case OP_NEGD:
nkeynes@1006
   552
        case OP_LOADB:
nkeynes@1006
   553
        case OP_LOADBFW:
nkeynes@1006
   554
        case OP_LOADW:
nkeynes@1006
   555
        case OP_LOADL:
nkeynes@1006
   556
        case OP_LOADQ:
nkeynes@1006
   557
        case OP_STOREB:
nkeynes@1006
   558
        case OP_STOREW:
nkeynes@1006
   559
        case OP_STOREL:
nkeynes@1006
   560
        case OP_STOREQ:
nkeynes@1006
   561
        case OP_STORELCA:
nkeynes@1006
   562
        case OP_OCBI:
nkeynes@1006
   563
        case OP_OCBP:
nkeynes@1006
   564
        case OP_OCBWB:
nkeynes@1006
   565
        case OP_PREF:
nkeynes@1006
   566
        default:
nkeynes@1006
   567
            ILLOP(it);
nkeynes@1006
   568
        }
nkeynes@1006
   569
        if( it == end )
nkeynes@1006
   570
            break;
nkeynes@1006
   571
    /* Epilogue */
nkeynes@1006
   572
    }
nkeynes@1006
   573
}
.