orcprogram-mmx.c 8.92 KB
Newer Older
1 2 3 4 5 6 7 8 9 10

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <unistd.h>
#include <sys/types.h>

11 12
#include <orc/orc.h>
#include <orc/orcdebug.h>
13 14 15 16
#include <orc/x86.h>

#define SIZE 65536

17
void mmx_emit_loop (OrcCompiler *compiler);
18

David Schleef's avatar
David Schleef committed
19 20
void orc_compiler_mmx_init (OrcCompiler *compiler);
void orc_compiler_mmx_assemble (OrcCompiler *compiler);
21

David Schleef's avatar
David Schleef committed
22
void orc_compiler_mmx_register_rules (OrcTarget *target);
23 24 25



26 27
void orc_compiler_rewrite_vars (OrcCompiler *compiler);
void orc_compiler_dump (OrcCompiler *compiler);
28

David Schleef's avatar
David Schleef committed
29 30 31 32 33 34 35 36 37 38 39 40
static OrcTarget mmx_target = {
  "mmx",
#if defined(HAVE_I386) || defined(HAVE_AMD64)
  TRUE,
#else
  FALSE,
#endif
  ORC_VEC_REG_BASE,
  orc_compiler_mmx_init,
  orc_compiler_mmx_assemble
};

41
void
42
orc_mmx_init (void)
43
{
David Schleef's avatar
David Schleef committed
44 45 46
  orc_target_register (&mmx_target);

  orc_compiler_mmx_register_rules (&mmx_target);
47 48 49
}

void
50
orc_compiler_mmx_init (OrcCompiler *compiler)
51 52 53
{
  int i;

54
  if (compiler->is_64bit) {
55
    for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+16;i++){
56
      compiler->valid_regs[i] = 1;
57
    }
58 59 60
    compiler->valid_regs[X86_ECX] = 0;
    compiler->valid_regs[X86_EDI] = 0;
    compiler->valid_regs[X86_ESP] = 0;
61
    for(i=X86_XMM0;i<X86_XMM0+16;i++){
62
      compiler->valid_regs[i] = 1;
63
    }
64 65 66 67 68 69
    compiler->save_regs[X86_EBX] = 1;
    compiler->save_regs[X86_EBP] = 1;
    compiler->save_regs[X86_R12] = 1;
    compiler->save_regs[X86_R13] = 1;
    compiler->save_regs[X86_R14] = 1;
    compiler->save_regs[X86_R15] = 1;
70 71
  } else {
    for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+8;i++){
72
      compiler->valid_regs[i] = 1;
73
    }
74 75 76
    compiler->valid_regs[X86_ECX] = 0;
    compiler->valid_regs[X86_ESP] = 0;
    compiler->valid_regs[X86_EBP] = 0;
77
    for(i=X86_XMM0;i<X86_XMM0+8;i++){
78
      compiler->valid_regs[i] = 1;
79
    }
80 81 82
    compiler->save_regs[X86_EBX] = 1;
    compiler->save_regs[X86_EDI] = 1;
    compiler->save_regs[X86_EBP] = 1;
83 84
  }
  for(i=X86_MM0;i<X86_MM0+8;i++){
85
    compiler->valid_regs[i] = 1;
86 87
  }
  for(i=0;i<128;i++){
88 89
    compiler->alloc_regs[i] = 0;
    compiler->used_regs[i] = 0;
90 91
  }

92
  compiler->loop_shift = 2;
93 94 95
}

void
96
mmx_load_constants (OrcCompiler *compiler)
97 98
{
  int i;
99 100
  for(i=0;i<ORC_N_VARIABLES;i++){
    if (compiler->vars[i].name == NULL) continue;
101
    switch (compiler->vars[i].vartype) {
102
      case ORC_VAR_TYPE_CONST:
103
        orc_mmx_emit_loadiw (compiler, compiler->vars[i].alloc,
104
            (int)compiler->vars[i].value);
105 106 107
        break;
      case ORC_VAR_TYPE_SRC:
      case ORC_VAR_TYPE_DEST:
108
        if (compiler->vars[i].ptr_register) {
109 110
          orc_x86_emit_mov_memoffset_reg (compiler, compiler->is_64bit ? 8 : 4,
              (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]), compiler->exec_reg,
111
              compiler->vars[i].ptr_register);
112
        } else {
David Schleef's avatar
hacking  
David Schleef committed
113
          ORC_COMPILER_ERROR(compiler, "unimplemented");
114 115 116 117 118 119 120 121 122
        }
        break;
      default:
        break;
    }
  }
}

