Beispiel #1
0
void parsearglist(void) {
	vpush((numvar) arg);				// save base of current argblock
#if defined(STRING_POOL)
	vpush((numvar) stringPool);			// save stringPool base for later release
	strpush(idbuf);						// save called function's name as arg[-1]
#endif
	numvar *newarg = &vstack[vsptr];	// move global arg pointer to base of new block
	vpush(0);							// initialize new arg(0) (a/k/a argc) to 0

	if (sym == s_lparen) {
		getsym();		// eat arglist '('
		while ((sym != s_rparen) && (sym != s_eof)) {

#if defined(STRING_POOL)
			if (sym == s_quote) {
				vpush((numvar) stringPool);	// push the string pointer
				parsestring(&spush);		// parse it into the pool
				spush(0);					// and terminate it
				getsym();					// eat closing "
			} else 
#endif
			vpush(getnum());				// push the value
			newarg[0]++;					// bump the count
			if (sym == s_comma) getsym();	// eat arglist ',' and go around
			else break;
		}
		if (sym == s_rparen) getsym();		// eat the ')'
		else expected(M_rparen);
	}
	arg = newarg;		// activate new argument frame
}
Beispiel #2
0
/////////
//
//	Parse and interpret a stream, and return its value
//
//	This is used in doCommand to execute a passed-in or collected text command,
// in domacrocommand() when a macro/function is called from within a parse stream,
//	and in runBackgroundTasks to kick off the background run.
//
//
numvar execscript(byte scripttype, numvar scriptaddress, char *scriptname) {

	// save parse context
	parsepoint fetchmark;
	markparsepoint(&fetchmark);
	byte thesym = sym;
	vpush(symval);

	// if this is the first stream context in this invocation,
	// set up our error recovery point and init the value stack
	// otherwise we skip this to allow nested execution calls 
	// to properly return to top
	//
	if (fetchtype == SCRIPT_NONE) {

		// Exceptions come here via longjmp; see bitlash-error.c
		switch(setjmp(env)) {
			case 0: break;
			case X_EXIT: {

				// POLICY: Stop all background tasks on any error
				//
				// It is not possible to be certain that continuing here will work.
				// Not all errors leave the interpreter in a working state.  Though most do.
				// The conservative/deterministic choice is to stop all background tasks
				// and drop the user back to the command prompt.
				//
				// On the other hand, you may find this inconvenient in your application, 
				// and may be happy taking the risk of continuing.
				//
				// In which case, comment out this line and proceed with caution.
				//	
				// TODO: if the macro "onerror" exists, call it here instead.  Let it "stop *".
				//
				// -br
				//
				initTaskList();		// stop all pending tasks

#ifdef SOFTWARE_SERIAL_TX
				resetOutput();		// clean up print module
#endif
				// Other cleanups here
				vinit();			// initialize the expression stack
				fetchtype = SCRIPT_NONE;	// reset parse context
				fetchptr = 0L;				// reset parse location
				// sd_up = 0;				// TODO: reset file system
				return (numvar) -1;
			}							// X_EXIT case
		}								// switch
	}
	initparsepoint(scripttype, scriptaddress, scriptname);
	getsym();

	// interpret the function text and collect its result
	numvar ret = getstatementlist();
	returntoparsepoint(&fetchmark, 1);		// now where were we?
	sym = thesym;
	symval = vpop();
	return ret;
}
Beispiel #3
0
void vinit(void) { 
	vsptr = VSTACKLEN-1;
	arg = &vstack[vsptr];	// point the argblock at the stack base
	vpush(0);				// push a 0 there so arg(0) is 0 at the top
#if defined(STRING_POOL)
	stringPool = (char *) vstack;	// stringPool starts at unused base of vstack
	*stringPool = 0;				// make it look empty
#endif
}
Beispiel #4
0
void Compiler::gen_jsr(unsigned target)
{
    AR gr = valloc(jobj);
    const JInst& jinst = *m_curr_inst;
    movp(gr, jinst.next, m_bbinfo->start);
    vpush(Val(jretAddr, gr));
    gen_bb_leave(target);
    br(cond_none, target, m_bbinfo->start);
}
Beispiel #5
0
void expr2_test()
{
    int a, b;

    printf("expr2:\n");
    vstack_ptr = vstack;
    vpush(1432432, 2);
    vstack_ptr[-2] &= ~0xffffff80;
    vpop(&a, &b);
    printf("res= %d %d\n", a, b);
}
Beispiel #6
0
/**
 * Provides fine-tuned implementation for IDIV/IREM operations on IA32-compatible platforms, 
 * in replacement of common arithmetic helper (see arith_rt.h).
 */
