home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / system / bsvc-1.000 / bsvc-1 / bsvc-1.0.4 / src / Sim68000 / cpu / m68000.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-26  |  12.1 KB  |  398 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // $Id: m68000.cxx,v 1.3 1995/06/30 00:06:57 bmott Exp $
  3. ///////////////////////////////////////////////////////////////////////////////
  4. // m68000.cxx 
  5. //
  6. // Motorola 68000 microprocessor class
  7. //
  8. // Sim68000 "Motorola 68000 Simulator"
  9. // Copyright (c) 1993
  10. // By: Bradford W. Mott
  11. // October 31,1993
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // $Log: m68000.cxx,v $
  15. // Revision 1.3  1995/06/30  00:06:57  bmott
  16. // Changed interrupt servicing so that breakpoints at the service routine
  17. // will operate correctly
  18. //
  19. // Revision 1.2  1994/09/22  00:12:48  bmott
  20. // Added code to handle the BREAK state
  21. //
  22. // Revision 1.1  1994/02/18  20:04:25  bmott
  23. // Initial revision
  24. //
  25. ///////////////////////////////////////////////////////////////////////////////
  26.  
  27. #include "Tools.hxx"
  28. #include "m68000.hxx"
  29.  
  30. RegisterData m68000::register_data[] = {
  31.   {"D0",  0xffffffff,  "Data Register 0"},
  32.   {"D1",  0xffffffff,  "Data Register 1"},
  33.   {"D2",  0xffffffff,  "Data Register 2"},
  34.   {"D3",  0xffffffff,  "Data Register 3"},
  35.   {"D4",  0xffffffff,  "Data Register 4"},
  36.   {"D5",  0xffffffff,  "Data Register 5"},
  37.   {"D6",  0xffffffff,  "Data Register 6"},
  38.   {"D7",  0xffffffff,  "Data Register 7"},
  39.   {"A0",  0xffffffff,  "Address Register 0"},
  40.   {"A1",  0xffffffff,  "Address Register 1"},
  41.   {"A2",  0xffffffff,  "Address Register 2"},
  42.   {"A3",  0xffffffff,  "Address Register 3"},
  43.   {"A4",  0xffffffff,  "Address Register 4"},
  44.   {"A5",  0xffffffff,  "Address Register 5"},
  45.   {"A6",  0xffffffff,  "Address Register 6"},
  46.   {"A7",  0xffffffff,  "Address Register 7 (User Stack Pointer)"},
  47.   {"A7'" ,0xffffffff,  "Address Register 7 (Supervisor Stack Pointer)"},
  48.   {"PC",  0xffffffff,  "Program Counter"},
  49.   {"SR",  0x0000ffff,  "Status Register: T-S--III---XNZVC\n  T: Trace Mode\n  S: Supervisory Mode\n  I: Interrupt Mask Level\n  X: Extend\n  N: Negative\n  Z: Zero\n  V: Overflow\n  C: Carry"}
  50. }; 
  51.  
  52.  
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // The m68000 Class constructor
  55. ///////////////////////////////////////////////////////////////////////////////
  56. m68000::m68000(AddressSpace *addr)
  57.     : BasicCPU("68000",                         // Name of the CPU
  58.                1,                               // Granularity in bytes
  59.                1,                               // Number of addr spaces
  60.                addr,                            // Array of addr spaces
  61.                "{InstructionAddress 8} "        // Execution trace record
  62.                    "{Mnemonic 35}",
  63.                "InstructionAddress Mnemonic"    // Default trace entries
  64.               ),     
  65.       number_of_registers(19),                  // Number of registers
  66.       C_FLAG(0x0001),                           // SR flags    
  67.       V_FLAG(0x0002),
  68.       Z_FLAG(0x0004),
  69.       N_FLAG(0x0008),
  70.       X_FLAG(0x0010),
  71.       I0_FLAG(0x0100),
  72.       I1_FLAG(0x0200),
  73.       I2_FLAG(0x0400),
  74.       S_FLAG(0x2000),
  75.       T_FLAG(0x8000),
  76.       D0_INDEX(0),                              // Register Indices
  77.       A0_INDEX(8),
  78.       USP_INDEX(15),
  79.       SSP_INDEX(16),
  80.       PC_INDEX(17),
  81.       SR_INDEX(18),
  82.       EXECUTE_OK(0),                            // Execution return codes
  83.       EXECUTE_PRIVILEGED_OK(1),
  84.       EXECUTE_BUS_ERROR(2),
  85.       EXECUTE_ADDRESS_ERROR(3),
  86.       EXECUTE_ILLEGAL_INSTRUCTION(4),
  87.       NORMAL_STATE(0),                          // Processor states
  88.       HALT_STATE(1),
  89.       STOP_STATE(2),
  90.       BREAK_STATE(3)
  91. {
  92.   // Buld the decode cache if necessary
  93.   if(decode_cache_table == (void*)0)
  94.   {
  95.     // Allocate memory for the decode cache table
  96.     decode_cache_table=new ExecutionPointer[65536];
  97.  
  98.     // Set all cache entries to invalid (NULL)
  99.     for(int t=0;t<65536;++t)
  100.       decode_cache_table[t]=(void*)0;
  101.   }
  102.  
  103.   // Allocate array for register values
  104.   register_value=new unsigned long[number_of_registers];
  105.  
  106.   // Clear the registers
  107.   for(int t=0;t<number_of_registers;++t)
  108.     register_value[t]=0;
  109.  
  110.   // Reset the system
  111.   Reset();
  112.  
  113.   my_interrupt=-1;
  114. }
  115.  
  116. ///////////////////////////////////////////////////////////////////////////////
  117. // The m68000 Class destructor
  118. ///////////////////////////////////////////////////////////////////////////////
  119. m68000::~m68000()
  120. {
  121.   // Free the register value array
  122.   delete[] register_value;
  123. }
  124.  
  125. ///////////////////////////////////////////////////////////////////////////////
  126. // Preform a system reset
  127. ///////////////////////////////////////////////////////////////////////////////
  128. void m68000::Reset()
  129. {
  130.   unsigned int pc, ssp;
  131.  
  132.   // Reset all of the device's attached to the processor
  133.   address_space->Reset();
  134.  
  135.   // Set the Status register to its reset value
  136.   register_value[SR_INDEX] = S_FLAG | I0_FLAG | I1_FLAG | I2_FLAG;
  137.  
  138.   // Fetch the Supervisor Stack Pointer from location $00000000
  139.   if(Peek(0x00000000, ssp, LONG) != EXECUTE_OK)
  140.     SetRegister(SSP_INDEX, 0, LONG);
  141.   else
  142.     SetRegister(SSP_INDEX, ssp, LONG);
  143.  
  144.   // Fetch the Program Counter from location $00000004
  145.   if(Peek(0x00000004, pc, LONG) != EXECUTE_OK)
  146.     SetRegister(PC_INDEX, 0, LONG);
  147.   else
  148.     SetRegister(PC_INDEX, pc, LONG);
  149.  
  150.   // Put the processor in normal instrution execution mode
  151.   processor_state=NORMAL_STATE;
  152. }
  153.  
  154. ///////////////////////////////////////////////////////////////////////////////
  155. // Return the value in the program counter
  156. ///////////////////////////////////////////////////////////////////////////////
  157. unsigned long m68000::ValueOfProgramCounter()
  158. {
  159.   return(register_value[PC_INDEX]);
  160. }
  161.  
  162. ///////////////////////////////////////////////////////////////////////////////
  163. // Build the statistics list for the StatisticalInformationList object
  164. ///////////////////////////////////////////////////////////////////////////////
  165. void m68000::BuildStatisticalInformationList(StatisticalInformationList*)
  166. {
  167.   // We're not keeping up with any stupid statistics :-}
  168. }
  169.  
  170. ///////////////////////////////////////////////////////////////////////////////
  171. // Set the named register to the given value
  172. ///////////////////////////////////////////////////////////////////////////////
  173. void m68000::SetRegister(String name, String hex_value)
  174. {
  175.   unsigned int value;
  176.  
  177.   value=StringToInt(hex_value);
  178.  
  179.   for(int t=0;t<number_of_registers;++t) 
  180.   {
  181.     if(name==register_data[t].name)
  182.     {
  183.       register_value[t]=(value & register_data[t].mask);
  184.       break;
  185.     }
  186.   }
  187. }
  188.  
  189. ///////////////////////////////////////////////////////////////////////////////
  190. // Build the register list for the RegisterInformationList object
  191. ///////////////////////////////////////////////////////////////////////////////
  192. void m68000::BuildRegisterInformationList(RegisterInformationList *list)
  193. {
  194.   int t;
  195.   String value;
  196.  
  197.   for(t=0;t<number_of_registers;++t)
  198.   {
  199.     if(t!=SR_INDEX)
  200.       value=IntToString((register_value[t]®ister_data[t].mask),8);
  201.     else
  202.       value=IntToString((register_value[t]®ister_data[t].mask),4);
  203.  
  204.     list->Append(register_data[t].name,value,register_data[t].description);
  205.   }
  206. }
  207.  
  208. ///////////////////////////////////////////////////////////////////////////////
  209. // Execute the next instruction
  210. ///////////////////////////////////////////////////////////////////////////////
  211. const char* m68000::ExecuteInstruction(String& trace_record, int trace_flag)
  212. {
  213.   unsigned int opcode;
  214.   ExecutionPointer exec_function;
  215.   int status;
  216.  
  217.   // Add instruction address to the trace record
  218.   if(trace_flag)
  219.   {
  220.     trace_record="{InstructionAddress ";
  221.     trace_record+=IntToString(register_value[PC_INDEX],8);
  222.     trace_record+="} ";
  223.   }
  224.  
  225.   // Make sure the CPU hasn't been halted
  226.   if(processor_state!=HALT_STATE)
  227.   {
  228.     int serviceFlag;
  229.  
  230.     // Service any pending interrupts
  231.     status = ServiceInterrupts(serviceFlag);
  232.  
  233.     // Only execute an instruction if we didn't service an interrupt
  234.     if((!serviceFlag) && (status == EXECUTE_OK))
  235.     { 
  236.       // Make sure the CPU isn't stopped waiting for exceptions
  237.       if(processor_state!=STOP_STATE)
  238.       {
  239.         // Fetch the next instruction
  240.         if((status=Peek(register_value[PC_INDEX],opcode,WORD))==EXECUTE_OK)
  241.         {
  242.           register_value[PC_INDEX]+=2;
  243.   
  244.           // Execute the instruction
  245.           exec_function=DecodeInstruction(opcode); 
  246.           status=(this->*exec_function)(opcode, trace_record, trace_flag);
  247.  
  248.           // If the last instruction was not priviledged then check for trace
  249.           if((status==EXECUTE_OK) && (register_value[SR_INDEX]&T_FLAG))
  250.             status=ProcessException(9);
  251.         }
  252.       }
  253.       else
  254.       {
  255.         if(trace_flag)
  256.           trace_record+="{Mnemonic {CPU is stopped}} ";
  257.       }
  258.     }
  259.  
  260.     if(status==EXECUTE_BUS_ERROR)
  261.     {
  262.       if(ExecuteBusError(opcode, trace_record, trace_flag) != EXECUTE_OK)
  263.       {
  264.         // Oh, no the cpu has fallen and it can't get up!
  265.         processor_state=HALT_STATE;
  266.         if(trace_flag)
  267.           trace_record+="{Mnemonic {Double Bus/Address Error CPU halted}} ";
  268.       }
  269.     }
  270.     else if (status==EXECUTE_ADDRESS_ERROR)
  271.     {
  272.       if(ExecuteAddressError(opcode, trace_record, trace_flag) != EXECUTE_OK)
  273.       {
  274.         // Now, where's that reset button???
  275.         processor_state=HALT_STATE;
  276.         if(trace_flag)
  277.           trace_record+="{Mnemonic {Double Bus/Address Error CPU halted}} ";
  278.       }
  279.     }
  280.   }
  281.   else
  282.   {
  283.     if(trace_flag)
  284.       trace_record+="{Mnemonic {CPU has halted}} ";
  285.   }
  286.  
  287.   // Check the event list
  288.   events.Check();
  289.  
  290.   // Signal if the processor is in a wierd state
  291.   if(processor_state==HALT_STATE)
  292.   {
  293.     return("CPU has halted");
  294.   }
  295.   else if(processor_state==BREAK_STATE)
  296.   {
  297.     processor_state = NORMAL_STATE;
  298.     if(trace_flag)
  299.       return((char*)0);
  300.     else
  301.       return("BREAK instruction");
  302.   }
  303.   else
  304.     return((char*)0);
  305. }
  306.  
  307. ///////////////////////////////////////////////////////////////////////////////
  308. // Handle an interrupt request from a device
  309. ///////////////////////////////////////////////////////////////////////////////
  310. void m68000::InterruptRequest(BasicDevice* device, int level)
  311. {
  312.   int interrupt_mask;
  313.  
  314.   // The 68000 has seven levels of interrupts
  315.   if(level>7)
  316.     level=7;
  317.   else if(level<1)
  318.     level=1;
  319.  
  320.   // Get the interrupt mask
  321.   interrupt_mask=(register_value[SR_INDEX] & 0x0700) >> 8;
  322.  
  323.   if((level>interrupt_mask) || (level==7))
  324.   {
  325.     my_interrupt=level;
  326.     my_device=device;
  327.   }
  328.   else
  329.   {
  330.     device->InterruptAcknowledge(1); 
  331.   }
  332. }
  333.  
  334. ///////////////////////////////////////////////////////////////////////////////
  335. // Service pending interrupts, set serviceFlag to true iff we
  336. // are had to service an interrupt
  337. ///////////////////////////////////////////////////////////////////////////////
  338. int m68000::ServiceInterrupts(int& serviceFlag)
  339. {
  340.   if(my_interrupt != -1)
  341.   {
  342.     // Indicate that I had to service an interrupt
  343.     serviceFlag = 1;
  344.  
  345.     int level=my_interrupt;
  346.     int status;
  347.  
  348.     my_interrupt=-1;
  349.  
  350.     // Put the processor into normal state if it's stopped
  351.     if(processor_state==STOP_STATE)
  352.       processor_state=NORMAL_STATE;
  353.  
  354.     // Copy the SR to a temp
  355.     unsigned long tmp_sr = register_value[SR_INDEX];
  356.  
  357.     // Set the Interrupt Mask in SR
  358.     register_value[SR_INDEX] &= 0x0000f8ff;
  359.     register_value[SR_INDEX] |= (level << 8);
  360.  
  361.     // Change to Supervisor mode and clear the Trace mode
  362.     register_value[SR_INDEX] |= S_FLAG;
  363.     register_value[SR_INDEX] &= ~T_FLAG;
  364.  
  365.     // Interrupt has occured so push the PC and the SR
  366.     SetRegister(SSP_INDEX, register_value[SSP_INDEX]-4, LONG);
  367.     if((status=Poke(register_value[SSP_INDEX],
  368.          register_value[PC_INDEX], LONG)) != EXECUTE_OK)
  369.     { return(status); }
  370.  
  371.     SetRegister(SSP_INDEX, register_value[SSP_INDEX]-2, LONG);
  372.     if((status=Poke(register_value[SSP_INDEX], tmp_sr, WORD)) != EXECUTE_OK)
  373.     { return(status); }
  374.  
  375.     // Get the vector number
  376.     long vector=my_device->InterruptAcknowledge(level);
  377.     if(vector==AUTOVECTOR_INTERRUPT)
  378.       vector=24+level;
  379.     else if(vector==SPURIOUS_INTERRUPT)
  380.       vector=24;
  381.  
  382.     // Get the interrupt service routine's address
  383.     unsigned int service_address;
  384.     if((status=Peek(vector*4, service_address , LONG)) != EXECUTE_OK)
  385.       return(status); 
  386.  
  387.     // Change the program counter to the service routine's address
  388.     SetRegister(PC_INDEX, service_address, LONG);
  389.   }
  390.   else
  391.   {
  392.     // Indicate that I didn't have to service an interrupt
  393.     serviceFlag = 0;
  394.   }
  395.   return(EXECUTE_OK);
  396. }
  397.  
  398.