Search
lxdream.org :: lxdream/src/xlat/xir.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/xir.h
changeset 1012:0b8cc74ac83a
prev1011:fdd58619b760
author nkeynes
date Sun Apr 19 05:14:19 2009 +0000 (15 years ago)
branchxlat-refactor
permissions -rw-r--r--
last change Remove branch instructions and replace with direct modification of PC + EXIT
Add MIN/MAX instructions (for bound checks)
Implement x86_target_is_legal
Correct a few sh4 instructions
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
 * This file defines the translation IR and associated functions.
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
nkeynes@1006
    19
#ifndef lxdream_xir_H
nkeynes@1006
    20
#define lxdream_xir_H 1
nkeynes@1006
    21
nkeynes@1006
    22
#include <stdint.h>
nkeynes@1006
    23
nkeynes@1006
    24
/*****************************************************************************
nkeynes@1006
    25
 *
nkeynes@1006
    26
 * We use a very simple low-level 2-op instruction form, largely intended to
nkeynes@1006
    27
 * closely match the x86 ISA to simplify final code generation. Complex
nkeynes@1006
    28
 * instructions are either broken up into simpler ops, or inserted as 
nkeynes@1006
    29
 * opaque macros. First operand is source, second operand is destination.
nkeynes@1006
    30
 *
nkeynes@1006
    31
 * Data types are encoded in the instruction:
nkeynes@1006
    32
 *    Byte   (B) 8-bit integer
nkeynes@1006
    33
 *    Word   (W) 16-bit integer
nkeynes@1006
    34
 *    Long   (L) 32-bit integer
nkeynes@1006
    35
 *    Quad   (Q) 64-bit integer
nkeynes@1006
    36
 *    Float  (F) 32-bit floating point
nkeynes@1006
    37
 *    Double (D) 64-bit floating point
nkeynes@1006
    38
 *    Vec4   (V) 4x32-bit floating point
nkeynes@1006
    39
 *    Matrix (M) 4x4x32-bit floating point in column-major order
nkeynes@1006
    40
 * This is not an exhaustive list, but it is sufficient to cover all operations
nkeynes@1006
    41
 * required for the SH4.
nkeynes@1006
    42
 * 
nkeynes@1006
    43
 * ALU instructions come in two variants, xxxS which modifies the condition 
nkeynes@1006
    44
 * flags, and the regular xxx version that does not. Implementations are assumed
nkeynes@1006
    45
 * to have at least the standard NZVC flags available (or will have to fake it) 
nkeynes@1006
    46
 * 
nkeynes@1006
    47
 * Variations in flag behaviour between implementations need to be accounted for
nkeynes@1006
    48
 * somehow.
nkeynes@1006
    49
 ****************************************************************************/
nkeynes@1006
    50
nkeynes@1006
    51
#define MAX_SOURCE_REGISTER 1023
nkeynes@1011
    52
#define MAX_TEMP_REGISTER 511
nkeynes@1011
    53
#define MAX_DEST_REGISTER 127
nkeynes@1006
    54
nkeynes@1011
    55
/* Preallocated temporaries for convenience */
nkeynes@1011
    56
#define REG_TMP0 0
nkeynes@1011
    57
#define REG_TMP1 1
nkeynes@1011
    58
#define REG_TMP2 2
nkeynes@1011
    59
#define REG_TMPQ0 3
nkeynes@1011
    60
#define REG_TMPQ1 4
nkeynes@1012
    61
#define REG_TMPF0 5
nkeynes@1012
    62
#define REG_TMPD0 6
nkeynes@1006
    63
nkeynes@1006
    64
nkeynes@1006
    65
/**
nkeynes@1006
    66
 * Operands are either integer, float, or double, and are either immediate or
nkeynes@1006
    67
 * assigned to a source-machine register, destination-machine register, or a
nkeynes@1006
    68
 * temporary register. (All temporaries have to be resolved to a dest-reg before
nkeynes@1006
    69
 * code generation)
nkeynes@1006
    70
 */
nkeynes@1006
    71
typedef enum {
nkeynes@1006
    72
    NO_OPERAND = 0,
nkeynes@1011
    73
    SOURCE_OPERAND =1, // Source (or temp) register
nkeynes@1011
    74
    DEST_OPERAND =2,
nkeynes@1011
    75
    TEMP_OPERAND=3,
nkeynes@1011
    76
    IMMEDIATE_OPERAND=4
nkeynes@1011
    77
} xir_operand_form_t;
nkeynes@1006
    78
nkeynes@1006
    79
typedef struct xir_operand {
nkeynes@1011
    80
    xir_operand_form_t form;
nkeynes@1006
    81
    union {
nkeynes@1006
    82
        uint32_t i;
nkeynes@1006
    83
        uint64_t q;
nkeynes@1006
    84
        float f;
nkeynes@1006
    85
        double d;
nkeynes@1006
    86
        void *p;
nkeynes@1006
    87
    } value;
nkeynes@1006
    88
} *xir_operand_t;
nkeynes@1006
    89
nkeynes@1011
    90
typedef enum {
nkeynes@1011
    91
    XTY_LONG = 0,  /* 32-bit integer */
nkeynes@1011
    92
    XTY_QUAD = 1,  /* 64-bit integer */
nkeynes@1011
    93
    XTY_FLOAT = 2, /* 32-bit float */
nkeynes@1011
    94
    XTY_DOUBLE = 3,/* 64-bit float */
nkeynes@1011
    95
    XTY_VEC4F  = 4,/* 4x 32-bit floats (16 bytes) */
nkeynes@1011
    96
    XTY_MAT16F = 5,/* 4x4x 32-bit floats (64 bytes) */
nkeynes@1011
    97
    XTY_PTR = 6,   /* Native pointer (of appropriate size) */
nkeynes@1011
    98
} xir_type_t;
nkeynes@1011
    99
nkeynes@1006
   100
/* Condition codes */
nkeynes@1006
   101
