Esempio n. 1
0
File: dcg.c Progetto: berkus/lang-e
/* driver */
static void scale(int n, data_t **a, data_t **b, data_t c) {
	struct v_reg  dst,src, src_end, v0, v1, al[10];
	struct v_label  loop1; 
	static unsigned insn[1024];
	v_vptr vp;

	/* simple unroll */
	/* assert(n >= 4 && (n % 4) == 0); */

	v_lambda("foo", "%p%p", al, V_LEAF, insn);

	/* row & c come in as parameters */
	dst 	= al[0];
	src 	= al[1];
	if(!v_getreg(&src_end, V_P, V_TEMP))
		v_fatal("scale: out of registers\n");
	if(!v_getreg(&v0, V_U, V_TEMP))
		v_fatal("scale: out of registers\n");
	if(!v_getreg(&v1, V_U, V_TEMP))
		v_fatal("scale: out of registers\n");

	loop1	= v_genlabel();

	/* relies on contigous memory */
	v_raw_load(v_ldpi(src, src, (0)), 1);	/* perform loads without interlocks */
	v_raw_load(v_ldpi(dst, dst, (0)), 1);
	v_addpi(src_end, src, (n * n) * sizeof **a);

	v_label(loop1);
		/* load 2 to get rid of delay slots */
		v_raw_load(v_ldui(v0, src, (0 * sizeof **a)), 1);
		v_raw_load(v_ldui(v1, src, (1 * sizeof **a)), 1);

		/* multiplies will be strength reduced */
		if(strength_reduce) cmuli(v0, v0, c);
		else		   v_mului(v0, v0, c);

		v_addpi(dst, dst, (2 * sizeof **a));

		if(strength_reduce) cmuli(v1, v1, c);
		else		   v_mului(v1, v1, c);

		v_stui(v0, dst, -(2 * sizeof **a));
		v_addpi(src, src, (2 * sizeof **a));
	/* schedule delay slot instructions */
	v_schedule_delay(
		v_bltp(src, src_end, loop1),
		v_stui(v1, dst, -(1 * sizeof **a))
	);

	vp = v_end().v;
	if(disass)
		v_dump((void *)vp);
	if(!pixie)
		vp(a,b);	/* perform multiplication */
}
Esempio n. 2
0
File: mult.c Progetto: berkus/lang-e
/* 
 * There are two problems here, both resulting from rd and rs conflicts:
 *	1. rr is used to store the initial value of rs
 *	2. rd == rs, then conflict.
 */
