orcprogram-c.c 21.9 KB
Newer Older
1 2 3 4 5

#include "config.h"

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

David Schleef's avatar
David Schleef committed
8
#include <orc/orc.h>
9
#include <orc/orcprogram.h>
David Schleef's avatar
David Schleef committed
10
#include <orc/orcdebug.h>
11

David Schleef's avatar
David Schleef committed
12
static const char *c_get_type_name (int size);
13
static void c_get_name (char *name, OrcCompiler *p, int var);
14
static void c_get_name_int (char *name, OrcCompiler *p, int var);
15 16 17

void orc_c_init (void);

David Schleef's avatar
David Schleef committed
18
void
19
orc_compiler_c_init (OrcCompiler *compiler)
David Schleef's avatar
David Schleef committed
20
{
David Schleef's avatar
David Schleef committed
21
  int i;
David Schleef's avatar
David Schleef committed
22

David Schleef's avatar
David Schleef committed
23
  for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+16;i++){
24
    compiler->valid_regs[i] = 1;
David Schleef's avatar
David Schleef committed
25
  }
26
  compiler->loop_shift = 0;
David Schleef's avatar
David Schleef committed
27 28
}

29
const char *
30
orc_target_c_get_typedefs (void)
31
{
32
  return
33 34 35
    "#ifndef _ORC_INTEGER_TYPEDEFS_\n"
    "#define _ORC_INTEGER_TYPEDEFS_\n"
    "#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n"
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    "#include <stdint.h>\n"
    "typedef int8_t orc_int8;\n"
    "typedef int16_t orc_int16;\n"
    "typedef int32_t orc_int32;\n"
    "typedef int64_t orc_int64;\n"
    "typedef uint8_t orc_uint8;\n"
    "typedef uint16_t orc_uint16;\n"
    "typedef uint32_t orc_uint32;\n"
    "typedef uint64_t orc_uint64;\n"
    "#elif defined(_MSC_VER)\n"
    "typedef signed __int8 orc_int8;\n"
    "typedef signed __int16 orc_int16;\n"
    "typedef signed __int32 orc_int32;\n"
    "typedef signed __int64 orc_int64;\n"
    "typedef unsigned __int8 orc_uint8;\n"
    "typedef unsigned __int16 orc_uint16;\n"
    "typedef unsigned __int32 orc_uint32;\n"
    "typedef unsigned __int64 orc_uint64;\n"
    "#else\n"
    "#include <limits.h>\n"
    "typedef signed char orc_int8;\n"
    "typedef short orc_int16;\n"
    "typedef int orc_int32;\n"
    "typedef unsigned char orc_uint8;\n"
    "typedef unsigned short orc_uint16;\n"
    "typedef unsigned int orc_uint32;\n"
    "#if INT_MAX == LONG_MAX\n"
    "typedef long long orc_int64;\n"
    "typedef unsigned long long orc_uint64;\n"
    "#else\n"
    "typedef long orc_int64;\n"
    "typedef unsigned long orc_uint64;\n"
    "#endif\n"
    "#endif\n"
    "typedef union { orc_int32 i; float f; } orc_union32;\n"
    "typedef union { orc_int64 i; double f; } orc_union64;\n"
72 73 74 75 76 77 78 79
    "#endif\n";
}