typedef enum {
nkeynes@1006
   102
    CC_TRUE = -1, /* Always */
nkeynes@1006
   103
    CC_OV   = 0,  /* Overflow */
nkeynes@1006
   104
    CC_NO   = 1,  /* !Overflow */
nkeynes@1006
   105
    CC_UGE  = 2,  /* Unsigned greater or equal */
nkeynes@1006
   106
    CC_ULT  = 3,  /* Unsigned less than */
nkeynes@1006
   107
    CC_ULE  = 4,  /* Unsigned less or equal */
nkeynes@1006
   108
    CC_UGT  = 5,  /* Unsigned greater than */
nkeynes@1006
   109
    CC_EQ   = 6,  /* Equal */
nkeynes@1006
   110
    CC_NE   = 7,  /* !Equal */
nkeynes@1006
   111
    CC_NEG  = 8,  /* Negative */
nkeynes@1006
   112
    CC_POS  = 9,  /* Not-negative (positive or zero) */ 
nkeynes@1006
   113
    CC_SGE  = 10,
nkeynes@1006
   114
    CC_SLT  = 11,
nkeynes@1006
   115
    CC_SLE  = 12,
nkeynes@1006
   116
    CC_SGT  = 13
nkeynes@1006
   117
} xir_cc_t;
nkeynes@1006
   118
nkeynes@1006
   119
#define CC_C  CC_ULT
nkeynes@1006
   120
#define CC_NC CC_UGE
nkeynes@1006
   121
nkeynes@1006
   122