bool CodeGen::gen_a_platf(JavaByteCodes op, jtype jt)
{
    if (jt != i32) return false;
    if (op != OPCODE_IDIV && op != OPCODE_IREM) {
        return false;
    }
    //
    // The method is supposed to be platform-depended, and may not have 
    // Encoder support - leaving as-is, without implementing general 
    // support in Encoder
    //
    
    vpark(eax.reg());
    vpark(edx.reg());
    rlock(eax);
    rlock(edx);
    Val& v1 = vstack(1, vis_imm(1));
    Val& v2 = vstack(0, true);
    alu(alu_cmp, v2.as_opnd(), Opnd(-1));
    unsigned br_normal = br(ne, 0, 0);
    alu(alu_cmp, v1.as_opnd(), Opnd(INT_MIN));
    unsigned br_exit = NOTHING;
    if (op == OPCODE_IREM) {
        do_mov(edx, Opnd(0)); // prepare exit value for the corner case
        br_exit = br(eq, 0, 0);
    }
    else {
        do_mov(eax, v1);
        br_exit = br(eq, 0, 0);
    }
    patch(br_normal, ip());
    do_mov(eax, v1);
    //
    // The method is supposed to be platform-depended, and may not have 
    // Encoder support - leaving as-is, without implementing general 
    // support in Encoder
    //
    
    //CDQ
    EncoderBase::Operands args0(RegName_EDX, RegName_EAX);
    ip(EncoderBase::encode(ip(), Mnemonic_CDQ, args0));
    //IDIV
    EncoderBase::Operands args(RegName_EDX, RegName_EAX, 
                               devirt(v2.reg(), i32));
    ip(EncoderBase::encode(ip(), Mnemonic_IDIV, args));
    patch(br_exit, ip());

    vpop();
    vpop();
    vpush(op == OPCODE_IREM ? edx : eax);
    runlock(eax);
    runlock(edx);
    return true;
}
// call a macro and push its return value on the stack
//
void domacrocall(int macroaddress) {
	if (macroaddress >= 0) {
	
		parsearglist();
		byte thesym = sym;					// save sym for restore
		vpush(symval);						// and symval
		char *fetchmark = fetchptr;			// save the current parse pointer

		// call the macro
		calleeprommacro(findend(macroaddress));	// register the macro into the parser stream
		getsym();								// fetch its first symbol
		
		numvar ret = getstatementlist();		// parse and execute the macro code here
//		if (sym != s_eof) expected(M_eof);

		// restore parsing context so we can resume cleanly
		symval = vpop();		// restore symval
		sym = thesym;			// restore saved sym
		releaseargblock();		// drop the args
		fetchptr = fetchmark;	// restore pointer
		primec();				// and inchar
		vpush(ret);				// send back our return value
	}
}
/////////
//
// Call a Bitlash script function and push its return value on the stack
//
void callscriptfunction(byte scripttype, numvar scriptaddress) {

	// note on function name management
	//
	// we get here with the name of the function we want to call in global idbuf.
	// parsearglist() pushes a copy of idbuf into the string pool, so
	// the function's name is the first data in the string pool slab
	// that will be deallocated when the function returns
	//
	// we can refer to this copy of the function's name via the callername macro
	//
	parsearglist();
	numvar ret = execscript(scripttype, scriptaddress, calleename);
	releaseargblock();
	vpush(ret);
}
pointer EUSPINHOLE_CAMERA_MODEL_PROJECT_3D_TO_PIXEL(register context *ctx,int n,pointer *argv)
{
  ckarg(2);
  image_geometry::PinholeCameraModel *pcm = (image_geometry::PinholeCameraModel *)(intval(argv[0]));
  if(!isvector(argv[1])) error(E_NOVECTOR);
  eusfloat_t *pos = argv[1]->c.fvec.fv;

  cv::Point3d xyz = cv::Point3d(pos[0]/1000.0, pos[1]/1000.0, pos[2]/1000.0);
  cv::Point2d uv = pcm->project3dToPixel(xyz);

  pointer vs = makefvector(2);
  vpush(vs);
  vs->c.fvec.fv[0] = uv.x;
  vs->c.fvec.fv[1] = uv.y;
  vpop();
  return(vs);
}
pointer EUSPINHOLE_CAMERA_MODEL_PROJECT_PIXEL_TO_3DRAY(register context *ctx,int n,pointer *argv)
{
  ckarg(2);
  image_geometry::PinholeCameraModel *pcm = (image_geometry::PinholeCameraModel *)(intval(argv[0]));
  if(!isvector(argv[1])) error(E_NOVECTOR);
  eusfloat_t *pixel = argv[1]->c.fvec.fv;

  cv::Point2d uv = cv::Point2d(pixel[0], pixel[1]);
  cv::Point3d xyz = pcm->projectPixelTo3dRay(uv);

  pointer vs = makefvector(3);
  vpush(vs);
  vs->c.fvec.fv[0] = xyz.x;
  vs->c.fvec.fv[1] = xyz.y;
  vs->c.fvec.fv[2] = xyz.z;
  vpop();
  return(vs);
}
// Get a statement
void getstatement(void) {

#if !defined(TINY85)
	chkbreak();
#endif

	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		char *fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (!getnum()) {					
				//longjmp(env, X_EXIT);		// get the conditional; exit on false
				sym = s_eof;				// we're finished here.  move along.
				return;
			}
			if (sym != s_colon) expectedchar(':');
			getsym();	// eat :
			getstatementlist();
		}
	}
	
	else if (sym == s_if) {
		getsym(); 								// fetch the start of the conditional
		if (!getnum()) {
			//longjmp(env, X_EXIT);	// get the conditional; exit on false
			sym = s_eof;
			return;
		}
		if (sym != s_colon) expectedchar(':');
		getsym();	// eat :
		getstatementlist();
	}