const char *
orc_target_c_get_asm_preamble (void)
{
  return "\n"
    "/* begin Orc C target preamble */\n"
David Schleef's avatar
David Schleef committed
80
    "#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x)))\n"
81
    "#define ORC_ABS(a) ((a)<0 ? -(a) : (a))\n"
David Schleef's avatar
David Schleef committed
82 83
    "#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b))\n"
    "#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b))\n"
84 85 86 87 88 89 90 91 92 93 94 95
    "#define ORC_SB_MAX 127\n"
    "#define ORC_SB_MIN (-1-ORC_SB_MAX)\n"
    "#define ORC_UB_MAX 255\n"
    "#define ORC_UB_MIN 0\n"
    "#define ORC_SW_MAX 32767\n"
    "#define ORC_SW_MIN (-1-ORC_SW_MAX)\n"
    "#define ORC_UW_MAX 65535\n"
    "#define ORC_UW_MIN 0\n"
    "#define ORC_SL_MAX 2147483647\n"
    "#define ORC_SL_MIN (-1-ORC_SL_MAX)\n"
    "#define ORC_UL_MAX 4294967295U\n"
    "#define ORC_UL_MIN 0\n"
David Schleef's avatar
David Schleef committed
96
    "#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX)\n"
97 98 99 100 101
    "#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX)\n"
    "#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX)\n"
    "#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX)\n"
    "#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX)\n"
    "#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX)\n"
David Schleef's avatar
David Schleef committed
102
    "#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8))\n"
103
    "#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))\n"
David Schleef's avatar
David Schleef committed
104
    "#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset)))\n"
105 106 107
    "/* end Orc C target preamble */\n\n";
}

David Schleef's avatar
David Schleef committed
108 109 110 111 112 113
unsigned int
orc_compiler_c_get_default_flags (void)
{
  return 0;
}

114
static const char *varnames[] = {
115 116 117 118 119 120 121 122 123 124 125
  "d1", "d2", "d3", "d4",
  "s1", "s2", "s3", "s4",
  "s5", "s6", "s7", "s8",
  "a1", "a2", "a3", "d4",
  "c1", "c2", "c3", "c4",
  "c5", "c6", "c7", "c8",
  "p1", "p2", "p3", "p4",
  "p5", "p6", "p7", "p8",
  "t1", "t2", "t3", "t4",
  "t5", "t6", "t7", "t8",
  "t9", "t10", "t11", "t12",
David Schleef's avatar
David Schleef committed
126
  "t13", "t14", "t15", "t16",
127 128
};

129 130 131 132 133 134
static void
get_varname (char *s, OrcCompiler *compiler, int var)
{
  if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
    sprintf(s, "ex->arrays[%d]", var);
  } else {
David Schleef's avatar
David Schleef committed
135 136 137 138 139
    if (var < 48) {
      strcpy (s, varnames[var]);
    } else {
      sprintf(s, "t%d", var-32);
    }
140 141 142 143 144 145 146 147 148 149 150 151 152
  }
}

static void
get_varname_stride (char *s, OrcCompiler *compiler, int var)
{
  if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
    sprintf(s, "ex->params[%d]", var);
  } else {
    sprintf(s, "%s_stride", varnames[var]);
  }
}

153
void
David Schleef's avatar
David Schleef committed
154
orc_compiler_c_assemble (OrcCompiler *compiler)
155 156 157 158
{
  int i;
  int j;
  OrcInstruction *insn;
David Schleef's avatar
David Schleef committed
159
  OrcStaticOpcode *opcode;
160
  OrcRule *rule;
David Schleef's avatar
David Schleef committed
161
  int prefix = 0;
162

163 164 165 166 167
  if (!(compiler->target_flags & ORC_TARGET_C_BARE)) {
    ORC_ASM_CODE(compiler,"void\n");
    ORC_ASM_CODE(compiler,"%s (OrcExecutor *ex)\n", compiler->program->name);
    ORC_ASM_CODE(compiler,"{\n");
  }
David Schleef's avatar
David Schleef committed
168 169

  ORC_ASM_CODE(compiler,"%*s  int i;\n", prefix, "");
David Schleef's avatar
David Schleef committed
170 171 172
  if (compiler->program->is_2d) {
    ORC_ASM_CODE(compiler,"  int j;\n");
  }
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
  if (compiler->program->constant_n == 0) {
    if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
      ORC_ASM_CODE(compiler,"  int n = ex->n;\n");
    }
  } else {
    ORC_ASM_CODE(compiler,"  int n = %d;\n", compiler->program->constant_n);
  }
  if (compiler->program->is_2d) {
    if (compiler->program->constant_m == 0) {
      if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
        ORC_ASM_CODE(compiler,"  int m = ex->params[ORC_VAR_A1];\n");
      }
    } else {
      ORC_ASM_CODE(compiler,"  int m = %d;\n", compiler->program->constant_m);
    }
  }
