Exemple #1
0
DTYPE _sbi_getfval(uint8_t type, SBITHREAD* thread, sbi_runtime_t* rt) {
    DTYPE val = _getfch();
    switch (type) {
        case _regid:
        case _varid:
        case _value8:
            break;
        case _value16:
        case _value32:
            val |= (DTYPE)_getfch() << 8; 
            if (type==_value16) break; 
            val |= (DTYPE)_getfch() << 16;
            val |= (DTYPE)_getfch() << 24;
            break;
    }
    return val;
}
Exemple #2
0
/*
	Executes the program
 */
unsigned int _sbi_run(void *rt)       // Runs a SBI program
												// Returns:
												// 					0: 	No errors
												// 					1: 	Reached end (no exit found)
												//					2: 	Program exited
												//					3: 	Wrong instruction code
												//					4: 	Can't understand byte
												//					5: 	User error
{
    if (!rt) return 5;

	RT(rt)->_exec = 1;
	
	byte rd = _getfch();
    byte var1, var1t, var2, var2t, var3, var3t;
    unsigned int i;
    byte b[16];

	switch (rd)
	{
		case _istr_assign:
			var1 = _getfch();
			RT(rt)->_t[var1] = _getfch();
			break;
		case _istr_move:
			var1 = _getfch();
			RT(rt)->_t[var1] = RT(rt)->_t[_getfch()];
			break;
		case _istr_add:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			RT(rt)->_t[_getfch()] = _getval(var1t, var1, rt) + _getval(var2t, var2, rt);
			break;
		case _istr_sub:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			RT(rt)->_t[_getfch()] = _getval(var1t, var1, rt) - _getval(var2t, var2, rt);
			break;
		case _istr_mul:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			RT(rt)->_t[_getfch()] = _getval(var1t, var1, rt) * _getval(var2t, var2, rt);
			break;
		case _istr_div:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			RT(rt)->_t[_getfch()] = _getval(var1t, var1, rt) / _getval(var2t, var2, rt);
			break;
		case _istr_incr:
			RT(rt)->_t[_getfch()]++;
			break;
		case _istr_decr:
			RT(rt)->_t[_getfch()]--;
			break;
		case _istr_inv:
			var1 = _getfch();
			if (RT(rt)->_t[var1]==0) RT(rt)->_t[var1]=1; else RT(rt)->_t[var1]=0;
			break;
		case _istr_tob:
			var1 = _getfch();
			if (RT(rt)->_t[var1]>0) RT(rt)->_t[var1]=1; else RT(rt)->_t[var1]=0;
			break;
		case _istr_cmp:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			if (_getval(var1t, var1, rt)==_getval(var2t, var2, rt)) RT(rt)->_t[_getfch()]=1; else RT(rt)->_t[_getfch()]=0;
			break;
		case _istr_high:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			if (_getval(var1t, var1, rt)>_getval(var2t, var2, rt)) RT(rt)->_t[_getfch()]=1; else RT(rt)->_t[_getfch()]=0;
			break;
		case _istr_low:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			if (_getval(var1t, var1, rt)<_getval(var2t, var2, rt)) RT(rt)->_t[_getfch()]=1; else RT(rt)->_t[_getfch()]=0;
			break;
		case _istr_jump:
			var1t = _getfch();
			var1 = _getfch();
			if (_getfch() > 0)
			{
				for (i=RETURNADDRESSESN-2; i>0; i--) RT(rt)->_returnaddresses[i+1] = RT(rt)->_returnaddresses[i];
				RT(rt)->_returnaddresses[1] = RT(rt)->_returnaddresses[0];
				RT(rt)->_returnaddresses[0] = _getfpos();
			}
			_setfpos(RT(rt)->_labels[_getval(var1t, var1, rt)]);
			break;
		case _istr_cmpjump:
			var1t = _getfch();
			var1 = _getfch();
			var2t = _getfch();
			var2 = _getfch();
			var3t = _getfch();
			var3 = _getfch();
			if (_getfch() > 0)
			{
				for (i=RETURNADDRESSESN-2; i>0; i--) RT(rt)->_returnaddresses[i+1] = RT(rt)->_returnaddresses[i];
				RT(rt)->_returnaddresses[1] = RT(rt)->_returnaddresses[0];
				RT(rt)->_returnaddresses[0] = _getfpos();
			}
			if (_getval(var1t, var1, rt)==_getval(var2t, var2, rt))
			{
				_setfpos(RT(rt)->_labels[_getval(var3t, var3, rt)]);
			}
			break;
		case _istr_ret:
			_setfpos(RT(rt)->_returnaddresses[0]);
			for (i=1; i<RETURNADDRESSESN; i++) RT(rt)->_returnaddresses[i-1] = RT(rt)->_returnaddresses[i];
			break;
		case _istr_debug:
			var1t = _getfch();
			_debug(_getval(var1t, _getfch(), rt));
			break;
		case _istr_error:
			var1t = _getfch();
			_error(_getval(var1t, _getfch(), rt));
			return 5;
			break;
		case _istr_sint:
			var1t = _getfch();
			RT(rt)->_userfid=_getval(var1t, _getfch(), rt);
			break;
		case _istr_int:
            {
			   for (i=0; i<16; i++) b[i] = _getfch();
			   RT(rt)->_userCtx->sbi_user_funcs[RT(rt)->_userfid](b,rt);
            }
			break;
		case _istr_exit:
			return 2;
			break;
		case FOOTER_0:
			if (_getfch()==FOOTER_1) return 1; else return 4;
		default:
			_error(0xB1);
			return 3;
			break;
	}
	
	RT(rt)->_exec = 0;
	
	if (RT(rt)->_intinqueue==1) _interrupt(RT(rt)->_queuedint, rt); // If there are interrupts in
																							// in the queue, do it
	
	return 0;
}
Exemple #3
0
/*
	Begins program execution
 */