#if SKETCH
	// The switch statement: call one of N macros based on a selector value
	// switch <numval>: macroid1, macroid2,.., macroidN
	// numval < 0: numval = 0
	// numval > N: numval = N

	else if (sym == s_switch) {
		getsym();	// eat "switch"
		numvar selector = getnum();	// evaluate the switch value
		if (selector < 0) selector = 0;
		if (sym != s_colon) expectedchar(':');

		// we sit before the first macroid
		// scan and discard the <selector>'s worth of macro ids 
		// that sit before the one we want
		for (;;) {
			getsym();	// get an id, sets symval to its eeprom addr as a side effect
			if (sym != s_macro) expected (6);		// TODO: define M_macro instead of 6
			getsym();	// eat id, get separator; assume symval is untouched
			if ((sym == s_semi) || (sym == s_eof)) break;	// last case is default so we exit always
			if (sym != s_comma) expectedchar(',');
			if (!selector) break;		// ok, this is the one we want to execute
			selector--;					// one down...
		}

		// call the macro whose addr is squirreled in symval all this time
		// on return, the parser is ready to pick up where we left off
		doMacroCall(symval);

		// scan past the rest of the unused switch options, if any
		// TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space
		while ((sym != s_semi) && (sym != s_eof)) getsym();		// scan to end of statement without executing
	}
#endif


	else if ((sym == s_macro) || (sym == s_undef)) {		// macro def or ref
		getsym();						// scan past macro name to next symbol: ; or :=
		if (sym == s_define) {			// macro definition: macroid := strvalue
			// to define the macro, we need to copy the id somewhere on the stack
			// to avoid having this local buffer in every getstatement stack frame,
			// we break out defineMacro here to a separate function that only eats that
			// stack in the case that a macro is being defined
#ifdef TINY85
			unexpected(M_defmacro);
#else
			defineMacro();
#endif
		}
		else if ((sym == s_semi) || (sym == s_eof)) {	// valid macro reference: let's call it
#if SKETCH
			doMacroCall(symval);			// parseid stashes the macro address in symval
#else
			char op = sym;					// save sym for restore
			expval = findKey(idbuf);		// assumes id in idbuf isn't clobbered since getsym() above
			if (expval >= 0) {
				char *fetchmark = fetchptr;			// save the current parse pointer

				// call the macro
				calleeprommacro(findend(expval));	// register the macro into the parser stream
				getsym();
				getstatementlist();		// parse and execute the macro code here
				if (sym != s_eof) expected(M_eof);

				// restore parsing context so we can resume cleanly
				fetchptr = fetchmark;	// restore pointer
				primec();				// and inchar
				sym = op;				// restore saved sym: s_semi or s_eof
			} else unexpected(M_id);
#endif
		}
		else expectedchar(';');
		//else getexpression();		// assume it was macro1+32+macro2...
	}
	
	else if (sym == s_run) {	// run macroname
		getsym();
		if (sym != s_macro) unexpected(M_id);

#if 0
		// address of macroid is in symval via parseid
		startTask(kludge(symval));
		getsym();
#else
		// address of macroid is in symval via parseid
		// check for [,snoozeintervalms]
		getsym();	// eat macroid to check for comma; symval untouched
		if (sym == s_comma) {
			vpush(symval);
			getsym();			// eat the comma
			getnum();			// get a number or else
			startTask(kludge(vpop()), expval);
		}
		else startTask(kludge(symval), 0);
#endif
	}
	else if (sym == s_stop) {
		getsym();
		if (sym == s_mul) {						// stop * stops all tasks
			initTaskList();
			getsym();
		}
		else if ((sym == s_semi) || (sym == s_eof)) {
			if (background) stopTask(curtask);	// stop with no args stops the current task IF we're in back
			else initTaskList();				// in foreground, stop all
		}
		else stopTask(getnum());
	}

	else if (sym == s_boot) reboot();

#if !defined(TINY85)
	else if (sym == s_rm) {		// rm "sym" or rm *
		getsym();
		if (sym == s_macro) {
			eraseentry(idbuf);
		} 
		else if (sym == s_mul) nukeeeprom();
		else expected(M_id);
		getsym();
	}
	else if (sym == s_ps) showTaskList();
	else if (sym == s_peep) 	{ getsym(); cmd_peep(); }
	else if (sym == s_ls) 		{ getsym(); cmd_ls(); }
	else if (sym == s_help) 	{ getsym(); cmd_help(); }
	else if (sym == s_print) 	{ getsym(); cmd_print(); }
#endif