typedef enum {
nkeynes@1006
   123
    // No operands
nkeynes@1006
   124
    OP_NOP     = 0,
nkeynes@1012
   125
    OP_EXIT,
nkeynes@1006
   126
    OP_BARRIER, // Direction to register allocator - Ensure all state is committed
nkeynes@1006
   127
nkeynes@1006
   128
    // One operand
nkeynes@1006
   129
    OP_DEC,        /* Decrement and set Z if result == 0 */
nkeynes@1006
   130
    OP_LD,        /* Load flags from reg/imm (1 = condition, 0 = !condition) */
nkeynes@1006
   131
    OP_ST,        /* Set reg to 1 on condition, 0 on !condition */
nkeynes@1006
   132
    OP_RESTFLAGS,    /* Restore flags from register */
nkeynes@1006
   133
    OP_SAVEFLAGS,    /* Save flags into register */
nkeynes@1006
   134
    OP_ENTER,     // Block start - immediate operand is a bitmask of target registers used
nkeynes@1006
   135
    OP_CALL0,  // Call function with no arguments or return value
nkeynes@1006
   136
    OP_OCBI,
nkeynes@1006
   137
    OP_OCBP,
nkeynes@1006
   138
    OP_OCBWB,
nkeynes@1006
   139
    OP_PREF,
nkeynes@1006
   140
nkeynes@1006
   141
    // Register moves */
nkeynes@1006
   142
    OP_MOV, 
nkeynes@1006
   143
    OP_MOVQ,
nkeynes@1006
   144
    OP_MOVV,
nkeynes@1006
   145
    OP_MOVM,
nkeynes@1006
   146
    OP_MOVSX8,
nkeynes@1006
   147
    OP_MOVSX16,
nkeynes@1006
   148
    OP_MOVSX32,
nkeynes@1006
   149
    OP_MOVZX8,
nkeynes@1006
   150
    OP_MOVZX16,
nkeynes@1006
   151
    OP_MOVZX32,
nkeynes@1006
   152
nkeynes@1006
   153
    /* ALU */
nkeynes@1006
   154
    OP_ADD,
nkeynes@1006
   155
    OP_ADDS,
nkeynes@1006
   156
    OP_ADDC,
nkeynes@1006
   157
    OP_ADDCS,
nkeynes@1006
   158
    OP_AND,
nkeynes@1006
   159
    OP_ANDS,
nkeynes@1006
   160
    OP_CMP,
nkeynes@1006
   161
    OP_DIV,    /* Unsigned division */
nkeynes@1006
   162
    OP_DIVS,   /* Unsigned divison and update flags */
nkeynes@1012
   163
    OP_MAX,
nkeynes@1012
   164
    OP_MAXQ,
nkeynes@1012
   165
    OP_MIN,
nkeynes@1012
   166
    OP_MINQ,
nkeynes@1006
   167
    OP_MUL,
nkeynes@1006
   168
    OP_MULS,
nkeynes@1006
   169
    OP_MULQ,
nkeynes@1006
   170
    OP_MULQS,
nkeynes@1006
   171
    OP_NEG,
nkeynes@1006
   172
    OP_NEGS,
nkeynes@1006
   173
    OP_NOT,
nkeynes@1006
   174
    OP_NOTS,
nkeynes@1006
   175
    OP_OR,
nkeynes@1006
   176
    OP_ORS,
nkeynes@1006
   177
    OP_RCL,
nkeynes@1006
   178
    OP_RCR,
nkeynes@1006
   179
    OP_ROL,    /* Rotate left w/o updating flags */
nkeynes@1006
   180
    OP_ROLS,   /* Rotate left, and set carry */ 
nkeynes@1006
   181
    OP_ROR,    /* Rotate right */
nkeynes@1006
   182
    OP_RORS,   /* Rotate right and set carry */
nkeynes@1006
   183
    OP_SAR,    /* Shift arithmetic right */
nkeynes@1006
   184
    OP_SARS,   /* Shift arithmetic right and set carry */
nkeynes@1006
   185
    OP_SDIV,   /* Signed division */
nkeynes@1006
   186
    OP_SDIVS,  /* Signed division and update flags */
nkeynes@1006
   187
    OP_SLL,    /* Shift logical left */
nkeynes@1006
   188
    OP_SLLS,   /* Shift logical left and set carry */
nkeynes@1006
   189
    OP_SLR,    /* Shift logical right */
nkeynes@1006
   190
    OP_SLRS,   /* Shift logical right and set carry */
nkeynes@1006
   191
    OP_SUB,    /* Subtract, no flags changed/used */
nkeynes@1006
   192
    OP_SUBS,   /* Subtract, flag set on overflow */
nkeynes@1006
   193
    OP_SUBB,    /* Subtract with borrow */
nkeynes@1006
   194
    OP_SUBBS,   /* Subtract with borrow and set carry */
nkeynes@1006
   195
    OP_SHUFFLE, /* Rearrange bytes according to immediate pattern */ 
nkeynes@1006
   196
    OP_TST,
nkeynes@1006
   197
    OP_XOR,
nkeynes@1006
   198
    OP_XORS,
nkeynes@1006
   199
    
nkeynes@1006
   200
    /* FPU */
nkeynes@1006
   201
    OP_ABSD,
nkeynes@1006
   202
    OP_ABSF,
nkeynes@1006
   203
    OP_ABSV,
nkeynes@1006
   204
    OP_ADDD,
nkeynes@1006
   205
    OP_ADDF,
nkeynes@1006
   206
    OP_ADDV,
nkeynes@1006
   207
    OP_CMPD,
nkeynes@1006
   208
    OP_CMPF,
nkeynes@1006
   209
    OP_DIVD,
nkeynes@1006
   210
    OP_DIVF,
nkeynes@1006
   211
    OP_DIVV,
nkeynes@1012
   212
    OP_MAXD,
nkeynes@1012
   213
    OP_MAXF,
nkeynes@1012
   214
    OP_MAXV,
nkeynes@1012
   215
    OP_MIND,
nkeynes@1012
   216
    OP_MINF,
nkeynes@1012
   217
    OP_MINV,
nkeynes@1006
   218
    OP_MULD,
nkeynes@1006
   219
    OP_MULF,
nkeynes@1006
   220
    OP_MULV,
nkeynes@1006
   221
    OP_NEGD,
nkeynes@1006
   222
    OP_NEGF,
nkeynes@1006
   223
    OP_NEGV,
nkeynes@1006
   224
    OP_SQRTD,
nkeynes@1006
   225
    OP_SQRTF,
nkeynes@1006
   226
    OP_SQRTV,
nkeynes@1006
   227
    OP_RSQRTD,
nkeynes@1006
   228
    OP_RSQRTF,
nkeynes@1006
   229
    OP_RSQRTV,
nkeynes@1006
   230
    OP_SUBD,
nkeynes@1006
   231
    OP_SUBF,
nkeynes@1006
   232
    OP_SUBV,
nkeynes@1006
   233
    OP_DTOF,
nkeynes@1006
   234
    OP_DTOI,
nkeynes@1006
   235
    OP_FTOD,
nkeynes@1006
   236
    OP_FTOI,
nkeynes@1006
   237
    OP_ITOD,
nkeynes@1006
   238
    OP_ITOF,
nkeynes@1006
   239
    OP_SINCOSF,
nkeynes@1006
   240
    OP_DOTPRODV,
nkeynes@1006
   241
    OP_MATMULV,
nkeynes@1006
   242
nkeynes@1006
   243
    // Memory operations - these all indirect through the memory tables.
nkeynes@1006
   244
    OP_LOADB,
nkeynes@1006
   245
    OP_LOADBFW,
nkeynes@1006
   246
    OP_LOADW,
nkeynes@1006
   247
    OP_LOADL,
nkeynes@1006
   248
    OP_LOADQ,
nkeynes@1006
   249
    OP_STOREB,
nkeynes@1006
   250
    OP_STOREW,
nkeynes@1006
   251
    OP_STOREL,
nkeynes@1006
   252
    OP_STOREQ,
nkeynes@1006
   253
    OP_STORELCA,
nkeynes@1006
   254
    
nkeynes@1006
   255
    OP_RAISEME, // imm mask in, reg in - branch to exception if (reg & mask) == 0
nkeynes@1006
   256
    OP_RAISEMNE, // imm mask in, reg in - branch to exception if (reg & mask) != 0
nkeynes@1006
   257
nkeynes@1006
   258
nkeynes@1011
   259
    // Native operations
nkeynes@1006
   260
    OP_CALLLUT, // Call indirect through base pointer (reg) + displacement
nkeynes@1006
   261
    OP_CALL1,  // Call function with single argument and no return value
nkeynes@1006
   262
    OP_CALLR,  // Call function with no arguments and a single return value
nkeynes@1012
   263
    OP_LOADPTRW, // Load 16-bit word from pointer and sign extend to 32-bits
nkeynes@1011
   264
    OP_LOADPTRL,
nkeynes@1011
   265
    OP_LOADPTRQ, 
nkeynes@1011
   266
    OP_XLAT,
nkeynes@1006
   267
nkeynes@1006
   268
    /********************** SH4-specific macro operations *************************/
nkeynes@1006
   269
    /* TODO: These need to be broken down into smaller operations eventually, 
nkeynes@1006
   270
     * especially as some are likely to be partially optimizable. But in the
nkeynes@1006
   271
     * meantime this at least gets things working
nkeynes@1006
   272
     */
nkeynes@1006
   273
    
nkeynes@1006
   274
    /**
nkeynes@1006
   275
     * ADDQSAT32 Rm, Rn - 64-bit Add Rm to Rn, saturating to 32-bits if S==1 (per SH4 MAC.W) 
nkeynes@1006
   276
     * 
nkeynes@1006
   277
     * if R_S == 0 ->
nkeynes@1006
   278
     *     Rn += Rm
nkeynes@1006
   279
     * else ->
nkeynes@1006
   280
     *     if overflow32( Rn + Rm ) ->
nkeynes@1006
   281
     *         Rn = saturate32( Rn + Rm ) | 0x100000000
nkeynes@1006
   282
     *     else ->
nkeynes@1006
   283
     *         Rn += Rm
nkeynes@1006
   284
     */
nkeynes@1006
   285
    OP_ADDQSAT32, 
nkeynes@1006
   286
    
nkeynes@1006
   287
    /**
nkeynes@1006
   288
     * ADDSAT48 Rm, Rn - 64-bit Add Rm to Rn, saturating to 48-bits if S==1 (per SH4 MAC.L)
nkeynes@1006
   289
     * 
nkeynes@1006
   290
     * if R_S == 0 ->
nkeynes@1012
   291
     *     ADDQ Rm, Rn
nkeynes@1006
   292
     * else ->
nkeynes@1012
   293
     *     ADDQ Rm, Rn
nkeynes@1012
   294
     *     if overflow ->
nkeynes@1006
   295
     *     else ->
nkeynes@1012
   296
     *         MINQ 0x00007FFFFFFFFFFF, Rn 
nkeynes@1012
   297
     *         MAXQ 0xFFFF800000000000, Rn
nkeynes@1006
   298
     */
nkeynes@1006
   299
    OP_ADDQSAT48,
nkeynes@1006
   300
    
nkeynes@1006
   301
    /**
nkeynes@1006
   302
     * CMP/STR Rm, Rn - Set T if any byte is the same between Rm and Rn
nkeynes@1006
   303
     * 
nkeynes@1006
   304
     * Macro expansion:
nkeynes@1006
   305
     *   MOV Rm, %tmp
nkeynes@1006
   306
     *   XOR Rn, %tmp
nkeynes@1006
   307
     *   TEST   0x000000FF, %tmp     
nkeynes@1006
   308
     *   TESTne 0x0000FF00, %tmp      
nkeynes@1006
   309
     *   TESTne 0x00FF0000, %tmp      
nkeynes@1006
   310
     *   TESTne 0xFF000000, %tmp      
nkeynes@1006
   311
     *   SETe T
nkeynes@1006
   312
     * 
nkeynes@1006
   313
     */
nkeynes@1006
   314
    OP_CMPSTR,
nkeynes@1006
   315
    
nkeynes@1006
   316
    /**
nkeynes@1006
   317
     * DIV1 Rm,Rn performs a single-step division of Rm/Rn, modifying flags
nkeynes@1006
   318
     * as it goes.
nkeynes@1006
   319
     * 
nkeynes@1006
   320
     * sign = Rn >> 31
nkeynes@1006
   321
     * Rn = (Rn << 1) | R_T
nkeynes@1006
   322
     * If R_Q == R_M -> Rn = Rn - Rm
nkeynes@1006
   323
     * Else           -> Rn = Rn + Rm
nkeynes@1006
   324
     * R_Q = sign ^ R_M ^ (Rn>>31)
nkeynes@1006
   325
     * R_T = (R_Q == R_M)    ; or newq == (rn>>31)
nkeynes@1006
   326
     * 
nkeynes@1006
   327
     * Macro expansion:
nkeynes@1006
   328
     *   LDc R_T
nkeynes@1006
   329
     *   RCL 1, Rn
nkeynes@1006
   330
     *   SETc temp
nkeynes@1006
   331
     *   CMP R_Q, R_M
nkeynes@1006
   332
     *   ADDne Rm, Rn
nkeynes@1006
   333
     *   SUBeq Rm, Rn
nkeynes@1006
   334
     *   MOV Rn, R_Q
nkeynes@1006
   335
     *   SHR 31, Rn
nkeynes@1006
   336
     *   XOR temp, R_Q
nkeynes@1006
   337
     *   XOR R_M, R_Q
nkeynes@1006
   338
     *   CMP R_M, R_Q
nkeynes@1006
   339
     *   SETe R_T
nkeynes@1006
   340
     */
nkeynes@1006
   341
    OP_DIV1, 
nkeynes@1006
   342
    
nkeynes@1006
   343
    /**
nkeynes@1006
   344
     * SHAD Rm, Rn performs an arithmetic shift of Rn as follows:
nkeynes@1006
   345
     *   If Rm >= 0 -> Rn = Rn << (Rm&0x1F)
nkeynes@1006
   346
     *   If Rm < 0  -> 
nkeynes@1006
   347
     *      If Rm&0x1F == 0 -> Rn = Rn >> 31
nkeynes@1006
   348
     *      Else            -> Rn = Rn >> 32 - (Rm&0x1F)
nkeynes@1006
   349
     * 
nkeynes@1006
   350
     *   CMP 0, Rm
nkeynes@1006
   351
     *   ANDuge 0x1F, Rm
nkeynes@1006
   352
     *   SLLuge Rm, Rn
nkeynes@1006
   353
     *   ORult 0xFFFFFFE0, Rm
nkeynes@1006
   354
     *   NEGult Rm
nkeynes@1006
   355
     *   SARult Rm, Rn ; unmasked shift
nkeynes@1006
   356
     *   
nkeynes@1006
   357
     */
nkeynes@1006
   358
    OP_SHAD,   // Shift dynamic arithmetic (left or right)
nkeynes@1006
   359
    
nkeynes@1006
   360
    /**
nkeynes@1006
   361
     * SHLD Rm, Rn performs a logical shift of Rn as follows:
nkeynes@1006
   362
     *   If Rm >= 0 -> Rn = Rn << (Rm&0x1F)
nkeynes@1006
   363
     *   If Rm < 0  -> 
nkeynes@1006
   364
     *      If Rm&0x1F == 0 -> Rn = 0
nkeynes@1006
   365
     *      Else            -> Rn = Rn >> 32 - (Rm&0x1F)
nkeynes@1006
   366
     */
nkeynes@1006
   367
    OP_SHLD,   // Shift dynamic logical (left or right)
nkeynes@1006
   368
} xir_opcode_t;
nkeynes@1006
   369
