Ejemplo n.º 1
0
int Decode(int index, uint8_t bytes[])
{
	Instruction instruction = DecodeInstruction(bytes[index]);
	AddressingMode addressingMode = DecodeAddressingMode(bytes[index]);
	
	/*
	* Exceptions:
	*    STX:
	*        ZeroPageX -> ZeroPageY
	*    LDX:
	*        ZeroPageX -> ZeroPageY
	*        AbsoluteX -> AbsoluteY
	*/
	if ((instruction == STX || instruction == LDX) && addressingMode == ZeroPageX)
		addressingMode = ZeroPageY;
	if (instruction == LDX && addressingMode == AbsoluteX)
		addressingMode = AbsoluteY;

	Dispatch(instruction, addressingMode, index, bytes);
	return FindInstructionLength(addressingMode);
}
Ejemplo n.º 2
0
AddressingMode DecodeAddressingMode(uint8_t instructionByte)
{
	Instruction instruction = DecodeInstruction(instructionByte);
	// Following instructions are always the same addressing mode.
	switch (instruction)
	{
	case CLC:
	case CLD:
	case CLI:
	case CLV:
	case DEX:
	case DEY:
	case INX:
	case INY:
	case NOP:
	case PHA:
	case PHP:
	case PLA:
	case PLP:
	case RTI:
	case RTS:
	case SEC:
	case SEI:
	case TAX:
	case TAY:
	case TSX:
	case TXA:
	case TXS:
	case TYA:
		return Implied;

	case BCC:
	case BCS:
	case BEQ:
	case BMI:
	case BNE:
	case BPL:
	case BVC:
		return Relative;

	case JSR:
		return Absolute;
	}

	uint8_t aaa, bbb, cc;
	aaa = 0b11100000 & instructionByte;
	aaa >>= 5;
	bbb = 0b00011100 & instructionByte;
	bbb >>= 2;
	cc  = 0b00000011 & instructionByte;

	switch (cc)
	{
	   /*
		* Exceptions:
		*     STA does not have an immediate mode.
		*/
	case 0b01:
		switch (bbb)
		{
		case 0:
			return ZeroPageIndirectX;
		case 1:
			return ZeroPage;
		case 0b10:
			return Immediate;
		case 0b11:
			return Absolute;
		case 0b100:
			return ZeroPageIndirectY;
		case 0b101:
			return ZeroPageX;
		case 0b110:
			return AbsoluteY;
		case 0b111:
			return AbsoluteX;
		}
	   /*
	    * Exceptions:
		*    STX:
		*        ZeroPageX -> ZeroPageY
		*    LDX:
		*        ZeroPageX -> ZeroPageY
		*        AbsoluteX -> AbsoluteY
		*/
	case 0b10:
		switch (bbb)
		{
		case 0:
			return Immediate;
		case 1:
			return ZeroPage;
		case 0b10:
			return Accumulator;
		case 0b11:
			return Absolute;
		case 0b101:
			return ZeroPageX;
		case 0b111:
			return AbsoluteX;
		}
	case 0:
		switch (bbb)
		{
		case 0:
			return Immediate;
		case 1:
			return ZeroPage;
		case 0b11:
			return Absolute;
		case 0b101:
			return ZeroPageX;
		case 0b111:
			return AbsoluteX;
		}
	}
	return UnknownAM;
}
Ejemplo n.º 3
0
/* Execute - execute the main code */
int Execute(System *sys, ObjHeap *heap, VMHANDLE main)
{
    size_t stackSize;
    Interpreter *i;
    VMVALUE tmp, tmp2, ind;
    VMHANDLE obj, htmp;
    int8_t tmpb;

    /* allocate the interpreter state */
    if (!(i = (Interpreter *)AllocateFreeSpace(sys, sizeof(Interpreter))))
        return VMFALSE;

    /* make sure there is space left for the stack */
    if ((stackSize = (sys->freeTop - sys->freeNext) / sizeof(VMVALUE)) <= 0)
        return VMFALSE;
        
    /* setup the heap before/after compact functions */
    heap->beforeCompact = NULL;
    heap->afterCompact = AfterCompact;
    heap->compactCookie = i;
    
    /* initialize the interpreter state */
    i->sys = sys;
    i->heap = heap;
    i->stack = (VMVALUE *)((uint8_t *)i + sizeof(Interpreter));
    i->stackTop = i->stack + stackSize;
    
    /* setup to execute the main function */
    i->code = main;
    ObjAddRef(i->code);
    i->cbase = i->pc = GetCodePtr(main);
    i->sp = i->fp = i->stackTop;
    i->hsp = i->hfp = (VMHANDLE *)i->stack - 1;

    if (setjmp(i->sys->errorTarget)) {
        while (i->hsp > (VMHANDLE *)i->stack)
            ObjRelease(i->heap, PopH(i));
        ObjRelease(i->heap, i->code);
        return VMFALSE;
    }

    for (;;) {
#if 0
        ShowStack(i);
        DecodeInstruction(0, 0, i->pc);
#endif
        switch (VMCODEBYTE(i->pc++)) {
        case OP_HALT:
            return VMTRUE;
        case OP_BRT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (Pop(i))
                i->pc += tmp;
            break;
        case OP_BRTSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BRF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!Pop(i))
                i->pc += tmp;
            break;
        case OP_BRFSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BR:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            i->pc += tmp;
            break;
        case OP_NOT:
            *i->sp = (*i->sp ? VMFALSE : VMTRUE);
            break;
        case OP_NEG:
            *i->sp = -*i->sp;
            break;
        case OP_ADD:
            tmp = Pop(i);
            *i->sp += tmp;
            break;
        case OP_SUB:
            tmp = Pop(i);
            *i->sp -= tmp;
            break;
        case OP_MUL:
            tmp = Pop(i);
            *i->sp *= tmp;
            break;
        case OP_DIV:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp / tmp);
            break;
        case OP_REM:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp % tmp);
            break;
        case OP_CAT:
            StringCat(i);
            break;
        case OP_BNOT:
            *i->sp = ~*i->sp;
            break;
        case OP_BAND:
            tmp = Pop(i);
            *i->sp &= tmp;
            break;
        case OP_BOR:
            tmp = Pop(i);
            *i->sp |= tmp;
            break;
        case OP_BXOR:
            tmp = Pop(i);
            *i->sp ^= tmp;
            break;
        case OP_SHL:
            tmp = Pop(i);
            *i->sp <<= tmp;
            break;
        case OP_SHR:
            tmp = Pop(i);
            *i->sp >>= tmp;
            break;
        case OP_LT:
            tmp = Pop(i);
            *i->sp = (*i->sp < tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LE:
            tmp = Pop(i);
            *i->sp = (*i->sp <= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_EQ:
            tmp = Pop(i);
            *i->sp = (*i->sp == tmp ? VMTRUE : VMFALSE);
            break;
        case OP_NE:
            tmp = Pop(i);
            *i->sp = (*i->sp != tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GE:
            tmp = Pop(i);
            *i->sp = (*i->sp >= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GT:
            tmp = Pop(i);
            *i->sp = (*i->sp > tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LIT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPush(i, tmp);
            break;
        case OP_GREF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            CPush(i, GetSymbolPtr(obj)->v.iValue);
            break;
        case OP_GSET:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            GetSymbolPtr(obj)->v.iValue = Pop(i);
            break;
        case OP_LREF:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPush(i, i->fp[(int)tmpb]);
            break;
        case OP_LSET:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            i->fp[(int)tmpb] = Pop(i);
            break;
        case OP_VREF:
            ind = *i->sp;
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->sp = GetIntegerVectorBase(obj)[ind];
            DropH(i, 1);
            break;
        case OP_VSET:
            tmp2 = Pop(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            GetIntegerVectorBase(obj)[ind] = tmp2;
            DropH(i, 1);
            break;
       case OP_LITH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, (VMHANDLE)tmp);
            ObjAddRef(*i->hsp);
            break;
        case OP_GREFH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            ObjAddRef(*i->hsp);
            break;
        case OP_GSETH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            ObjRelease(i->heap, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            GetSymbolPtr((VMHANDLE)tmp)->v.hValue = PopH(i);
            break;
        case OP_LREFH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPushH(i, i->hfp[(int)tmpb]);
            ObjAddRef(*i->hsp);
            break;
        case OP_LSETH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            ObjRelease(i->heap, i->hfp[(int)tmpb]);
            i->hfp[(int)tmpb] = PopH(i);
            break;
        case OP_VREFH:
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->hsp = GetStringVectorBase(obj)[ind];
            ObjAddRef(*i->hsp);
            break;
        case OP_VSETH:
            htmp = PopH(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            ObjRelease(i->heap, GetStringVectorBase(obj)[ind]);
            GetStringVectorBase(obj)[ind] = htmp;
            DropH(i, 1);
            break;
        case OP_RESERVE:
            tmp = VMCODEBYTE(i->pc++);
            tmp2 = VMCODEBYTE(i->pc++);
            Reserve(i, tmp);
            ReserveH(i, tmp2);
            break;
         case OP_CALL:
            StartCode(i);
            break;
        case OP_RETURN:
            tmp = *i->sp;
            PopFrame(i);
            Push(i, tmp);
            break;
        case OP_RETURNH:
            htmp = *i->hsp;
            PopFrame(i);
            PushH(i, htmp);
            break;
        case OP_RETURNV:
            PopFrame(i);
            break;
        case OP_DROP:
            Drop(i, 1);
            break;
        case OP_DROPH:
            ObjRelease(i->heap, *i->hsp);
            DropH(i, 1);
            break;
        default:
            Abort(i->sys, str_opcode_err, VMCODEBYTE(i->pc - 1));
            break;
        }
    }
}
Ejemplo n.º 4
0
int main (int argc, char * const argv[]) 
{
   // Settings
   u32 uiStartAddress   = 0;
   u32 uiOffset         = 0;
   u32 uiSize           = 0xFFFFFFFF;

   g_bShowLdrLabels = true;
   g_bShowComments  = false;
   g_bGccCompatible = true;
      
   // Parse arguments
   bool bError = false;
   int  i      = 1;
   for (i = 1; i < argc; i++)
   {
      if ('-' == argv[i][0])
      {
         switch (argv[i][1])
         {
         case 'a':
            // Stating address
            i++;
            if (argc == i)
               bError = true;
            else
               bError = !parse_number(argv[i],  uiStartAddress);
         	break;
         case 'o':
            // Start offset
            i++;
            if (argc == i)
               bError = true;
            else
               bError = !parse_number(argv[i],  uiOffset);
            break;
         case 's':
            // Disassemble size
            i++;
            if (argc == i)
               bError = true;
            else
               bError = !parse_number(argv[i],  uiSize);
            break;
         case 'p':
            g_bShowLdrLabels = false;
            break;
         default:
            bError = true;
            break;
         }
         
      }
      else
         break;
   }

   if (1 >= argc || bError || i != (argc - 1))
   {
      usage();
      return 0;
   }

   // Align
   uiStartAddress = ALIGN2(uiStartAddress);
   uiOffset       = ALIGN2(uiOffset);

   uiStartAddress += uiOffset;

   // Open file and start disassembly
   FILE *in = fopen(argv[i], "rb");
   if (in == NULL)
   {
      printf("mdisasm: Failed to open input file.\n");
      return 0;
   }

   // Seek to offset
   if (0 != fseek(in, uiOffset, SEEK_SET))
   {
      // Offset too biga nd is behind the file end, quit silently
      fclose(in);
      return 0;
   }

   // Prepare
   StartInstructionChain();

   // Disassemble
   u16   usCode;
   u16   usCode2;
   bool  bSkipFirstRead = false;

   for (u32 pos = 0; pos < uiSize;)
   {
      // Load 2 bytes from the file
      if (!bSkipFirstRead && 2 != fread(&usCode, 1, 2, in))
      {
         // End of the file, exit
         fclose(in);
         return 0;
      }
      bSkipFirstRead = false;

      // Try to load 2 more bytes
      if (2 != fread(&usCode2, 1, 2, in))
      {
         // End of file, try to decode as 16bit and exit
         DecodeInstruction(uiStartAddress + pos * 2, usCode, 0);
         fclose(in);
         return 0;
      }

      // Decode
      int iSize = DecodeInstruction(uiStartAddress + pos * 2, usCode, usCode2);
      if (1 == iSize)
      {
         // This is 16bit instruction, shft halfwords and continue
         usCode         = usCode2;
         bSkipFirstRead = true;
      }
      
      pos += iSize;
   }

   fclose(in);
   
   return 0;
}
Ejemplo n.º 5
0
// Execute the next instruction
std::string m68000::ExecuteInstruction(std::string &traceRecord, bool tracing) {
  unsigned int opcode;
  int status;

  // Add instruction address to the trace record
  if (tracing) {
    traceRecord = "{InstructionAddress ";
    traceRecord += IntToString(register_value[PC_INDEX], 8);
    traceRecord += "} ";
  }

  // Make sure the CPU hasn't been halted
  if (myState != HALT_STATE) {
    // Service any pending interrupts
    bool serviceFlag;
    status = ServiceInterrupts(serviceFlag);

    // Only execute an instruction if we didn't service an interrupt
    if (!serviceFlag && status == EXECUTE_OK) {
      // Make sure the CPU isn't stopped waiting for exceptions
      if (myState != STOP_STATE) {
        // Fetch the next instruction
        status = Peek(register_value[PC_INDEX], opcode, WORD);
        if (status == EXECUTE_OK) {
          register_value[PC_INDEX] += 2;

          // Execute the instruction
          ExecutionPointer executeMethod = DecodeInstruction(opcode);
          status = (this->*executeMethod)(opcode, traceRecord, tracing);

          // If the last instruction was not priviledged then check for trace
          if ((status == EXECUTE_OK) && (register_value[SR_INDEX] & T_FLAG))
            status = ProcessException(9);
        }
      } else {
        if (tracing)
          traceRecord += "{Mnemonic {CPU is stopped}} ";
      }
    }

    if (status == EXECUTE_BUS_ERROR) {
      if (ExecuteBusError(opcode, traceRecord, tracing) != EXECUTE_OK) {
        // Oh, no the cpu has fallen and it can't get up!
        myState = HALT_STATE;
        if (tracing)
          traceRecord += "{Mnemonic {Double Bus/Address Error CPU halted}} ";
      }
    } else if (status == EXECUTE_ADDRESS_ERROR) {
      if (ExecuteAddressError(opcode, traceRecord, tracing) != EXECUTE_OK) {
        // Now, where's that reset button???
        myState = HALT_STATE;
        if (tracing)
          traceRecord += "{Mnemonic {Double Bus/Address Error CPU halted}} ";
      }
    }
  } else {
    if (tracing)
      traceRecord += "{Mnemonic {CPU has halted}} ";
  }

  // Check the event list
  myEventHandler.Check();

  // Signal if the processor is in a wierd state
  if (myState == HALT_STATE) {
    return "CPU has halted";
  } else if (myState == BREAK_STATE) {
    myState = NORMAL_STATE;
    if (tracing)
      return "";
    else
      return "BREAK instruction";
  }

  return "";
}