#ifdef HEX_UPLOAD
	// a line beginning with a colon is treated as a hex record
	// containing data to upload to eeprom
	//
	// TODO: verify checksum
	//
	else if (sym == s_colon) {
		// fetchptr points at the byte count
		byte byteCount = gethex(2);		// 2 bytes byte count
		int addr = gethex(4);			// 4 bytes address
		byte recordType = gethex(2);	// 2 bytes record type; now fetchptr -> data
		if (recordType == 1) reboot();	// reboot on EOF record (01)
		if (recordType != 0) return;	// we only handle the data record (00)
		if (addr == 0) nukeeeprom();	// auto-clear eeprom on write to 0000
		while (byteCount--) eewrite(addr++, gethex(2));		// update the eeprom
		gethex(2);						// discard the checksum
		getsym();						// and re-prime the parser
	}
#endif

	else  {
		getexpression();
	}
}
// Get a statement
numvar getstatement(void) {
numvar retval = 0;
//char *fetchmark;
numvar fetchmark;

	chkbreak();

	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		//fetchmark = fetchptr;
		fetchmark = markparsepoint();
		for (;;) {
			//fetchptr = fetchmark;			// restore to mark
			//primec();						// set up for mr. getsym()
			returntoparsepoint(fetchmark, 0);
			getsym(); 						// fetch the start of the conditional
			if (getnum()) {
				retval = getstatement();
				if (sym == s_returning) break;	// exit if we caught a return
			}
			else {
				skipstatement();
				break;
			}
		}
	}
	
	else if (sym == s_if) {
		getsym();			// eat "if"
		if (getnum()) {
			retval = getstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				skipstatement();
			}
		} else {
			skipstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				retval = getstatement();
			}
		}
	}
	else if (sym == s_lcurly) {
		getsym(); 	// eat "{"
		while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement();
		if (sym == s_rcurly) getsym();	// eat "}"
	}
	else if (sym == s_return) {
		getsym();	// eat "return"
		if ((sym != s_eof) && (sym != s_semi)) retval = getnum();
		sym = s_returning;		// signal we're returning up the line
	}
	else if (sym == s_switch) retval = getswitchstatement();

	else if (sym == s_function) cmd_function();

	else if (sym == s_run) {	// run macroname
		getsym();
		if ((sym != s_script_eeprom) && (sym != s_script_progmem) &&
			(sym != s_script_file)) unexpected(M_id);

		// address of macroid is in symval via parseid
		// check for [,snoozeintervalms]
		getsym();	// eat macroid to check for comma; symval untouched
		if (sym == s_comma) {
			vpush(symval);
			getsym();			// eat the comma
			getnum();			// get a number or else
			startTask(vpop(), expval);
		}
		else startTask(symval, 0);
	}

	else if (sym == s_stop) {
		getsym();
		if (sym == s_mul) {						// stop * stops all tasks
			initTaskList();
			getsym();
		}
		else if ((sym == s_semi) || (sym == s_eof)) {
			if (background) stopTask(curtask);	// stop with no args stops the current task IF we're in back
			else initTaskList();				// in foreground, stop all
		}
		else stopTask(getnum());
	}

	else if (sym == s_boot) reboot();
	else if (sym == s_rm) {		// rm "sym" or rm *
		getsym();
		if (sym == s_script_eeprom) {
			eraseentry(idbuf);
		} 
		else if (sym == s_mul) nukeeeprom();
		else if (sym != s_undef) expected(M_id);
		getsym();
	}
	else if (sym == s_ps) 		{ getsym();	showTaskList(); }
	else if (sym == s_peep) 	{ getsym(); cmd_peep(); }
	else if (sym == s_ls) 		{ getsym(); cmd_ls(); }
	else if (sym == s_help) 	{ getsym(); cmd_help(); }
	else if (sym == s_print) 	{ getsym(); cmd_print(); }
	else if (sym == s_semi)		{ ; }	// ;)

#ifdef HEX_UPLOAD
	// a line beginning with a colon is treated as a hex record
	// containing data to upload to eeprom
	//
	// TODO: verify checksum
	//
	else if (sym == s_colon) {
		// fetchptr points at the byte count
		byte byteCount = gethex(2);		// 2 bytes byte count
		int addr = gethex(4);			// 4 bytes address
		byte recordType = gethex(2);	// 2 bytes record type; now fetchptr -> data
		if (recordType == 1) reboot();	// reboot on EOF record (01)
		if (recordType != 0) return;	// we only handle the data record (00)
		if (addr == 0) nukeeeprom();	// auto-clear eeprom on write to 0000
		while (byteCount--) eewrite(addr++, gethex(2));		// update the eeprom
		gethex(2);						// discard the checksum
		getsym();						// and re-prime the parser
	}