nkeynes@1006
   370
#define MAX_OP0_OPCODE OP_BARRIER
nkeynes@1006
   371
#define MAX_OP1_OPCODE OP_PREF
nkeynes@1006
   372
#define MAX_OP2_OPCODE OP_SHLD
nkeynes@1006
   373
#define NUM_OP0_OPCODES (MAX_OP0_OPCODE+1)
nkeynes@1006
   374
#define NUM_OP1_OPCODES (MAX_OP1_OPCODE-MAX_OP0_OPCODE)
nkeynes@1006
   375
#define NUM_OP2_OPCODES (MAX_OP2_OPCODE-MAX_OP1_OPCODE)
nkeynes@1006
   376
#define MAX_OPCODE (MAX_OP2_OPCODE)
nkeynes@1006
   377
#define NUM_OPCODES (MAX_OP2_OPCODE+1)
nkeynes@1006
   378
nkeynes@1006
   379
typedef struct xir_op {
nkeynes@1006
   380
    xir_opcode_t opcode;
nkeynes@1006
   381
    xir_cc_t cond;
nkeynes@1006
   382
    struct xir_operand operand[2];
nkeynes@1006
   383
    struct xir_op *next; /* Next instruction (normal path) - NULL in the case of the last instruction */
nkeynes@1006
   384
    struct xir_op *prev; /* Previous instruction (normal path) - NULL in the case of the first instruction */
nkeynes@1006
   385
    struct xir_op *exc;  /* Next instruction if the opcode takes an exception - NULL if no exception is possible */
nkeynes@1006
   386
} *xir_op_t;
nkeynes@1006
   387
