Reintroduce command line mode
[emu8051.git] / src / cpu8051.c
index 4e3a656..65a79ed 100644 (file)
@@ -22,7 +22,6 @@
 /* Define only here, for not having extern scope on local variables. */
 #define CPU8051_M 1
 
-
 #include <stdio.h>
 
 #include "reg8051.h"
 #include "disasm.h"
 #include "instructions_8051.h"
 
-
-void
-cpu8051_init( void )
-{
-  cpu8051.pc = 0;
-  cpu8051.clock = 0;
-  cpu8051.active_priority = -1;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Execute at address cpu8051.pc from PGMMem
-//////////////////////////////////////////////////////////////////////////////
 void
-cpu8051_Exec( void )
-{
-  int i;
-  unsigned char opcode;
-  int insttiming;
-
-  opcode = memory_read8( PGM_MEM_ID, cpu8051.pc );
-  cpu8051.pc++;
-  insttiming = (*opcode_table[opcode])(); /* Function callback. */
-  
-  for( i = 0; i < insttiming; i++ ) {
-    cpu8051_CheckInterrupts();
-    cpu8051_DoTimers();
-    cpu8051.clock++;
-  }
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Return cpu8051.pc + size in bytes of current instruction
-//////////////////////////////////////////////////////////////////////////////
-unsigned int
-cpu8051_GetNextAddress( void )
+cpu8051_init(void)
 {
-#ifdef DECPP
-  return ( cpu8051.pc + InstSizesTbl[ memory_read8( PGM_MEM_ID, cpu8051.pc ) ] );
-#endif
-  return 0; /* temp */
+       cpu8051.pc = 0;
+       cpu8051.clock = 0;
+       cpu8051.active_priority = -1;
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-// Reset the registers and CPU state
-//////////////////////////////////////////////////////////////////////////////
+/* Reset the registers and CPU state */
 void
-cpu8051_Reset( void )
+cpu8051_Reset(void)
 {
-  cpu8051.pc = 0;
-  cpu8051.clock= 0;
-  cpu8051.active_priority = -1;
-
-  // Reinitialisation des registres
-  int i;
-  for ( i = 0; i < 128; i++ ) {
-
-    memory_write8( SFR_MEM_ID, i, 0 );
-
-    memory_write8( INT_MEM_ID, i, 0 );
-  }
+       cpu8051.pc = 0;
+       cpu8051.clock= 0;
+       cpu8051.active_priority = -1;
+
+       // Reinitialisation des registres
+       int i;
+       for ( i = 0; i < 256; i++ ) {
+               /* Clear  IRAM nad SFR */
+               memory_write8( INT_MEM_ID, i, 0 );
+       }
 
-  memory_write8( SFR_MEM_ID, _P0_ - 0x80, 0xFF );
-  memory_write8( SFR_MEM_ID, _P1_ - 0x80, 0xFF );
-  memory_write8( SFR_MEM_ID, _P2_ - 0x80, 0xFF );
-  memory_write8( SFR_MEM_ID, _P3_ - 0x80, 0xFF );
-  memory_write8( SFR_MEM_ID, _SP_ - 0x80, 0x07 );
+       memory_write8( INT_MEM_ID, _P0_, 0xFF );
+       memory_write8( INT_MEM_ID, _P1_, 0xFF );
+       memory_write8( INT_MEM_ID, _P2_, 0xFF );
+       memory_write8( INT_MEM_ID, _P3_, 0xFF );
+       memory_write8( INT_MEM_ID, _SP_, 0x07 );
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-// Write with a direct addressing mode at Address the new Value
-//////////////////////////////////////////////////////////////////////////////
+/* Write with a direct addressing mode at Address the new Value */
 void
 cpu8051_WriteD( unsigned int Address, unsigned char Value )
 {
-  if ( Address > 0x7F ) {
-    memory_write8( SFR_MEM_ID, Address - 0x80, Value );
-    return;
-  }
-  
-  memory_write8( INT_MEM_ID, Address, Value );
+       memory_write8( INT_MEM_ID, Address, Value );
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-// Ecriture d'une valeur dans la memoire interne ( Address = $00 a $FF )
-//////////////////////////////////////////////////////////////////////////////
+// Write with an indirect addressing mode at Address the new Value
 void
-cpu8051_WriteInt( unsigned int Address, unsigned char Value )
+cpu8051_WriteI( unsigned int Address, unsigned char Value )
 {
-  if ( Address > 0x7F ) {
-    memory_write8( SFR_MEM_ID, Address - 0x80, Value );
-  }
-  else {
-    memory_write8( INT_MEM_ID, Address, Value );
-  }
+       if ( Address > 0x7F ) {
+               memory_write8( EXT_MEM_ID, Address, Value );
+               return;
+       }
 
-  return;
+       memory_write8( INT_MEM_ID, Address, Value );
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-// Write with an indirect addressing mode at Address the new Value
-//////////////////////////////////////////////////////////////////////////////
+// Write with a bit addressing mode at BitAddress the new Value
 void
-cpu8051_WriteI( unsigned int Address, unsigned char Value )
+cpu8051_WriteB( unsigned int BitAddress, unsigned char Value )
 {
-  if ( Address > 0x7F ) {
-    memory_write8( EXT_MEM_ID, Address, Value );
-    return;
-  }
+       unsigned int ByteAddress, BitNumber;
+       unsigned char ByteValue, ByteMask;
 
-  memory_write8( INT_MEM_ID, Address, Value );
+       if ( BitAddress > 0x7F ) {
+               // SFR 80-FF
+               ByteAddress = BitAddress & 0xF8;
+               BitNumber = BitAddress & 0x07;
+       }
+       else {
+               // 20-2F
+               ByteAddress = ( BitAddress >> 3 ) + 0x20;
+               BitNumber = BitAddress & 0x07;
+       }
+       ByteMask = ( ( 1 << BitNumber ) ^ 0xFF );
+       ByteValue = cpu8051_ReadD( ByteAddress ) & ByteMask;
+       ByteValue += Value << BitNumber;
+       cpu8051_WriteD( ByteAddress, ByteValue );
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Read with a direct addressing mode at Address
-//////////////////////////////////////////////////////////////////////////////
 unsigned char
 cpu8051_ReadD( unsigned int Address )
 {
-  if ( Address > 0xFF ) {
-    return memory_read8( EXT_MEM_ID, Address );
-  }
-
-  if ( Address > 0x7F ) {
-    return memory_read8( SFR_MEM_ID, Address - 0x80 );
-  }
-
-  return memory_read8( INT_MEM_ID, Address );
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Read Internal data memory at Address
-//////////////////////////////////////////////////////////////////////////////
-unsigned char
-cpu8051_ReadInt( unsigned int Address )
-{
-  if ( Address > 0x7F ) {
-    return memory_read8( SFR_MEM_ID, Address - 0x80 );
-  }
-  else {
-    return memory_read8( INT_MEM_ID, Address );
-  }
+       if (Address > 0xFF)
+               return memory_read8(EXT_MEM_ID, Address);
+       else
+               return memory_read8(INT_MEM_ID, Address);
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-// unsigned char cpu8051_ReadI( unsigned int Address )
 // Read with a indirect addressing mode at Address
-//////////////////////////////////////////////////////////////////////////////
 unsigned char
 cpu8051_ReadI( unsigned int Address )
 {
-  if ( Address > 0x7F ) {
-    return memory_read8( EXT_MEM_ID, Address );
-  }
-  else {
-    return memory_read8( INT_MEM_ID, Address );
-  }
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Write with a bit addressing mode at BitAddress the new Value
-//////////////////////////////////////////////////////////////////////////////
-void
-cpu8051_WriteB( unsigned int BitAddress, unsigned char Value )
-{
-  unsigned int ByteAddress, BitNumber;
-  unsigned char ByteValue, ByteMask;
-
-  if ( BitAddress > 0x7F ) {
-    // SFR 80-FF
-    ByteAddress = BitAddress & 0xF8;
-    BitNumber = BitAddress & 0x07;
-  }
-  else {
-    // 20-2F
-    ByteAddress = ( BitAddress >> 3 ) + 0x20;
-    BitNumber = BitAddress & 0x07;
-  }
-  ByteMask = ( ( 1 << BitNumber ) ^ 0xFF );
-  ByteValue = cpu8051_ReadD( ByteAddress ) & ByteMask;
-  ByteValue += Value << BitNumber;
-  cpu8051_WriteD( ByteAddress, ByteValue );
+       if (Address > 0x7F) {
+               return memory_read8(EXT_MEM_ID, Address);
+       }
+       else {
+               return memory_read8(INT_MEM_ID, Address);
+       }
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Read with a bit addressing mode at BitAddress
-//////////////////////////////////////////////////////////////////////////////
 unsigned char
 cpu8051_ReadB( unsigned int BitAddress )
 {
-  unsigned int ByteAddress, BitNumber;
-  unsigned char BitValue;
+       unsigned int ByteAddress, BitNumber;
+       unsigned char BitValue;
 
-  if ( BitAddress > 0x7F ) {
-    // SFR 80-FF
-    ByteAddress = BitAddress & 0xF8;
-    BitNumber = BitAddress & 0x07;
-  }
-  else {
-    // 20-2F
-    ByteAddress = ( BitAddress >> 3 ) + 0x20;
-    BitNumber = BitAddress & 0x07;
-  }
-  BitValue = ( cpu8051_ReadD( ByteAddress ) >> BitNumber );
-  BitValue &= 1;
-  return BitValue;
+       if ( BitAddress > 0x7F ) {
+               // SFR 80-FF
+               ByteAddress = BitAddress & 0xF8;
+               BitNumber = BitAddress & 0x07;
+       }
+       else {
+               // 20-2F
+               ByteAddress = ( BitAddress >> 3 ) + 0x20;
+               BitNumber = BitAddress & 0x07;
+       }
+       BitValue = ( cpu8051_ReadD( ByteAddress ) >> BitNumber );
+       BitValue &= 1;
+       return BitValue;
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Check interrupts state and process them as needed
-//////////////////////////////////////////////////////////////////////////////
-void
+static void
 cpu8051_CheckInterrupts()
 {
-  unsigned char SP;
-  int i;
-
-  if ( cpu8051_ReadD( _IE_ ) & 0x80 ) {
-    for ( i = 1; i >= 0; i-- )
-      if ( cpu8051.active_priority < i ) {
-       //-------------------------  External interrupt 0 ----------------------------     
-       //        if ( ( cpu8051_ReadD( _IE_ ) & 0x01 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x01 ) ? i : !i ) && pin0 )
-       //-------------------------- Interrupt timer 0 -------------------------------
-       if ( ( cpu8051_ReadD( _IE_ ) & 0x02 ) && ( ( cpu8051_ReadD( _IP_ & 0x02 ) ? i : !i ) && ( cpu8051_ReadD( _TCON_ ) & 0x20 ) ) ){
-         cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) & 0xDF );
-         SP = cpu8051_ReadD( _SP_ );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
-         cpu8051_WriteD( _SP_, SP );
-         cpu8051.pc = 0x0B;  
-         cpu8051.active_priority = i;
-         return;          
-       }
-       //-------------------------- External interrupt 1 ----------------------------     
-       //        if ( ( cpu8051_ReadD( _IE_ ) & 0x04 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x04 ) ? i : !i ) && pin1 )
-       //-------------------------- Interrupt timer 1 -------------------------------      
-       if ( ( cpu8051_ReadD( _IE_ ) & 0x08 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x08 ) ? i : !i ) && ( cpu8051_ReadD( _TCON_ ) & 0x80 ) ) {
-         cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) & 0x7F );
-         SP = cpu8051_ReadD( _SP_ );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
-         cpu8051_WriteD( _SP_, SP );
-         cpu8051.pc = 0x1B;
-         cpu8051.active_priority = i;
-         return;
-       }
-       //-------------------------- Serial Interrupts -------------------------------
-       if ( ( cpu8051_ReadD( _IE_ ) & 0x10 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x10 ) ? i : !i ) && ( cpu8051_ReadD( _SCON_ ) & 0x03 ) ) {
-         SP = cpu8051_ReadD( _SP_ );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
-         cpu8051_WriteD( _SP_, SP );
-         cpu8051.pc = 0x23;
-         cpu8051.active_priority = i;
-         return;
+       unsigned char SP;
+       int i;
+
+       if ( cpu8051_ReadD( _IE_ ) & 0x80 ) {
+               for ( i = 1; i >= 0; i-- )
+                       if ( cpu8051.active_priority < i ) {
+                               //-------------------------  External interrupt 0 ----------------------------     
+                               //        if ( ( cpu8051_ReadD( _IE_ ) & 0x01 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x01 ) ? i : !i ) && pin0 )
+                               //-------------------------- Interrupt timer 0 -------------------------------
+                               if ( ( cpu8051_ReadD( _IE_ ) & 0x02 ) && ( ( cpu8051_ReadD( _IP_ & 0x02 ) ? i : !i ) && ( cpu8051_ReadD( _TCON_ ) & 0x20 ) ) ){
+                                       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) & 0xDF );
+                                       SP = cpu8051_ReadD( _SP_ );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
+                                       cpu8051_WriteD( _SP_, SP );
+                                       cpu8051.pc = 0x0B;  
+                                       cpu8051.active_priority = i;
+                                       return;          
+                               }
+                               //-------------------------- External interrupt 1 ----------------------------     
+                               //        if ( ( cpu8051_ReadD( _IE_ ) & 0x04 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x04 ) ? i : !i ) && pin1 )
+                               //-------------------------- Interrupt timer 1 -------------------------------      
+                               if ( ( cpu8051_ReadD( _IE_ ) & 0x08 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x08 ) ? i : !i ) && ( cpu8051_ReadD( _TCON_ ) & 0x80 ) ) {
+                                       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) & 0x7F );
+                                       SP = cpu8051_ReadD( _SP_ );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
+                                       cpu8051_WriteD( _SP_, SP );
+                                       cpu8051.pc = 0x1B;
+                                       cpu8051.active_priority = i;
+                                       return;
+                               }
+                               //-------------------------- Serial Interrupts -------------------------------
+                               if ( ( cpu8051_ReadD( _IE_ ) & 0x10 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x10 ) ? i : !i ) && ( cpu8051_ReadD( _SCON_ ) & 0x03 ) ) {
+                                       SP = cpu8051_ReadD( _SP_ );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
+                                       cpu8051_WriteD( _SP_, SP );
+                                       cpu8051.pc = 0x23;
+                                       cpu8051.active_priority = i;
+                                       return;
+                               }
+                               //-------------------------- Interrupt timer 2 -------------------------------
+                               if ( ( cpu8051_ReadD( _IE_ ) & 0x20 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x20 ) ? i : !i ) && ( cpu8051_ReadD( _T2CON_ ) & 0x80 ) ) {          
+                                       SP = cpu8051_ReadD( _SP_ );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
+                                       cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
+                                       cpu8051_WriteD( _SP_, SP );
+                                       cpu8051.pc = 0x2B;
+                                       cpu8051.active_priority = i;
+                                       return;
+                               }
+                       }
        }
-       //-------------------------- Interrupt timer 2 -------------------------------
-       if ( ( cpu8051_ReadD( _IE_ ) & 0x20 ) && ( ( cpu8051_ReadD( _IP_ ) & 0x20 ) ? i : !i ) && ( cpu8051_ReadD( _T2CON_ ) & 0x80 ) ) {          
-         SP = cpu8051_ReadD( _SP_ );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc & 0xFF ) );
-         cpu8051_WriteI( ++SP, ( cpu8051.pc >> 8 ) );
-         cpu8051_WriteD( _SP_, SP );
-         cpu8051.pc = 0x2B;
-         cpu8051.active_priority = i;
-         return;
-       }
-      }
-  }
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Execute les timers
-//////////////////////////////////////////////////////////////////////////////
-void
+static void
 cpu8051_DoTimers( )
 {
-  unsigned int tmp;
-  unsigned int TR;
-  unsigned int MODE;
-  unsigned int GATE;
-  unsigned int TimerCounter;
-
-  // ----- Timer 0
-  TR = cpu8051_ReadD( _TCON_ ) & 0x10;
-  MODE = cpu8051_ReadD( _TMOD_ ) & 0x03;
-  GATE = cpu8051_ReadD( _TMOD_ ) & 0x08;
-  TimerCounter = cpu8051_ReadD( _TMOD_ ) & 0x04;
+       unsigned int tmp;
+       unsigned int TR;
+       unsigned int MODE;
+       unsigned int GATE;
+       unsigned int TimerCounter;
+
+       // ----- Timer 0
+       TR = cpu8051_ReadD( _TCON_ ) & 0x10;
+       MODE = cpu8051_ReadD( _TMOD_ ) & 0x03;
+       GATE = cpu8051_ReadD( _TMOD_ ) & 0x08;
+       TimerCounter = cpu8051_ReadD( _TMOD_ ) & 0x04;
   
-  if ( ( TR && !GATE && !TimerCounter ) || ( MODE == 3 ) )
-    switch( MODE ) {
-      // Mode 0, compteur de 13 bits.
-    case 0 :
-      tmp = cpu8051_ReadD( _TH0_ ) * 0x100 + cpu8051_ReadD( _TL0_ );
-
-      tmp++;
-      tmp &= 0x1FFF;   // On ne garde que 13 bits.
-
-      if ( tmp == 0 )    // If overflow set TF0
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
-      cpu8051_WriteD( _TH0_, tmp / 0x100 );
-      cpu8051_WriteD( _TL0_, tmp & 0xFF  );
-      break;
+       if ( ( TR && !GATE && !TimerCounter ) || ( MODE == 3 ) )
+               switch( MODE ) {
+                       // Mode 0, compteur de 13 bits.
+               case 0 :
+                       tmp = cpu8051_ReadD( _TH0_ ) * 0x100 + cpu8051_ReadD( _TL0_ );
+
+                       tmp++;
+                       tmp &= 0x1FFF;   // On ne garde que 13 bits.
+
+                       if ( tmp == 0 )    // If overflow set TF0
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
+                       cpu8051_WriteD( _TH0_, tmp / 0x100 );
+                       cpu8051_WriteD( _TL0_, tmp & 0xFF  );
+                       break;
       
-      // Mode 1, compteur de 16 bits.
-    case 1 :
-      tmp = cpu8051_ReadD( _TH0_ ) * 0x100 + cpu8051_ReadD( _TL0_ );
-      tmp++;
-      tmp &= 0xFFFF;   // On ne garde que 16 bits.
-      if ( tmp == 0 )   // If overflow set TF0
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
-      cpu8051_WriteD( _TH0_, ( tmp / 0x100 ) );
-      cpu8051_WriteD( _TL0_, ( tmp & 0xFF ) );
-      break;
+                       // Mode 1, compteur de 16 bits.
+               case 1 :
+                       tmp = cpu8051_ReadD( _TH0_ ) * 0x100 + cpu8051_ReadD( _TL0_ );
+                       tmp++;
+                       tmp &= 0xFFFF;   // On ne garde que 16 bits.
+                       if ( tmp == 0 )   // If overflow set TF0
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
+                       cpu8051_WriteD( _TH0_, ( tmp / 0x100 ) );
+                       cpu8051_WriteD( _TL0_, ( tmp & 0xFF ) );
+                       break;
       
-      // Mode 2, Compteur de 8 bits avec Auto-Reload
-    case 2 :
-      tmp = cpu8051_ReadD( _TL0_ );
-      tmp++;
-      tmp &= 0xFF;
-      if ( tmp == 0 ) {    // If overflow -> reload et set TF0
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
-       cpu8051_WriteD( _TL0_, cpu8051_ReadD( _TH0_ ) );
-      }
-      else
-       cpu8051_WriteD( _TL0_, tmp );
-      break;
+                       // Mode 2, Compteur de 8 bits avec Auto-Reload
+               case 2 :
+                       tmp = cpu8051_ReadD( _TL0_ );
+                       tmp++;
+                       tmp &= 0xFF;
+                       if ( tmp == 0 ) {    // If overflow -> reload et set TF0
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
+                               cpu8051_WriteD( _TL0_, cpu8051_ReadD( _TH0_ ) );
+                       }
+                       else
+                               cpu8051_WriteD( _TL0_, tmp );
+                       break;
     
-    // Mode 3 : TL0 et TH0 sont 2 Timers independants de 8 bits chacuns.
-    case 3 :
-      if ( TR && !GATE && !TimerCounter ) {
-       tmp = cpu8051_ReadD( _TL0_ );
-       tmp++;
-       tmp &= 0xFF;
-       if ( tmp == 0 )  // If TL0 overflow set TF0
-         cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
-       cpu8051_WriteD( _TL0_, tmp );
-      }  // TH0 utilise TR1 et TF1.
-      TR = cpu8051_ReadD( _TCON_ ) & 0x40;
-      if ( TR ) {
-       tmp = cpu8051_ReadD( _TH0_ );
-       tmp++;
-       tmp &= 0xFF;
-       if ( tmp == 0 )  // If TH0 overflow set TF1
-         cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );  // TF1 = 1.
-       cpu8051_WriteD( _TH0_, tmp );
-      }
-      break;
-    };
+                       // Mode 3 : TL0 et TH0 sont 2 Timers independants de 8 bits chacuns.
+               case 3 :
+                       if ( TR && !GATE && !TimerCounter ) {
+                               tmp = cpu8051_ReadD( _TL0_ );
+                               tmp++;
+                               tmp &= 0xFF;
+                               if ( tmp == 0 )  // If TL0 overflow set TF0
+                                       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x20 );
+                               cpu8051_WriteD( _TL0_, tmp );
+                       }  // TH0 utilise TR1 et TF1.
+                       TR = cpu8051_ReadD( _TCON_ ) & 0x40;
+                       if ( TR ) {
+                               tmp = cpu8051_ReadD( _TH0_ );
+                               tmp++;
+                               tmp &= 0xFF;
+                               if ( tmp == 0 )  // If TH0 overflow set TF1
+                                       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );  // TF1 = 1.
+                               cpu8051_WriteD( _TH0_, tmp );
+                       }
+                       break;
+               };
   
 
-  // ----- Timer 1
-  TR = cpu8051_ReadD( _TCON_ ) & 0x40;
-  MODE = ( cpu8051_ReadD( _TMOD_ ) & 0x30 ) >> 4 ;
-  GATE = cpu8051_ReadD( _TMOD_ ) & 0x80;
-  TimerCounter = cpu8051_ReadD( _TMOD_ ) & 0x40;
+       // ----- Timer 1
+       TR = cpu8051_ReadD( _TCON_ ) & 0x40;
+       MODE = ( cpu8051_ReadD( _TMOD_ ) & 0x30 ) >> 4 ;
+       GATE = cpu8051_ReadD( _TMOD_ ) & 0x80;
+       TimerCounter = cpu8051_ReadD( _TMOD_ ) & 0x40;
   