#endif

	else getexpression();

	if (sym == s_semi) getsym();		// eat trailing ';'
	return retval;
}
Beispiel #13
0
//
//	Recursive descent parser, old-school style.
//
void getfactor(void) {
numvar thesymval = symval;
byte thesym = sym;
	getsym();		// eat the sym we just saved

	switch (thesym) {
		case s_nval:
			vpush(thesymval);
			break;
			
		case s_nvar:
			if (sym == s_equals) {		// assignment, push is after the break;
				getsym();
				assignVar(thesymval, getnum());
			}
			else if (sym == s_incr) {	// postincrement nvar++
				vpush(getVar(thesymval));
				assignVar(thesymval, getVar(thesymval) + 1);
				getsym();
				break;
			}
			else if (sym == s_decr) {	// postdecrement nvar--
				vpush(getVar(thesymval));
				assignVar(thesymval, getVar(thesymval) - 1);
				getsym();
				break;
			}
			vpush(getVar(thesymval));			// both assignment and reference get pushed here
			break;

		case s_nfunct:
			dofunctioncall(thesymval);			// get its value onto the stack
			break;

		// Script-function-returning-value used as a factor
		case s_script_eeprom:				// macro returning value
			callscriptfunction(SCRIPT_EEPROM, findend(thesymval));
			break;

		case s_script_progmem:
			callscriptfunction(SCRIPT_PROGMEM, thesymval);
			break;

		case s_script_file:
			callscriptfunction(SCRIPT_FILE, (numvar) 0);	// name implicitly in idbuf!
			break;

		case s_apin:					// analog pin reference like a0
			if (sym == s_equals) { 		// digitalWrite or analogWrite
				getsym();
				analogWrite(thesymval, getnum());
				vpush(expval);
			}
			else vpush(analogRead(thesymval));
			break;

		case s_dpin:					// digital pin reference like d1
			if (sym == s_equals) { 		// digitalWrite or analogWrite
				getsym();
				digitalWrite(thesymval, getnum());
				vpush(expval);
			}
			else vpush(digitalRead(thesymval));
			break;

		case s_incr:
			if (sym != s_nvar) expected(M_var);
			assignVar(symval, getVar(symval) + 1);
			vpush(getVar(symval));
			getsym();
			break;

		case s_decr:		// pre decrement
			if (sym != s_nvar) expected(M_var);
			assignVar(symval, getVar(symval) - 1);
			vpush(getVar(symval));
			getsym();
			break;

		case s_arg:			// arg(n) - argument value
			if (sym != s_lparen) expectedchar(s_lparen);
			getsym(); 		// eat '('
			vpush(getarg(getnum()));
			if (sym != s_rparen) expectedchar(s_rparen);
			getsym();		// eat ')'
			break;

		case s_lparen:  // expression in parens
			getexpression();
			if (exptype != s_nval) expected(M_number);
			if (sym != s_rparen) missing(M_rparen);
			vpush(expval);
			getsym();	// eat the )
			break;

		//
		// The Family of Unary Operators, which Bind Most Closely to their Factor
		//
		case s_add:			// unary plus (like +3) is kind of a no-op
			getfactor();	// scan a factor and leave its result on the stack
			break;			// done
	
		case s_sub:			// unary minus (like -3)
			getfactor();
			vpush(-vpop());	// similar to above but we adjust the stack value
			break;
	
		case s_bitnot:
			getfactor();
			vpush(~vpop());
			break;
	
		case s_logicalnot:
			getfactor();
			vpush(!vpop());
			break;

		case s_bitand:		// &var gives address-of-var; &macro gives eeprom address of macro
			if (sym == s_nvar) vpush((numvar) &vars[symval]);
			else if (sym == s_script_eeprom) vpush(symval);
			else expected(M_var);
			getsym();		// eat the var reference
			break;

		case s_mul:			// *foo is contents-of-address-foo; *foo=bar is byte poke assignment

/*****
// what is really acceptable for an lvalue here? ;)
//	*y = 5 is failing now by assigning 5 to y before the * is dereferenced
//	due to calling getfactor
//	everything else works :(
*****/
			getfactor();
#if 0
			if (sym == s_equals) {
				getsym();	// eat '='
				getexpression();
				* (volatile byte *) vpop() = (byte) expval;
				vpush((numvar) (byte) expval);
			} 
			else 
#endif
			vpush((numvar) (* (volatile byte *) vpop()));
			break;

		default: 
			unexpected(M_number);
	}

}
Beispiel #14
0
void vop(byte op)  {
numvar x,y;
	x = vpop(); y = vpop();
	switch (op) {
		case s_add:			vpush(y + x);	break;
		case s_sub:			vpush(y - x);	break;
		case s_mul:			vpush(y * x);	break;
		case s_div:			vpush(y / x);	break;
		case s_mod:			vpush(y % x);	break;
		case s_lt:			vpush(y < x);	break;
		case s_gt:			vpush(y > x);	break;
		case s_le:	 		vpush(y <= x);	break;
		case s_ge:	 		vpush(y >= x);	break;
		case s_logicalne: 	vpush(y != x);	break;
		case s_logicaland:	vpush(y && x);	break;
		case s_logicalor:	vpush(y || x);	break;
		case s_logicaleq:	vpush(y == x);	break;
		case s_bitor:		vpush(y | x);	break;
		case s_bitand:		vpush(y & x);	break;
		case s_xor:			vpush(y ^ x);	break;
		case s_shiftleft:	vpush(y << x);	break;
		case s_shiftright:	vpush(y >> x);	break;
		default: 			unexpected(M_op);
	}
}
Beispiel #15
0
void CodeGen::gen_a(JavaByteCodes op, jtype jt)
{
    if (gen_a_platf(op, jt)) {
        return;
    }
    
    if (gen_a_generic(op, jt)) {
        return;
    }
    
    if (is_f(jt) && gen_a_f(op, jt)) {
        return;
    }
    
    if (jt == i32 && gen_a_i32(op)) {
        return;
    }

    unsigned stackFix = 0;
    bool shft = op == OPCODE_ISHL || op == OPCODE_ISHR || op == OPCODE_IUSHR;
    const CallSig* rcs = NULL;
    if (is_f(jt)) {
        assert(jt == dbl64 || jt == flt32);
        char * helper = NULL;
        bool is_dbl = jt == dbl64;
        if (op == OPCODE_INEG) {
            SYNC_FIRST(static const CallSig cs_dbl(CCONV_STDCALL, dbl64, dbl64));
            SYNC_FIRST(static const CallSig cs_flt(CCONV_STDCALL, flt32, flt32));
            rcs = is_dbl? &cs_dbl : &cs_flt;
            stackFix = gen_stack_to_args(true, *rcs, 0, 1);
            helper = is_dbl ? (char*)&rt_h_neg_dbl64 : (char*)&rt_h_neg_flt32;
            gen_call_novm(*rcs, helper, 1);
            runlock(*rcs);
        }
        else {
            //if (m_jframe->dip(1).stype == st_imm && )
            SYNC_FIRST(static const CallSig cs_dbl(CCONV_STDCALL, dbl64, dbl64, dbl64, i32));
            SYNC_FIRST(static const CallSig cs_flt(CCONV_STDCALL, flt32, flt32, flt32, i32));
            rcs = is_dbl? &cs_dbl : &cs_flt;
            stackFix = gen_stack_to_args(true, *rcs, 0, 2);
            helper = is_dbl ? (char*)&rt_h_dbl_a : (char*)&rt_h_flt_a;
            gen_call_novm(*rcs, helper, 2, op);
            runlock(*rcs);
        }
    }
    else if (jt==i64) {
        if (op == OPCODE_INEG) {
            SYNC_FIRST(static const CallSig cs(CCONV_STDCALL, i64, i64));
            rcs = &cs;
            stackFix = gen_stack_to_args(true, *rcs, 0, 1);
            gen_call_novm(*rcs, (void*)&rt_h_neg_i64, 1);
            runlock(*rcs);
        }
        else if (shft) {
            SYNC_FIRST(static const CallSig cs(CCONV_STDCALL, i64, i64, i32, i32));
            rcs = &cs;
            stackFix = gen_stack_to_args(true, *rcs, 0, 2);
            gen_call_novm(*rcs, (void*)&rt_h_i64_shift, 2, op);
            runlock(*rcs);
        }
        else {
            SYNC_FIRST(static const CallSig cs(CCONV_STDCALL, i64, i64, i64, i32));
            rcs = &cs;
            stackFix = gen_stack_to_args(true, *rcs, 0, 2);
            gen_call_novm(*rcs, (void*)&rt_h_i64_a, 2, op);
            runlock(*rcs);
        }
    }
    else {
        assert(jt==i32);
        if (op == OPCODE_INEG) {
            SYNC_FIRST(static const CallSig cs(CCONV_STDCALL, i32, i32));
            rcs = &cs;
            stackFix = gen_stack_to_args(true, *rcs, 0, 1);
            gen_call_novm(*rcs, (void*)&rt_h_neg_i32, 1);
            runlock(*rcs);
        }
        else if (op == OPCODE_IADD || op == OPCODE_ISUB) {
            const Val& op2 = vstack(0);
            vpop();
            rlock(op2);
            const Val& op1 = vstack(0);
            vpop();
            rlock(op1);
            AR ar = valloc(i32);
            Opnd reg(i32, ar);
            //TODO: may eliminate additional register allocation
            mov(reg, op1.as_opnd());
            alu(op == OPCODE_IADD ? alu_add : alu_sub, reg, op2.as_opnd());
            runlock(op1);
            runlock(op2);
            vpush(Val(i32, ar));
            return;
        }
        else {
            SYNC_FIRST(static const CallSig cs(CCONV_STDCALL, i32, i32, i32, i32));
            rcs = &cs;
            stackFix = gen_stack_to_args(true, *rcs, 0, 2);
            gen_call_novm(*rcs, (void*)&rt_h_i32_a, 2, op);
            runlock(*rcs);
        }
    }
    assert(rcs != NULL);
    gen_save_ret(*rcs);
    if (stackFix != 0) {
        alu(alu_sub, sp, stackFix);
    }
}
Beispiel #16
0
bool CodeGen::gen_a_generic(JavaByteCodes op, jtype jt)
{
    if (op == OPCODE_INEG) {
        return false; // later
    }
    if (jt == i32) {
        bool v2_imm = vis_imm(0);
        if (v2_imm &&
            (op == OPCODE_ISHL || op == OPCODE_ISHL || op == OPCODE_IUSHR)) {
            // accept it
        }
        /*else if (v2_imm && (op == OPCODE_IMUL || op == OPCODE_IDIV)) {
            // accept it
        }
        else if (op == OPCODE_IMUL) {
            // accept it
        }*/
        else if (op == OPCODE_IADD || op == OPCODE_ISUB) {
            // accept it
        }
        else if (op == OPCODE_IOR || op == OPCODE_IAND || op == OPCODE_IXOR) {
            // accept it
        }
        else if (vis_imm(0) && m_jframe->size()>1 && vis_imm(1)) {
            // accept it
        }
        else {
            return false;
        }
    }
    else if (is_f(jt)) {
        if (op != OPCODE_IADD && op != OPCODE_ISUB && 
            op != OPCODE_IMUL && op != OPCODE_IDIV) {
            return false;    
        }
    }
    else {
        return false;
    }
    
    bool is_dbl = jt == dbl64;
    unsigned v1_depth = is_dbl?2:1;
    
    if (vis_imm(v1_depth) && vis_imm(0)) {
        const Val& v1 = m_jframe->dip(v1_depth);
        const Val& v2 = m_jframe->dip(0);
        Val res;
        if (jt==dbl64) {
            double d = rt_h_dbl_a(v1.dval(), v2.dval(), op);
            res = Val(d);
        }
        else if (jt==flt32) {
            float f = rt_h_flt_a(v1.fval(), v2.fval(), op);
            res = Val(f);
        }
        else {
            assert(jt==i32);
            int i = rt_h_i32_a(v1.ival(), v2.ival(), op);
            res = Val(i);
        }
        vpop();
        vpop();
        vpush(res);
        return true;
    } // if v1.is_imm() && v2.is_imm()
    

    const Val& v1 = vstack(v1_depth, true);
    Opnd res = v1.as_opnd();
    if (rrefs(v1.reg()) > 1) {
        rlock(v1);
        AR ar = valloc(jt);
        runlock(v1);
        Opnd reg(jt, ar);
        mov(reg, v1.as_opnd());
        res = reg;
    }
    rlock(res);
    rlock(v1);
    const Val& v2 = m_jframe->dip(0);
/*    if (false )v2.
        
#ifdef _IA32_
        // on IA32 can use address in a displacement
        alu(to_alu(op), v1, ar_x, (int)v2.addr());
#else
        AR addr = valloc(jobj); rlock(addr);
        movp(addr, v2.addr());
        alu_mem(jt, to_alu(op), r1, addr);
        runlock(addr);
#endif
    }
    else */
    if(v2.is_mem()) {
        // Everyone can do 'reg, mem' operation
        alu(to_alu(op), res, v2.as_opnd());
    }
    else if(v2.is_imm() && jt==i32) {
        // 'reg, imm' is only for i32 operations
        alu(to_alu(op), res, v2.ival());
    }
    else {
        Opnd v2 = vstack(0, true).as_opnd();
        alu(to_alu(op), res, v2);
    }
    vpop();
    vpop();
    runlock(v1);
    runlock(res);
    vpush(res);

    return true;
}
// Get a statement
numvar getstatement(void) {
numvar retval = 0;
char *fetchmark;

	chkbreak();

//#define LINEMODE
#ifdef LINEMODE
	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		char *fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (!getnum()) {					
				//longjmp(env, X_EXIT);		// get the conditional; exit on false
				sym = s_eof;				// we're finished here.  move along.
				return;
			}
			if (sym != s_colon) expectedchar(':');
			getsym();	// eat :
			getstatementlist();
		}
	}
	else if (sym == s_if) {
		getsym(); 								// fetch the start of the conditional
		if (!getnum()) {
			//longjmp(env, X_EXIT);	// get the conditional; exit on false
			sym = s_eof;
			return;
		}
		if (sym != s_colon) expectedchar(':');
		getsym();	// eat :
		getstatementlist();
	}

	// The switch statement: call one of N macros based on a selector value
	// switch <numval>: macroid1, macroid2,.., macroidN
	// numval < 0: numval = 0
	// numval > N: numval = N

	else if (sym == s_switch) {
		getsym();	// eat "switch"
		numvar selector = getnum();	// evaluate the switch value
		if (selector < 0) selector = 0;
		if (sym != s_colon) expectedchar(':');

		// we sit before the first macroid
		// scan and discard the <selector>'s worth of macro ids 
		// that sit before the one we want
		for (;;) {
			getsym();	// get an id, sets symval to its eeprom addr as a side effect
			if (sym != s_macro) expected (6);		// TODO: define M_macro instead of 6
			getsym();	// eat id, get separator; assume symval is untouched
			if ((sym == s_semi) || (sym == s_eof)) break;	// last case is default so we exit always
			if (sym != s_comma) expectedchar(',');
			if (!selector) break;		// ok, this is the one we want to execute
			selector--;					// one down...
		}

		// call the macro whose addr is squirreled in symval all this time
		// on return, the parser is ready to pick up where we left off
		domacrocall(symval);

		// scan past the rest of the unused switch options, if any
		// TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space
		while ((sym != s_semi) && (sym != s_eof)) getsym();		// scan to end of statement without executing
	}

