runtime.c 16 KB
Newer Older
1
/* vim:set ts=2:set sw=2:set expandtab: */
Axel Simon's avatar
Axel Simon committed
2 3 4
@I-am-a-template-so-edit-me@

@include-prefix@
5
#include <string.h>
Axel Simon's avatar
Axel Simon committed
6
#include <stdio.h>
7
#include <limits.h>
8 9 10
#ifdef _MSC_VER
  #include <crtdefs.h>
#endif
11

Axel Simon's avatar
Axel Simon committed
12 13 14 15
/* generated declarations for records with fixed fields */
@records@


16
struct state {
Julian Kranz's avatar
Julian Kranz committed
17
  void* userdata;      /* a pointer to arbitrary data */
18 19 20
  char* heap_base;    /* the beginning of the heap */
  char* heap_limit;   /* first byte beyond the heap buffer */
  char* heap;         /* current top of the heap */
Axel Simon's avatar
Axel Simon committed
21 22
@state_type@
;      /* the current monadic state */
23
  unsigned char* ip_start;     /* beginning of code buffer */
24
  size_t ip_base;     /* base address of code */
25 26
  unsigned char* ip_limit;     /* first byte beyond the code buffer */
  unsigned char* ip;           /* current pointer into the buffer */
Axel Simon's avatar
Axel Simon committed
27
  int_t token_addr_inv;
28 29
  char* err_str;      /* a string describing the fatal error that occurred */
  jmp_buf err_tgt;    /* the position of the exception handler */
Axel Simon's avatar
Axel Simon committed
30
  FILE* handle;       /* the file that the puts primitve uses */
31 32 33 34
  char* const_heap_base;
  /* the following fields contain the values of constant GDSL expressions */
  @gdsl_constants@

35 36
};

Axel Simon's avatar
Axel Simon committed
37 38 39 40 41
typedef unsigned int field_tag_t;

@field_delete_arrays@


42 43
#define CHUNK_SIZE (4*1024)

Axel Simon's avatar
Axel Simon committed
44
#if defined(__CLANG__)
45
#define INLINE_ATTR inline
Axel Simon's avatar
Axel Simon committed
46
#elif defined(__GNUC__)
47
#define INLINE_ATTR inline
Axel Simon's avatar
Axel Simon committed
48
#elif defined(_MSC_VER)
49 50 51 52 53
#define INLINE_ATTR __inline
#else
#define INLINE_ATTR inline
#endif

Axel Simon's avatar
Axel Simon committed
54
#if defined(__CLANG__)
Axel Simon's avatar
Axel Simon committed
55
#define NO_INLINE_ATTR __attribute__((noinline))
Axel Simon's avatar
Axel Simon committed
56
#elif defined(__GNUC__)
Axel Simon's avatar
Axel Simon committed
57
#define NO_INLINE_ATTR __attribute__((noinline))
Axel Simon's avatar
Axel Simon committed
58
#elif defined(_MSC_VER)
59
#define NO_INLINE_ATTR __declspec(noinline)
Axel Simon's avatar
Axel Simon committed
60 61 62 63
#else
#define NO_INLINE_ATTR
#endif

Axel Simon's avatar
Axel Simon committed
64
#if defined(__CLANG__)
Axel Simon's avatar
Axel Simon committed
65
#define MALLOC_ATTR __attribute__((malloc))
Axel Simon's avatar
Axel Simon committed
66
#elif defined(__GNUC__)
Axel Simon's avatar
Axel Simon committed
67
#define MALLOC_ATTR __attribute__((malloc))
Axel Simon's avatar
Axel Simon committed
68
#elif defined(_MSC_VER)
69
#define MALLOC_ATTR __declspec(restrict)
Axel Simon's avatar
Axel Simon committed
70 71 72 73 74
#else
#define MALLOC_ATTR
#endif


Axel Simon's avatar
Axel Simon committed
75
static NO_INLINE_ATTR void alloc_heap(state_t s, char* prev_page, size_t size) {
76
  if (size<CHUNK_SIZE) size = CHUNK_SIZE; else size = CHUNK_SIZE*((size/CHUNK_SIZE)+1);
77
  s->heap_base = (char*) malloc(size);
78 79 80 81 82 83 84 85 86 87 88
  if (s->heap_base==NULL) {
    s->err_str = "GDSL runtime: out of memory";
    longjmp(s->err_tgt,2);
  };
  s->heap = s->heap_base+sizeof(char*);
  /* store a pointer to the previous page in the first bytes of this page */
  *((char**) s->heap_base) = prev_page;
  s->heap_limit = s->heap_base+size;
};