nkeynes@1006
   388
/* Defined in xlat/xlat.h */
nkeynes@1006
   389
typedef struct xlat_source_machine *xlat_source_machine_t;
nkeynes@1006
   390
typedef struct xlat_target_machine *xlat_target_machine_t;
nkeynes@1006
   391
nkeynes@1011
   392
typedef struct xir_temp_register {
nkeynes@1011
   393
    xir_type_t type;
nkeynes@1011
   394
    uint32_t home_register; /* corresponding source register, or -1 for none */
nkeynes@1011
   395
} *xir_temp_register_t;
nkeynes@1011
   396
nkeynes@1006
   397
/**
nkeynes@1006
   398
 * Source data structure. This mainly exists to manage memory for XIR operations
nkeynes@1006
   399
 */
nkeynes@1006
   400
typedef struct xir_basic_block {
nkeynes@1006
   401
    xir_op_t ir_begin; /* Beginning of code block */
nkeynes@1006
   402
    xir_op_t ir_end; /* End of code block (Last instruction in code block) */
nkeynes@1006
   403
    xir_op_t ir_ptr; /* First unallocated instruction in allocation block */
nkeynes@1006
   404
    xir_op_t ir_alloc_begin; /* Beginning of memory allocation */
nkeynes@1006
   405
    xir_op_t ir_alloc_end; /* End of allocation */
nkeynes@1006
   406
    uint32_t pc_begin; /* first instruction */
nkeynes@1006
   407
    uint32_t pc_end;   /* next instruction after end */ 
nkeynes@1011
   408
    struct xir_temp_register temp_regs[MAX_TEMP_REGISTER+1]; /* temporary register table */
nkeynes@1011
   409
    uint32_t next_temp_reg;
nkeynes@1006
   410
    xlat_source_machine_t source;
nkeynes@1011
   411
    xlat_target_machine_t target;
nkeynes@1006
   412
    struct mem_region_fn **address_space; /* source machine memory access table */
nkeynes@1006
   413
} *xir_basic_block_t;
nkeynes@1006
   414
nkeynes@1006
   415
typedef int xir_offset_t;
nkeynes@1006
   416
nkeynes@1006
   417
/**************************** OP Information ******************************/
nkeynes@1006
   418
nkeynes@1006
   419
/* Instruction operand modes */
nkeynes@1006
   420
#define OPM_NO   0x000000  /* No operands */
nkeynes@1006
   421
#define OPM_R    0x000001  /* Single operand, read-only */
nkeynes@1006
   422
#define OPM_W    0x000002  /* Single operand, write-only */
nkeynes@1006
   423
#define OPM_RW   0x000003  /* Single operand, read-write */
nkeynes@1006
   424
#define OPM_R_R  0x000005  /* Two operands, both read-only */
nkeynes@1006
   425
#define OPM_R_W  0x000009  /* Two operands, first read-only, second write-only */
nkeynes@1006
   426
#define OPM_R_RW 0x00000D  /* Two operands, first read-only, second read-write */
nkeynes@1006
   427
#define OPM_I_I  0x000000  /* Both operands i32 */
nkeynes@1006
   428
#define OPM_Q_Q  0x000110  /* Both operands i64 */
nkeynes@1006
   429
#define OPM_I_Q  0x000100  /* i32,i64 operands */
nkeynes@1006
   430
#define OPM_Q_I  0x000010  /* i64,i32 operands */
nkeynes@1006
   431
#define OPM_F_F  0x000220  /* Both operands float */
nkeynes@1006
   432
#define OPM_D_D  0x000330  /* Both operands double */
nkeynes@1006
   433
#define OPM_I_F  0x000200  /* i32,float operands */
nkeynes@1006
   434
#define OPM_I_D  0x000300  /* i32,double operands */
nkeynes@1006
   435
#define OPM_F_I  0x000020  /* float,i32 operands */
nkeynes@1006
   436
#define OPM_D_I  0x000030  /* double,i32 operands */
nkeynes@1006
   437
#define OPM_F_D  0x000320  /* float,double operands */
nkeynes@1006
   438
#define OPM_D_F  0x000230  /* double,float operands */
nkeynes@1006
   439
#define OPM_V_V  0x000440  /* vec4,vec4 operands */
nkeynes@1006
   440
#define OPM_V_M  0x000540  /* vec4,matrix16 operands */
nkeynes@1006
   441
#define OPM_M_M  0x000550  /* mat16,mat16 operands */
nkeynes@1006
   442
#define OPM_TR   0x001000  /* Use T */
nkeynes@1006
   443
#define OPM_TW   0x002000  /* Set T */
nkeynes@1006
   444
#define OPM_TRW  0x003000  /* Use+Set T */
nkeynes@1006
   445
#define OPM_EXC  0x004000  /* May raise an exception, clobbers volatiles */
nkeynes@1006
   446
#define OPM_CLB  0x008000  /* Clobbers volatile registers */
nkeynes@1006
   447
#define OPM_CLBT 0x00C000  /* Clobbers 'temporary regs' but not the full volatile set */
nkeynes@1006
   448
#define OPM_TERM 0x010000 /* Terminates block. (Must be final instruction in block) */ 
nkeynes@1006
   449
nkeynes@1006
   450
#define OPM_R_R_TW   (OPM_R_R|OPM_TW)   /* Read two ops + set flags */
nkeynes@1006
   451