189

190
  for(i=0;i<ORC_N_VARIABLES;i++){
191
    OrcVariable *var = compiler->vars + i;
192
    char varname[20];
193
    if (var->name == NULL) continue;
194 195
    switch (var->vartype) {
      case ORC_VAR_TYPE_CONST:
196 197 198 199 200 201 202 203
        if (var->size >= 4) {
          if (var->value == 0x80000000) {
            ORC_ASM_CODE(compiler,"  const %s var%d = { 0x80000000 };\n",
                c_get_type_name(var->size), i);
          } else {
            ORC_ASM_CODE(compiler,"  const %s var%d = { %d };\n",
                c_get_type_name(var->size), i, var->value);
          }
204
        } else {
205 206 207 208 209 210 211
          if (var->value == 0x80000000) {
            ORC_ASM_CODE(compiler,"  const %s var%d = 0x80000000;\n",
                c_get_type_name(var->size), i);
          } else {
            ORC_ASM_CODE(compiler,"  const %s var%d = %d;\n",
                c_get_type_name(var->size), i, var->value);
          }
212
        }
213 214
        break;
      case ORC_VAR_TYPE_TEMP:
215
        ORC_ASM_CODE(compiler,"  %s var%d;\n", c_get_type_name(var->size), i);
216 217
        break;
      case ORC_VAR_TYPE_SRC:
218 219
        ORC_ASM_CODE(compiler,"  %s var%d;\n", c_get_type_name(var->size), i);
        ORC_ASM_CODE(compiler,"  const %s *%s ptr%d;\n",
220 221
            c_get_type_name (var->size),
            (compiler->target_flags & ORC_TARGET_C_C99) ? "restrict " : "",
David Schleef's avatar
David Schleef committed
222
            i);
223
        break;
224
      case ORC_VAR_TYPE_DEST:
225 226
        ORC_ASM_CODE(compiler,"  %s var%d;\n", c_get_type_name(var->size), i);
        ORC_ASM_CODE(compiler,"  %s *%s ptr%d;\n",
David Schleef's avatar
David Schleef committed
227 228
            c_get_type_name (var->size),
            (compiler->target_flags & ORC_TARGET_C_C99) ? "restrict " : "",
David Schleef's avatar
David Schleef committed
229
            i);
230
        break;
231
      case ORC_VAR_TYPE_ACCUMULATOR:
232 233 234 235 236 237 238 239 240
        if (var->size >= 4) {
          ORC_ASM_CODE(compiler,"  %s var%d =  { 0 };\n",
              c_get_type_name (var->size),
              i);
        } else {
          ORC_ASM_CODE(compiler,"  %s var%d = 0;\n",
              c_get_type_name (var->size),
              i);
        }
241
        break;
242
      case ORC_VAR_TYPE_PARAM:
243
        c_get_name (varname, compiler, i);
244
        if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
David Schleef's avatar
David Schleef committed
245 246 247 248
          if (var->is_float_param) {
            ORC_ASM_CODE(compiler,"  const float %s = ((orc_union32 *)(ex->params+%d))->f;\n",
                varname, i);
          } else {
249
            ORC_ASM_CODE(compiler,"  const int %s = ex->params[%d];\n",
David Schleef's avatar
David Schleef committed
250 251
                varname, i);
          }
252
        } else {
David Schleef's avatar
David Schleef committed
253 254
          ORC_ASM_CODE(compiler,"  const %s %s = %s;\n",
              var->is_float_param ? "float" : "int",
255
              varname, varnames[i]);
256
        }
257 258
        break;
      default:
David Schleef's avatar
David Schleef committed
259
        ORC_COMPILER_ERROR(compiler, "bad vartype");
260 261 262 263
        break;
    }
  }

264
  ORC_ASM_CODE(compiler,"\n");
