예제 #1
0
파일: bp.c 프로젝트: pcpa/lightning
int main()
{
  pifi      nfibs;
  int	    in;				/* offset of the argument */
  jit_insn  *ref;			/* to patch the forward reference */
  jit_insn  *mref;                     /* ref of move to backpatch */
  jit_insn  *tp;                       /* location to patch */

  codeBuffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
                    MAP_PRIVATE | MAP_ANON, -1, 0);
  if (codeBuffer == MAP_FAILED) {
    perror("mmap");
    exit(0);
  }

  nfibs = (pifi) (jit_set_ip(codeBuffer).iptr);

        jit_prolog   (1);
  in =  jit_arg_ui   ();
        jit_getarg_ui(JIT_V0, in);              /* V0 = n */
  mref= jit_movi_p(JIT_V2,jit_forward ());      /* Generate a dumb movi */
        jit_jmpr(JIT_V2);
        /* generate some dump filler that will never be executed!*/
        jit_addi_ui(JIT_V0,JIT_V0,1);
        jit_addi_ui(JIT_V0,JIT_V0,1);        
        jit_addi_ui(JIT_V0,JIT_V0,1);        
        jit_addi_ui(JIT_V0,JIT_V0,1);        
  tp  = jit_get_label ();
  ref = jit_blti_ui  (jit_forward(), JIT_V0, 2);
        jit_subi_ui  (JIT_V1, JIT_V0, 1);       /* V1 = n-1 */
        jit_subi_ui  (JIT_V2, JIT_V0, 2);       /* V2 = n-2 */
        jit_prepare  (1);
          jit_pusharg_ui(JIT_V1);
        jit_finish(nfibs);
        jit_retval(JIT_V1);                     /* V1 = nfibs(n-1) */
        jit_prepare(1);
          jit_pusharg_ui(JIT_V2);
        jit_finish(nfibs);
        jit_retval(JIT_V2);                     /* V2 = nfibs(n-2) */
        jit_addi_ui(JIT_V1,  JIT_V1,  1);
        jit_addr_ui(JIT_RET, JIT_V1, JIT_V2);   /* RET = V1 + V2 + 1 */
        jit_ret();

  jit_patch(ref);                               /* patch jump */
        jit_movi_i(JIT_RET, 1);                 /* RET = 1 */
        jit_ret();

  jit_patch_movi(mref,tp);                      /* Ok. Do the back-patching */

  /* call the generated code, passing 32 as an argument */
  jit_flush_code(codeBuffer, jit_get_ip().ptr);

#ifdef LIGHTNING_DISASSEMBLE
  disassemble(stderr, (char *)codeBuffer, jit_get_ip().ptr);
#endif
#ifndef LIGHTNING_CROSS
  printf("nfibs(%d) = %d\n", 32, nfibs(32));