unsigned int _sbi_begin(void* rt)       		// Returns:
												// 					0: 	No errors
												//					1: 	No function pointers for _getfch,
												//							_setfpos and _getfpos
												//					2:	Old version of executable format
												//					3:	Invalid program file
{
	// Check function pointers
    if (RT(rt)->_userCtx==0) return 1;
	if ((RT(rt)->_userCtx->getfch==0)||(RT(rt)->_userCtx->setfpos==0)||(RT(rt)->_userCtx->getfpos==0)) return 1;
	
	// Read head
	byte rd = _getfch();
	if (rd!=HEADER_0) return 3;
	rd = _getfch();
	if (rd!=HEADER_1) {
		if ((rd==0x1B)||(rd==0x2B)||(rd==0x3B))
			return 2;
		else
			return 3;
	}
	
	// Getting labels
	if (_getfch()!=LABELSECTION) return 3;
	unsigned int ln = _getfch();
	RT(rt)->_labels = (unsigned int*)malloc(ln * sizeof(int));
	unsigned int c = 0;
	while (ln--)
	{
    RT(rt)->_labels[c] = _getfch() | (_getfch() << 8);
    c++;
	}
	if (_getfch()!=SEPARATOR) return 3;
	
	// Getting interrupts addresses
	if (_getfch()!=INTERRUPTSECTION) return 3;
	ln = _getfch();
	RT(rt)->_interrupts = (unsigned int*)malloc(ln + ln); //ln * sizeof(unsigned int) -> ln * 2 -> ln+ln
	c = 0;
	while (ln--)
	{
    RT(rt)->_interrupts[c] = _getfch() | (_getfch() << 8);
    c++;
	}
	if (_getfch()!=SEPARATOR) return 3;
	
	// Done
	return 0;
}
Exemple #4
0
/*
	Steps the program of one instruction

	Returns: sbi_error_t
*/
sbi_error_t _sbi_step_internal(SBITHREAD* thread, sbi_runtime_t* rt)
{

    uint8_t rd, var1t, var2t, var3t;
    DTYPE var1, var2, var3;
    int i;

	rd = _getfch();
    _TRACE("Instruction code 0x%02x at pcount: 0x%02x thread %d\n", rd, CUR_PCOUNT-1, thread->threadid );
	switch (rd)
	{
		case _istr_assign:
            var1t= _getfch();
			var1 = _getfch();
			_setval(var1t,var1,_getfval(_getfch()), thread);
			break;
		case _istr_move:
            var1t = _getfch();
			var1 = _getfch();
            var2t = _getfch();
            var2 = _getfval(var2t);
            _setval ( var1t, var1,
                      _getval(var2t,var2, thread),
                      thread );
			break;
		case _istr_add:
		case _istr_sub:
        case _istr_mul:
        case _istr_div:
        case _istr_cmp:
        case _istr_high:
        case _istr_low:
        case _istr_lte:
        case _istr_gte:
	    {
	    	DTYPE v1, v2, val;

			var1t = _getfch();
			var1 = _getfval(var1t);
			var2t = _getfch();
			var2 = _getfval(var2t);
            var3t = _getfch();
            var3 = _getfch();
            v1=_getval(var1t,var1, thread); 
            v2=_getval(var2t,var2, thread);
            val = rd == _istr_add ? v1+v2 :
                       rd == _istr_sub ? v1-v2 :
                       rd == _istr_mul ? v1*v2 :
                       rd == _istr_div ? v1/v2 :
                       rd == _istr_cmp ? (v1==v2?1:0) :
                       rd == _istr_high ? (v1>v2?1:0) :
                       rd == _istr_low ? (v1<v2?1:0) :
                       rd == _istr_lte ? (v1<=v2?1:0) :
                       rd == _istr_gte ? (v1>=v2?1:0) :
                       0;
            _setval( var3t, var3, 
                     val,
                     thread );
	    }
			break;
        case _istr_push:
            if (thread->stackp>=STACK_SIZE-1) {
                _error(SBI_STACK_OVERFLOW); // TODO error codes (overflow)
                return SBI_PROG_ERROR;
            }
            var1t=_getfch();
            var1 = _getfval(var1t);
            thread->stack[thread->stackp++] = _getval(var1t,var1,thread);
            break;
        case _istr_pop:
            {
	    	uint8_t n;
                if (thread->stackp==0) {
                    _error(SBI_STACK_UNDERFLOW); // underflow
                    return SBI_PROG_ERROR;
                }
                n = _getfch();
                --thread->stackp;
                if (n) {
                    DTYPE val = thread->stack[thread->stackp];
                    var1t=_getfch();
                    var1=_getfch();
                    _setval(var1t,var1,val,thread);
                }
            }
            break;
		case _istr_incr:
		case _istr_decr:
        case _istr_inv:
        case _istr_tob:
            {
	    	DTYPE val;
                var1t=_getfch();
                var1=_getfch();
                val = _getval( var1t, var1, thread);
                val = rd == _istr_incr ? val+1 :
                      rd == _istr_decr ? val-1 :
                      rd == _istr_inv ? !val :
                      rd == _istr_tob ? (val?1:0) :
                      0;
                _setval(var1t,var1,val,thread);
            }
            break;
		case _istr_jump:
			var1t = _getfch();
			var1 = _getfval(var1t);
			if (_getfch() > 0)
			{
                _RETADDRS[thread->raddr_cnt++] = CUR_PCOUNT;
			}
			CUR_PCOUNT = _LABELS[_getval(var1t, var1, thread)];
			break;
		case _istr_cmpjump:
			var1t = _getfch();
			var1 = _getfval(var1t);
			var2t = _getfch();
			var2 = _getfval(var2t);
			var3t = _getfch();
			var3 = _getfch();
            i=_getfch(); // push ret
			if (_getval(var1t, var1, thread)==_getval(var2t, var2, thread))
			{
			    if (i > 0)
			    {
                    _RETADDRS[thread->raddr_cnt++] = CUR_PCOUNT;
			    }
				CUR_PCOUNT = _LABELS[_getval(var3t, var3, thread)];
			} 
			break;
		case _istr_ret:
            if (thread->raddr_cnt>0) {
			    CUR_PCOUNT = _RETADDRS[--thread->raddr_cnt];
            } else {
                // thread exit
                return SBI_THREAD_EXIT;
            }
			break;
		case _istr_debug:
			var1t = _getfch();
            var1 = _getfval(var1t);
			_debug(_getval(var1t, var1, thread));
			break;
		case _istr_error:
			var1t = _getfch();
            var1 = _getfval(var1t);
			_error(_getval(var1t, var1, thread));
			return SBI_PROG_ERROR;
			break;
        case _istr_print:
            { 
                uint16_t strLoc = _getfch();
                strLoc |= _getfch()<<8;
                if (rt->ctx->print) {
                    int slen, tmplen;
                    char *tmp, cur;
                    PCOUNT curp = CUR_PCOUNT; 
                    CUR_PCOUNT = strLoc;
                    slen = 0;
                    tmplen=0;
                    tmp = NULL;
                    cur;
                    do {
                        cur = _getfch();
                        if (tmplen==slen) {
                           tmp = (char*) realloc ( tmp, slen+20 ); 
                           slen += 20;
                           if (!tmp) return SBI_ALLOC_ERROR;
                        }
                        tmp[tmplen++] = cur;
                    } while (cur != 0);
                    _print(tmp);
                    free(tmp);
                    CUR_PCOUNT = curp; 
                }
            }
            break;
		case _istr_sint:
			var1t = _getfch();
            var1 = _getfval(var1t);
			thread->_userfid=_getval(var1t, var1, thread);
			break;
		case _istr_int:
        case _istr_intr:
            {
	    	uint8_t argc;
		DTYPE *pvals=NULL, r;
                // NOTE should parameters be pushed on the stack instead?
                if (rd==_istr_intr) {
                    var1t=_getfch();
                    var1=_getfch();
                }
                argc = _getfch();
                if (argc>0) {
                    pvals = malloc(sizeof(DTYPE)*(argc));
                    if (!pvals) return SBI_ALLOC_ERROR; 
                }
                for (i=0;i<argc;++i)
                {
                    var2t = _getfch();
                    var2 = _getfval(var2t);
                    pvals[i] = _getval(var2t,var2,thread);
                }
		r = RT->ctx->sbi_user_funcs[thread->_userfid](argc,pvals);
                if (rd==_istr_intr) {
                    _setval(var1t,var1,r,thread);
                }
                if (pvals) free(pvals);
            }
			break;
        case _istr_thread:
            {
	    	int ret;
		uint8_t tId;
                var1t = _getfch();
                var1 = _getfch();
                var2t = _getfch();
                var2 = _getfch();
                ret = _sbi_new_thread_at(_LABELS[_getval(var1t,var1,thread)], rt);
                tId = !ret ? rt->new_threadid : 0;
                _setval( var2t, var2, tId, thread );
                if (ret) _error(ret);
                return ret;
            }
            break;
        case _istr_wait:
            {
	        DTYPE tId;
                var1t = _getfch();
                var1 = _getfch();
                tId = _getval(var1t,var1,thread);
                for (i=0;i<rt->thread_cnt;++i) {
                    if ( rt->_sbi_threads[i]->threadid == tId &&
                         rt->_sbi_threads[i]->status == RUNNING ) {
                         CUR_PCOUNT-=3; // rerun wait
                         break;
                    }
                }
            }
            break;
        case _istr_alive:
            {
	    DTYPE tId, val;
            var1t = _getfch();
            var1 = _getfch();
            var2t = _getfch();
            var2 = _getfch();
            tId = _getval(var1t,var1,thread);
            val = 0; // not running
            for (i=0;i<rt->thread_cnt;++i) {
               if (rt->_sbi_threads[i]->threadid == tId &&
                   rt->_sbi_threads[i]->status == RUNNING) {
                   val=1;
                   break;
               }
            }
            _setval(var2t,var2,val,thread);
            }
            break;
        case _istr_stop:
            {
	    DTYPE tId;
            var1t = _getfch();
            var1 = _getfch();
            tId = _getval(var1t,var1,thread);
            for (i=0;i<rt->thread_cnt;++i) {
               if (rt->_sbi_threads[i]->threadid == tId) {
                  rt->_sbi_threads[i]->status = STOPPED;
                  break;
               }
            }
            }
            break;
		case _istr_exit:
			return SBI_PROG_EXIT;
			break;
		case FOOTER_0:
			if (_getfch()==FOOTER_1) return SBI_PROG_EOF; else return SBI_INSTR_ERROR;
		default:
			_error(SBI_INSTR_ERROR);
            _error(rd);
            _error(CUR_PCOUNT-1);
            _ERR("Instruction error 0x%02x at pcount: 0x%02x thread %d\n", rd, CUR_PCOUNT-1, thread->threadid );
			return SBI_PROG_ERROR;
			break;
	}
	
	return SBI_NOERROR;
}
Exemple #5
0
/*
 * Starts the main thread
 */