-  if ( TR && !GATE && !TimerCounter )
-    switch( MODE ) {
-      // Mode 0, compteur de 13 bits.
-    case 0 :
-      tmp = cpu8051_ReadD( _TH1_ ) * 0x100 + cpu8051_ReadD( _TL1_ );
-      tmp++;
-      tmp &= 0x1FFF;   // On ne garde que 13 bits.
-      if ( tmp == 0 )    // If overflow set TF1
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
-      cpu8051_WriteD( _TH1_, tmp / 0x100 );
-      cpu8051_WriteD( _TL1_, tmp & 0xFF  );
-      break;
+       if ( TR && !GATE && !TimerCounter )
+               switch( MODE ) {
+                       // Mode 0, compteur de 13 bits.
+               case 0 :
+                       tmp = cpu8051_ReadD( _TH1_ ) * 0x100 + cpu8051_ReadD( _TL1_ );
+                       tmp++;
+                       tmp &= 0x1FFF;   // On ne garde que 13 bits.
+                       if ( tmp == 0 )    // If overflow set TF1
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
+                       cpu8051_WriteD( _TH1_, tmp / 0x100 );
+                       cpu8051_WriteD( _TL1_, tmp & 0xFF  );
+                       break;
       
-      // Mode 1, compteur de 16 bits.
-    case 1 :
-      tmp = cpu8051_ReadD( _TH1_ ) * 0x100 + cpu8051_ReadD( _TL1_ );
-      tmp++;
-      tmp &= 0xFFFF;   // On ne garde que 16 bits.
-      if ( tmp == 0 )   // If overflow set TF1
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
-      cpu8051_WriteD( _TH1_, ( tmp / 0x100 ) );
-      cpu8051_WriteD( _TL1_, ( tmp & 0xFF ) );
-      break;
+                       // Mode 1, compteur de 16 bits.
+               case 1 :
+                       tmp = cpu8051_ReadD( _TH1_ ) * 0x100 + cpu8051_ReadD( _TL1_ );
+                       tmp++;
+                       tmp &= 0xFFFF;   // On ne garde que 16 bits.
+                       if ( tmp == 0 )   // If overflow set TF1
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
+                       cpu8051_WriteD( _TH1_, ( tmp / 0x100 ) );
+                       cpu8051_WriteD( _TL1_, ( tmp & 0xFF ) );
+                       break;
       
-      // Mode 2, Compteur de 8 bits avec Auto-Reload
-    case 2 :
-      tmp = cpu8051_ReadD( _TL1_ );
-      tmp++;
-      tmp &= 0xFF;
-      if ( tmp == 0 ) {    // If overflow -> reload et set TF1
-       cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
-       cpu8051_WriteD( _TL1_, cpu8051_ReadD( _TH1_ ) );
-      }
-      else
-       cpu8051_WriteD( _TL1_, tmp );
-      break;
+                       // Mode 2, Compteur de 8 bits avec Auto-Reload
+               case 2 :
+                       tmp = cpu8051_ReadD( _TL1_ );
+                       tmp++;
+                       tmp &= 0xFF;
+                       if ( tmp == 0 ) {    // If overflow -> reload et set TF1
+                               cpu8051_WriteD( _TCON_, cpu8051_ReadD( _TCON_ ) | 0x80 );
+                               cpu8051_WriteD( _TL1_, cpu8051_ReadD( _TH1_ ) );
+                       }
+                       else
+                               cpu8051_WriteD( _TL1_, tmp );
+                       break;
       
-      // Mode 3 : mode inactif: retient la valeur de TH1 et TL1.
-      // Equivalent a TR1 = 0.
-    case 3 :
-      break;
+                       // Mode 3 : mode inactif: retient la valeur de TH1 et TL1.
+                       // Equivalent a TR1 = 0.
+               case 3 :
+                       break;
       
-    };
+               };
 }
 