Julian Kranz's avatar
Julian Kranz committed
89
void
Axel Simon's avatar
Axel Simon committed
90 91
@reset_heap@
(state_t s) {
92 93 94 95 96 97 98 99 100 101 102
  char* heap = s->heap_base;
  if (heap==NULL) return;
  while (1) {
    char* prev = *((char**) heap);
    if (prev==NULL) break;
    free (heap);
    heap = prev;
  }
  s->heap_base = heap;
  s->heap = heap+sizeof(char*);
  s->heap_limit = heap+CHUNK_SIZE;
103
  memset(&(s->mon_state), 0, sizeof(s->mon_state));
104 105
};

Julian Kranz's avatar
Julian Kranz committed
106
size_t
Axel Simon's avatar
Axel Simon committed
107 108
@heap_residency@
(state_t s) {
109
  char* heap = s->heap_base;
110
  size_t res;
111
  if (heap==NULL) return 0;
112
  res = s->heap - s->heap_base;
113 114 115 116 117 118 119 120 121
  while (1) {
    char* prev = *((char**) heap);
    if (prev==NULL) break;
    res += CHUNK_SIZE;
    heap = prev;
  }
  return res;
};

Axel Simon's avatar
Axel Simon committed
122
static INLINE_ATTR MALLOC_ATTR void* alloc(state_t s, size_t bytes) {
123 124 125 126 127 128 129 130
  bytes = ((bytes+7)>>3)<<3;    /* align to multiple of 8 */
  if (s->heap+bytes >= s->heap_limit) alloc_heap(s, s->heap_base, bytes);
  char* res = s->heap;
  s->heap = s->heap+bytes;
  return res;
};

#define GEN_ALLOC(type) \
131 132
static INLINE_ATTR type ## _t* alloc_ ## type (state_t s, type ## _t v) { \
  type ## _t* res = (type ## _t*) alloc(s, sizeof(type ## _t));\
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
  *res = v;\
  return res;\
}

#define alloc_string(s,str) str

#define GEN_CON_STRUCT(type)  \
struct con_ ## type {         \
  con_tag_t tag;              \
  type ## _t payload;         \
};                            \
                              \
typedef struct con_ ## type  con_ ## type ## _t

#define GEN_REC_STRUCT(type)  \
struct field_ ## type {       \
  field_tag_t tag;            \
  obj_t next;                 \
Axel Simon's avatar
Axel Simon committed
151
  unsigned int size;          \
152 153 154 155 156 157
  type ## _t payload;         \
};                            \
                              \
typedef struct field_ ## type  field_ ## type ## _t