static void mgeni (v_reg_type rd, v_reg_type rs, v_reg_type t, int x) {
     char *p = mlookup[x];
     v_reg_type rr, t2 = 0, lastr;
     int equal;
     demand(x, bogus value);
     if (x >= LSIZE) {
	  v_mulii(rd, rs, x);
	  return;
     }
     p++;
     lastr = rd;
     if((equal = isequal(rd,rs))) {
	  if(v_getreg(&rd, V_I, V_TEMP) < 0) 
	       v_fatal("mgen: out of registers\n");
	  t2 = rd;
     }
     rr = rs;
     while(1) {
	  switch(*p++) {
	  case NEGATE: if(*p == DONE) rd = lastr;
	       v_negi(rd, rr);
	       break;
	  case SHIFT_ADD: v_lshii(t, rr, *p++);
	       if(*p == DONE) rd = lastr;
	       v_addi(rd, t, rs);
	       break;
	  case SHIFT_SUB: v_lshii(t, rr, *p++);
	       if(*p == DONE) rd = lastr;
	       v_subi(rd, t, rs);
	       break;
	  case SHIFT_REV: v_lshii(t, rr, *p++);
	       if(*p == DONE) rd = lastr;
	       v_subi(rd, rs, t);
	       break;
	  case FACTOR_ADD: v_lshii(t, rr, *p++);
	       if(*p == DONE) v_addi(lastr, t, rd);
	       else    v_addi(rd, t, rd);
	       break;
	  case FACTOR_SUB: 
	       v_lshii(t, rr, *p++);
	       if(*p == DONE) v_subi(lastr, t, rd);
	       else v_subi(rd, t, rd);
	       break;
	  case FACTOR_REV: 
	       v_lshii(t, rr, *p++);
	       if(*p == DONE) v_subi(lastr, rd, t);
	       else    v_subi(rd, rd, t);
	       break;
	  case SHIFT:	  if(p[1] == DONE) rd = lastr;
	       v_lshii(rd, rr, *p++);
	       break;
	  case DONE:	  goto quit;
	  default:	  demand(0, bogus op);
	  }	  
	  rr = rd;
     }	  
quit:	 
	  if(equal) 
	       v_putreg(t2, V_I );
} 
Esempio n. 3
0
int main(void) {
	static v_code insn[1000]; 	/* Memory to hold code in. */

        /* Test jump and link instruction */
        v_lambda("jump-and-link", "", 0, V_NLEAF, insn, sizeof insn);
        {
                static v_code *linked_addr;
                v_reg_type rdp, rr;
                v_label_type l;

		/* Allocate two registers persistent accross procedure calls. */
                v_getreg(&rdp, V_P, V_VAR);
		/* Allocate register to hold return pointer */
                v_getreg(&rr, V_P, V_VAR);

                l = v_genlabel(); 	  /* Allocate label */
                v_dlabel(&linked_addr, l); /* mark memory to hold target address */
                v_setp(rdp, &linked_addr); /* Load address */
                v_ldpi(rdp, rdp, 0);

                v_scallv((v_vptr)printf, "%P", "Jumping!\n");
                v_jalp(rr, rdp); 	   /* Jump to it. */

                v_scallv((v_vptr)printf, "%P", "Returning!\n");
                v_retv();		/* Done */

                v_label(l);
                        v_scallv((v_vptr)printf, "%P", "Jumping back!\n");
                        v_jp(rr);	/* Jump back to caller. */
        }
        v_end(0).v();
#if 0
{
	v_vptr vp = v_end(0).v;
	v_dump(vp);
	vp();
}
#endif

	return 0;
}
Esempio n. 4
0
int main() { 
	static v_code insn[1000];
	v_iptr ip;

        /* jal reg  */
        v_lambda("v_jal", "", 0, V_NLEAF, insn, sizeof insn);
        {
        	static void * linked_addr;
        	v_reg_type rdp;
        	v_reg_type rr;
		v_label_type l;

		v_getreg(&rdp, V_P, V_VAR);
		v_getreg(&rr, V_P, V_VAR);

                l = v_genlabel();
                v_dmark(&linked_addr, l);

                v_ldpi(rdp, v_zero, (unsigned long)&linked_addr);
		v_scallv((v_vptr)printf, "%P", "Jumping!\n");
                v_jalp(rr, rdp);
		v_scallv((v_vptr)printf, "%P", "Returning.\n");	
               	v_retii(13);

                v_label(l);
			v_scallv((v_vptr)printf, "%P", "Jumping back!\n");
			v_jp(rr);
        }
	printf("Testing jalr\n");
	ip = v_end(0).i;
#if 0
	v_dump((void*)ip);
#endif
        if(ip() != 13)
		demand(0, bogus value!);
	return 0;
}
Esempio n. 5
0
int main() { 
	static unsigned insn[1000];
	v_reg_type r;
	struct v_cstate c;
	v_vptr vp;

	v_clambda("foo", V_NLEAF, insn, sizeof insn);
	v_getreg(&r, V_I, V_TEMP);

	v_push_init(&c);
	v_push_argpi(&c, "Hello: %d %d %d %d\n");
	v_seti(r, 10);
	v_push_argi(&c, r);
	v_seti(r,20);
	v_push_argi(&c, r);
	v_seti(r,30);
	v_push_argi(&c, r);
	v_seti(r,40);
	v_push_argi(&c, r);
	v_ccallv(&c, (v_vptr)printf);
	vp = v_end(0).v;
#if 0
	v_dump((void*)vp);
#endif
	vp();

	v_clambda("foo", V_NLEAF, insn, sizeof insn);
	v_push_init(&c);
	v_push_argpi(&c, "Hello: %d %d %d %d\n");
	v_push_argii(&c, 10);
	v_push_argii(&c, 20);
	v_push_argii(&c, 30);
	v_push_argii(&c, 40);
	v_ccallv(&c, (v_vptr)printf);
	vp = v_end(0).v;
#if 0
	v_dump((void*)vp);
#endif
	vp();

#if 0
	v_clambda("foo", V_NLEAF, insn, sizeof insn);
	v_push_argpi(&c, "Hello: %d %d %d %d\n");
#endif
	return 0;
}
Esempio n. 6
0
File: mult.c Progetto: berkus/lang-e
void v_cmuli (v_reg_type rd, v_reg_type rs, int x) {
     v_reg_type t1;
     if(!x) {
	  v_seti(rd, 0);
	  return;
     } else if(x == 1) {
	  if(isequal(rd, rs))	  
	       return;
	  v_movi(rd, rs);
	  return;
     }	     v_getreg(&t1, V_I, V_TEMP);
     if(x >= 0) {
	  mgeni(rd, rs, t1, x);
     } else {
	  mgeni(rd, rs, t1, -x);
	  v_negi(rd, rd);
     }
     v_putreg(t1, V_I);
} 
Esempio n. 7
0
/* Power: raise base to n-th power: n > 0; specialized for a runtime constant n. */
v_fptr specialize_power(int n) {
	v_reg_type x, sum;

        v_lambda("power", "%d", &x, V_LEAF, malloc(512), 512);
	{
		int i;

		/* Allocate accumulator */
		v_getreg(&sum, V_D, V_TEMP);
		v_movf(sum, x);		/* initialize sum */

		/* Specialize power to x^n by unrolling the loop to multiply
	 	   x n times: (x * x * ... * x). */
		for(i = 0; i < n - 1; i++)
			v_mulf(sum, sum, x);

		v_retf(sum);	/* return x ^ n */
	}
        return v_end(0).f;	/* return pointer to result. */
}
Esempio n. 8
0
File: mult.c Progetto: berkus/lang-e
void v_cmulu (v_reg_type rd, v_reg_type rs, unsigned x) {
     v_reg_type t1;
     if(!x) {
	  v_setu(rd, 0);
	  return;
     } else if(x == 1) {
	  if(isequal(rd, rs))
	       return;
	  v_movu(rd, rs);
	  return;
     }
     v_getreg(&t1, V_U, V_TEMP);
     if(x >= 0) {
	  mgenu(rd, rs, t1, x);
     } else {
	  mgenu(rd, rs, t1, -x);
	  v_negu(rd, rd);
     }	     
     v_putreg(t1, V_U);
} 
Esempio n. 9
0
File: wk.c Progetto: aunali1/exopc
/* A predicate is represented as a sum-of-products, that is
   (A1 A2 ... ) OR (B1 B2 ...) OR ...
   where each element in a product (the A?'s and B?'s) are simple
   predicates like v > 10.

   Predicates are represented in memory as an array of wk_term's,
   one term for each immediate, variable, operator, conjunction or
   disjunction. A single product is considered to be a group of
   contiguous wk_term's that are not WK_ORs. The whole mess is
   terminated by a WK_END.  */