#else
	// new statement handling
	if (sym == s_while) {
		// at this point sym is pointing at s_while, before the conditional expression
		// save fetchptr so we can restart parsing from here as the while iterates
		fetchmark = fetchptr;
		for (;;) {
			fetchptr = fetchmark;			// restore to mark
			primec();						// set up for mr. getsym()
			getsym(); 						// fetch the start of the conditional
			if (getnum()) {
				retval = getstatement();
				if (sym == s_returning) break;	// exit if we caught a return
			}
			else {
				skipstatement();
				break;
			}
		}
	}
	
	else if (sym == s_if) {
		getsym();			// eat "if"
		if (getnum()) {
			retval = getstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				skipstatement();
			}
		} else {
			skipstatement();
			if (sym == s_else) {
				getsym();	// eat "else"
				retval = getstatement();
			}
		}
	}
	else if (sym == s_lcurly) {
		getsym(); 	// eat "{"
		while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement();
		if (sym == s_rcurly) getsym();	// eat "}"
	}
	else if (sym == s_return) {
		getsym();	// eat "return"
		if ((sym != s_eof) && (sym != s_semi)) retval = getnum();
		sym = s_returning;		// signal we're returning up the line
	}
	else if (sym == s_switch) retval = getswitchstatement();

	else if (sym == s_function) cmd_function();