#define OPM_R_RW_TR  (OPM_R_RW|OPM_TR)  /* Read/write + use flags */
nkeynes@1006
   452
#define OPM_R_RW_TW  (OPM_R_RW|OPM_TW)  /* Read/write + set flags */
nkeynes@1006
   453
#define OPM_R_RW_TRW (OPM_R_RW|OPM_TRW) /* Read/write + use/set flags */
nkeynes@1006
   454
#define OPM_R_W_TW   (OPM_R_W|OPM_TW)  /* Read/write + set flags */
nkeynes@1006
   455
#define OPM_RW_TW    (OPM_RW|OPM_TW)    /* Read/write single op + set flags */
nkeynes@1006
   456
#define OPM_RW_TRW   (OPM_RW|OPM_TRW)   /* Read/write single op + use/set flags */
nkeynes@1006
   457
#define OPM_FRW      (OPM_RW|OPM_F_F)   /* Read/write single float op */
nkeynes@1006
   458
#define OPM_FR_FRW   (OPM_R_RW|OPM_F_F) /* Read/write float op pair */
nkeynes@1006
   459
#define OPM_FR_FW    (OPM_R_W|OPM_F_F) /* Read/write float op pair */
nkeynes@1006
   460
#define OPM_FR_FR_TW (OPM_R_R_TW|OPM_F_F) /* Read two float ops + set flags */ 
nkeynes@1006
   461
#define OPM_DRW      (OPM_RW|OPM_D_D)   /* Read/write single double op */
nkeynes@1006
   462
#define OPM_DR_DRW   (OPM_R_RW|OPM_D_D) /* Read/write double op pair */
nkeynes@1006
   463
#define OPM_DR_DW    (OPM_R_W|OPM_D_D) /* Read/write double op pair */
nkeynes@1006
   464
#define OPM_VR_VRW   (OPM_R_RW|OPM_V_V) /* Vector Read/write double op pair */
nkeynes@1006
   465
#define OPM_VR_VW    (OPM_R_W|OPM_V_V) /* Vector Read/write double op pair */
nkeynes@1006
   466
#define OPM_DR_DR_TW (OPM_R_R_TW|OPM_D_D) /* Read two double ops + set flags */
nkeynes@1006
   467
nkeynes@1006
   468
#define OPM_R_W_EXC  (OPM_R_W|OPM_EXC)  /* Read first, write second, possible exc (typical load) */
nkeynes@1006
   469
#define OPM_R_R_EXC  (OPM_R_R|OPM_EXC)  /* Read first, write second, possible exc (typical store) */
nkeynes@1006
   470
#define OPM_R_EXC    (OPM_R|OPM_EXC)    /* Read-only single op, possible exc (eg pref) */
nkeynes@1006
   471
nkeynes@1006
   472
struct xir_opcode_entry {
nkeynes@1006
   473
    char *name;
nkeynes@1006
   474
    int mode;
nkeynes@1006
   475
};
nkeynes@1006
   476
nkeynes@1006
   477
struct xir_symbol_entry {
nkeynes@1006
   478
    const char *name;
nkeynes@1006
   479
    void *ptr;
nkeynes@1006
   480
};
nkeynes@1006
   481
nkeynes@1011
   482
extern const struct xir_opcode_entry XIR_OPCODE_TABLE[];
nkeynes@1011
   483
extern const int XIR_OPERAND_SIZE[];
nkeynes@1006
   484
nkeynes@1006
   485
#define XOP_REG(op,n) (op->operand[n].value.i)
nkeynes@1006
   486
#define XOP_REG1(op) XOP_REG(op,0)
nkeynes@1006
   487
#define XOP_REG2(op) XOP_REG(op,1)
nkeynes@1006
   488
#define XOP_INT(op,n) (op->operand[n].value.i)
nkeynes@1006
   489
#define XOP_QUAD(op,n) (op->operand[n].value.q)
nkeynes@1006
   490
#define XOP_FLOAT(op,n) (op->operand[n].value.f)
nkeynes@1006
   491
#define XOP_DOUBLE(op,n) (op->operand[n].value.d)
nkeynes@1006
   492
#define XOP_PTR(op,n) (op->operand[n].value.p)
nkeynes@1006
   493
nkeynes@1006
   494
#define XOP_IS_TERMINATOR(op) (XIR_OPCODE_TABLE[op->opcode].mode & OPM_TERM)
nkeynes@1006
   495
#define XOP_HAS_0_OPERANDS(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0F) == 0)
nkeynes@1006
   496
#define XOP_HAS_1_OPERAND(op)  ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0F) < 4)
nkeynes@1006
   497
#define XOP_HAS_2_OPERANDS(op)  ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0C) != 0)
nkeynes@1006
   498
#define XOP_HAS_EXCEPTION(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0xC000) == OPM_EXC)
nkeynes@1006
   499
nkeynes@1006
   500
#define XOP_READS_OP1(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x01)
nkeynes@1006
   501
#define XOP_WRITES_OP1(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x02)
nkeynes@1006
   502
#define XOP_READS_OP2(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x04)
nkeynes@1006
   503
#define XOP_WRITES_OP2(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x08)
nkeynes@1006
   504
#define XOP_READS_FLAGS(op) ((XIR_OPCODE_TABLE[op->opcode].mode & OPM_TR) || (op->cond != CC_TRUE && op->opcode != OP_LD)) 
nkeynes@1006
   505
#define XOP_WRITES_FLAGS(op) (XIR_OPCODE_TABLE[op->opcode].mode & OPM_TW)
nkeynes@1006
   506
nkeynes@1006
   507
#define XOP_READS_REG1(op) (XOP_READS_OP1(op) && XOP_IS_REG(op,0))
nkeynes@1006
   508
#define XOP_WRITES_REG1(op) (XOP_WRITES_OP1(op) && XOP_IS_REG(op,0))
nkeynes@1006
   509
#define XOP_READS_REG2(op) (XOP_READS_OP2(op) && XOP_IS_REG(op,1))
nkeynes@1006
   510