David Schleef's avatar
David Schleef committed
265
  if (compiler->program->is_2d) {
266
    ORC_ASM_CODE(compiler,"  for (j = 0; j < m; j++) {\n");
David Schleef's avatar
David Schleef committed
267 268 269 270 271 272 273
    prefix = 2;

    for(i=0;i<ORC_N_VARIABLES;i++){
      OrcVariable *var = compiler->vars + i;
      if (var->name == NULL) continue;
      switch (var->vartype) {
        case ORC_VAR_TYPE_SRC:
274 275 276 277
          {
            char s1[20], s2[20];
            get_varname(s1, compiler, i);
            get_varname_stride(s2, compiler, i);
278 279 280
            ORC_ASM_CODE(compiler,
                "    ptr%d = ORC_PTR_OFFSET(%s, %s * j);\n",
                i, s1, s2);
281
          }
David Schleef's avatar
David Schleef committed
282 283
          break;
        case ORC_VAR_TYPE_DEST:
284 285 286 287 288
          {
            char s1[20], s2[20];
            get_varname(s1, compiler, i),
            get_varname_stride(s2, compiler, i),
            ORC_ASM_CODE(compiler,
289
                "    ptr%d = ORC_PTR_OFFSET(%s, %s * j);\n",
290
                i, s1, s2);
291
          }
David Schleef's avatar
David Schleef committed
292 293 294 295 296 297 298 299
          break;
        default:
          break;
      }
    }
  } else {
    for(i=0;i<ORC_N_VARIABLES;i++){
      OrcVariable *var = compiler->vars + i;
300
      char s[20];
David Schleef's avatar
David Schleef committed
301
      if (var->name == NULL) continue;
302
      get_varname(s, compiler, i);
David Schleef's avatar
David Schleef committed
303 304
      switch (var->vartype) {
        case ORC_VAR_TYPE_SRC:
305 306
          ORC_ASM_CODE(compiler,"  ptr%d = (%s *)%s;\n", i,
              c_get_type_name (var->size), s);
David Schleef's avatar
David Schleef committed
307 308
          break;
        case ORC_VAR_TYPE_DEST:
309 310
          ORC_ASM_CODE(compiler,"  ptr%d = (%s *)%s;\n", i,
              c_get_type_name (var->size), s);
David Schleef's avatar
David Schleef committed
311 312 313 314 315
          break;
        default:
          break;
      }
    }
David Schleef's avatar
David Schleef committed
316
  }
David Schleef's avatar
David Schleef committed
317 318

  ORC_ASM_CODE(compiler,"\n");
319
  ORC_ASM_CODE(compiler,"%*s  for (i = 0; i < n; i++) {\n", prefix, "");
320

321 322 323 324 325 326 327 328 329 330
  /* Load from source (and maybe destination) arrays */
  for(i=0;i<ORC_N_VARIABLES;i++){
    OrcVariable *var = compiler->vars + i;
    char s[20];
    if (var->name == NULL) continue;
    c_get_name(s, compiler, i);
    if (var->vartype == ORC_VAR_TYPE_SRC) {
      ORC_ASM_CODE (compiler, "%*s    %s = *ptr%d;\n", prefix, "", s, i);
      ORC_ASM_CODE (compiler, "%*s    ptr%d++;\n", prefix, "", i);
    }
331
    if (var->vartype == ORC_VAR_TYPE_DEST && var->load_dest) {
332 333 334 335
      ORC_ASM_CODE (compiler, "%*s    %s = *ptr%d;\n", prefix, "", s, i);
    }
  }
  /* Emit instructions */
336 337
  for(j=0;j<compiler->n_insns;j++){
    insn = compiler->insns + j;
338 339
    opcode = insn->opcode;

David Schleef's avatar
David Schleef committed
340 341
    ORC_ASM_CODE(compiler,"%*s    /* %d: %s */\n", prefix, "",
        j, insn->opcode->name);
342 343 344

    rule = insn->rule;
    if (rule) {
David Schleef's avatar
David Schleef committed
345
      ORC_ASM_CODE(compiler,"%*s", prefix, "");
346
      rule->emit (compiler, rule->emit_user, insn);
347
    } else {
348
      ORC_COMPILER_ERROR(compiler, "No rule for: %s on target %s", opcode->name,
349
          compiler->target->name);
350
      compiler->error = TRUE;
351 352
    }
  }