#endif
  return 0;
}
예제 #2
0
void push_reg(jit_value reg, Frame* frame) {

	struct jit* jit = frame->jit;

	jit_op* overflow_jump = jit_bner(frame->jit, (intptr_t) JIT_FORWARD, frame->stack_size, frame->stack_offset);


	jit_addi(jit, frame->stack_size, frame->stack_size, 10);
	jit_movr(jit, frame->accum[0], frame->stack_size);
	jit_muli(jit, frame->accum[0], frame->accum[0], sizeof(YValue*));
	jit_prepare(jit);
	jit_putargr(jit, frame->stack_ptr);
	jit_putargr(jit, frame->accum[0]);
	jit_call(jit, realloc);
	jit_retval(jit, frame->stack_ptr);

	jit_patch(frame->jit, overflow_jump);

	jit_muli(jit, frame->accum[ACCUM_COUNT-1], frame->stack_offset, sizeof(YValue*));
	jit_stxr(jit, frame->stack_ptr, frame->accum[ACCUM_COUNT-1], reg, sizeof(YValue*));
	jit_addi(jit, frame->stack_offset, frame->stack_offset, 1);

	jit_prepare(jit);
	jit_putargr(jit, reg);
	jit_call(jit, inc_linkc);
}
예제 #3
0
파일: oemit_except.c 프로젝트: pcpa/owl
static void
unwind_exception(jit_int32_t regval, obool_t unsafe)
{
    jit_int32_t		 frame;
    jit_int32_t		 stack;
    jit_node_t		*equal;

    /* Need to restore and resync thread state */
    frame = GPR[FRAME] != JIT_NOREG ? GPR[FRAME] : JIT_R0;
    stack = GPR[STACK] != JIT_NOREG ? GPR[STACK] : JIT_R0;
    /* Restore fp */
    jit_ldxi(frame, regval, offsetof(oexception_t, fp));
    jit_stxi(offsetof(othread_t, fp), JIT_V0, frame);
    /* Restore sp */
    if (unsafe) {
	/* If throw may be from another vm stack frame, need to
	 * zero memory, or it may later be cast to the wrong object;
	 * the logic is somewhat optimized, to zero memory before
	 * function return instead of function call, but exceptions
	 * break all rules. */
	if (GPR[STACK] != JIT_NOREG) {
	    jit_ldxi(GPR[STACK], regval, offsetof(oexception_t, sp));
	    jit_ldxi(JIT_R1, JIT_V0, offsetof(othread_t, sp));
	    equal = jit_beqr(GPR[STACK], JIT_R1);
	    jit_subr(JIT_R0, GPR[STACK], JIT_R1);
	    jit_prepare();
	    jit_pushargr(JIT_R1);
	    jit_pushargi(0);
	    jit_pushargr(JIT_R0);
	    jit_finishi(memset);
	    jit_patch(equal);
	    jit_stxi(offsetof(othread_t, sp), JIT_V0, GPR[STACK]);
	}
	else {
	    jit_ldxi(JIT_R0, regval, offsetof(oexception_t, sp));
	    jit_ldxi(JIT_R1, JIT_V0, offsetof(othread_t, sp));
	    equal = jit_beqr(JIT_R0, JIT_R1);
	    jit_subr(JIT_R0, JIT_R0, JIT_R1);
	    jit_prepare();
	    jit_pushargr(JIT_R1);
	    jit_pushargi(0);
	    jit_pushargr(JIT_R0);
	    jit_finishi(memset);
	    jit_ldxi(JIT_R0, regval, offsetof(oexception_t, sp));
	    jit_patch(equal);
	    jit_stxi(offsetof(othread_t, sp), JIT_V0, JIT_R0);
	}
    }
    else {
	jit_ldxi(stack, regval, offsetof(oexception_t, sp));
	jit_stxi(offsetof(othread_t, sp), JIT_V0, stack);
    }
    /* Restore this (if there is a this register) */
    if (GPR[THIS] != JIT_NOREG)
	jit_ldxi(GPR[THIS], regval, offsetof(oexception_t, th));
    /* Restore exception frame */
    jit_ldxi(JIT_R0, regval, offsetof(oexception_t, ex));
    jit_stxi(offsetof(othread_t, ex), JIT_V0, JIT_R0);
}
예제 #4
0
int compile_blit_mono_inv(int retreg, Cell* args) {
  compile_arg(JIT_R0, car(args), TAG_BYTES);
  jit_ldr(JIT_R0, JIT_R0); // load bytes addr
  stack_push(JIT_R0, &stack_ptr);
  
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();

  jit_prepare();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg();
  push_stack_arg(); // pop bytes addr
  jit_finishi(blit_vector1_invert);
  
  jit_movi(retreg, 0);

  return 1;
}
예제 #5
0
파일: ret.C 프로젝트: pippijn/rasm
static int_return_int_t
generate_function_proxy (int_return_int_t func)
{
  static jit_insn buffer[1024];
  static jit_state _jit;
  int_return_int_t result;
  int arg;

  result = (int_return_int_t)(jit_set_ip (buffer).ptr);
  jit_prolog (1);
  arg = jit_arg_i ();
  jit_getarg_i (JIT_R1, arg);

  /* Reset `JIT_RET'.  */
  jit_movi_i (JIT_RET, -1);

  /* Invoke a FUNC.  */
  jit_prepare (1);
  jit_pusharg_i (JIT_R1);
  (void)jit_finish (func);

  /* Copy the result of FUNC from `JIT_RET' into our own result register.  */
  jit_retval_i (JIT_RET);

  jit_ret ();
  jit_flush_code (buffer, jit_get_ip ().ptr);

  return result;
}
예제 #6
0
int scheme_generate_alloc_retry(mz_jit_state *jitter, int i)
{
  GC_CAN_IGNORE jit_insn *refr;

#ifdef JIT_USE_FP_OPS
  if (i == 2) {
    (void)mz_tl_sti_d_fppop(tl_scheme_jit_save_fp, JIT_FPR1, JIT_R2);
  }
#endif
  JIT_UPDATE_THREAD_RSPTR();
  jit_prepare(2);
  CHECK_LIMIT();
  if (i == 1) {
    jit_pusharg_p(JIT_R1);
    jit_pusharg_p(JIT_R0);
  } else {
    (void)jit_movi_p(JIT_R0, NULL);
    jit_pusharg_p(JIT_R0);
    jit_pusharg_p(JIT_R0);
  }
  (void)mz_finish_lwe(ts_prepare_retry_alloc, refr);
  jit_retval(JIT_R0);
  if (i == 1) {
    mz_tl_ldi_l(JIT_R1, tl_retry_alloc_r1);
  }
#ifdef JIT_USE_FP_OPS
  if (i == 2) {
    (void)mz_tl_ldi_d_fppush(JIT_FPR1, tl_scheme_jit_save_fp, JIT_R2);
  }
#endif
  return 1;
}
예제 #7
0
int compile_pixel(int retreg, Cell* args) {
  Cell* arg_x = car(args);
  if (!arg_x) return argnum_error("(pixel x y color)");
  args = cdr(args);
  Cell* arg_y = car(args);
  if (!arg_y) return argnum_error("(pixel x y color)");
  args = cdr(args);
  Cell* arg_c = car(args);
  if (!arg_c) return argnum_error("(pixel x y color)");
  
  compile_arg(JIT_R0, arg_c, TAG_PURE_INT);
  stack_push(JIT_R0, &stack_ptr);
  compile_arg(JIT_R0, arg_y, TAG_PURE_INT);
  stack_push(JIT_R0, &stack_ptr);
  compile_arg(JIT_R0, arg_x, TAG_PURE_INT);
  stack_push(JIT_R0, &stack_ptr);
  
  jit_prepare();
  stack_pop(JIT_R0, &stack_ptr);
  jit_pushargr(JIT_R0);
  stack_pop(JIT_R0, &stack_ptr);
  jit_pushargr(JIT_R0);
  stack_pop(JIT_R0, &stack_ptr);
  jit_pushargr(JIT_R0);
  jit_finishi(machine_video_set_pixel);

  jit_movi(retreg, 0);
  
  return 1;
}
예제 #8
0
int compile_blit_string(int retreg, Cell* args, int requires) {
  compile_arg(JIT_R0, car(args), TAG_BYTES); // font
  stack_push(JIT_R0, &stack_ptr);

  args = cdr(args);
  compile_arg(JIT_R0, car(args), TAG_ANY); // string
  stack_push(JIT_R0, &stack_ptr);
  
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();
  compile_int_arg();

  jit_prepare();
  push_stack_arg(); // color
  push_stack_arg(); // h
  push_stack_arg(); // w
  push_stack_arg(); // y
  push_stack_arg(); // x
  push_stack_arg(); // cursor_pos (or -1)
  
  push_stack_arg(); // string
  push_stack_arg(); // font
  jit_finishi(blit_string1);
  jit_retval(retreg);

  box_int(retreg, requires);
  
  return 1;
}
예제 #9
0
int compile_flip(int retreg) {
  jit_prepare();
  jit_finishi(machine_video_flip);
  
  jit_movi(retreg, 0);

  return 1;
}
예제 #10
0
파일: push-pop.c 프로젝트: pcpa/lightning
static stakumilo_t
generate_push_pop (void)
{
  static const char msg[] = "we got %i\n";
  stakumilo_t result;
  int arg;
  int retval;

  buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
		MAP_PRIVATE | MAP_ANON, -1, 0);
  if (buffer == MAP_FAILED) {
    perror("mmap");
    exit(0);
  }

  result = (stakumilo_t)(jit_set_ip (buffer).ptr);
  jit_prolog (1);
  arg = jit_arg_i ();
  jit_getarg_i (JIT_R1, arg);

  /* Save R1 on the stack.  */
  jit_pushr_i (JIT_R1);

  /* Save two other registers just for the sake of using the stack.  */
  jit_movi_i (JIT_R0, -1);
  jit_movi_i (JIT_R2, -1);
  jit_pushr_i (JIT_R0);
  jit_pushr_i (JIT_R2);
  /* most likely need stack aligned at 16 bytes, dummy push to force align */
  jit_pushr_i (JIT_R2);

  jit_movr_i (JIT_R0, JIT_R1);
  jit_movi_p (JIT_R1, msg);

  /* Invoke a function that may modify R1.  */
  jit_prepare (2);
  jit_pusharg_i (JIT_R0);
  jit_pusharg_p (JIT_R1);
  (void)jit_finish (display_message);

  /* dummy pop for the sake of calling function with 16 byte aligned stack */
  jit_popr_i (JIT_R2);
  /* Restore the dummy registers.  */
  jit_popr_i (JIT_R2);
  jit_popr_i (JIT_R0);

  /* Restore R1.  */
  jit_popr_i (JIT_R1);

  jit_movr_i (JIT_RET, JIT_R1);

  jit_ret ();
  jit_flush_code (buffer, jit_get_ip ().ptr);

  return result;
}
예제 #11
0
jit_value pop_reg(Frame* frame) {
	struct jit* jit = frame->jit;

	jit_movr(jit, frame->accum[0], frame->null_ptr);
	jit_op* underflow_jump = jit_beqi(jit, (intptr_t) JIT_FORWARD, frame->stack_offset, 0);
	jit_subi(jit, frame->stack_offset, frame->stack_offset, 1);
	jit_muli(jit, frame->accum[ACCUM_COUNT-1], frame->stack_offset, sizeof(YValue*));
	jit_ldxr(jit, frame->accum[0], frame->stack_ptr, frame->accum[ACCUM_COUNT-1], sizeof(YValue*));	

	jit_patch(jit, underflow_jump);

	jit_prepare(jit);
	jit_putargr(jit, frame->accum[0]);
	jit_call(jit, dec_linkc);
	return frame->accum[0];
}
예제 #12
0
void set_reg(ssize_t r, jit_value v, Frame* frame) {
	if (r >= 0 && r < frame->stats->ssa_reg_count) {
		r = frame->stats->ssa_regs[r]->real_reg;

		jit_op*  label = jit_beqi(frame->jit, (intptr_t) JIT_FORWARD, v, 0);;
		
		jit_prepare(frame->jit);
		jit_putargr(frame->jit, frame->regs[r]);
		jit_putargr(frame->jit, v);
		jit_call(frame->jit, exchange_values);
		
		jit_movr(frame->jit, frame->regs[r], v);

		jit_patch(frame->jit, label);
	}
}
예제 #13
0
static stakumilo_t
generate_push_pop (void)
{
  static const char msg[] = "we got %i\n";
  static char buffer[1024];
  stakumilo_t result;
  int arg;

  result = (stakumilo_t)(jit_set_ip (buffer).ptr);
  jit_prolog (1);
  arg = jit_arg_i ();
  jit_getarg_i (JIT_R1, arg);

  /* Save R1 on the stack.  */
  jit_pushr_i (JIT_R1);

  /* Save two other registers just for the sake of using the stack.  */
  jit_movi_i (JIT_R0, -1);
  jit_movi_i (JIT_R2, -1);
  jit_pushr_i (JIT_R0);
  jit_pushr_i (JIT_R2);

  jit_movr_i (JIT_R0, JIT_R1);
  jit_movi_p (JIT_R1, msg);

  /* Invoke a function that may modify R1.  */
  jit_prepare (2);
  jit_pusharg_i (JIT_R0);
  jit_pusharg_p (JIT_R1);
  (void)jit_finish (display_message);

  /* Restore the dummy registers.  */
  jit_popr_i (JIT_R2);
  jit_popr_i (JIT_R0);

  /* Restore R1.  */
  jit_popr_i (JIT_R1);

  jit_movr_i (JIT_RET, JIT_R1);

  jit_ret ();
  jit_flush_code (buffer, jit_get_ip ().ptr);

  return result;
}
예제 #14
0
파일: main.cpp 프로젝트: selavy/stackvm
    bool compile(const Program &program, Translator &trans, Environment &env) {
        jit_node_t *ref;        
        jit_node_t *fn = jit_note(NULL, 0);
        jit_prolog();
        const int stack_base_offset = jit_allocai(32 * sizeof(double));
        int stack_top_idx = 0;

        auto &&stackPush = [&](int reg) {
            jit_stxi_d(stack_base_offset + stack_top_idx * sizeof(double), JIT_FP, reg);
            ++stack_top_idx;
        };
        
        auto &&stackPop = [&](int reg) {
            --stack_top_idx;
            jit_ldxi_d(reg, JIT_FP, stack_base_offset + stack_top_idx * sizeof(double));
            return reg;
        };

        size_t pc = 0;
        const size_t progsz = program.size();
        while (pc < progsz) {
            const Instruction &instr = program[pc];
            switch (instr.op) {
            case OP_NOP:
                break;
            case OP_PUSH:
                stackPush(JIT_F0);
                jit_movi_d(JIT_F0, instr.dval);
                break;
            case OP_ADD: {
                const int reg = stackPop(JIT_F1);
                jit_addr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_SUB: {
                const int reg = stackPop(JIT_F1);
                jit_subr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_MUL: {
                const int reg = stackPop(JIT_F1);
                jit_mulr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_DIV: {
                const int reg = stackPop(JIT_F1);
                jit_divr_d(JIT_F0, reg, JIT_F0);                
            }
                break;
            case OP_CALL: {
                stackPush(JIT_F0);
                const int sp = stack_top_idx - (instr.callop.nargs);
                jit_addi(JIT_R0, JIT_FP, stack_base_offset + sp * sizeof(double));
                
                jit_prepare();
                jit_pushargi((jit_word_t)&env);    // 1st arg: userdata
                jit_pushargi(instr.callop.nargs);  // 2nd arg: # of arguments
                jit_pushargr(JIT_R0);              // 3rd arg: pointer to args on stack
                jit_pushargi((jit_word_t)&error_); // 4th arg: pointer to error message

                auto &&cb = trans.lookup(instr.callop.fidx);
                jit_finishi(reinterpret_cast<jit_pointer_t>(cb));

                stack_top_idx -= instr.callop.nargs; // consume arguments on stack
                jit_retval_d(JIT_F0);
                jit_retval(JIT_R0);

                ref = jit_bnei(JIT_R0, 0);
                jit_reti_d(*reinterpret_cast<const double*>(&JIT_ERROR));
                jit_patch(ref);
            }
                break;
            }

            ++pc;
        }

        jit_retr_d(JIT_F0);
        jit_epilog();

        (void)jit_emit();
        func_ = reinterpret_cast<JitFunction>(jit_address(fn));
        
        return true;
    }
예제 #15
0
jit_pointer_t compile(const std::vector<Oper>& ops, jit_word_t *memory, const bool flush = true)
{
  jit_prolog();
  jit_movi(JIT_V0, reinterpret_cast<jit_word_t>(memory));
  jit_movi(JIT_V1, 0);

  std::stack<Loop> loops;

  jit_node_t* start = jit_note(__FILE__, __LINE__);

  for ( size_t n=0; n<ops.size(); ++n ) {
    switch ( ops[n].code ) {
      case '<':
        jit_str(JIT_V0, JIT_V1);
        jit_subi(JIT_V0, JIT_V0, ops[n].count * sizeof(jit_word_t));
        jit_ldr(JIT_V1, JIT_V0);
        break;

      case '>':
        jit_str(JIT_V0, JIT_V1);
        jit_addi(JIT_V0, JIT_V0, ops[n].count * sizeof(jit_word_t));
        jit_ldr(JIT_V1, JIT_V0);
        break;

      case 'z':
        jit_movi(JIT_V1, 0);
        break;

      case '+':
        jit_addi(JIT_V1, JIT_V1, ops[n].count);
        break;

      case '-':
        jit_subi(JIT_V1, JIT_V1, ops[n].count);
        break;

      case '.':
        jit_prepare();
        jit_pushargr(JIT_V1);
        jit_finishi(reinterpret_cast<jit_pointer_t>(putchar));

        if ( flush ) {
          jit_prepare();
          jit_pushargi(reinterpret_cast<jit_word_t>(stdout));
          jit_finishi(reinterpret_cast<jit_pointer_t>(fflush));
        }
        break;

      case ',':
        jit_prepare();
        jit_finishi(reinterpret_cast<jit_pointer_t>(getchar));
        jit_retval(JIT_V1);
        break;

      case '[': {
        Loop loop;
        loop.end = jit_forward();
        jit_node_t *j = jit_beqi(JIT_V1, 0);
        jit_patch_at(j, loop.end);
        loop.body = jit_label();
        loops.push(loop);
      } break;

      case ']': {
        Loop loop = loops.top();
        jit_node_t *j = jit_bnei(JIT_V1, 0);
        jit_patch_at(j, loop.body);
        jit_link(loop.end);
        loops.pop();
        break;
      }
      default:
        break;
    }
  }

  jit_node_t* stop = jit_note(__FILE__, __LINE__);

  jit_ret();
  jit_epilog();
  jit_pointer_t r = jit_emit();
  fprintf(stderr, "compiled to %zu bytes\n", (char*)jit_address(stop) -
      (char*)jit_address(start));
  return r;
}
예제 #16
0
void
run_gnulightning(void)
{
    struct bfi * n = bfprog;
    int maxstack = 0, stackptr = 0;
    char *strbuf = 0;
    size_t maxstrlen = 0;
#ifdef GNULIGHTv1
    jit_insn** loopstack = 0;
    jit_insn *codeBuffer;
    void * startptr;
    int argp;
#endif
#ifdef GNULIGHTv2
    jit_node_t    *start, *end;	    /* For size of code */
    jit_node_t** loopstack = 0;
    jit_node_t    *argp;
#endif

    if (cell_size == 8) tape_step = 1; else
    tape_step = sizeof(int);

#ifdef GNULIGHTv1
    /* TODO: Use mmap for allocating memory, the x86 execute protection
     * bit is on the segment so Linux has to say thay everything below
     * a specific address is executable. If you ask mmap for executable
     * memory it can put it below the current value. The mprotect()
     * function can't do this.
     */
    if (total_nodes < 4096)
	codeBuffer = malloc(65536);
    else
	codeBuffer = malloc(16 * total_nodes);
    save_ptr_for_free(codeBuffer);

    codeptr = (codeptr_t) jit_set_ip(codeBuffer).vptr;
    startptr = jit_get_ip().ptr;
    /* Function call prolog */
    jit_prolog(1);
    /* Get the data area pointer */
    argp = jit_arg_p();
    jit_getarg_p(REG_P, argp);
#endif

#ifdef GNULIGHTv2
    init_jit(NULL); // argv[0]);
    _jit = jit_new_state();
    start = jit_note(__FILE__, __LINE__);
    jit_prolog();

    /* Get the data area pointer */
    argp = jit_arg();
    jit_getarg(REG_P, argp);
#endif

    while(n)
    {
	switch(n->type)
	{
	case T_MOV:
	    if (acc_loaded)
		acc_offset -= n->count;

	    jit_addi(REG_P, REG_P, n->count * tape_step);
	    break;

	case T_ADD:
	    load_acc_offset(n->offset);
	    set_acc_offset(n->offset);

	    jit_addi(REG_ACC, REG_ACC, n->count);
	    break;

	case T_SET:
	    set_acc_offset(n->offset);
	    if (acc_const && acc_const_val == n->count) {
		;
	    } else if (acc_const && acc_const_val+1 == n->count) {
		jit_addi(REG_ACC, REG_ACC, 1);
            } else if (acc_const && acc_const_val-1 == n->count) {
		jit_addi(REG_ACC, REG_ACC, -1);
            } else {
		jit_movi(REG_ACC, n->count);
            }
            acc_const = 1;
            acc_const_val = n->count;
            break;

	case T_CALC:
	    if (n->offset == n->offset2 && n->count2 == 1) {
		load_acc_offset(n->offset);
		set_acc_offset(n->offset);
		if (n->count)
		    jit_addi(REG_ACC, REG_ACC, n->count);
	    } else if (n->count2 != 0) {
		load_acc_offset(n->offset2);
		set_acc_offset(n->offset);
		if (n->count2 == -1)
		    jit_negr(REG_ACC, REG_ACC);
		else if (n->count2 != 1)
		    jit_muli(REG_ACC, REG_ACC, n->count2);
		if (n->count)
		    jit_addi(REG_ACC, REG_ACC, n->count);
	    } else {
		clean_acc();
		set_acc_offset(n->offset);

		jit_movi(REG_ACC, n->count);
		if (n->count2 != 0) {
		    if (tape_step > 1)
			jit_ldxi_i(REG_A1, REG_P, n->offset2 * tape_step);
		    else
			jit_ldxi_uc(REG_A1, REG_P, n->offset2);
		    if (n->count2 == -1)
			jit_negr(REG_A1, REG_A1);
		    else if (n->count2 != 1)
			jit_muli(REG_A1, REG_A1, n->count2);
		    jit_addr(REG_ACC, REG_ACC, REG_A1);
		}
	    }

	    if (n->count3 != 0) {
		if (tape_step > 1)
		    jit_ldxi_i(REG_A1, REG_P, n->offset3 * tape_step);
		else
		    jit_ldxi_uc(REG_A1, REG_P, n->offset3);
		if (n->count3 == -1)
		    jit_negr(REG_A1, REG_A1);
		else if (n->count3 != 1)
		    jit_muli(REG_A1, REG_A1, n->count3);
		jit_addr(REG_ACC, REG_ACC, REG_A1);
	    }
	    break;

	case T_IF: case T_MULT: case T_CMULT:
	case T_WHL:
	    load_acc_offset(n->offset);
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    if (stackptr >= maxstack) {
		loopstack = realloc(loopstack,
			    ((maxstack+=32)+2)*sizeof(*loopstack));
		if (loopstack == 0) {
		    perror("loop stack realloc failure");
		    exit(1);
		}
	    }

	    if (cell_mask > 0 && acc_hi_dirty) {
		if (cell_mask == 0xFF)
		    jit_extr_uc(REG_ACC,REG_ACC);
		else
		    jit_andi(REG_ACC, REG_ACC, cell_mask);
	    }

#ifdef GNULIGHTv1
	    loopstack[stackptr] = jit_beqi_i(jit_forward(), REG_ACC, 0);
	    loopstack[stackptr+1] = jit_get_label();
#endif
#ifdef GNULIGHTv2
	    loopstack[stackptr] = jit_beqi(REG_ACC, 0);
	    loopstack[stackptr+1] = jit_label();
#endif
	    stackptr += 2;
	    break;

	case T_END:
	    load_acc_offset(n->offset);
	    clean_acc();

	    stackptr -= 2;
	    if (stackptr < 0) {
		fprintf(stderr, "Code gen failure: Stack pointer negative.\n");
		exit(1);
	    }

	    if (cell_mask > 0 && acc_hi_dirty) {
		if (cell_mask == 0xFF)
		    jit_extr_uc(REG_ACC,REG_ACC);
		else
		    jit_andi(REG_ACC, REG_ACC, cell_mask);
	    }

#ifdef GNULIGHTv1
	    jit_bnei_i(loopstack[stackptr+1], REG_ACC, 0);
	    jit_patch(loopstack[stackptr]);
#endif
#ifdef GNULIGHTv2
	    {
		jit_node_t *ref;
		ref = jit_bnei(REG_ACC, 0);
		jit_patch_at(ref, loopstack[stackptr+1]);
		jit_patch(loopstack[stackptr]);
	    }
#endif
	    break;

	case T_ENDIF:
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    stackptr -= 2;
	    if (stackptr < 0) {
		fprintf(stderr, "Code gen failure: Stack pointer negative.\n");
		exit(1);
	    }
	    jit_patch(loopstack[stackptr]);
	    break;

	case T_PRT:
	    clean_acc();
	    load_acc_offset(n->offset);
	    acc_loaded = 0;

#ifdef GNULIGHTv1
	    jit_prepare_i(1);
	    jit_pusharg_i(REG_ACC);
	    jit_finish(putch);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_pushargr(REG_ACC);
	    jit_finishi(putch);
#endif
	    break;

	case T_CHR:
	    clean_acc();
	    acc_const = acc_loaded = 0;

	    if (n->count <= 0 || (n->count >= 127 && iostyle == 1) ||
		    !n->next || n->next->type != T_CHR) {
		jit_movi(REG_ACC, n->count);
#ifdef GNULIGHTv1
		jit_prepare_i(1);
		jit_pusharg_i(REG_ACC);
		jit_finish(putch);
#endif
#ifdef GNULIGHTv2
		jit_prepare();
		jit_pushargr(REG_ACC);
		jit_finishi(putch);
#endif
	    } else {
		unsigned i = 0;
		struct bfi * v = n;
		char *s;
		while(v->next && v->next->type == T_CHR &&
			v->next->count > 0 &&
			    (v->next->count < 127 || iostyle != 1)) {

		    if (i+2 > maxstrlen) {
			if (maxstrlen) maxstrlen *= 2; else maxstrlen = 4096;
			strbuf = realloc(strbuf, maxstrlen);
			if (!strbuf) {
			    fprintf(stderr, "Reallocate of string buffer failed\n");
			    exit(42);
			}
		    }

		    strbuf[i++] = (char) /*GCC -Wconversion*/ v->count;
		    n = v;
		    v = v->next;
		}
		strbuf[i] = 0;
		s = strdup(strbuf);
		if (!s) {
		    fprintf(stderr, "Save of string failed\n");
		    exit(43);
		}
		save_ptr_for_free(s);

#ifdef GNULIGHTv1
		jit_movi_p(REG_ACC, s);
		jit_prepare_i(1);
		jit_pusharg_i(REG_ACC);
		jit_finish(puts_without_nl);
#endif
#ifdef GNULIGHTv2
		jit_prepare();
		jit_pushargi((jit_word_t) s);
		jit_finishi(puts_without_nl);
#endif
	    }
	    break;

	case T_INP:
	    load_acc_offset(n->offset);
	    set_acc_offset(n->offset);

#ifdef GNULIGHTv1
	    jit_prepare_i(1);
	    jit_pusharg_i(REG_ACC);
	    jit_finish(getch);
	    jit_retval_i(REG_ACC);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_pushargr(REG_ACC);
	    jit_finishi(getch);
	    jit_retval(REG_ACC);
#endif
	    break;

	case T_STOP:
#ifdef GNULIGHTv1
	    jit_prepare_i(0);
	    jit_finish(failout);
#endif
#ifdef GNULIGHTv2
	    jit_prepare();
	    jit_finishi(failout);
#endif
	    break;

	case T_NOP:
	case T_DUMP:
	    fprintf(stderr, "Warning on code generation: "
		    "%s node: ptr+%d, cnt=%d, @(%d,%d).\n",
		    tokennames[n->type],
		    n->offset, n->count, n->line, n->col);
	    break;

	default:
	    fprintf(stderr, "Code gen error: "
		    "%s\t"
		    "%d:%d, %d:%d, %d:%d\n",
		    tokennames[n->type],
		    n->offset, n->count,
		    n->offset2, n->count2,
		    n->offset3, n->count3);
	    exit(1);
	}
	n=n->next;

#if 0 /*def GNULIGHTv2 */
	if(n && enable_trace) {
	    char *p, buf[250];
	    clean_acc();
	    acc_loaded = 0;

	    sprintf(buf, "@(%d,%d)\n", n->line, n->col);
	    p = strdup(buf);
	    save_ptr_for_free(p);

	    jit_prepare();
	    jit_pushargi((jit_word_t) p);
	    jit_finishi(puts_without_nl);
	}
#endif

#ifdef GNULIGHTv1
	/* TODO -- Check for codeBuffer overflow (add jmp to new) */
#endif
    }

    jit_ret();

    if (strbuf) { maxstrlen = 0; free(strbuf); strbuf = 0; }

    delete_tree();

#ifdef GNULIGHTv1
    jit_flush_code(startptr, jit_get_ip().ptr);

    if (verbose)
	fprintf(stderr, "Generated %d bytes of V1 GNU Lightning code, running\n",
		(int)(jit_get_ip().ptr - (char*)startptr));

    start_runclock();
    codeptr(map_hugeram());
    finish_runclock(&run_time, &io_time);
#endif

#ifdef GNULIGHTv2
    jit_epilog();
    end = jit_note(__FILE__, __LINE__);
    codeptr = jit_emit();

    if (verbose)
	fprintf(stderr, "Generated %d bytes of V2 GNU Lightning code, running\n",
	    (int)((char*)jit_address(end) - (char*)jit_address(start)));

    jit_clear_state();
    // jit_disassemble();

    start_runclock();
    codeptr(map_hugeram());
    finish_runclock(&run_time, &io_time);
#endif

#if 0
  /* This code writes the generated instructions to a file
   * so we can disassemble it using:  ndisasm -b 32/64 code.bin  */
    {
#ifdef GNULIGHTv1
	char   *p = startptr;
	int     s = jit_get_ip().ptr - p;
#endif
#ifdef GNULIGHTv2
	char   *p = (char*)jit_address(start);
	int     s = (char*)jit_address(end) - p;
#endif
	FILE   *fp = fopen("code.bin", "w");
	int     i;
	for (i = 0; i < s; ++i) {
	    fputc(p[i], fp);
	}
	fclose(fp);
    }
#endif

#ifdef GNULIGHTv2
    jit_destroy_state();
    finish_jit();
#endif

    codeptr = 0;
    if (loopstack) { free(loopstack); loopstack = 0; }
    free_saved_memory();
}
예제 #17
0
void
outrun(int ch, int count)
{
    jit_node_t    *argp;

    switch(ch) {
    case '!':
	if (bytecell) tape_step = 1; else
	tape_step = sizeof(int);

        init_jit(NULL); // argv[0]);
	_jit = jit_new_state();
	start = jit_note(__FILE__, __LINE__);
	jit_prolog();

	/* Get the data area pointer */
	argp = jit_arg();
	jit_getarg(REG_P, argp);
	break;

    case '~':
	jit_ret();
	jit_epilog();
	end = jit_note(__FILE__, __LINE__);
	codeptr = jit_emit();
	jit_clear_state();
	codeptr(calloc(tape_step, tapelen));
	jit_destroy_state();
	finish_jit();
	codeptr = 0;
	if (loopstack) { free(loopstack); loopstack = 0; }
	break;

    case '>':
	jit_addi(REG_P, REG_P, count * tape_step);
	break;

    case '<':
	jit_subi(REG_P, REG_P, count * tape_step);
	break;

    case '+':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);
	jit_addi(REG_ACC, REG_ACC, count);
	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);
	break;

    case '-':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);
	jit_subi(REG_ACC, REG_ACC, count);
	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);
	break;

    case '[':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

	if (stackptr >= maxstack) {
	    loopstack = realloc(loopstack,
			((maxstack+=32)+2)*sizeof(*loopstack));
	    if (loopstack == 0) {
		perror("loop stack realloc failure");
		exit(1);
	    }
	}

	loopstack[stackptr] = jit_beqi(REG_ACC, 0);
	loopstack[stackptr+1] = jit_label();
	stackptr += 2;
	break;

    case ']':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

	stackptr -= 2;
	if (stackptr < 0) {
	    fprintf(stderr, "Code gen failure: Stack pointer negative.\n");
	    exit(1);
	}

	{
	    jit_node_t *ref;
	    ref = jit_bnei(REG_ACC, 0);
	    jit_patch_at(ref, loopstack[stackptr+1]);
	    jit_patch(loopstack[stackptr]);
	}
	break;

    case '.':
	if (tape_step>1)
	    jit_ldr_i(REG_ACC, REG_P);
	else
	    jit_ldr_uc(REG_ACC, REG_P);

	jit_prepare();
	jit_pushargr(REG_ACC);
	jit_finishi(putchar);
	break;

    case ',':
	jit_prepare();
	jit_pushargr(REG_ACC);
	jit_finishi(getchar);
	jit_retval(REG_ACC);

	if (tape_step>1)
	    jit_str_i(REG_P, REG_ACC);
	else
	    jit_str_c(REG_P, REG_ACC);

	break;
    }
}