vm.c
Go to the documentation of this file.
00001 /*
00002         Aseba - an event-based framework for distributed robot control
00003         Copyright (C) 2007--2010:
00004                 Stephane Magnenat <stephane at magnenat dot net>
00005                 (http://stephane.magnenat.net)
00006                 and other contributors, see authors.txt for details
00007         
00008         This program is free software: you can redistribute it and/or modify
00009         it under the terms of the GNU Lesser General Public License as published
00010         by the Free Software Foundation, version 3 of the License.
00011         
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU Lesser General Public License for more details.
00016         
00017         You should have received a copy of the GNU Lesser General Public License
00018         along with this program. If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 #include "../common/consts.h"
00022 #include "../common/types.h"
00023 #include "vm.h"
00024 #include <string.h>
00025 
00033 
00034 // TODO: potentially replace by more efficient native asm instruction
00036 #define GET_BIT(v, b) (((v) >> (b)) & 0x1)
00037 
00038 #define BIT_SET(v, b) ((v) |= (1 << (b)))
00039 
00040 #define BIT_CLR(v, b) ((v) &= (~(1 << (b))))
00041 
00042 void AsebaVMSendExecutionStateChanged(AsebaVMState *vm);
00043 
00044 void AsebaVMInit(AsebaVMState *vm)
00045 {
00046         vm->pc = 0;
00047         vm->flags = 0;
00048         vm->breakpointsCount = 0;
00049         
00050         // fill with no event
00051         vm->bytecode[0] = 0;
00052         memset(vm->variables, 0, vm->variablesSize*sizeof(sint16));
00053 }
00054 
00055 uint16 AsebaVMGetEventAddress(AsebaVMState *vm, uint16 event)
00056 {
00057         uint16 eventVectorSize = vm->bytecode[0];
00058         uint16 i;
00059 
00060         // look into event vectors and if event match execute corresponding bytecode
00061         for (i = 1; i < eventVectorSize; i += 2)
00062                 if (vm->bytecode[i] == event)
00063                         return vm->bytecode[i + 1];
00064         return 0;
00065 }
00066 
00067 
00068 uint16 AsebaVMSetupEvent(AsebaVMState *vm, uint16 event)
00069 {
00070         uint16 address = AsebaVMGetEventAddress(vm, event);
00071         if (address)
00072         {
00073                 // if currently executing a thread, notify kill
00074                 if (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00075                 {
00076                         AsebaSendMessageWords(vm, ASEBA_MESSAGE_EVENT_EXECUTION_KILLED, &vm->pc, 1);
00077                 }
00078                 
00079                 vm->pc = address;
00080                 vm->sp = -1;
00081                 AsebaMaskSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK);
00082                 
00083                 // if we are in step by step, notify
00084                 if (AsebaMaskIsSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK))
00085                         AsebaVMSendExecutionStateChanged(vm);
00086         }
00087         return address;
00088 }
00089 
00090 static sint16 AsebaVMDoBinaryOperation(AsebaVMState *vm, sint16 valueOne, sint16 valueTwo, uint16 op)
00091 {
00092         switch (op)
00093         {
00094                 case ASEBA_OP_SHIFT_LEFT: return valueOne << valueTwo;
00095                 case ASEBA_OP_SHIFT_RIGHT: return valueOne >> valueTwo;
00096                 case ASEBA_OP_ADD: return valueOne + valueTwo;
00097                 case ASEBA_OP_SUB: return valueOne - valueTwo;
00098                 case ASEBA_OP_MULT: return valueOne * valueTwo;
00099                 case ASEBA_OP_DIV:
00100                         // check division by zero
00101                         if (valueTwo == 0)
00102                         {
00103                                 if(AsebaVMErrorCB)
00104                                         AsebaVMErrorCB(vm,NULL);
00105                                 vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00106                                 AsebaSendMessageWords(vm, ASEBA_MESSAGE_DIVISION_BY_ZERO, &vm->pc, 1);
00107                                 return 0;
00108                         }
00109                         else
00110                         {
00111                                 return valueOne / valueTwo;
00112                         }
00113                 case ASEBA_OP_MOD: return valueOne % valueTwo;
00114                 
00115                 case ASEBA_OP_BIT_OR: return valueOne | valueTwo;
00116                 case ASEBA_OP_BIT_XOR: return valueOne ^ valueTwo;
00117                 case ASEBA_OP_BIT_AND: return valueOne & valueTwo;
00118                 
00119                 case ASEBA_OP_EQUAL: return valueOne == valueTwo;
00120                 case ASEBA_OP_NOT_EQUAL: return valueOne != valueTwo;
00121                 case ASEBA_OP_BIGGER_THAN: return valueOne > valueTwo;
00122                 case ASEBA_OP_BIGGER_EQUAL_THAN: return valueOne >= valueTwo;
00123                 case ASEBA_OP_SMALLER_THAN: return valueOne < valueTwo;
00124                 case ASEBA_OP_SMALLER_EQUAL_THAN: return valueOne <= valueTwo;
00125                 
00126                 case ASEBA_OP_OR: return valueOne || valueTwo;
00127                 case ASEBA_OP_AND: return valueOne && valueTwo;
00128                 
00129                 default:
00130                 #ifdef ASEBA_ASSERT
00131                 AsebaAssert(vm, ASEBA_ASSERT_UNKNOWN_BINARY_OPERATOR);
00132                 #endif
00133                 return 0;
00134         }
00135 }
00136 
00137 static sint16 AsebaVMDoUnaryOperation(AsebaVMState *vm, sint16 value, uint16 op)
00138 {
00139         switch (op)
00140         {
00141                 case ASEBA_UNARY_OP_SUB: return -value;
00142                 case ASEBA_UNARY_OP_ABS: return value >= 0 ? value : -value;
00143                 case ASEBA_UNARY_OP_BIT_NOT: return ~value;
00144                 
00145                 default:
00146                 #ifdef ASEBA_ASSERT
00147                 AsebaAssert(vm, ASEBA_ASSERT_UNKNOWN_UNARY_OPERATOR);
00148                 #endif
00149                 return 0;
00150         }
00151 }
00152 
00155 void AsebaVMStep(AsebaVMState *vm)
00156 {
00157         uint16 bytecode = vm->bytecode[vm->pc];
00158         
00159         #ifdef ASEBA_ASSERT
00160         if (AsebaMaskIsClear(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00161                 AsebaAssert(vm, ASEBA_ASSERT_STEP_OUT_OF_RUN);
00162         #endif
00163         
00164         switch (bytecode >> 12)
00165         {
00166                 // Bytecode: Stop
00167                 case ASEBA_BYTECODE_STOP:
00168                 {
00169                         AsebaMaskClear(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK);
00170                 }
00171                 break;
00172                 
00173                 // Bytecode: Small Immediate
00174                 case ASEBA_BYTECODE_SMALL_IMMEDIATE:
00175                 {
00176                         sint16 value = ((sint16)(bytecode << 4)) >> 4;
00177                         
00178                         // check sp
00179                         #ifdef ASEBA_ASSERT
00180                         if (vm->sp + 1 >= vm->stackSize)
00181                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_OVERFLOW);
00182                         #endif
00183                         
00184                         // push value in stack
00185                         vm->stack[++vm->sp] = value;
00186                         
00187                         // increment PC
00188                         vm->pc ++;
00189                 }
00190                 break;
00191                 
00192                 // Bytecode: Large Immediate
00193                 case ASEBA_BYTECODE_LARGE_IMMEDIATE:
00194                 {
00195                         // check sp
00196                         #ifdef ASEBA_ASSERT
00197                         if (vm->sp + 1 >= vm->stackSize)
00198                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_OVERFLOW);
00199                         #endif
00200                         
00201                         // push value in stack
00202                         vm->stack[++vm->sp] = vm->bytecode[vm->pc + 1];
00203                         
00204                         // increment PC
00205                         vm->pc += 2;
00206                 }
00207                 break;
00208                 
00209                 // Bytecode: Load
00210                 case ASEBA_BYTECODE_LOAD:
00211                 {
00212                         uint16 variableIndex = bytecode & 0x0fff;
00213                         
00214                         // check sp and variable index
00215                         #ifdef ASEBA_ASSERT
00216                         if (vm->sp + 1 >= vm->stackSize)
00217                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_OVERFLOW);
00218                         if (variableIndex >= vm->variablesSize)
00219                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS);
00220                         #endif
00221                         
00222                         // push value in stack
00223                         vm->stack[++vm->sp] = vm->variables[variableIndex];
00224                         
00225                         // increment PC
00226                         vm->pc ++;
00227                 }
00228                 break;
00229                 
00230                 // Bytecode: Store
00231                 case ASEBA_BYTECODE_STORE:
00232                 {
00233                         uint16 variableIndex = bytecode & 0x0fff;
00234                         
00235                         // check sp and variable index
00236                         #ifdef ASEBA_ASSERT
00237                         if (vm->sp < 0)
00238                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_UNDERFLOW);
00239                         if (variableIndex >= vm->variablesSize)
00240                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS);
00241                         #endif
00242                         
00243                         // pop value from stack
00244                         vm->variables[variableIndex] = vm->stack[vm->sp--];
00245                         
00246                         // increment PC
00247                         vm->pc ++;
00248                 }
00249                 break;
00250                 
00251                 // Bytecode: Load Indirect
00252                 case ASEBA_BYTECODE_LOAD_INDIRECT:
00253                 {
00254                         uint16 arrayIndex;
00255                         uint16 arraySize;
00256                         uint16 variableIndex;
00257                         
00258                         // check sp
00259                         #ifdef ASEBA_ASSERT
00260                         if (vm->sp < 0)
00261                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_UNDERFLOW);
00262                         #endif
00263                         
00264                         // get indexes
00265                         arrayIndex = bytecode & 0x0fff;
00266                         arraySize = vm->bytecode[vm->pc + 1];
00267                         variableIndex = vm->stack[vm->sp];
00268                         
00269                         // check variable index
00270                         if (variableIndex >= arraySize)
00271                         {
00272                                 uint16 buffer[3];
00273                                 buffer[0] = vm->pc;
00274                                 buffer[1] = arraySize;
00275                                 buffer[2] = variableIndex;
00276                                 vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00277                                 AsebaSendMessageWords(vm, ASEBA_MESSAGE_ARRAY_ACCESS_OUT_OF_BOUNDS, buffer, 3);
00278                                 if(AsebaVMErrorCB)
00279                                         AsebaVMErrorCB(vm,NULL);
00280                                 break;
00281                         }
00282                         
00283                         // load variable
00284                         vm->stack[vm->sp] = vm->variables[arrayIndex + variableIndex];
00285                         
00286                         // increment PC
00287                         vm->pc += 2;
00288                 }
00289                 break;
00290                 
00291                 // Bytecode: Store Indirect
00292                 case ASEBA_BYTECODE_STORE_INDIRECT:
00293                 {
00294                         uint16 arrayIndex;
00295                         uint16 arraySize;
00296                         uint16 variableIndex;
00297                         sint16 variableValue;
00298                         
00299                         // check sp
00300                         #ifdef ASEBA_ASSERT
00301                         if (vm->sp < 1)
00302                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_UNDERFLOW);
00303                         #endif
00304                         
00305                         // get value and indexes
00306                         arrayIndex = bytecode & 0x0fff;
00307                         arraySize = vm->bytecode[vm->pc + 1];
00308                         variableValue = vm->stack[vm->sp - 1];
00309                         variableIndex = (uint16)vm->stack[vm->sp];
00310                         
00311                         // check variable index
00312                         if (variableIndex >= arraySize)
00313                         {
00314                                 uint16 buffer[3];
00315                                 buffer[0] = vm->pc;
00316                                 buffer[1] = arraySize;
00317                                 buffer[2] = variableIndex;
00318                                 vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00319                                 AsebaSendMessageWords(vm, ASEBA_MESSAGE_ARRAY_ACCESS_OUT_OF_BOUNDS, buffer, 3);
00320                                 if(AsebaVMErrorCB)
00321                                         AsebaVMErrorCB(vm,NULL);
00322                                 break;
00323                         }
00324                         
00325                         // store variable and change sp
00326                         vm->variables[arrayIndex + variableIndex] = variableValue;
00327                         vm->sp -= 2;
00328                         
00329                         // increment PC
00330                         vm->pc += 2;
00331                 }
00332                 break;
00333                 
00334                 // Bytecode: Unary Arithmetic
00335                 case ASEBA_BYTECODE_UNARY_ARITHMETIC:
00336                 {
00337                         sint16 value, opResult;
00338                         
00339                         // check sp
00340                         #ifdef ASEBA_ASSERT
00341                         if (vm->sp < 0)
00342                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_UNDERFLOW);
00343                         #endif
00344                         
00345                         // get operand
00346                         value = vm->stack[vm->sp];
00347                         
00348                         // do operation
00349                         opResult = AsebaVMDoUnaryOperation(vm, value, bytecode & ASEBA_UNARY_OPERATOR_MASK);
00350                         
00351                         // write result
00352                         vm->stack[vm->sp] = opResult;
00353                         
00354                         // increment PC
00355                         vm->pc ++;
00356                 }
00357                 break;
00358                 
00359                 // Bytecode: Binary Arithmetic
00360                 case ASEBA_BYTECODE_BINARY_ARITHMETIC:
00361                 {
00362                         sint16 valueOne, valueTwo, opResult;
00363                         
00364                         // check sp
00365                         #ifdef ASEBA_ASSERT
00366                         if (vm->sp < 1)
00367                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_UNDERFLOW);
00368                         #endif
00369                         
00370                         // get operands
00371                         valueOne = vm->stack[vm->sp - 1];
00372                         valueTwo = vm->stack[vm->sp];
00373                         
00374                         // do operation
00375                         opResult = AsebaVMDoBinaryOperation(vm, valueOne, valueTwo, bytecode & ASEBA_BINARY_OPERATOR_MASK);
00376                         
00377                         // write result
00378                         vm->sp--;
00379                         vm->stack[vm->sp] = opResult;
00380                         
00381                         // increment PC
00382                         vm->pc ++;
00383                 }
00384                 break;
00385                 
00386                 // Bytecode: Jump
00387                 case ASEBA_BYTECODE_JUMP:
00388                 {
00389                         sint16 disp = ((sint16)(bytecode << 4)) >> 4;
00390                         
00391                         // check pc
00392                         #ifdef ASEBA_ASSERT
00393                         if ((vm->pc + disp < 0) || (vm->pc + disp >=  vm->bytecodeSize))
00394                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS);
00395                         #endif
00396                         
00397                         // do jump
00398                         vm->pc += disp;
00399                 }
00400                 break;
00401                 
00402                 // Bytecode: Conditional Branch
00403                 case ASEBA_BYTECODE_CONDITIONAL_BRANCH:
00404                 {
00405                         sint16 conditionResult;
00406                         sint16 valueOne, valueTwo;
00407                         sint16 disp;
00408                         
00409                         // check sp
00410                         #ifdef ASEBA_ASSERT
00411                         if (vm->sp < 1)
00412                                 AsebaAssert(vm, ASEBA_ASSERT_STACK_OVERFLOW);
00413                         #endif
00414                         
00415                         // evaluate condition
00416                         valueOne = vm->stack[vm->sp - 1];
00417                         valueTwo = vm->stack[vm->sp];
00418                         conditionResult = AsebaVMDoBinaryOperation(vm, valueOne, valueTwo, bytecode & ASEBA_BINARY_OPERATOR_MASK);
00419                         vm->sp -= 2;
00420                         
00421                         // is the condition really true ?
00422                         if (conditionResult && !(GET_BIT(bytecode, ASEBA_IF_IS_WHEN_BIT) && GET_BIT(bytecode, ASEBA_IF_WAS_TRUE_BIT)))
00423                         {
00424                                 // if true disp
00425                                 disp = 2;
00426                         }
00427                         else
00428                         {
00429                                 // if false disp
00430                                 disp = (sint16)vm->bytecode[vm->pc + 1];
00431                         }
00432                         
00433                         // write back condition result
00434                         if (conditionResult)
00435                                 BIT_SET(vm->bytecode[vm->pc], ASEBA_IF_WAS_TRUE_BIT);
00436                         else
00437                                 BIT_CLR(vm->bytecode[vm->pc], ASEBA_IF_WAS_TRUE_BIT);
00438                         
00439                         // check pc
00440                         #ifdef ASEBA_ASSERT
00441                         if ((vm->pc + disp < 0) || (vm->pc + disp >=  vm->bytecodeSize))
00442                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS);
00443                         #endif
00444                         
00445                         // do branch
00446                         vm->pc += disp;
00447                 }
00448                 break;
00449                 
00450                 // Bytecode: Emit
00451                 case ASEBA_BYTECODE_EMIT:
00452                 {
00453                         // emit event
00454                         uint16 start = vm->bytecode[vm->pc + 1];
00455                         uint16 length = vm->bytecode[vm->pc + 2];
00456                         
00457                         #ifdef ASEBA_ASSERT
00458                         if (length > ASEBA_MAX_EVENT_ARG_SIZE)
00459                                 AsebaAssert(vm, ASEBA_ASSERT_EMIT_BUFFER_TOO_LONG);
00460                         #endif
00461                         AsebaSendMessageWords(vm, bytecode & 0x0fff, vm->variables + start, length);
00462                         
00463                         // increment PC
00464                         vm->pc += 3;
00465                 }
00466                 break;
00467                 
00468                 // Bytecode: Call
00469                 case ASEBA_BYTECODE_NATIVE_CALL:
00470                 {
00471                         // call native function
00472                         AsebaNativeFunction(vm, bytecode & 0x0fff);
00473                         
00474                         // increment PC
00475                         vm->pc ++;
00476                 }
00477                 break;
00478                 
00479                 // Bytecode: Subroutine call
00480                 case ASEBA_BYTECODE_SUB_CALL:
00481                 {
00482                         uint16 dest = bytecode & 0x0fff;
00483                         
00484                         // store return value on stack
00485                         vm->stack[++vm->sp] = vm->pc + 1;
00486                         
00487                         // jump
00488                         vm->pc = dest;
00489                 }
00490                 break;
00491                 
00492                 // Bytecode: Subroutine return
00493                 case ASEBA_BYTECODE_SUB_RET:
00494                 {
00495                         // do return
00496                         vm->pc = vm->stack[vm->sp--];
00497                 }
00498                 break;
00499                 
00500                 default:
00501                 #ifdef ASEBA_ASSERT
00502                 AsebaAssert(vm, ASEBA_ASSERT_UNKNOWN_BYTECODE);
00503                 #endif
00504                 break;
00505         } // switch bytecode...
00506 }
00507 
00508 void AsebaVMEmitNodeSpecificError(AsebaVMState *vm, const char* message)
00509 {
00510         uint16 msgLen = strlen(message);
00511 #if defined(__GNUC__)
00512         uint8 buffer[msgLen+3];
00513 #elif defined(_MSC_VER)
00514         uint8 * buffer = _alloca(msgLen+3);
00515 #else
00516         #error "Please provide a stack memory allocator for your compiler"
00517 #endif
00518         
00519         if (AsebaVMErrorCB)
00520                 AsebaVMErrorCB(vm, message);
00521         
00522         vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00523         
00524         ((uint16*)buffer)[0] = bswap16(vm->pc);
00525         buffer[2] = (uint8)msgLen;
00526         memcpy(buffer+3, message, msgLen);
00527         
00528         AsebaSendMessage(vm, ASEBA_MESSAGE_NODE_SPECIFIC_ERROR, buffer, msgLen+3);
00529 }
00530 
00534 uint16 AsebaVMCheckBreakpoint(AsebaVMState *vm)
00535 {
00536         uint16 i;
00537         for (i = 0; i < vm->breakpointsCount; i++)
00538         {
00539                 if (vm->breakpoints[i] == vm->pc)
00540                 {
00541                         AsebaMaskSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK);
00542                         return 1;
00543                 }
00544         }
00545         
00546         return 0;
00547 }
00548 
00551 void AsebaDebugBareRun(AsebaVMState *vm, uint16 stepsLimit)
00552 {
00553         AsebaMaskSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK);
00554         
00555         if (stepsLimit > 0)
00556         {
00557                 // no breakpoint, still poll the mask and check stepsLimit
00558                 while (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK) &&
00559                         AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK) &&
00560                         stepsLimit
00561                 )
00562                 {
00563                         AsebaVMStep(vm);
00564                         stepsLimit--;
00565                         // TODO : send exception event on step limits overflow
00566                 }
00567         }
00568         else
00569         {
00570                 // no breakpoint, only poll the mask
00571                 while (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK) &&
00572                         AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK) 
00573                 )
00574                         AsebaVMStep(vm);
00575         }
00576         
00577         AsebaMaskClear(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK);
00578 }
00579 
00582 void AsebaDebugBreakpointRun(AsebaVMState *vm, uint16 stepsLimit)
00583 {
00584         AsebaMaskSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK);
00585         
00586         if (stepsLimit > 0)
00587         {
00588                 // breakpoints, check before each step, poll the mask, and check stepsLimit
00589                 while (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK) &&
00590                         AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK) &&
00591                         stepsLimit
00592                 )
00593                 {
00594                         if (AsebaVMCheckBreakpoint(vm) != 0)
00595                         {
00596                                 AsebaMaskSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK);
00597                                 AsebaVMSendExecutionStateChanged(vm);
00598                                 return;
00599                         }
00600                         AsebaVMStep(vm);
00601                         stepsLimit--;
00602                         // TODO : send exception event on step limits overflow
00603                 }
00604         }
00605         else
00606         {
00607                 // breakpoints, check before each step and poll the mask
00608                 while (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK) &&
00609                         AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK)
00610                 )
00611                 {
00612                         if (AsebaVMCheckBreakpoint(vm) != 0)
00613                         {
00614                                 AsebaMaskSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK);
00615                                 AsebaVMSendExecutionStateChanged(vm);
00616                                 return;
00617                         }
00618                         AsebaVMStep(vm);
00619                 }
00620         }
00621         
00622         AsebaMaskClear(vm->flags, ASEBA_VM_EVENT_RUNNING_MASK);
00623 }
00624 
00625 uint16 AsebaVMRun(AsebaVMState *vm, uint16 stepsLimit)
00626 {
00627         // if there is nothing to execute, just return
00628         if (AsebaMaskIsClear(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00629                 return 0;
00630         
00631         // if we are running step by step, just return either
00632         if (AsebaMaskIsSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK))
00633                 return 0;
00634         
00635         // run until something stops the vm
00636         if (vm->breakpointsCount)
00637                 AsebaDebugBreakpointRun(vm, stepsLimit);
00638         else
00639                 AsebaDebugBareRun(vm, stepsLimit);
00640         
00641         return 1;
00642 }
00643 
00644 
00646 uint8 AsebaVMSetBreakpoint(AsebaVMState *vm, uint16 pc)
00647 {
00648         #ifdef ASEBA_ASSERT
00649         if (pc >= vm->bytecodeSize)
00650                 AsebaAssert(vm, ASEBA_ASSERT_BREAKPOINT_OUT_OF_BYTECODE_BOUNDS);
00651         #endif
00652         
00653         if (vm->breakpointsCount < ASEBA_MAX_BREAKPOINTS)
00654         {
00655                 vm->breakpoints[vm->breakpointsCount++] = pc;
00656                 return 1;
00657         }
00658         else
00659                 return 0;
00660 }
00661 
00663 uint16 AsebaVMClearBreakpoint(AsebaVMState *vm, uint16 pc)
00664 {
00665         uint16 i;
00666         for (i = 0; i < vm->breakpointsCount; i++)
00667         {
00668                 if (vm->breakpoints[i] == pc)
00669                 {
00670                         uint16 j;
00671                         // displace
00672                         vm->breakpointsCount--;
00673                         for (j = i; j < vm->breakpointsCount; j++)
00674                                 vm->breakpoints[j] = vm->breakpoints[j+1];
00675                         return 1;
00676                 }
00677         }
00678         return 0;
00679 }
00680 
00682 void AsebaVMClearBreakpoints(AsebaVMState *vm)
00683 {
00684         vm->breakpointsCount = 0;
00685 }
00686 
00688 void AsebaVMSendExecutionStateChanged(AsebaVMState *vm)
00689 {
00690         uint16 buffer[2];
00691         buffer[0] = vm->pc;
00692         buffer[1] = vm->flags;
00693         AsebaSendMessageWords(vm, ASEBA_MESSAGE_EXECUTION_STATE_CHANGED, buffer, 2);
00694 }
00695 
00696 void AsebaVMDebugMessage(AsebaVMState *vm, uint16 id, uint16 *data, uint16 dataLength)
00697 {
00698         
00699         // react to global presence
00700         if (id == ASEBA_MESSAGE_GET_DESCRIPTION)
00701         {
00702                 AsebaSendDescription(vm);
00703                 return;
00704         }
00705         
00706         // check if we are the destination, return otherwise
00707         if (bswap16(data[0]) != vm->nodeId)
00708                 return;
00709 
00710         data++;
00711         dataLength--;
00712         
00713         switch (id)
00714         {
00715                 case ASEBA_MESSAGE_SET_BYTECODE:
00716                 {
00717                         uint16 start = bswap16(data[0]);
00718                         uint16 length = dataLength - 1;
00719                         uint16 i;
00720                         #ifdef ASEBA_ASSERT
00721                         if (start + length > vm->bytecodeSize)
00722                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS);
00723                         #endif
00724                         for (i = 0; i < length; i++)
00725                                 vm->bytecode[start+i] = bswap16(data[i+1]);
00726                 }
00727                 // There is no break here because we want to do a reset after a set bytecode
00728                 
00729                 case ASEBA_MESSAGE_RESET:
00730                 vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00731                 // try to setup event, if it fails, return the execution state anyway
00732                 if (AsebaVMSetupEvent(vm, ASEBA_EVENT_INIT) == 0)
00733                         AsebaVMSendExecutionStateChanged(vm);
00734                 break;
00735                 
00736                 case ASEBA_MESSAGE_RUN:
00737                 AsebaMaskClear(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK);
00738                 AsebaVMSendExecutionStateChanged(vm);
00739                 if(AsebaVMRunCB)
00740                         AsebaVMRunCB(vm);
00741                 break;
00742                 
00743                 case ASEBA_MESSAGE_PAUSE:
00744                 AsebaMaskSet(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK);
00745                 AsebaVMSendExecutionStateChanged(vm);
00746                 break;
00747                 
00748                 case ASEBA_MESSAGE_STEP:
00749                 if (AsebaMaskIsSet(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00750                 {
00751                         AsebaVMStep(vm);
00752                         AsebaVMSendExecutionStateChanged(vm);
00753                 }
00754                 break;
00755                 
00756                 case ASEBA_MESSAGE_STOP:
00757                 vm->flags = ASEBA_VM_STEP_BY_STEP_MASK;
00758                 AsebaVMSendExecutionStateChanged(vm);
00759                 break;
00760                 
00761                 case ASEBA_MESSAGE_GET_EXECUTION_STATE:
00762                 AsebaVMSendExecutionStateChanged(vm);
00763                 break;
00764                 
00765                 case ASEBA_MESSAGE_BREAKPOINT_SET:
00766                 {
00767                         uint16 buffer[2];
00768                         buffer[0] = bswap16(data[0]);
00769                         buffer[1] = AsebaVMSetBreakpoint(vm, buffer[0]);
00770                         AsebaSendMessageWords(vm, ASEBA_MESSAGE_BREAKPOINT_SET_RESULT, buffer, 2);
00771                 }
00772                 break;
00773                 
00774                 case ASEBA_MESSAGE_BREAKPOINT_CLEAR:
00775                 AsebaVMClearBreakpoint(vm, bswap16(data[0]));
00776                 break;
00777                 
00778                 case ASEBA_MESSAGE_BREAKPOINT_CLEAR_ALL:
00779                 AsebaVMClearBreakpoints(vm);
00780                 break;
00781                 
00782                 case ASEBA_MESSAGE_GET_VARIABLES:
00783                 {
00784                         uint16 start = bswap16(data[0]);
00785                         uint16 length = bswap16(data[1]);
00786                         #ifdef ASEBA_ASSERT
00787                         if (start + length > vm->variablesSize)
00788                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS);
00789                         #endif
00790                         AsebaSendVariables(vm, start, length);
00791                 }
00792                 break;
00793                 
00794                 case ASEBA_MESSAGE_SET_VARIABLES:
00795                 {
00796                         uint16 start = bswap16(data[0]);
00797                         uint16 length = dataLength - 1;
00798                         uint16 i;
00799                         #ifdef ASEBA_ASSERT
00800                         if (start + length > vm->variablesSize)
00801                                 AsebaAssert(vm, ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS);
00802                         #endif
00803                         for (i = 0; i < length; i++)
00804                                 vm->variables[start+i] = bswap16(data[i+1]);
00805                 }
00806                 break;
00807                 
00808                 case ASEBA_MESSAGE_WRITE_BYTECODE:
00809                 AsebaWriteBytecode(vm);
00810                 break;
00811                 
00812                 case ASEBA_MESSAGE_REBOOT:
00813                 AsebaResetIntoBootloader(vm);
00814                 break;
00815                 
00816                 case ASEBA_MESSAGE_SUSPEND_TO_RAM:
00817                 AsebaPutVmToSleep(vm);
00818                 break;
00819                 
00820                 default:
00821                 break;
00822         }
00823 }
00824 
00825 uint16 AsebaVMShouldDropPacket(AsebaVMState *vm, uint16 source, const uint8* data)
00826 {
00827         uint16 type = bswap16(((const uint16*)data)[0]);
00828         if (type < 0x8000)
00829         {
00830                 // user message
00831                 return !AsebaVMGetEventAddress(vm, type);
00832         }
00833         else if (type >= 0xA000)
00834         {
00835                 // debug message
00836                 uint16 dest = bswap16(((const uint16*)data)[1]);
00837                 if (type == ASEBA_MESSAGE_GET_DESCRIPTION)
00838                         return 0;
00839                 
00840                 // check it is for us
00841                 return dest != vm->nodeId;
00842         }
00843         return 1;
00844 }       
00845 


aseba
Author(s): Stéphane Magnenat
autogenerated on Sun Oct 5 2014 23:46:39