void
123
orc_mmx_emit_load_src (OrcCompiler *compiler, OrcVariable *var)
124 125 126
{
  int ptr_reg;
  if (var->ptr_register == 0) {
127 128
    orc_x86_emit_mov_memoffset_reg (compiler, compiler->is_64bit ? 8 : 4,
        var->ptr_offset, compiler->exec_reg, X86_ECX);
129 130 131 132
    ptr_reg = X86_ECX;
  } else {
    ptr_reg = var->ptr_register;
  }
133
  switch (compiler->loop_shift) {
David Schleef's avatar
David Schleef committed
134
    case 0:
135 136
      orc_x86_emit_mov_memoffset_reg (compiler, 2, 0, ptr_reg, X86_ECX);
      orc_x86_emit_mov_reg_mmx (compiler, X86_ECX, var->alloc);
137
      break;
David Schleef's avatar
David Schleef committed
138
    case 1:
139
      orc_x86_emit_mov_memoffset_mmx (compiler, 4, 0, ptr_reg, var->alloc);
140
      break;
David Schleef's avatar
David Schleef committed
141
    case 2:
142
      orc_x86_emit_mov_memoffset_mmx (compiler, 8, 0, ptr_reg, var->alloc);
143 144
      break;
    default:
David Schleef's avatar
hacking  
David Schleef committed
145
      ORC_COMPILER_ERROR(compiler, "bad size");
146 147 148 149
  }
}

void
150
mmx_emit_store_dest (OrcCompiler *compiler, OrcVariable *var)
151 152 153
{
  int ptr_reg;
  if (var->ptr_register == 0) {
154 155
    orc_x86_emit_mov_memoffset_reg (compiler, compiler->is_64bit ? 8 : 4,
        var->ptr_offset, compiler->exec_reg, X86_ECX);
156 157 158 159
    ptr_reg = X86_ECX;
  } else {
    ptr_reg = var->ptr_register;
  }
160
  switch (compiler->loop_shift) {
David Schleef's avatar
David Schleef committed
161
    case 0:
162 163
      /* FIXME we might be using ecx twice here */
      if (ptr_reg == X86_ECX) {
David Schleef's avatar
hacking  
David Schleef committed
164
        ORC_COMPILER_ERROR(compiler, "unimplemented");
165
      }
166 167
      orc_x86_emit_mov_mmx_reg (compiler, var->alloc, X86_ECX);
      orc_x86_emit_mov_reg_memoffset (compiler, 2, X86_ECX, 0, ptr_reg);
168
      break;
David Schleef's avatar
David Schleef committed
169
    case 1:
170
      orc_x86_emit_mov_mmx_memoffset (compiler, 4, var->alloc, 0, ptr_reg);
171
      break;
David Schleef's avatar
David Schleef committed
172
    case 2:
173
      orc_x86_emit_mov_mmx_memoffset (compiler, 8, var->alloc, 0, ptr_reg);
174 175
      break;
    default:
David Schleef's avatar
hacking  
David Schleef committed
176
      ORC_COMPILER_ERROR(compiler, "unimplemented");
177 178 179 180
  }
}

void
181
orc_compiler_mmx_assemble (OrcCompiler *compiler)
182
{
183
  orc_x86_emit_prologue (compiler);
184

185 186 187 188 189
  orc_x86_emit_mov_memoffset_reg (compiler, 4, (int)ORC_STRUCT_OFFSET(OrcExecutor,n),
      compiler->exec_reg, X86_ECX);
  orc_x86_emit_sar_imm_reg (compiler, 4, compiler->loop_shift, X86_ECX);
  orc_x86_emit_mov_reg_memoffset (compiler, 4, X86_ECX,
      (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2), compiler->exec_reg);
190

191 192 193 194 195
  orc_x86_emit_mov_memoffset_reg (compiler, 4,
      (int)ORC_STRUCT_OFFSET(OrcExecutor,n), compiler->exec_reg, X86_ECX);
  orc_x86_emit_and_imm_reg (compiler, 4, (1<<compiler->loop_shift)-1, X86_ECX);
  orc_x86_emit_mov_reg_memoffset (compiler, 4, X86_ECX,
      (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1), compiler->exec_reg);
196

197
  mmx_load_constants (compiler);
198

199
  if (compiler->loop_shift > 0) {
David Schleef's avatar
David Schleef committed
200
    int save_loop_shift;
201

202 203 204
    orc_x86_emit_cmp_imm_memoffset (compiler, 4, 0,
        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1), compiler->exec_reg);
    orc_x86_emit_je (compiler, 1);
David Schleef's avatar
David Schleef committed
205

206 207
    save_loop_shift = compiler->loop_shift;
    compiler->loop_shift = 0;
David Schleef's avatar
David Schleef committed
208

209
    orc_x86_emit_label (compiler, 0);
210
    mmx_emit_loop (compiler);
211
    orc_x86_emit_dec_memoffset (compiler, 4,
David Schleef's avatar
David Schleef committed
212
        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1),
213 214
        compiler->exec_reg);
    orc_x86_emit_jne (compiler, 0);