#endif


	else if (sym == s_run) {	// run macroname
		getsym();
		if (sym != s_macro) unexpected(M_id);

		// address of macroid is in symval via parseid
		// check for [,snoozeintervalms]
		getsym();	// eat macroid to check for comma; symval untouched
		if (sym == s_comma) {
			vpush(symval);
			getsym();			// eat the comma
			getnum();			// get a number or else
			startTask(kludge(vpop()), expval);
		}
		else startTask(kludge(symval), 0);
	}

	else if (sym == s_stop) {
		getsym();
		if (sym == s_mul) {						// stop * stops all tasks
			initTaskList();
			getsym();
		}
		else if ((sym == s_semi) || (sym == s_eof)) {
			if (background) stopTask(curtask);	// stop with no args stops the current task IF we're in back
			else initTaskList();				// in foreground, stop all
		}
		else stopTask(getnum());
	}

	else if (sym == s_boot) reboot();

#if !defined(TINY85)
	else if (sym == s_rm) {		// rm "sym" or rm *
		getsym();
		if (sym == s_macro) {
			eraseentry(idbuf);
		} 
		else if (sym == s_mul) nukeeeprom();
		else if (sym != s_undef) expected(M_id);
		getsym();
	}
	else if (sym == s_ps) 		{ getsym();	showTaskList(); }
	else if (sym == s_peep) 	{ getsym(); cmd_peep(); }
	else if (sym == s_ls) 		{ getsym(); cmd_ls(); }
	else if (sym == s_help) 	{ getsym(); cmd_help(); }
	else if (sym == s_print) 	{ getsym(); cmd_print(); }
	else if (sym == s_semi)		{ ; }	// ;)