sbi_error_t sbi_begin(void *rt) {

    SBITHREAD *thread;
    uint8_t rd;
    unsigned int ln, c;
    int ret;

    if (!rt) return SBI_INVALID_RT;

    // create the main thread
	
	thread = _sbi_createthread(0, (sbi_runtime_t*)rt);
    if (!thread) return SBI_ALLOC_ERROR;
	
    if (!RT->ctx->getfch) return SBI_CTX_ERROR;
 
	// Read head
	if (_getfch()!=HEADER_0) return SBI_HEADER_ERROR;
	rd = _getfch();
	if (rd!=HEADER_1) {
		if ((rd==0x1B)||(rd==0x2B)||(rd==0x3B))
			return SBI_HEADER_OLD;
		else
			return SBI_HEADER_ERROR;
	}
	
	// Getting labels
	if (_getfch()!=LABELSECTION) return SBI_HEADER_ERROR;
	ln = _getfch();
	RT->_labels = malloc(ln * sizeof(LABEL));
	c = 0;
	while (ln--)
	{
			RT->_labels[c] = _getfch() | (_getfch() << 8);
			c++;
	}
	if (_getfch()!=SEPARATOR) return SBI_HEADER_ERROR;
	
	// Getting interrupts addresses
	if (_getfch()!=INTERRUPTSECTION) return SBI_HEADER_ERROR;
	ln = _getfch();
	RT->_interrupts = malloc(ln * sizeof(INTERRUPT));
	c = 0;
	while (ln--)
	{
			RT->_interrupts[c] = _getfch() | (_getfch() << 8);
			c++;
	}
	if (_getfch()!=SEPARATOR) return SBI_HEADER_ERROR;

	ret = _sbi_loadthread(thread, RT);
    return ret;

}