Program: 5523
Project: 5523
Buggy source:
public int emulateOP(long maxCycles) throws EmulationException {
  int pc=readRegister(PC);
  long startCycles=cycles;
  if (interruptsEnabled && servicedInterrupt == -1 && interruptMax >= 0) {
    pc=serviceInterrupt(pc);
  }
  if (cpuOff || flash.blocksCPU()) {
    while (cycles >= nextEventCycles) {
      executeEvents();
    }
    if (interruptsEnabled && interruptMax > 0) {
      return -1;
    }
    if (maxCycles >= 0 && maxCycles < nextEventCycles) {
      cycles=cycles < maxCycles ? maxCycles : cycles;
    }
 else {
      cycles=nextEventCycles;
    }
    return -1;
  }
  CPUMonitor wp=watchPoints[pc];
  if (wp != null) {
    if (breakpointActive) {
      wp.cpuAction(CPUMonitor.EXECUTE,pc,0);
      breakpointActive=false;
      return -1;
    }
    breakpointActive=true;
  }
  wp=globalMonitor;
  if (wp != null) {
    wp.cpuAction(CPUMonitor.EXECUTE,pc,0);
  }
  int pcBefore=pc;
  instruction=read(pc,MODE_WORD);
  int ext3_0=0;
  boolean repeatsInDstReg=false;
  boolean wordx20=false;
  if ((instruction & 0xf800) == 0x1800) {
    extWord=instruction;
    ext3_0=instruction & 0xf;
    pc+=2;
    if ((instruction & 0x80) == 0x80) {
      repeatsInDstReg=true;
    }
    wordx20=(instruction & 0x40) == 0;
    instruction=read(pc,MODE_WORD);
  }
 else {
    extWord=0;
  }
  op=instruction >> 12;
  int sp=0;
  int sr=0;
  int rval=0;
  int repeats=1;
  boolean zeroCarry=false;
  boolean word=(instruction & 0x40) == 0;
  int dstRegister=0;
  int dstAddress=-1;
  boolean dstRegMode=false;
  int dst=0;
  boolean write=false;
  boolean updateStatus=true;
  pc+=2;
  writeRegister(PC,pc);
switch (op) {
case 0:
    op=instruction & 0xf0f0;
  if (!MSP430XArch)   throw new EmulationException("String_Node_Str");
int src=0;
int srcData=(instruction & 0x0f00) >> 8;
int dstData=(instruction & 0x000f);
boolean rrword=true;
switch (op) {
case MOVA_IND:
writeRegister(dstData,readRegister(srcData));
updateStatus=false;
cycles+=3;
break;
case MOVA_IND_AUTOINC:
if (profiler != null && instruction == 0x0110) {
profiler.profileReturn(cpuCycles);
}
writeRegister(PC,pc);
src=readRegister(srcData);
dst=read(src,MODE_WORD20);
writeRegister(srcData,src + 4);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=3;
break;
case MOVA_ABS2REG:
src=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
dst=src + (srcData << 16);
dst=read(dst,MODE_WORD20);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=4;
break;
case MOVA_INDX2REG:
int index=read(pc,MODE_WORD);
int indexModifier=readRegister(srcData);
if (index > 0x8000) {
index=-(0x10000 - index);
}
if (indexModifier > 0x8000) {
indexModifier=-(0x10000 - indexModifier);
}
writeRegister(dstData,read(indexModifier + index,MODE_WORD20));
writeRegister(PC,pc+=2);
updateStatus=false;
cycles+=4;
break;
case MOVA_REG2ABS:
dst=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
write(dst + (dstData << 16),readRegister(srcData),MODE_WORD20);
updateStatus=false;
cycles+=4;
break;
case MOVA_REG2INDX:
index=read(pc,MODE_WORD);
indexModifier=readRegister(dstData);
if (index > 0x8000) {
index=-(0x10000 - index);
}
if (indexModifier > 0x8000) {
indexModifier=-(0x10000 - indexModifier);
}
write(indexModifier + index,readRegister(srcData),MODE_WORD20);
writeRegister(PC,pc+=2);
updateStatus=false;
cycles+=4;
break;
case MOVA_IMM2REG:
src=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
dst=src + (srcData << 16);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=2;
break;
case ADDA_IMM:
int immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
dst=readRegister(dstData) + immData;
writeRegister(dstData,dst);
cycles+=3;
break;
case CMPA_IMM:
{
immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
sr=readRegister(SR);
int destRegValue=readRegister(dstData);
sr&=~(NEGATIVE | ZERO | CARRY| OVERFLOW);
if (destRegValue >= immData) {
sr|=CARRY;
}
if (destRegValue < immData) {
sr|=NEGATIVE;
}
if (destRegValue == immData) {
sr|=ZERO;
}
int cmpTmp=destRegValue - immData;
int b=0x80000;
if (((destRegValue ^ cmpTmp) & b) == 0 && (((destRegValue ^ immData) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
updateStatus=false;
cycles+=3;
break;
}
case SUBA_IMM:
immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
dst=readRegister(dstData) - immData;
writeRegister(dstData,dst);
cycles+=3;
break;
case MOVA_REG:
cycles+=1;
writeRegister(dstData,readRegister(srcData));
break;
case CMPA_REG:
{
sr=readRegister(SR);
sr&=~(NEGATIVE | ZERO | CARRY| OVERFLOW);
int destRegValue=readRegister(dstData);
int srcRegValue=readRegister(srcData);
if (destRegValue >= srcRegValue) {
sr|=CARRY;
}
if (destRegValue < srcRegValue) {
sr|=NEGATIVE;
}
if (destRegValue == srcRegValue) {
sr|=ZERO;
}
int cmpTmp=destRegValue - srcRegValue;
int b=0x80000;
if (((destRegValue ^ cmpTmp) & b) == 0 && (((destRegValue ^ srcRegValue) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
updateStatus=false;
cycles+=1;
break;
}
case ADDA_REG:
dst=readRegister(dstData) + readRegister(srcData);
writeRegister(dstData,dst);
cycles+=1;
break;
case SUBA_REG:
dst=readRegister(dstData) - readRegister(srcData);
writeRegister(dstData,dst);
cycles+=1;
break;
case RRXX_ADDR:
rrword=false;
case RRXX_WORD:
int count=((instruction >> 10) & 0x03) + 1;
dst=readRegister(dstData);
sr=readRegister(SR);
int nxtCarry=0;
int carry=(sr & CARRY) > 0 ? 1 : 0;
if (rrword) {
dst=dst & 0xffff;
}
cycles+=1 + count;
switch (instruction & RRMASK) {
case RRCM:
int dst_low=dst & ((1 << count) - 1);
nxtCarry=(dst & (1 << (count + 1))) > 0 ? CARRY : 0;
dst=dst >> (count);
if (rrword) {
dst|=(dst_low << (17 - count)) | (carry << (16 - count));
}
 else {
dst|=(dst_low << (21 - count)) | (carry << (20 - count));
}
break;
case RRAM:
if ((dst & (rrword ? 0x8000 : 0x80000)) > 0) {
dst=dst | (rrword ? 0xf8000 : 0xf80000);
}
dst=dst >> (count - 1);
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
break;
case RLAM:
dst=dst << (count - 1);
nxtCarry=(dst & (rrword ? 0x8000 : 0x80000)) > 0 ? CARRY : 0;
dst=dst << 1;
break;
case RRUM:
dst=dst >> (count - 1);
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
break;
}
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
dst=dst & (rrword ? 0xffff : 0xfffff);
writeRegister(dstData,dst);
break;
default :
System.out.println("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
throw new EmulationException("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
}
break;
case 1:
{
dstRegister=instruction & 0xf;
if ((op=instruction & CALLA_MASK) > RETI) {
pc=readRegister(PC);
dst=-1;
updateStatus=false;
switch (op) {
case CALLA_IMM:
dst=(dstRegister << 16) | read(pc,MODE_WORD);
pc+=2;
cycles+=5;
break;
case CALLA_ABS:
dst=(dstRegister << 16) | read(pc,MODE_WORD);
dst=read(dst,MODE_WORD20);
pc+=2;
cycles+=7;
break;
default :
int type=MODE_WORD;
int size=2;
sp=readRegister(SP);
switch (op & 0x1f00) {
case PUSHM_A:
type=MODE_WORD20;
size=4;
cycles+=2;
case PUSHM_W:
int n=1 + ((instruction >> 4) & 0x0f);
int regNo=instruction & 0x0f;
for (int i=0; i < n; i++) {
sp-=size;
cycles+=2;
write(sp,this.reg[regNo--],type);
if (regNo < 0) regNo=15;
}
writeRegister(SP,sp);
break;
case POPM_A:
type=MODE_WORD20;
size=4;
cycles+=2;
case POPM_W:
n=1 + ((instruction >> 4) & 0x0f);
regNo=instruction & 0x0f;
for (int i=0; i < n; i++) {
cycles+=2;
this.reg[regNo++]=read(sp,type);
sp+=size;
if (regNo > 15) regNo=0;
}
writeRegister(SP,sp);
break;
default :
System.out.println("String_Node_Str");
throw new EmulationException("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
}
}
if (dst != -1) {
sp=readRegister(SP) - 2;
write(sp,(pc >> 16) & 0xf,MODE_WORD);
sp=sp - 2;
write(sp,pc & 0xffff,MODE_WORD);
writeRegister(SP,sp);
writeRegister(PC,dst);
if (profiler != null) {
profileCall(dst,pc);
}
}
}
 else {
int ad=(instruction >> 4) & 3;
int nxtCarry=0;
op=instruction & 0xff80;
if (op == PUSH || op == CALL) {
sp=readRegister(SP) - 2;
writeRegister(SP,sp);
}
if ((dstRegister == CG1 && ad > AM_INDEX) || dstRegister == CG2) {
dstRegMode=true;
cycles++;
}
 else {
switch (ad) {
case AM_REG:
dstRegMode=true;
cycles++;
break;
case AM_INDEX:
rval=readRegisterCG(dstRegister,ad);
if (rval < 0xffff) {
dstAddress=(rval + read(pc,MODE_WORD)) & 0xffff;
}
 else {
dstAddress=read(pc,MODE_WORD);
if ((dstAddress & 0x8000) > 0) {
dstAddress|=0xf0000;
}
dstAddress+=rval;
dstAddress&=0xfffff;
}
pc+=2;
writeRegister(PC,pc);
cycles+=4;
break;
case AM_IND_REG:
dstAddress=readRegister(dstRegister);
cycles+=3;
break;
case AM_IND_AUTOINC:
if (dstRegister == PC) {
dstAddress=readRegister(PC);
pc+=2;
writeRegister(PC,pc);
}
 else {
dstAddress=readRegister(dstRegister);
writeRegister(dstRegister,dstAddress + (word ? 2 : 1));
}
cycles+=3;
break;
}
}
if (dstRegMode) {
dst=readRegisterCG(dstRegister,ad);
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
if (repeatsInDstReg) {
repeats=1 + readRegister(ext3_0);
}
 else {
repeats=1 + ext3_0;
}
zeroCarry=(extWord & EXTWORD_ZC) > 0;
}
 else {
dst=read(dstAddress,word ? MODE_WORD : MODE_BYTE);
}
while (repeats-- > 0) {
sr=readRegister(SR);
if (repeats >= 0) {
if (zeroCarry) {
sr=sr & ~CARRY;
}
}
switch (op) {
case RRC:
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
if (word) {
dst|=(sr & CARRY) > 0 ? 0x8000 : 0;
}
 else if (wordx20) {
dst|=(sr & CARRY) > 0 ? 0x80000 : 0;
}
 else {
dst|=(sr & CARRY) > 0 ? 0x80 : 0;
}
write=true;
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
break;
case SWPB:
int tmp=dst;
dst=((tmp >> 8) & 0xff) + ((tmp << 8) & 0xff00);
write=true;
break;
case RRA:
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
if (word) {
dst=(dst & 0x8000) | (dst >> 1);
}
 else if (wordx20) {
dst=(dst & 0x80000) | (dst >> 1);
}
 else {
dst=(dst & 0x80) | (dst >> 1);
}
write=true;
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
break;
case SXT:
dst=(dst & 0x80) > 0 ? dst | 0xfff00 : dst & 0x7f;
write=true;
sr=sr & ~(CARRY | OVERFLOW);
if (dst != 0) {
sr|=CARRY;
}
writeRegister(SR,sr);
break;
case PUSH:
if (word) {
write(sp,dst,MODE_WORD);
}
 else {
write(sp,dst & 0xff,MODE_WORD);
}
cycles+=(ad == AM_REG || ad == AM_IND_AUTOINC) ? 2 : 1;
write=false;
updateStatus=false;
break;
case CALL:
pc=readRegister(PC);
write(sp,pc,MODE_WORD);
writeRegister(PC,dst);
cycles+=(ad == AM_REG) ? 3 : (ad == AM_IND_AUTOINC) ? 2 : 1;
if (profiler != null) {
profileCall(dst,pc);
}
write=false;
updateStatus=false;
break;
case RETI:
servicedInterrupt=-1;
sp=readRegister(SP);
sr=read(sp,MODE_WORD);
writeRegister(SR,sr & 0x0fff);
sp=sp + 2;
writeRegister(PC,read(sp,MODE_WORD) | (sr & 0xf000) << 4);
sp=sp + 2;
writeRegister(SP,sp);
write=false;
updateStatus=false;
cycles+=4;
if (debugInterrupts) {
System.out.println("String_Node_Str" + pc + "String_Node_Str"+ reg[PC]+ "String_Node_Str"+ reg[SP]);
}
if (profiler != null) {
profiler.profileRETI(cycles);
}
handlePendingInterrupts();
break;
default :
System.out.println("String_Node_Str" + Utils.hex16(instruction));
}
if (repeats > 0) {
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
}
}
}
}
break;
case 2:
case 3:
int jmpOffset=instruction & 0x3ff;
jmpOffset=(jmpOffset & 0x200) == 0 ? 2 * jmpOffset : -(2 * (0x200 - (jmpOffset & 0x1ff)));
boolean jump=false;
cycles+=2;
sr=readRegister(SR);
switch (instruction & 0xfc00) {
case JNE:
jump=(sr & ZERO) == 0;
break;
case JEQ:
jump=(sr & ZERO) > 0;
break;
case JNC:
jump=(sr & CARRY) == 0;
break;
case JC:
jump=(sr & CARRY) > 0;
break;
case JN:
jump=(sr & NEGATIVE) > 0;
break;
case JGE:
jump=(sr & NEGATIVE) > 0 == (sr & OVERFLOW) > 0;
break;
case JL:
jump=(sr & NEGATIVE) > 0 != (sr & OVERFLOW) > 0;
break;
case JMP:
jump=true;
break;
default :
logw("String_Node_Str" + Utils.binary16(instruction));
}
if (jump) {
writeRegister(PC,pc + jmpOffset);
}
updateStatus=false;
break;
default :
dstRegister=instruction & 0xf;
int srcRegister=(instruction >> 8) & 0xf;
int as=(instruction >> 4) & 3;
dstRegMode=((instruction >> 7) & 1) == 0;
dstAddress=-1;
int srcAddress=-1;
src=0;
if ((srcRegister == CG1 && as > AM_INDEX) || srcRegister == CG2) {
src=CREG_VALUES[srcRegister - 2][as];
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
cycles+=dstRegMode ? 1 : 4;
}
 else {
switch (as) {
case AM_REG:
src=readRegister(srcRegister);
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
cycles+=dstRegMode ? 1 : 4;
if (dstRegister == PC) cycles++;
if (dstRegMode) {
if (repeatsInDstReg) {
repeats=1 + readRegister(ext3_0);
}
 else {
repeats=1 + ext3_0;
}
zeroCarry=(extWord & EXTWORD_ZC) > 0;
}
break;
case AM_INDEX:
srcAddress=readRegisterCG(srcRegister,as) + read(pc,MODE_WORD);
incRegister(PC,2);
cycles+=dstRegMode ? 3 : 6;
break;
case AM_IND_REG:
srcAddress=readRegister(srcRegister);
cycles+=dstRegMode ? 2 : 5;
break;
case AM_IND_AUTOINC:
if (srcRegister == PC) {
srcAddress=readRegister(PC);
pc+=2;
incRegister(PC,2);
cycles+=dstRegMode ? 2 : 5;
}
 else {
srcAddress=readRegister(srcRegister);
incRegister(srcRegister,word ? 2 : 1);
cycles+=dstRegMode ? 2 : 5;
}
if (dstRegister == PC) {
cycles++;
}
break;
}
}
if (dstRegMode) {
if (op != MOV) {
dst=readRegister(dstRegister);
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
}
}
 else {
pc=readRegister(PC);
if (dstRegister == 2) {
dstAddress=read(pc,MODE_WORD);
}
 else {
rval=readRegister(dstRegister);
if (rval < 0xffff) {
dstAddress=(rval + read(pc,MODE_WORD)) & 0xffff;
}
 else {
dstAddress=read(pc,MODE_WORD);
if ((dstAddress & 0x8000) > 0) {
dstAddress|=0xf0000;
}
dstAddress+=rval;
dstAddress&=0xfffff;
}
}
if (op != MOV) dst=read(dstAddress,word ? MODE_WORD : MODE_BYTE);
pc+=2;
incRegister(PC,2);
}
if (srcAddress != -1) {
src=read(srcAddress,word ? MODE_WORD : MODE_BYTE);
}
while (repeats-- > 0) {
sr=readRegister(SR);
if (repeats >= 0) {
if (zeroCarry) {
sr=sr & ~CARRY;
}
}
int tmp=0;
int tmpAdd=0;
switch (op) {
case MOV:
dst=src;
write=true;
updateStatus=false;
if (instruction == RETURN && profiler != null) {
profiler.profileReturn(cpuCycles);
}
break;
case SUB:
tmpAdd=1;
case SUBC:
src=(src ^ 0xffff) & 0xffff;
case ADDC:
if (op == ADDC || op == SUBC) tmpAdd=((sr & CARRY) > 0) ? 1 : 0;
case ADD:
sr&=~(OVERFLOW | CARRY);
int b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
tmp=(src ^ dst) & b;
dst=dst + src + tmpAdd;
int b2=word ? 0xffff : (wordx20 ? 0xfffff : 0xff);
if (dst > b2) {
sr|=CARRY;
}
if (tmp == 0 && ((src ^ dst) & b) != 0) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
write=true;
break;
case CMP:
b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
sr=(sr & ~(CARRY | OVERFLOW)) | (dst >= src ? CARRY : 0);
tmp=(dst - src);
if (((src ^ tmp) & b) == 0 && (((src ^ dst) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
dst=tmp;
break;
case DADD:
if (DEBUG) log("String_Node_Str");
dst=dst + src + ((sr & CARRY) > 0 ? 1 : 0);
write=true;
break;
case BIT:
dst=src & dst;
sr=sr & ~(CARRY | OVERFLOW);
if (dst != 0) {
sr|=CARRY;
}
writeRegister(SR,sr);
break;
case BIC:
dst=(~src) & dst;
write=true;
updateStatus=false;
break;
case BIS:
dst=src | dst;
write=true;
updateStatus=false;
break;
case XOR:
sr=sr & ~(CARRY | OVERFLOW);
b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
if ((src & b) != 0 && (dst & b) != 0) {
sr|=OVERFLOW;
}
dst=src ^ dst;
if (dst != 0) {
sr|=CARRY;
}
write=true;
writeRegister(SR,sr);
break;
case AND:
sr=sr & ~(CARRY | OVERFLOW);
dst=src & dst;
if (dst != 0) {
sr|=CARRY;
}
write=true;
writeRegister(SR,sr);
break;
default :
logw("String_Node_Str" + op + "String_Node_Str"+ pc);
if (EXCEPTION_ON_BAD_OPERATION) {
EmulationException ex=new EmulationException("String_Node_Str" + op + "String_Node_Str"+ pc);
ex.initCause(new Throwable("String_Node_Str" + pc));
throw ex;
}
}
if (repeats > 0 && srcRegister == dstRegister) {
src=dst;
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
}
}
}
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
if (write) {
if (dstRegMode) {
writeRegister(dstRegister,dst);
}
 else {
dstAddress&=0xffff;
write(dstAddress,dst,word ? MODE_WORD : MODE_BYTE);
}
}
if (updateStatus) {
sr=readRegister(SR);
sr=(sr & ~(ZERO | NEGATIVE)) | ((dst == 0) ? ZERO : 0) | (word ? ((dst & 0x8000) > 0 ? NEGATIVE : 0) : (wordx20 ? ((dst & 0x80000) > 0 ? NEGATIVE : 0) : ((dst & 0x80) > 0 ? NEGATIVE : 0)));
writeRegister(SR,sr);
}
while (cycles >= nextEventCycles) {
executeEvents();
}
cpuCycles+=cycles - startCycles;
return pcBefore;
}

Fixed version (ground truth):
public int emulateOP(long maxCycles) throws EmulationException {
  int pc=readRegister(PC);
  long startCycles=cycles;
  if (interruptsEnabled && servicedInterrupt == -1 && interruptMax >= 0) {
    pc=serviceInterrupt(pc);
  }
  if (cpuOff || flash.blocksCPU()) {
    while (cycles >= nextEventCycles) {
      executeEvents();
    }
    if (interruptsEnabled && interruptMax > 0) {
      return -1;
    }
    if (maxCycles >= 0 && maxCycles < nextEventCycles) {
      cycles=cycles < maxCycles ? maxCycles : cycles;
    }
 else {
      cycles=nextEventCycles;
    }
    return -1;
  }
  CPUMonitor wp=watchPoints[pc];
  if (wp != null) {
    if (breakpointActive) {
      wp.cpuAction(CPUMonitor.EXECUTE,pc,0);
      breakpointActive=false;
      return -1;
    }
    breakpointActive=true;
  }
  wp=globalMonitor;
  if (wp != null) {
    wp.cpuAction(CPUMonitor.EXECUTE,pc,0);
  }
  int pcBefore=pc;
  instruction=read(pc,MODE_WORD);
  int ext3_0=0;
  boolean repeatsInDstReg=false;
  boolean wordx20=false;
  if ((instruction & 0xf800) == 0x1800) {
    extWord=instruction;
    ext3_0=instruction & 0xf;
    pc+=2;
    if ((instruction & 0x80) == 0x80) {
      repeatsInDstReg=true;
    }
    wordx20=(instruction & 0x40) == 0;
    instruction=read(pc,MODE_WORD);
  }
 else {
    extWord=0;
  }
  op=instruction >> 12;
  int sp=0;
  int sr=0;
  int rval=0;
  int repeats=1;
  boolean zeroCarry=false;
  boolean word=(instruction & 0x40) == 0;
  int dstRegister=0;
  int dstAddress=-1;
  boolean dstRegMode=false;
  int dst=0;
  boolean write=false;
  boolean updateStatus=true;
  pc+=2;
  writeRegister(PC,pc);
switch (op) {
case 0:
    op=instruction & 0xf0f0;
  if (!MSP430XArch)   throw new EmulationException("String_Node_Str");
int src=0;
int srcData=(instruction & 0x0f00) >> 8;
int dstData=(instruction & 0x000f);
boolean rrword=true;
switch (op) {
case MOVA_IND:
writeRegister(dstData,readRegister(srcData));
updateStatus=false;
cycles+=3;
break;
case MOVA_IND_AUTOINC:
if (profiler != null && instruction == 0x0110) {
profiler.profileReturn(cpuCycles);
}
writeRegister(PC,pc);
src=readRegister(srcData);
dst=read(src,MODE_WORD20);
writeRegister(srcData,src + 4);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=3;
break;
case MOVA_ABS2REG:
src=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
dst=src + (srcData << 16);
dst=read(dst,MODE_WORD20);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=4;
break;
case MOVA_INDX2REG:
int index=read(pc,MODE_WORD);
int indexModifier=readRegister(srcData);
if (index > 0x8000) {
index=-(0x10000 - index);
}
if (indexModifier > 0x8000) {
indexModifier=-(0x10000 - indexModifier);
}
writeRegister(dstData,read(indexModifier + index,MODE_WORD20));
writeRegister(PC,pc+=2);
updateStatus=false;
cycles+=4;
break;
case MOVA_REG2ABS:
dst=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
write(dst + (dstData << 16),readRegister(srcData),MODE_WORD20);
updateStatus=false;
cycles+=4;
break;
case MOVA_REG2INDX:
index=read(pc,MODE_WORD);
indexModifier=readRegister(dstData);
if (index > 0x8000) {
index=-(0x10000 - index);
}
if (indexModifier > 0x8000) {
indexModifier=-(0x10000 - indexModifier);
}
write(indexModifier + index,readRegister(srcData),MODE_WORD20);
writeRegister(PC,pc+=2);
updateStatus=false;
cycles+=4;
break;
case MOVA_IMM2REG:
src=read(pc,MODE_WORD);
writeRegister(PC,pc+=2);
dst=src + (srcData << 16);
writeRegister(dstData,dst);
updateStatus=false;
cycles+=2;
break;
case ADDA_IMM:
int immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
dst=readRegister(dstData) + immData;
writeRegister(dstData,dst);
cycles+=3;
break;
case CMPA_IMM:
{
immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
sr=readRegister(SR);
int destRegValue=readRegister(dstData);
sr&=~(NEGATIVE | ZERO | CARRY| OVERFLOW);
if (destRegValue >= immData) {
sr|=CARRY;
}
if (destRegValue < immData) {
sr|=NEGATIVE;
}
if (destRegValue == immData) {
sr|=ZERO;
}
int cmpTmp=destRegValue - immData;
int b=0x80000;
if (((destRegValue ^ cmpTmp) & b) == 0 && (((destRegValue ^ immData) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
updateStatus=false;
cycles+=3;
break;
}
case SUBA_IMM:
immData=read(pc,MODE_WORD) + (srcData << 16);
writeRegister(PC,pc+=2);
dst=readRegister(dstData) - immData;
writeRegister(dstData,dst);
cycles+=3;
break;
case MOVA_REG:
cycles+=1;
writeRegister(dstData,readRegister(srcData));
break;
case CMPA_REG:
{
sr=readRegister(SR);
sr&=~(NEGATIVE | ZERO | CARRY| OVERFLOW);
int destRegValue=readRegister(dstData);
int srcRegValue=readRegister(srcData);
if (destRegValue >= srcRegValue) {
sr|=CARRY;
}
if (destRegValue < srcRegValue) {
sr|=NEGATIVE;
}
if (destRegValue == srcRegValue) {
sr|=ZERO;
}
int cmpTmp=destRegValue - srcRegValue;
int b=0x80000;
if (((destRegValue ^ cmpTmp) & b) == 0 && (((destRegValue ^ srcRegValue) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
updateStatus=false;
cycles+=1;
break;
}
case ADDA_REG:
dst=readRegister(dstData) + readRegister(srcData);
writeRegister(dstData,dst);
cycles+=1;
break;
case SUBA_REG:
dst=readRegister(dstData) - readRegister(srcData);
writeRegister(dstData,dst);
cycles+=1;
break;
case RRXX_ADDR:
rrword=false;
case RRXX_WORD:
int count=((instruction >> 10) & 0x03) + 1;
dst=readRegister(dstData);
sr=readRegister(SR);
int nxtCarry=0;
int carry=(sr & CARRY) > 0 ? 1 : 0;
if (rrword) {
dst=dst & 0xffff;
}
cycles+=1 + count;
switch (instruction & RRMASK) {
case RRCM:
int dst_low=dst & ((1 << count) - 1);
nxtCarry=(dst & (1 << (count + 1))) > 0 ? CARRY : 0;
dst=dst >> (count);
if (rrword) {
dst|=(dst_low << (17 - count)) | (carry << (16 - count));
}
 else {
dst|=(dst_low << (21 - count)) | (carry << (20 - count));
}
break;
case RRAM:
if ((dst & (rrword ? 0x8000 : 0x80000)) > 0) {
dst=dst | (rrword ? 0xf8000 : 0xf80000);
}
dst=dst >> (count - 1);
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
break;
case RLAM:
dst=dst << (count - 1);
nxtCarry=(dst & (rrword ? 0x8000 : 0x80000)) > 0 ? CARRY : 0;
dst=dst << 1;
break;
case RRUM:
dst=dst >> (count - 1);
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
break;
}
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
dst=dst & (rrword ? 0xffff : 0xfffff);
writeRegister(dstData,dst);
break;
default :
System.out.println("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
throw new EmulationException("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
}
break;
case 1:
{
dstRegister=instruction & 0xf;
if ((op=instruction & CALLA_MASK) > RETI) {
pc=readRegister(PC);
dst=-1;
updateStatus=false;
switch (op) {
case CALLA_IMM:
dst=(dstRegister << 16) | read(pc,MODE_WORD);
pc+=2;
cycles+=5;
break;
case CALLA_ABS:
dst=(dstRegister << 16) | read(pc,MODE_WORD);
dst=read(dst,MODE_WORD20);
pc+=2;
cycles+=7;
break;
default :
int type=MODE_WORD;
int size=2;
sp=readRegister(SP);
switch (op & 0x1f00) {
case PUSHM_A:
type=MODE_WORD20;
size=4;
cycles+=2;
case PUSHM_W:
int n=1 + ((instruction >> 4) & 0x0f);
int regNo=instruction & 0x0f;
for (int i=0; i < n; i++) {
sp-=size;
cycles+=2;
write(sp,this.reg[regNo--],type);
if (regNo < 0) regNo=15;
}
writeRegister(SP,sp);
break;
case POPM_A:
type=MODE_WORD20;
size=4;
cycles+=2;
case POPM_W:
n=1 + ((instruction >> 4) & 0x0f);
regNo=instruction & 0x0f;
for (int i=0; i < n; i++) {
cycles+=2;
this.reg[regNo++]=read(sp,type);
sp+=size;
if (regNo > 15) regNo=0;
}
writeRegister(SP,sp);
break;
default :
System.out.println("String_Node_Str");
throw new EmulationException("String_Node_Str" + Utils.hex16(instruction) + "String_Node_Str"+ Utils.hex16(op));
}
}
if (dst != -1) {
sp=readRegister(SP) - 2;
write(sp,(pc >> 16) & 0xf,MODE_WORD);
sp=sp - 2;
write(sp,pc & 0xffff,MODE_WORD);
writeRegister(SP,sp);
writeRegister(PC,dst);
if (profiler != null) {
profileCall(dst,pc);
}
}
}
 else {
int ad=(instruction >> 4) & 3;
int nxtCarry=0;
op=instruction & 0xff80;
if (op == PUSH || op == CALL) {
sp=readRegister(SP) - 2;
writeRegister(SP,sp);
}
if ((dstRegister == CG1 && ad > AM_INDEX) || dstRegister == CG2) {
dstRegMode=true;
cycles++;
}
 else {
switch (ad) {
case AM_REG:
dstRegMode=true;
cycles++;
break;
case AM_INDEX:
rval=readRegisterCG(dstRegister,ad);
if (rval < 0xffff) {
dstAddress=(rval + read(pc,MODE_WORD)) & 0xffff;
}
 else {
dstAddress=read(pc,MODE_WORD);
if ((dstAddress & 0x8000) > 0) {
dstAddress|=0xf0000;
}
dstAddress+=rval;
dstAddress&=0xfffff;
}
pc+=2;
writeRegister(PC,pc);
cycles+=4;
break;
case AM_IND_REG:
dstAddress=readRegister(dstRegister);
cycles+=3;
break;
case AM_IND_AUTOINC:
if (dstRegister == PC) {
dstAddress=readRegister(PC);
pc+=2;
writeRegister(PC,pc);
}
 else {
dstAddress=readRegister(dstRegister);
writeRegister(dstRegister,dstAddress + (word ? 2 : 1));
}
cycles+=3;
break;
}
}
if (dstRegMode) {
dst=readRegisterCG(dstRegister,ad);
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
if (repeatsInDstReg) {
repeats=1 + readRegister(ext3_0);
}
 else {
repeats=1 + ext3_0;
}
zeroCarry=(extWord & EXTWORD_ZC) > 0;
}
 else {
dst=read(dstAddress,word ? MODE_WORD : MODE_BYTE);
}
while (repeats-- > 0) {
sr=readRegister(SR);
if (repeats >= 0) {
if (zeroCarry) {
sr=sr & ~CARRY;
}
}
switch (op) {
case RRC:
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
dst=dst >> 1;
if (word) {
dst|=(sr & CARRY) > 0 ? 0x8000 : 0;
}
 else if (wordx20) {
dst|=(sr & CARRY) > 0 ? 0x80000 : 0;
}
 else {
dst|=(sr & CARRY) > 0 ? 0x80 : 0;
}
write=true;
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
break;
case SWPB:
int tmp=dst;
dst=((tmp >> 8) & 0xff) + ((tmp << 8) & 0xff00);
write=true;
break;
case RRA:
nxtCarry=(dst & 1) > 0 ? CARRY : 0;
if (word) {
dst=(dst & 0x8000) | (dst >> 1);
}
 else if (wordx20) {
dst=(dst & 0x80000) | (dst >> 1);
}
 else {
dst=(dst & 0x80) | (dst >> 1);
}
write=true;
writeRegister(SR,(sr & ~(CARRY | OVERFLOW)) | nxtCarry);
break;
case SXT:
dst=(dst & 0x80) > 0 ? dst | 0xfff00 : dst & 0x7f;
write=true;
sr=sr & ~(CARRY | OVERFLOW);
if (dst != 0) {
sr|=CARRY;
}
writeRegister(SR,sr);
break;
case PUSH:
if (word) {
write(sp,dst,MODE_WORD);
}
 else {
write(sp,dst & 0xff,MODE_WORD);
}
cycles+=(ad == AM_REG || ad == AM_IND_AUTOINC) ? 2 : 1;
write=false;
updateStatus=false;
break;
case CALL:
pc=readRegister(PC);
write(sp,pc,MODE_WORD);
writeRegister(PC,dst);
cycles+=(ad == AM_REG) ? 3 : (ad == AM_IND_AUTOINC) ? 2 : 1;
if (profiler != null) {
profileCall(dst,pc);
}
write=false;
updateStatus=false;
break;
case RETI:
servicedInterrupt=-1;
sp=readRegister(SP);
sr=read(sp,MODE_WORD);
writeRegister(SR,sr & 0x0fff);
sp=sp + 2;
writeRegister(PC,read(sp,MODE_WORD) | (sr & 0xf000) << 4);
sp=sp + 2;
writeRegister(SP,sp);
write=false;
updateStatus=false;
cycles+=4;
if (debugInterrupts) {
System.out.println("String_Node_Str" + pc + "String_Node_Str"+ reg[PC]+ "String_Node_Str"+ reg[SP]);
}
if (profiler != null) {
profiler.profileRETI(cycles);
}
handlePendingInterrupts();
break;
default :
System.out.println("String_Node_Str" + Utils.hex16(instruction));
}
if (repeats > 0) {
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
}
}
}
}
break;
case 2:
case 3:
int jmpOffset=instruction & 0x3ff;
jmpOffset=(jmpOffset & 0x200) == 0 ? 2 * jmpOffset : -(2 * (0x200 - (jmpOffset & 0x1ff)));
boolean jump=false;
cycles+=2;
sr=readRegister(SR);
switch (instruction & 0xfc00) {
case JNE:
jump=(sr & ZERO) == 0;
break;
case JEQ:
jump=(sr & ZERO) > 0;
break;
case JNC:
jump=(sr & CARRY) == 0;
break;
case JC:
jump=(sr & CARRY) > 0;
break;
case JN:
jump=(sr & NEGATIVE) > 0;
break;
case JGE:
jump=(sr & NEGATIVE) > 0 == (sr & OVERFLOW) > 0;
break;
case JL:
jump=(sr & NEGATIVE) > 0 != (sr & OVERFLOW) > 0;
break;
case JMP:
jump=true;
break;
default :
logw("String_Node_Str" + Utils.binary16(instruction));
}
if (jump) {
writeRegister(PC,pc + jmpOffset);
}
updateStatus=false;
break;
default :
dstRegister=instruction & 0xf;
int srcRegister=(instruction >> 8) & 0xf;
int as=(instruction >> 4) & 3;
dstRegMode=((instruction >> 7) & 1) == 0;
dstAddress=-1;
int srcAddress=-1;
src=0;
if ((srcRegister == CG1 && as > AM_INDEX) || srcRegister == CG2) {
src=CREG_VALUES[srcRegister - 2][as];
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
cycles+=dstRegMode ? 1 : 4;
}
 else {
switch (as) {
case AM_REG:
src=readRegister(srcRegister);
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
cycles+=dstRegMode ? 1 : 4;
if (dstRegister == PC) cycles++;
if (dstRegMode) {
if (repeatsInDstReg) {
repeats=1 + readRegister(ext3_0);
}
 else {
repeats=1 + ext3_0;
}
zeroCarry=(extWord & EXTWORD_ZC) > 0;
}
break;
case AM_INDEX:
{
int sval=readRegisterCG(srcRegister,as);
if (sval < 0xffff) {
srcAddress=(sval + read(pc,MODE_WORD)) & 0xffff;
}
 else {
srcAddress=read(pc,MODE_WORD);
if ((srcAddress & 0x8000) > 0) {
srcAddress|=0xf0000;
}
srcAddress+=sval;
srcAddress&=0xfffff;
}
incRegister(PC,2);
cycles+=dstRegMode ? 3 : 6;
break;
}
case AM_IND_REG:
srcAddress=readRegister(srcRegister);
cycles+=dstRegMode ? 2 : 5;
break;
case AM_IND_AUTOINC:
if (srcRegister == PC) {
srcAddress=readRegister(PC);
pc+=2;
incRegister(PC,2);
cycles+=dstRegMode ? 2 : 5;
}
 else {
srcAddress=readRegister(srcRegister);
incRegister(srcRegister,word ? 2 : 1);
cycles+=dstRegMode ? 2 : 5;
}
if (dstRegister == PC) {
cycles++;
}
break;
}
}
if (dstRegMode) {
if (op != MOV) {
dst=readRegister(dstRegister);
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
}
}
 else {
pc=readRegister(PC);
if (dstRegister == 2) {
dstAddress=read(pc,MODE_WORD);
}
 else {
rval=readRegister(dstRegister);
if (rval < 0xffff) {
dstAddress=(rval + read(pc,MODE_WORD)) & 0xffff;
}
 else {
dstAddress=read(pc,MODE_WORD);
if ((dstAddress & 0x8000) > 0) {
dstAddress|=0xf0000;
}
dstAddress+=rval;
dstAddress&=0xfffff;
}
}
if (op != MOV) dst=read(dstAddress,word ? MODE_WORD : MODE_BYTE);
pc+=2;
incRegister(PC,2);
}
if (srcAddress != -1) {
src=read(srcAddress,word ? MODE_WORD : MODE_BYTE);
}
while (repeats-- > 0) {
sr=readRegister(SR);
if (repeats >= 0) {
if (zeroCarry) {
sr=sr & ~CARRY;
}
}
int tmp=0;
int tmpAdd=0;
switch (op) {
case MOV:
dst=src;
write=true;
updateStatus=false;
if (instruction == RETURN && profiler != null) {
profiler.profileReturn(cpuCycles);
}
break;
case SUB:
tmpAdd=1;
case SUBC:
src=(src ^ 0xffff) & 0xffff;
case ADDC:
if (op == ADDC || op == SUBC) tmpAdd=((sr & CARRY) > 0) ? 1 : 0;
case ADD:
sr&=~(OVERFLOW | CARRY);
int b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
tmp=(src ^ dst) & b;
dst=dst + src + tmpAdd;
int b2=word ? 0xffff : (wordx20 ? 0xfffff : 0xff);
if (dst > b2) {
sr|=CARRY;
}
if (tmp == 0 && ((src ^ dst) & b) != 0) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
write=true;
break;
case CMP:
b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
sr=(sr & ~(CARRY | OVERFLOW)) | (dst >= src ? CARRY : 0);
tmp=(dst - src);
if (((src ^ tmp) & b) == 0 && (((src ^ dst) & b) != 0)) {
sr|=OVERFLOW;
}
writeRegister(SR,sr);
dst=tmp;
break;
case DADD:
if (DEBUG) log("String_Node_Str");
dst=dst + src + ((sr & CARRY) > 0 ? 1 : 0);
write=true;
break;
case BIT:
dst=src & dst;
sr=sr & ~(CARRY | OVERFLOW);
if (dst != 0) {
sr|=CARRY;
}
writeRegister(SR,sr);
break;
case BIC:
dst=(~src) & dst;
write=true;
updateStatus=false;
break;
case BIS:
dst=src | dst;
write=true;
updateStatus=false;
break;
case XOR:
sr=sr & ~(CARRY | OVERFLOW);
b=word ? 0x8000 : (wordx20 ? 0x80000 : 0x80);
if ((src & b) != 0 && (dst & b) != 0) {
sr|=OVERFLOW;
}
dst=src ^ dst;
if (dst != 0) {
sr|=CARRY;
}
write=true;
writeRegister(SR,sr);
break;
case AND:
sr=sr & ~(CARRY | OVERFLOW);
dst=src & dst;
if (dst != 0) {
sr|=CARRY;
}
write=true;
writeRegister(SR,sr);
break;
default :
logw("String_Node_Str" + op + "String_Node_Str"+ pc);
if (EXCEPTION_ON_BAD_OPERATION) {
EmulationException ex=new EmulationException("String_Node_Str" + op + "String_Node_Str"+ pc);
ex.initCause(new Throwable("String_Node_Str" + pc));
throw ex;
}
}
if (repeats > 0 && srcRegister == dstRegister) {
src=dst;
if (word) {
src&=0xffff;
}
 else if (wordx20) {
src&=0xfffff;
}
 else {
src&=0xff;
}
}
}
}
if (word) {
dst&=0xffff;
}
 else if (wordx20) {
dst&=0xfffff;
}
 else {
dst&=0xff;
}
if (write) {
if (dstRegMode) {
writeRegister(dstRegister,dst);
}
 else {
dstAddress&=0xffff;
write(dstAddress,dst,word ? MODE_WORD : MODE_BYTE);
}
}
if (updateStatus) {
sr=readRegister(SR);
sr=(sr & ~(ZERO | NEGATIVE)) | ((dst == 0) ? ZERO : 0) | (word ? ((dst & 0x8000) > 0 ? NEGATIVE : 0) : (wordx20 ? ((dst & 0x80000) > 0 ? NEGATIVE : 0) : ((dst & 0x80) > 0 ? NEGATIVE : 0)));
writeRegister(SR,sr);
}
while (cycles >= nextEventCycles) {
executeEvents();
}
cpuCycles+=cycles - startCycles;
return pcBefore;
}