353 354 355 356 357 358 359 360 361 362 363
  /* Store to destination arrays */
  for(i=0;i<ORC_N_VARIABLES;i++){
    OrcVariable *var = compiler->vars + i;
    char s[20];
    if (var->name == NULL) continue;
    c_get_name(s, compiler, i);
    if (var->vartype == ORC_VAR_TYPE_DEST) {
      ORC_ASM_CODE (compiler, "%*s    *ptr%d = %s;\n", prefix, "", i, s);
      ORC_ASM_CODE (compiler, "%*s    ptr%d++;\n", prefix, "", i);
    }
  }
David Schleef's avatar
David Schleef committed
364
  ORC_ASM_CODE(compiler,"%*s  }\n", prefix, "");
David Schleef's avatar
David Schleef committed
365 366 367
  if (compiler->program->is_2d) {
    ORC_ASM_CODE(compiler,"  }\n");
  }
368

369
  for(i=0;i<ORC_N_VARIABLES;i++){
370
    char varname[20];
371
    OrcVariable *var = compiler->vars + i;
372
    c_get_name_int (varname, compiler, i);
373 374 375
    if (var->name == NULL) continue;
    switch (var->vartype) {
      case ORC_VAR_TYPE_ACCUMULATOR:
David Schleef's avatar
David Schleef committed
376
        if (var->size == 2) {
377
          if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
378 379
            ORC_ASM_CODE(compiler,"  ex->accumulators[%d] = (%s & 0xffff);\n",
                i - ORC_VAR_A1, varname);
380
          } else {
381 382
            ORC_ASM_CODE(compiler,"  *%s = (%s & 0xffff);\n",
                varnames[i], varname);
383
          }
David Schleef's avatar
David Schleef committed
384
        } else {
385
          if (!(compiler->target_flags & ORC_TARGET_C_NOEXEC)) {
386 387
            ORC_ASM_CODE(compiler,"  ex->accumulators[%d] = %s;\n",
                i - ORC_VAR_A1, varname);
388
          } else {
389 390
            ORC_ASM_CODE(compiler,"  *%s = %s;\n",
                varnames[i], varname);
391
          }
David Schleef's avatar
David Schleef committed
392
        }
393 394 395 396 397 398 399 400 401 402
        break;
      default:
        break;
    }
  }

  if (!(compiler->target_flags & ORC_TARGET_C_BARE)) {
    ORC_ASM_CODE(compiler,"}\n");
    ORC_ASM_CODE(compiler,"\n");
  }
403 404 405 406 407 408
}


/* rules */

static void
409
c_get_name (char *name, OrcCompiler *p, int var)
410 411 412 413 414
{
  switch (p->vars[var].vartype) {
    case ORC_VAR_TYPE_CONST:
    case ORC_VAR_TYPE_PARAM:
    case ORC_VAR_TYPE_TEMP:
415
    case ORC_VAR_TYPE_ACCUMULATOR:
416 417
    case ORC_VAR_TYPE_SRC:
    case ORC_VAR_TYPE_DEST:
418
      sprintf(name, "var%d", var);
419 420
      break;
    default:
David Schleef's avatar
David Schleef committed
421
      ORC_COMPILER_ERROR(p, "bad vartype");
422 423 424
      sprintf(name, "ERROR");
      break;
  }
David Schleef's avatar
David Schleef committed
425
}
426

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static void
c_get_name_int (char *name, OrcCompiler *p, int var)
{
  switch (p->vars[var].vartype) {
    case ORC_VAR_TYPE_CONST:
    case ORC_VAR_TYPE_TEMP:
    case ORC_VAR_TYPE_ACCUMULATOR:
    case ORC_VAR_TYPE_SRC:
    case ORC_VAR_TYPE_DEST:
      if (p->vars[var].size >= 4) {
        sprintf(name, "var%d.i", var);
      } else {
        sprintf(name, "var%d", var);
      }
      break;
442 443 444
    case ORC_VAR_TYPE_PARAM:
      sprintf(name, "var%d", var);
      break;
445 446 447 448 449 450 451
    default:
      ORC_COMPILER_ERROR(p, "bad vartype");
      sprintf(name, "ERROR");
      break;
  }
}