#define GEN_ADD_FIELD(type)                               \
Axel Simon's avatar
Axel Simon committed
158
static obj_t add_field_ ## type                           \
Axel Simon's avatar
Axel Simon committed
159
(state_t s,field_tag_t tag, type ## _t v, obj_t rec) {    \
160
  field_ ## type ## _t* res = (field_ ## type ## _t*)     \
161 162 163 164 165 166 167 168
    alloc(s, sizeof(field_ ## type ## _t));               \
  res->tag = tag;                                         \
  res->size = sizeof(field_ ## type ## _t);               \
  res->next = rec;                                        \
  res->payload = v;                                       \
  return res;                                             \
}

Axel Simon's avatar
Axel Simon committed
169 170 171 172 173 174
#define GEN_SELECT_FIELD(type)                            \
static type ## _t select_  ## type                        \
(state_t s,field_tag_t field, obj_t rec) {                \
  field_ ## type ## _t* v = (field_ ## type ## _t*) rec;  \
  while (v) {                                             \
    if (v->tag==field) return v->payload;                 \
175
    v = (field_ ## type ## _t*) v->next;                                          \
Axel Simon's avatar
Axel Simon committed
176 177 178 179 180
  };                                                      \
  s->err_str = "GDSL runtime: field not found in record"; \
  longjmp(s->err_tgt,1);                                  \
}                                                         \

181 182 183 184 185 186 187 188 189
GEN_REC_STRUCT(obj);

/* Returns a pointer to a record in which the given fields are removed.
  This operation copies all fields of the record except for those that
  are to be removed. The function returns the tail of the old record if
  all given fields could be removed before the end of the record was
  reached.
*/
static obj_t del_fields(state_t s, field_tag_t tags[], int tags_size, obj_t rec) {
190
  field_obj_t* current = (field_obj_t*) rec;
191 192 193 194 195 196 197 198 199 200 201
  int idx;
  obj_t res = NULL;
  obj_t* last_next = &res;
  while (current && tags_size>0) {
    for (idx=0; idx<tags_size; idx++)
      if (current->tag == tags[idx]) break;
    if (idx<tags_size) {
      /* delete this field by doing nothing, but remove the index */
      tags[idx]=tags[--tags_size];
    } else {
      /* this field is not supposed to be deleted, copy it */
202
      field_obj_t* copy = (field_obj_t*) alloc(s, current->size);
203 204 205 206
      memcpy(copy,current,current->size);
      *last_next = copy;
      last_next = &copy->next;
    };
207
    current = (field_obj_t*) current->next;
208 209 210 211 212
  };
  *last_next = current;
  return res;
}

Axel Simon's avatar
Axel Simon committed
213 214 215 216

/* Functions to allocate values, constructors and record fields on the heap. */
@alloc_funcs@

217
#define slice(vec_data,ofs,sz) ((vec_data >> ofs) & ((1ul << sz)-1))
218 219

static INLINE_ATTR vec_t gen_vec(unsigned int vec_sz,vec_data_t vec_data) {
Axel Simon's avatar
Axel Simon committed
220 221 222
  vec_t res;
  res.size=vec_sz;
  res.data=vec_data;
223 224
  return res;
}
225

Julian Kranz's avatar
Julian Kranz committed
226
jmp_buf*
Axel Simon's avatar
Axel Simon committed
227 228
@err_tgt@
(state_t s) {
229 230 231
  return &(s->err_tgt);
};

Julian Kranz's avatar
Julian Kranz committed
232
char*
Axel Simon's avatar
Axel Simon committed
233 234
@get_error_message@
(state_t s) {
235 236 237
  return s->err_str;
};

Julian Kranz's avatar
Julian Kranz committed
238

Axel Simon's avatar
Axel Simon committed
239
static INLINE_ATTR int_t consume(state_t s, int_t size) {
Julian Kranz's avatar
Julian Kranz committed
240 241 242 243
  if(s->ip + size > s->ip_limit) {
    s->err_str = "GDSL runtime: end of code input stream";
    longjmp(s->err_tgt, 1);
  };
Julian Kranz's avatar
Julian Kranz committed
244
  int_t result = 0;
Axel Simon's avatar
Axel Simon committed
245
  while (size)
246
    result |= s->ip_start[(s->ip++ - s->ip_start) ^ s->token_addr_inv] << (--size*8);
Julian Kranz's avatar
Julian Kranz committed
247
  return result;
Julian Kranz's avatar
Julian Kranz committed
248 249
}

Axel Simon's avatar
Axel Simon committed
250
static INLINE_ATTR void unconsume(state_t s, int_t size) {
Julian Kranz's avatar
Julian Kranz committed
251
  s->ip -= size;
Julian Kranz's avatar
Julian Kranz committed
252 253
}

Julian Kranz's avatar
Julian Kranz committed
254 255
void
@endianness@
Julian Kranz's avatar
Julian Kranz committed
256
(state_t s, int_t le, int_t size) {
Axel Simon's avatar
Axel Simon committed
257
  if ((size != 1) && (size != 2) && (size != 4) && (size != 8)) {
Julian Kranz's avatar
Julian Kranz committed
258 259 260
    s->err_str = "GDSL runtime: endianness(); invalid token size";
    longjmp(s->err_tgt, 100);
  };
Axel Simon's avatar
Axel Simon committed
261
  if ((le != 0) && (le != 1)) {
Julian Kranz's avatar
Julian Kranz committed
262
    s->err_str = "GDSL runtime: endianness(); invalid kind";
Julian Kranz's avatar
Julian Kranz committed
263 264
    longjmp(s->err_tgt, 101);
  };
Julian Kranz's avatar
Julian Kranz committed
265
  s->token_addr_inv = le * (size - 1);
Julian Kranz's avatar
Julian Kranz committed
266 267
}

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
static int_t vec_to_signed(state_t s, vec_t v) {
  unsigned int bit_size = sizeof(int_t)*8;
  if (v.size>bit_size) {
    s->err_str = "GDSL runtime: signed applied to very long vector";
    longjmp(s->err_tgt,2);
  };
  int bits_to_fill = bit_size-v.size;
  return (((int_t) v.data) << bits_to_fill) >> bits_to_fill;
}

static int_t vec_to_unsigned(state_t s, vec_t v) {
  unsigned int int_bitsize = sizeof(int_t)*8;
  if (v.size>int_bitsize) {
    s->err_str = "GDSL runtime: unsigned applied to very long vector";
    longjmp(s->err_tgt,2);
  };
  return (int_t) v.data;
}

287
static INLINE_ATTR vec_t vec_not(state_t s, vec_t v) {
288
  vec_data_t mask = (1<<((vec_data_t) v.size))-1;
289 290 291 292
  vec_t res;
  res.size = v.size;
  res.data = v.data ^ mask;
  return res;
293 294
}

295
static INLINE_ATTR vec_data_t vec_eq(state_t s, vec_data_t d1, vec_data_t d2) {
296 297 298
  return (d1==d2 ? 1 : 0);
}

299 300 301 302 303
static INLINE_ATTR vec_t vec_concat(state_t s, vec_t v1, vec_t v2) {
  vec_t res;
  res.size = v1.size+v2.size;
  res.data = v1.data << v2.size | v2.data;
  return res;
304 305 306
}

static string_t int_to_string(state_t s, int_t v) {
307 308 309 310 311 312 313 314 315 316 317
  char *str = (char*) alloc(s, 23)+22;
  int negate = v<0;
  int r;
  *str = 0;
  do {
    r = v % 10;
    v = v / 10;
    *--str = "9876543210123456789"[r+9];
  } while (v!=0);
  if (negate) {
    *--str = '-';
Julian Kranz's avatar
---  
Julian Kranz committed
318
  }
319
  return alloc_string(s,str);
320 321
};

Julian Kranz's avatar
Julian Kranz committed
322
void
Axel Simon's avatar
Axel Simon committed
323
@set_code@
324
(state_t s, unsigned char* buf, size_t buf_len, size_t base) {
Axel Simon's avatar
Axel Simon committed
325 326
  s->ip = buf;
  s->ip_limit = buf+buf_len;
Julian Kranz's avatar
Julian Kranz committed
327 328
  s->ip_start = buf;
  s->ip_base = base;
Axel Simon's avatar
Axel Simon committed
329 330
}

Julian Kranz's avatar
Julian Kranz committed
331
size_t
Axel Simon's avatar
Axel Simon committed
332
@get_ip@
Axel Simon's avatar
Axel Simon committed
333
(state_t s) {
Julian Kranz's avatar
Julian Kranz committed
334
  return s->ip_base + (s->ip - s->ip_start);
Axel Simon's avatar
Axel Simon committed
335 336
}

Julian Kranz's avatar
Julian Kranz committed
337
int_t
Axel Simon's avatar
Axel Simon committed
338 339
@seek@
(state_t s, size_t i) {
Julian Kranz's avatar
Julian Kranz committed
340 341
  size_t size = (size_t)(s->ip_limit - s->ip_start);
  size_t start_offset = i - s->ip_base;
Julian Kranz's avatar
Julian Kranz committed
342 343 344 345
  if(start_offset >= size)
    return 1;
  s->ip = s->ip_start + start_offset;
  return 0;
346 347
}

Axel Simon's avatar
Axel Simon committed
348 349 350
string_t
@merge_rope@
(state_t s, obj_t rope) {
351
  string_t buf,end;
Axel Simon's avatar
Axel Simon committed
352 353 354
  int_t len =
@rope_length@
(s,rope);
355 356 357
  if (len<0) return ""; /* make MSVC happy */
  buf = (string_t) alloc(s,(size_t) len);
  end =
Axel Simon's avatar
Axel Simon committed
358 359 360 361 362 363
@rope_to_string@
(s,rope,buf);
  *end = 0;
  return buf;
}

Julian Kranz's avatar
Julian Kranz committed
364
void
Axel Simon's avatar
Axel Simon committed
365 366 367 368
@destroy@
(state_t s) {
@reset_heap@
(s);
369
  char* heap;
370
  free(s->heap_base);
371
  /* free heap of GDSL constants */
372
  heap = s->const_heap_base;
373 374 375 376 377
  while (heap!=NULL) {
    char* prev = *((char**) heap);
    free (heap);
    heap = prev;
  }
378 379
  free(s);
}
Axel Simon's avatar
Axel Simon committed
380 381

@prototypes@
Axel Simon's avatar
Axel Simon committed
382

383

384 385 386
@functions@


Julian Kranz's avatar
Julian Kranz committed
387
state_t
388
@init@
Axel Simon's avatar
Axel Simon committed
389
(void) {
390 391 392 393 394 395 396 397 398 399
  state_t s = calloc(1,sizeof(struct state));
  s->handle = stdout;
  /* compute all constant expressions */
@gdsl_init_constants@

  /* keep the heap of constant expressions separate */
  s->const_heap_base = s->heap_base;
  s->heap_base = NULL;
  s->heap_limit = NULL;
  s->heap = NULL;
Julian Kranz's avatar
Julian Kranz committed
400

Julian Kranz's avatar
Julian Kranz committed
401 402
  @endianness@
  (s, 0, 1);
Julian Kranz's avatar
Julian Kranz committed
403

404 405 406 407
  return s;
}


Axel Simon's avatar
Axel Simon committed
408
#ifdef WITHMAIN
409

Axel Simon's avatar
Axel Simon committed
410 411 412 413 414 415 416
#if defined(gdsl_decode_translate_block_optimized) && defined(gdsl_rreil_pretty)
  #define HAVE_TRANS
#endif
#if defined(gdsl_decode) && defined(gdsl_pretty)
  #define HAVE_DECODE
#endif

417
#define BUF_SIZE 32*1024*1024
418
static unsigned char blob[BUF_SIZE];
Axel Simon's avatar
Axel Simon committed
419

Axel Simon's avatar
Axel Simon committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
int readNum(char* str, size_t* res) {
  size_t mult = 10;
  *res = 0;
  while (*str) {
    char c = *str;
    if (c=='x') mult=16; else
      if ((c>='0') && (c<='9')) *res=*res*mult+(size_t) (c-'0'); else
        if ((c>='a') && (c<='f')) *res=*res*mult+10+(size_t) (c-'a'); else
          if ((c>='A') && (c<='F')) *res=*res*mult+10+(size_t) (c-'A'); else
            return 1;
    str++;
  }
  return 0;
}

Axel Simon's avatar
Axel Simon committed
435
int main (int argc, char** argv) {
Axel Simon's avatar
Axel Simon committed
436
  size_t buf_size = BUF_SIZE;
Axel Simon's avatar
Axel Simon committed
437
  FILE* file = NULL;
Axel Simon's avatar
Axel Simon committed
438 439 440 441 442 443
  int_t decode_options =
#if defined(gdsl_default_config)
    gdsl_default_config;
#else
    0;
#endif
Axel Simon's avatar
Axel Simon committed
444
  int_t optimization_options = 0;
Axel Simon's avatar
Axel Simon committed
445 446
  int_t run_translate = 0;
  int_t translate_options = 0;
Axel Simon's avatar
Axel Simon committed
447 448
  size_t base_address = 0;
  size_t start_address = 0;
449
  int print_addr = 0;
Julian Kranz's avatar
Julian Kranz committed
450
  obj_t config;
Axel Simon's avatar
Axel Simon committed
451
  state_t s = gdsl_init();
452 453
  long long alloc_size,alloc_no,alloc_max;
  
Axel Simon's avatar
Axel Simon committed
454
  /* read command line parameters */
Axel Simon's avatar
Axel Simon committed
455
  int i;
Axel Simon's avatar
Axel Simon committed
456 457 458
  for(i=1; i<argc; i++) {
    char* arg = argv[i];
    if (strncmp(arg,"--",2)) {
Axel Simon's avatar
Axel Simon committed
459 460 461
#ifdef _MSC_VER
      fopen_s(&file,arg,"r");
#else
Axel Simon's avatar
Axel Simon committed
462
      file = fopen(arg,"r");
Axel Simon's avatar
Axel Simon committed
463
#endif
Axel Simon's avatar
Axel Simon committed
464 465 466 467 468
      if (file==NULL) {
        printf("file '%s' not found, please run %s --help for usage\n", arg, argv[0]);
        return 1;
      }
    } else {
469
      arg+=2;
Axel Simon's avatar
Axel Simon committed
470 471
#if defined(gdsl_decoder_config)
      for (config = gdsl_decoder_config(s); gdsl_has_conf(s,config);
472
        config = gdsl_conf_next(s,config))
Axel Simon's avatar
Axel Simon committed
473
        if (strcmp(arg,gdsl_conf_short(s,config))==0) {
Axel Simon's avatar
Axel Simon committed
474
          decode_options |= gdsl_conf_data(s,config);
Axel Simon's avatar
Axel Simon committed
475 476 477
          break;
        }
      if (gdsl_has_conf(s,config)) continue;
478
#endif
Axel Simon's avatar
Axel Simon committed
479 480
#if defined(gdsl_optimization_config)
      for (config = gdsl_optimization_config(s); gdsl_has_conf(s,config);
481
        config = gdsl_conf_next(s,config))
Axel Simon's avatar
Axel Simon committed
482
        if (strcmp(arg,gdsl_conf_short(s,config))==0) {
Axel Simon's avatar
Axel Simon committed
483
          optimization_options |= gdsl_conf_data(s,config);
Axel Simon's avatar
Axel Simon committed
484 485 486
          break;
        }
      if (gdsl_has_conf(s,config)) continue;
Axel Simon's avatar
Axel Simon committed
487 488
#endif
      if (strncmp(arg,"base=",5)==0) {
Axel Simon's avatar
Axel Simon committed
489
        int res=readNum(arg+5,&base_address);
490
        print_addr=1;
Axel Simon's avatar
Axel Simon committed
491
        if (res==0) continue;
Axel Simon's avatar
Axel Simon committed
492 493
      }
      if (strncmp(arg,"start=",6)==0) {
Axel Simon's avatar
Axel Simon committed
494 495
        int res=readNum(arg+6,&start_address);
        if (res==0) continue;
Axel Simon's avatar
Axel Simon committed
496 497 498 499 500 501
      }
      if (strcmp(arg,"trans")==0) {
        run_translate = 1;
        continue;
      }
      fprintf(stderr,
Axel Simon's avatar
Axel Simon committed
502 503
        "Command line argument `%s' not recognized. Usage:\n"
        "\t%s [options] filename\nwhere\n"
Axel Simon's avatar
Axel Simon committed
504 505
        "  --trans               translate to semantics\n"
        "  --base=addr           print addresses relative to addr\n"
Axel Simon's avatar
Axel Simon committed
506
        "  --start=addr          decode starting from addr\n", argv[i], argv[0]);
Axel Simon's avatar
Axel Simon committed
507
#if defined(gdsl_decoder_config)
Julian Kranz's avatar
Julian Kranz committed
508
      for (config = gdsl_decoder_config(s); gdsl_has_conf(s,config);
Axel Simon's avatar
Axel Simon committed
509
        config = gdsl_conf_next(s,config))
Axel Simon's avatar
Axel Simon committed
510 511
        fprintf(stderr,"  --%s\t\t%s\n",
          gdsl_conf_short(s,config), gdsl_conf_long(s,config));
512
#endif
Axel Simon's avatar
Axel Simon committed
513 514
#if defined(gdsl_optimization_config)
      for (config = gdsl_optimization_config(s); gdsl_has_conf(s,config);
515
        config = gdsl_conf_next(s,config))
Axel Simon's avatar
Axel Simon committed
516 517
        fprintf(stderr,"  --%s\t\t%s\n",
          gdsl_conf_short(s,config), gdsl_conf_long(s,config));
Axel Simon's avatar
Axel Simon committed
518 519 520
#endif
      return 1;
    }
Axel Simon's avatar
Axel Simon committed
521
  }
Axel Simon's avatar
Axel Simon committed
522 523 524
  /* fill the buffer, either in binary from file or as sequence
     of hex bytes separated by space or newlines */
  if (file) {
Julian Kranz's avatar
Julian Kranz committed
525 526
    size_t bytes_read = fread(blob, 1, BUF_SIZE, file);
    if (bytes_read == 0) return 1;
Axel Simon's avatar
Axel Simon committed
527 528
    buf_size = bytes_read;
  } else {
Axel Simon's avatar
Axel Simon committed
529 530 531 532 533 534 535 536 537 538 539 540 541 542
    size_t i=0;
    int num=0;
    int digit=0;
    while (i<buf_size) {
      int x = getchar();
      if (x==EOF) buf_size = i; else
      if ((x>='0') && (x<='9')) { num=num*16+(x-'0'); digit++; } else
      if ((x>='a') && (x<='f')) { num=num*16+(10+x-'a'); digit++; } else
      if ((x>='A') && (x<='F')) { num=num*16+(10+x-'A'); digit++; } else
      if (x>' ') {
        fprintf(stderr, "invalid input; should be in hex form: '0f 0b ..'.\n");
        return 1;
      }
      if (digit==2) { blob[i] = num & 0xff; i+=1; digit=0; };
Axel Simon's avatar
Axel Simon committed
543
    }
544
  }  
Axel Simon's avatar
Axel Simon committed
545 546 547
  /* initialize the GDSL program */
  gdsl_set_code(s, blob, buf_size, base_address);
  gdsl_seek(s, start_address);
Julian Kranz's avatar
Julian Kranz committed
548

549 550 551
  alloc_size = 0;
  alloc_no = 0;
  alloc_max = 0;
552

Axel Simon's avatar
Axel Simon committed
553
  while (gdsl_get_ip(s)-base_address<buf_size) {
Axel Simon's avatar
Axel Simon committed
554
    size_t size;
555
    if (setjmp(*gdsl_err_tgt(s))==0) {
Axel Simon's avatar
Axel Simon committed
556 557
      if (run_translate) {
#ifdef HAVE_TRANS
Axel Simon's avatar
Axel Simon committed
558
        opt_result_t block = gdsl_decode_translate_block_optimized(s,
Axel Simon's avatar
Axel Simon committed
559
          decode_options,
560
          gdsl_int_max(s),
Axel Simon's avatar
Axel Simon committed
561
          optimization_options);
Axel Simon's avatar
Axel Simon committed
562
        obj_t res = gdsl_rreil_pretty(s,block->rreil);
Axel Simon's avatar
Axel Simon committed
563
        string_t str = gdsl_merge_rope(s,res);
564
        if (print_addr) printf("0x%016lx:\n",gdsl_get_ip(s));
Axel Simon's avatar
Axel Simon committed
565
        fputs(str,stdout);
566
#else
567
        fputs("GDSL modules contain no semantic translation\n",stdout);
568
        return 1;
Axel Simon's avatar
Axel Simon committed
569
#endif
570
      } else {
Axel Simon's avatar
Axel Simon committed
571 572
#ifdef HAVE_DECODE
        obj_t instr = gdsl_decode(s, decode_options);
Axel Simon's avatar
Axel Simon committed
573 574
        obj_t res = gdsl_pretty(s,instr);
        string_t str = gdsl_merge_rope(s,res);
575
        if (print_addr) printf("%016lx ",gdsl_get_ip(s));
Axel Simon's avatar
Axel Simon committed
576
        fputs(str,stdout);
577
#else
578
        fputs("GDSL modules contain no decoder function\n",stdout);
579
        return 1;
Axel Simon's avatar
Axel Simon committed
580
#endif
581 582
      }
    } else {
583
      fprintf(stdout,"exception at address 0x%lx: %s", gdsl_get_ip(s), gdsl_get_error_message(s));
Axel Simon's avatar
Axel Simon committed
584
      size_t step = (s->token_addr_inv>0 ? (size_t) s->token_addr_inv+1 : 1u);
585
      gdsl_seek(s,gdsl_get_ip(s)+step);
Axel Simon's avatar
Axel Simon committed
586
    }
Axel Simon's avatar
Axel Simon committed
587
    fputs("\n",stdout);
588
    size = gdsl_heap_residency(s);
589 590 591 592
    alloc_size += size;
    alloc_no++;
    if (size>alloc_max) alloc_max = size;
    gdsl_reset_heap(s);
Axel Simon's avatar
Axel Simon committed
593
  }
594
  fprintf(stderr, "heap: no: %lli mem: %lli max: %lli\n", alloc_no, alloc_size, alloc_max);
Axel Simon's avatar
Axel Simon committed
595
  gdsl_destroy(s);
Julian Kranz's avatar
Julian Kranz committed
596
  return 0;
Axel Simon's avatar
Axel Simon committed
597 598
}

Axel Simon's avatar
Axel Simon committed
599
#endif
Axel Simon's avatar
Axel Simon committed
600 601