$search
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