David Schleef's avatar
David Schleef committed
215

216
    compiler->loop_shift = save_loop_shift;
David Schleef's avatar
David Schleef committed
217
  }
David Schleef's avatar
David Schleef committed
218

219
  orc_x86_emit_label (compiler, 1);
220

221 222 223
  orc_x86_emit_cmp_imm_memoffset (compiler, 4, 0,
      (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2), compiler->exec_reg);
  orc_x86_emit_je (compiler, 3);
224

225
  orc_x86_emit_label (compiler, 2);
226
  mmx_emit_loop (compiler);
227
  orc_x86_emit_dec_memoffset (compiler, 4,
228
      (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2),
229 230 231
      compiler->exec_reg);
  orc_x86_emit_jne (compiler, 2);
  orc_x86_emit_label (compiler, 3);
232

233 234
  orc_x86_emit_emms (compiler);
  orc_x86_emit_epilogue (compiler);
235

236
  x86_do_fixups (compiler);
237 238 239
}

void
240
mmx_emit_loop (OrcCompiler *compiler)
241 242 243 244
{
  int j;
  int k;
  OrcInstruction *insn;
David Schleef's avatar
David Schleef committed
245 246
  OrcStaticOpcode *opcode;
  //OrcVariable *args[10];
247 248
  OrcRule *rule;

249 250
  for(j=0;j<compiler->n_insns;j++){
    insn = compiler->insns + j;
251 252
    opcode = insn->opcode;

David Schleef's avatar
David Schleef committed
253
    orc_compiler_append_code(compiler,"# %d: %s\n", j, insn->opcode->name);
254

David Schleef's avatar
David Schleef committed
255
#if 0
256 257
    /* set up args */
    for(k=0;k<opcode->n_src + opcode->n_dest;k++){
258 259
      args[k] = compiler->vars + insn->args[k];
      orc_compiler_append_code(compiler," %d", args[k]->alloc);
260
      if (args[k]->is_chained) {
261
        orc_compiler_append_code(compiler," (chained)");
262 263
      }
    }
264
    orc_compiler_append_code(compiler,"\n");
David Schleef's avatar
David Schleef committed
265 266 267 268
#endif

    for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){
      OrcVariable *var = compiler->vars + insn->src_args[k];
269

David Schleef's avatar
David Schleef committed
270 271 272
      if (opcode->src_size[k] == 0) continue;

      switch (var->vartype) {
273
        case ORC_VAR_TYPE_SRC:
274
          orc_mmx_emit_load_src (compiler, var);
275 276 277 278 279 280 281 282 283 284 285 286
          break;
        case ORC_VAR_TYPE_CONST:
          break;
        case ORC_VAR_TYPE_TEMP:
          break;
        default:
          break;
      }
    }

    rule = insn->rule;
    if (rule) {
David Schleef's avatar
David Schleef committed
287 288
      if (compiler->vars[insn->dest_args[0]].alloc !=
          compiler->vars[insn->src_args[0]].alloc) {
289
        orc_x86_emit_mov_mmx_reg_reg (compiler,
David Schleef's avatar
David Schleef committed
290 291
            compiler->vars[insn->src_args[0]].alloc,
            compiler->vars[insn->dest_args[0]].alloc);
292
      }
293
      rule->emit (compiler, rule->emit_user, insn);
294
    } else {
295
      orc_compiler_append_code(compiler,"No rule for: %s\n", opcode->name);
296 297
    }

David Schleef's avatar
David Schleef committed
298 299 300 301 302 303
    for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){
      OrcVariable *var = compiler->vars + insn->dest_args[k];

      if (opcode->dest_size[k] == 0) continue;

      switch (var->vartype) {
304
        case ORC_VAR_TYPE_DEST:
David Schleef's avatar
David Schleef committed
305
          mmx_emit_store_dest (compiler, var);
306 307 308 309 310 311 312 313 314
          break;
        case ORC_VAR_TYPE_TEMP:
          break;
        default:
          break;
      }
    }
  }

315 316
  for(k=0;k<ORC_N_VARIABLES;k++){
    if (compiler->vars[k].name == NULL) continue;
317 318 319
    if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
        compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
      if (compiler->vars[k].ptr_register) {
320
        orc_x86_emit_add_imm_reg (compiler, compiler->is_64bit ? 8 : 4,
321 322
            compiler->vars[k].size << compiler->loop_shift,
            compiler->vars[k].ptr_register);
323
      } else {
324
        orc_x86_emit_add_imm_memoffset (compiler, compiler->is_64bit ? 8 : 4,
325
            compiler->vars[k].size << compiler->loop_shift,
326
            (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]),
327
            compiler->exec_reg);
328 329 330 331 332
      }
    }
  }
}