#include <vcode/vcode.h>
#include <xok/wk.h>
#include <xok/mmu.h>
#include <xok/sys_proto.h>
#include <xok/kerrno.h>
#include <xok/malloc.h>
#include <xok_include/assert.h>
#include <xok/printf.h>

#ifndef __CAP__
#include <xok/pmapP.h>
#else
#include <xok/pmap.h>
#endif

#define WK_MAX_CODE_BYTES 4096

#define OVERRUN_SAFETY 20
#define OVERRUN_CHECK						\
{								\
  if (v_ip > code + WK_MAX_CODE_BYTES - OVERRUN_SAFETY) {	\
    warn ("wk_compile: out of code space\n");			\
    ret = -E_INVAL;						\
    goto error;							\
  }								\
}

static int next_pp; /* outside function so can be used by cleanup code */
static int wk_compile (struct wk_term *t, int sz, char *code,
		       u_int *pred_pages) {
  int i;
  v_reg_t r1, r2, z, tag;
  v_label_t end_of_term;
  int start_term = 1;
  int op1 = 1;
  cap c;
  struct Ppage *pp;
  u_int ppn;
  int ret = 0;

  next_pp = 0;

  v_lambda ("", "", NULL, 1, code, WK_MAX_CODE_BYTES);
  if (!v_getreg (&r1, V_U, V_TEMP) ||
      !v_getreg (&r2, V_U, V_TEMP) ||
      !v_getreg (&z, V_U, V_TEMP) ||
      !v_getreg (&tag, V_U, V_TEMP))
    panic ("wk_compile: architecture doesn't have enough registers.");

  v_setu (tag, -1);
  v_setu (z, 0);  
  
  for (i = 0; i < sz; i++) {
    if (start_term) {
      end_of_term = v_genlabel ();
      start_term = 0;
    }
    OVERRUN_CHECK;
    switch (t[i].wk_type) {
    case WK_VAR:
      if (next_pp >= WK_MAX_PP-1) {
	warn ("wk_compile: too many pages in predicate\n");
	ret = -E_INVAL;
	goto error;
      }
      if ((ret = env_getcap (curenv, t[i].wk_cap, &c)) < 0) {
	goto error;
      }
      ppn = PGNO((u_int)t[i].wk_var);
      if (!ppn || ppn >= nppage) {
	printf ("at index %d\n", i);
	warn ("wk_compile: invalid physical page\n");
	ret = -E_INVAL;
	goto error;
      }
      pp = ppages_get(ppn);
      switch (Ppage_pp_status_get(pp)) {
      case PP_USER:
	if ((ret = ppage_acl_check(pp,&c,PP_ACL_LEN,0)) < 0) {
	  goto error;
	}
	ppage_pin (pp);
	pred_pages[next_pp++] = ppn;
	break;
      case PP_KERNRO:
	/* user can access pages that each env get's mapped r/o */
	break;
      default:
	printf ("at index %d\n", i);
	warn ("wk_compile: attempt to reference non PP_KERNRO or PP_USER page\n");
	ret = -E_INVAL;
	goto error;
      }
      if (op1) {
	v_ldui (r1, z, (int )ptov (t[i].wk_var));
	op1 = 0;
      } else {
	v_ldui (r2, z, (int )ptov (t[i].wk_var));
	op1 = 1;
      }
      break;
    case WK_IMM:
      if (op1) {
	v_setu (r1, t[i].wk_imm);
	op1 = 0;
      } else {
	v_setu (r2, t[i].wk_imm);
	op1 = 1;
      }
      break;
    case WK_TAG: {
      v_setu (tag, t[i].wk_tag);
      break;
    }
    case WK_OP: {
      switch (t[i].wk_op) {
      case WK_GT: {
	v_bleu (r1, r2, end_of_term); 
	break;
      }
      case WK_GTE: {
	v_bltu (r1, r2, end_of_term); 
	break;
      }
      case WK_LT: {
	v_bgeu (r1, r2, end_of_term);
	break;
      }
      case WK_LTE: {
	v_bgtu (r1, r2, end_of_term); 
	break;
      }
      case WK_EQ: {
	v_bneu (r1, r2, end_of_term);
	break;
      }
      case WK_NEQ: {
	v_bequ (r1, r2, end_of_term);
	break;
      }
      case WK_OR: {
	v_retu (tag);
	v_label (end_of_term);
	start_term = 1; 
	break;
      }
      default: {
	printf ("at index %d\n", i);
	warn ("wk_compile: invalid wk-pred instruction\n");
	ret = -E_INVAL;
	goto error;
      }
      }
      break;
    }
    default:
      printf ("at index %d\n", i);
      warn ("wk_compile: invalid wk-pred type\n");
      ret = -E_INVAL;
      goto error;
    }
  }
      
  /* end the last term */
  OVERRUN_CHECK;
  v_retu (tag);
  v_label (end_of_term);

  v_retui (0);
  v_end (NULL);

error:
  /* have to do this even on error so that our caller can just call
     wk_free to clean memory/ref counts up */
  pred_pages[next_pp] = 0;
  curenv->env_pred_pgs = pred_pages;
  curenv->env_pred = (Spred)code;
  return ret;
}