+/* Execute at address cpu8051.pc from PGMMem */
+void
+cpu8051_Exec(void)
+{
+       int i;
+       unsigned char opcode;
+       int insttiming;
+
+       opcode = memory_read8( PGM_MEM_ID, cpu8051.pc );
+       cpu8051.pc++;
+       insttiming = (*opcode_table[opcode])(); /* Function callback. */
+  
+       for( i = 0; i < insttiming; i++ ) {
+               cpu8051_CheckInterrupts();
+               cpu8051_DoTimers();
+               cpu8051.clock++;
+       }
+}
 
 // Addressing modes defined in the order as they appear in disasm.hpp
 // from table argstext[]
@@ -476,164 +385,155 @@ cpu8051_DoTimers( )
 // 80 |  P0  |  SP  |  DPL |  DPH |      |      |      | PCON | 87
 // ---------------------------------------------------------------
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Return as Text the name of the SFR register at Address if any
-//////////////////////////////////////////////////////////////////////////////
-int
+static int
 cpu8051_SFRMemInfo( unsigned int Address, char *Text )
 {
-  switch( Address ) {
-  case 0x80 : return sprintf( Text, "P0" );
-  case 0x81 : return sprintf( Text, "SP" );
-  case 0x82 : return sprintf( Text, "DPL" );
-  case 0x83 : return sprintf( Text, "DPH" );
-  case 0x87 : return sprintf( Text, "PCON" );
-  case 0x88 : return sprintf( Text, "TCON" );
-  case 0x89 : return sprintf( Text, "TMOD" );
-  case 0x8A : return sprintf( Text, "TL0" );
-  case 0x8B : return sprintf( Text, "TL1" );
-  case 0x8C : return sprintf( Text, "TH0" );
-  case 0x8D : return sprintf( Text, "TH1" );
-  case 0x90 : return sprintf( Text, "P1" );
-  case 0x98 : return sprintf( Text, "SCON" );
-  case 0x99 : return sprintf( Text, "SBUF" );
-  case 0xA0 : return sprintf( Text, "P2" );
-  case 0xA8 : return sprintf( Text, "IE" );
-  case 0xB0 : return sprintf( Text, "P3" );
-  case 0xB8 : return sprintf( Text, "IP" );
-  case 0xC8 : return sprintf( Text, "T2CON" );
-  case 0xCA : return sprintf( Text, "RCAP2L" );
-  case 0xCB : return sprintf( Text, "RCAP2H" );
-  case 0xCC : return sprintf( Text, "TL2" );
-  case 0xCD : return sprintf( Text, "TH2" );
-  case 0xD0 : return sprintf( Text, "PSW" );
-  case 0xE0 : return sprintf( Text, "ACC" );
-  case 0xF0 : return sprintf( Text, "B" );
-  default : return sprintf( Text, "%.2XH", Address );
-  }
+       switch( Address ) {
+       case 0x80 : return sprintf( Text, "P0" );
+       case 0x81 : return sprintf( Text, "SP" );
+       case 0x82 : return sprintf( Text, "DPL" );
+       case 0x83 : return sprintf( Text, "DPH" );
+       case 0x87 : return sprintf( Text, "PCON" );
+       case 0x88 : return sprintf( Text, "TCON" );
+       case 0x89 : return sprintf( Text, "TMOD" );
+       case 0x8A : return sprintf( Text, "TL0" );
+       case 0x8B : return sprintf( Text, "TL1" );
+       case 0x8C : return sprintf( Text, "TH0" );
+       case 0x8D : return sprintf( Text, "TH1" );
+       case 0x90 : return sprintf( Text, "P1" );
+       case 0x98 : return sprintf( Text, "SCON" );
+       case 0x99 : return sprintf( Text, "SBUF" );
+       case 0xA0 : return sprintf( Text, "P2" );
+       case 0xA8 : return sprintf( Text, "IE" );
+       case 0xB0 : return sprintf( Text, "P3" );
+       case 0xB8 : return sprintf( Text, "IP" );
+       case 0xC8 : return sprintf( Text, "T2CON" );
+       case 0xCA : return sprintf( Text, "RCAP2L" );
+       case 0xCB : return sprintf( Text, "RCAP2H" );
+       case 0xCC : return sprintf( Text, "TL2" );
+       case 0xCD : return sprintf( Text, "TH2" );
+       case 0xD0 : return sprintf( Text, "PSW" );
+       case 0xE0 : return sprintf( Text, "ACC" );
+       case 0xF0 : return sprintf( Text, "B" );
+       default : return sprintf( Text, "%.2XH", Address );
+       }
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Return as Text the decoded BitAddress
-//////////////////////////////////////////////////////////////////////////////
-void
+static void
 cpu8051_IntMemBitInfo( unsigned int BitAddress, char *Text )
 {
-  unsigned int ByteAddress, BitNumber;
-  int TextLength;
+       unsigned int ByteAddress, BitNumber;
+       int TextLength;
   
-  if ( BitAddress > 0x7F ) {
-    // SFR 80-FF
-    ByteAddress = BitAddress & 0xF8;
-    BitNumber = BitAddress & 0x07;
-  }
-  else {
-    // 20-2F
-    ByteAddress = ( BitAddress >> 3 ) + 0x20;
-    BitNumber = BitAddress & 0x07;
-  }
+       if ( BitAddress > 0x7F ) {
+               // SFR 80-FF
+               ByteAddress = BitAddress & 0xF8;
+               BitNumber = BitAddress & 0x07;
+       }
+       else {
+               // 20-2F
+               ByteAddress = ( BitAddress >> 3 ) + 0x20;
+               BitNumber = BitAddress & 0x07;
+       }
   
-  TextLength = cpu8051_SFRMemInfo( ByteAddress, Text );
-  // sprintf( &Text[ TextLength ], ".%X" );
-  // Modified by Hugo Villeneuve to remove compilation warning
-  sprintf( &Text[ TextLength ], ".%X", BitAddress );
+       TextLength = cpu8051_SFRMemInfo( ByteAddress, Text );
+       // sprintf( &Text[ TextLength ], ".%X" );
+       // Modified by Hugo Villeneuve to remove compilation warning
+       sprintf( &Text[ TextLength ], ".%X", BitAddress );
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
 // Disasm one instruction at Address into a Text string
-//////////////////////////////////////////////////////////////////////////////
 int
 cpu8051_Disasm( unsigned int Address, char *Text )
 {
-  int TextLength=0;
-  char TextTmp[20];
-  unsigned char OpCode;
-  int ArgTblOfs;
-  int InstSize;
-  int i;
+       int TextLength=0;
+       char TextTmp[20];
+       unsigned char OpCode;
+       int ArgTblOfs;
+       int InstSize;
+       int i;
   
-  OpCode = memory_read8( PGM_MEM_ID, Address );
-  InstSize = InstSizesTbl[ OpCode ];
-  //printf("%.4X\n", Address);
+       OpCode = memory_read8( PGM_MEM_ID, Address );
+       InstSize = InstSizesTbl[ OpCode ];
+       //printf("%.4X\n", Address);
   
-  TextLength += sprintf( Text, " %.4X ", Address );
+       TextLength += sprintf( Text, " %.4X ", Address );
   
-  for (i = 0; i < InstSize; i++ )
-    TextLength += sprintf( &Text[TextLength], " %.2X", memory_read8( PGM_MEM_ID, Address + i ) );
+       for (i = 0; i < InstSize; i++ )
+               TextLength += sprintf( &Text[TextLength], " %.2X", memory_read8( PGM_MEM_ID, Address + i ) );
   
-  Address++;
+       Address++;
   
-  for (; TextLength < 17; ) TextLength += sprintf( &Text[ TextLength ], " " );
+       for (; TextLength < 17; ) TextLength += sprintf( &Text[ TextLength ], " " );
   
-  TextLength += sprintf( &Text[ TextLength ], "%s ", InstTextTbl[ InstTypesTbl[ OpCode ] ] );
-  ArgTblOfs = OpCode << 2;
+       TextLength += sprintf( &Text[ TextLength ], "%s ", InstTextTbl[ InstTypesTbl[ OpCode ] ] );
+       ArgTblOfs = OpCode << 2;
   
-  for (; TextLength < 25; ) TextLength += sprintf( &Text[ TextLength ], " " );
+       for (; TextLength < 25; ) TextLength += sprintf( &Text[ TextLength ], " " );
   
-  // MOV direct, direct (OpCode 85h) is peculiar, the operands are inverted
-  if ( OpCode == 0x85 ) {
-    cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address + 1 ), TextTmp );
-    TextLength += sprintf( &Text[ TextLength ], "%s,", TextTmp );
-    cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address ), TextTmp );
-    TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp );
-    Address += 2;
-    return InstSize;
-  }
+       // MOV direct, direct (OpCode 85h) is peculiar, the operands are inverted
+       if ( OpCode == 0x85 ) {
+               cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address + 1 ), TextTmp );
+               TextLength += sprintf( &Text[ TextLength ], "%s,", TextTmp );
+               cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address ), TextTmp );
+               TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp );
+               Address += 2;
+               return InstSize;
+       }
   