#define XOP_WRITES_REG2(op) (XOP_WRITES_OP2(op) && XOP_IS_REG(op,1))
nkeynes@1006
   511
nkeynes@1011
   512
#define XOP_TYPE1(op) ((XIR_OPCODE_TABLE[op->opcode].mode >> 4) & 0x0F)
nkeynes@1011
   513
#define XOP_TYPE2(op) ((XIR_OPCODE_TABLE[op->opcode].mode >> 8) & 0x0F)
nkeynes@1011
   514
#define XOP_FORM1(op) (op->operand[0].form)
nkeynes@1011
   515
#define XOP_FORM2(op) (op->operand[1].form)
nkeynes@1006
   516
#define XOP_OPERAND(op,i) (&op->operand[i])
nkeynes@1011
   517
#define XOP_OPTYPE(op,n) (n == 0 ? XOP_TYPE1(op) : XOP_TYPE2(op))
nkeynes@1011
   518
#define XOP_OPSIZE(op,n) (XIR_OPERAND_SIZE[XOP_OPTYPE(op,n)])
nkeynes@1006
   519
nkeynes@1011
   520
#define XOP_IS_SRC(op,n) (op->operand[n].form == SOURCE_OPERAND)
nkeynes@1011
   521
#define XOP_IS_DST(op,n) (op->operand[n].form == DEST_OPERAND)
nkeynes@1011
   522
#define XOP_IS_TMP(op,n) (op->operand[n].form == TEMP_OPERAND)
nkeynes@1011
   523
#define XOP_IS_IMM(op,n) (op->operand[n].form == IMMEDIATE_OPERAND)
nkeynes@1011
   524
#define XOP_IS_IMMF(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_FLOAT)
nkeynes@1011
   525
#define XOP_IS_IMMD(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_DOUBLE)
nkeynes@1011
   526
#define XOP_IS_IMML(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_LONG)
nkeynes@1011
   527
#define XOP_IS_IMMQ(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_QUAD)
nkeynes@1011
   528
#define XOP_IS_IMMP(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_PTR)
nkeynes@1011
   529
#define XOP_IS_REG(op,n) (op->operand[n].form >= SOURCE_OPERAND && op->operand[n].form <= TEMP_OPERAND)
nkeynes@1011
   530
#define XOP_IS_FORM(op,t1,t2) (op->operand[0].form == t1 && op->operand[1].form == t2)
nkeynes@1006
   531
nkeynes@1011
   532
/******************************* IR Construction ******************************/
nkeynes@1006
   533
nkeynes@1011
   534
/**
nkeynes@1011
   535
 * Clear out a basic block structure, ready for reuse
nkeynes@1011
   536
 */
nkeynes@1011
   537
void xir_clear_basic_block( xir_basic_block_t xbb );
nkeynes@1006
   538
nkeynes@1011
   539
/**
nkeynes@1011
   540
 * Allocate a temporary register of the given type, with given home position
nkeynes@1011
   541
 * (-1 for a pure temporary)
nkeynes@1011
   542
 */
nkeynes@1011
   543
uint32_t xir_alloc_temp_reg( xir_basic_block_t xbb, xir_type_t type, int home );
nkeynes@1011
   544
nkeynes@1011
   545
xir_op_t xir_append_op2( xir_basic_block_t xbb, int op, int arg0form, uint32_t arg0, int arg1form, uint32_t arg1 );
nkeynes@1011
   546
xir_op_t xir_append_op2cc( xir_basic_block_t xbb, int op, int cc, int arg0form, uint32_t arg0, int arg1form, uint32_t arg1 );
nkeynes@1011
   547
xir_op_t xir_append_float_op2( xir_basic_block_t xbb, int op, float imm1, int arg1form, uint32_t arg1 );
nkeynes@1011
   548
xir_op_t xir_append_ptr_op2( xir_basic_block_t xbb, int op, void *arg0, int arg1form, uint32_t arg1 );
nkeynes@1011
   549
nkeynes@1011
   550
nkeynes@1011
   551
#define XOP1I( op, arg0 )      xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, NO_OPERAND, 0)
nkeynes@1011
   552
#define XOP1S( op, arg0 )       xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, NO_OPERAND, 0)
nkeynes@1011
   553
#define XOP1SCC( op, cc, arg0 ) xir_append_op2cc(xbb, op, cc, SOURCE_OPERAND, arg0, NO_OPERAND, 0)
nkeynes@1011
   554
#define XOP1T( op, arg0 )       xir_append_op2(xbb, op, TEMP_OPERAND, arg0, NO_OPERAND, 0)
nkeynes@1011
   555
#define XOP1TCC( op, cc, arg0 ) xir_append_op2cc(xbb, op, cc, TEMP_OPERAND, arg0, NO_OPERAND, 0)
nkeynes@1011
   556
#define XOP2IS( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, SOURCE_OPERAND, arg1)
nkeynes@1012
   557
#define XOP2ISCC( op, cc, arg0, arg1 ) xir_append_op2cc(xbb, op, cc, IMMEDIATE_OPERAND, arg0, SOURCE_OPERAND, arg1)
nkeynes@1011
   558
#define XOP2IT( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, TEMP_OPERAND, arg1)
nkeynes@1011
   559
#define XOP2II( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, IMMEDIATE_OPERAND, arg1)
nkeynes@1011
   560
#define XOP2IICC( op, cc, arg0, arg1 ) xir_append_op2cc(xbb, op, cc, IMMEDIATE_OPERAND, arg0, IMMEDIATE_OPERAND, arg1)
nkeynes@1011
   561
#define XOP2SS( op, arg0, arg1 ) xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, SOURCE_OPERAND, arg1)
nkeynes@1011
   562
#define XOP2ST( op, arg0, arg1 ) xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, TEMP_OPERAND, arg1)
nkeynes@1011
   563
#define XOP2TS( op, arg0, arg1 ) xir_append_op2(xbb, op, TEMP_OPERAND, arg0, SOURCE_OPERAND, arg1)
nkeynes@1011
   564
