This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.

Dependencies:   mbed

For details, refer to the following.

http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436

Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.

Files at this revision

API Documentation at this revision

Comitter:
tk_takateku
Date:
Wed Feb 15 01:03:35 2017 +0000
Commit message:
Commit before publishing

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mrubyc/alloc.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/alloc.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_array.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_array.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_hash.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_hash.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_numeric.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_numeric.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_range.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_range.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_string.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_string.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_symbol.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/c_symbol.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/class.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/class.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/console.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/console.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/errorcode.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/global.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/global.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/hal/hal.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/load.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/load.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/mrubyc.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/opcode.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/rrt0.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/rrt0.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/static.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/static.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/symbol.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/symbol.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/value.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/value.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/vm.c Show annotated file Show diff for this revision Revisions of this file
mrubyc/vm.h Show annotated file Show diff for this revision Revisions of this file
mrubyc/vm_config.h Show annotated file Show diff for this revision Revisions of this file
sample1.c Show annotated file Show diff for this revision Revisions of this file
sample1.rb Show annotated file Show diff for this revision Revisions of this file
sample2.c Show annotated file Show diff for this revision Revisions of this file
sample2.rb Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 33feccbba3ff main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,57 @@
+#include "mbed.h"
+
+#include "mrubyc/hal/hal.h"
+#include "mrubyc/mrubyc.h"
+
+DigitalIn mybutton(USER_BUTTON);
+DigitalOut myled(LED1);
+RawSerial mysci(USBTX, USBRX);
+
+extern const uint8_t sample1[];
+extern const uint8_t sample2[];
+
+int hal_write(int fd, const void *buf, size_t nbytes)
+{
+    return mysci.write((const uint8_t *)buf, (int)nbytes, NULL, SERIAL_EVENT_TX_COMPLETE);
+}
+
+int hal_flush(int fd)
+{
+    char char1 = 0;
+    while (mysci.readable()) 
+    { 
+        char1 = mysci.getc();
+    }
+    return 0;
+}
+
+void hal_delay(mrb_vm *vm, mrb_value *v)
+{
+    wait_ms((int)GET_INT_ARG(0));
+}
+
+void hal_led(mrb_vm *vm, mrb_value *v)
+{
+    myled = (int)GET_INT_ARG(0);
+}
+
+void hal_button(mrb_vm *vm, mrb_value *v)
+{
+    int sw = mybutton;
+    SET_INT_RETURN(sw);
+}
+
+int main() {
+    mysci.baud(115200);                     // 115Kbps
+    mysci.format(8, Serial::None, 1);       // 8bt, none parity, stop bit 1
+    mrbc_init();
+    mrbc_define_method(0, mrbc_class_object, "led1_write", hal_led);
+    mrbc_define_method(0, mrbc_class_object, "delay", hal_delay);
+    mrbc_define_method(0, mrbc_class_object, "sw1_read", hal_button);
+    mrbc_create_task( sample1, 0 );
+    mrbc_create_task( sample2, 0 );
+    
+    mrbc_run();
+    
+}
+ 
\ No newline at end of file
diff -r 000000000000 -r 33feccbba3ff mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/ef9c61f8c49f
\ No newline at end of file
diff -r 000000000000 -r 33feccbba3ff mrubyc/alloc.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/alloc.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,373 @@
+/*! @file
+  @brief
+  mrubyc memory management.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  Memory management for objects in mruby/c.
+
+  </pre>
+*/
+
+#include <stddef.h>
+#include <string.h>
+#include "alloc.h"
+#include "console.h"
+
+//
+#define ALLOC_TOTAL_MEMORY_SIZE 0x2800
+
+// address space 16bit, 64KB
+#define ALLOC_MAX_BIT 16
+
+// Layer 1st(f) and 2nd(s) model
+// last 4bit is ignored
+// f : size
+// 0 : 0000-007f
+// 1 : 0080-00ff
+// 2 : 0100-01ff
+// 3 : 0200-03ff
+// 4 : 0400-07ff
+// 5 : 0800-0fff
+// 6 : 1000-1fff
+// 7 : 2000-3fff
+// 8 : 4000-7fff
+// 9 : 8000-ffff
+
+#define ALLOC_1ST_LAYER 8
+#define ALLOC_1ST_LAYER_BIT ALLOC_1ST_LAYER
+#define ALLOC_1ST_LAYER_MASK 0xff80
+
+// 2nd layer size
+#define ALLOC_2ND_LAYER 8
+#define ALLOC_2ND_LAYER_BIT 3
+#define ALLOC_2ND_LAYER_MASK 0x0070
+
+// memory
+static uint8_t memory_pool[ALLOC_TOTAL_MEMORY_SIZE];
+
+// define flags
+#define FLAG_TAIL_BLOCK 1
+#define FLAG_NOT_TAIL_BLOCK 0
+#define FLAG_FREE_BLOCK 1
+#define FLAG_USED_BLOCK 0
+
+// memory block header
+struct USED_BLOCK {
+  unsigned int t: 1;  /* FLAG_TAIL_BLOCK or FLAG_NOT_TAIL_BLOCK */
+  unsigned int f: 1;  /* FLAG_FREE_BLOCK or BLOCK_IS_NOT_FREE */
+  unsigned int size: 14; /* block size, header included */
+  struct USED_BLOCK *prev;  /* link to previous block */
+  uint8_t data[];
+};
+
+struct FREE_BLOCK {
+  unsigned int t: 1;  /* 0: not tail,  1: tail */
+  unsigned int f: 1;  /* 0: not free,  1: free */
+  unsigned int size: 14; /* block size, header included */
+  struct FREE_BLOCK *prev;  /* link to previous block */
+  struct FREE_BLOCK *next_free;
+  struct FREE_BLOCK *prev_free;
+};
+
+// free memory bitmap
+static struct FREE_BLOCK *free_blocks[ALLOC_1ST_LAYER * ALLOC_2ND_LAYER];
+
+
+// calc f and s, and returns index of free_blocks
+static int calc_index(uint32_t alloc_size)
+{
+  if( alloc_size < 16 ) alloc_size = 16;
+
+  // 1st layer
+  int f = 0;
+  uint32_t f_bit = ALLOC_1ST_LAYER_MASK;
+  uint32_t s_bit = ALLOC_2ND_LAYER_MASK;
+  while( (alloc_size & f_bit) != 0 ){
+    f++;
+    f_bit <<= 1;
+    s_bit <<= 1;
+  }
+
+  // 2nd layer
+  int s = (alloc_size & s_bit) >> (f + 4);
+
+  return f * ALLOC_2ND_LAYER + s;
+}
+
+
+//
+static void add_free_block(struct FREE_BLOCK *block)
+{
+  block->f = FLAG_FREE_BLOCK;
+  int index = calc_index(block->size);
+
+  block->prev_free = NULL;
+  block->next_free = free_blocks[index];
+  if( free_blocks[index] != NULL ){
+    free_blocks[index]->prev_free = block;
+  }
+  free_blocks[index] = block;
+}
+
+
+// initialize free block
+void mrbc_init_alloc(void)
+{
+  // clear links to free block
+  int i;
+  for( i=0 ; i<ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ; i++ ){
+    free_blocks[i] = NULL;
+  }
+
+  // memory pool
+  struct FREE_BLOCK *block = (struct FREE_BLOCK *)memory_pool;
+  block->t = FLAG_TAIL_BLOCK;
+  block->size = ALLOC_TOTAL_MEMORY_SIZE;
+  add_free_block(block);
+}
+
+// split block *alloc by size
+static struct FREE_BLOCK *split_block(struct FREE_BLOCK *alloc, int size)
+{
+  if( alloc->size < size + 24 ) return NULL;
+
+  // split block, free
+  uint8_t *p = (uint8_t *)alloc;
+  struct FREE_BLOCK *split = (struct FREE_BLOCK *)(p + size);
+  struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + alloc->size);
+  split->size = alloc->size - size;
+  split->prev = alloc;
+  split->f = FLAG_FREE_BLOCK;
+  split->t = alloc->t;
+  alloc->size = size;
+  alloc->f = FLAG_USED_BLOCK;
+  alloc->t = FLAG_NOT_TAIL_BLOCK;
+  if( split->t == FLAG_NOT_TAIL_BLOCK ){
+    next->prev = split;
+  }
+
+  return split;
+}
+
+
+// just remove the free_block *remove from index
+static void remove_index(struct FREE_BLOCK *remove)
+{
+  // remove is top of linked list?
+  if( remove->prev_free == NULL ){
+    int index = calc_index(remove->size);
+    free_blocks[index] = remove->next_free;
+    if( free_blocks[index] != NULL ){
+      free_blocks[index]->prev = NULL;
+    }
+  } else {
+    remove->prev_free->next_free = remove->next_free;
+    if( remove->next_free != NULL ){
+      remove->next_free->prev_free = remove->prev_free;
+    }
+  }
+}
+
+// memory allocation
+uint8_t *mrbc_raw_alloc(uint32_t size)
+{
+  uint32_t alloc_size = size + sizeof(struct USED_BLOCK);
+
+  int index = calc_index(alloc_size);
+  while( index < ALLOC_1ST_LAYER*ALLOC_2ND_LAYER && free_blocks[index] == NULL ){
+    index++;
+  }
+  if( index >= ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ){
+    // out of memory
+    console_print("Fatal error: Out of memory.\n");
+    return NULL;
+  }
+
+  // alloc a free block
+  struct FREE_BLOCK *alloc = free_blocks[index];
+  alloc->f = FLAG_USED_BLOCK;
+  remove_index(alloc);
+
+  // split a block
+  struct FREE_BLOCK *release = split_block(alloc, alloc_size);
+  if( release != NULL ){
+    // split alloc -> alloc + release
+    int index = calc_index(release->size);
+    release->next_free = free_blocks[index];
+    release->prev_free = NULL;
+    free_blocks[index] = release;
+    if( release->next_free != NULL ){
+      release->next_free->prev_free = release;
+    }
+  }
+
+  return ((struct USED_BLOCK *)alloc)->data;
+}
+
+
+// merge ptr1 and ptr2
+// ptr2 will disappear
+static void merge(struct FREE_BLOCK *ptr1, struct FREE_BLOCK *ptr2)
+{
+  // merge ptr1 and ptr2
+  ptr1->t = ptr2->t;
+  ptr1->size += ptr2->size;
+
+  // update block info
+  if( ptr1->t == FLAG_NOT_TAIL_BLOCK ){
+    uint8_t *p = (uint8_t *)ptr1;
+    struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + ptr1->size);
+    next->prev = ptr1;
+  }
+}
+
+// memory release
+void mrbc_raw_free(void *ptr)
+{
+  // get free block
+  uint8_t *p = ptr;
+  struct FREE_BLOCK *free_ptr = (struct FREE_BLOCK *)(p - sizeof(struct USED_BLOCK));
+  free_ptr->f = FLAG_FREE_BLOCK;
+
+  // check next block, merge?
+  p = (uint8_t *)free_ptr;
+  struct FREE_BLOCK *next_ptr = (struct FREE_BLOCK *)(p + free_ptr->size);
+  if( free_ptr->t == FLAG_NOT_TAIL_BLOCK && next_ptr->f == FLAG_FREE_BLOCK ){
+    remove_index(next_ptr);
+    merge(free_ptr, next_ptr);
+  }
+
+  // check prev block, merge?
+  struct FREE_BLOCK *prev_ptr = free_ptr->prev;
+  if( prev_ptr != NULL && prev_ptr->f == FLAG_FREE_BLOCK ){
+    remove_index(prev_ptr);
+    merge(prev_ptr, free_ptr);
+    free_ptr = prev_ptr;
+  }
+
+  // free, add to index
+  add_free_block(free_ptr);
+}
+
+
+// simple realloc
+uint8_t *mrbc_raw_realloc(uint8_t *ptr, uint32_t size)
+{
+  uint8_t *new_ptr = mrbc_raw_alloc(size);
+  if( new_ptr == NULL ) return NULL;  // ENOMEM
+
+  // get block info
+  uint8_t *src_ptr = ptr;
+  struct USED_BLOCK *src_block = (struct USED_BLOCK *)(src_ptr - sizeof(struct USED_BLOCK));
+
+  // copy size
+  int copy_size;
+  if( size > src_block->size-sizeof(struct USED_BLOCK) ){
+    copy_size = src_block->size - sizeof(struct USED_BLOCK);
+  } else {
+    copy_size = size;
+  }
+
+  // copy and free
+  memcpy(new_ptr, src_ptr, copy_size);
+  mrbc_raw_free(ptr);
+
+  return new_ptr;
+}
+
+// for debug
+#ifdef MRBC_DEBUG
+#include <stdio.h>
+void mrbc_alloc_debug(void)
+{
+  struct FREE_BLOCK *ptr = (struct FREE_BLOCK *)memory_pool;
+  printf("-----\naddress f size\n");
+  do {
+    uint8_t *p = (uint8_t *)ptr;
+    printf("%p: %d %x\n", p, ptr->f, ptr->size);
+    if( ptr->t == FLAG_TAIL_BLOCK ) break;
+    p += ptr->size;
+    ptr = (struct FREE_BLOCK *)p;
+  } while(1);
+
+  printf("-----\n");
+  int i;
+  for( i=0 ; i<ALLOC_1ST_LAYER * ALLOC_2ND_LAYER ; i++ ){
+    if( free_blocks[i] == NULL ) continue;
+    printf("free[%d]\n", i);
+    struct FREE_BLOCK *ptr = free_blocks[i];
+    while( ptr != NULL ){
+      printf("  %p: size=%d\n", ptr, ptr->size);
+      ptr = ptr->next_free;
+    }
+  }
+}
+#endif
+
+//// for mruby/c
+
+struct MEM_WITH_VM {
+  uint8_t vm_id;
+  uint8_t data[];
+};
+
+uint8_t *mrbc_alloc(mrb_vm *vm, int size)
+{
+  int alloc_size = size + sizeof(struct MEM_WITH_VM);
+  struct MEM_WITH_VM *alloc_block =
+      (struct MEM_WITH_VM *)mrbc_raw_alloc(alloc_size);
+  if( alloc_block == NULL ) return NULL;  // ENOMEM
+
+  alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0;
+  return alloc_block->data;
+}
+
+
+uint8_t *mrbc_realloc(mrb_vm *vm, void *ptr, int size)
+{
+  int alloc_size = size + sizeof(struct MEM_WITH_VM);
+  struct MEM_WITH_VM *alloc_block =
+      (struct MEM_WITH_VM *)mrbc_raw_realloc(ptr, alloc_size);
+  if( alloc_block == NULL ) return NULL;  // ENOMEM
+
+  alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0;
+  return alloc_block->data;
+}
+
+
+void mrbc_free(mrb_vm *vm, void *ptr)
+{
+  if( ptr == NULL ) return;
+
+  uint8_t *p = (uint8_t *)ptr;
+  struct MEM_WITH_VM *free_block = (struct MEM_WITH_VM *)(p - sizeof(struct MEM_WITH_VM));
+  mrbc_raw_free(free_block);
+}
+
+
+void mrbc_free_all(mrb_vm *vm)
+{
+  int vm_id = vm->vm_id;
+
+  struct USED_BLOCK *ptr = (struct USED_BLOCK *)memory_pool;
+  while( ptr->t != FLAG_TAIL_BLOCK ){
+    struct MEM_WITH_VM *vm_ptr = (struct MEM_WITH_VM *)(ptr->data);
+    if( ptr->f == FLAG_FREE_BLOCK || vm_ptr->vm_id != vm_id ){
+      uint8_t *p = (uint8_t *)ptr;
+      ptr = (struct USED_BLOCK *)(p + ptr->size);
+      continue;
+    }
+    if( vm_ptr->vm_id != vm_id ) continue;
+    // free a block
+    struct USED_BLOCK *next_ptr = ptr->prev;
+    if( next_ptr == NULL ) next_ptr = ptr;
+    mrbc_raw_free(ptr->data);
+    ptr = next_ptr;
+  }  
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/alloc.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/alloc.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,43 @@
+/*! @file
+  @brief
+  mrubyc memory management.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  Memory management for objects in mruby/c.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_ALLOC_H_
+#define MRBC_SRC_ALLOC_H_
+
+#include <stdint.h>
+#include "vm.h"    // for mruby/c
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void mrbc_init_alloc(void);
+uint8_t *mrbc_raw_alloc(uint32_t size);
+uint8_t *mrbc_raw_realloc(uint8_t *ptr, uint32_t size);
+void mrbc_raw_free(void *ptr);
+
+void mrbc_alloc_debug(void);
+
+// for mruby/c
+uint8_t *mrbc_alloc(mrb_vm *vm, int size);
+uint8_t *mrbc_realloc(mrb_vm *vm, void *ptr, int size);
+void mrbc_free(mrb_vm *vm, void *ptr);
+void mrbc_free_all(mrb_vm *vm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_array.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_array.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,175 @@
+#include <stddef.h>
+
+#include "c_array.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+
+// Internal use only
+// get size of array
+static int array_size(mrb_value *v)
+{
+  mrb_value *array = v->value.obj;
+  return array->value.i;
+}
+
+
+// Array#!=
+static void c_array_neq(mrb_vm *vm, mrb_value *v)
+{
+  if( mrbc_eq(v, v+1) ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+// Array = empty?
+static void c_array_empty(mrb_vm *vm, mrb_value *v)
+{
+  if( array_size(v) > 0 ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+// Array = size
+static void c_array_size(mrb_vm *vm, mrb_value *v)
+{
+  int cnt = array_size(v);
+  SET_INT_RETURN( cnt );
+}
+
+// Array = []
+static void c_array_get(mrb_vm *vm, mrb_value *v)
+{
+  int pos = GET_INT_ARG(0);
+  mrb_value *array = v->value.obj;
+
+  if( pos >= 0 && pos < array->value.i ){
+    *v = array[pos+1];
+  } else {
+    SET_NIL_RETURN();
+  }
+}
+
+// Array = []=
+static void c_array_set(mrb_vm *vm, mrb_value *v)
+{
+  int pos = GET_INT_ARG(0);
+  mrb_value *array = v->value.obj;
+
+  if( pos >= 0 && pos < array->value.i ){
+    array[pos+1] = GET_ARG(1);
+  } else {
+    SET_NIL_RETURN();
+  }
+}
+
+// Array = operator +
+static void c_array_plus(mrb_vm *vm, mrb_value *v)
+{
+  // because realloc is not ready in alloc.c,
+  // use free and alloc
+  mrb_value *array1 = v->value.array;
+  mrb_value *array2 = GET_ARY_ARG(0).value.array;
+  int len1 = array1->value.i;
+  int len2 = array2->value.i;
+  mrb_value *new_array = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*(len1+len2+1));
+
+  if( new_array == NULL ) return;  // ENOMEM
+
+  new_array->tt = MRB_TT_FIXNUM;
+  new_array->value.i = len1+len2;
+  mrb_value *p = new_array + 1;
+  int i;
+  for( i=0 ; i<len1 ; i++ ){
+    *p++ = array1[i+1];
+  }
+  for( i=0 ; i<len2 ; i++ ){
+    *p++ = array2[i+1];
+  }
+  mrbc_free(vm, array1);
+  mrbc_free(vm, array2);
+  // return
+  v->value.array = new_array;
+}
+
+
+static void c_array_index(mrb_vm *vm, mrb_value *v)
+{
+  int len = v->value.array->value.i;
+  mrb_value *array = v->value.array + 1;
+  mrb_value value = GET_ARG(0);
+
+  int i;
+  for( i=0 ; i<len ; i++ ){
+    // check EQ
+    if( mrbc_eq(array+i, &value) ) break;
+  }
+  if( i<len ){
+    SET_INT_RETURN(i);
+  } else {
+    SET_NIL_RETURN();
+  }
+}
+
+static void c_array_first(mrb_vm *vm, mrb_value *v)
+{
+  if( GET_TT_ARG(0) == MRB_TT_FIXNUM ){
+    mrb_value *array = v->value.array + 1;
+    SET_RETURN( array[0] );
+  } else {
+    SET_NIL_RETURN();
+  }
+}
+
+static void c_array_last(mrb_vm *vm, mrb_value *v)
+{
+  if( GET_TT_ARG(0) == MRB_TT_FIXNUM ){
+    int len = v->value.array->value.i;
+    mrb_value *array = v->value.array + 1;
+    SET_RETURN( array[len-1] );
+  } else {
+    SET_NIL_RETURN();
+  }
+}
+
+static void c_array_pop(mrb_vm *vm, mrb_value *v)
+{
+	mrb_object *obj = v->value.obj;
+	mrb_object *tmp = obj->next;
+	while( tmp->next ){
+		obj = obj->next;
+		tmp = obj->next;
+	}
+	obj->next = tmp->next;
+	SET_INT_RETURN(tmp->value.i);
+}
+
+
+void mrbc_init_class_array(mrb_vm *vm)
+{
+  // Array
+  mrbc_class_array = mrbc_class_alloc(vm, "Array", mrbc_class_object);
+
+  mrbc_define_method(vm, mrbc_class_array, "!=", c_array_neq);
+  mrbc_define_method(vm, mrbc_class_array, "count", c_array_size);
+  mrbc_define_method(vm, mrbc_class_array, "length", c_array_size);
+  mrbc_define_method(vm, mrbc_class_array, "size", c_array_size);
+  mrbc_define_method(vm, mrbc_class_array, "+", c_array_plus);
+  mrbc_define_method(vm, mrbc_class_array, "empty?", c_array_empty);
+  mrbc_define_method(vm, mrbc_class_array, "[]", c_array_get);
+  mrbc_define_method(vm, mrbc_class_array, "at", c_array_get);
+  mrbc_define_method(vm, mrbc_class_array, "[]=", c_array_set);
+  mrbc_define_method(vm, mrbc_class_array, "index", c_array_index);
+
+
+  mrbc_define_method(vm, mrbc_class_array, "first", c_array_first);
+  mrbc_define_method(vm, mrbc_class_array, "last", c_array_last);
+  mrbc_define_method(vm, mrbc_class_array, "pop", c_array_pop);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_array.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_array.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_ARRAY_H_
+#define MRBC_SRC_C_ARRAY_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_array(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_hash.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_hash.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,90 @@
+#include <stddef.h>
+
+#include "c_hash.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+
+static void c_hash_size(mrb_vm *vm, mrb_value *v)
+{
+  mrb_value *hash = v->value.obj;
+
+  SET_INT_RETURN(hash->value.obj->value.i);
+}
+
+
+// Hash = []
+static void c_hash_get(mrb_vm *vm, mrb_value *v)
+{
+  mrb_value *hash = v->value.obj->value.obj;
+  int i;
+  int n = hash->value.i;       // hash size
+  mrb_value key = GET_ARG(0);  // search key
+
+  // ptr: 1st entry(key) of hash
+  mrb_value *ptr = &hash[1];
+
+  for( i=0 ; i<n ; i++ ){
+    if( mrbc_eq(ptr, &key) ){
+      SET_RETURN( *(ptr+1) );
+      return;
+    }
+    ptr += 2;
+  }
+
+  SET_NIL_RETURN();
+}
+
+// Hash = []=
+static void c_hash_set(mrb_vm *vm, mrb_value *v)
+{
+  mrb_value *hash = v->value.obj->value.obj;
+  int i;
+  int n = hash[0].value.i;       // hash size
+  mrb_value key = GET_ARG(0);  // search key
+  mrb_value val = GET_ARG(1);  // new value
+
+  mrb_value *ptr = &hash[1];
+  for( i=0 ; i<n ; i++ ){
+    if( mrbc_eq(ptr, &key) ){
+      *(ptr+1) = val;  // Change value
+      return;
+    }
+  }
+
+  // key was not found
+  // add hash entry (key and val)
+  int new_size = (n+1)*2 + 1;
+
+  // use alloc instead of realloc, realloc has some bugs?
+  mrb_value *new_hash = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*new_size);
+  if( new_hash == NULL ) return;  // ENOMEM
+
+  mrb_value *src = &hash[1];
+  mrb_value *dst = &new_hash[1];
+  for( i=0 ; i<n ; i++ ){
+    *dst++ = *src++;  // copy key
+    *dst++ = *src++;  // copy value
+  }
+  new_hash[0].tt = MRB_TT_FIXNUM;
+  new_hash[0].value.i = n+1;
+  *dst++ = key;
+  *dst   = val;
+  mrbc_free(vm, v->value.obj->value.obj);
+  v->value.obj->value.obj = new_hash;
+}
+
+
+void mrbc_init_class_hash(mrb_vm *vm)
+{
+  // Hash
+  mrbc_class_hash = mrbc_class_alloc(vm, "Hash", mrbc_class_object);
+
+  mrbc_define_method(vm, mrbc_class_hash, "size", c_hash_size);
+  mrbc_define_method(vm, mrbc_class_hash, "[]", c_hash_get);
+  mrbc_define_method(vm, mrbc_class_hash, "[]=", c_hash_set);
+
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_hash.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_hash.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_HASH_H_
+#define MRBC_SRC_C_HASH_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_hash(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_numeric.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_numeric.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,141 @@
+#include <stdio.h>
+
+#include "vm_config.h"
+#include "c_numeric.h"
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "console.h"
+
+static void c_fixnum_eq(mrb_vm *vm, mrb_value *v)
+{
+  console_printf("ERROR ==\n");
+}
+
+// Operator %
+static void c_fixnum_mod(mrb_vm *vm, mrb_value *v)
+{
+  int num = GET_INT_ARG(0);
+  SET_INT_RETURN( v->value.i % num );
+}
+
+// Operator <=>
+static void c_fixnum_comp(mrb_vm *vm, mrb_value *v)
+{
+  int num = GET_INT_ARG(0);
+  if(v->value.i > num){
+  SET_INT_RETURN(1);
+  }else if(v->value.i == num){
+  SET_INT_RETURN(0);
+  }else{
+  SET_INT_RETURN(-1);
+  }
+}
+
+// Unary Operator ~; bit operation NOT
+static void c_fixnum_deny(mrb_vm *vm, mrb_value *v)
+{
+  SET_INT_RETURN( (v->value.i + 1) * (-1)  );
+}
+
+
+// Operator &; bit operation AND
+static void c_fixnum_and(mrb_vm *vm, mrb_value *v)
+{
+  int num = GET_INT_ARG(0);
+  SET_INT_RETURN(v->value.i & num);
+}
+
+// x-bit left shift for x
+static int32_t shift(int32_t x, int32_t y)
+{
+  if( y >= 33 ){
+    x = 0;
+  } else if( y >= 0 ){
+    x <<= y;
+  } else if( y > -33 ){
+    x = x >> -y;
+  } else {
+    x = 0;
+  }
+  return x;
+}
+
+// Operator <<; bit operation LEFT_SHIFT
+static void c_fixnum_lshift(mrb_vm *vm, mrb_value *v)
+{
+  int num = GET_INT_ARG(0);
+  SET_INT_RETURN( shift(v->value.i, num) );
+}
+
+// Operator >>; bit operation RIGHT_SHIFT
+static void c_fixnum_rshift(mrb_vm *vm, mrb_value *v)
+{
+  int num = GET_INT_ARG(0);
+  SET_INT_RETURN( shift(v->value.i, -num) );
+}
+
+#if MRBC_USE_STRING
+static void c_fixnum_to_s(mrb_vm *vm, mrb_value *v)
+{
+  int num = v->value.i;
+  int i = 0, j = 0;
+  char buf[10];
+  int sign = 0;
+
+  if( num < 0 ){
+    sign = 1;
+    num = -num;
+  }
+  do {
+    buf[i++] = (num % 10) + '0';
+    num = num / 10;
+  } while( num > 0 );
+  if( sign ){
+    buf[i] = '-';
+  } else {
+    i--;
+  }
+  char *str = (char *)mrbc_alloc(vm, i+2);
+  if( str == NULL ) return;  // ENOMEM
+  while( i>=0 ){
+    str[j++] = buf[i--];
+  }
+  str[j] = 0;
+  v->tt = MRB_TT_STRING;
+  v->value.str = str;
+}
+#endif
+
+
+
+void mrbc_init_class_fixnum(mrb_vm *vm)
+{
+  // Fixnum
+  mrbc_class_fixnum = mrbc_class_alloc(vm, "Fixnum", mrbc_class_object);
+  mrbc_define_method(vm, mrbc_class_fixnum, "==", c_fixnum_eq);
+  mrbc_define_method(vm, mrbc_class_fixnum, "%", c_fixnum_mod);
+  mrbc_define_method(vm, mrbc_class_fixnum, "<=>", c_fixnum_comp);
+  mrbc_define_method(vm, mrbc_class_fixnum, "~", c_fixnum_deny);
+  mrbc_define_method(vm, mrbc_class_fixnum, "&", c_fixnum_and);
+  mrbc_define_method(vm, mrbc_class_fixnum, "<<", c_fixnum_lshift);
+  mrbc_define_method(vm, mrbc_class_fixnum, ">>", c_fixnum_rshift);
+#if MRBC_USE_STRING
+  mrbc_define_method(vm, mrbc_class_fixnum, "to_s", c_fixnum_to_s);
+#endif
+}
+
+
+// Float
+#if MRBC_USE_FLOAT
+
+void mrbc_init_class_float(mrb_vm *vm)
+{
+  // Float
+  mrbc_class_float = mrbc_class_alloc(vm, "Float", mrbc_class_object);
+
+}
+
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_numeric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_numeric.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_NUMERIC_H_
+#define MRBC_SRC_C_NUMERIC_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_fixnum(mrb_vm *vm);
+void mrbc_init_class_float(mrb_vm *vm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_range.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_range.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,42 @@
+#include <stddef.h>
+
+#include "c_range.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "vm.h"
+
+
+mrb_value mrbc_range_new(mrb_vm *vm, mrb_value *v_st, mrb_value *v_ed, int exclude)
+{
+  mrb_value value;
+  value.tt = MRB_TT_RANGE;
+
+  mrb_value *ptr = (mrb_value*)mrbc_alloc(vm, sizeof(mrb_value)*3);
+  if( ptr == NULL ) return value;  // ENOMEM
+
+  if( exclude ){
+    ptr[0].tt = MRB_TT_TRUE;
+  } else {
+    ptr[0].tt = MRB_TT_FALSE;
+  }
+  ptr[1] = *v_st;
+  ptr[2] = *v_ed;
+  value.value.range = ptr;
+
+  return value;
+}
+
+
+
+
+// init class
+void mrbc_init_class_range(mrb_vm *vm)
+{
+  mrbc_class_range = mrbc_class_alloc(vm, "Range", mrbc_class_object);
+
+
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_range.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_range.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,34 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_RANGE_H_
+#define MRBC_SRC_C_RANGE_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_value mrbc_range_new(mrb_vm *vm, mrb_value *v_st, mrb_value *v_ed, int exclude);
+
+void mrbc_init_class_range(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_string.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_string.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,109 @@
+#include <string.h>
+#include "c_string.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "vm.h"
+
+// dupulicate string (clone)
+// returns duplicated string pointer
+char* mrbc_string_dup(mrb_vm *vm, const char *str)
+{
+  int len = strlen((char *)str);
+  char *ptr = (char *)mrbc_alloc(vm, len+1);
+  if( ptr == NULL ) return NULL;  // ENOMEM
+
+  strcpy(ptr, str);
+  return ptr;
+}
+
+// catination string
+// returns new string
+char *mrbc_string_cat(mrb_vm *vm, char *s1, const char *s2)
+{
+  int len1 = strlen(s1);
+  int len2 = strlen(s2);
+  char *ptr = (char *)mrbc_alloc(vm, len1+len2+1);
+  if( ptr == NULL ) return NULL;  // ENOMEM
+
+  strcpy(ptr, s1);
+  strcpy(ptr+len1, s2);
+  return ptr;
+}
+
+// substr
+// returns new string
+static char *mrbc_string_substr(mrb_vm *vm, char *s, int start, int len)
+{
+  char *ptr = (char *)mrbc_alloc(vm, len+1);
+  if( ptr == NULL ) return NULL;  // ENOMEM
+
+  int i;
+  for( i=0 ; i<len ; i++ ){
+    ptr[i] = s[start+i];
+  }
+  ptr[len] = 0;
+  return ptr;
+}
+
+
+// method
+// string size
+static void c_string_size(mrb_vm *vm, mrb_value *v)
+{
+  int cnt = strlen(v->value.str);
+  SET_INT_RETURN( cnt );
+}
+
+
+// method
+// string !=
+static void c_string_neq(mrb_vm *vm, mrb_value *v)
+{
+  if( mrbc_eq(v, v+1) ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+// method
+// string []
+//  string[Fixnum]
+static void c_string_idx_get(mrb_vm *vm, mrb_value *v)
+{
+  int index = GET_INT_ARG(0);
+  char *str = mrbc_string_substr(vm, v->value.str, index, 1);
+  v->value.str = str;
+}
+
+
+// method
+// string to_i
+static void c_string_to_fixnum(mrb_vm *vm, mrb_value *v)
+{
+  char *str = v->value.str;
+  int value = 0;
+  while( *str && *str >= '0' && *str <= '9' ){
+    value *= 10;
+    value += *str - '0';
+    str++;
+  }
+  SET_INT_RETURN(value);
+}
+
+
+
+// init class
+void mrbc_init_class_string(mrb_vm *vm)
+{
+  mrbc_class_string = mrbc_class_alloc(vm, "String", mrbc_class_object);
+
+  mrbc_define_method(vm, mrbc_class_string, "size", c_string_size);
+  mrbc_define_method(vm, mrbc_class_string, "length", c_string_size);
+  mrbc_define_method(vm, mrbc_class_string, "!=", c_string_neq);
+  mrbc_define_method(vm, mrbc_class_string, "to_i", c_string_to_fixnum);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_string.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_string.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,35 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_STRING_H_
+#define MRBC_SRC_C_STRING_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_string(mrb_vm *vm);
+
+char *mrbc_string_dup(mrb_vm *vm, const char *str);
+char *mrbc_string_cat(mrb_vm *vm, char *s1, const char *s2);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_symbol.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_symbol.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,42 @@
+#include "c_symbol.h"
+
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "symbol.h"
+
+static void c_symbol_to_s(mrb_vm *vm, mrb_value *v)
+{
+  v->tt = MRB_TT_STRING;
+
+  const char *sym = symid_to_str(v->value.i);
+  v->value.str = mrbc_string_dup(vm, sym);
+}
+
+static void c_symbol_to_sym(mrb_vm *vm, mrb_value *v)
+{
+  // nothing
+}
+
+static void c_symbol_equal(mrb_vm *vm, mrb_value *v)
+{
+  if( mrbc_eq(v, &GET_ARG(0)) ){
+    SET_TRUE_RETURN();
+  } else {
+    SET_FALSE_RETURN();
+  }
+}
+
+
+void mrbc_init_class_symbol(mrb_vm *vm)
+{
+  // Symbol
+  mrbc_class_symbol = mrbc_class_alloc(vm, "Symbol", mrbc_class_object);
+
+  mrbc_define_method(vm, mrbc_class_symbol, "to_s", c_symbol_to_s);
+  mrbc_define_method(vm, mrbc_class_symbol, "id2name", c_symbol_to_s);
+  mrbc_define_method(vm, mrbc_class_symbol, "to_sym", c_symbol_to_sym);
+  mrbc_define_method(vm, mrbc_class_symbol, "===", c_symbol_equal);
+}
+
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_symbol.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_symbol.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_C_SYMBOL_H_
+#define MRBC_SRC_C_SYMBOL_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_symbol(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/class.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/class.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,263 @@
+/*! @file
+  @brief
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#include "value.h"
+#include "class.h"
+#include "static.h"
+#include "console.h"
+
+#include "c_array.h"
+#include "c_hash.h"
+#include "c_numeric.h"
+#include "c_string.h"
+#include "c_symbol.h"
+#include "c_range.h"
+
+
+
+//================================================================
+/*!@brief
+  find class from a object
+
+  @param  vm
+  @param  obj
+  @return pointer to mrb_class
+*/
+mrb_class *find_class_by_object(mrb_vm *vm, mrb_object *obj)
+{
+  mrb_class *cls = mrbc_class_object;
+  switch( obj->tt ){
+    case MRB_TT_ARRAY:
+      cls = mrbc_class_array;
+      break;
+    case MRB_TT_HASH:
+      cls = mrbc_class_hash;
+      break;
+    case MRB_TT_FIXNUM:
+      cls = mrbc_class_fixnum;
+      break;
+    case MRB_TT_SYMBOL:
+      cls = mrbc_class_symbol;
+      break;
+    case MRB_TT_FALSE:
+      cls = mrbc_class_false;
+      break;
+    case MRB_TT_TRUE:
+      cls = mrbc_class_true;
+      break;
+#if MRBC_USE_FLOAT
+    case MRB_TT_FLOAT:
+      cls = mrbc_class_float;
+      break;
+#endif
+#if MRBC_USE_STRING
+    case MRB_TT_STRING:
+      cls = mrbc_class_string;
+      break;
+#endif
+    default:
+      break;
+  }
+  return cls;
+}
+
+
+
+//================================================================
+/*!@brief
+  find method from
+
+  @param  vm
+  @param  recv
+  @param  sym_id
+  @return
+*/
+mrb_proc *find_method(mrb_vm *vm, mrb_value recv, mrb_sym sym_id)
+{
+  mrb_class *cls = find_class_by_object(vm, &recv);
+
+  while( cls != 0 ) {
+    mrb_proc *proc = cls->procs;
+    while( proc != 0 ) {
+      if( proc->sym_id == sym_id ) {
+        return proc;
+      }
+      proc = proc->next;
+    }
+    cls = cls->super;
+  }
+  return 0;
+}
+
+
+
+void mrbc_define_method(mrb_vm *vm, mrb_class *cls, const char *name, mrb_func_t cfunc)
+{
+  mrb_proc *rproc = mrbc_rproc_alloc(vm, name);
+  rproc->c_func = 1;  // c-func
+  rproc->next = cls->procs;
+  cls->procs = rproc;
+  rproc->func.func = cfunc;
+}
+
+
+
+
+void mrbc_define_method_proc(mrb_vm *vm, mrb_class *cls, mrb_sym sym_id, mrb_proc *rproc)
+{
+  rproc->c_func = 0;
+  rproc->sym_id = sym_id;
+  rproc->next = cls->procs;
+  cls->procs = rproc;
+}
+
+
+
+// Object - puts
+void c_puts(mrb_vm *vm, mrb_value *v)
+{
+  mrb_value *arg0 = v+1;
+  switch( arg0->tt ){
+  case MRB_TT_FIXNUM:
+    console_printf("%d", arg0->value.i);
+    break;
+  case MRB_TT_NIL:
+    console_printf("");
+    break;
+  case MRB_TT_TRUE:
+    console_printf("true");
+    break;
+  case MRB_TT_FALSE:
+    console_printf("false");
+    break;
+#if MRBC_USE_FLOAT
+  case MRB_TT_FLOAT:
+    console_printf("%f", arg0->value.d);
+    break;
+#endif
+#if MRBC_USE_STRING
+  case MRB_TT_STRING:
+    console_printf("%s", arg0->value.str);
+    break;
+#endif
+  case MRB_TT_RANGE:{
+    mrb_value *ptr = arg0->value.range;
+    if( ptr[0].tt == MRB_TT_TRUE ){
+      console_printf("%d...%d", ptr[1].value.i, ptr[2].value.i);
+    } else {
+      console_printf("%d..%d", ptr[1].value.i, ptr[2].value.i);
+    }
+  } break;
+  default:
+    console_printf("Not supported: MRB_TT_XX(%d)", arg0->tt);
+    break;
+  }
+  console_printf("\n");
+}
+
+// Object !=
+void c_object_neq(mrb_vm *vm, mrb_value *v)
+{
+  if( mrbc_eq(v, &GET_ARG(0)) ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+static void mrbc_init_class_object(mrb_vm *vm)
+{
+  // Class
+  mrbc_class_object = mrbc_class_alloc(vm, "Object", 0);
+  // Methods
+  mrbc_define_method(vm, mrbc_class_object, "puts", c_puts);
+  mrbc_define_method(vm, mrbc_class_object, "!=", c_object_neq);
+}
+
+
+// =============== FalseClass
+
+void c_false_ne(mrb_vm *vm, mrb_value *v)
+{
+  mrb_object *arg0 = v+1;
+  if( arg0->tt == MRB_TT_FALSE ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+void c_false_not(mrb_vm *vm, mrb_value *v)
+{
+  SET_TRUE_RETURN();
+}
+
+static void mrbc_init_class_false(mrb_vm *vm)
+{
+  // Class
+  mrbc_class_false = mrbc_class_alloc(vm, "FalseClass", mrbc_class_object);
+  // Methods
+  mrbc_define_method(vm, mrbc_class_false, "!=", c_false_ne);
+  mrbc_define_method(vm, mrbc_class_false, "!", c_false_not);
+}
+
+
+// =============== TrueClass
+
+void c_true_ne(mrb_vm *vm, mrb_value *v)
+{
+  mrb_object *arg0 = v+1;
+  if( arg0->tt == MRB_TT_TRUE ){
+    SET_FALSE_RETURN();
+  } else {
+    SET_TRUE_RETURN();
+  }
+}
+
+void c_true_not(mrb_vm *vm, mrb_value *v)
+{
+  SET_FALSE_RETURN();
+}
+
+
+
+static void mrbc_init_class_true(mrb_vm *vm)
+{
+  // Class
+  mrbc_class_true = mrbc_class_alloc(vm, "TrueClass", mrbc_class_object);
+  // Methods
+  mrbc_define_method(vm, mrbc_class_true, "!=", c_true_ne);
+  mrbc_define_method(vm, mrbc_class_true, "!", c_true_not);
+
+}
+
+
+void mrbc_init_class(void)
+{
+  mrbc_init_class_object(0);
+  mrbc_init_class_false(0);
+  mrbc_init_class_true(0);
+
+  mrbc_init_class_fixnum(0);
+  mrbc_init_class_symbol(0);
+#if MRBC_USE_FLOAT
+  mrbc_init_class_float(0);
+#endif
+#if MRBC_USE_STRING
+  mrbc_init_class_string(0);
+#endif
+  mrbc_init_class_array(0);
+  mrbc_init_class_range(0);
+  mrbc_init_class_hash(0);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/class.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/class.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,35 @@
+/*! @file
+  @brief
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_CLASS_H_
+#define MRBC_SRC_CLASS_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_class *find_class_by_object(struct VM *vm, mrb_object *obj);
+mrb_proc *find_method(struct VM *vm, mrb_value recv, mrb_sym sym_id);
+
+void mrbc_init_class(void);
+void mrbc_define_method(struct VM *vm, mrb_class *cls, const char *name, mrb_func_t func);
+void mrbc_define_method_proc(struct VM *vm, mrb_class *cls, mrb_sym sym_id, mrb_proc *rproc);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/console.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/console.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,211 @@
+/*! @file
+  @brief
+  console I/O module.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include "hal/hal.h"
+#include "console.h"
+
+
+//================================================================
+/*! output string with format
+
+  @param  value		output value
+  @param  align		left(-1) or right(1)
+  @param  w		width
+  @param  base		n base
+  @param  pad		padding character
+*/
+static void format_output_str(const char *value, int align, int w, char pad)
+{
+  if( !value ) return;
+
+  int len = strlen(value);
+  int n_pad = w - len;
+
+  if( align == 1 ) {
+    while( n_pad-- > 0 ) {
+      console_putchar(pad);
+    }
+  }
+  hal_write(1, value, len);
+  while( n_pad-- > 0 ) {
+    console_putchar(pad);
+  }
+}
+
+
+//================================================================
+/*! output int value with format
+
+  @param  value		output value
+  @param  align		left(-1) or right(1)
+  @param  w		width
+  @param  base		n base
+  @param  pad		padding character
+*/
+static void format_output_int(int32_t value, int align, int w, int base, char pad)
+{
+  char buf[21];
+  int sign = 0;
+  int idx = sizeof(buf);
+  buf[--idx] = 0;
+
+  if( value < 0 ) {
+    sign  = -1;
+    value = -value;
+  }
+
+  do {
+    buf[--idx] = "0123456789ABCDEF"[value % base];
+    value /= base;
+  } while( value != 0 && idx != 0 );
+
+  if( sign < 0 && align > 0 && pad == '0' ) {
+    console_putchar('-');	// when "%08d",-12345 then "-0012345"
+    w--;
+  } else if( sign < 0 && idx != 0 ) {
+    buf[--idx] = '-';
+  }
+
+  format_output_str(buf + idx, align, w, pad);
+}
+
+
+//================================================================
+/*! output unsigned int value with format
+
+  @param  value		output value
+  @param  align		left(-1) or right(1)
+  @param  w		width
+  @param  base		n base
+  @param  pad		padding character
+*/
+static void format_output_uint(uint32_t value, int align, int w, int base, char pad)
+{
+  char buf[21];
+  int idx = sizeof(buf);
+  buf[--idx] = 0;
+
+  do {
+    buf[--idx] = "0123456789ABCDEF"[value % base];
+    value /= base;
+  } while( value != 0 && idx != 0 );
+
+  format_output_str(buf + idx, align, w, pad);
+}
+
+
+//================================================================
+/*! output a character
+
+  @param  c	character
+*/
+void console_putchar(char c)
+{
+  hal_write(1, &c, 1);
+}
+
+
+//================================================================
+/*! output string
+
+  @param str	str
+*/
+void console_print(const char *str)
+{
+  hal_write(1, str, strlen(str));
+}
+
+
+//================================================================
+/*! output formatted string
+
+  @param  fmt		format string.
+  @note
+*/
+void console_printf(const char *fmt, ...)
+{
+  va_list params;
+  va_start(params, fmt);
+
+  int c;
+  while((c = *fmt++)) {
+    if( c != '%' ) {
+      console_putchar(c);
+      continue;
+    }
+
+    int  align = 1;	// left(-1) or right(1)
+    char pad   = ' ';	// padding
+    int  w     = 0;	// width
+    while( 1 ) {
+      switch( (c = *fmt++) ) {
+      case '-':
+        align = -1;
+        break;
+
+      case '0':
+        if( pad == ' ' ) {
+          pad = '0';
+          break;
+        }
+	// fall through.
+
+      case '1': case '2': case '3': case '4': case '5':
+      case '6': case '7': case '8': case '9':
+        w = w * 10 + (c - '0');
+        break;
+
+      case '\0':
+	goto L_return;
+
+      default:
+        goto L_exit;
+      }
+    }
+
+L_exit:
+    switch(c) {
+    case 's':
+      format_output_str(va_arg(params, char *), align, w, pad);
+      break;
+
+    case 'd':
+    case 'i':
+      format_output_int(va_arg(params, int), align, w, 10, pad);
+      break;
+
+    case 'u':
+      format_output_uint(va_arg(params, unsigned int), align, w, 10, pad);
+      break;
+
+    case 'X':
+    case 'x':
+      format_output_uint(va_arg(params, unsigned int), align, w, 16, pad);
+      break;
+
+    case 'c':
+      console_putchar(va_arg(params, int));	// ignore "%03c" and others.
+      break;
+
+    default:
+      console_putchar(c);
+    }
+  }
+
+L_return:
+  va_end(params);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/console.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/console.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,30 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_CONSOLE_H_
+#define MRBC_SRC_CONSOLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void console_putchar(const char c);
+void console_print(const char *str);
+void console_printf(const char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/errorcode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/errorcode.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,56 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_ERRORCODE_H_
+#define MRBC_SRC_ERRORCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* no error */
+#define NO_ERROR 0
+
+/* unknown */
+#define UNKNOWN_ERROR 0x0000ffff
+
+/* load_file */
+#define LOAD_FILE_ERROR (0x0100 << 16)
+#define LOAD_FILE_ERROR_MALLOC (LOAD_FILE_ERROR | 0x0001)
+#define LOAD_FILE_ERROR_NOFILE (LOAD_FILE_ERROR | 0x0002)
+
+#define LOAD_FILE_HEADER_ERROR (0x0101 << 16)
+#define LOAD_FILE_HEADER_ERROR_RITE (LOAD_FILE_HEADER_ERROR) | 0x0001)
+#define LOAD_FILE_HEADER_ERROR_VERSION (LOAD_FILE_HEADER_ERROR | 0x0002)
+#define LOAD_FILE_HEADER_ERROR_CRC (LOAD_FILE_HEADER_ERROR | 0x0003)
+#define LOAD_FILE_HEADER_ERROR_MATZ (LOAD_FILE_HEADER_ERROR | 0x0004)
+
+#define LOAD_FILE_IREP_ERROR (0x0102 << 16)
+#define LOAD_FILE_IREP_ERROR_IREP (LOAD_FILE_IREP_ERROR | 0x0001)
+#define LOAD_FILE_IREP_ERROR_VERSION (LOAD_FILE_IREP_ERROR | 0x0002)
+#define LOAD_FILE_IREP_ERROR_ALLOCATION (LOAD_FILE_IREP_ERROR | 0x0003)
+
+/* VM execution */
+#define VM_EXEC_ERROR (0x1000 << 16)
+#define VM_EXEC_STATIC_OVWEFLOW_VM (VM_EXEC_ERROR | 0x0001)
+#define VM_EXEC_STATIC_OVWEFLOW_IREP (VM_EXEC_ERROR | 0x0002)
+#define VM_EXEC_STATIC_OVWEFLOW_CALLINFO (VM_EXEC_ERROR | 0x0003)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/global.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/global.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,98 @@
+
+#include "value.h"
+#include "static.h"
+#include "vm_config.h"
+
+/*
+
+  GLobal objects are stored in 'mrbc_global' array.
+  'mrbc_global' array is decending order by sym_id.
+  In case of searching a global object, binary search is used.
+  In case of adding a global object, insertion sort is used.
+
+*/
+
+/* search */
+static int search_global_object(mrb_sym sym_id)
+{
+  int left = 0, right = MAX_GLOBAL_OBJECT_SIZE-1;
+  while( left <= right ){
+    int mid = (left+right)/2;
+    if( mrbc_global[mid].sym_id == sym_id ) return mid;
+    if( mrbc_global[mid].sym_id < sym_id ){
+      right = mid - 1;
+    } else {
+      left = mid + 1;
+    }
+  }
+  return -1;
+}
+
+static int search_const(mrb_sym sym_id) {
+  int left = 0, right = MAX_CONST_COUNT-1;
+  while (left <= right) {
+    int mid = (left + right) / 2;
+    if ( mrbc_const[mid].sym_id == sym_id ) return mid;
+    if ( mrbc_const[mid].sym_id < sym_id ) {
+      right = mid - 1;
+    } else {
+      left = mid + 1;
+    }
+  }
+  return -1;
+}
+
+/* add */
+void global_object_add(mrb_sym sym_id, mrb_object *obj)
+{
+  int index = search_global_object(sym_id);
+  if( index == -1 ){
+    index = MAX_GLOBAL_OBJECT_SIZE-1;
+    while( index > 0 && mrbc_global[index].sym_id < sym_id ){
+      mrbc_global[index] = mrbc_global[index-1];
+      index--;
+    }
+  }
+  mrbc_global[index].sym_id = sym_id;
+  mrbc_global[index].obj = *obj;
+}
+
+void const_add(mrb_sym sym_id, mrb_object *obj)
+{
+  int index = search_const(sym_id);
+  if( index == -1 ){
+    index = MAX_CONST_COUNT-1;
+    while(index > 0 && mrbc_const[index].sym_id < sym_id ){
+      mrbc_const[index] = mrbc_const[index-1];
+      index--;
+    }
+  }
+  mrbc_const[index].sym_id = sym_id;
+  mrbc_const[index].obj = *obj;
+}
+
+/* get */
+mrb_object global_object_get(mrb_sym sym_id)
+{
+  int index = search_global_object(sym_id);
+  if( index >= 0 ){
+    return mrbc_global[index].obj;
+  } else {
+    /* nil */
+    mrb_object obj;
+    obj.tt = MRB_TT_FALSE;
+    return obj;
+  }
+}
+
+mrb_object const_get(mrb_sym sym_id) {
+  int index = search_const(sym_id);
+  if (index >= 0){
+    return mrbc_const[index].obj;
+  } else {
+    mrb_object obj;
+    obj.tt = MRB_TT_FALSE;
+    return obj;
+  }
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/global.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/global.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,45 @@
+/*! @file
+  @brief
+  Manage global objects.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_GLOBAL_H_
+#define MRBC_SRC_GLOBAL_H_
+
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OBJECT_WITH_SYMBOL\
+  mrb_sym sym_id;\
+  mrb_object obj
+
+typedef struct GLOBAL_OBJECT {
+  OBJECT_WITH_SYMBOL;
+} mrb_globalobject;
+
+typedef struct CONST_OBJECT {
+  OBJECT_WITH_SYMBOL;
+} mrb_constobject;
+
+void global_object_add(mrb_sym sym_id, mrb_object *obj);
+mrb_object global_object_get(mrb_sym sym_id);
+
+void const_add(mrb_sym sym_id, mrb_object *obj);
+mrb_object const_get(mrb_sym sym_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/hal/hal.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/hal/hal.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,66 @@
+/*! @file
+  @brief
+  Realtime multitask monitor for mruby/c
+  Hardware abstraction layer
+        for PSoC5LP
+
+  <pre>
+  Copyright (C) 2016 Kyushu Institute of Technology.
+  Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+  </pre>
+*/
+
+#ifndef MRBC_SRC_HAL_H_
+#define MRBC_SRC_HAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* DON'T USE TIMER */
+#define MRBC_NO_TIMER 1
+
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+
+
+/***** Local headers ********************************************************/
+/***** Constant values ******************************************************/
+/***** Macros ***************************************************************/
+extern void wait_ms(int tm);
+
+#ifndef MRBC_NO_TIMER
+# define hal_init()        ((void)0)
+# define hal_enable_irq()  CyGlobalIntEnable
+# define hal_disable_irq() CyGlobalIntDisable
+# define hal_idle_cpu()    CyPmAltAct(PM_SLEEP_TIME_NONE, \
+                                      PM_SLEEP_SRC_CTW | PM_SLEEP_SRC_PICU)
+
+#else // MRBC_NO_TIMER
+# define hal_init()        ((void)0)
+# define hal_enable_irq()  ((void)0)
+# define hal_disable_irq() ((void)0)
+# define hal_idle_cpu()    (wait_ms(1), mrbc_tick())
+
+#endif
+
+
+/***** Typedefs *************************************************************/
+/***** Global variables *****************************************************/
+/***** Function prototypes **************************************************/
+int hal_write(int fd, const void *buf, size_t nbytes);
+int hal_flush(int fd);
+
+
+/***** Inline functions *****************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ifndef MRBC_HAL_H_
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/load.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/load.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,282 @@
+/*! @file
+  @brief
+  mruby bytecode loader.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "vm.h"
+#include "vm_config.h"
+#include "load.h"
+#include "errorcode.h"
+#include "static.h"
+#include "value.h"
+
+
+//================================================================
+/*!@brief
+  Parse header section.
+
+  @param  vm    A pointer of VM.
+  @param  pos	A pointer of pointer of RITE header.
+  @return int	zero if no error.
+
+  <pre>
+  Structure
+   "RITE"	identifier
+   "0003"	version
+   0000		CRC
+   0000_0000	total size
+   "MATZ"	compiler name
+   "0000"	compiler version
+  </pre>
+*/
+static int load_header(struct VM *vm, const uint8_t **pos)
+{
+  const uint8_t *p = *pos;
+
+  if( memcmp(p + 4, "0003", 4) != 0 ) {
+    vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
+    return -1;
+  }
+
+  /* Ignore CRC */
+
+  /* Ignore size */
+
+  if( memcmp(p + 14, "MATZ", 4) != 0 ) {
+    vm->error_code = LOAD_FILE_HEADER_ERROR_MATZ;
+    return -1;
+  }
+  if( memcmp(p + 18, "0000", 4) != 0 ) {
+    vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
+    return -1;
+  }
+
+  *pos += 22;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Parse IREP section.
+
+  @param  vm    A pointer of VM.
+  @param  pos	A pointer of pointer of IREP section.
+  @return int	zero if no error.
+
+  <pre>
+  Structure
+   "IREP"	section identifier
+   0000_0000	section size
+   "0000"	rite version
+
+   (loop n of child irep bellow)
+   0000_0000	record size
+   0000		n of local variable
+   0000		n of register
+   0000		n of child irep
+
+   0000_0000	n of byte code  (ISEQ BLOCK)
+   ...		byte codes
+
+   0000_0000	n of pool	(POOL BLOCK)
+   (loop n of pool)
+     00		type
+     0000	length
+     ...	pool data
+
+   0000_0000	n of symbol	(SYMS BLOCK)
+   (loop n of symbol)
+     0000	length
+     ...	symbol data
+  </pre>
+*/
+static int load_irep(struct VM *vm, const uint8_t **pos)
+{
+  const uint8_t *p = *pos;
+  p += 4;
+  int section_size = bin_to_uint32(p);
+  p += 4;
+
+  if( memcmp(p, "0000", 4) != 0 ) {
+    vm->error_code = LOAD_FILE_IREP_ERROR_VERSION;
+    return -1;
+  }
+  p += 4;
+
+  int cnt = 0;
+  while( cnt < section_size ) {
+    cnt += bin_to_uint32(p) + 8;
+    p += 4;
+
+    // new irep
+    mrb_irep *irep = new_irep(vm);
+    if( irep == 0 ) {
+      vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
+      return -1;
+    }
+
+    // add irep into vm->irep (at tail)
+    // TODO: Optimize this process
+    if( vm->irep == 0 ) {
+      vm->irep = irep;
+    } else {
+      mrb_irep *p = vm->irep;
+      while( p->next != 0 ) {
+        p = p->next;
+      }
+      p->next = irep;
+    }
+    irep->next = 0;
+
+    // nlocals,nregs,rlen
+    irep->nlocals = bin_to_uint16(p);  p += 2;
+    irep->nregs = bin_to_uint16(p);    p += 2;
+    irep->rlen = bin_to_uint16(p);     p += 2;
+    irep->ilen = bin_to_uint32(p);     p += 4;
+
+    // padding
+    p += (-(p - *pos + 2) & 0x03);  // +2 = (RITE(22) + IREP(12)) & 0x03
+
+    // ISEQ (code) BLOCK
+    irep->code = (uint8_t *)p;
+    p += irep->ilen * 4;
+
+    // POOL BLOCK
+    irep->ptr_to_pool = 0;
+    int plen = bin_to_uint32(p);    p += 4;
+    int i;
+    for( i=0 ; i<plen ; i++ ){
+      int tt = (int)*p++;
+      int obj_size = bin_to_uint16(p);   p += 2;
+      mrb_object *ptr = mrbc_obj_alloc(vm, MRB_TT_FALSE);
+      if( ptr == 0 ){
+        vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
+	return -1;
+      }
+      switch( tt ){
+#if MRBC_USE_STRING
+        case 0: { // IREP_TT_STRING
+          ptr->tt = MRB_TT_STRING;
+	  ptr->value.str = (char*)p;
+        } break;
+#endif
+        case 1: { // IREP_TT_FIXNUM
+          char buf[obj_size+1];
+          memcpy(buf, p, obj_size);
+          buf[obj_size] = '\0';
+          ptr->tt = MRB_TT_FIXNUM;
+          ptr->value.i = atoi(buf);
+        } break;
+#if MRBC_USE_FLOAT
+        case 2: { // IREP_TT_FLOAT
+          char buf[obj_size+1];
+          memcpy(buf, p, obj_size);
+          buf[obj_size] = '\0';
+          ptr->tt = MRB_TT_FLOAT;
+          ptr->value.d = atof(buf);
+        } break;
+#endif
+        default:
+          break;
+      }
+      if( irep->ptr_to_pool == 0 ){
+        irep->ptr_to_pool = ptr;
+      } else {
+        mrb_object *pp = irep->ptr_to_pool;
+        while( pp->next != 0 ) pp = pp->next;
+        pp->next = ptr;
+      }
+      p += obj_size;
+    }
+
+    // SYMS BLOCK
+    irep->ptr_to_sym = (uint8_t*)p;
+    int slen = bin_to_uint32(p);    p += 4;
+    for( i=0 ; i<slen ; i++ ){
+      int s = bin_to_uint16(p);     p += 2;
+      p += s+1;
+    }
+  }
+
+  /* TODO: size */
+  *pos += section_size;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Parse LVAR section.
+
+  @param  vm    A pointer of VM.
+  @param  pos	A pointer of pointer of LVAR section.
+  @return int	zero if no error.
+*/
+static int load_lvar(struct VM *vm, const uint8_t **pos)
+{
+  const uint8_t *p = *pos;
+
+  /* size */
+  *pos += bin_to_uint32(p+4);
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Setup mrb program
+
+  @param  vm    A pointer of VM.
+  @return int	zero if no error.
+*/
+int load_mrb(struct VM *vm)
+{
+  int ret = -1;
+  const uint8_t *pos = vm->mrb;
+
+  if( memcmp(pos, "RITE", 4) == 0 ) {
+    ret = load_header(vm, &pos);
+  }
+  while( ret == 0 ) {
+    if( memcmp(pos, "IREP", 4) == 0 ) {
+      ret = load_irep(vm, &pos);
+    }
+    else if( memcmp(pos, "LVAR", 4) == 0 ) {
+      ret = load_lvar(vm, &pos);
+    }
+    else if( memcmp(pos, "END\0", 4) == 0 ) {
+      break;
+    }
+  }
+
+  return ret;
+}
+
+
+//================================================================
+/*!@brief
+
+
+  @param  vm    A pointer of VM.
+  @param  ptr	A pointer of RITE (.mrb) code.
+
+*/
+int loca_mrb_array(struct VM *vm, const uint8_t *ptr)
+{
+  vm->mrb = ptr;
+  return load_mrb(vm);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/load.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/load.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+  mruby bytecode loader.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_LOAD_H_
+#define MRBC_SRC_LOAD_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int loca_mrb_array(struct VM *vm, const uint8_t *ptr);
+int load_mrb(struct VM *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/mrubyc.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/mrubyc.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,27 @@
+/*! @file
+  @brief
+  Include at once the necessary header files for user program.
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_MRUBYC_H_
+#define MRBC_SRC_MRUBYC_H_
+
+#include "errorcode.h"
+#include "vm.h"
+#include "value.h"
+#include "static.h"
+#include "alloc.h"
+#include "class.h"
+#include "load.h"
+#include "rrt0.h"
+
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/opcode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/opcode.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,102 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_OPCODE_H_
+#define MRBC_SRC_OPCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define GET_OPCODE(code)            ((code) & 0x7f)
+#define GETARG_A(code)              (((code) >> 23) & 0x1ff)
+#define GETARG_B(code)              (((code) >> 14) & 0x1ff)
+#define GETARG_C(code)              (((code) >>  7) & 0x7f)
+#define GETARG_Ax(code)             (((code) >>  7) & 0x1ffffff)
+
+#define GETARG_b(code)              GETARG_UNPACK_b(code,14,2)
+
+#define GETARG_UNPACK_b(i,n1,n2)    ((((code)) >> (7+(n2))) & (((1<<(n1))-1)))
+
+
+#define MAXARG_Bx                   (0xffff)
+#define MAXARG_sBx                  (MAXARG_Bx>>1)
+#define GETARG_Bx(code)             (((code) >>  7) & 0xffff)
+#define GETARG_sBx(code)            (GETARG_Bx(code)-MAXARG_sBx)
+#define GETARG_C(code)              (((code) >>  7) & 0x7f)
+
+
+//================================================================
+/*!@brief
+
+*/
+enum OPCODE {
+  OP_NOP       = 0x00,
+  OP_MOVE      = 0x01,
+  OP_LOADL     = 0x02,
+  OP_LOADI     = 0x03,
+  OP_LOADSYM   = 0x04,
+  OP_LOADNIL   = 0x05,
+  OP_LOADSELF  = 0x06,
+  OP_LOADT     = 0x07,
+  OP_LOADF     = 0x08,
+  OP_GETGLOBAL = 0x09,
+  OP_SETGLOBAL = 0x0a,
+
+  OP_GETCONST  = 0x11,
+  OP_SETCONST  = 0x12,
+
+  OP_JMP       = 0x17,
+  OP_JMPIF     = 0x18,
+  OP_JMPNOT    = 0x19,
+  OP_SEND      = 0x20,
+
+  OP_ENTER     = 0x26,
+
+  OP_RETURN    = 0x29,
+
+  OP_ADD       = 0x2c,
+  OP_ADDI      = 0x2d,
+  OP_SUB       = 0x2e,
+  OP_SUBI      = 0x2f,
+  OP_MUL       = 0x30,
+  OP_DIV       = 0x31,
+  OP_EQ        = 0x32,
+  OP_LT        = 0x33,
+  OP_LE        = 0x34,
+  OP_GT        = 0x35,
+  OP_GE        = 0x36,
+  OP_ARRAY     = 0x37,
+
+  OP_STRING    = 0x3d,
+
+  OP_HASH      = 0x3f,
+  OP_LAMBDA    = 0x40,
+  OP_RANGE     = 0x41,
+
+  OP_CLASS     = 0x43,
+
+  OP_METHOD    = 0x46,
+
+  OP_TCLASS    = 0x48,
+
+  OP_STOP      = 0x4a,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/rrt0.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/rrt0.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,574 @@
+/*! @file
+  @brief
+  Realtime multitask monitor for mruby/c
+
+  <pre>
+  Copyright (C) 2016 Kyushu Institute of Technology.
+  Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+  </pre>
+*/
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+
+/***** Local headers ********************************************************/
+#include "alloc.h"
+#include "static.h"
+#include "load.h"
+#include "class.h"
+#include "vm.h"
+#include "rrt0.h"
+#include "hal/hal.h"
+
+
+/***** Constat values *******************************************************/
+const int TIMESLICE_TICK = 10; // 10 * 1ms(HardwareTimer)  255 max
+
+
+/***** Macros ***************************************************************/
+/***** Typedefs *************************************************************/
+/***** Function prototypes **************************************************/
+/***** Local variables ******************************************************/
+static MrbcTcb *q_domant_;
+static MrbcTcb *q_ready_;
+static MrbcTcb *q_waiting_;
+static MrbcTcb *q_suspended_;
+static volatile uint32_t tick_;
+
+
+/***** Global variables *****************************************************/
+/***** Signal catching functions ********************************************/
+/***** Local functions ******************************************************/
+
+//================================================================
+/*! Insert to task queue
+
+  @param        Pointer of target TCB
+
+  引数で指定されたタスク(TCB)を、状態別Queueに入れる。
+  TCBはフリーの状態でなければならない。(別なQueueに入っていてはならない)
+  Queueはpriority_preemption順にソート済みとなる。
+  挿入するTCBとQueueに同じpriority_preemption値がある場合は、同値の最後に挿入される。
+
+ */
+static void q_insert_task(MrbcTcb *p_tcb)
+{
+  MrbcTcb **pp_q;
+
+  switch( p_tcb->state ) {
+  case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
+  case TASKSTATE_READY:
+  case TASKSTATE_RUNNING: pp_q   = &q_ready_; break;
+  case TASKSTATE_WAITING: pp_q   = &q_waiting_; break;
+  case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
+  default:
+    assert(!"Wrong task state.");
+    return;
+  }
+
+  // case insert on top.
+  if((*pp_q == NULL) ||
+     (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
+    p_tcb->next = *pp_q;
+    *pp_q       = p_tcb;
+    assert(p_tcb->next != p_tcb);
+    return;
+  }
+
+  // find insert point in sorted linked list.
+  MrbcTcb *p = *pp_q;
+  while( 1 ) {
+    if((p->next == NULL) ||
+       (p_tcb->priority_preemption < p->next->priority_preemption)) {
+      p_tcb->next = p->next;
+      p->next     = p_tcb;
+      assert(p->next != p);
+      return;
+    }
+
+    p = p->next;
+  }
+}
+
+
+//================================================================
+/*! Delete from task queue
+
+  @param        Pointer of target TCB
+
+  Queueからタスク(TCB)を取り除く。
+
+ */
+static void q_delete_task(MrbcTcb *p_tcb)
+{
+  MrbcTcb **pp_q;
+
+  switch( p_tcb->state ) {
+  case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
+  case TASKSTATE_READY:
+  case TASKSTATE_RUNNING: pp_q   = &q_ready_; break;
+  case TASKSTATE_WAITING: pp_q   = &q_waiting_; break;
+  case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
+  default:
+    assert(!"Wrong task state.");
+    return;
+  }
+
+  if( *pp_q == NULL ) return;
+  if( *pp_q == p_tcb ) {
+    *pp_q       = p_tcb->next;
+    p_tcb->next = NULL;
+    return;
+  }
+
+  MrbcTcb *p = *pp_q;
+  while( p ) {
+    if( p->next == p_tcb ) {
+      p->next     = p_tcb->next;
+      p_tcb->next = NULL;
+      return;
+    }
+
+    p = p->next;
+  }
+}
+
+
+//================================================================
+/*! Find requested task
+
+  @param        Pointer of vm
+  @return       Pointer of MrbcTcb. zero is not found.
+ */
+static inline MrbcTcb* find_requested_task(mrb_vm *vm)
+{
+  MrbcTcb *tcb;
+
+  for( tcb = q_ready_; tcb != NULL; tcb = tcb->next ) {
+    if( tcb->vm == vm ) break;
+  }
+
+  return tcb;
+}
+
+
+//================================================================
+/*! 一定時間停止(cruby互換)
+
+*/
+static void c_sleep(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  switch( v[1].tt ) {
+  case MRB_TT_FIXNUM:
+    mrbc_sleep_ms(tcb, GET_INT_ARG(0) * 1000);
+    break;
+
+  case MRB_TT_FLOAT:
+    mrbc_sleep_ms(tcb, (uint32_t)(GET_FLOAT_ARG(0) * 1000));
+    break;
+
+  default:
+
+    // TODO 引数なしの場合は永久停止
+    break;
+  }
+}
+
+
+//================================================================
+/*! 一定時間停止(ms単位)
+
+*/
+static void c_sleep_ms(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  mrbc_sleep_ms(tcb, GET_INT_ARG(0));
+}
+
+
+//================================================================
+/*! 実行権を手放す
+
+*/
+static void c_relinquish(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  mrbc_relinquish(tcb);
+}
+
+
+//================================================================
+/*! プライオリティー変更
+
+*/
+static void c_change_priority(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  mrbc_change_priority(tcb, GET_INT_ARG(0));
+}
+
+
+//================================================================
+/*! 実行停止
+
+*/
+static void c_suspend_task(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  mrbc_suspend_task(tcb);
+}
+
+
+//================================================================
+/*! 実行再開
+
+*/
+static void c_resume_task(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  // TODO: 未デバグ。引数で与えられたTCBのタスクを実行再開する。
+  mrbc_resume_task(tcb);
+}
+
+
+//================================================================
+/*! TCBを得る
+
+*/
+static void c_get_tcb(mrb_vm *vm, mrb_value *v)
+{
+  MrbcTcb *tcb = find_requested_task(vm);
+
+  if( tcb == NULL ) return;
+
+  // TODO: 未実装。TCBポインタをオブジェクトとして返す。
+}
+
+
+/***** Global functions *****************************************************/
+
+//================================================================
+/*! Tick timer interrupt handler.
+
+*/
+void mrbc_tick(void)
+{
+  MrbcTcb *tcb;
+  int flag_preemption = 0;
+
+  tick_++;
+
+  // 実行中タスクのタイムスライス値を減らす
+  tcb = q_ready_;
+  if((tcb != NULL) &&
+     (tcb->state == TASKSTATE_RUNNING) &&
+     (tcb->timeslice > 0)) {
+    tcb->timeslice--;
+    if( tcb->timeslice == 0 ) tcb->vm->flag_preemption = 1;
+  }
+
+  // 待ちタスクキューから、ウェイクアップすべきタスクを探す
+  tcb = q_waiting_;
+  while( tcb != NULL ) {
+    MrbcTcb *t = tcb;
+    tcb = tcb->next;
+
+    if( t->wakeup_tick == tick_ ) {
+      q_delete_task(t);
+      t->state     = TASKSTATE_READY;
+      t->timeslice = TIMESLICE_TICK;
+      q_insert_task(t);
+      flag_preemption = 1;
+    }
+  }
+
+  if( flag_preemption ) {
+    tcb = q_ready_;
+    while( tcb != NULL ) {
+      if( tcb->state == TASKSTATE_RUNNING ) tcb->vm->flag_preemption = 1;
+      tcb = tcb->next;
+    }
+  }
+}
+
+
+//================================================================
+/*! initialize
+
+*/
+void mrbc_init(void)
+{
+  mrbc_init_alloc();
+  init_static();
+  hal_init();
+
+
+  // TODO 関数呼び出しが、c_XXX => mrbc_XXX の daisy chain になっている。
+  //      不要な複雑さかもしれない。要リファクタリング。
+  mrbc_define_method(0, mrbc_class_object, "sleep",           c_sleep);
+  mrbc_define_method(0, mrbc_class_object, "sleep_ms",        c_sleep_ms);
+  mrbc_define_method(0, mrbc_class_object, "relinquish",      c_relinquish);
+  mrbc_define_method(0, mrbc_class_object, "change_priority", c_change_priority);
+  mrbc_define_method(0, mrbc_class_object, "suspend_task",    c_suspend_task);
+  mrbc_define_method(0, mrbc_class_object, "resume_task",     c_resume_task);
+}
+
+
+//================================================================
+/*! specify running VM code.
+
+  @param        vm_code pointer of VM byte code.
+  @param        tcb	Task control block with parameter, or NULL.
+  @retval       Pointer of MrbcTcb.
+  @retval       NULL is error.
+
+*/
+MrbcTcb* mrbc_create_task(const uint8_t *vm_code, MrbcTcb *tcb)
+{
+  // allocate Task Control Block
+  if( tcb == NULL ) {
+    tcb = (MrbcTcb*)mrbc_raw_alloc( sizeof(MrbcTcb) );
+    if( tcb == NULL ) return NULL;	// ENOMEM
+
+    static const MrbcTcb init_val = MRBC_TCB_INITIALIZER;
+    *tcb = init_val;
+  }
+  tcb->timeslice           = TIMESLICE_TICK;
+  tcb->priority_preemption = tcb->priority;
+
+  // assign VM on TCB
+  if( tcb->state != TASKSTATE_DOMANT ) {
+    tcb->vm = vm_open();
+    if( !tcb->vm ) return 0;    // error. can't open VM.
+				// NOTE: memory leak MrbcTcb. but ignore.
+
+    loca_mrb_array(tcb->vm, vm_code);
+    vm_boot(tcb->vm);
+  }
+
+  hal_disable_irq();
+  q_insert_task(tcb);
+  hal_enable_irq();
+
+  return tcb;
+}
+
+
+//================================================================
+/*! execute
+
+*/
+int mrbc_run(void)
+{
+  while( 1 ) {
+    MrbcTcb *tcb = q_ready_;
+    if( tcb == NULL ) {
+      // 実行すべきタスクなし
+      hal_idle_cpu();
+      continue;
+    }
+
+    // 実行開始
+    tcb->state = TASKSTATE_RUNNING;
+    int res = 0;
+
+#ifndef MRBC_NO_TIMER
+    tcb->vm->flag_preemption = 0;
+    res = vm_run(tcb->vm);
+
+#else
+    while( tcb->timeslice > 0 ) {
+      tcb->vm->flag_preemption = 1;
+      res = vm_run(tcb->vm);
+      tcb->timeslice--;
+      if( res < 0 ) break;
+      if( tcb->state != TASKSTATE_RUNNING ) break;
+    }
+    mrbc_tick();
+#endif /* ifndef MRBC_NO_TIMER */
+
+    // タスク終了?
+    if( res < 0 ) {
+      hal_disable_irq();
+      q_delete_task(tcb);
+      tcb->state = TASKSTATE_DOMANT;
+      q_insert_task(tcb);
+      hal_enable_irq();
+      vm_close(tcb->vm);
+      tcb->vm = 0;
+
+      if( q_ready_ == NULL && q_waiting_ == NULL &&
+          q_suspended_ == NULL ) break;
+      continue;
+    }
+
+    // タスク切り替え
+    hal_disable_irq();
+    if( tcb->state == TASKSTATE_RUNNING ) {
+      tcb->state = TASKSTATE_READY;
+
+      // タイムスライス終了?
+      if( tcb->timeslice == 0 ) {
+        q_delete_task(tcb);
+        tcb->timeslice = TIMESLICE_TICK;
+        q_insert_task(tcb); // insert task on queue last.
+      }
+    }
+    hal_enable_irq();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*! 実行一時停止
+
+*/
+void mrbc_sleep_ms(MrbcTcb *tcb, uint32_t ms)
+{
+  hal_disable_irq();
+  q_delete_task(tcb);
+  tcb->timeslice   = 0;
+  tcb->state       = TASKSTATE_WAITING;
+  tcb->wakeup_tick = tick_ + ms;
+  q_insert_task(tcb);
+  hal_enable_irq();
+
+  tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行権を手放す
+
+*/
+void mrbc_relinquish(MrbcTcb *tcb)
+{
+  tcb->timeslice           = 0;
+  tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! プライオリティーの変更
+  TODO: No check, yet.
+*/
+void mrbc_change_priority(MrbcTcb *tcb, int priority)
+{
+  tcb->priority            = (uint8_t)priority;
+  tcb->priority_preemption = (uint8_t)priority;
+  tcb->timeslice           = 0;
+  tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行停止
+
+*/
+void mrbc_suspend_task(MrbcTcb *tcb)
+{
+  hal_disable_irq();
+  q_delete_task(tcb);
+  tcb->state = TASKSTATE_SUSPENDED;
+  q_insert_task(tcb);
+  hal_enable_irq();
+
+  tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行再開
+
+*/
+void mrbc_resume_task(MrbcTcb *tcb)
+{
+  hal_disable_irq();
+
+  MrbcTcb *t = q_ready_;
+  while( t != NULL ) {
+    if( t->state == TASKSTATE_RUNNING ) t->vm->flag_preemption = 1;
+    t = t->next;
+  }
+
+  q_delete_task(tcb);
+  tcb->state = TASKSTATE_READY;
+  q_insert_task(tcb);
+  hal_enable_irq();
+}
+
+
+#ifdef MRBC_DEBUG
+#include "console.h"
+
+//================================================================
+/*! DEBUG print queue
+
+ */
+void pq(MrbcTcb *p_tcb)
+{
+  MrbcTcb *p;
+
+  p = p_tcb;
+  while( p != NULL ) {
+    console_printf("%08x ", (int)((uint64_t)p & 0xffffffff));
+    p = p->next;
+  }
+  console_printf("\n");
+
+  p = p_tcb;
+  while( p != NULL ) {
+    console_printf(" pri: %2d ", p->priority_preemption);
+    p = p->next;
+  }
+  console_printf("\n");
+
+  p = p_tcb;
+  while( p != NULL ) {
+    console_printf(" nx:%04x ", (int)((uint64_t)p->next & 0xffff));
+    p = p->next;
+  }
+  console_printf("\n");
+}
+
+
+void pqall(void)
+{
+  //  console_printf("<<<<< DOMANT >>>>>\n");
+  //  pq(q_domant_);
+  console_printf("<<<<< READY >>>>>\n");
+  pq(q_ready_);
+  console_printf("<<<<< WAITING >>>>>\n");
+  pq(q_waiting_);
+  console_printf("<<<<< SUSPENDED >>>>>\n");
+  pq(q_suspended_);
+}
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/rrt0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/rrt0.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,83 @@
+/*! @file
+  @brief
+  Realtime multitask monitor for mruby/c
+
+  <pre>
+  Copyright (C) 2016 Kyushu Institute of Technology.
+  Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+  </pre>
+*/
+
+#ifndef MRBC_SRC_RRT0_H_
+#define MRBC_SRC_RRT0_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+#include <stdint.h>
+
+/***** Local headers ********************************************************/
+/***** Constant values ******************************************************/
+
+//================================================
+/*!@brief
+  Task state
+*/
+enum MrbcTaskState {
+  TASKSTATE_DOMANT    = 0x00,
+  TASKSTATE_READY     = 0x01,
+  TASKSTATE_RUNNING   = 0x03,
+  TASKSTATE_WAITING   = 0x04,
+  TASKSTATE_SUSPENDED = 0x08,
+};
+
+
+/***** Macros ***************************************************************/
+/***** Typedefs *************************************************************/
+
+//================================================
+/*!@brief
+  Task control block
+*/
+struct VM;
+typedef volatile struct st_MrbcTcb {
+  volatile struct st_MrbcTcb *next;
+  struct VM               *vm;
+  uint8_t                  priority;
+  uint8_t                  priority_preemption;
+  uint8_t                  timeslice;
+  uint8_t                  state; //!< enum MrbcTaskState
+  union {
+    uint32_t wakeup_tick;
+  };
+} MrbcTcb;
+
+#define MRBC_TCB_INITIALIZER { 0, 0, 128, 128, 0, TASKSTATE_READY }
+
+
+/***** Global variables *****************************************************/
+/***** Function prototypes **************************************************/
+void mrbc_tick(void);
+void mrbc_init(void);
+MrbcTcb *mrbc_create_task(const uint8_t *vm_code, MrbcTcb *tcb);
+int mrbc_run(void);
+void mrbc_sleep_ms(MrbcTcb *tcb, uint32_t ms);
+void mrbc_relinquish(MrbcTcb *tcb);
+void mrbc_change_priority(MrbcTcb *tcb, int priority);
+void mrbc_suspend_task(MrbcTcb *tcb);
+void mrbc_resume_task(MrbcTcb *tcb);
+
+
+/***** Inline functions *****************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ifndef MRBC_RRT0_H_
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/static.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/static.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,69 @@
+/*! @file
+  @brief
+  Declare static data.
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+  </pre>
+*/
+
+#include "static.h"
+#include "vm_config.h"
+#include "class.h"
+#include "symbol.h"
+
+/* Static Variables */
+/* VM contains regs, stack, PC, and so on */
+mrb_vm mrbc_vm[MAX_VM_COUNT];
+
+//static mrb_object mrbc_object[MAX_OBJECT_COUNT];
+//mrb_object *mrbc_pool_object;
+
+mrb_constobject mrbc_const[MAX_CONST_COUNT];
+
+mrb_globalobject mrbc_global[MAX_GLOBAL_OBJECT_SIZE];
+
+/* Class Tree */
+mrb_class *mrbc_class_object;
+
+/* Classes */
+mrb_class *mrbc_class_false;
+mrb_class *mrbc_class_true;
+mrb_class *mrbc_class_nil;
+mrb_class *mrbc_class_array;
+mrb_class *mrbc_class_fixnum;
+mrb_class *mrbc_class_symbol;
+#if MRBC_USE_FLOAT
+mrb_class *mrbc_class_float;
+#endif
+#if MRBC_USE_STRING
+mrb_class *mrbc_class_string;
+#endif
+mrb_class *mrbc_class_range;
+mrb_class *mrbc_class_hash;
+
+void init_static(void)
+{
+  int i;
+
+  for( i=0 ; i<MAX_VM_COUNT ; i++ ){
+    mrbc_vm[i].vm_id = i+1;
+    mrbc_vm[i].priority = -1;
+  }
+
+  /* global objects */
+  for( i=0 ; i<MAX_GLOBAL_OBJECT_SIZE ; i++ ){
+    mrbc_global[i].sym_id = -1;
+  }
+
+  for( i=0 ; i<MAX_CONST_COUNT; i++ ){
+    mrbc_const[i].sym_id = -1;
+  }
+
+  /* init class */
+  mrbc_init_class();
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/static.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/static.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,58 @@
+/*! @file
+  @brief
+  Declare static data.
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+  </pre>
+*/
+
+#ifndef MRBC_SRC_STATIC_H_
+#define MRBC_SRC_STATIC_H_
+
+#include "vm.h"
+#include "global.h"
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* VM */
+extern mrb_vm mrbc_vm[];
+
+/* Object */
+//extern mrb_object *mrbc_pool_object;
+
+
+/* Class Tree */
+extern mrb_class *mrbc_class_object;
+
+extern mrb_class *mrbc_class_false;
+extern mrb_class *mrbc_class_true;
+extern mrb_class *mrbc_class_nil;
+extern mrb_class *mrbc_class_array;
+extern mrb_class *mrbc_class_fixnum;
+extern mrb_class *mrbc_class_float;
+extern mrb_class *mrbc_class_string;
+extern mrb_class *mrbc_class_symbol;
+extern mrb_class *mrbc_class_range;
+extern mrb_class *mrbc_class_hash;
+
+
+extern mrb_constobject mrbc_const[];
+/* Global Objects */
+extern mrb_globalobject mrbc_global[];
+
+void init_static(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/symbol.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/symbol.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,123 @@
+/*! @file
+  @brief
+  Symbol
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#include <string.h>
+#include "symbol.h"
+#include "console.h"
+
+
+struct SYM_INDEX {
+  uint16_t hash;	//!< hash value, returned by calc_hash().
+  char    *pos;		//!< point to the symbol string. maybe in sym_table[].
+};
+
+
+static struct SYM_INDEX sym_index[MAX_SYMBOLS_COUNT];
+static int sym_index_pos;	// point to the last(free) sym_index array.
+static char  sym_table[MAX_SYMBOLS_SIZE];	// symbol string table.
+static char *sym_table_pos = sym_table;	// point to the last(free) sym_table.
+
+
+//================================================================
+/*! Caliculate hash value.
+
+  @param  str		Target string.
+  @return uint16_t	Hash value.
+*/
+static uint16_t calc_hash(const char *str)
+{
+  uint16_t h = 0;
+
+  while( *str != '\0' ) {
+    h = h * 37 + *str;
+    str++;
+  }
+  return h;
+}
+
+
+//================================================================
+/*! Add symbol to symbol table.
+
+  @param  str		Target string.
+  @return mrb_sym	Symbol value.
+  @retval -1		If error occurred.
+*/
+mrb_sym add_sym(const char *str)
+{
+  mrb_sym sym_id = str_to_symid(str);
+
+  if( sym_id < 0 ) {
+    // check overflow.
+    if( sym_index_pos >= MAX_SYMBOLS_COUNT ) {
+      console_printf( "Overflow %s '%s'\n", "MAX_SYMBOLS_COUNT", str );
+      return -1;
+    }
+    int len = strlen(str);
+    if( len == 0 ) return -1;
+    len++;
+    if( len > (MAX_SYMBOLS_SIZE - (sym_table_pos - sym_table)) ) {
+      console_printf( "Overflow %s '%s'\n", "MAX_SYMBOLS_SIZE", str );
+      return -1;
+    }
+
+    // ok! go.
+    sym_index[sym_index_pos].hash = calc_hash(str);
+    sym_index[sym_index_pos].pos = sym_table_pos;
+    sym_id = sym_index_pos;
+    sym_index_pos++;
+    memcpy(sym_table_pos, str, len);
+    sym_table_pos += len;
+  }
+
+  return sym_id;
+}
+
+
+//================================================================
+/*! Convert string to symbol value.
+
+  @param  str		Target string.
+  @return mrb_sym	Symbol value.
+*/
+mrb_sym str_to_symid(const char *str)
+{
+  uint16_t h = calc_hash(str);
+  int i;
+
+  for( i = 0; i < sym_index_pos; i++ ) {
+    if( sym_index[i].hash == h ) {
+      if( strcmp(str, sym_index[i].pos) == 0 ) {
+        return i;
+      }
+    }
+  }
+  return -1;
+}
+
+
+//================================================================
+/*! Convert symbol value to string.
+
+  @param  mrb_sym	Symbol value.
+  @return const char*	String.
+  @retval NULL		Invalid sym_id was given.
+*/
+const char* symid_to_str(mrb_sym sym_id)
+{
+  if( sym_id < 0 ) return NULL;
+  if( sym_id >= sym_index_pos ) return NULL;
+
+  return sym_index[sym_id].pos;
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/symbol.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/symbol.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+  @brief
+  Symbol
+
+  <pre>
+  Copyright (C) 2015-2016 Kyushu Institute of Technology.
+  Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_SYMBOL_H_
+#define MRBC_SRC_SYMBOL_H_
+
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_sym add_sym(const char *str);
+mrb_sym str_to_symid(const char *str);
+const char* symid_to_str(mrb_sym sym_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/value.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/value.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,91 @@
+#include <stdint.h>
+#include <string.h>
+#include "value.h"
+#include "static.h"
+#include "symbol.h"
+#include "alloc.h"
+#include "vm.h"
+
+mrb_object *mrbc_obj_alloc(mrb_vm *vm, mrb_vtype tt)
+{
+  mrb_object *ptr = (mrb_object *)mrbc_alloc(vm, sizeof(mrb_object));
+  if( ptr ){
+    ptr->tt = tt;
+    ptr->next = 0;
+  }
+  return ptr;
+}
+
+mrb_class *mrbc_class_alloc(mrb_vm *vm, const char *name, mrb_class *super)
+{
+  mrb_class *ptr = (mrb_class *)mrbc_alloc(vm, sizeof(mrb_class));
+  if( ptr ){
+    ptr->tt = MRB_TT_CLASS;
+    ptr->super = super;
+    ptr->name = add_sym(name);
+    ptr->procs = 0;
+    ptr->next = 0;
+  }
+  return ptr;
+}
+
+mrb_proc *mrbc_rproc_alloc(mrb_vm *vm, const char *name)
+{
+  mrb_proc *ptr = (mrb_proc *)mrbc_alloc(vm, sizeof(mrb_proc));
+  if( ptr ) {
+    ptr->sym_id = add_sym(name);
+    ptr->next = 0;
+  }
+  return ptr;
+}
+
+mrb_proc *mrbc_rproc_alloc_to_class(mrb_vm *vm, const char *name, mrb_class *cls)
+{
+  mrb_proc *rproc = mrbc_rproc_alloc(vm, name);
+  if( rproc != 0 ){
+    rproc->next = cls->procs;
+    cls->procs = rproc;
+  }
+  return rproc;
+}
+
+
+// EQ? two objects
+// EQ: return true
+// NEQ: return false
+int mrbc_eq(mrb_value *v1, mrb_value *v2)
+{
+  // TT_XXX is different
+  if( v1->tt != v2->tt ) return 0;
+  // check value
+  switch( v1->tt ){
+  case MRB_TT_TRUE:
+  case MRB_TT_FALSE:
+  case MRB_TT_NIL:
+    return 1;
+  case MRB_TT_FIXNUM:
+  case MRB_TT_SYMBOL:
+    return v1->value.i == v2->value.i;
+  case MRB_TT_FLOAT:
+    return v1->value.d == v2->value.d;
+  case MRB_TT_STRING:
+    return !strcmp(v1->value.str, v2->value.str);
+  case MRB_TT_ARRAY: {
+    mrb_value *array1 = v1->value.obj;
+    mrb_value *array2 = v2->value.obj;
+    int i, len = array1[0].value.i;
+    if( len != array2[0].value.i ) return 0;
+    for( i=1 ; i<=len ; i++ ){
+      if( !mrbc_eq(array1+i, array2+i) ) break;
+    }
+    if( i > len ){
+      return 1;
+    } else {
+      return 0;
+    }
+  } break;
+  default:
+    return 0;
+  }
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/value.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,156 @@
+/*! @file
+  @brief
+
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_VALUE_H_
+#define MRBC_SRC_VALUE_H_
+
+#include <stdint.h>
+#include "vm_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// mrb types
+//typedef float mrb_float;
+typedef int32_t mrb_int;
+typedef int32_t mrb_sym;
+
+/* aspec access ? */
+#define MRB_ASPEC_REQ(a)          (((a) >> 18) & 0x1f)
+#define MRB_ASPEC_OPT(a)          (((a) >> 13) & 0x1f)
+#define MRB_ASPEC_REST(a)         (((a) >> 12) & 0x1)
+#define MRB_ASPEC_POST(a)         (((a) >> 7) & 0x1f)
+
+// #define GET_TYPE(v) ((v).tt)
+#define IS_FIXNUM(v) (((v).tt)==MRB_TT_FIXNUM)
+
+#pragma pack(2)
+
+//================================================================
+/*!@brief
+
+*/
+typedef enum {
+  /* internal use */
+  MRB_TT_HANDLE = -1,
+  /* primitive */
+  MRB_TT_EMPTY = 0,
+  MRB_TT_TRUE,
+  MRB_TT_FALSE,
+  MRB_TT_NIL,
+  MRB_TT_FIXNUM,
+  MRB_TT_FLOAT,
+  MRB_TT_SYMBOL,
+  /* non-primitive */
+  MRB_TT_OBJECT = 20,
+  MRB_TT_CLASS,
+  MRB_TT_PROC,
+  MRB_TT_ARRAY,
+  MRB_TT_STRING,
+  MRB_TT_RANGE,
+  MRB_TT_HASH,
+
+} mrb_vtype;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RClass {
+  struct RClass *next;  // linked list
+  mrb_vtype tt:8;
+  mrb_sym name;   // class name
+  struct RClass *super;    // mrbc_class[super]
+  struct RProc *procs;   // mrbc_proc[rprocs], linked list
+} mrb_class;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RObject {
+  struct RObject *next;
+  mrb_vtype tt;
+  union {
+    int32_t i;             // MRB_TT_FIXNUM
+    struct RObject *obj;   // MRB_TT_OBJECT : link to object
+    struct RClass *cls;    // MRB_TT_CLASS : link to class
+    struct RProc *proc;    // MRB_TT_PROC : link to proc
+    struct RObject *array; // MRB_TT_ARRAY : array of objects
+    struct RObject *range; // MRB_TT_RANGE : link to range
+    double d;              // MRB_TT_FLOAT : float
+    char *str;             // MRB_TT_STRING : C-string
+  } value;
+} mrb_object;
+typedef struct RObject mrb_value;
+
+
+struct VM;
+typedef void (*mrb_func_t)(struct VM *vm, mrb_value *v);
+
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RProc {
+  struct RProc *next;
+  unsigned int c_func:1;   // 0:IREP, 1:C Func
+  int16_t sym_id;
+  union {
+    struct IREP *irep;
+    mrb_func_t func;
+  } func;
+} mrb_proc;
+
+
+// alloc one object
+mrb_object *mrbc_obj_alloc(struct VM *vm, mrb_vtype tt);
+
+// alloc one class
+mrb_class *mrbc_class_alloc(struct VM *vm, const char *name, mrb_class *super);
+
+
+// alloc one RProc
+mrb_proc *mrbc_rproc_alloc(struct VM *vm, const char *name);
+mrb_proc *mrbc_rproc_alloc_to_class(struct VM *vm, const char *name, mrb_class *cls);
+
+// EQ two objects
+int mrbc_eq(mrb_value *v1, mrb_value *v2);
+
+
+// for C call
+#define SET_INT_RETURN(n)         {v[0].tt=MRB_TT_FIXNUM;v[0].value.i=(n);}
+#define SET_NIL_RETURN()          v[0].tt=MRB_TT_NIL
+#define SET_FALSE_RETURN()        v[0].tt=MRB_TT_FALSE
+#define SET_TRUE_RETURN()         v[0].tt=MRB_TT_TRUE
+#define SET_RETURN(n)             v[0]=n
+
+#define GET_TT_ARG(n)             v[(n)+1].tt
+#define GET_INT_ARG(n)            v[(n)+1].value.i
+#define GET_ARY_ARG(n)            v[(n)+1]
+#define GET_ARG(n)                v[(n)+1]
+#define GET_FLOAT_ARG(n)          v[(n)+1].value.d
+#define GET_STRING_ARG(n)          v[(n)+1].value.str
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/vm.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,1362 @@
+/*! @file
+  @brief
+  mruby bytecode executor.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  Fetch mruby VM bytecodes, decode and execute.
+
+  </pre>
+*/
+
+#include <stdint.h>
+#include <stddef.h>
+#include "vm.h"
+#include "alloc.h"
+#include "static.h"
+#include "vm_config.h"
+#include "opcode.h"
+#include "class.h"
+#include "symbol.h"
+#include "console.h"
+
+#include "c_string.h"
+#include "c_range.h"
+
+
+//================================================================
+/*!@brief
+  find sym[n] from symbol table in irep
+
+  @param  p
+  @param  n
+  @return  symbol string
+*/
+static char *find_irep_symbol( uint8_t *p, int n )
+{
+  int cnt = bin_to_uint32(p);
+  if( n >= cnt ) return 0;
+  p += 4;
+  while( n > 0 ) {
+    uint16_t s = bin_to_uint16(p);
+    p += 2+s+1;   // size(2 bytes) + symbol len + '\0'
+    n--;
+  }
+  return (char *)p+2;  // skip size(2 bytes)
+}
+
+
+//================================================================
+/*!@brief
+
+*/
+static void not_supported(void)
+{
+  console_printf("Not supported!\n");
+}
+
+
+//================================================================
+/*!@brief
+  Execute NOP
+
+  No operation
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_nop( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute MOVE
+
+  R(A) := R(B)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_move( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)] = regs[GETARG_B(code)];
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADL
+
+  R(A) := Pool(Bx)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadl( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rb = GETARG_Bx(code);
+  mrb_object *ptr = vm->pc_irep->ptr_to_pool;
+  while( rb > 0 ){
+    ptr = ptr->next;
+    rb--;
+  }
+  regs[GETARG_A(code)] = *ptr;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADI
+
+  R(A) := sBx
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)].value.i = GETARG_sBx(code);
+  regs[GETARG_A(code)].tt = MRB_TT_FIXNUM;
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADSYM
+
+  R(A) := Syms(Bx)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadsym( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int ra = GETARG_A(code);
+  int rb = GETARG_Bx(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+
+  mrb_sym sym_id = add_sym(sym);
+
+  regs[ra].value.i = sym_id;
+  regs[ra].tt = MRB_TT_SYMBOL;
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADNIL
+
+  R(A) := nil
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadnil( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)].tt = MRB_TT_NIL;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADSELF
+
+  R(A) := self
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadself( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)] = regs[0];
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADT
+
+  R(A) := true
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)].tt = MRB_TT_TRUE;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LOADF
+
+  R(A) := false
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_loadf( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)].tt = MRB_TT_FALSE;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute GETGLOBAL
+
+  R(A) := getglobal(Syms(Bx))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_getglobal( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int ra = GETARG_A(code);
+  int rb = GETARG_Bx(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+  mrb_sym sym_id = add_sym(sym);
+  regs[ra] = global_object_get(sym_id);
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute SETGLOBAL
+
+  setglobal(Syms(Bx), R(A))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_setglobal( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int ra = GETARG_A(code);
+  int rb = GETARG_Bx(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+  mrb_sym sym_id = add_sym(sym);
+  global_object_add(sym_id, &regs[ra]);
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute GETCONST
+
+  R(A) := constget(Syms(Bx))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_getconst( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int ra = GETARG_A(code);
+  int rb = GETARG_Bx(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+  mrb_sym sym_id = add_sym(sym);
+  regs[ra] = const_get(sym_id);
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute SETCONST
+
+  constset(Syms(Bx),R(A))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+
+inline static int op_setconst( mrb_vm *vm, uint32_t code, mrb_value *regs ) {
+  int ra = GETARG_A(code);
+  int rb = GETARG_Bx(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+  mrb_sym sym_id = add_sym(sym);
+  const_add(sym_id, &regs[ra]);
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute JMP
+
+  pc += sBx
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_jmp( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  vm->pc += GETARG_sBx(code) - 1;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute JMPIF
+
+  if R(A) pc += sBx
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_jmpif( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  if( regs[GETARG_A(code)].tt != MRB_TT_FALSE ) {
+    vm->pc += GETARG_sBx(code) - 1;
+  }
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute JMPNOT
+
+  if not R(A) pc += sBx
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_jmpnot( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  if( regs[GETARG_A(code)].tt == MRB_TT_FALSE ) {
+    vm->pc += GETARG_sBx(code) - 1;
+  }
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute SEND
+
+  R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_send( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  mrb_value recv = regs[GETARG_A(code)];
+  int rb = GETARG_B(code);
+  char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+  mrb_sym sym_id = str_to_symid(sym);
+  mrb_proc *m = find_method(vm, recv, sym_id);
+
+  if( m == 0 ) {
+    console_printf("no method(%s)!\n", sym);
+  } else {
+    if( m->c_func == 0 ) {
+      // Ruby method
+      // callinfo
+      mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top;
+      callinfo->reg_top = vm->reg_top;
+      callinfo->pc_irep = vm->pc_irep;
+      callinfo->pc = vm->pc;
+      callinfo->n_args = GETARG_C(code);
+      vm->callinfo_top++;
+      // target irep
+      vm->pc = 0;
+      vm->pc_irep = m->func.irep;
+      // new regs
+      vm->reg_top += GETARG_A(code);
+    } else {
+      // C func
+      m->func.func(vm, regs+GETARG_A(code));
+    }
+  }
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute ENTER
+
+  arg setup according to flags (23=5:5:1:5:5:1:1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_enter( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top - 1;
+  uint32_t enter_param = GETARG_Ax(code);
+  int def_args = (enter_param >> 13) & 0x1f;
+  int args = (enter_param >> 18) & 0x1f;
+  if( def_args > 0 ){
+    vm->pc += callinfo->n_args - args;
+  }
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute RETURN
+
+  return R(A) (B=normal,in-block return/break)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_return( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  // return value
+  mrb_value v = regs[GETARG_A(code)];
+  regs[0] = v;
+  // restore irep,pc,regs
+  vm->callinfo_top--;
+  mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top;
+  vm->reg_top = callinfo->reg_top;
+  vm->pc_irep = callinfo->pc_irep;
+  vm->pc = callinfo->pc;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute ADD
+
+  R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_add( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i += regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      regs[rr].value.d += regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      regs[rr].value.d += regs[rr+1].value.d;
+    } else {
+      op_send(vm, code, regs);
+    }
+#endif
+#if MRBC_USE_STRING
+  } else if( regs[rr].tt == MRB_TT_STRING && regs[rr+1].tt == MRB_TT_STRING ){
+    regs[rr].value.str = mrbc_string_cat(vm, regs[rr].value.str, regs[rr+1].value.str);
+
+#endif
+  } else {
+    op_send(vm, code, regs);
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute ADDI
+
+  R(A) := R(A)+C (Syms[B]=:+)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_addi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum + (value)
+  if( regs[rr].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i += GETARG_C(code);
+  } else {
+    not_supported();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute ADD
+
+  R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_sub( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum - Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i -= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      regs[rr].value.d -= regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      regs[rr].value.d -= regs[rr+1].value.d;
+    } else {
+      not_supported();
+    }
+#endif
+  } else {
+    not_supported();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute
+
+  R(A) := R(A)-C (Syms[B]=:-)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_subi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum + (value)
+  if( regs[rr].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i -= GETARG_C(code);
+  } else {
+    not_supported();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute
+
+  R(A) := R(A)*R(A+1) (Syms[B]=:*)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_mul( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum * Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i *= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      regs[rr].value.d *= regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      regs[rr].value.d *= regs[rr+1].value.d;
+    } else {
+      not_supported();
+    }
+#endif
+  } else {
+    not_supported();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute
+
+  R(A) := R(A)/R(A+1) (Syms[B]=:/)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_div( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+
+  // support Fixnum * Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    regs[rr].value.i /= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      regs[rr].value.d /= regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      regs[rr].value.d /= regs[rr+1].value.d;
+    } else {
+      not_supported();
+    }
+#endif
+  } else {
+    not_supported();
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute EQ
+
+  R(A) := R(A)==R(A+1)  (Syms[B]=:==,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_eq( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+  int result;
+
+  //
+  if( mrbc_eq(&regs[rr], &regs[rr+1]) ){
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+  return 1;
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    result = (regs[rr].value.i == regs[rr+1].value.i);
+#if MRBC_USE_FLOAT
+  if( regs[rr].tt == MRB_TT_FLOAT ) {
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      result = (regs[rr].value.d == regs[rr+1].value.i );
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      result = (regs[rr].value.d == regs[rr+1].value.d );
+    } else {
+      result = 0;
+    }
+  }
+#endif
+  } else if( regs[rr].tt == MRB_TT_TRUE ){
+    result = regs[rr+1].tt == MRB_TT_TRUE;
+  } else if( regs[rr].tt == MRB_TT_FALSE ){
+    result = regs[rr+1].tt == MRB_TT_FALSE;
+  } else {
+    op_send(vm,code,regs);
+    result = regs[rr].tt == MRB_TT_TRUE;
+  }
+  if( result ) {
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LT
+
+  R(A) := R(A)<R(A+1)  (Syms[B]=:<,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_lt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+  int result;
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    result = regs[rr].value.i < regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      result = regs[rr].value.d < regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      result = regs[rr].value.d < regs[rr+1].value.d;
+    } else {
+      result = 0;
+    }
+#endif
+  } else {
+    result = 0;
+    not_supported();
+  }
+
+  if( result ) {
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute LE
+
+  R(A) := R(A)<=R(A+1)  (Syms[B]=:<=,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_le( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+  int result;
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    result = regs[rr].value.i <= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      result = regs[rr].value.d <= regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      result = regs[rr].value.d <= regs[rr+1].value.d;
+    } else {
+      result = 0;
+    }
+#endif
+  } else {
+    result = 0;
+    not_supported();
+  }
+  if( result ) {
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute GE
+
+  R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_gt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+  int result;
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    result = regs[rr].value.i > regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      result = regs[rr].value.d > regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      result = regs[rr].value.d > regs[rr+1].value.d;
+    } else {
+      result = 0;
+    }
+#endif
+  } else {
+    result = 0;
+    not_supported();
+  }
+  if( result ) {
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute GE
+
+  R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_ge( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int rr = GETARG_A(code);
+  int result;
+
+  // support Fixnum + Fixnum
+  if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+    result = regs[rr].value.i >= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+  } else if( regs[rr].tt == MRB_TT_FLOAT ){
+    if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+      result = regs[rr].value.d >= regs[rr+1].value.i;
+    } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+      result = regs[rr].value.d >= regs[rr+1].value.d;
+    } else {
+      result = 0;
+    }
+#endif
+  } else {
+    result = 0;
+    not_supported();
+  }
+  if( result ) {
+    regs[rr].tt = MRB_TT_TRUE;
+  } else {
+    regs[rr].tt = MRB_TT_FALSE;
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Make Array
+
+  R(A) := ary_new(R(B),R(B+1)..R(B+C))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_array( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int arg_a = GETARG_A(code);
+  int arg_b = GETARG_B(code);
+  int arg_c = GETARG_C(code);
+  mrb_value *ptr;
+
+  mrb_value v;
+  v.tt = MRB_TT_ARRAY;
+  v.value.obj = 0;
+
+  if( arg_c >= 0 ){
+    mrb_object *p;
+    // ptr[0] : array info
+    // ptr[1..] : array elements
+    ptr = (mrb_value*)mrbc_alloc(vm, sizeof(mrb_value)*(arg_c + 1));
+    if( ptr == NULL ) return 0;  // ENOMEM
+
+    v.value.obj = ptr;
+    ptr->tt = MRB_TT_FIXNUM;
+    ptr->value.i = arg_c;
+
+    p = ptr + 1;
+    while( arg_c > 0 ){
+      p->tt = regs[arg_b].tt;
+      p->value = regs[arg_b].value;
+      p++;
+      arg_c--;
+      arg_b++;
+    }
+  }
+
+  regs[arg_a] = v;
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Create string object
+
+  R(A) := str_dup(Lit(Bx))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_string( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  mrb_value v;
+  v.tt = MRB_TT_STRING;
+
+  int arg_b = GETARG_Bx(code);
+  mrb_object *ptr = vm->pc_irep->ptr_to_pool;
+  while( arg_b > 0 ){
+    ptr = ptr->next;
+    arg_b--;
+  }
+  v.value.str = mrbc_string_dup(vm, ptr->value.str);
+
+  int arg_a = GETARG_A(code);
+  regs[arg_a] = v;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Create HASH object
+
+  R(A) := hash_new(R(B),R(B+1)..R(B+C))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_hash( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int arg_a = GETARG_A(code);
+  int arg_b = GETARG_B(code);
+  int arg_c = GETARG_C(code);
+
+  mrb_value v; // return value
+  v.tt = MRB_TT_HASH;
+
+  // make handle for hash pair
+  mrb_value *handle = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value));
+  if( handle == NULL ) return 0;  // ENOMEM
+
+  v.value.obj = handle;
+  handle->tt = MRB_TT_HANDLE;
+
+  // make hash
+  mrb_value *hash = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*(arg_c*2+1));
+  if( hash == NULL ) return 0;  // ENOMEM
+  handle->value.obj = hash;
+
+  hash[0].tt = MRB_TT_FIXNUM;
+  hash[0].value.i = arg_c;
+
+  mrb_value *src = &regs[arg_b];
+  mrb_value *dst = &hash[1];
+  while( arg_c > 0 ){
+    // copy key
+    *dst++ = *src++;
+
+    // copy value
+    *dst++ = *src++;
+
+    arg_c--;
+  }
+
+  regs[arg_a] = v;
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute  LAMBDA
+
+  R(A) := lambda(SEQ[Bz],Cz)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_lambda( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  // int c = GETARG_C(code); // TODO: Add flags support for OP_LAMBDA
+  int b = GETARG_b(code); // sequence position in irep list
+  mrb_proc *proc = mrbc_rproc_alloc(vm, "(lambda)");
+  mrb_irep *current = vm->irep;
+  mrb_irep *p = current->next; //starting from next for current sequence;
+  // code length is p->ilen * sizeof(uint32_t);
+  int i;
+  for (i=0; i < b; i++) {
+    p = p->next;
+  }
+  proc->c_func = 0;
+  proc->func.irep = p;
+  int a = GETARG_A(code);
+  regs[a].tt = MRB_TT_PROC;
+  regs[a].value.proc = proc;
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute  RANGE
+
+  R(A) := R(A) := range_new(R(B),R(B+1),C)
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_range( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int a = GETARG_A(code);
+  int b = GETARG_B(code);
+  int c = GETARG_C(code);
+  regs[a] = mrbc_range_new(vm, &regs[b], &regs[b+1], c);
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute CLASS
+
+    R(A) := newclass(R(A),Syms(B),R(A+1))
+    Syms(B): class name
+    R(A+1): super class
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_class( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute METHOD
+
+  R(A).newmethod(Syms(B),R(A+1))
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_method( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  int a = GETARG_A(code);
+  mrb_proc *rproc = regs[a+1].value.proc;
+
+  if( regs[a].tt == MRB_TT_CLASS ) {
+    mrb_class *cls = regs[a].value.cls;
+    int b = GETARG_B(code);
+    // sym_id : method name
+    mrb_irep *cur_irep = vm->pc_irep;
+    char *sym = find_irep_symbol(cur_irep->ptr_to_sym, b);
+    int sym_id = add_sym( sym );
+    mrbc_define_method_proc(vm, cls, sym_id, rproc);
+  }
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute TCLASS
+
+  R(A) := target_class
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_tclass( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  regs[GETARG_A(code)].tt = MRB_TT_CLASS;
+  regs[GETARG_A(code)].value.cls = vm->target_class;
+
+  return 0;
+}
+
+
+//================================================================
+/*!@brief
+  Execute STOP
+
+  stop VM
+
+  @param  vm    A pointer of VM.
+  @param  code  bytecode
+  @param  regs  vm->regs + vm->reg_top
+  @retval 0  No error.
+*/
+inline static int op_stop( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+  vm->flag_preemption = 1;
+  return -1;
+}
+
+
+//================================================================
+/*!@brief
+  Allocate new IREP
+
+  @param  vm	Pointer of VM.
+  @return	Pointer of new IREP.
+*/
+mrb_irep *new_irep(mrb_vm *vm)
+{
+  mrb_irep *p = (mrb_irep *)mrbc_alloc(vm, sizeof(mrb_irep));
+  return p;
+}
+
+
+//================================================================
+/*!@brief
+  VM initializer.
+
+  Get a VM from static heap.
+
+  @return  Pointer of struct VM in static area.
+
+  @code
+  init_static();
+  struct VM *vm = vm_open();
+  @endcode
+*/
+struct VM *vm_open(void)
+{
+  int i;
+  mrb_vm *p = 0;
+  for( i=0 ; i<MAX_VM_COUNT ; i++ ){
+    if( mrbc_vm[i].priority < 0 ){
+      p = mrbc_vm + i;
+      break;
+    }
+  }
+
+  if( p != 0 ){
+    p->priority = 1;
+    p->pc = 0;
+    p->callinfo_top = 0;
+  }
+
+  return p;
+}
+
+
+//================================================================
+/*!@brief
+  VM finalizer.
+
+  @param  vm  Pointer of VM
+*/
+void vm_close(struct VM *vm)
+{
+  vm->priority = -1;
+  mrbc_free_all(vm);
+  
+}
+
+
+//================================================================
+/*!@brief
+  Boot the VM.
+
+  @param  vm  Pointer of VM
+*/
+// init vm
+void vm_boot(struct VM *vm)
+{
+  vm->pc_irep = vm->irep;
+  vm->pc = 0;
+  vm->reg_top = 0;
+  // set self to reg[0]
+  vm->top_self = mrbc_obj_alloc(vm, MRB_TT_OBJECT);
+  vm->top_self->value.cls = mrbc_class_object;
+  vm->regs[0].tt = MRB_TT_OBJECT;
+  vm->regs[0].value.obj = vm->top_self;
+  // target_class
+  vm->target_class = vm->top_self->value.cls;
+  vm->error_code = 0;
+  vm->flag_preemption = 0;
+}
+
+
+//================================================================
+/*!@brief
+  Fetch a bytecode and execute
+
+  @param  vm    A pointer of VM.
+  @retval 0  No error.
+*/
+int vm_run( mrb_vm *vm )
+{
+  int ret = 0;
+
+  do {
+    // get one bytecode
+    uint32_t code = bin_to_uint32(vm->pc_irep->code + vm->pc * 4);
+    vm->pc++;
+
+    // regs
+    mrb_value *regs = vm->regs + vm->reg_top;
+
+    // Dispatch
+    enum OPCODE opcode = GET_OPCODE(code);
+    switch( opcode ) {
+    case OP_NOP:        ret = op_nop       (vm, code, regs); break;
+    case OP_MOVE:       ret = op_move      (vm, code, regs); break;
+    case OP_LOADL:      ret = op_loadl     (vm, code, regs); break;
+    case OP_LOADI:      ret = op_loadi     (vm, code, regs); break;
+    case OP_LOADSYM:    ret = op_loadsym   (vm, code, regs); break;
+    case OP_LOADNIL:    ret = op_loadnil   (vm, code, regs); break;
+    case OP_LOADSELF:   ret = op_loadself  (vm, code, regs); break;
+    case OP_LOADT:      ret = op_loadt     (vm, code, regs); break;
+    case OP_LOADF:      ret = op_loadf     (vm, code, regs); break;
+    case OP_GETGLOBAL:  ret = op_getglobal (vm, code, regs); break;
+    case OP_SETGLOBAL:  ret = op_setglobal (vm, code, regs); break;
+    case OP_GETCONST:   ret = op_getconst  (vm, code, regs); break;
+    case OP_SETCONST:   ret = op_setconst  (vm, code, regs); break;
+    case OP_JMP:        ret = op_jmp       (vm, code, regs); break;
+    case OP_JMPIF:      ret = op_jmpif     (vm, code, regs); break;
+    case OP_JMPNOT:     ret = op_jmpnot    (vm, code, regs); break;
+    case OP_SEND:       ret = op_send      (vm, code, regs); break;
+    case OP_ENTER:      ret = op_enter     (vm, code, regs); break;
+    case OP_RETURN:     ret = op_return    (vm, code, regs); break;
+    case OP_ADD:        ret = op_add       (vm, code, regs); break;
+    case OP_ADDI:       ret = op_addi      (vm, code, regs); break;
+    case OP_SUB:        ret = op_sub       (vm, code, regs); break;
+    case OP_SUBI:       ret = op_subi      (vm, code, regs); break;
+    case OP_MUL:        ret = op_mul       (vm, code, regs); break;
+    case OP_DIV:        ret = op_div       (vm, code, regs); break;
+    case OP_EQ:         ret = op_eq        (vm, code, regs); break;
+    case OP_LT:         ret = op_lt        (vm, code, regs); break;
+    case OP_LE:         ret = op_le        (vm, code, regs); break;
+    case OP_GT:         ret = op_gt        (vm, code, regs); break;
+    case OP_GE:         ret = op_ge        (vm, code, regs); break;
+    case OP_ARRAY:      ret = op_array     (vm, code, regs); break;
+    case OP_STRING:     ret = op_string    (vm, code, regs); break;
+    case OP_HASH:       ret = op_hash      (vm, code, regs); break;
+    case OP_LAMBDA:     ret = op_lambda    (vm, code, regs); break;
+    case OP_RANGE:      ret = op_range     (vm, code, regs); break;
+    case OP_CLASS:      ret = op_class     (vm, code, regs); break;
+    case OP_METHOD:     ret = op_method    (vm, code, regs); break;
+    case OP_TCLASS:     ret = op_tclass    (vm, code, regs); break;
+    case OP_STOP:       ret = op_stop      (vm, code, regs); break;
+    default:
+      console_printf("Skip OP=%02x\n", GET_OPCODE(code));
+      break;
+    }
+  } while( !vm->flag_preemption );
+
+  return ret;
+}
+
+
+#ifdef MRBC_DEBUG
+
+//================================================================
+/*!@brief
+
+  @param  vm  Pointer of VM.
+  @param  irep
+  @return
+*/
+void debug_irep(mrb_vm *vm, mrb_irep *irep)
+{
+  if( irep->unused == 1 ) {
+    console_printf("  not used.\n");
+    return;
+  }
+  console_printf("  code:0x%x\n", (int)((char *)irep->code - (char *)vm->mrb));
+  console_printf("  regs:%d\n", irep->nregs);
+  console_printf("  locals:%d\n", irep->nlocals);
+}
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/vm.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,140 @@
+/*! @file
+  @brief
+  mruby bytecode executor.
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+  Fetch mruby VM bytecodes, decode and execute.
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_VM_H_
+#define MRBC_SRC_VM_H_
+
+#include <stdint.h>
+#include "value.h"
+#include "vm_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct IREP {
+  int16_t unused;       //! unused flag
+  struct IREP *next;         //! irep linked list
+
+  uint8_t *code;
+  mrb_object *ptr_to_pool;
+  uint8_t *ptr_to_sym;
+
+  int16_t nlocals;
+  int16_t nregs;
+  int16_t rlen;
+  int32_t ilen;
+
+  int16_t iseq;
+
+} mrb_irep;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct CALLINFO {
+  mrb_irep *pc_irep;
+  uint32_t pc;
+  uint32_t reg_top;
+  uint8_t n_args;   // num of args
+} mrb_callinfo;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct VM {
+  mrb_irep *irep;    // irep linked list
+
+  uint8_t vm_id;     // vm_id : 1..n
+  int16_t priority;  //
+  const uint8_t *mrb;      // bytecode
+
+  mrb_irep *pc_irep;  // PC
+  int16_t pc;       // PC
+
+  int reg_top;
+  mrb_value regs[MAX_REGS_SIZE];
+  int callinfo_top;
+  mrb_callinfo callinfo[MAX_CALLINFO_SIZE];
+
+  mrb_class *target_class;
+  mrb_object *top_self;  // ?
+
+  int32_t error_code;
+
+  volatile int8_t flag_preemption;
+} mrb_vm;
+
+
+
+mrb_irep *new_irep(mrb_vm *vm);
+struct VM *vm_open(void);
+void vm_close(struct VM *vm);
+void vm_boot(struct VM *vm);
+int vm_run(struct VM *vm);
+
+
+//================================================================
+/*!@brief
+  Get 32bit value from memory big endian.
+
+  @param  s	Pointer of memory.
+  @return	32bit unsigned value.
+*/
+inline static uint32_t bin_to_uint32( const void *s )
+{
+  uint8_t *s1 = (uint8_t *)s;
+  uint32_t ret;
+
+  ret = *s1++;
+  ret = (ret << 8) + *s1++;
+  ret = (ret << 8) + *s1++;
+  ret = (ret << 8) + *s1;
+  return ret;
+}
+
+
+//================================================================
+/*!@brief
+  Get 16bit value from memory big endian.
+
+  @param  s	Pointer of memory.
+  @return	16bit unsigned value.
+*/
+inline static uint16_t bin_to_uint16( const void *s )
+{
+  uint8_t *s1 = (uint8_t *)s;
+  uint16_t ret;
+
+  ret = *s1++;
+  ret = (ret << 8) + *s1;
+  return ret;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/vm_config.h	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,76 @@
+/*! @file
+  @brief
+  Global configration of mruby/c VM's
+
+  <pre>
+  Copyright (C) 2015 Kyushu Institute of Technology.
+  Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+  This file is distributed under BSD 3-Clause License.
+
+
+  </pre>
+*/
+
+#ifndef MRBC_SRC_VM_CONFIG_H_
+#define MRBC_SRC_VM_CONFIG_H_
+
+/* maximum number of VMs */
+#ifndef MAX_VM_COUNT
+#define MAX_VM_COUNT 5
+#endif
+
+/* maximum size of registers */
+#ifndef MAX_REGS_SIZE
+#define MAX_REGS_SIZE 100
+#endif
+
+/* maximum size of callinfo (callstack) */
+#ifndef MAX_CALLINFO_SIZE
+#define MAX_CALLINFO_SIZE 100
+#endif
+
+/* maximum number of objects */
+#ifndef MAX_OBJECT_COUNT
+#define MAX_OBJECT_COUNT 400
+#endif
+
+/* maximum number of classes */
+#ifndef MAX_CLASS_COUNT
+#define MAX_CLASS_COUNT 20
+#endif
+
+/* maximum size of symbol table */
+#ifndef MAX_SYMBOLS_SIZE
+#define MAX_SYMBOLS_SIZE 400
+#endif
+
+/* maximum number of symbols */
+#ifndef MAX_SYMBOLS_COUNT
+#define MAX_SYMBOLS_COUNT 200
+#endif
+
+/* maximum size of global objects */
+#ifndef MAX_GLOBAL_OBJECT_SIZE
+#define MAX_GLOBAL_OBJECT_SIZE 20
+#endif
+
+/* maximum size of consts */
+#ifndef MAX_CONST_COUNT
+#define MAX_CONST_COUNT 20
+#endif
+
+
+/* Configure environment */
+/* 0: NOT USE */
+/* 1: USE */
+
+/* USE Float. Support Float class */
+//#define MRBC_USE_FLOAT 1
+
+/* USE String. Support String class */
+#define MRBC_USE_STRING 1
+
+
+#endif
+
diff -r 000000000000 -r 33feccbba3ff sample1.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sample1.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,27 @@
+/* dumped in big endian order.
+   use `mrbc -e` option for better performance on little endian CPU. */
+#include <stdint.h>
+const uint8_t
+#if defined __GNUC__
+__attribute__((aligned(4)))
+#elif defined _MSC_VER
+__declspec(align(4))
+#endif
+sample1[] = {
+0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x33,0x5e,0x0d,0x00,0x00,0x00,0xe9,0x4d,0x41,
+0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0xb6,0x30,0x30,
+0x30,0x30,0x00,0x00,0x00,0xae,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x1b,
+0x00,0xbf,0xff,0x83,0x00,0x40,0x0a,0x97,0x01,0x00,0x40,0x01,0x01,0xbf,0xff,0x83,
+0x01,0x00,0x00,0xb2,0x01,0x40,0x01,0x19,0x00,0xc0,0x00,0x03,0x00,0x40,0x00,0x97,
+0x00,0xbf,0xff,0x83,0x01,0x00,0x00,0x89,0x01,0xbf,0xff,0x83,0x01,0x00,0x00,0xb2,
+0x01,0x40,0x00,0x99,0x00,0xc0,0x00,0x03,0x01,0x00,0x00,0x06,0x01,0x80,0x40,0x01,
+0x01,0x00,0x80,0xa0,0x01,0x00,0x00,0x06,0x01,0x80,0x40,0x01,0x01,0x00,0xc0,0xa0,
+0x01,0x00,0x00,0x06,0x01,0xc0,0x31,0x83,0x01,0x01,0x00,0xa0,0x01,0x00,0x00,0x07,
+0x01,0x3f,0xf4,0x98,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x05,0x00,0x02,0x3d,0x3d,0x00,0x00,0x04,0x24,0x73,0x77,0x31,0x00,
+0x00,0x0a,0x6c,0x65,0x64,0x31,0x5f,0x77,0x72,0x69,0x74,0x65,0x00,0x00,0x04,0x70,
+0x75,0x74,0x73,0x00,0x00,0x05,0x64,0x65,0x6c,0x61,0x79,0x00,0x4c,0x56,0x41,0x52,
+0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x01,0x00,0x03,0x6c,0x65,0x64,0x00,0x00,0x00,
+0x01,0x45,0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
+};
+
diff -r 000000000000 -r 33feccbba3ff sample1.rb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sample1.rb	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,15 @@
+led = 0
+while(true)
+	if(led == 0)
+		led = 1
+	else
+		led = 0
+	end
+	if($sw1 == 0)
+		led = 1
+	end
+	led1_write( led )
+	puts led
+	delay 100
+end
+
diff -r 000000000000 -r 33feccbba3ff sample2.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sample2.c	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,20 @@
+/* dumped in big endian order.
+   use `mrbc -e` option for better performance on little endian CPU. */
+#include <stdint.h>
+const uint8_t
+#if defined __GNUC__
+__attribute__((aligned(4)))
+#elif defined _MSC_VER
+__declspec(align(4))
+#endif
+sample2[] = {
+0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x33,0xe4,0x90,0x00,0x00,0x00,0x72,0x4d,0x41,
+0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x54,0x30,0x30,
+0x30,0x30,0x00,0x00,0x00,0x4c,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x08,
+0x00,0x40,0x01,0x97,0x00,0x80,0x00,0x06,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x8a,
+0x00,0x80,0x00,0x07,0x00,0xbf,0xfd,0x98,0x00,0x80,0x00,0x05,0x00,0x00,0x00,0x4a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x08,0x73,0x77,0x31,0x5f,0x72,0x65,
+0x61,0x64,0x00,0x00,0x04,0x24,0x73,0x77,0x31,0x00,0x45,0x4e,0x44,0x00,0x00,0x00,
+0x00,0x08,
+};
+
diff -r 000000000000 -r 33feccbba3ff sample2.rb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sample2.rb	Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,4 @@
+while(true)
+	$sw1 = sw1_read()
+end
+