-  for ( i = 1; i <= InstArgTbl[ ArgTblOfs ]; i++ ) {
-    switch( InstArgTbl[ ArgTblOfs + i ] ) {
-    case ADDR11  : {
-      TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( OpCode << 3) & 0xF00 ) + ( memory_read8( PGM_MEM_ID, Address ) ) );
-      Address++;
-      break;
-    }
-    case ADDR16  : {
-      TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( memory_read8( PGM_MEM_ID, Address ) << 8 ) + memory_read8( PGM_MEM_ID, Address + 1 ) ) );
-      Address += 2;
-      break;
-    }
-    case DIRECT  : {
-      cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address ), TextTmp );
-      TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp );
-      Address++;
-      break;
-    }
-    case BITADDR : {
-      cpu8051_IntMemBitInfo( ( memory_read8( PGM_MEM_ID, Address ) & 0xF8 ), TextTmp );
-      TextLength += sprintf( &Text[ TextLength ], "%s.%X" , TextTmp, ( memory_read8( PGM_MEM_ID, Address ) & 7 ) );
-      Address++;
-      break;
-    }
-    case RELADDR : {
-      Address++;
-      TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( Address & 0xFF00 ) + ( ( ( Address & 0xFF ) + memory_read8( PGM_MEM_ID, Address - 1 ) ) & 0xFF ) );
-      break;
-    }
-    case DATAIMM : {
-      TextLength += sprintf( &Text[ TextLength ], "#%.2XH", memory_read8( PGM_MEM_ID, Address ) );
-      Address++;
-      break;
-    }
-    case DATA16  : {
-      TextLength += sprintf( &Text[ TextLength ],"#%.4XH", ( ( memory_read8( PGM_MEM_ID, Address ) << 8 ) + memory_read8( PGM_MEM_ID, Address+1 ) ) );
-      Address += 2;
-      break;
-    }
-    case CBITADDR : {
-      cpu8051_IntMemBitInfo( ( memory_read8( PGM_MEM_ID, Address ) & 0xF8 ), TextTmp );
-      TextLength += sprintf( &Text[ TextLength ], "/%s.%X", TextTmp, ( memory_read8( PGM_MEM_ID, Address ) & 7 ) );
-      Address++;
-      break;
-    }
-    default : {
-      TextLength += sprintf( &Text[ TextLength ],"%s", ArgsTextTbl[ InstArgTbl[ ArgTblOfs + i ] ] );
-    }
-    }
-    if (i < InstArgTbl[ ArgTblOfs ]) { TextLength += sprintf( &Text[ TextLength ], "," ); }
-  }
+       for ( i = 1; i <= InstArgTbl[ ArgTblOfs ]; i++ ) {
+               switch( InstArgTbl[ ArgTblOfs + i ] ) {
+               case ADDR11  : {
+                       TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( OpCode << 3) & 0xF00 ) + ( memory_read8( PGM_MEM_ID, Address ) ) );
+                       Address++;
+                       break;
+               }
+               case ADDR16  : {
+                       TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( ( memory_read8( PGM_MEM_ID, Address ) << 8 ) + memory_read8( PGM_MEM_ID, Address + 1 ) ) );
+                       Address += 2;
+                       break;
+               }
+               case DIRECT  : {
+                       cpu8051_SFRMemInfo( memory_read8( PGM_MEM_ID, Address ), TextTmp );
+                       TextLength += sprintf( &Text[ TextLength ], "%s", TextTmp );
+                       Address++;
+                       break;
+               }
+               case BITADDR : {
+                       cpu8051_IntMemBitInfo( ( memory_read8( PGM_MEM_ID, Address ) & 0xF8 ), TextTmp );
+                       TextLength += sprintf( &Text[ TextLength ], "%s.%X" , TextTmp, ( memory_read8( PGM_MEM_ID, Address ) & 7 ) );
+                       Address++;
+                       break;
+               }
+               case RELADDR : {
+                       Address++;
+                       TextLength += sprintf( &Text[ TextLength ], "%.4XH", ( Address & 0xFF00 ) + ( ( ( Address & 0xFF ) + memory_read8( PGM_MEM_ID, Address - 1 ) ) & 0xFF ) );
+                       break;
+               }
+               case DATAIMM : {
+                       TextLength += sprintf( &Text[ TextLength ], "#%.2XH", memory_read8( PGM_MEM_ID, Address ) );
+                       Address++;
+                       break;
+               }
+               case DATA16  : {
+                       TextLength += sprintf( &Text[ TextLength ],"#%.4XH", ( ( memory_read8( PGM_MEM_ID, Address ) << 8 ) + memory_read8( PGM_MEM_ID, Address+1 ) ) );
+                       Address += 2;
+                       break;
+               }
+               case CBITADDR : {
+                       cpu8051_IntMemBitInfo( ( memory_read8( PGM_MEM_ID, Address ) & 0xF8 ), TextTmp );
+                       TextLength += sprintf( &Text[ TextLength ], "/%s.%X", TextTmp, ( memory_read8( PGM_MEM_ID, Address ) & 7 ) );
+                       Address++;
+                       break;
+               }
+               default : {
+                       TextLength += sprintf( &Text[ TextLength ],"%s", ArgsTextTbl[ InstArgTbl[ ArgTblOfs + i ] ] );
+               }
+               }
+               if (i < InstArgTbl[ ArgTblOfs ]) { TextLength += sprintf( &Text[ TextLength ], "," ); }
+       }
 
-  return InstSize;
+       return InstSize;
 }