452 453 454 455 456 457 458 459 460
static void
c_get_name_float (char *name, OrcCompiler *p, int var)
{
  switch (p->vars[var].vartype) {
    case ORC_VAR_TYPE_CONST:
    case ORC_VAR_TYPE_TEMP:
    case ORC_VAR_TYPE_ACCUMULATOR:
    case ORC_VAR_TYPE_SRC:
    case ORC_VAR_TYPE_DEST:
461
      sprintf(name, "var%d.f", var);
462
      break;
463 464 465
    case ORC_VAR_TYPE_PARAM:
      sprintf(name, "var%d", var);
      break;
466 467 468 469 470 471 472
    default:
      ORC_COMPILER_ERROR(p, "bad vartype");
      sprintf(name, "ERROR");
      break;
  }
}

David Schleef's avatar
David Schleef committed
473 474 475 476 477
static const char *
c_get_type_name (int size)
{
  switch (size) {
    case 1:
478
      return "orc_int8";
David Schleef's avatar
David Schleef committed
479
    case 2:
480
      return "orc_int16";
David Schleef's avatar
David Schleef committed
481
    case 4:
482
      return "orc_union32";
David Schleef's avatar
David Schleef committed
483
    case 8:
484
      return "orc_union64";
David Schleef's avatar
David Schleef committed
485 486 487
    default:
      return "ERROR";
  }
488 489
}

David Schleef's avatar
David Schleef committed
490

491 492 493 494 495 496
#define UNARY(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[20], src1[20]; \
\
497 498
  c_get_name_int (dest, p, insn->dest_args[0]); \
  c_get_name_int (src1, p, insn->src_args[0]); \
499 500 501 502
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1); \
}

503 504
#define BINARY(name,op) \
static void \
505
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
506 507 508
{ \
  char dest[20], src1[20], src2[20]; \
\
509 510 511
  c_get_name_int (dest, p, insn->dest_args[0]); \
  c_get_name_int (src1, p, insn->src_args[0]); \
  c_get_name_int (src2, p, insn->src_args[1]); \
512 513 514
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1, src2); \
}
David Schleef's avatar
David Schleef committed
515

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
#define UNARYF(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[40], src1[40]; \
\
  c_get_name_float (dest, p, insn->dest_args[0]); \
  c_get_name_float (src1, p, insn->src_args[0]); \
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1); \
}

#define BINARYF(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[40], src1[40], src2[40]; \
\
  c_get_name_float (dest, p, insn->dest_args[0]); \
  c_get_name_float (src1, p, insn->src_args[0]); \
  c_get_name_float (src2, p, insn->src_args[1]); \
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1, src2); \
}

#define BINARYFL(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[40], src1[40], src2[40]; \
\
547
  c_get_name_int (dest, p, insn->dest_args[0]); \
548 549 550 551 552 553 554 555 556 557 558 559
  c_get_name_float (src1, p, insn->src_args[0]); \
  c_get_name_float (src2, p, insn->src_args[1]); \
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1, src2); \
}

#define UNARYFL(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[40], src1[40]; \
\
560
  c_get_name_int (dest, p, insn->dest_args[0]); \
561 562 563 564 565 566 567 568 569 570 571 572
  c_get_name_float (src1, p, insn->src_args[0]); \
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1); \
}

#define UNARYLF(name,op) \
static void \
c_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
{ \
  char dest[40], src1[40]; \
\
  c_get_name_float (dest, p, insn->dest_args[0]); \
573
  c_get_name_int (src1, p, insn->src_args[0]); \
574 575 576 577
 \
  ORC_ASM_CODE(p,"    %s = " op ";\n", dest, src1); \
}