#endif

#ifdef HEX_UPLOAD
	// a line beginning with a colon is treated as a hex record
	// containing data to upload to eeprom
	//
	// TODO: verify checksum
	//
	else if (sym == s_colon) {
		// fetchptr points at the byte count
		byte byteCount = gethex(2);		// 2 bytes byte count
		int addr = gethex(4);			// 4 bytes address
		byte recordType = gethex(2);	// 2 bytes record type; now fetchptr -> data
		if (recordType == 1) reboot();	// reboot on EOF record (01)
		if (recordType != 0) return;	// we only handle the data record (00)
		if (addr == 0) nukeeeprom();	// auto-clear eeprom on write to 0000
		while (byteCount--) eewrite(addr++, gethex(2));		// update the eeprom
		gethex(2);						// discard the checksum
		getsym();						// and re-prime the parser
	}
#endif

	else getexpression();

	if (sym == s_semi) getsym();		// eat trailing ';'
	return retval;
}
Beispiel #18
0
int main()
{
	int type;
	double op2;
	char tmp;
	char s[MAXOP];

	while ((type = getop(s)) != EOF) {
		switch (type) {
		case NUMBER:
			push(atof(s));
			break;
		case VARIABLE:
			push(var[s[0] - 'a']);
			vpush(s[0]);
			break;
		case '=':
			tmp = vpop();
			duplicate_stack_top();
			var[tmp - 'a'] = pop();
			break;
		case '+':
			push(pop() + pop());
			break;
		case '*':
			push(pop() * pop());
			break;
		case '-':
			op2 = pop();
			push(pop() - op2);
			break;
		case '/':
			op2 = pop();
			if (op2 != 0.0)
				push(pop() / op2);
			else
				printf("error: zero divisor\n");
			break;
		case '%':
			op2 = pop();
			push((int)pop() % (int)op2);
			break;
		case 'S':
			push(sin(pop()));
			break;
		case 'E':
			push(exp(pop()));
			break;
		case 'P':
			op2 = pop();
			push(pow(pop(),op2));
			break;
		case '?':
			print_stack_top();
			break;
		case '~':
			swap_top();
			break;
		case '#':
			duplicate_stack_top();
			break;
		case '@':
			clear();
			break;
		case '\n':
			var['z' - 'a'] = pop();
			printf("\t%.8g\n", var['z' - 'a']);
			break;
		default:
			printf("error: unknown command %s\n", s);
			break;
		}
	}
	return 0;
}