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;
Axel Simon's avatar
Axel Simon committed
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);
Axel Simon's avatar
Axel Simon committed
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));
Axel Simon's avatar
Axel Simon committed
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);
Axel Simon's avatar
Axel Simon committed
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
Axel Simon's avatar
Axel Simon committed
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
Axel Simon's avatar
Axel Simon committed
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