578 579 580 581 582 583
#define BINARY_SB(a,b) BINARY(a,b)
#define BINARY_UB(a,b) BINARY(a,b)
#define BINARY_SW(a,b) BINARY(a,b)
#define BINARY_UW(a,b) BINARY(a,b)
#define BINARY_SL(a,b) BINARY(a,b)
#define BINARY_UL(a,b) BINARY(a,b)
584 585 586 587 588 589
#define UNARY_SB(a,b) UNARY(a,b)
#define UNARY_UB(a,b) UNARY(a,b)
#define UNARY_SW(a,b) UNARY(a,b)
#define UNARY_UW(a,b) UNARY(a,b)
#define UNARY_SL(a,b) UNARY(a,b)
#define UNARY_UL(a,b) UNARY(a,b)
590 591 592 593
#define BINARY_BW(a,b) BINARY(a,b)
#define BINARY_WL(a,b) BINARY(a,b)
#define BINARY_LW(a,b) BINARY(a,b)
#define BINARY_WB(a,b) BINARY(a,b)
594 595 596 597
#define UNARY_BW(a,b) UNARY(a,b)
#define UNARY_WL(a,b) UNARY(a,b)
#define UNARY_LW(a,b) UNARY(a,b)
#define UNARY_WB(a,b) UNARY(a,b)
598

599 600 601 602 603 604
#define BINARY_F(a,b) BINARYF(a,b)
#define BINARY_FL(a,b) BINARYFL(a,b)
#define UNARY_F(a,b) UNARYF(a,b)
#define UNARY_FL(a,b) UNARYFL(a,b)
#define UNARY_LF(a,b) UNARYLF(a,b)

605 606 607 608 609 610 611 612
#include "opcodes.h"

#undef BINARY_SB
#undef BINARY_UB
#undef BINARY_SW
#undef BINARY_UW
#undef BINARY_SL
#undef BINARY_UL
613
#undef BINARY_F
614 615 616 617 618 619
#undef UNARY_SB
#undef UNARY_UB
#undef UNARY_SW
#undef UNARY_UW
#undef UNARY_SL
#undef UNARY_UL
620
#undef UNARY_F
621 622 623 624
#undef BINARY_BW
#undef BINARY_WL
#undef BINARY_LW
#undef BINARY_WB
625 626 627 628
#undef UNARY_BW
#undef UNARY_WL
#undef UNARY_LW
#undef UNARY_WB
629 630 631
#undef UNARY_FL
#undef UNARY_LF
#undef BINARY_FL
632

David Schleef's avatar
David Schleef committed
633 634 635 636 637
static void
c_rule_accw (OrcCompiler *p, void *user, OrcInstruction *insn)
{
  char dest[20], src1[20];

638 639
  c_get_name_int (dest, p, insn->dest_args[0]);
  c_get_name_int (src1, p, insn->src_args[0]);
David Schleef's avatar
David Schleef committed
640 641 642 643 644 645 646 647 648

  ORC_ASM_CODE(p,"    %s = %s + %s;\n", dest, dest, src1);
}

static void
c_rule_accl (OrcCompiler *p, void *user, OrcInstruction *insn)
{
  char dest[20], src1[20];

649 650
  c_get_name_int (dest, p, insn->dest_args[0]);
  c_get_name_int (src1, p, insn->src_args[0]);
David Schleef's avatar
David Schleef committed
651 652 653 654 655 656 657 658 659

  ORC_ASM_CODE(p,"    %s = %s + %s;\n", dest, dest, src1);
}