#define XOP2TT( op, arg0, arg1 ) xir_append_op2(xbb, op, TEMP_OPERAND, arg0, TEMP_OPERAND, arg1)
nkeynes@1011
   565
#define XOP2CC( op, cc, arg0, arg1 ) xir_append_op2cc(xbb, op, cc, SOURCE_OPERAND, arg0, SOURCE_OPERAND, arg1)
nkeynes@1011
   566
#define XOP2FS( op, arg0, arg1 ) xir_append_float_op2(xbb, op, arg0, SOURCE_OPERAND, arg1) 
nkeynes@1011
   567
#define XOP2PS( op, arg0, arg1 ) xir_append_ptr_op2(xbb, op, arg0, SOURCE_OPERAND, arg1) 
nkeynes@1011
   568
#define XOP2PT( op, arg0, arg1 ) xir_append_ptr_op2(xbb, op, arg0, TEMP_OPERAND, arg1) 
nkeynes@1006
   569
#define XOP0( op )             xir_append_op2(xbb, op, NO_OPERAND, 0, NO_OPERAND, 0)
nkeynes@1006
   570
#define XOPCALL0( arg0 )   xir_append_ptr_op2(xbb, OP_CALL0, arg0, NO_OPERAND, 0) 
nkeynes@1011
   571
#define XOPCALL1I( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, IMMEDIATE_OPERAND, arg1)
nkeynes@1011
   572
#define XOPCALL1S( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, SOURCE_OPERAND, arg1) 
nkeynes@1011
   573
#define XOPCALL1T( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, TEMP_OPERAND, arg1) 
nkeynes@1011
   574
#define XOPCALLRS( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALLR, arg0, SOURCE_OPERAND, arg1)
nkeynes@1011
   575
#define XOPCALLRT( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALLR, arg0, TEMP_OPERAND, arg1)
nkeynes@1006
   576
nkeynes@1006
   577
/**************************** IR Modification ******************************/
nkeynes@1006
   578
nkeynes@1006
   579
/**
nkeynes@1006
   580
 * Insert a new instruction immediately before the given existing inst.
nkeynes@1006
   581
 */
nkeynes@1006
   582
void xir_insert_op( xir_op_t op, xir_op_t before );
nkeynes@1006
   583
nkeynes@1006
   584
/**
nkeynes@1006
   585
 * Insert the block start..end immediately before the given instruction
nkeynes@1006
   586
 */
nkeynes@1006
   587
void xir_insert_block( xir_op_t start, xir_op_t end, xir_op_t before );
nkeynes@1006
   588
                      
nkeynes@1006
   589
/**
nkeynes@1006
   590
 * Remove the specified instruction completely from the block in which it appears.
nkeynes@1006
   591
 * Note: removing terminators with this method may break the representation.
nkeynes@1006
   592
 * Op itself is not modified. 
nkeynes@1006
   593
 */
nkeynes@1006
   594
void xir_remove_op( xir_op_t op );
nkeynes@1006
   595
nkeynes@1006
   596
/**
nkeynes@1006
   597
 * Apply a shuffle directly to the given operand, and return the result
nkeynes@1006
   598
 */ 
nkeynes@1006
   599
uint32_t xir_shuffle_imm32( uint32_t shuffle, uint32_t operand );
nkeynes@1006
   600
nkeynes@1006
   601
/**
nkeynes@1006
   602
 * Apply a shuffle transitively to the operation (which must also be a shuffle).
nkeynes@1006
   603
 * For example, given the sequence
nkeynes@1006
   604
 *   op1: shuffle 0x2134, r12
nkeynes@1006
   605
 *   op2: shuffle 0x3412, r12
nkeynes@1006
   606
 * xir_trans_shuffle( 0x2134, op2 ) can be used to replace op2 wih
nkeynes@1006
   607
 *        shuffle 0x3421, r12
nkeynes@1006
   608
 */
nkeynes@1006
   609
void xir_shuffle_op( uint32_t shuffle, xir_op_t it );
nkeynes@1006
   610
nkeynes@1006
   611
/**
nkeynes@1006
   612
 * Return the number of instructions that would be emitted by xir_shuffle_lower
nkeynes@1006
   613
 * for the given instruction (not including the leading nop, if there is one)
nkeynes@1006
   614
 */
nkeynes@1006
   615
int xir_shuffle_lower_size( xir_op_t it );
nkeynes@1006
   616
nkeynes@1006
   617
/**
nkeynes@1006
   618
 * Transform a shuffle instruction into an equivalent sequence of shifts, and
nkeynes@1006
   619
 * logical operations.
nkeynes@1006
   620
 * @return the last instruction in the resultant sequence (which may be the
nkeynes@1006
   621
 * original instruction pointer). 
nkeynes@1006
   622
 */
nkeynes@1006
   623
xir_op_t xir_shuffle_lower( xir_basic_block_t xbb, xir_op_t it, int tmp1, int tmp2 );
nkeynes@1006
   624
nkeynes@1006
   625
nkeynes@1006
   626
/**************************** Debugging ******************************/
nkeynes@1006
   627
nkeynes@1006
   628
/**
nkeynes@1006
   629
 * Verify the integrity of an IR block - abort with assertion failure on any
nkeynes@1006
   630
 * errors.
nkeynes@1006
   631
 */
nkeynes@1011
   632
void xir_verify_block( xir_basic_block_t xbb, xir_op_t begin, xir_op_t end );
nkeynes@1006
   633
nkeynes@1006
   634
/**
nkeynes@1006
   635
 * Set the symbol table mappings for target points - also only really for
nkeynes@1006
   636
 * debugging output.
nkeynes@1006
   637
 */
nkeynes@1006
   638
void xir_set_symbol_table( const struct xir_symbol_entry *symtab ); 
nkeynes@1006
   639
nkeynes@1006
   640
/**
nkeynes@1006
   641
 * Dump the specified block of IR to stdout
nkeynes@1006
   642
 */
nkeynes@1011
   643
void xir_dump_block( xir_basic_block_t xbb );
nkeynes@1006
   644
nkeynes@1006
   645
nkeynes@1006
   646
#endif /* !lxdream_xir_H */
.