static void
c_rule_accsadubl (OrcCompiler *p, void *user, OrcInstruction *insn)
{
  char dest[20], src1[20], src2[20];

660 661 662
  c_get_name_int (dest, p, insn->dest_args[0]);
  c_get_name_int (src1, p, insn->src_args[0]);
  c_get_name_int (src2, p, insn->src_args[1]);
David Schleef's avatar
David Schleef committed
663

664
  ORC_ASM_CODE(p,
665
      "    %s = %s + ORC_ABS((orc_int32)(orc_uint8)%s - (orc_int32)(orc_uint8)%s);\n",
666
      dest, dest, src1, src2);
David Schleef's avatar
David Schleef committed
667 668
}

669 670 671 672 673
static void
c_rule_splitlw (OrcCompiler *p, void *user, OrcInstruction *insn)
{
  char dest1[20], dest2[20], src[20];

674 675 676
  c_get_name_int (dest1, p, insn->dest_args[0]);
  c_get_name_int (dest2, p, insn->dest_args[1]);
  c_get_name_int (src, p, insn->src_args[0]);
677 678 679 680 681 682 683 684 685 686

  ORC_ASM_CODE(p,"    %s = (%s >> 16) & 0xffff;\n", dest1, src);
  ORC_ASM_CODE(p,"    %s = %s & 0xffff;\n", dest2, src);
}

static void
c_rule_splitwb (OrcCompiler *p, void *user, OrcInstruction *insn)
{
  char dest1[20], dest2[20], src[20];

687 688 689
  c_get_name_int (dest1, p, insn->dest_args[0]);
  c_get_name_int (dest2, p, insn->dest_args[1]);
  c_get_name_int (src, p, insn->src_args[0]);
690 691 692 693 694

  ORC_ASM_CODE(p,"    %s = (%s >> 8) & 0xff;\n", dest1, src);
  ORC_ASM_CODE(p,"    %s = %s & 0xff;\n", dest2, src);
}

David Schleef's avatar
David Schleef committed
695 696
static OrcTarget c_target = {
  "c",
David Schleef's avatar
David Schleef committed
697
  FALSE,
David Schleef's avatar
David Schleef committed
698
  ORC_GP_REG_BASE,
David Schleef's avatar
David Schleef committed
699
  orc_compiler_c_get_default_flags,
David Schleef's avatar
David Schleef committed
700
  orc_compiler_c_init,
David Schleef's avatar
David Schleef committed
701 702 703 704
  orc_compiler_c_assemble,
  { { 0 } },
  0,
  orc_target_c_get_asm_preamble,
David Schleef's avatar
David Schleef committed
705 706
};

707

708 709 710
void
orc_c_init (void)
{
David Schleef's avatar
David Schleef committed
711 712 713 714
  OrcRuleSet *rule_set;

  orc_target_register (&c_target);

David Schleef's avatar
David Schleef committed
715
  rule_set = orc_rule_set_new (orc_opcode_set_get("sys"), &c_target, 0);
David Schleef's avatar
David Schleef committed
716 717 718 719 720 721 722

#define BINARY_SB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_UB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_SW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_UW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_SL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_UL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
723
#define BINARY_F(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
David Schleef's avatar
David Schleef committed
724 725 726 727 728 729
#define UNARY_SB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_UB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_SW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_UW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_SL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_UL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
730
#define UNARY_F(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
David Schleef's avatar
David Schleef committed
731 732 733 734
#define BINARY_BW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_WL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_LW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_WB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
735 736 737 738
#define UNARY_BW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_WL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_LW(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_WB(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
739

740 741 742 743
#define UNARY_FL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define BINARY_FL(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);
#define UNARY_LF(a,b) orc_rule_register (rule_set, #a , c_rule_ ## a, NULL);

744 745
#include "opcodes.h"

David Schleef's avatar
David Schleef committed
746 747 748
  orc_rule_register (rule_set, "accw", c_rule_accw, NULL);
  orc_rule_register (rule_set, "accl", c_rule_accl, NULL);
  orc_rule_register (rule_set, "accsadubl", c_rule_accsadubl, NULL);
749 750
  orc_rule_register (rule_set, "splitlw", c_rule_splitlw, NULL);
  orc_rule_register (rule_set, "splitwb", c_rule_splitwb, NULL);
751 752
}